diff --git a/lib/2wp-utils.js b/lib/2wp-utils.js index c1bf2c08..e380f03e 100644 --- a/lib/2wp-utils.js +++ b/lib/2wp-utils.js @@ -1,6 +1,6 @@ const expect = require('chai').expect; -const { sendFromCow, mineAndSync, sendTxWithCheck, getUnlockedAddress, waitForRskMempoolToGetTxs, waitAndUpdateBridge } = require('./rsk-utils'); -const { retryWithCheck, waitForBtcTxToBeInMempool, waitForBtcMempoolToGetTxs } = require('./utils'); +const { sendFromCow, mineAndSync, sendTxWithCheck, getUnlockedAddress, waitForRskMempoolToGetNewTxs, waitAndUpdateBridge } = require('./rsk-utils'); +const { retryWithCheck, waitForBitcoinTxToBeInMempool, waitForBitcoinMempoolToGetTxs } = require('./utils'); const { getBridge, getLatestActiveForkName } = require('./precompiled-abi-forks-util'); const { getBridgeState } = require('@rsksmart/bridge-state-data-parser'); const btcEthUnitConverter = require('@rsksmart/btc-eth-unit-converter'); @@ -64,7 +64,7 @@ const sendTxToBridge = async (rskTxHelper, amountInRbtc, rskFromAddress, mine = } // Wait for the rsk tx to be in the rsk mempool before mining - await waitForRskMempoolToGetTxs(rskTxHelper); + await waitForRskMempoolToGetNewTxs(rskTxHelper); await mineAndSync(getRskTransactionHelpers()); const result = await txPromise; @@ -107,12 +107,12 @@ const isUtxoRegisteredInBridge = async (rskTxHelper, peginTxHash, expectedUxtosC const mineForPeginRegistration = async (rskTxHelper, btcTxHelper) => { // Enough confirmations to register the coinbase but not the pegin. // Wait for the pegin to be in the bitcoin mempool before mining - await waitForBtcMempoolToGetTxs(btcTxHelper); + await waitForBitcoinMempoolToGetTxs(btcTxHelper); await btcTxHelper.mine(BTC_TO_RSK_MINIMUM_CONFIRMATIONS - 1); await waitAndUpdateBridge(rskTxHelper, 500); // One more confirmation to register the pegin. // Wait for the pegin to be in the bitcoin mempool before mining - await waitForBtcMempoolToGetTxs(btcTxHelper); + await waitForBitcoinMempoolToGetTxs(btcTxHelper); await btcTxHelper.mine(1); await waitAndUpdateBridge(rskTxHelper, 500); }; @@ -140,7 +140,7 @@ const sendPegin = async (rskTxHelper, btcTxHelper, btcSenderAddressInformation, const peginBtcTxHash = await btcTxHelper.transferBtc(btcSenderAddressInformation, recipientsTransferInformation, data); // Wait for the pegin to be in the bitcoin mempool before mining - await waitForBtcTxToBeInMempool(btcTxHelper, peginBtcTxHash); + await waitForBitcoinTxToBeInMempool(btcTxHelper, peginBtcTxHash); await mineForPeginRegistration(rskTxHelper, btcTxHelper); diff --git a/lib/rsk-utils.js b/lib/rsk-utils.js index ba41ce86..7f32a70c 100644 --- a/lib/rsk-utils.js +++ b/lib/rsk-utils.js @@ -5,7 +5,7 @@ const { getBridge, getLatestActiveForkName } = require('./precompiled-abi-forks- const hopBridgeTxParser = require('bridge-transaction-parser-hop400'); const fingerrootBridgeTxParser = require('bridge-transaction-parser-fingerroot500'); const { getRskTransactionHelpers } = require('../lib/rsk-tx-helper-provider'); -const { removePrefix0x, waitForBtcMempoolToGetTxs } = require('./utils'); +const { removePrefix0x, waitForBitcoinMempoolToGetTxs } = require('./utils'); const BTC_TO_RSK_MINIMUM_ACCEPTABLE_CONFIRMATIONS = 3; const RSK_TO_BTC_MINIMUM_ACCEPTABLE_CONFIRMATIONS = 3; @@ -138,7 +138,7 @@ const waitAndUpdateBridge = async (rskTxHelper, timeInMilliseconds = 1000) => { await rskTxHelper.updateBridge(); // Wait for the rsk `updateBridge` tx to be in the rsk mempool before mining - await waitForRskMempoolToGetTxs(rskTxHelper); + await waitForRskMempoolToGetNewTxs(rskTxHelper); await mineAndSync(getRskTransactionHelpers()); }; @@ -159,7 +159,7 @@ const getRskMempoolTransactionHashes = async (rskTxHelper) => { * @param {string} txHash * @param {number} maxAttempts Defaults to 20 * @param {number} checkEveryMilliseconds Defaults to 1000 milliseconds - * @returns {boolean} whether the tx is in the mempool or not + * @returns {Promise} whether the tx is in the mempool or not */ const waitForRskTxToBeInTheMempool = async (rskTxHelper, txHash, maxAttempts = 5, checkEveryMilliseconds = 1000) => { @@ -171,10 +171,9 @@ const waitForRskTxToBeInTheMempool = async (rskTxHelper, txHash, maxAttempts = 5 } else if(tx && tx.blockNumber) { console.debug(`The tx (${txHash}) is already mined in a block`); return true; - } else { - console.debug(`The tx (${txHash}) is not in the mempool nor in a block yet. Will keep retrying until it is in the mempool, block, or it reaches the max attempts to find it`); - return false; } + console.debug(`The tx (${txHash}) is not in the mempool nor in a block yet. Will keep retrying until it is in the mempool, block, or it reaches the max attempts to find it`); + return false; }; const check = async (txIsInTheMempool, currentAttempts) => { @@ -182,7 +181,9 @@ const waitForRskTxToBeInTheMempool = async (rskTxHelper, txHash, maxAttempts = 5 return txIsInTheMempool; }; - return await retryWithCheck(method, check, maxAttempts, checkEveryMilliseconds); + const txIsInTheMempool = await retryWithCheck(method, check, maxAttempts, checkEveryMilliseconds); + + console.debug(`Tx ${txHash} was found in the mempool or mined: ${txIsInTheMempool}`); }; @@ -191,32 +192,36 @@ const waitForRskTxToBeInTheMempool = async (rskTxHelper, txHash, maxAttempts = 5 * @param {RskTransactionHelper} rskTxHelper * @param {number} maxAttempts Defaults to 20 * @param {number} checkEveryMilliseconds Defaults to 1000 milliseconds - * @returns + * @returns {Promise} whether the mempool has new txs or not */ -const waitForRskMempoolToGetTxs = async (rskTxHelper, maxAttempts = 5, checkEveryMilliseconds = 1000) => { +const waitForRskMempoolToGetNewTxs = async (rskTxHelper, maxAttempts = 5, checkEveryMilliseconds = 1000) => { const initialRskMempoolTxHashes = await getRskMempoolTransactionHashes(rskTxHelper); - console.debug(`[waitForRskMempoolToGetTxs] initial mempool size: ${initialRskMempoolTxHashes.length}`); + console.debug(`[waitForRskMempoolToGetNewTxs] initial rsk mempool size: ${initialRskMempoolTxHashes.length}`); + console.debug(`Will wait and attempt to check if the rsk mempool has received any new transactions ${maxAttempts} times.`); const method = async () => { const mempoolTxHashes = await getRskMempoolTransactionHashes(rskTxHelper); if(mempoolTxHashes.length > initialRskMempoolTxHashes.length) { - console.debug(`The mempool got new ${mempoolTxHashes.length - initialRskMempoolTxHashes.length} transactions`); + console.debug(`The mempool got ${mempoolTxHashes.length - initialRskMempoolTxHashes.length} new transactions`); return true; - } else { - console.debug(`The mempool did not get new transactions yet. Will keep retrying until it gets new transactions or it reaches the max attempts`); - return false; } + return false; }; - const check = async (mempoolHasTxs, currentAttempts) => { - console.debug(`Attempting to find new txs in the mempool. Attempt ${currentAttempts} out of ${maxAttempts}`); + const check = async (mempoolHasTxs) => { return mempoolHasTxs; }; - return await retryWithCheck(method, check, maxAttempts, checkEveryMilliseconds); + const retryResult = await retryWithCheck(method, check, maxAttempts, checkEveryMilliseconds); + const finalRskMempoolTxHashes = await getRskMempoolTransactionHashes(rskTxHelper); + + console.debug(`[waitForRskMempoolToGetNewTxs] final rsk mempool size: ${finalRskMempoolTxHashes.length}. Difference with initial mempool size: ${finalRskMempoolTxHashes.length - initialRskMempoolTxHashes.length}`); + + return retryResult; + }; /** @@ -282,7 +287,7 @@ const triggerRelease = async (rskTransactionHelpers, btcClient, callbacks = {}) } // Waiting to make sure that the pegout tx is in the bitcoin mempool before mining the required blocks for confirmation. - await waitForBtcMempoolToGetTxs(btcClient); + await waitForBitcoinMempoolToGetTxs(btcClient); // From the btc network side, mine `RSK_TO_BTC_MINIMUM_ACCEPTABLE_CONFIRMATIONS + 1` blocks, 1 for the pegout funds to be mined and reflected in the recipient address, // and `RSK_TO_BTC_MINIMUM_ACCEPTABLE_CONFIRMATIONS` more to have enough confirmation for the change balance to be reflected back in the bridge (like a pegin) @@ -313,7 +318,7 @@ const sendTxWithCheck = async (rskTxHelper, method, from, checkCallback) => { const estimatedGas = await method.estimateGas({ from }); const txReceiptPromise = method.send({ from, value: 0, gasPrice: 0, gas: estimatedGas }); - await waitForRskMempoolToGetTxs(rskTxHelper); + await waitForRskMempoolToGetNewTxs(rskTxHelper); await mineAndSync(getRskTransactionHelpers()); return await txReceiptPromise; @@ -439,6 +444,6 @@ module.exports = { getLatestForkName, getRskMempoolTransactionHashes, waitForRskTxToBeInTheMempool, - waitForRskMempoolToGetTxs, + waitForRskMempoolToGetNewTxs, waitAndUpdateBridge, }; diff --git a/lib/utils.js b/lib/utils.js index 801efbb0..1172d5b6 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -100,7 +100,7 @@ const fundAddressAndGetData = async (btcTxHelper, addressToFund, amountToFundInB const txId = await btcTxHelper.transferBtc(btcSenderAddressInformation, recipientsTransactionInformation); // Wait for the pegin to be in the bitcoin mempool before mining - await waitForBtcTxToBeInMempool(btcTxHelper, txId); + await waitForBitcoinTxToBeInMempool(btcTxHelper, txId); const rawTx = await btcTxHelper.nodeClient.getRawTransaction(txId); @@ -218,7 +218,7 @@ const retryWithCheck = async (method, check, maxAttempts = 5, delayInMillisecond /** * * @param {BtcTransactionHelper} btcTxHelper - * @returns {Array} the mempool tx ids + * @returns {Promise>} the mempool tx ids */ const getBitcoinMempool = async (btcTxHelper) => { const mempool = await btcTxHelper.nodeClient.execute('getrawmempool', []); @@ -228,9 +228,9 @@ const getBitcoinMempool = async (btcTxHelper) => { /** * * @param {BtcTransactionHelper} btcTxHelper - * @param {string} btcTxHash + * @param {Promise} btcTxHash */ -const waitForBtcTxToBeInMempool = async (btcTxHelper, btcTxHash) => { +const waitForBitcoinTxToBeInMempool = async (btcTxHelper, btcTxHash) => { const bitcoinMempoolHasTx = async () => { const bitcoinMempool = await getBitcoinMempool(btcTxHelper); @@ -269,15 +269,16 @@ const waitForBtcTxToBeInMempool = async (btcTxHelper, btcTxHash) => { }; /** - * Waits until the btc mempool has at least one tx. + * Waits until the bitcoin mempool has at least one tx. * @param {BtcTransactionHelper} btcTxHelper - * @returns {boolean} + * @returns {Promise} */ -const waitForBtcMempoolToGetTxs = async (btcTxHelper) => { +const waitForBitcoinMempoolToGetTxs = async (btcTxHelper, maxAttempts, checkEveryMilliseconds = 1000) => { const initialBitcoinMempoolSize = (await getBitcoinMempool(btcTxHelper)).length; - console.debug(`[waitForBtcMempoolToGetTxs] The initial btc mempool size is ${initialBitcoinMempoolSize}.`); + console.debug(`[waitForBitcoinMempoolToGetTxs] The initial bitcoin mempool size is ${initialBitcoinMempoolSize}.`); + console.debug(`Will wait and attempt to check if the bitcoin mempool has received any new transactions ${maxAttempts} times.`); const getBitcoinMempoolSize = async () => { const bitcoinMempool = await getBitcoinMempool(btcTxHelper); @@ -286,16 +287,17 @@ const waitForBtcMempoolToGetTxs = async (btcTxHelper) => { }; const checkBtcMempoolIsNotEmpty = async (bitcoinMempoolSize, currentAttempts) => { - console.debug(`The btc mempool has ${bitcoinMempoolSize} txs at attempt ${currentAttempts}.`); return bitcoinMempoolSize > 0; }; - const onError = async (e) => { - console.error(`Un expected error while trying to get the btc mempool.`, e); - throw e; - }; + const bitcoinMempoolHasTx = await retryWithCheck(getBitcoinMempoolSize, checkBtcMempoolIsNotEmpty, maxAttempts, checkEveryMilliseconds); + + const finalBitcoinMempoolSize = (await getBitcoinMempool(btcTxHelper)).length; + + console.debug(`[waitForBitcoinMempoolToGetTxs] The final bitcoin mempool size is ${finalBitcoinMempoolSize}. Difference with initial mempool size: ${finalBitcoinMempoolSize - initialBitcoinMempoolSize}.`); + + return bitcoinMempoolHasTx; - return await retryWithCheck(getBitcoinMempoolSize, checkBtcMempoolIsNotEmpty, 5, 1000, onError); } module.exports = { @@ -320,6 +322,6 @@ module.exports = { removePrefix0x, retryWithCheck, getBitcoinMempool, - waitForBtcTxToBeInMempool, - waitForBtcMempoolToGetTxs, + waitForBitcoinTxToBeInMempool, + waitForBitcoinMempoolToGetTxs, } diff --git a/tests/01_03_54-post-papyrus_coinbase_information.js b/tests/01_03_54-post-papyrus_coinbase_information.js index cb16cf6b..90401da2 100644 --- a/tests/01_03_54-post-papyrus_coinbase_information.js +++ b/tests/01_03_54-post-papyrus_coinbase_information.js @@ -31,7 +31,7 @@ describe('Calling coinbase information methods after papyrus', () => { const blockHash = await btcClient.mine(1); await wait(1000); await rskTxHelper.updateBridge(); - await rskUtils.waitForRskMempoolToGetTxs(rskTxHelper); + await rskUtils.waitForRskMempoolToGetNewTxs(rskTxHelper); const blockData = await btcClient.nodeClient.getBlock(blockHash[0], false); const block = bitcoinJs.Block.fromHex(blockData);