From c5f6867047e73baecf1108d85e05323b708b5628 Mon Sep 17 00:00:00 2001 From: jeremy-then Date: Tue, 14 Jan 2025 14:00:58 -0400 Subject: [PATCH] Settup and add initial svp tests. --- config/node-configs/rsk-reg-1.conf | 5 + config/node-configs/rsk-reg-2.conf | 5 + config/node-configs/rsk-reg-3.conf | 5 + lib/constants/federation-constants.js | 15 +- lib/federation-utils.js | 74 +++ lib/rsk-tx-helper-provider.js | 9 +- lib/utils.js | 37 ++ lib/web3-utils.js | 15 + package-lock.json | 888 +++++++++++++++++++++++++- package.json | 4 +- test.js | 2 +- tests/00_00_04-change-federation.js | 196 +++++- 12 files changed, 1212 insertions(+), 43 deletions(-) create mode 100644 lib/web3-utils.js diff --git a/config/node-configs/rsk-reg-1.conf b/config/node-configs/rsk-reg-1.conf index a316672b..48290550 100644 --- a/config/node-configs/rsk-reg-1.conf +++ b/config/node-configs/rsk-reg-1.conf @@ -29,6 +29,11 @@ federator { rpc { # Enabled RPC Modules. If the module is NOT in the list, and mark as "enabled", the rpc calls will be discard. modules = [ + { + name: "rsk", + version: "1.0", + enabled: "true", + }, { name: "eth", version: "1.0", diff --git a/config/node-configs/rsk-reg-2.conf b/config/node-configs/rsk-reg-2.conf index 90a360ee..03e6f702 100644 --- a/config/node-configs/rsk-reg-2.conf +++ b/config/node-configs/rsk-reg-2.conf @@ -29,6 +29,11 @@ federator { rpc { # Enabled RPC Modules. If the module is NOT in the list, and mark as "enabled", the rpc calls will be discard. modules = [ + { + name: "rsk", + version: "1.0", + enabled: "true", + }, { name: "eth", version: "1.0", diff --git a/config/node-configs/rsk-reg-3.conf b/config/node-configs/rsk-reg-3.conf index 46c1d99e..e4d6a881 100644 --- a/config/node-configs/rsk-reg-3.conf +++ b/config/node-configs/rsk-reg-3.conf @@ -29,6 +29,11 @@ federator { rpc { # Enabled RPC Modules. If the module is NOT in the list, and mark as "enabled", the rpc calls will be discard. modules = [ + { + name: "rsk", + version: "1.0", + enabled: "true", + }, { name: "eth", version: "1.0", diff --git a/lib/constants/federation-constants.js b/lib/constants/federation-constants.js index 7a76a08b..d6c1f813 100644 --- a/lib/constants/federation-constants.js +++ b/lib/constants/federation-constants.js @@ -1,3 +1,5 @@ +const { getBridgeStorageIndexFromKey } = require('../utils'); + const KEY_TYPE_BTC = 'btc'; const KEY_TYPE_RSK = 'rsk'; const KEY_TYPE_MST = 'mst'; @@ -35,10 +37,16 @@ const REGTEST_FEDERATION_CHANGE_ADDRESSES = [ const GENESIS_FEDERATION_ADDRESS = '2N5muMepJizJE1gR7FbHJU6CD18V3BpNF9p'; const GENESIS_FEDERATION_REDEEM_SCRIPT = '0x522102cd53fc53a07f211641a677d250f6de99caf620e8e77071e811a28b3bcddf0be1210362634ab57dae9cb373a5d536e66a8c4f67468bbcfb063809bab643072d78a1242103c5946b3fbae03a654237da863c9ed534e0878657175b132b8ca630f245df04db53ae'; -const FEDERATION_ACTIVATION_AGE = 20; +const VALIDATION_PERIOD_DURATION_IN_BLOCKS = 125; +const FEDERATION_ACTIVATION_AGE = 150; const FUNDS_MIGRATION_AGE_SINCE_ACTIVATION_BEGIN = 15; const FUNDS_MIGRATION_AGE_SINCE_ACTIVATION_END = 150; +const svpFundTxHashUnsignedStorageIndex = getBridgeStorageIndexFromKey('svpFundTxHashUnsigned'); +const svpFundTxSignedStorageIndex = getBridgeStorageIndexFromKey('svpFundTxSigned'); +const svpSpendTxHashUnsignedStorageIndex = getBridgeStorageIndexFromKey('svpSpendTxHashUnsigned'); +const svpSpendTxWaitingForSignaturesStorageIndex = getBridgeStorageIndexFromKey('svpSpendTxWaitingForSignatures'); + module.exports = { KEY_TYPE_BTC, KEY_TYPE_RSK, @@ -54,4 +62,9 @@ module.exports = { FEDERATION_ACTIVATION_AGE, FUNDS_MIGRATION_AGE_SINCE_ACTIVATION_BEGIN, FUNDS_MIGRATION_AGE_SINCE_ACTIVATION_END, + VALIDATION_PERIOD_DURATION_IN_BLOCKS, + svpFundTxHashUnsignedStorageIndex, + svpFundTxSignedStorageIndex, + svpSpendTxHashUnsignedStorageIndex, + svpSpendTxWaitingForSignaturesStorageIndex, }; diff --git a/lib/federation-utils.js b/lib/federation-utils.js index 8ff2f4a4..37db8a0e 100644 --- a/lib/federation-utils.js +++ b/lib/federation-utils.js @@ -23,7 +23,81 @@ var compareFederateKeys = (publicKeysA, publicKeysB) => { return comparison; }; +const getActiveFederationKeys = async (bridge) => { + + const initialFederationKeys = []; + + const initialFederationSize = Number(await bridge.methods.getFederationSize().call()); + + for(let i = 0; i < initialFederationSize; i++) { + + const federatorBtcPublicKey = await bridge.methods.getFederatorPublicKeyOfType(i, KEY_TYPE_BTC).call(); + const federatorRskPublicKey = await bridge.methods.getFederatorPublicKeyOfType(i, KEY_TYPE_RSK).call(); + const federatorMstPublicKey = await bridge.methods.getFederatorPublicKeyOfType(i, KEY_TYPE_MST).call(); + + initialFederationKeys.push({ + [KEY_TYPE_BTC]: federatorBtcPublicKey, + [KEY_TYPE_RSK]: federatorRskPublicKey, + [KEY_TYPE_MST]: federatorMstPublicKey + }); + + } + + return initialFederationKeys; + +}; + +const getProposedFederationPublicKeys = async (bridge) => { + + const proposedFederationKeys = []; + + const proposedFederationSize = Number(await bridge.methods.getProposedFederationSize().call()); + + for(let i = 0; i < proposedFederationSize; i++) { + + const federatorBtcPublicKey = await bridge.methods.getProposedFederatorPublicKeyOfType(i, KEY_TYPE_BTC).call(); + const federatorRskPublicKey = await bridge.methods.getProposedFederatorPublicKeyOfType(i, KEY_TYPE_RSK).call(); + const federatorMstPublicKey = await bridge.methods.getProposedFederatorPublicKeyOfType(i, KEY_TYPE_MST).call(); + + proposedFederationKeys.push({ + [KEY_TYPE_BTC]: federatorBtcPublicKey, + [KEY_TYPE_RSK]: federatorRskPublicKey, + [KEY_TYPE_MST]: federatorMstPublicKey + }); + + } + + return proposedFederationKeys; + +}; + +const getProposedFederationInfo = async (bridge) => { + + const proposedFederationInfoResponses = await Promise.all([ + bridge.methods.getProposedFederationSize().call(), + bridge.methods.getProposedFederationAddress().call(), + bridge.methods.getProposedFederationCreationBlockNumber().call(), + bridge.methods.getProposedFederationCreationTime().call() + ]); + + const proposedFederationSize = Number(proposedFederationInfoResponses[0]); + const proposedFederationAddress = proposedFederationInfoResponses[1]; + const proposedFederationCreationBlockNumber = Number(proposedFederationInfoResponses[2]); + const proposedFederationCreationTime = Number(proposedFederationInfoResponses[3]); + + return { + proposedFederationSize, + proposedFederationAddress, + proposedFederationCreationBlockNumber, + proposedFederationCreationTime + }; + +}; + module.exports = { comparePublicKeys, compareFederateKeys, + getProposedFederationPublicKeys, + getProposedFederationInfo, + getActiveFederationKeys, }; diff --git a/lib/rsk-tx-helper-provider.js b/lib/rsk-tx-helper-provider.js index 7524b342..d43a2c05 100644 --- a/lib/rsk-tx-helper-provider.js +++ b/lib/rsk-tx-helper-provider.js @@ -1,4 +1,5 @@ const { RskTransactionHelper } = require('rsk-transaction-helper'); +const { extendWeb3WithRskModule } = require('../lib/web3-utils'); /** * Creates and returns a list of RskTransactionHelper instances for each federate node @@ -7,7 +8,12 @@ const { RskTransactionHelper } = require('rsk-transaction-helper'); */ const getRskTransactionHelpers = (federates) => { federates = federates || Runners.hosts.federates; - const rskTransactionHelpers = federates.map(federate => getRskTransactionHelper(federate.host)); + const rskTransactionHelpers = federates.map(federate => { + const rskTxHelper = getRskTransactionHelper(federate.host); + extendWeb3WithRskModule(rskTxHelper.getClient()); + return rskTxHelper; + }); + return rskTransactionHelpers; }; @@ -19,6 +25,7 @@ const getRskTransactionHelpers = (federates) => { */ const getRskTransactionHelper = (host, maxAttempts = 5) => { const rskTransactionHelper = new RskTransactionHelper({ hostUrl: host || Runners.hosts.federate.host, maxAttempts }); + extendWeb3WithRskModule(rskTransactionHelper.getClient()); return rskTransactionHelper; }; diff --git a/lib/utils.js b/lib/utils.js index fb3cfe7a..933c2774 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,5 +1,6 @@ var fs = require('fs-extra'); var utils = require('peglib').utils; +const RLP = require('rlp'); var sequentialPromise = function(n, promiseReturn) { if (n <= 0) { @@ -160,6 +161,37 @@ function splitStringIntoChunks(inputString, chunkSize) { return inputString.match(regex); } +const bytesToHexString = (bytes) => { + return bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), ''); +}; + +const removeEmptyLeftBytes = (storageValue) => { + const result = `${storageValue.replaceAll(/^0x0+/g, '')}`; + if(!result.startsWith('0x')) { + return `0x${result}`; + } + return result; +}; + +const decodeRlp = (rlpEncoded) => { + const uint8ArrayDecoded = RLP.decode(rlpEncoded); + const bytesStr = bytesToHexString(uint8ArrayDecoded); + return bytesStr; +}; + +const getBridgeStorageValueDecodedHexString = (bridgeStorageValueEncodedAsRlp, append0xPrefix = true) => { + const rlpBytesWithoutEmptyBytes = removeEmptyLeftBytes(bridgeStorageValueEncodedAsRlp); + const decodedHexFromRlp = decodeRlp(rlpBytesWithoutEmptyBytes); + return append0xPrefix ? `0x${decodedHexFromRlp}` : decodedHexFromRlp; +}; + +const getBridgeStorageIndexFromKey = (storageKey) => { + return Buffer.from(storageKey) + .toString('hex') + .padStart(64, '0') + .padStart(66, '0x'); +}; + module.exports = { sequentialPromise, mapPromiseAll, @@ -180,4 +212,9 @@ module.exports = { remove: removeAdditionalFederationAddress }, splitStringIntoChunks, + bytesToHexString, + removeEmptyLeftBytes, + decodeRlp, + getBridgeStorageValueDecodedHexString, + getBridgeStorageIndexFromKey, } diff --git a/lib/web3-utils.js b/lib/web3-utils.js new file mode 100644 index 00000000..b8d63b48 --- /dev/null +++ b/lib/web3-utils.js @@ -0,0 +1,15 @@ +const extendWeb3WithRskModule = (web3) => { + web3.extend({ + property: 'rsk', + methods: [{ + name: 'getStorageBytesAt', + call: 'rsk_getStorageBytesAt', + params: 3, + inputFormatter: [web3.extend.formatters.inputAddressFormatter, web3.extend.formatters.inputDefaultBlockNumberFormatter, web3.extend.formatters.inputDefaultBlockNumberFormatter] + }] + }); +}; + +module.exports = { + extendWeb3WithRskModule, +}; diff --git a/package-lock.json b/package-lock.json index 3bb5406e..a0097b6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,12 +10,12 @@ "license": "GPL3", "dependencies": { "@rsksmart/bridge-state-data-parser": "^1.2.0", - "@rsksmart/bridge-transaction-parser": "^1.1.4", + "@rsksmart/bridge-transaction-parser": "github:rsksmart/bridge-transaction-parser#fbdeb686fc438f530d3a5f01bce062fd455be01f", "@rsksmart/btc-eth-unit-converter": "^1.0.0", "@rsksmart/btc-rsk-derivation": "^0.0.2", "@rsksmart/pmt-builder": "^3.0.0", "@rsksmart/powpeg-redeemscript-parser": "^1.0.1", - "@rsksmart/rsk-precompiled-abis": "^6.0.0-ARROWHEAD", + "@rsksmart/rsk-precompiled-abis": "github:rsksmart/precompiled-abis#841aa8f0caab0356ae510708bfb2fceae9144790", "bn.js": "^4.11.8", "btc-transaction-helper": "git+https://git@github.com/rsksmart/btc-transaction-helper#v3.5.0", "chai": "^4.1.2", @@ -42,6 +42,139 @@ "shelljs": "^0.8.5" } }, + "node_modules/@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz", + "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/@ethereumjs/rlp": { "version": "4.0.1", "license": "MPL-2.0", @@ -483,6 +616,26 @@ "@ethersproject/strings": "^5.7.0" } }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "deprecated": "Use @eslint/config-array instead", + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "deprecated": "Use @eslint/object-schema instead" + }, "node_modules/@noble/curves": { "version": "1.4.2", "license": "MIT", @@ -522,11 +675,18 @@ "web3": "^1.5.2" } }, + "node_modules/@rsksmart/bridge-state-data-parser/node_modules/@rsksmart/rsk-precompiled-abis": { + "version": "6.0.0-ARROWHEAD", + "resolved": "https://registry.npmjs.org/@rsksmart/rsk-precompiled-abis/-/rsk-precompiled-abis-6.0.0-ARROWHEAD.tgz", + "integrity": "sha512-+g22mIXjdTHoakCXnjttA9MMJMVyYzZ8VsAL4bMPeTZ8kn9OCZBpXkAtCsXkDCGeYCgrWD9F3VS59vBb/AOdGA==" + }, "node_modules/@rsksmart/bridge-transaction-parser": { "version": "1.1.4", + "resolved": "git+ssh://git@github.com/rsksmart/bridge-transaction-parser.git#fbdeb686fc438f530d3a5f01bce062fd455be01f", + "integrity": "sha512-DksoNRRvqnci+Mqxo2S3pnDqoerIq3F4H/fGCzsbxKE8f9EZQPOFeyesEFFeY5HkF7vQ8WoYTKdCXo0FeMuaZQ==", "license": "MIT", "dependencies": { - "@rsksmart/rsk-precompiled-abis": "^6.0.0-ARROWHEAD" + "@rsksmart/rsk-precompiled-abis": "git+https://github.com/rsksmart/precompiled-abis#841aa8f0caab0356ae510708bfb2fceae9144790" } }, "node_modules/@rsksmart/btc-eth-unit-converter": { @@ -617,7 +777,9 @@ } }, "node_modules/@rsksmart/rsk-precompiled-abis": { - "version": "6.0.0-ARROWHEAD", + "version": "7.0.0-LOVELL", + "resolved": "git+ssh://git@github.com/rsksmart/precompiled-abis.git#841aa8f0caab0356ae510708bfb2fceae9144790", + "integrity": "sha512-/9awaBSdKy8lNXxW7b6aOmykJy7kGj26zHdLihxLMRRx4bzCs6ttHeoxmZcynss56jhH+f19/PRgFoZxjEqoMQ==", "license": "ISC" }, "node_modules/@scure/base": { @@ -792,6 +954,25 @@ "node": ">= 0.6" } }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/aes-js": { "version": "3.1.2", "license": "MIT" @@ -877,6 +1058,14 @@ "node": "*" } }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/async": { "version": "0.2.10" }, @@ -1309,6 +1498,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase": { "version": "6.3.0", "license": "MIT", @@ -1611,6 +1808,19 @@ "node-fetch": "^2.6.12" } }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/crypt": { "version": "0.0.2", "license": "BSD-3-Clause", @@ -1629,6 +1839,21 @@ "node": ">=0.12" } }, + "node_modules/d/node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/dashdash": { "version": "1.14.1", "license": "MIT", @@ -1715,6 +1940,11 @@ "node": ">=6" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, "node_modules/defer-to-connect": { "version": "2.0.1", "license": "MIT", @@ -1770,6 +2000,17 @@ "node": ">=0.3.1" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dom-walk": { "version": "0.1.2" }, @@ -1834,6 +2075,18 @@ "once": "^1.4.0" } }, + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dependencies": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/es-define-property": { "version": "1.0.0", "license": "MIT", @@ -1851,7 +2104,6 @@ "node": ">= 0.4" } }, - "node_modules/es5-ext": {}, "node_modules/es6-iterator": { "version": "2.0.3", "license": "MIT", @@ -1861,6 +2113,21 @@ "es6-symbol": "^3.1.1" } }, + "node_modules/es6-iterator/node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/es6-promise": { "version": "4.2.8", "license": "MIT" @@ -1897,7 +2164,48 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint": {}, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "engines": { + "node": ">=10" + } + }, "node_modules/esniff": { "version": "2.0.1", "license": "ISC", @@ -1911,6 +2219,108 @@ "node": ">=0.10" } }, + "node_modules/esniff/node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/etag": { "version": "1.8.1", "license": "MIT", @@ -2084,6 +2494,21 @@ "es5-ext": "~0.10.14" } }, + "node_modules/event-emitter/node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/eventemitter3": { "version": "4.0.4", "license": "MIT" @@ -2177,6 +2602,37 @@ "version": "2.1.0", "license": "MIT" }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "node_modules/fast-uri": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", + "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/file-uri-to-path": { "version": "1.0.0", "license": "MIT" @@ -2246,6 +2702,19 @@ "flat": "cli.js" } }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/flatted": { "version": "3.3.1", "license": "ISC" @@ -2350,6 +2819,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==" + }, "node_modules/get-caller-file": { "version": "2.0.5", "license": "ISC", @@ -2434,6 +2908,20 @@ "process": "^0.11.10" } }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gopd": { "version": "1.0.1", "license": "MIT", @@ -2678,6 +3166,37 @@ ], "license": "BSD-3-Clause" }, + "node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/inflight": { "version": "1.0.6", "license": "ISC", @@ -2847,6 +3366,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, "node_modules/isstream": { "version": "0.1.2", "license": "MIT" @@ -2859,6 +3383,11 @@ "version": "0.8.0", "license": "MIT" }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, "node_modules/js-yaml": { "version": "4.1.0", "license": "MIT", @@ -2885,6 +3414,11 @@ "version": "0.4.1", "license": "MIT" }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "license": "ISC" @@ -2940,6 +3474,18 @@ "json-buffer": "3.0.1" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "license": "MIT", @@ -2963,6 +3509,16 @@ "version": "4.4.2", "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==" + }, "node_modules/log-symbols": { "version": "4.1.0", "license": "MIT", @@ -3291,6 +3847,11 @@ "version": "0.1.2", "license": "MIT" }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, "node_modules/negotiator": { "version": "0.6.3", "license": "MIT", @@ -3432,6 +3993,22 @@ "wrappy": "1" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/os-tmpdir": { "version": "1.0.2", "license": "MIT", @@ -3472,6 +4049,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-headers": { "version": "2.0.5", "license": "MIT" @@ -3497,6 +4085,14 @@ "node": ">=0.10.0" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, "node_modules/path-parse": { "version": "1.0.7", "dev": true, @@ -3611,6 +4207,11 @@ "version": "2.1.0", "license": "MIT" }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, "node_modules/picomatch": { "version": "2.3.1", "license": "MIT", @@ -3628,6 +4229,14 @@ "node": ">= 0.4" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/process": { "version": "0.11.10", "license": "MIT", @@ -3635,6 +4244,14 @@ "node": ">= 0.6.0" } }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "license": "MIT", @@ -3784,6 +4401,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, "node_modules/request": { "version": "2.88.2", "license": "Apache-2.0", @@ -3827,10 +4455,26 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve-alpn": { "version": "1.2.1", "license": "MIT" }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, "node_modules/responselike": { "version": "2.0.1", "license": "MIT", @@ -3855,10 +4499,102 @@ "eslint": "^7.32.0" } }, + "node_modules/rewire/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/rewire/node_modules/eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dependencies": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/rewire/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/rfdc": { "version": "1.4.1", "license": "MIT" }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/ripemd160": { "version": "2.0.2", "license": "MIT", @@ -3923,6 +4659,17 @@ "pbkdf2": "^3.0.3" } }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/send": { "version": "0.19.0", "license": "MIT", @@ -4031,6 +4778,25 @@ "sha.js": "bin.js" } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, "node_modules/shelljs": { "version": "0.8.5", "dev": true, @@ -4131,6 +4897,22 @@ "node": ">=8" } }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, "node_modules/solc": { "version": "0.8.28", "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.28.tgz", @@ -4169,6 +4951,11 @@ "node": ">=0.6.0" } }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, "node_modules/sshpk": { "version": "1.18.0", "license": "MIT", @@ -4393,6 +5180,41 @@ "node": ">=8" } }, + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "node_modules/tar": { "version": "4.4.19", "license": "ISC", @@ -4419,6 +5241,11 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, "node_modules/timed-out": { "version": "4.0.1", "license": "MIT", @@ -4487,6 +5314,17 @@ "version": "2.7.3", "license": "ISC" }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.1.0", "license": "MIT", @@ -4494,6 +5332,17 @@ "node": ">=4" } }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/type-is": { "version": "1.6.18", "license": "MIT", @@ -4589,6 +5438,11 @@ "uuid": "bin/uuid" } }, + "node_modules/v8-compile-cache": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz", + "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==" + }, "node_modules/varint": { "version": "5.0.2", "license": "MIT" @@ -5046,6 +5900,20 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/which-typed-array": { "version": "1.1.15", "license": "MIT", @@ -5070,6 +5938,14 @@ "bs58check": "<3.0.0" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/workerpool": { "version": "6.5.1", "license": "Apache-2.0" diff --git a/package.json b/package.json index 493c95f5..7e168606 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "license": "GPL3", "dependencies": { "@rsksmart/bridge-state-data-parser": "^1.2.0", - "@rsksmart/bridge-transaction-parser": "^1.1.4", + "@rsksmart/bridge-transaction-parser": "github:rsksmart/bridge-transaction-parser#fbdeb686fc438f530d3a5f01bce062fd455be01f", "@rsksmart/btc-eth-unit-converter": "^1.0.0", "@rsksmart/btc-rsk-derivation": "^0.0.2", "@rsksmart/pmt-builder": "^3.0.0", @@ -34,7 +34,7 @@ "mocha-junit-reporter": "^2.2.1", "pegin-address-verificator": "git+https://git@github.com/rsksmart/pegin-address-verifier#v0.4.0", "peglib": "git+https://github.com/rsksmart/rsk-peglib#v1.4.15", - "@rsksmart/rsk-precompiled-abis": "^6.0.0-ARROWHEAD", + "@rsksmart/rsk-precompiled-abis": "github:rsksmart/precompiled-abis#841aa8f0caab0356ae510708bfb2fceae9144790", "rsk-transaction-helper": "git+https://github.com/rsksmart/rootstock-transaction-helper#v3.1.0", "solc": "^0.8.28", "stream-line-wrapper": "^0.1.1", diff --git a/test.js b/test.js index 79f6d8e4..fac28e9e 100644 --- a/test.js +++ b/test.js @@ -56,7 +56,7 @@ global.Runners = { fingerroot500: 1, arrowhead600: 1, arrowhead631: 1, - lovell700: -1, + lovell700: 1, }, additionalFederationAddresses: [] } diff --git a/tests/00_00_04-change-federation.js b/tests/00_00_04-change-federation.js index 456d3528..f90e88ee 100644 --- a/tests/00_00_04-change-federation.js +++ b/tests/00_00_04-change-federation.js @@ -1,11 +1,18 @@ -const rskUtils = require('../lib/rsk-utils'); -const { getRskTransactionHelpers } = require('../lib/rsk-tx-helper-provider'); -const { getBridge } = require('../lib/bridge-provider'); +const { expect } = require('chai'); +const bitcoinJsLib = require('bitcoinjs-lib'); +const { getBridgeState } = require('@rsksmart/bridge-state-data-parser'); const { btcToWeis } = require('@rsksmart/btc-eth-unit-converter'); -const { removePrefix0x, ensure0x, splitStringIntoChunks } = require('../lib/utils'); const BridgeTransactionParser = require('@rsksmart/bridge-transaction-parser'); const redeemScriptParser = require('@rsksmart/powpeg-redeemscript-parser'); -const { expect } = require('chai'); +const rskUtils = require('../lib/rsk-utils'); +const { getRskTransactionHelpers } = require('../lib/rsk-tx-helper-provider'); +const { getBridge } = require('../lib/bridge-provider'); +const { + removePrefix0x, + ensure0x, + splitStringIntoChunks, + getBridgeStorageValueDecodedHexString, +} = require('../lib/utils'); const { KEY_TYPE_BTC, KEY_TYPE_RSK, @@ -15,37 +22,30 @@ const { FUNDS_MIGRATION_AGE_SINCE_ACTIVATION_END, ERP_PUBKEYS, ERP_CSV_VALUE, + svpFundTxHashUnsignedStorageIndex, + svpFundTxSignedStorageIndex, + svpSpendTxHashUnsignedStorageIndex, + svpSpendTxWaitingForSignaturesStorageIndex, } = require('../lib/constants/federation-constants'); +const { + BRIDGE_ADDRESS, + createSenderRecipientInfo, + sendPegin, + ensurePeginIsRegistered +} = require('../lib/2wp-utils'); +const { getBtcClient } = require('../lib/btc-client-provider'); +const { MINIMUM_PEGOUT_AMOUNT_IN_SATOSHIS } = require('../lib/constants/pegout-constants'); +const { + getActiveFederationKeys, + getProposedFederationInfo, + getProposedFederationPublicKeys +} = require('../lib/federation-utils'); // Generated with seed newFed1 const newFederator1PublicKey = '0x02f80abfd3dac069887f974ac033cb62991a0ed55b9880faf8b8cbd713b75d649e'; // Generated with seed newFed2 const newFederator2PublicKey = '0x03488898918c76758e52842c700060adbbbd0a38aa836838fd7215147b924ef7dc'; -const getCurrentFederationKeys = async (bridge) => { - - const initialFederationKeys = []; - - const initialFederationSize = Number(await bridge.methods.getFederationSize().call()); - - for(let i = 0; i < initialFederationSize; i++) { - - const federatorBtcPublicKey = await bridge.methods.getFederatorPublicKeyOfType(i, KEY_TYPE_BTC).call(); - const federatorRskPublicKey = await bridge.methods.getFederatorPublicKeyOfType(i, KEY_TYPE_RSK).call(); - const federatorMstPublicKey = await bridge.methods.getFederatorPublicKeyOfType(i, KEY_TYPE_MST).call(); - - initialFederationKeys.push({ - [KEY_TYPE_BTC]: federatorBtcPublicKey, - [KEY_TYPE_RSK]: federatorRskPublicKey, - [KEY_TYPE_MST]: federatorMstPublicKey - }); - - } - - return initialFederationKeys; - -}; - const createNewFederationKeys = (currentFederationKeys) => { const newFederationKeys = [...currentFederationKeys]; @@ -63,7 +63,7 @@ const createNewFederationKeys = (currentFederationKeys) => { }); // Sort by btc public key - newFederationKeys.sort((keyA, keyB) => keyA.btc.localeCompare(keyB.btc)) + newFederationKeys.sort((keyA, keyB) => keyA.btc.localeCompare(keyB.btc)); return newFederationKeys; @@ -87,6 +87,7 @@ describe('Change federation', async function() { let rskTxHelper; let bridge; let bridgeTxParser; + let btcTxHelper; const regtestFedChangeAuthorizer1PrivateKey = REGTEST_FEDERATION_CHANGE_PRIVATE_KEYS[0]; const regtestFedChangeAuthorizer2PrivateKey = REGTEST_FEDERATION_CHANGE_PRIVATE_KEYS[1]; @@ -103,12 +104,15 @@ describe('Change federation', async function() { let expectedNewFederationAddress; let commitFederationCreationBlockNumber; let expectedNewFederationErpRedeemScript; - + let minimumPeginValueInSatoshis; + let expectedFlyoverAddress; + before(async () => { rskTxHelpers = getRskTransactionHelpers(); rskTxHelper = rskTxHelpers[0]; bridgeTxParser = new BridgeTransactionParser(rskTxHelper.getClient()); + btcTxHelper = getBtcClient(); // Import the private keys of the federation change authorizers. fedChangeAuthorizer1Address = await rskTxHelper.importAccount(regtestFedChangeAuthorizer1PrivateKey); @@ -122,14 +126,24 @@ describe('Change federation', async function() { bridge = getBridge(rskTxHelper.getClient()); - initialFederationPublicKeys = await getCurrentFederationKeys(bridge); + initialFederationPublicKeys = await getActiveFederationKeys(bridge); newFederationPublicKeys = createNewFederationKeys(initialFederationPublicKeys); newFederationBtcPublicKeys = newFederationPublicKeys.map(federator => federator[KEY_TYPE_BTC]); const expectedNewFederationErpRedeemScriptBuffer = redeemScriptParser.getP2shErpRedeemScript(newFederationBtcPublicKeys.map(key => removePrefix0x(key)), ERP_PUBKEYS, ERP_CSV_VALUE); expectedNewFederationErpRedeemScript = expectedNewFederationErpRedeemScriptBuffer.toString('hex'); expectedNewFederationAddress = redeemScriptParser.getAddressFromRedeemScript('REGTEST', expectedNewFederationErpRedeemScriptBuffer); + const flyoverPowpegRedeemScript = redeemScriptParser.getFlyoverRedeemScript(expectedNewFederationErpRedeemScriptBuffer, "0000000000000000000000000000000000000000000000000000000000000001"); + expectedFlyoverAddress = redeemScriptParser.getAddressFromRedeemScript('REGTEST', flyoverPowpegRedeemScript); + initialFederationAddress = await bridge.methods.getFederationAddress().call(); + + minimumPeginValueInSatoshis = Number(await bridge.methods.getMinimumLockTxValue().call()); + + // Making a donation pegin to the Bridge to ensure there is enough utxo value to create the SVP fund transaction. + const senderRecipientInfo = await createSenderRecipientInfo(rskTxHelper, btcTxHelper, 'legacy', 2 + btcTxHelper.getFee()); + const btcPeginTxHash = await sendPegin(rskTxHelper, btcTxHelper, senderRecipientInfo.btcSenderAddressInfo, 2); + await ensurePeginIsRegistered(rskTxHelper, btcPeginTxHash); }); @@ -236,6 +250,91 @@ describe('Change federation', async function() { }); + it('should create the proposed federation', async () => { + + // Act + + const proposedFederationInfo = await getProposedFederationInfo(bridge); + + // Assert + + const expectedProposedFederationSize = newFederationPublicKeys.length; + expect(proposedFederationInfo.proposedFederationSize).to.be.equal(expectedProposedFederationSize, 'The proposed federation size should be the expected one.'); + + expect(proposedFederationInfo.proposedFederationAddress).to.be.equal(expectedNewFederationAddress, 'The proposed federation address should be the expected one.'); + + expect(proposedFederationInfo.proposedFederationCreationBlockNumber).to.be.equal(commitFederationCreationBlockNumber, 'The proposed federation creation block number should be the expected one.'); + + const proposedFederationMembers = await getProposedFederationPublicKeys(bridge); + + expect(proposedFederationMembers).to.be.deep.equal(newFederationPublicKeys, 'The proposed federation members should be the expected ones.'); + + }); + + it('should not have created svp transaction and there should not be any SVP values in storage yet', async () => { + + // Assert + + const bridgeState = await getBridgeState(rskTxHelper.getClient()); + + expect(bridgeState.pegoutsWaitingForConfirmations.length).to.be.equal(0, 'No pegout should be waiting for confirmations.'); + expect(bridgeState.pegoutsWaitingForSignatures.length).to.be.equal(0, 'No pegout should be waiting for signatures.'); + + await assertSvpValuesNotPresentInStorage(rskTxHelper); + + }); + + it('should create the SVP Fund transaction on the next updateCollections call', async () => { + + // Act + + await rskUtils.waitAndUpdateBridge(rskTxHelper); + + // Assert + + const bridgeStateAfterUpdateCollections = await getBridgeState(rskTxHelper.getClient()); + + // The SVP fund transaction should be created and put in waiting for confirmations. + expect(bridgeStateAfterUpdateCollections.pegoutsWaitingForConfirmations.length).to.be.equal(1, 'There should be one pegout waiting for confirmations.'); + expect(bridgeStateAfterUpdateCollections.pegoutsWaitingForSignatures.length).to.be.equal(0, 'No pegout should be waiting for signatures.'); + + const svpPegoutWaitingForConfirmations = bridgeStateAfterUpdateCollections.pegoutsWaitingForConfirmations[0]; + + const pegoutCreationBlockNumber = Number(svpPegoutWaitingForConfirmations.pegoutCreationBlockNumber); + + expect(pegoutCreationBlockNumber).to.be.equal(commitFederationCreationBlockNumber + 1, 'The svp fund tx pegout creation block number should be the block that contains the first updateCollections call right after the commitFederation call.'); + + const rawSvpBtcTransaction = svpPegoutWaitingForConfirmations.btcRawTx; + + const btcTransaction = bitcoinJsLib.Transaction.fromHex(rawSvpBtcTransaction); + + expect(btcTransaction.outs.length).to.be.equal(3, 'The SVP fund transaction should have 3 outputs.'); + + const proposedFederationAddress = await bridge.methods.getProposedFederationAddress().call(); + + // The output addresses should be in the expected order. + const proposedFederationOutput = btcTransaction.outs[0]; + const flyoverOutput = btcTransaction.outs[1]; + const activeFederationOutput = btcTransaction.outs[2]; + + const actualProposedFederationAddress = bitcoinJsLib.address.fromOutputScript(proposedFederationOutput.script, btcTxHelper.btcConfig.network); + expect(actualProposedFederationAddress).to.be.equal(proposedFederationAddress, 'The proposed federation address in the SVP fund transaction should be the first output.'); + + const actualFlyoverAddress = bitcoinJsLib.address.fromOutputScript(flyoverOutput.script, btcTxHelper.btcConfig.network); + expect(actualFlyoverAddress).to.be.equal(expectedFlyoverAddress, 'The flyover address in the SVP fund transaction should be the second expected output.'); + + const actualActiveFederationAddress = bitcoinJsLib.address.fromOutputScript(activeFederationOutput.script, btcTxHelper.btcConfig.network); + expect(actualActiveFederationAddress).to.be.equal(initialFederationAddress, 'The active federation address in the SVP fund transaction should be the third output.'); + + // The proposed federation and flyover addresses output values should be double the minimum pegout value. + expect(proposedFederationOutput.value).to.be.equal(MINIMUM_PEGOUT_AMOUNT_IN_SATOSHIS * 2, 'The proposed federation output value should be double the minimum pegout value.'); + expect(flyoverOutput.value).to.be.equal(MINIMUM_PEGOUT_AMOUNT_IN_SATOSHIS * 2, 'The flyover output value should be double the minimum pegout value.'); + + // Only the svp fund tx hash unsigned value should be in storage + await assertOnlySvpFundTxHashUnsignedIsInStorage(rskTxHelper, btcTransaction.getId()); + + }); + it('should activate federation', async () => { const federationActivationBlockNumber = commitFederationCreationBlockNumber + FEDERATION_ACTIVATION_AGE; @@ -284,3 +383,36 @@ describe('Change federation', async function() { }); }); + +const assertSvpValuesNotPresentInStorage = async (rskTxHelper) => { + + const svpFundTxHashUnsigned = await rskTxHelper.getClient().rsk.getStorageBytesAt(BRIDGE_ADDRESS, svpFundTxHashUnsignedStorageIndex); + expect(svpFundTxHashUnsigned).to.be.equal('0x0', 'The SVP fund tx hash unsigned storage value should be empty.'); + + const svpFundTxSigned = await rskTxHelper.getClient().rsk.getStorageBytesAt(BRIDGE_ADDRESS, svpFundTxSignedStorageIndex); + expect(svpFundTxSigned).to.be.equal('0x0', 'The SVP fund tx signed storage value should be empty.'); + + const svpSpendTxHashUnsigned = await rskTxHelper.getClient().rsk.getStorageBytesAt(BRIDGE_ADDRESS, svpSpendTxHashUnsignedStorageIndex); + expect(svpSpendTxHashUnsigned).to.be.equal('0x0', 'The SVP spend tx hash unsigned storage value should be empty.'); + + const svpSpendTxWaitingForSignatures = await rskTxHelper.getClient().rsk.getStorageBytesAt(BRIDGE_ADDRESS, svpSpendTxWaitingForSignaturesStorageIndex); + expect(svpSpendTxWaitingForSignatures).to.be.equal('0x0', 'The SVP spend tx waiting for signatures storage value should be empty.'); + +}; + +const assertOnlySvpFundTxHashUnsignedIsInStorage = async (rskTxHelper, pegoutBtcTxHash) => { + + const svpFundTxHashUnsignedRlpEncoded = await rskTxHelper.getClient().rsk.getStorageBytesAt(BRIDGE_ADDRESS, svpFundTxHashUnsignedStorageIndex); + const svpFundTxHashUnsigned = getBridgeStorageValueDecodedHexString(svpFundTxHashUnsignedRlpEncoded, false); + expect(svpFundTxHashUnsigned).to.be.equal(pegoutBtcTxHash, 'The SVP fund tx hash unsigned storage value should be the tx id of the SVP fund tx.'); + + const svpFundTxSigned = await rskTxHelper.getClient().rsk.getStorageBytesAt(BRIDGE_ADDRESS, svpFundTxSignedStorageIndex); + expect(svpFundTxSigned).to.be.equal('0x0', 'The SVP fund tx signed storage value should be empty.'); + + const svpSpendTxHashUnsigned = await rskTxHelper.getClient().rsk.getStorageBytesAt(BRIDGE_ADDRESS, svpSpendTxHashUnsignedStorageIndex); + expect(svpSpendTxHashUnsigned).to.be.equal('0x0', 'The SVP spend tx hash unsigned storage value should be empty.'); + + const svpSpendTxWaitingForSignatures = await rskTxHelper.getClient().rsk.getStorageBytesAt(BRIDGE_ADDRESS, svpSpendTxWaitingForSignaturesStorageIndex); + expect(svpSpendTxWaitingForSignatures).to.be.equal('0x0', 'The SVP spend tx waiting for signatures storage value should be empty.'); + +};