From eb17e9bbb0afc3827d480aeea291b12eb4df7e42 Mon Sep 17 00:00:00 2001 From: jeremy-then Date: Wed, 25 Sep 2024 15:16:51 -0400 Subject: [PATCH 1/8] Adds bridge own balance and bridge utxos balance checks Rebases --- lib/tests/2wp.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/tests/2wp.js b/lib/tests/2wp.js index 38fc1c46..cc703e14 100644 --- a/lib/tests/2wp.js +++ b/lib/tests/2wp.js @@ -242,6 +242,15 @@ const execute = (description, getRskHost) => { const finalRskRecipient2BalanceInWeisBN = await rskTxHelper.getBalance(senderRecipientInfo2.rskRecipientRskAddressInfo.address); expect(finalRskRecipient2BalanceInWeisBN.eq(new BN('0'))).to.be.true; + // After the successful pegin, the Bridge balance should be reduced by the pegin value + const finalBridgeBalanceInWeisBN = await rskTxHelper.getBalance(BRIDGE_ADDRESS); + const expectedPeginValueInWeisBN = initialBridgeBalanceInWeisBN.sub(rskTxHelper.getClient().utils.BN(`${satoshisToWeis(peginValueInSatoshis)}`)); + expect(finalBridgeBalanceInWeisBN.eq(expectedPeginValueInWeisBN)).to.be.true; + + // After the successful pegin, the Bridge utxos sum should be incremented by the pegin value + const finalBridgeUtxosBalance = await getBridgeUtxosBalance(rskTxHelper); + expect(finalBridgeUtxosBalance).to.be.equal(initialBridgeUtxosBalanceInSatoshis + peginValueInSatoshis); + }); }); From dd999add7735227f620f0de39faaa9b6df7abd82 Mon Sep 17 00:00:00 2001 From: jeremy-then Date: Mon, 23 Sep 2024 23:40:50 -0400 Subject: [PATCH 2/8] Adds legacy pegin test with multiple inputs from multiple accounts. Rebases --- lib/tests/2wp.js | 78 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/lib/tests/2wp.js b/lib/tests/2wp.js index cc703e14..5066e4e2 100644 --- a/lib/tests/2wp.js +++ b/lib/tests/2wp.js @@ -253,6 +253,84 @@ const execute = (description, getRskHost) => { }); + it('should do legacy pegin with multiple inputs from different accounts and one output to the federation with value exactly minimum', async () => { + + // Arrange + + const initialFederationAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, federationAddress); + const sender1RecipientInfo = await createSenderRecipientInfo(rskTxHelper, btcTxHelper); + const sender2RecipientInfo = await createSenderRecipientInfo(rskTxHelper, btcTxHelper); + const initialSender1AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender1RecipientInfo.btcSenderAddressInfo.address); + const initialSender2AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender2RecipientInfo.btcSenderAddressInfo.address); + + const sender1PeginValueInSatoshis = minimumPeginValueInSatoshis; + const sender2PeginValueInSatoshis = minimumPeginValueInSatoshis; + const peginValueInSatoshis = sender1PeginValueInSatoshis + sender2PeginValueInSatoshis; + + const sender1UtxosInfo = await getSenderUtxosInfo(sender1RecipientInfo, satoshisToBtc(sender1PeginValueInSatoshis)); + const sender2UtxosInfo = await getSenderUtxosInfo(sender2RecipientInfo, satoshisToBtc(sender2PeginValueInSatoshis)); + + const sender1ChangeInSatoshis = btcToSatoshis(sender1UtxosInfo.change); + const sender2ChangeInSatoshis = btcToSatoshis(sender2UtxosInfo.change); + + const tx = new bitcoinJsLib.Transaction(); + + // Adding inputs + addInputs(tx, sender1UtxosInfo); + addInputs(tx, sender2UtxosInfo); + + // Adding output to federation + addOutputToFed(tx, peginValueInSatoshis); + + // Adding change outputs + addChangeOutputs(tx, sender1RecipientInfo.btcSenderAddressInfo.address, sender1ChangeInSatoshis); + addChangeOutputs(tx, sender2RecipientInfo.btcSenderAddressInfo.address, sender2ChangeInSatoshis); + + // Signing the transaction + const sender1PrivateKey = sender1RecipientInfo.btcSenderAddressInfo.privateKey; + const sender2PrivateKey = sender2RecipientInfo.btcSenderAddressInfo.privateKey; + const sendersPrivateKeys = [sender1PrivateKey, sender2PrivateKey]; + const signedTx = await btcTxHelper.nodeClient.signTransaction(tx.toHex(), [], sendersPrivateKeys); + + // Act + + // Sending the pegin and ensuring the pegin is registered + const btcPeginTxHash = await btcTxHelper.nodeClient.sendTransaction(signedTx); + await pushPegin(btcPeginTxHash); + + // Assert + + const isBtcTxHashAlreadyProcessed = await bridge.methods.isBtcTxHashAlreadyProcessed(btcPeginTxHash).call(); + expect(isBtcTxHashAlreadyProcessed).to.be.true; + + // The expected pegin_btc event should be emitted with the expected values + const recipient1RskAddressChecksumed = rskTxHelper.getClient().utils.toChecksumAddress(ensure0x(sender1RecipientInfo.rskRecipientRskAddressInfo.address)); + const expectedEvent = createExpectedPeginBtcEvent(PEGIN_EVENTS.PEGIN_BTC, recipient1RskAddressChecksumed, btcPeginTxHash, peginValueInSatoshis); + const btcTxHashProcessedHeight = Number(await bridge.methods.getBtcTxHashProcessedHeight(btcPeginTxHash).call()); + const peginBtcEvent = await findEventInBlock(rskTxHelper, expectedEvent.name, btcTxHashProcessedHeight); + expect(peginBtcEvent).to.be.deep.equal(expectedEvent); + + // The federation address should have received the total amount sent by the senders + const finalFederationAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, federationAddress); + expect(finalFederationAddressBalanceInSatoshis).to.be.equal(initialFederationAddressBalanceInSatoshis + peginValueInSatoshis); + + // The senders should have their balances reduced by the amount sent to the federation and the fee + const finalSender1AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender1RecipientInfo.btcSenderAddressInfo.address); + expect(finalSender1AddressBalanceInSatoshis).to.be.equal(initialSender1AddressBalanceInSatoshis - sender1PeginValueInSatoshis - btcFeeInSatoshis); + + const finalSender2AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender2RecipientInfo.btcSenderAddressInfo.address); + expect(finalSender2AddressBalanceInSatoshis).to.be.equal(initialSender2AddressBalanceInSatoshis - sender2PeginValueInSatoshis - btcFeeInSatoshis); + + // Only the first sender should have the total amount in rsk since in legacy pegins the rsk address is derived from the first input. + const finalRskRecipient1Balance = Number(await rskTxHelper.getBalance(sender1RecipientInfo.rskRecipientRskAddressInfo.address)); + expect(finalRskRecipient1Balance).to.be.equal(Number(satoshisToWeis(peginValueInSatoshis))); + + // Other senders should have 0 balance in rsk. + const finalRskRecipient2Balance = Number(await rskTxHelper.getBalance(sender2RecipientInfo.rskRecipientRskAddressInfo.address)); + expect(finalRskRecipient2Balance).to.be.equal(0); + + }); + }); } From 390d074d12b191cef2fb0aa814287b21238f872b Mon Sep 17 00:00:00 2001 From: jeremy-then Date: Mon, 23 Sep 2024 23:52:42 -0400 Subject: [PATCH 3/8] Adds legacy pegin test with multiple inputs and outputs. --- lib/tests/2wp.js | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/lib/tests/2wp.js b/lib/tests/2wp.js index 5066e4e2..fdb8e421 100644 --- a/lib/tests/2wp.js +++ b/lib/tests/2wp.js @@ -331,6 +331,85 @@ const execute = (description, getRskHost) => { }); + it('should do legacy pegin with multiple inputs from different accounts and two outputs to the federation with value exactly minimum', async () => { + + // Arrange + + const initialFederationAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, federationAddress); + const sender1RecipientInfo = await createSenderRecipientInfo(rskTxHelper, btcTxHelper); + const sender2RecipientInfo = await createSenderRecipientInfo(rskTxHelper, btcTxHelper); + const initialSender1AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender1RecipientInfo.btcSenderAddressInfo.address); + const initialSender2AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender2RecipientInfo.btcSenderAddressInfo.address); + + const sender1PeginValueInSatoshis = minimumPeginValueInSatoshis; + const sender2PeginValueInSatoshis = minimumPeginValueInSatoshis; + const peginValueInSatoshis = sender1PeginValueInSatoshis + sender2PeginValueInSatoshis; + + const sender1UtxosInfo = await getSenderUtxosInfo(sender1RecipientInfo, satoshisToBtc(sender1PeginValueInSatoshis)); + const sender2UtxosInfo = await getSenderUtxosInfo(sender2RecipientInfo, satoshisToBtc(sender2PeginValueInSatoshis)); + + const sender1ChangeInSatoshis = btcToSatoshis(sender1UtxosInfo.change); + const sender2ChangeInSatoshis = btcToSatoshis(sender2UtxosInfo.change); + + const tx = new bitcoinJsLib.Transaction(); + + // Adding inputs + addInputs(tx, sender1UtxosInfo); + addInputs(tx, sender2UtxosInfo); + + // Adding 2 outputs to the federation + addOutputToFed(tx, sender1PeginValueInSatoshis); + addOutputToFed(tx, sender2PeginValueInSatoshis); + + // Adding change outputs + addChangeOutputs(tx, sender1RecipientInfo.btcSenderAddressInfo.address, sender1ChangeInSatoshis); + addChangeOutputs(tx, sender2RecipientInfo.btcSenderAddressInfo.address, sender2ChangeInSatoshis); + + // Signing the transaction + const sender1PrivateKey = sender1RecipientInfo.btcSenderAddressInfo.privateKey; + const sender2PrivateKey = sender2RecipientInfo.btcSenderAddressInfo.privateKey; + const sendersPrivateKeys = [sender1PrivateKey, sender2PrivateKey]; + const signedTx = await btcTxHelper.nodeClient.signTransaction(tx.toHex(), [], sendersPrivateKeys); + + // Act + + // Sending the pegin and ensuring the pegin is registered + const btcPeginTxHash = await btcTxHelper.nodeClient.sendTransaction(signedTx); + await pushPegin(btcPeginTxHash, 2); + + // Assert + + const isBtcTxHashAlreadyProcessed = await bridge.methods.isBtcTxHashAlreadyProcessed(btcPeginTxHash).call(); + expect(isBtcTxHashAlreadyProcessed).to.be.true; + + // The expected pegin_btc event should be emitted with the expected values + const recipient1RskAddressChecksumed = rskTxHelper.getClient().utils.toChecksumAddress(ensure0x(sender1RecipientInfo.rskRecipientRskAddressInfo.address)); + const expectedEvent = createExpectedPeginBtcEvent(PEGIN_EVENTS.PEGIN_BTC, recipient1RskAddressChecksumed, btcPeginTxHash, peginValueInSatoshis); + const btcTxHashProcessedHeight = Number(await bridge.methods.getBtcTxHashProcessedHeight(btcPeginTxHash).call()); + const peginBtcEvent = await findEventInBlock(rskTxHelper, expectedEvent.name, btcTxHashProcessedHeight); + expect(peginBtcEvent).to.be.deep.equal(expectedEvent); + + // The federation address should have received the total amount sent by the senders + const finalFederationAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, federationAddress); + expect(finalFederationAddressBalanceInSatoshis).to.be.equal(initialFederationAddressBalanceInSatoshis + peginValueInSatoshis); + + // The senders should have their balances reduced by the amount sent to the federation and the fee + const finalSender1AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender1RecipientInfo.btcSenderAddressInfo.address); + expect(finalSender1AddressBalanceInSatoshis).to.be.equal(initialSender1AddressBalanceInSatoshis - sender1PeginValueInSatoshis - btcFeeInSatoshis); + + const finalSender2AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender2RecipientInfo.btcSenderAddressInfo.address); + expect(finalSender2AddressBalanceInSatoshis).to.be.equal(initialSender2AddressBalanceInSatoshis - sender2PeginValueInSatoshis - btcFeeInSatoshis); + + // Only the first sender should have the total amount in rsk since in legacy pegins the rsk address is derived from the first input. + const finalRskRecipient1Balance = Number(await rskTxHelper.getBalance(sender1RecipientInfo.rskRecipientRskAddressInfo.address)); + expect(finalRskRecipient1Balance).to.be.equal(Number(satoshisToWeis(peginValueInSatoshis))); + + // Other senders should have 0 balance in rsk. + const finalRskRecipient2Balance = Number(await rskTxHelper.getBalance(sender2RecipientInfo.rskRecipientRskAddressInfo.address)); + expect(finalRskRecipient2Balance).to.be.equal(0); + + }); + }); } From 702cd0695e65bdb4362a7c4d0c8b611844bcd40b Mon Sep 17 00:00:00 2001 From: jeremy-then Date: Wed, 25 Sep 2024 22:14:41 -0400 Subject: [PATCH 4/8] Refactors to use weis in BN --- lib/tests/2wp.js | 112 +++++------------------------------------------ 1 file changed, 11 insertions(+), 101 deletions(-) diff --git a/lib/tests/2wp.js b/lib/tests/2wp.js index fdb8e421..05e8f3c5 100644 --- a/lib/tests/2wp.js +++ b/lib/tests/2wp.js @@ -253,89 +253,11 @@ const execute = (description, getRskHost) => { }); - it('should do legacy pegin with multiple inputs from different accounts and one output to the federation with value exactly minimum', async () => { - - // Arrange - - const initialFederationAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, federationAddress); - const sender1RecipientInfo = await createSenderRecipientInfo(rskTxHelper, btcTxHelper); - const sender2RecipientInfo = await createSenderRecipientInfo(rskTxHelper, btcTxHelper); - const initialSender1AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender1RecipientInfo.btcSenderAddressInfo.address); - const initialSender2AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender2RecipientInfo.btcSenderAddressInfo.address); - - const sender1PeginValueInSatoshis = minimumPeginValueInSatoshis; - const sender2PeginValueInSatoshis = minimumPeginValueInSatoshis; - const peginValueInSatoshis = sender1PeginValueInSatoshis + sender2PeginValueInSatoshis; - - const sender1UtxosInfo = await getSenderUtxosInfo(sender1RecipientInfo, satoshisToBtc(sender1PeginValueInSatoshis)); - const sender2UtxosInfo = await getSenderUtxosInfo(sender2RecipientInfo, satoshisToBtc(sender2PeginValueInSatoshis)); - - const sender1ChangeInSatoshis = btcToSatoshis(sender1UtxosInfo.change); - const sender2ChangeInSatoshis = btcToSatoshis(sender2UtxosInfo.change); - - const tx = new bitcoinJsLib.Transaction(); - - // Adding inputs - addInputs(tx, sender1UtxosInfo); - addInputs(tx, sender2UtxosInfo); - - // Adding output to federation - addOutputToFed(tx, peginValueInSatoshis); - - // Adding change outputs - addChangeOutputs(tx, sender1RecipientInfo.btcSenderAddressInfo.address, sender1ChangeInSatoshis); - addChangeOutputs(tx, sender2RecipientInfo.btcSenderAddressInfo.address, sender2ChangeInSatoshis); - - // Signing the transaction - const sender1PrivateKey = sender1RecipientInfo.btcSenderAddressInfo.privateKey; - const sender2PrivateKey = sender2RecipientInfo.btcSenderAddressInfo.privateKey; - const sendersPrivateKeys = [sender1PrivateKey, sender2PrivateKey]; - const signedTx = await btcTxHelper.nodeClient.signTransaction(tx.toHex(), [], sendersPrivateKeys); - - // Act - - // Sending the pegin and ensuring the pegin is registered - const btcPeginTxHash = await btcTxHelper.nodeClient.sendTransaction(signedTx); - await pushPegin(btcPeginTxHash); - - // Assert - - const isBtcTxHashAlreadyProcessed = await bridge.methods.isBtcTxHashAlreadyProcessed(btcPeginTxHash).call(); - expect(isBtcTxHashAlreadyProcessed).to.be.true; - - // The expected pegin_btc event should be emitted with the expected values - const recipient1RskAddressChecksumed = rskTxHelper.getClient().utils.toChecksumAddress(ensure0x(sender1RecipientInfo.rskRecipientRskAddressInfo.address)); - const expectedEvent = createExpectedPeginBtcEvent(PEGIN_EVENTS.PEGIN_BTC, recipient1RskAddressChecksumed, btcPeginTxHash, peginValueInSatoshis); - const btcTxHashProcessedHeight = Number(await bridge.methods.getBtcTxHashProcessedHeight(btcPeginTxHash).call()); - const peginBtcEvent = await findEventInBlock(rskTxHelper, expectedEvent.name, btcTxHashProcessedHeight); - expect(peginBtcEvent).to.be.deep.equal(expectedEvent); - - // The federation address should have received the total amount sent by the senders - const finalFederationAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, federationAddress); - expect(finalFederationAddressBalanceInSatoshis).to.be.equal(initialFederationAddressBalanceInSatoshis + peginValueInSatoshis); - - // The senders should have their balances reduced by the amount sent to the federation and the fee - const finalSender1AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender1RecipientInfo.btcSenderAddressInfo.address); - expect(finalSender1AddressBalanceInSatoshis).to.be.equal(initialSender1AddressBalanceInSatoshis - sender1PeginValueInSatoshis - btcFeeInSatoshis); - - const finalSender2AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender2RecipientInfo.btcSenderAddressInfo.address); - expect(finalSender2AddressBalanceInSatoshis).to.be.equal(initialSender2AddressBalanceInSatoshis - sender2PeginValueInSatoshis - btcFeeInSatoshis); - - // Only the first sender should have the total amount in rsk since in legacy pegins the rsk address is derived from the first input. - const finalRskRecipient1Balance = Number(await rskTxHelper.getBalance(sender1RecipientInfo.rskRecipientRskAddressInfo.address)); - expect(finalRskRecipient1Balance).to.be.equal(Number(satoshisToWeis(peginValueInSatoshis))); - - // Other senders should have 0 balance in rsk. - const finalRskRecipient2Balance = Number(await rskTxHelper.getBalance(sender2RecipientInfo.rskRecipientRskAddressInfo.address)); - expect(finalRskRecipient2Balance).to.be.equal(0); - - }); - it('should do legacy pegin with multiple inputs from different accounts and two outputs to the federation with value exactly minimum', async () => { // Arrange - const initialFederationAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, federationAddress); + const initial2wpBalances = await get2wpInitialBalances(); const sender1RecipientInfo = await createSenderRecipientInfo(rskTxHelper, btcTxHelper); const sender2RecipientInfo = await createSenderRecipientInfo(rskTxHelper, btcTxHelper); const initialSender1AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender1RecipientInfo.btcSenderAddressInfo.address); @@ -365,33 +287,20 @@ const execute = (description, getRskHost) => { addChangeOutputs(tx, sender1RecipientInfo.btcSenderAddressInfo.address, sender1ChangeInSatoshis); addChangeOutputs(tx, sender2RecipientInfo.btcSenderAddressInfo.address, sender2ChangeInSatoshis); - // Signing the transaction - const sender1PrivateKey = sender1RecipientInfo.btcSenderAddressInfo.privateKey; - const sender2PrivateKey = sender2RecipientInfo.btcSenderAddressInfo.privateKey; - const sendersPrivateKeys = [sender1PrivateKey, sender2PrivateKey]; - const signedTx = await btcTxHelper.nodeClient.signTransaction(tx.toHex(), [], sendersPrivateKeys); + const signedTx = await signPeginTransaction(tx, sender1RecipientInfo, sender2RecipientInfo); // Act - // Sending the pegin and ensuring the pegin is registered const btcPeginTxHash = await btcTxHelper.nodeClient.sendTransaction(signedTx); - await pushPegin(btcPeginTxHash, 2); // Assert - const isBtcTxHashAlreadyProcessed = await bridge.methods.isBtcTxHashAlreadyProcessed(btcPeginTxHash).call(); - expect(isBtcTxHashAlreadyProcessed).to.be.true; + // Since we are not using `sendPegin` here, we need to do some extra steps before ensuring the pegin is registered. + await ensurePeginIsPushed(btcPeginTxHash); - // The expected pegin_btc event should be emitted with the expected values - const recipient1RskAddressChecksumed = rskTxHelper.getClient().utils.toChecksumAddress(ensure0x(sender1RecipientInfo.rskRecipientRskAddressInfo.address)); - const expectedEvent = createExpectedPeginBtcEvent(PEGIN_EVENTS.PEGIN_BTC, recipient1RskAddressChecksumed, btcPeginTxHash, peginValueInSatoshis); - const btcTxHashProcessedHeight = Number(await bridge.methods.getBtcTxHashProcessedHeight(btcPeginTxHash).call()); - const peginBtcEvent = await findEventInBlock(rskTxHelper, expectedEvent.name, btcTxHashProcessedHeight); - expect(peginBtcEvent).to.be.deep.equal(expectedEvent); + await assertExpectedPeginBtcEventIsEmitted(btcPeginTxHash, sender1RecipientInfo.rskRecipientRskAddressInfo.address, peginValueInSatoshis); - // The federation address should have received the total amount sent by the senders - const finalFederationAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, federationAddress); - expect(finalFederationAddressBalanceInSatoshis).to.be.equal(initialFederationAddressBalanceInSatoshis + peginValueInSatoshis); + await assertSuccessfulPegin2wpFinalBalances(initial2wpBalances, peginValueInSatoshis); // The senders should have their balances reduced by the amount sent to the federation and the fee const finalSender1AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender1RecipientInfo.btcSenderAddressInfo.address); @@ -401,12 +310,13 @@ const execute = (description, getRskHost) => { expect(finalSender2AddressBalanceInSatoshis).to.be.equal(initialSender2AddressBalanceInSatoshis - sender2PeginValueInSatoshis - btcFeeInSatoshis); // Only the first sender should have the total amount in rsk since in legacy pegins the rsk address is derived from the first input. - const finalRskRecipient1Balance = Number(await rskTxHelper.getBalance(sender1RecipientInfo.rskRecipientRskAddressInfo.address)); - expect(finalRskRecipient1Balance).to.be.equal(Number(satoshisToWeis(peginValueInSatoshis))); + const finalRskRecipient1BalanceInWeisBN = await rskTxHelper.getBalance(sender1RecipientInfo.rskRecipientRskAddressInfo.address); + const expectedFinalRskRecipient1BalanceInWeisBN = rskTxHelper.getClient().utils.BN(satoshisToWeis(peginValueInSatoshis)); + expect(finalRskRecipient1BalanceInWeisBN.eq(expectedFinalRskRecipient1BalanceInWeisBN)).to.be.true; // Other senders should have 0 balance in rsk. - const finalRskRecipient2Balance = Number(await rskTxHelper.getBalance(sender2RecipientInfo.rskRecipientRskAddressInfo.address)); - expect(finalRskRecipient2Balance).to.be.equal(0); + const finalRskRecipient2BalanceInWeisBN = await rskTxHelper.getBalance(sender2RecipientInfo.rskRecipientRskAddressInfo.address); + expect(finalRskRecipient2BalanceInWeisBN).to.be.equal(0); }); From 388ced7f1c1b1e7bb0611ad3dcec748819ed2837 Mon Sep 17 00:00:00 2001 From: jeremy-then Date: Tue, 24 Sep 2024 09:06:20 -0400 Subject: [PATCH 5/8] Adds basic peginv1 test --- lib/tests/2wp.js | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/lib/tests/2wp.js b/lib/tests/2wp.js index 05e8f3c5..d999c8b1 100644 --- a/lib/tests/2wp.js +++ b/lib/tests/2wp.js @@ -16,6 +16,7 @@ const { sendPegin, const { getBtcAddressBalanceInSatoshis, waitForBitcoinMempoolToGetTxs } = require('../btc-utils'); const { ensure0x } = require('../utils'); const bitcoinJsLib = require('bitcoinjs-lib'); +const { createPeginV1TxData } = require('pegin-address-verificator'); let btcTxHelper; let rskTxHelper; @@ -320,6 +321,54 @@ const execute = (description, getRskHost) => { }); + it('should do a basic pegin v1 with the exact minimum value', async () => { + + // Arrange + + const initialFederationAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, federationAddress); + const senderRecipientInfo = await createSenderRecipientInfo(rskTxHelper, btcTxHelper); + const initialSenderAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, senderRecipientInfo.btcSenderAddressInfo.address); + const peginValueInSatoshis = minimumPeginValueInSatoshis; + const peginV1RskRecipientAddress = await rskTxHelper.newAccountWithSeed(''); + + // Act + + const peginV1Data = [Buffer.from(createPeginV1TxData(peginV1RskRecipientAddress), 'hex')]; + + const btcPeginTxHash = await sendPegin(rskTxHelper, btcTxHelper, senderRecipientInfo.btcSenderAddressInfo, satoshisToBtc(peginValueInSatoshis), peginV1Data); + await ensurePeginIsRegistered(rskTxHelper, btcPeginTxHash); + + // Assert + + // The btc pegin tx is already marked as processed by the bridge + const isBtcTxHashAlreadyProcessed = await bridge.methods.isBtcTxHashAlreadyProcessed(btcPeginTxHash).call(); + expect(isBtcTxHashAlreadyProcessed).to.be.true; + + // The pegin_btc event is emitted with the expected values + const recipientRskAddressChecksumed = rskTxHelper.getClient().utils.toChecksumAddress(peginV1RskRecipientAddress); + const expectedEvent = createExpectedPeginBtcEvent(PEGIN_EVENTS.PEGIN_BTC, recipientRskAddressChecksumed, btcPeginTxHash, peginValueInSatoshis, '1'); + const btcTxHashProcessedHeight = Number(await bridge.methods.getBtcTxHashProcessedHeight(btcPeginTxHash).call()); + const peginBtcEvent = await findEventInBlock(rskTxHelper, expectedEvent.name, btcTxHashProcessedHeight); + expect(peginBtcEvent).to.be.deep.equal(expectedEvent); + + // The federation balance is increased by the pegin value + const finalFederationAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, federationAddress); + expect(finalFederationAddressBalanceInSatoshis).to.be.equal(initialFederationAddressBalanceInSatoshis + peginValueInSatoshis); + + // The sender address balance is decreased by the pegin value and the btc fee + const finalSenderAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, senderRecipientInfo.btcSenderAddressInfo.address); + expect(finalSenderAddressBalanceInSatoshis).to.be.equal(initialSenderAddressBalanceInSatoshis - peginValueInSatoshis - btcFeeInSatoshis); + + // The sender derived rsk address rsk address balance is unchanged + const finalSenderDerivedRskAddressBalance = Number(await rskTxHelper.getBalance(senderRecipientInfo.rskRecipientRskAddressInfo.address)); + expect(finalSenderDerivedRskAddressBalance).to.be.equal(0); + + // The pegin v1 rsk recipient address has the funds + const finalRskRecipientBalance = Number(await rskTxHelper.getBalance(peginV1RskRecipientAddress)); + expect(finalRskRecipientBalance).to.be.equal(Number(satoshisToWeis(peginValueInSatoshis))); + + }); + }); } From 5326f10416144369b10b1e299aa886f2356baeee Mon Sep 17 00:00:00 2001 From: jeremy-then Date: Thu, 26 Sep 2024 10:21:05 -0400 Subject: [PATCH 6/8] Refactors to extract 2wp balances check Rebases --- lib/tests/2wp.js | 94 +++++------------------------------------------- 1 file changed, 9 insertions(+), 85 deletions(-) diff --git a/lib/tests/2wp.js b/lib/tests/2wp.js index d999c8b1..646419d9 100644 --- a/lib/tests/2wp.js +++ b/lib/tests/2wp.js @@ -254,78 +254,11 @@ const execute = (description, getRskHost) => { }); - it('should do legacy pegin with multiple inputs from different accounts and two outputs to the federation with value exactly minimum', async () => { - - // Arrange - - const initial2wpBalances = await get2wpInitialBalances(); - const sender1RecipientInfo = await createSenderRecipientInfo(rskTxHelper, btcTxHelper); - const sender2RecipientInfo = await createSenderRecipientInfo(rskTxHelper, btcTxHelper); - const initialSender1AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender1RecipientInfo.btcSenderAddressInfo.address); - const initialSender2AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender2RecipientInfo.btcSenderAddressInfo.address); - - const sender1PeginValueInSatoshis = minimumPeginValueInSatoshis; - const sender2PeginValueInSatoshis = minimumPeginValueInSatoshis; - const peginValueInSatoshis = sender1PeginValueInSatoshis + sender2PeginValueInSatoshis; - - const sender1UtxosInfo = await getSenderUtxosInfo(sender1RecipientInfo, satoshisToBtc(sender1PeginValueInSatoshis)); - const sender2UtxosInfo = await getSenderUtxosInfo(sender2RecipientInfo, satoshisToBtc(sender2PeginValueInSatoshis)); - - const sender1ChangeInSatoshis = btcToSatoshis(sender1UtxosInfo.change); - const sender2ChangeInSatoshis = btcToSatoshis(sender2UtxosInfo.change); - - const tx = new bitcoinJsLib.Transaction(); - - // Adding inputs - addInputs(tx, sender1UtxosInfo); - addInputs(tx, sender2UtxosInfo); - - // Adding 2 outputs to the federation - addOutputToFed(tx, sender1PeginValueInSatoshis); - addOutputToFed(tx, sender2PeginValueInSatoshis); - - // Adding change outputs - addChangeOutputs(tx, sender1RecipientInfo.btcSenderAddressInfo.address, sender1ChangeInSatoshis); - addChangeOutputs(tx, sender2RecipientInfo.btcSenderAddressInfo.address, sender2ChangeInSatoshis); - - const signedTx = await signPeginTransaction(tx, sender1RecipientInfo, sender2RecipientInfo); - - // Act - - const btcPeginTxHash = await btcTxHelper.nodeClient.sendTransaction(signedTx); - - // Assert - - // Since we are not using `sendPegin` here, we need to do some extra steps before ensuring the pegin is registered. - await ensurePeginIsPushed(btcPeginTxHash); - - await assertExpectedPeginBtcEventIsEmitted(btcPeginTxHash, sender1RecipientInfo.rskRecipientRskAddressInfo.address, peginValueInSatoshis); - - await assertSuccessfulPegin2wpFinalBalances(initial2wpBalances, peginValueInSatoshis); - - // The senders should have their balances reduced by the amount sent to the federation and the fee - const finalSender1AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender1RecipientInfo.btcSenderAddressInfo.address); - expect(finalSender1AddressBalanceInSatoshis).to.be.equal(initialSender1AddressBalanceInSatoshis - sender1PeginValueInSatoshis - btcFeeInSatoshis); - - const finalSender2AddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, sender2RecipientInfo.btcSenderAddressInfo.address); - expect(finalSender2AddressBalanceInSatoshis).to.be.equal(initialSender2AddressBalanceInSatoshis - sender2PeginValueInSatoshis - btcFeeInSatoshis); - - // Only the first sender should have the total amount in rsk since in legacy pegins the rsk address is derived from the first input. - const finalRskRecipient1BalanceInWeisBN = await rskTxHelper.getBalance(sender1RecipientInfo.rskRecipientRskAddressInfo.address); - const expectedFinalRskRecipient1BalanceInWeisBN = rskTxHelper.getClient().utils.BN(satoshisToWeis(peginValueInSatoshis)); - expect(finalRskRecipient1BalanceInWeisBN.eq(expectedFinalRskRecipient1BalanceInWeisBN)).to.be.true; - - // Other senders should have 0 balance in rsk. - const finalRskRecipient2BalanceInWeisBN = await rskTxHelper.getBalance(sender2RecipientInfo.rskRecipientRskAddressInfo.address); - expect(finalRskRecipient2BalanceInWeisBN).to.be.equal(0); - - }); - it('should do a basic pegin v1 with the exact minimum value', async () => { // Arrange - const initialFederationAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, federationAddress); + const initial2wpBalances = await get2wpInitialBalances(); const senderRecipientInfo = await createSenderRecipientInfo(rskTxHelper, btcTxHelper); const initialSenderAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, senderRecipientInfo.btcSenderAddressInfo.address); const peginValueInSatoshis = minimumPeginValueInSatoshis; @@ -336,36 +269,27 @@ const execute = (description, getRskHost) => { const peginV1Data = [Buffer.from(createPeginV1TxData(peginV1RskRecipientAddress), 'hex')]; const btcPeginTxHash = await sendPegin(rskTxHelper, btcTxHelper, senderRecipientInfo.btcSenderAddressInfo, satoshisToBtc(peginValueInSatoshis), peginV1Data); - await ensurePeginIsRegistered(rskTxHelper, btcPeginTxHash); // Assert - // The btc pegin tx is already marked as processed by the bridge - const isBtcTxHashAlreadyProcessed = await bridge.methods.isBtcTxHashAlreadyProcessed(btcPeginTxHash).call(); - expect(isBtcTxHashAlreadyProcessed).to.be.true; + await ensurePeginIsRegistered(rskTxHelper, btcPeginTxHash); - // The pegin_btc event is emitted with the expected values - const recipientRskAddressChecksumed = rskTxHelper.getClient().utils.toChecksumAddress(peginV1RskRecipientAddress); - const expectedEvent = createExpectedPeginBtcEvent(PEGIN_EVENTS.PEGIN_BTC, recipientRskAddressChecksumed, btcPeginTxHash, peginValueInSatoshis, '1'); - const btcTxHashProcessedHeight = Number(await bridge.methods.getBtcTxHashProcessedHeight(btcPeginTxHash).call()); - const peginBtcEvent = await findEventInBlock(rskTxHelper, expectedEvent.name, btcTxHashProcessedHeight); - expect(peginBtcEvent).to.be.deep.equal(expectedEvent); + await assertExpectedPeginBtcEventIsEmitted(btcPeginTxHash, senderRecipientInfo.rskRecipientRskAddressInfo.address, peginValueInSatoshis, '1'); - // The federation balance is increased by the pegin value - const finalFederationAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, federationAddress); - expect(finalFederationAddressBalanceInSatoshis).to.be.equal(initialFederationAddressBalanceInSatoshis + peginValueInSatoshis); + await assertSuccessfulPegin2wpFinalBalances(initial2wpBalances, peginValueInSatoshis); // The sender address balance is decreased by the pegin value and the btc fee const finalSenderAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, senderRecipientInfo.btcSenderAddressInfo.address); expect(finalSenderAddressBalanceInSatoshis).to.be.equal(initialSenderAddressBalanceInSatoshis - peginValueInSatoshis - btcFeeInSatoshis); // The sender derived rsk address rsk address balance is unchanged - const finalSenderDerivedRskAddressBalance = Number(await rskTxHelper.getBalance(senderRecipientInfo.rskRecipientRskAddressInfo.address)); - expect(finalSenderDerivedRskAddressBalance).to.be.equal(0); + const finalSenderDerivedRskAddressBalanceInWeisBN = await rskTxHelper.getBalance(senderRecipientInfo.rskRecipientRskAddressInfo.address); + expect(finalSenderDerivedRskAddressBalanceInWeisBN).to.be.equal(0); // The pegin v1 rsk recipient address has the funds - const finalRskRecipientBalance = Number(await rskTxHelper.getBalance(peginV1RskRecipientAddress)); - expect(finalRskRecipientBalance).to.be.equal(Number(satoshisToWeis(peginValueInSatoshis))); + const finalRskRecipientBalanceInWeisBN = await rskTxHelper.getBalance(peginV1RskRecipientAddress); + const expectedFinalRskRecipientBalanceInWeisBN = rskTxHelper.getClient().utils.BN(satoshisToWeis(peginValueInSatoshis)); + expect(finalRskRecipientBalanceInWeisBN.eq(expectedFinalRskRecipientBalanceInWeisBN)).to.be.true; }); From d0f3871f9cf6ffbb3c79db355063b4761bab457e Mon Sep 17 00:00:00 2001 From: jeremy-then Date: Mon, 30 Sep 2024 14:43:17 -0400 Subject: [PATCH 7/8] Refactors to use get2wpBalances function. --- lib/tests/2wp.js | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/lib/tests/2wp.js b/lib/tests/2wp.js index 646419d9..f2c49c88 100644 --- a/lib/tests/2wp.js +++ b/lib/tests/2wp.js @@ -243,22 +243,13 @@ const execute = (description, getRskHost) => { const finalRskRecipient2BalanceInWeisBN = await rskTxHelper.getBalance(senderRecipientInfo2.rskRecipientRskAddressInfo.address); expect(finalRskRecipient2BalanceInWeisBN.eq(new BN('0'))).to.be.true; - // After the successful pegin, the Bridge balance should be reduced by the pegin value - const finalBridgeBalanceInWeisBN = await rskTxHelper.getBalance(BRIDGE_ADDRESS); - const expectedPeginValueInWeisBN = initialBridgeBalanceInWeisBN.sub(rskTxHelper.getClient().utils.BN(`${satoshisToWeis(peginValueInSatoshis)}`)); - expect(finalBridgeBalanceInWeisBN.eq(expectedPeginValueInWeisBN)).to.be.true; - - // After the successful pegin, the Bridge utxos sum should be incremented by the pegin value - const finalBridgeUtxosBalance = await getBridgeUtxosBalance(rskTxHelper); - expect(finalBridgeUtxosBalance).to.be.equal(initialBridgeUtxosBalanceInSatoshis + peginValueInSatoshis); - }); it('should do a basic pegin v1 with the exact minimum value', async () => { // Arrange - const initial2wpBalances = await get2wpInitialBalances(); + const initial2wpBalances = await get2wpBalances(rskTxHelper, btcTxHelper); const senderRecipientInfo = await createSenderRecipientInfo(rskTxHelper, btcTxHelper); const initialSenderAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, senderRecipientInfo.btcSenderAddressInfo.address); const peginValueInSatoshis = minimumPeginValueInSatoshis; @@ -272,9 +263,11 @@ const execute = (description, getRskHost) => { // Assert - await ensurePeginIsRegistered(rskTxHelper, btcPeginTxHash); + const expectedCountOfThisPeginUtxosInTheBridge = 1; + await ensurePeginIsRegistered(rskTxHelper, btcPeginTxHash, expectedCountOfThisPeginUtxosInTheBridge); - await assertExpectedPeginBtcEventIsEmitted(btcPeginTxHash, senderRecipientInfo.rskRecipientRskAddressInfo.address, peginValueInSatoshis, '1'); + const expectedPeginProtocolVersion = '1'; + await assertExpectedPeginBtcEventIsEmitted(btcPeginTxHash, senderRecipientInfo.rskRecipientRskAddressInfo.address, peginValueInSatoshis, expectedPeginProtocolVersion); await assertSuccessfulPegin2wpFinalBalances(initial2wpBalances, peginValueInSatoshis); From bf95c067794da9d6c9c92834e87c0cc09e53ff22 Mon Sep 17 00:00:00 2001 From: jeremy-then Date: Mon, 30 Sep 2024 15:26:25 -0400 Subject: [PATCH 8/8] Fixing BN assertions --- lib/tests/2wp.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/tests/2wp.js b/lib/tests/2wp.js index f2c49c88..18311ee9 100644 --- a/lib/tests/2wp.js +++ b/lib/tests/2wp.js @@ -267,9 +267,9 @@ const execute = (description, getRskHost) => { await ensurePeginIsRegistered(rskTxHelper, btcPeginTxHash, expectedCountOfThisPeginUtxosInTheBridge); const expectedPeginProtocolVersion = '1'; - await assertExpectedPeginBtcEventIsEmitted(btcPeginTxHash, senderRecipientInfo.rskRecipientRskAddressInfo.address, peginValueInSatoshis, expectedPeginProtocolVersion); + await assertExpectedPeginBtcEventIsEmitted(btcPeginTxHash, peginV1RskRecipientAddress, peginValueInSatoshis, expectedPeginProtocolVersion); - await assertSuccessfulPegin2wpFinalBalances(initial2wpBalances, peginValueInSatoshis); + await assert2wpBalancesAfterSuccessfulPegin(initial2wpBalances, peginValueInSatoshis); // The sender address balance is decreased by the pegin value and the btc fee const finalSenderAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, senderRecipientInfo.btcSenderAddressInfo.address); @@ -277,7 +277,7 @@ const execute = (description, getRskHost) => { // The sender derived rsk address rsk address balance is unchanged const finalSenderDerivedRskAddressBalanceInWeisBN = await rskTxHelper.getBalance(senderRecipientInfo.rskRecipientRskAddressInfo.address); - expect(finalSenderDerivedRskAddressBalanceInWeisBN).to.be.equal(0); + expect(finalSenderDerivedRskAddressBalanceInWeisBN.eq(new BN('0'))).to.be.true; // The pegin v1 rsk recipient address has the funds const finalRskRecipientBalanceInWeisBN = await rskTxHelper.getBalance(peginV1RskRecipientAddress); @@ -290,9 +290,9 @@ const execute = (description, getRskHost) => { } -const assertExpectedPeginBtcEventIsEmitted = async (btcPeginTxHash, rskRecipientAddress, peginValueInSatoshis) => { +const assertExpectedPeginBtcEventIsEmitted = async (btcPeginTxHash, rskRecipientAddress, peginValueInSatoshis, expectedPeginProtocolVersion) => { const recipientRskAddressChecksummed = rskTxHelper.getClient().utils.toChecksumAddress(ensure0x(rskRecipientAddress)); - const expectedEvent = createExpectedPeginBtcEvent(PEGIN_EVENTS.PEGIN_BTC, recipientRskAddressChecksummed, btcPeginTxHash, peginValueInSatoshis); + const expectedEvent = createExpectedPeginBtcEvent(PEGIN_EVENTS.PEGIN_BTC, recipientRskAddressChecksummed, btcPeginTxHash, peginValueInSatoshis, expectedPeginProtocolVersion); const btcTxHashProcessedHeight = Number(await bridge.methods.getBtcTxHashProcessedHeight(btcPeginTxHash).call()); const peginBtcEvent = await findEventInBlock(rskTxHelper, expectedEvent.name, btcTxHashProcessedHeight); expect(peginBtcEvent).to.be.deep.equal(expectedEvent);