diff --git a/lib/2wp-utils.js b/lib/2wp-utils.js index bfd105b0..33e85aaf 100644 --- a/lib/2wp-utils.js +++ b/lib/2wp-utils.js @@ -1,5 +1,5 @@ const expect = require('chai').expect; -const { sendFromCow, mineAndSync, sendTxWithCheck } = require('./rsk-utils'); +const { sendFromCow, mineAndSync, sendTxWithCheck, getUnlockedAddress } = require('./rsk-utils'); const { wait, retryWithCheck } = require('./utils'); const { getBridge, getLatestActiveForkName } = require('./precompiled-abi-forks-util'); const { getBridgeState } = require('@rsksmart/bridge-state-data-parser'); @@ -250,11 +250,11 @@ const donateToBridge = async (rskTxHelper, btcTxHelper, donatingBtcAddressInform */ const disableWhitelisting = async (rskTxHelper, btcTxHelper, blockDelay = 1) => { const bridge = getBridge(rskTxHelper.getClient()); - const unlocked = await rskUtils.getUnlockedAddress(rskTxHelper, WHITELIST_CHANGE_PK, WHITELIST_CHANGE_ADDR); + const unlocked = await getUnlockedAddress(rskTxHelper, WHITELIST_CHANGE_PK, WHITELIST_CHANGE_ADDR); expect(unlocked).to.be.true; const disableLockWhitelistMethod = bridge.methods.setLockWhitelistDisableBlockDelay(blockDelay); const disableResultCallback = (disableResult) => expect(Number(disableResult)).to.equal(1); - await rskUtils.sendTxWithCheck(rskTxHelper, disableLockWhitelistMethod, WHITELIST_CHANGE_ADDR, disableResultCallback); + await sendTxWithCheck(rskTxHelper, disableLockWhitelistMethod, WHITELIST_CHANGE_ADDR, disableResultCallback); if(blockDelay > 0) { await btcTxHelper.mine(blockDelay); } diff --git a/lib/utils.js b/lib/utils.js index f2460e24..cfc96921 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -11,6 +11,12 @@ var sequentialPromise = function(n, promiseReturn) { return promiseReturn(n).then(() => sequentialPromise(n - 1, promiseReturn)); }; +const publicKeyToCompressed = function(publicKey) { + return bitcoinJs.ECPair.fromPublicKey(Buffer.from(publicKey, 'hex'), { compressed: true }) + .publicKey + .toString('hex'); +} + var mapPromiseAll = function(map) { var promises = Object.keys(map).map(key => map[key].then(result => ({ key, result }))); return Promise.all(promises).then(arr => { @@ -215,6 +221,7 @@ module.exports = { getRandomInt: getRandomInt, isPromise: utils.isPromise, interval: utils.interval, + publicKeyToCompressed, ensure0x: ensure0x, removeDir: removeDir, executeWithRetries: executeWithRetries, diff --git a/tests/01_05_57-post_hop_active_powpeg_redeem_script.js b/tests/01_05_57-post_hop_active_powpeg_redeem_script.js index 0488c5e7..dabedcf4 100644 --- a/tests/01_05_57-post_hop_active_powpeg_redeem_script.js +++ b/tests/01_05_57-post_hop_active_powpeg_redeem_script.js @@ -2,30 +2,44 @@ const chai = require('chai'); chai.use(require('chai-as-promised')); const expect = chai.expect; -const rsk = require('peglib').rsk; const redeemScriptParser = require('@rsksmart/powpeg-redeemscript-parser'); const CustomError = require('../lib/CustomError'); -const removePrefix0x = require("../lib/utils").removePrefix0x; -const { GENESIS_FEDERATION_ADDRESS, GENESIS_FEDERATION_REDEEM_SCRIPT } = require('../lib/constants'); - +const removePrefix0x = require('../lib/utils').removePrefix0x; +const {getRskTransactionHelpers} = require('../lib/rsk-tx-helper-provider'); +const {getBridge, getLatestActiveForkName} = require('../lib/precompiled-abi-forks-util'); +const {GENESIS_FEDERATION_ADDRESS, GENESIS_FEDERATION_REDEEM_SCRIPT} = require('../lib/constants'); +const {activateFork} = require('../lib/rsk-utils'); +/** + * Takes the blockchain to the required state for this test file to run in isolation. + */ +const fulfillRequirementsToRunAsSingleTestFile = async () => { + await activateFork(Runners.common.forks.hop400); +}; describe('Calling getActivePowpegRedeemScript method after hop', function() { + let rskTxHelpers; + let rskTxHelper; + let bridge; + before(async () => { + if (process.env.RUNNING_SINGLE_TEST_FILE) { + await fulfillRequirementsToRunAsSingleTestFile(); + } + rskTxHelpers = getRskTransactionHelpers(); + rskTxHelper = rskTxHelpers[0]; + bridge = getBridge(rskTxHelper.getClient(), await getLatestActiveForkName()); + }); + + it('should return the active powpeg redeem script', async () => { + try { + const activePowpegRedeemScript = await bridge.methods.getActivePowpegRedeemScript().call(); + const activeFederationAddressFromBridge = await bridge.methods.getFederationAddress().call(); + const addressFromRedeemScript = redeemScriptParser.getAddressFromRedeemScript( + 'REGTEST', Buffer.from(removePrefix0x(activePowpegRedeemScript), 'hex'), + ); - before(() => { - rskClient = rsk.getClient(Runners.hosts.federate.host); - }); - - it('should return the active powpeg redeem script', async () => { - try{ - const activePowpegRedeemScript = await rskClient.rsk.bridge.methods.getActivePowpegRedeemScript().call(); - const activeFederationAddressFromBridge = await rskClient.rsk.bridge.methods.getFederationAddress().call(); - const addressFromRedeemScript = redeemScriptParser.getAddressFromRedeemScript( - 'REGTEST', Buffer.from(removePrefix0x(activePowpegRedeemScript), 'hex') - ); - - expect(activePowpegRedeemScript).to.eq(GENESIS_FEDERATION_REDEEM_SCRIPT); - expect(addressFromRedeemScript).to.eq(GENESIS_FEDERATION_ADDRESS).to.eq(activeFederationAddressFromBridge); - } catch (err) { - throw new CustomError('getActivePowpegRedeemScript method validation failure', err); - } - }) + expect(activePowpegRedeemScript).to.eq(GENESIS_FEDERATION_REDEEM_SCRIPT); + expect(addressFromRedeemScript).to.eq(GENESIS_FEDERATION_ADDRESS).to.eq(activeFederationAddressFromBridge); + } catch (err) { + throw new CustomError('getActivePowpegRedeemScript method validation failure', err); + } + }); }); diff --git a/tests/03_02_01-last_fork_active_powpeg_redeem_script.js b/tests/03_02_01-last_fork_active_powpeg_redeem_script.js new file mode 100644 index 00000000..3212afe3 --- /dev/null +++ b/tests/03_02_01-last_fork_active_powpeg_redeem_script.js @@ -0,0 +1,55 @@ +const chai = require('chai'); +chai.use(require('chai-as-promised')); +const expect = chai.expect; +const redeemScriptParser = require('@rsksmart/powpeg-redeemscript-parser'); +const {getRskTransactionHelpers} = require('../lib/rsk-tx-helper-provider'); +const {getBridge, getLatestActiveForkName} = require('../lib/precompiled-abi-forks-util'); +const CustomError = require('../lib/CustomError'); +const removePrefix0x = require('../lib/utils').removePrefix0x; +const rskUtils = require('../lib/rsk-utils'); +const { + GENESIS_FEDERATION_ADDRESS, + GENESIS_FEDERATION_REDEEM_SCRIPT, +} = require('../lib/constants'); + +const fulfillRequirementsToRunAsSingleTestFile = async () => { + const latestForkName = rskUtils.getLatestForkName(); + await rskUtils.activateFork(latestForkName); +}; + +describe('Calling getActivePowpegRedeemScript method after last fork before fedchange', function() { + let rskTxHelpers; + let rskTxHelper; + let bridge; + + before(async () => { + rskTxHelpers = getRskTransactionHelpers(); + rskTxHelper = rskTxHelpers[0]; + if (process.env.RUNNING_SINGLE_TEST_FILE) { + await fulfillRequirementsToRunAsSingleTestFile(); + } + bridge = getBridge(rskTxHelper.getClient(), await getLatestActiveForkName()); + }); + + it('should return the active powpeg redeem script', async () => { + try { + const activePowpegRedeemScript = await bridge.methods.getActivePowpegRedeemScript().call(); + const activeFederationAddressFromBridge = await bridge.methods.getFederationAddress().call(); + const addressFromRedeemScript = + redeemScriptParser.getAddressFromRedeemScript( + 'REGTEST', + Buffer.from(removePrefix0x(activePowpegRedeemScript), 'hex'), + ); + + expect(activePowpegRedeemScript).to.eq(GENESIS_FEDERATION_REDEEM_SCRIPT); + expect(addressFromRedeemScript) + .to.eq(GENESIS_FEDERATION_ADDRESS) + .to.eq(activeFederationAddressFromBridge); + } catch (err) { + throw new CustomError( + 'getActivePowpegRedeemScript method validation failure', + err, + ); + } + }); +}); diff --git a/tests/04_00_02-fedchange.js b/tests/04_00_02-fedchange.js index 483206eb..7e3ed13f 100644 --- a/tests/04_00_02-fedchange.js +++ b/tests/04_00_02-fedchange.js @@ -689,6 +689,7 @@ describe('RSK Federation change', function() { throw new CustomError('Transfer BTC to RBTC with outputs both federations failure', err); } }); + }); const getActiveFederationAddress = async() => { diff --git a/tests/05_02_01-last_fork_active_powpeg_redeem_script.js b/tests/05_02_01-last_fork_active_powpeg_redeem_script.js new file mode 100644 index 00000000..8c4fb460 --- /dev/null +++ b/tests/05_02_01-last_fork_active_powpeg_redeem_script.js @@ -0,0 +1,87 @@ +const chai = require('chai'); +chai.use(require('chai-as-promised')); +const expect = chai.expect; +const {compareFederateKeys} = require('../lib/federation-utils'); +const {getRskTransactionHelpers} = require('../lib/rsk-tx-helper-provider'); +const redeemScriptParser = require('@rsksmart/powpeg-redeemscript-parser'); +const CustomError = require('../lib/CustomError'); +const removePrefix0x = require('../lib/utils').removePrefix0x; +const publicKeyToCompressed = require('../lib/utils').publicKeyToCompressed; +const {getBridge, getLatestActiveForkName} = require('../lib/precompiled-abi-forks-util'); + +// in order to run this as a single test file, it requires a federation change so follow the following command +// npm run run-single-test-file 04_00_02-fedchange.js,05_02_01-last_fork_active_powpeg_redeem_script.js + +const { + ERP_PUBKEYS, + ERP_CSV_VALUE, + KEY_TYPE_BTC, + KEY_TYPE_RSK, + KEY_TYPE_MST, +} = require('../lib/constants'); +const INITIAL_FEDERATION_SIZE = 3; + +let rskTxHelpers; +let rskTxHelper; +let bridge; + +describe('Calling getActivePowpegRedeemScript method after last fork after fed change', function() { + before(async () => { + rskTxHelpers = getRskTransactionHelpers(); + rskTxHelper = rskTxHelpers[0]; + bridge = getBridge(rskTxHelper.getClient(), await getLatestActiveForkName()); + }); + + it('should return the active powpeg redeem script', async () => { + try { + const activePowpegRedeemScript = await bridge.methods + .getActivePowpegRedeemScript() + .call(); + const activeFederationAddressFromBridge = await bridge.methods.getFederationAddress().call(); + const addressFromRedeemScript = redeemScriptParser.getAddressFromRedeemScript( + 'REGTEST', + Buffer.from(removePrefix0x(activePowpegRedeemScript), 'hex'), + ); + const newFederationPublicKeys = Runners.hosts.federates + .filter((federate, index) => index >= INITIAL_FEDERATION_SIZE) + .map((federate) => ({ + [KEY_TYPE_BTC]: publicKeyToCompressed( + federate.publicKeys[KEY_TYPE_BTC], + ), + [KEY_TYPE_RSK]: publicKeyToCompressed( + federate.publicKeys[KEY_TYPE_RSK], + ), + [KEY_TYPE_MST]: publicKeyToCompressed( + federate.publicKeys[KEY_TYPE_MST], + ), + })) + .sort(compareFederateKeys); + const newFederationBtcPublicKeys = newFederationPublicKeys.map( + (publicKeys) => publicKeys[KEY_TYPE_BTC], + ); + const p2shErpFedRedeemScript = redeemScriptParser.getP2shErpRedeemScript( + newFederationBtcPublicKeys, + ERP_PUBKEYS, + ERP_CSV_VALUE, + ); + const expectedNewFederationAddress = + redeemScriptParser.getAddressFromRedeemScript( + 'REGTEST', + p2shErpFedRedeemScript, + ); + + expect(removePrefix0x(activePowpegRedeemScript)).to.eq(p2shErpFedRedeemScript.toString('hex')); + + + expect(addressFromRedeemScript) + .to.eq(expectedNewFederationAddress); + expect(addressFromRedeemScript) + .to.eq(activeFederationAddressFromBridge); + } catch (err) { + throw new CustomError( + 'getActivePowpegRedeemScript method validation failure', + err, + ); + } + }); +});