From c23416a1e50c78bc58fad809d3224d9de45e8e0c Mon Sep 17 00:00:00 2001 From: Warrior-7 Date: Sat, 18 Nov 2023 17:58:47 +0330 Subject: [PATCH 1/4] implement createTriggerBox also implement unit tests --- .../trigger/lib/triggerTxBuilder.ts | 71 ++++++++++++++++++- packages/transactions/trigger/lib/utils.ts | 9 +++ .../trigger/tests/triggerTxBuilder.spec.ts | 62 ++++++++++++++++ 3 files changed, 141 insertions(+), 1 deletion(-) diff --git a/packages/transactions/trigger/lib/triggerTxBuilder.ts b/packages/transactions/trigger/lib/triggerTxBuilder.ts index edc33091..083a5ad4 100644 --- a/packages/transactions/trigger/lib/triggerTxBuilder.ts +++ b/packages/transactions/trigger/lib/triggerTxBuilder.ts @@ -3,7 +3,12 @@ import { ObservationEntity } from '@rosen-bridge/observation-extractor'; import { RWTRepo } from '@rosen-bridge/rwt-repo'; import { blake2b } from 'blakejs'; import * as ergoLib from 'ergo-lib-wasm-nodejs'; -import { bigIntToUint8Array, toScriptHash, uint8ArrayToHex } from './utils'; +import { + bigIntToUint8Array, + hexToUint8Array, + toScriptHash, + uint8ArrayToHex, +} from './utils'; export class TriggerTxBuilder { private permitScriptHash: string; @@ -169,4 +174,68 @@ export class TriggerTxBuilder { ]); return blake2b(content, undefined, 32); }; + + /** + * creates the trigger box + * + * @param {bigint} rwtCount + * @param {bigint} value + * @return {ergoLib.ErgoBoxCandidate} + */ + private createTriggerBox = ( + rwtCount: bigint, + value: bigint + ): ergoLib.ErgoBoxCandidate => { + const boxBuilder = new ergoLib.ErgoBoxCandidateBuilder( + ergoLib.BoxValue.from_i64(ergoLib.I64.from_str(value.toString())), + ergoLib.Contract.pay_to_address( + ergoLib.Address.from_base58(this.triggerAddress) + ), + this.creationHeight + ); + + boxBuilder.add_token( + ergoLib.TokenId.from_str(this.rwt), + ergoLib.TokenAmount.from_i64(ergoLib.I64.from_str(rwtCount.toString())) + ); + this.logger?.debug( + `added rwt tokens to trigger box with amount=[${rwtCount}]` + ); + + boxBuilder.set_register_value( + 4, + ergoLib.Constant.from_coll_coll_byte( + this.wids.map((wid) => hexToUint8Array(wid)) + ) + ); + + boxBuilder.set_register_value( + 5, + ergoLib.Constant.from_coll_coll_byte(this.eventData) + ); + + boxBuilder.set_register_value( + 6, + ergoLib.Constant.from_byte_array(hexToUint8Array(this.permitScriptHash)) + ); + + return boxBuilder.build(); + }; + + private get eventData() { + return [ + Buffer.from(this.observation.sourceTxId), + Buffer.from(this.observation.fromChain), + Buffer.from(this.observation.toChain), + Buffer.from(this.observation.fromAddress), + Buffer.from(this.observation.toAddress), + bigIntToUint8Array(BigInt(this.observation.amount)), + bigIntToUint8Array(BigInt(this.observation.bridgeFee)), + bigIntToUint8Array(BigInt(this.observation.networkFee)), + Buffer.from(this.observation.sourceChainTokenId), + Buffer.from(this.observation.targetChainTokenId), + Buffer.from(this.observation.sourceBlockId), + bigIntToUint8Array(BigInt(this.observation.height)), + ]; + } } diff --git a/packages/transactions/trigger/lib/utils.ts b/packages/transactions/trigger/lib/utils.ts index ae9739e7..ced8c1c4 100644 --- a/packages/transactions/trigger/lib/utils.ts +++ b/packages/transactions/trigger/lib/utils.ts @@ -42,3 +42,12 @@ export const bigIntToUint8Array = (num: bigint): Uint8Array => { export const uint8ArrayToHex = (bytes: Uint8Array): string => { return Buffer.from(bytes).toString('hex'); }; + +/** + * converts a hex string to Uint8Array bytes + * + * @param {string} hex + * @return {Uint8Array} + */ +export const hexToUint8Array = (hex: string): Uint8Array => + Uint8Array.from(Buffer.from(hex, 'hex')); diff --git a/packages/transactions/trigger/tests/triggerTxBuilder.spec.ts b/packages/transactions/trigger/tests/triggerTxBuilder.spec.ts index cdafacb4..b7c0f70c 100644 --- a/packages/transactions/trigger/tests/triggerTxBuilder.spec.ts +++ b/packages/transactions/trigger/tests/triggerTxBuilder.spec.ts @@ -9,6 +9,7 @@ import { sampleRwtRepoboxInfo, triggerTxParams, } from './triggerTxTestData'; +import { hexToUint8Array, uint8ArrayToHex } from '../lib/utils'; describe('TriggerTxBuilder', () => { let triggerTxBuilder: TriggerTxBuilder; @@ -126,4 +127,65 @@ describe('TriggerTxBuilder', () => { ).toEqual(commitments.map((box) => box.box_id().to_str()).sort()); }); }); + + describe('createTriggerBox', () => { + /** + * @target should create a trigger box from instance's properties + * @dependencies + * @scenario + * - setup triggerTxBuilder instance + * - call createTriggerBox + * - check returned box to have the right properties set + * @expected + * - returned box should have the right properties set + */ + it(`should create a trigger box from instance's properties`, async () => { + const height = 100; + triggerTxBuilder.setCreationHeight(height); + + const commitments = sampleCommitmentBoxes + .slice(0, 3) + .map((boxInfo) => + ergoLib.ErgoBox.from_json(JsonBigInt.stringify(boxInfo)) + ); + commitments.forEach((commitment) => + triggerTxBuilder.addCommitment(commitment) + ); + + const rsnValue = + BigInt(triggerTxBuilder['wids'].length) * + triggerTxBuilder['rwtRepo'].getCommitmentRwtCount(); + const value = 10_000_000_000n; + const triggerBox = triggerTxBuilder['createTriggerBox'](rsnValue, value); + + expect(triggerBox.value().as_i64().to_str()).toEqual(value.toString()); + + expect( + ergoLib.Address.recreate_from_ergo_tree( + triggerBox.ergo_tree() + ).to_base58(ergoLib.NetworkPrefix.Mainnet) + ).toEqual(triggerTxBuilder['triggerAddress']); + + expect(triggerBox.creation_height()).toEqual(height); + + expect(triggerBox.tokens().get(0).id().to_str()).toEqual( + triggerTxBuilder['rwt'] + ); + expect(triggerBox.tokens().get(0).amount().as_i64().to_str()).toEqual( + rsnValue.toString() + ); + + expect(triggerBox.register_value(4)?.to_coll_coll_byte()).toEqual( + triggerTxBuilder['wids'].map((wid) => hexToUint8Array(wid)) + ); + + expect(triggerBox.register_value(5)!.to_coll_coll_byte()).toEqual( + triggerTxBuilder['eventData'].map((data) => new Uint8Array(data)) + ); + + expect( + uint8ArrayToHex(triggerBox.register_value(6)!.to_byte_array()) + ).toEqual(triggerTxBuilder['permitScriptHash']); + }); + }); }); From b99a78586f0ea1933ce939b605e869a80df820f2 Mon Sep 17 00:00:00 2001 From: Warrior-7 Date: Mon, 27 Nov 2023 16:13:59 +0330 Subject: [PATCH 2/4] add logs to resolve mr comments --- .../transactions/trigger/lib/triggerTxBuilder.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/transactions/trigger/lib/triggerTxBuilder.ts b/packages/transactions/trigger/lib/triggerTxBuilder.ts index 80b9b5ed..c455a8c1 100644 --- a/packages/transactions/trigger/lib/triggerTxBuilder.ts +++ b/packages/transactions/trigger/lib/triggerTxBuilder.ts @@ -1,4 +1,4 @@ -import { AbstractLogger } from '@rosen-bridge/abstract-logger'; +import { AbstractLogger, DummyLogger } from '@rosen-bridge/abstract-logger'; import { ObservationEntity } from '@rosen-bridge/observation-extractor'; import { RWTRepo } from '@rosen-bridge/rwt-repo'; import { blake2b } from 'blakejs'; @@ -26,7 +26,7 @@ export class TriggerTxBuilder { private txFee: string, private rwtRepo: RWTRepo, private observation: ObservationEntity, - private logger?: AbstractLogger + private logger: AbstractLogger = new DummyLogger() ) { this.permitScriptHash = toScriptHash(permitAddress); } @@ -235,16 +235,27 @@ export class TriggerTxBuilder { this.wids.map((wid) => hexToUint8Array(wid)) ) ); + this.logger?.debug( + `added wids to R4 register of trigger box: wids=[${this.wids}]` + ); boxBuilder.set_register_value( 5, ergoLib.Constant.from_coll_coll_byte(this.eventData) ); + this.logger?.debug( + `added event data to R5 register of trigger box: event-data=[${this.eventData.map( + (data) => uint8ArrayToHex(data) + )}]` + ); boxBuilder.set_register_value( 6, ergoLib.Constant.from_byte_array(hexToUint8Array(this.permitScriptHash)) ); + this.logger?.debug( + `added permit script hash to R6 register of trigger box: permit-script-hash=[${this.permitScriptHash}]` + ); return boxBuilder.build(); }; From a2faad0dc289bb2199dea4fadc9410001009a12e Mon Sep 17 00:00:00 2001 From: Warrior-7 Date: Tue, 28 Nov 2023 17:25:11 +0330 Subject: [PATCH 3/4] remove ? from logger calls --- .../transactions/trigger/lib/triggerTxBuilder.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/transactions/trigger/lib/triggerTxBuilder.ts b/packages/transactions/trigger/lib/triggerTxBuilder.ts index c455a8c1..db388e25 100644 --- a/packages/transactions/trigger/lib/triggerTxBuilder.ts +++ b/packages/transactions/trigger/lib/triggerTxBuilder.ts @@ -42,7 +42,7 @@ export class TriggerTxBuilder { throw new Error('creation height must be a positive integer'); } this.creationHeight = height; - this.logger?.debug(`new value set for height=[${this.creationHeight}]`); + this.logger.debug(`new value set for height=[${this.creationHeight}]`); return this; }; @@ -84,7 +84,7 @@ export class TriggerTxBuilder { } this.commitments.push(...validCommitments); this.wids.push(...validWids); - this.logger?.debug( + this.logger.debug( `added new commitments with boxIds=[${validCommitments .map((commitment) => commitment.box_id().to_str()) .join(', ')}] and wids=[${this.wids.join( @@ -225,7 +225,7 @@ export class TriggerTxBuilder { ergoLib.TokenId.from_str(this.rwt), ergoLib.TokenAmount.from_i64(ergoLib.I64.from_str(rwtCount.toString())) ); - this.logger?.debug( + this.logger.debug( `added rwt tokens to trigger box with amount=[${rwtCount}]` ); @@ -235,7 +235,7 @@ export class TriggerTxBuilder { this.wids.map((wid) => hexToUint8Array(wid)) ) ); - this.logger?.debug( + this.logger.debug( `added wids to R4 register of trigger box: wids=[${this.wids}]` ); @@ -243,7 +243,7 @@ export class TriggerTxBuilder { 5, ergoLib.Constant.from_coll_coll_byte(this.eventData) ); - this.logger?.debug( + this.logger.debug( `added event data to R5 register of trigger box: event-data=[${this.eventData.map( (data) => uint8ArrayToHex(data) )}]` @@ -253,7 +253,7 @@ export class TriggerTxBuilder { 6, ergoLib.Constant.from_byte_array(hexToUint8Array(this.permitScriptHash)) ); - this.logger?.debug( + this.logger.debug( `added permit script hash to R6 register of trigger box: permit-script-hash=[${this.permitScriptHash}]` ); From 7fafb5deeba82db766212ff721d504dd4b6d3287 Mon Sep 17 00:00:00 2001 From: Warrior-7 Date: Thu, 30 Nov 2023 00:56:14 +0330 Subject: [PATCH 4/4] improve logging for event data --- .../trigger/lib/triggerTxBuilder.ts | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/transactions/trigger/lib/triggerTxBuilder.ts b/packages/transactions/trigger/lib/triggerTxBuilder.ts index db388e25..29725c5a 100644 --- a/packages/transactions/trigger/lib/triggerTxBuilder.ts +++ b/packages/transactions/trigger/lib/triggerTxBuilder.ts @@ -244,9 +244,7 @@ export class TriggerTxBuilder { ergoLib.Constant.from_coll_coll_byte(this.eventData) ); this.logger.debug( - `added event data to R5 register of trigger box: event-data=[${this.eventData.map( - (data) => uint8ArrayToHex(data) - )}]` + `added event data to R5 register of trigger box: event-data=[${this.rawEventData}]` ); boxBuilder.set_register_value( @@ -276,4 +274,21 @@ export class TriggerTxBuilder { bigIntToUint8Array(BigInt(this.observation.height)), ]; } + + private get rawEventData() { + return [ + this.observation.sourceTxId, + this.observation.fromChain, + this.observation.toChain, + this.observation.fromAddress, + this.observation.toAddress, + this.observation.amount, + this.observation.bridgeFee, + this.observation.networkFee, + this.observation.sourceChainTokenId, + this.observation.targetChainTokenId, + this.observation.sourceBlockId, + this.observation.height, + ]; + } }