diff --git a/package-lock.json b/package-lock.json index d7cdf9e75c..2c266b2421 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "@types/ws": "7.4.7", "ajv": "6.12.6", "bignumber.js": "9.0.2", - "bitcoinjs-lib": "5.2.0", + "bitcoinjs-lib": "6.0.2", "bluebird": "3.7.2", "c32check": "1.1.3", "chokidar": "3.5.3", @@ -31,6 +31,7 @@ "cross-env": "7.0.3", "dotenv": "8.6.0", "dotenv-flow": "3.2.0", + "ecpair": "2.1.0", "elliptic": "6.5.4", "escape-goat": "3.0.0", "evt": "1.10.1", @@ -58,6 +59,7 @@ "split2": "3.2.2", "stacks-encoding-native-js": "0.2.0-alpha.0", "strict-event-emitter-types": "2.0.0", + "tiny-secp256k1": "2.2.1", "ts-unused-exports": "7.0.3", "typescript": "4.6.2", "uuid": "8.3.2", @@ -3647,9 +3649,9 @@ } }, "node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" }, "node_modules/before-after-hook": { "version": "2.2.2", @@ -3673,14 +3675,6 @@ "node": ">=8" } }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, "node_modules/bintrees": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz", @@ -3694,60 +3688,18 @@ "node": ">=8.0.0" } }, - "node_modules/bip32": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", - "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", - "dependencies": { - "@types/node": "10.12.18", - "bs58check": "^2.1.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "tiny-secp256k1": "^1.1.3", - "typeforce": "^1.11.5", - "wif": "^2.0.6" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/bip32/node_modules/@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" - }, - "node_modules/bip66": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", - "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/bitcoin-ops": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/bitcoin-ops/-/bitcoin-ops-1.4.1.tgz", - "integrity": "sha512-pef6gxZFztEhaE9RY9HmWVmiIHqCb2OyS4HPKkpc6CIiiOa3Qmuoylxc5P2EkU3w+5eTSifI9SEZC88idAIGow==" - }, "node_modules/bitcoinjs-lib": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-5.2.0.tgz", - "integrity": "sha512-5DcLxGUDejgNBYcieMIUfjORtUeNWl828VWLHJGVKZCb4zIS1oOySTUr0LGmcqJBQgTBz3bGbRQla4FgrdQEIQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-6.0.2.tgz", + "integrity": "sha512-I994pGt9cL5s5OA6mkv1e8IuYcsKN2ORXnWbkqAXLNGvEnOHBhKBSvCjFl7YC2uVoJnfr/iwq7JMrq575SYO5w==", "dependencies": { - "bech32": "^1.1.2", + "bech32": "^2.0.0", "bip174": "^2.0.1", - "bip32": "^2.0.4", - "bip66": "^1.1.0", - "bitcoin-ops": "^1.4.0", - "bs58check": "^2.0.0", + "bs58check": "^2.1.2", "create-hash": "^1.1.0", - "create-hmac": "^1.1.3", - "merkle-lib": "^2.0.10", - "pushdata-bitcoin": "^1.0.1", - "randombytes": "^2.0.1", - "tiny-secp256k1": "^1.1.1", + "ripemd160": "^2.0.2", "typeforce": "^1.11.3", - "varuint-bitcoin": "^1.0.4", + "varuint-bitcoin": "^1.1.2", "wif": "^2.0.1" }, "engines": { @@ -3873,7 +3825,7 @@ "node_modules/bs58": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", "dependencies": { "base-x": "^3.0.2" } @@ -4523,19 +4475,6 @@ "sha.js": "^2.4.0" } }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -4910,6 +4849,19 @@ "safer-buffer": "^2.1.0" } }, + "node_modules/ecpair": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ecpair/-/ecpair-2.1.0.tgz", + "integrity": "sha512-cL/mh3MtJutFOvFc27GPZE2pWL3a3k4YvzUWEOvilnfZVlH3Jwgx/7d6tlD7/75tNk8TG2m+7Kgtz0SI1tWcqw==", + "dependencies": { + "randombytes": "^2.1.0", + "typeforce": "^1.18.0", + "wif": "^2.0.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -6009,11 +5961,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -8432,11 +8379,6 @@ "node": ">= 8" } }, - "node_modules/merkle-lib": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/merkle-lib/-/merkle-lib-2.0.10.tgz", - "integrity": "sha1-grjbrnXieneFOItz+ddyXQ9vMyY=" - }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -8609,7 +8551,8 @@ "node_modules/nan": { "version": "2.15.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "optional": true }, "node_modules/natural-compare": { "version": "1.4.0", @@ -9698,14 +9641,6 @@ "node": ">=6" } }, - "node_modules/pushdata-bitcoin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pushdata-bitcoin/-/pushdata-bitcoin-1.0.1.tgz", - "integrity": "sha1-FZMdPNlnreUiBvUjqnMxrvfUOvc=", - "dependencies": { - "bitcoin-ops": "^1.3.0" - } - }, "node_modules/q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", @@ -11102,19 +11037,14 @@ } }, "node_modules/tiny-secp256k1": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz", - "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==", - "hasInstallScript": true, + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.1.tgz", + "integrity": "sha512-/U4xfVqnVxJXN4YVsru0E6t5wVncu2uunB8+RVR40fYUxkKYUPS10f+ePQZgFBoE/Jbf9H1NBveupF2VmB58Ng==", "dependencies": { - "bindings": "^1.3.0", - "bn.js": "^4.11.8", - "create-hmac": "^1.1.7", - "elliptic": "^6.4.0", - "nan": "^2.13.2" + "uint8array-tools": "0.0.7" }, "engines": { - "node": ">=6.0.0" + "node": ">=14.0.0" } }, "node_modules/tmpl": { @@ -11506,6 +11436,14 @@ "node": ">=4.2.0" } }, + "node_modules/uint8array-tools": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.7.tgz", + "integrity": "sha512-vrrNZJiusLWoFWBqz5Y5KMCgP9W9hnjZHzZiZRT8oNAkq3d5Z5Oe76jAvVVSRh4U8GGR90N2X1dWtrhvx6L8UQ==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", @@ -11829,7 +11767,7 @@ "node_modules/wif": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", - "integrity": "sha1-CNP1IFbGZnkplyb63g1DKudLRwQ=", + "integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==", "dependencies": { "bs58check": "<3.0.0" } @@ -14934,9 +14872,9 @@ } }, "bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" }, "before-after-hook": { "version": "2.2.2", @@ -14954,14 +14892,6 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "requires": { - "file-uri-to-path": "1.0.0" - } - }, "bintrees": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz", @@ -14972,59 +14902,18 @@ "resolved": "https://registry.npmjs.org/bip174/-/bip174-2.0.1.tgz", "integrity": "sha512-i3X26uKJOkDTAalYAp0Er+qGMDhrbbh2o93/xiPyAN2s25KrClSpe3VXo/7mNJoqA5qfko8rLS2l3RWZgYmjKQ==" }, - "bip32": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", - "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", - "requires": { - "@types/node": "10.12.18", - "bs58check": "^2.1.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "tiny-secp256k1": "^1.1.3", - "typeforce": "^1.11.5", - "wif": "^2.0.6" - }, - "dependencies": { - "@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" - } - } - }, - "bip66": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", - "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "bitcoin-ops": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/bitcoin-ops/-/bitcoin-ops-1.4.1.tgz", - "integrity": "sha512-pef6gxZFztEhaE9RY9HmWVmiIHqCb2OyS4HPKkpc6CIiiOa3Qmuoylxc5P2EkU3w+5eTSifI9SEZC88idAIGow==" - }, "bitcoinjs-lib": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-5.2.0.tgz", - "integrity": "sha512-5DcLxGUDejgNBYcieMIUfjORtUeNWl828VWLHJGVKZCb4zIS1oOySTUr0LGmcqJBQgTBz3bGbRQla4FgrdQEIQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-6.0.2.tgz", + "integrity": "sha512-I994pGt9cL5s5OA6mkv1e8IuYcsKN2ORXnWbkqAXLNGvEnOHBhKBSvCjFl7YC2uVoJnfr/iwq7JMrq575SYO5w==", "requires": { - "bech32": "^1.1.2", + "bech32": "^2.0.0", "bip174": "^2.0.1", - "bip32": "^2.0.4", - "bip66": "^1.1.0", - "bitcoin-ops": "^1.4.0", - "bs58check": "^2.0.0", + "bs58check": "^2.1.2", "create-hash": "^1.1.0", - "create-hmac": "^1.1.3", - "merkle-lib": "^2.0.10", - "pushdata-bitcoin": "^1.0.1", - "randombytes": "^2.0.1", - "tiny-secp256k1": "^1.1.1", + "ripemd160": "^2.0.2", "typeforce": "^1.11.3", - "varuint-bitcoin": "^1.0.4", + "varuint-bitcoin": "^1.1.2", "wif": "^2.0.1" } }, @@ -15124,7 +15013,7 @@ "bs58": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", "requires": { "base-x": "^3.0.2" } @@ -15638,19 +15527,6 @@ "sha.js": "^2.4.0" } }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, "create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -15935,6 +15811,16 @@ "safer-buffer": "^2.1.0" } }, + "ecpair": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ecpair/-/ecpair-2.1.0.tgz", + "integrity": "sha512-cL/mh3MtJutFOvFc27GPZE2pWL3a3k4YvzUWEOvilnfZVlH3Jwgx/7d6tlD7/75tNk8TG2m+7Kgtz0SI1tWcqw==", + "requires": { + "randombytes": "^2.1.0", + "typeforce": "^1.18.0", + "wif": "^2.0.6" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -16792,11 +16678,6 @@ "flat-cache": "^3.0.4" } }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -18619,11 +18500,6 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, - "merkle-lib": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/merkle-lib/-/merkle-lib-2.0.10.tgz", - "integrity": "sha1-grjbrnXieneFOItz+ddyXQ9vMyY=" - }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -18753,7 +18629,8 @@ "nan": { "version": "2.15.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "optional": true }, "natural-compare": { "version": "1.4.0", @@ -19561,14 +19438,6 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, - "pushdata-bitcoin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pushdata-bitcoin/-/pushdata-bitcoin-1.0.1.tgz", - "integrity": "sha1-FZMdPNlnreUiBvUjqnMxrvfUOvc=", - "requires": { - "bitcoin-ops": "^1.3.0" - } - }, "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", @@ -20648,15 +20517,11 @@ } }, "tiny-secp256k1": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz", - "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.1.tgz", + "integrity": "sha512-/U4xfVqnVxJXN4YVsru0E6t5wVncu2uunB8+RVR40fYUxkKYUPS10f+ePQZgFBoE/Jbf9H1NBveupF2VmB58Ng==", "requires": { - "bindings": "^1.3.0", - "bn.js": "^4.11.8", - "create-hmac": "^1.1.7", - "elliptic": "^6.4.0", - "nan": "^2.13.2" + "uint8array-tools": "0.0.7" } }, "tmpl": { @@ -20917,6 +20782,11 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==" }, + "uint8array-tools": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.7.tgz", + "integrity": "sha512-vrrNZJiusLWoFWBqz5Y5KMCgP9W9hnjZHzZiZRT8oNAkq3d5Z5Oe76jAvVVSRh4U8GGR90N2X1dWtrhvx6L8UQ==" + }, "unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", @@ -21183,7 +21053,7 @@ "wif": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", - "integrity": "sha1-CNP1IFbGZnkplyb63g1DKudLRwQ=", + "integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==", "requires": { "bs58check": "<3.0.0" } diff --git a/package.json b/package.json index fb02635a03..db275fc166 100644 --- a/package.json +++ b/package.json @@ -114,7 +114,7 @@ "@types/ws": "7.4.7", "ajv": "6.12.6", "bignumber.js": "9.0.2", - "bitcoinjs-lib": "5.2.0", + "bitcoinjs-lib": "6.0.2", "bluebird": "3.7.2", "c32check": "1.1.3", "chokidar": "3.5.3", @@ -123,6 +123,7 @@ "cross-env": "7.0.3", "dotenv": "8.6.0", "dotenv-flow": "3.2.0", + "ecpair": "2.1.0", "elliptic": "6.5.4", "escape-goat": "3.0.0", "evt": "1.10.1", @@ -150,6 +151,7 @@ "split2": "3.2.2", "stacks-encoding-native-js": "0.2.0-alpha.0", "strict-event-emitter-types": "2.0.0", + "tiny-secp256k1": "2.2.1", "ts-unused-exports": "7.0.3", "typescript": "4.6.2", "uuid": "8.3.2", diff --git a/src/btc-faucet.ts b/src/btc-faucet.ts index 1155155377..04db67de3e 100644 --- a/src/btc-faucet.ts +++ b/src/btc-faucet.ts @@ -3,6 +3,7 @@ import * as btc from 'bitcoinjs-lib'; import * as Bluebird from 'bluebird'; import { parsePort, time, logger, logError } from './helpers'; import * as coinselect from 'coinselect'; +import { ECPair, ECPairInterface, validateSigFunction } from './ec-helpers'; function getFaucetPk(): string { const { BTC_FAUCET_PK } = process.env; @@ -12,15 +13,13 @@ function getFaucetPk(): string { return BTC_FAUCET_PK; } -export function getFaucetAccount( - network: btc.Network -): { key: btc.ECPairInterface; address: string } { +export function getFaucetAccount(network: btc.Network): { key: ECPairInterface; address: string } { const pkBuffer = Buffer.from(getFaucetPk(), 'hex'); - const key = btc.ECPair.fromPrivateKey(pkBuffer, { network: network }); + const key = ECPair.fromPrivateKey(pkBuffer, { network: network }); return { key, address: getKeyAddress(key) }; } -export function getKeyAddress(key: btc.ECPairInterface): string { +export function getKeyAddress(key: ECPairInterface): string { const { address } = btc.payments.p2pkh({ pubkey: key.publicKey, network: key.network, @@ -212,7 +211,7 @@ export async function makeBtcFaucetPayment( }); psbt.signAllInputs(faucetWallet.key); - if (!psbt.validateSignaturesOfAllInputs()) { + if (!psbt.validateSignaturesOfAllInputs(validateSigFunction)) { throw new Error('invalid psbt signature'); } psbt.finalizeAllInputs(); diff --git a/src/ec-helpers.ts b/src/ec-helpers.ts new file mode 100644 index 0000000000..7a7876d713 --- /dev/null +++ b/src/ec-helpers.ts @@ -0,0 +1,79 @@ +import * as bitcoin from 'bitcoinjs-lib'; +import * as ecc from 'tiny-secp256k1'; +import { ECPairAPI, ECPairFactory } from 'ecpair'; + +export { ECPairInterface } from 'ecpair'; + +export const ECPair: ECPairAPI = ECPairFactory(ecc); + +export function validateSigFunction(pubkey: Buffer, msghash: Buffer, signature: Buffer): boolean { + return ECPair.fromPublicKey(pubkey).verify(msghash, signature); +} + +const BITCOIN_NETWORKS = { + mainnet: bitcoin.networks.bitcoin, + testnet: bitcoin.networks.testnet, + regtest: bitcoin.networks.regtest, +} as const; + +/** + * Function for creating a tweaked p2tr key-spend only address (this is recommended by BIP341) + * @see https://github.com/bitcoinjs/bitcoinjs-lib/blob/424abf2376772bb57b7668bc35b29ed18879fa0a/test/integration/taproot.md + */ +export function p2trAddressFromPublicKey( + publicKey: Buffer, + network: keyof typeof BITCOIN_NETWORKS +): string { + if (publicKey.length === 32) { + // Defined in BIP340 + const X_ONLY_PUB_KEY_TIE_BREAKER = 0x02; + publicKey = Buffer.concat([Buffer.from([X_ONLY_PUB_KEY_TIE_BREAKER]), publicKey]); + } + const ecPair = ECPair.fromPublicKey(publicKey, { compressed: true }); + const pubKeyBuffer = ecPair.publicKey; + if (!pubKeyBuffer) { + throw new Error(`Could not get public key`); + } + + // x-only pubkey (remove 1 byte y parity) + const myXOnlyPubkey = pubKeyBuffer.slice(1, 33); + const commitHash = bitcoin.crypto.taggedHash('TapTweak', myXOnlyPubkey); + const tweakResult = ecc.xOnlyPointAddTweak(myXOnlyPubkey, commitHash); + if (tweakResult === null) { + throw new Error('Invalid Tweak'); + } + const { xOnlyPubkey: tweaked } = tweakResult; + const scriptPubkey = Buffer.concat([ + // witness v1, PUSH_DATA 32 bytes + Buffer.from([0x51, 0x20]), + // x-only tweaked pubkey + tweaked, + ]); + + const address = bitcoin.address.fromOutputScript(scriptPubkey, BITCOIN_NETWORKS[network]); + return address; +} + +export function p2trAddressFromPrivateKey( + privateKey: Buffer, + network: keyof typeof BITCOIN_NETWORKS +): string { + const ecPair = ECPair.fromPrivateKey(privateKey, { compressed: true }); + if (!ecPair.publicKey) { + throw new Error(`Could not get public key`); + } + return p2trAddressFromPublicKey(ecPair.publicKey, network); +} + +export function generateRandomP2TRAccount( + network: keyof typeof BITCOIN_NETWORKS +): { + address: string; + privateKey: Buffer; +} { + const ecPair = ECPair.makeRandom({ compressed: true }); + return { + address: p2trAddressFromPublicKey(ecPair.publicKey, network), + privateKey: ecPair.privateKey as Buffer, + }; +} diff --git a/src/tests-2.1/pox-2.ts b/src/tests-2.1/pox-2.ts index 72f2bb2dbd..c4c87d0b18 100644 --- a/src/tests-2.1/pox-2.ts +++ b/src/tests-2.1/pox-2.ts @@ -11,6 +11,7 @@ import * as poxHelpers from '../pox-helpers'; import { PgWriteStore } from '../datastore/pg-write-store'; import { StacksNetwork } from '@stacks/network'; import * as btcLib from 'bitcoinjs-lib'; +import { ECPair } from '../ec-helpers'; import { AddressStxBalanceResponse, BurnchainRewardListResponse, @@ -122,7 +123,7 @@ describe('PoX-2 tests', () => { const cycleCount = 1; beforeAll(async () => { - const btcAccount = btcLib.ECPair.makeRandom({ + const btcAccount = ECPair.makeRandom({ compressed: true, network: btcLib.networks.testnet, }); diff --git a/src/tests-btc-faucet/faucet-btc-tests.ts b/src/tests-btc-faucet/faucet-btc-tests.ts index d4dedc4543..1b06cc5f6f 100644 --- a/src/tests-btc-faucet/faucet-btc-tests.ts +++ b/src/tests-btc-faucet/faucet-btc-tests.ts @@ -1,5 +1,6 @@ import * as supertest from 'supertest'; import * as bitcoin from 'bitcoinjs-lib'; +import { ECPair } from '../ec-helpers'; import { makeBtcFaucetPayment, getRpcClient, @@ -39,12 +40,12 @@ describe('btc faucet', () => { const faucetBalanceInitial = await getBtcBalance(regtest, wallet.address); const btcToSend1 = 0.5; - const recipientAddress = getKeyAddress(bitcoin.ECPair.makeRandom({ network: regtest })); + const recipientAddress = getKeyAddress(ECPair.makeRandom({ network: regtest })); const paymentResult = await makeBtcFaucetPayment(regtest, recipientAddress, btcToSend1); expect(paymentResult.txId).toBeTruthy(); await client.generatetoaddress({ - address: getKeyAddress(bitcoin.ECPair.makeRandom({ network: regtest })), + address: getKeyAddress(ECPair.makeRandom({ network: regtest })), nblocks: 100, }); const faucetBalanceFinal = await getBtcBalance(regtest, wallet.address); @@ -64,17 +65,17 @@ describe('btc faucet', () => { await client.generatetoaddress({ address: wallet.address, nblocks: 110 }); const btcToSend1 = 55.2; - const recipientAddress1 = getKeyAddress(bitcoin.ECPair.makeRandom({ network: regtest })); + const recipientAddress1 = getKeyAddress(ECPair.makeRandom({ network: regtest })); const paymentResult1 = await makeBtcFaucetPayment(regtest, recipientAddress1, btcToSend1); expect(paymentResult1.txId).toBeTruthy(); const btcToSend2 = 60.5; - const recipientAddress2 = getKeyAddress(bitcoin.ECPair.makeRandom({ network: regtest })); + const recipientAddress2 = getKeyAddress(ECPair.makeRandom({ network: regtest })); const paymentResult2 = await makeBtcFaucetPayment(regtest, recipientAddress2, btcToSend2); expect(paymentResult2.txId).toBeTruthy(); const btcToSend3 = 0.5; - const recipientAddress3 = getKeyAddress(bitcoin.ECPair.makeRandom({ network: regtest })); + const recipientAddress3 = getKeyAddress(ECPair.makeRandom({ network: regtest })); const paymentResult3 = await makeBtcFaucetPayment(regtest, recipientAddress3, btcToSend3); expect(paymentResult3.txId).toBeTruthy(); @@ -123,7 +124,7 @@ describe('btc faucet', () => { }); test('faucet http receive endpoint', async () => { - const addr = getKeyAddress(bitcoin.ECPair.makeRandom({ network: regtest })); + const addr = getKeyAddress(ECPair.makeRandom({ network: regtest })); const response = await supertest(apiServer.server).post( `/extended/v1/faucets/btc?address=${addr}` ); @@ -134,13 +135,13 @@ describe('btc faucet', () => { }); test('faucet http balance endpoint', async () => { - const addr = getKeyAddress(bitcoin.ECPair.makeRandom({ network: regtest })); + const addr = getKeyAddress(ECPair.makeRandom({ network: regtest })); const response = await supertest(apiServer.server).post( `/extended/v1/faucets/btc?address=${addr}` ); expect(response.status).toBe(200); await getRpcClient().generatetoaddress({ - address: getKeyAddress(bitcoin.ECPair.makeRandom({ network: regtest })), + address: getKeyAddress(ECPair.makeRandom({ network: regtest })), nblocks: 1, }); const balanceResponse = await supertest(apiServer.server).get( diff --git a/src/tests/helpers-tests.ts b/src/tests/helpers-tests.ts index 78945c2a4b..576b078ace 100644 --- a/src/tests/helpers-tests.ts +++ b/src/tests/helpers-tests.ts @@ -4,6 +4,11 @@ import { bitcoinToStacksAddress, stacksToBitcoinAddress } from 'stacks-encoding- import * as c32AddrCache from '../c32-addr-cache'; import { ADDR_CACHE_ENV_VAR } from '../c32-addr-cache'; import { getCurrentGitTag, has0xPrefix, isValidBitcoinAddress } from '../helpers'; +import { + generateRandomP2TRAccount, + p2trAddressFromPrivateKey, + p2trAddressFromPublicKey, +} from '../ec-helpers'; test('get git tag', () => { const tag = getCurrentGitTag(); @@ -187,3 +192,38 @@ test('PoX bitcoin address encoding', () => { expect(encoded).toBe(addr); } }); + +test('P2TR bitcoin address encoding', () => { + // Test vectors from + // https://github.com/bitcoin/bitcoin/blob/master/src/test/data/bip341_wallet_vectors.json + // https://github.com/chaintope/bitcoinrb/blob/c6d2cf564f069e37301b7ba5cd2ff8a25b94dbfe/spec/bitcoin/taproot/simple_builder_spec.rb#L31 + const P2TR_TEST_VECTORS = [ + { + privateKey: null, + publicKey: 'd6889cb081036e0faefa3a35157ad71086b123b2b144b649798b494c300a961d', + address: 'bc1p2wsldez5mud2yam29q22wgfh9439spgduvct83k3pm50fcxa5dps59h4z5', + }, + { + privateKey: '0000000000000000000000000000000000000000000000000000000000000001', + publicKey: '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', + address: 'bc1pmfr3p9j00pfxjh0zmgp99y8zftmd3s5pmedqhyptwy6lm87hf5sspknck9', + }, + ] as const; + + for (const vector of P2TR_TEST_VECTORS) { + const pubKeyBuff = Buffer.from(vector.publicKey, 'hex'); + const p2trAddrFromPub = p2trAddressFromPublicKey(pubKeyBuff, 'mainnet'); + expect(p2trAddrFromPub).toBe(vector.address); + if (vector.privateKey) { + const privKeyBuff = Buffer.from(vector.privateKey, 'hex'); + const p2trAddrFromPriv = p2trAddressFromPrivateKey(privKeyBuff, 'mainnet'); + expect(p2trAddrFromPriv).toBe(vector.address); + } + } + + const randP2TRMainnet = generateRandomP2TRAccount('mainnet'); + expect(randP2TRMainnet.address).toMatch(/^bc1p/); + + const randP2TRTestnet = generateRandomP2TRAccount('testnet'); + expect(randP2TRTestnet.address).toMatch(/^tb1p/); +});