Compare commits
No commits in common. "master" and "feature/taproot" have entirely different histories.
master
...
feature/ta
16 changed files with 128 additions and 371 deletions
2
.github/workflows/main_ci.yml
vendored
2
.github/workflows/main_ci.yml
vendored
|
@ -41,7 +41,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
services:
|
services:
|
||||||
regtest:
|
regtest:
|
||||||
image: junderw/bitcoinjs-regtest-server@sha256:5b69cf95d9edf6d5b3a00504665d6b3c382a6aa3728fe8ce897974c519061463
|
image: junderw/bitcoinjs-regtest-server@sha256:a46ec1a651ca5b1a5408f2b2526ea5f435421dd2bc2f28fae3bc33e1fd614552
|
||||||
ports:
|
ports:
|
||||||
- 8080:8080
|
- 8080:8080
|
||||||
steps:
|
steps:
|
||||||
|
|
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -1,16 +1,3 @@
|
||||||
# 6.0.0
|
|
||||||
__removed__
|
|
||||||
- bip32: Removed the re-export. Please add as dependency to your app instead.
|
|
||||||
- ECPair: Please use bip32 moving forward. ecpair package was created for those who need it.
|
|
||||||
- TransactionBuilder: Any internal files used only in TB (classify, templates, etc.) were also removed.
|
|
||||||
|
|
||||||
__added__
|
|
||||||
- taproot segwit v1 address support (bech32m) via address module (#1676)
|
|
||||||
- hashForWitnessV1 method on Transaction class (#1745)
|
|
||||||
|
|
||||||
__fixed__
|
|
||||||
- Transaction version read/write differed. (#1717)
|
|
||||||
|
|
||||||
# 5.2.0
|
# 5.2.0
|
||||||
__changed__
|
__changed__
|
||||||
- Updated PSBT to allow for witnessUtxo and nonWitnessUtxo simultaneously (Re: segwit psbt bug) (#1563)
|
- Updated PSBT to allow for witnessUtxo and nonWitnessUtxo simultaneously (Re: segwit psbt bug) (#1563)
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
# BitcoinJS (bitcoinjs-lib)
|
# BitcoinJS (bitcoinjs-lib)
|
||||||
[![Github CI](https://github.com/bitcoinjs/bitcoinjs-lib/actions/workflows/main_ci.yml/badge.svg)](https://github.com/bitcoinjs/bitcoinjs-lib/actions/workflows/main_ci.yml) [![NPM](https://img.shields.io/npm/v/bitcoinjs-lib.svg)](https://www.npmjs.org/package/bitcoinjs-lib) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
|
[![Build Status](https://travis-ci.org/bitcoinjs/bitcoinjs-lib.png?branch=master)](https://travis-ci.org/bitcoinjs/bitcoinjs-lib)
|
||||||
|
[![NPM](https://img.shields.io/npm/v/bitcoinjs-lib.svg)](https://www.npmjs.org/package/bitcoinjs-lib)
|
||||||
|
|
||||||
|
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
|
||||||
|
|
||||||
A javascript Bitcoin library for node.js and browsers. Written in TypeScript, but committing the JS files to verify.
|
A javascript Bitcoin library for node.js and browsers. Written in TypeScript, but committing the JS files to verify.
|
||||||
|
|
||||||
|
@ -91,8 +94,6 @@ The below examples are implemented as integration tests, they should be very eas
|
||||||
Otherwise, pull requests are appreciated.
|
Otherwise, pull requests are appreciated.
|
||||||
Some examples interact (via HTTPS) with a 3rd Party Blockchain Provider (3PBP).
|
Some examples interact (via HTTPS) with a 3rd Party Blockchain Provider (3PBP).
|
||||||
|
|
||||||
- [Taproot Key Spend](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/taproot.md)
|
|
||||||
|
|
||||||
- [Generate a random address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts)
|
- [Generate a random address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts)
|
||||||
- [Import an address via WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts)
|
- [Import an address via WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts)
|
||||||
- [Generate a 2-of-3 P2SH multisig address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts)
|
- [Generate a 2-of-3 P2SH multisig address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts)
|
||||||
|
|
129
package-lock.json
generated
129
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "bitcoinjs-lib",
|
"name": "bitcoinjs-lib",
|
||||||
"version": "6.0.1",
|
"version": "5.2.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -541,21 +541,31 @@
|
||||||
"integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
|
"integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"bindings": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"file-uri-to-path": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"bip174": {
|
"bip174": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/bip174/-/bip174-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/bip174/-/bip174-2.0.1.tgz",
|
||||||
"integrity": "sha512-i3X26uKJOkDTAalYAp0Er+qGMDhrbbh2o93/xiPyAN2s25KrClSpe3VXo/7mNJoqA5qfko8rLS2l3RWZgYmjKQ=="
|
"integrity": "sha512-i3X26uKJOkDTAalYAp0Er+qGMDhrbbh2o93/xiPyAN2s25KrClSpe3VXo/7mNJoqA5qfko8rLS2l3RWZgYmjKQ=="
|
||||||
},
|
},
|
||||||
"bip32": {
|
"bip32": {
|
||||||
"version": "3.0.1",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/bip32/-/bip32-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz",
|
||||||
"integrity": "sha512-Uhpp9aEx3iyiO7CpbNGFxv9WcMIVdGoHG04doQ5Ln0u60uwDah7jUSc3QMV/fSZGm/Oo01/OeAmYevXV+Gz5jQ==",
|
"integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/node": "10.12.18",
|
"@types/node": "10.12.18",
|
||||||
"bs58check": "^2.1.1",
|
"bs58check": "^2.1.1",
|
||||||
"create-hash": "^1.2.0",
|
"create-hash": "^1.2.0",
|
||||||
"create-hmac": "^1.1.7",
|
"create-hmac": "^1.1.7",
|
||||||
|
"tiny-secp256k1": "^1.1.3",
|
||||||
"typeforce": "^1.11.5",
|
"typeforce": "^1.11.5",
|
||||||
"wif": "^2.0.6"
|
"wif": "^2.0.6"
|
||||||
},
|
},
|
||||||
|
@ -631,6 +641,12 @@
|
||||||
"fill-range": "^7.0.1"
|
"fill-range": "^7.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"brorand": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"browser-stdout": {
|
"browser-stdout": {
|
||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
|
||||||
|
@ -916,14 +932,44 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"ecpair": {
|
"ecpair": {
|
||||||
"version": "2.0.1",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/ecpair/-/ecpair-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/ecpair/-/ecpair-1.0.0.tgz",
|
||||||
"integrity": "sha512-iT3wztQMeE/nDTlfnAg8dAFUfBS7Tq2BXzq3ae6L+pWgFU0fQ3l0woTzdTBrJV3OxBjxbzjq8EQhAbEmJNWFSw==",
|
"integrity": "sha512-1L+P/ivLC3eKHgqcX1M9tFYQWXDoqwJ3zQnN7zDaTtLpiCQKpFTaAZvnsPC5PkWB4q3EPFAHffCLvjfCqRjuwQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"randombytes": "^2.1.0",
|
"randombytes": "^2.0.1",
|
||||||
"typeforce": "^1.18.0",
|
"tiny-secp256k1": "^1.1.6",
|
||||||
"wif": "^2.0.6"
|
"typeforce": "^1.11.3",
|
||||||
|
"wif": "^2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"elliptic": {
|
||||||
|
"version": "6.5.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
|
||||||
|
"integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"bn.js": "^4.11.9",
|
||||||
|
"brorand": "^1.1.0",
|
||||||
|
"hash.js": "^1.0.0",
|
||||||
|
"hmac-drbg": "^1.0.1",
|
||||||
|
"inherits": "^2.0.4",
|
||||||
|
"minimalistic-assert": "^1.0.1",
|
||||||
|
"minimalistic-crypto-utils": "^1.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"bn.js": {
|
||||||
|
"version": "4.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
|
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"emoji-regex": {
|
"emoji-regex": {
|
||||||
|
@ -980,6 +1026,12 @@
|
||||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"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==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"fill-keys": {
|
"fill-keys": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz",
|
||||||
|
@ -1152,6 +1204,16 @@
|
||||||
"safe-buffer": "^5.0.1"
|
"safe-buffer": "^5.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"hash.js": {
|
||||||
|
"version": "1.1.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
|
||||||
|
"integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"minimalistic-assert": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"hasha": {
|
"hasha": {
|
||||||
"version": "5.2.2",
|
"version": "5.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz",
|
||||||
|
@ -1168,6 +1230,17 @@
|
||||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"hmac-drbg": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"hash.js": "^1.0.3",
|
||||||
|
"minimalistic-assert": "^1.0.0",
|
||||||
|
"minimalistic-crypto-utils": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"hoodwink": {
|
"hoodwink": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/hoodwink/-/hoodwink-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/hoodwink/-/hoodwink-2.0.0.tgz",
|
||||||
|
@ -1553,6 +1626,18 @@
|
||||||
"pushdata-bitcoin": "^1.0.1"
|
"pushdata-bitcoin": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"minimalistic-assert": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"minimalistic-crypto-utils": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"minimatch": {
|
"minimatch": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||||
|
@ -1621,6 +1706,12 @@
|
||||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
|
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"nan": {
|
||||||
|
"version": "2.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
|
||||||
|
"integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node-environment-flags": {
|
"node-environment-flags": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz",
|
||||||
|
@ -2374,12 +2465,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tiny-secp256k1": {
|
"tiny-secp256k1": {
|
||||||
"version": "2.1.2",
|
"version": "1.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz",
|
||||||
"integrity": "sha512-8qPw7zDK6Hco2tVGYGQeOmOPp/hZnREwy2iIkcq0ygAuqc9WHo29vKN94lNymh1QbB3nthtAMF6KTIrdbsIotA==",
|
"integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"uint8array-tools": "0.0.6"
|
"bindings": "^1.3.0",
|
||||||
|
"bn.js": "^4.11.8",
|
||||||
|
"create-hmac": "^1.1.7",
|
||||||
|
"elliptic": "^6.4.0",
|
||||||
|
"nan": "^2.13.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"to-fast-properties": {
|
"to-fast-properties": {
|
||||||
|
@ -2488,12 +2583,6 @@
|
||||||
"integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==",
|
"integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"uint8array-tools": {
|
|
||||||
"version": "0.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.6.tgz",
|
|
||||||
"integrity": "sha512-aIvEHNRX1AlOYAr6qSUjQBn4mCduxx6MtC967aRDTb2UUBPj0Ix2ZFQDcmXUUO/UxRPHcw1f5a5nVbCSKDSOqA==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"uuid": {
|
"uuid": {
|
||||||
"version": "3.4.0",
|
"version": "3.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "bitcoinjs-lib",
|
"name": "bitcoinjs-lib",
|
||||||
"version": "6.0.1",
|
"version": "5.2.0",
|
||||||
"description": "Client-side Bitcoin JavaScript library",
|
"description": "Client-side Bitcoin JavaScript library",
|
||||||
"main": "./src/index.js",
|
"main": "./src/index.js",
|
||||||
"types": "./src/index.d.ts",
|
"types": "./src/index.d.ts",
|
||||||
|
@ -66,14 +66,14 @@
|
||||||
"@types/proxyquire": "^1.3.28",
|
"@types/proxyquire": "^1.3.28",
|
||||||
"@types/randombytes": "^2.0.0",
|
"@types/randombytes": "^2.0.0",
|
||||||
"@types/wif": "^2.0.2",
|
"@types/wif": "^2.0.2",
|
||||||
"bip32": "^3.0.1",
|
"bip32": "^2.0.6",
|
||||||
"bip39": "^3.0.2",
|
"bip39": "^3.0.2",
|
||||||
"bip65": "^1.0.1",
|
"bip65": "^1.0.1",
|
||||||
"bip68": "^1.0.3",
|
"bip68": "^1.0.3",
|
||||||
"bn.js": "^4.11.8",
|
"bn.js": "^4.11.8",
|
||||||
"bs58": "^4.0.0",
|
"bs58": "^4.0.0",
|
||||||
"dhttp": "^3.0.0",
|
"dhttp": "^3.0.0",
|
||||||
"ecpair": "^2.0.1",
|
"ecpair": "^1.0.0",
|
||||||
"hoodwink": "^2.0.0",
|
"hoodwink": "^2.0.0",
|
||||||
"minimaldata": "^1.0.2",
|
"minimaldata": "^1.0.2",
|
||||||
"mocha": "^7.1.1",
|
"mocha": "^7.1.1",
|
||||||
|
@ -84,7 +84,6 @@
|
||||||
"randombytes": "^2.1.0",
|
"randombytes": "^2.1.0",
|
||||||
"regtest-client": "0.2.0",
|
"regtest-client": "0.2.0",
|
||||||
"rimraf": "^2.6.3",
|
"rimraf": "^2.6.3",
|
||||||
"tiny-secp256k1": "^2.1.2",
|
|
||||||
"ts-node": "^8.3.0",
|
"ts-node": "^8.3.0",
|
||||||
"tslint": "^6.1.3",
|
"tslint": "^6.1.3",
|
||||||
"typescript": "^4.4.4"
|
"typescript": "^4.4.4"
|
||||||
|
|
|
@ -13,11 +13,6 @@ const FUTURE_SEGWIT_MIN_SIZE = 2;
|
||||||
const FUTURE_SEGWIT_MAX_VERSION = 16;
|
const FUTURE_SEGWIT_MAX_VERSION = 16;
|
||||||
const FUTURE_SEGWIT_MIN_VERSION = 1;
|
const FUTURE_SEGWIT_MIN_VERSION = 1;
|
||||||
const FUTURE_SEGWIT_VERSION_DIFF = 0x50;
|
const FUTURE_SEGWIT_VERSION_DIFF = 0x50;
|
||||||
const FUTURE_SEGWIT_VERSION_WARNING =
|
|
||||||
'WARNING: Sending to a future segwit version address can lead to loss of funds. ' +
|
|
||||||
'End users MUST be warned carefully in the GUI and asked if they wish to proceed ' +
|
|
||||||
'with caution. Wallets should verify the segwit version from the output of fromBech32, ' +
|
|
||||||
'then decide when it is safe to use which version of segwit.';
|
|
||||||
function _toFutureSegwitAddress(output, network) {
|
function _toFutureSegwitAddress(output, network) {
|
||||||
const data = output.slice(2);
|
const data = output.slice(2);
|
||||||
if (
|
if (
|
||||||
|
@ -33,7 +28,6 @@ function _toFutureSegwitAddress(output, network) {
|
||||||
throw new TypeError('Invalid version for segwit address');
|
throw new TypeError('Invalid version for segwit address');
|
||||||
if (output[1] !== data.length)
|
if (output[1] !== data.length)
|
||||||
throw new TypeError('Invalid script for segwit address');
|
throw new TypeError('Invalid script for segwit address');
|
||||||
console.warn(FUTURE_SEGWIT_VERSION_WARNING);
|
|
||||||
return toBech32(data, version, network.bech32);
|
return toBech32(data, version, network.bech32);
|
||||||
}
|
}
|
||||||
function fromBase58Check(address) {
|
function fromBase58Check(address) {
|
||||||
|
@ -134,15 +128,13 @@ function toOutputScript(address, network) {
|
||||||
decodeBech32.version <= FUTURE_SEGWIT_MAX_VERSION &&
|
decodeBech32.version <= FUTURE_SEGWIT_MAX_VERSION &&
|
||||||
decodeBech32.data.length >= FUTURE_SEGWIT_MIN_SIZE &&
|
decodeBech32.data.length >= FUTURE_SEGWIT_MIN_SIZE &&
|
||||||
decodeBech32.data.length <= FUTURE_SEGWIT_MAX_SIZE
|
decodeBech32.data.length <= FUTURE_SEGWIT_MAX_SIZE
|
||||||
) {
|
)
|
||||||
console.warn(FUTURE_SEGWIT_VERSION_WARNING);
|
|
||||||
return bscript.compile([
|
return bscript.compile([
|
||||||
decodeBech32.version + FUTURE_SEGWIT_VERSION_DIFF,
|
decodeBech32.version + FUTURE_SEGWIT_VERSION_DIFF,
|
||||||
decodeBech32.data,
|
decodeBech32.data,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
throw new Error(address + ' has no matching Script');
|
throw new Error(address + ' has no matching Script');
|
||||||
}
|
}
|
||||||
exports.toOutputScript = toOutputScript;
|
exports.toOutputScript = toOutputScript;
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import ECPairFactory from 'ecpair';
|
import { ECPair } from 'ecpair';
|
||||||
import * as ecc from 'tiny-secp256k1';
|
|
||||||
import { describe, it } from 'mocha';
|
import { describe, it } from 'mocha';
|
||||||
import * as bitcoin from '../..';
|
import * as bitcoin from '../..';
|
||||||
import { regtestUtils } from './_regtest';
|
import { regtestUtils } from './_regtest';
|
||||||
|
|
||||||
const ECPair = ECPairFactory(ecc);
|
|
||||||
const dhttp = regtestUtils.dhttp;
|
const dhttp = regtestUtils.dhttp;
|
||||||
const TESTNET = bitcoin.networks.testnet;
|
const TESTNET = bitcoin.networks.testnet;
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import BIP32Factory from 'bip32';
|
import * as bip32 from 'bip32';
|
||||||
import * as ecc from 'tiny-secp256k1';
|
|
||||||
import * as bip39 from 'bip39';
|
import * as bip39 from 'bip39';
|
||||||
import { describe, it } from 'mocha';
|
import { describe, it } from 'mocha';
|
||||||
import * as bitcoin from '../..';
|
import * as bitcoin from '../..';
|
||||||
|
|
||||||
const bip32 = BIP32Factory(ecc);
|
|
||||||
|
|
||||||
function getAddress(node: any, network?: any): string {
|
function getAddress(node: any, network?: any): string {
|
||||||
return bitcoin.payments.p2pkh({ pubkey: node.publicKey, network }).address!;
|
return bitcoin.payments.p2pkh({ pubkey: node.publicKey, network }).address!;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import ECPairFactory from 'ecpair';
|
import { ECPair } from 'ecpair';
|
||||||
import * as ecc from 'tiny-secp256k1';
|
|
||||||
import { before, describe, it } from 'mocha';
|
import { before, describe, it } from 'mocha';
|
||||||
import * as bitcoin from '../..';
|
import * as bitcoin from '../..';
|
||||||
import { regtestUtils } from './_regtest';
|
import { regtestUtils } from './_regtest';
|
||||||
|
|
||||||
const ECPair = ECPairFactory(ecc);
|
|
||||||
const regtest = regtestUtils.network;
|
const regtest = regtestUtils.network;
|
||||||
const bip65 = require('bip65');
|
const bip65 = require('bip65');
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import { PsbtInput } from 'bip174/src/lib/interfaces';
|
import { PsbtInput } from 'bip174/src/lib/interfaces';
|
||||||
import ECPairFactory from 'ecpair';
|
import { ECPair } from 'ecpair';
|
||||||
import * as ecc from 'tiny-secp256k1';
|
|
||||||
import { before, describe, it } from 'mocha';
|
import { before, describe, it } from 'mocha';
|
||||||
import * as bitcoin from '../..';
|
import * as bitcoin from '../..';
|
||||||
import { regtestUtils } from './_regtest';
|
import { regtestUtils } from './_regtest';
|
||||||
|
|
||||||
const ECPair = ECPairFactory(ecc);
|
|
||||||
const regtest = regtestUtils.network;
|
const regtest = regtestUtils.network;
|
||||||
const bip68 = require('bip68');
|
const bip68 = require('bip68');
|
||||||
const varuint = require('varuint-bitcoin');
|
const varuint = require('varuint-bitcoin');
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import ECPairFactory from 'ecpair';
|
import { ECPair } from 'ecpair';
|
||||||
import * as ecc from 'tiny-secp256k1';
|
|
||||||
import { describe, it } from 'mocha';
|
import { describe, it } from 'mocha';
|
||||||
import * as bitcoin from '../..';
|
import * as bitcoin from '../..';
|
||||||
import { regtestUtils } from './_regtest';
|
import { regtestUtils } from './_regtest';
|
||||||
|
|
||||||
const ECPair = ECPairFactory(ecc);
|
|
||||||
const NETWORK = regtestUtils.network;
|
const NETWORK = regtestUtils.network;
|
||||||
const keyPairs = [
|
const keyPairs = [
|
||||||
ECPair.makeRandom({ network: NETWORK }),
|
ECPair.makeRandom({ network: NETWORK }),
|
||||||
|
|
|
@ -1,156 +0,0 @@
|
||||||
# Taproot
|
|
||||||
|
|
||||||
A simple keyspend example that is possible with the current API is below.
|
|
||||||
|
|
||||||
## Current state of taproot support
|
|
||||||
|
|
||||||
- [x] segwit v1 address support via bech32m
|
|
||||||
- [x] segwit v1 sighash calculation on Transaction class
|
|
||||||
|
|
||||||
## TODO
|
|
||||||
|
|
||||||
- [ ] p2tr payment API to make script spends easier
|
|
||||||
- [ ] Support within the Psbt class
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
### Requirements
|
|
||||||
- npm dependencies
|
|
||||||
- bitcoinjs-lib v6.x.x
|
|
||||||
- bip32 v3.x.x
|
|
||||||
- tiny-secp256k1 v2.x.x
|
|
||||||
- regtest-client vx.x.x
|
|
||||||
- local regtest-server docker container running
|
|
||||||
- `docker run -d -p 8080:8080 junderw/bitcoinjs-regtest-server`
|
|
||||||
- node >= v14
|
|
||||||
|
|
||||||
```js
|
|
||||||
// Run this whole file as async
|
|
||||||
// Catch any errors at the bottom of the file
|
|
||||||
// and exit the process with 1 error code
|
|
||||||
(async () => {
|
|
||||||
|
|
||||||
// Order of the curve (N) - 1
|
|
||||||
const N_LESS_1 = Buffer.from(
|
|
||||||
'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140',
|
|
||||||
'hex'
|
|
||||||
);
|
|
||||||
// 1 represented as 32 bytes BE
|
|
||||||
const ONE = Buffer.from(
|
|
||||||
'0000000000000000000000000000000000000000000000000000000000000001',
|
|
||||||
'hex'
|
|
||||||
);
|
|
||||||
|
|
||||||
const crypto = require('crypto');
|
|
||||||
// bitcoinjs-lib v6
|
|
||||||
const bitcoin = require('bitcoinjs-lib');
|
|
||||||
// bip32 v3 wraps tiny-secp256k1
|
|
||||||
const BIP32Wrapper = require('bip32').default;
|
|
||||||
const RegtestUtils = require('regtest-client').RegtestUtils;
|
|
||||||
// tiny-secp256k1 v2 is an ESM module, so we can't "require", and must import async
|
|
||||||
const ecc = await import('tiny-secp256k1');
|
|
||||||
// wrap the bip32 library
|
|
||||||
const bip32 = BIP32Wrapper(ecc);
|
|
||||||
// set up dependencies
|
|
||||||
const APIPASS = process.env.APIPASS || 'satoshi';
|
|
||||||
// docker run -d -p 8080:8080 junderw/bitcoinjs-regtest-server
|
|
||||||
const APIURL = process.env.APIURL || 'http://127.0.0.1:8080/1';
|
|
||||||
const regtestUtils = new RegtestUtils({ APIPASS, APIURL });
|
|
||||||
// End imports
|
|
||||||
|
|
||||||
const myKey = bip32.fromSeed(crypto.randomBytes(64), regtestUtils.network);
|
|
||||||
|
|
||||||
const output = createKeySpendOutput(myKey.publicKey);
|
|
||||||
const address = bitcoin.address.fromOutputScript(
|
|
||||||
output,
|
|
||||||
regtestUtils.network
|
|
||||||
);
|
|
||||||
// amount from faucet
|
|
||||||
const amount = 42e4;
|
|
||||||
// amount to send
|
|
||||||
const sendAmount = amount - 1e4;
|
|
||||||
// get faucet
|
|
||||||
const unspent = await regtestUtils.faucetComplex(output, amount);
|
|
||||||
|
|
||||||
const tx = createSigned(
|
|
||||||
myKey,
|
|
||||||
unspent.txId,
|
|
||||||
unspent.vout,
|
|
||||||
sendAmount,
|
|
||||||
[output],
|
|
||||||
[amount]
|
|
||||||
);
|
|
||||||
|
|
||||||
const hex = tx.toHex();
|
|
||||||
console.log('Valid tx sent from:');
|
|
||||||
console.log(address);
|
|
||||||
console.log('tx hex:');
|
|
||||||
console.log(hex);
|
|
||||||
await regtestUtils.broadcast(hex);
|
|
||||||
await regtestUtils.verify({
|
|
||||||
txId: tx.getId(),
|
|
||||||
address,
|
|
||||||
vout: 0,
|
|
||||||
value: sendAmount,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Function for creating a tweaked p2tr key-spend only address
|
|
||||||
// (This is recommended by BIP341)
|
|
||||||
function createKeySpendOutput(publicKey) {
|
|
||||||
// x-only pubkey (remove 1 byte y parity)
|
|
||||||
const myXOnlyPubkey = publicKey.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;
|
|
||||||
// scriptPubkey
|
|
||||||
return Buffer.concat([
|
|
||||||
// witness v1, PUSH_DATA 32 bytes
|
|
||||||
Buffer.from([0x51, 0x20]),
|
|
||||||
// x-only tweaked pubkey
|
|
||||||
tweaked,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function for signing for a tweaked p2tr key-spend only address
|
|
||||||
// (Required for the above address)
|
|
||||||
function signTweaked(messageHash, key) {
|
|
||||||
const privateKey =
|
|
||||||
key.publicKey[0] === 2
|
|
||||||
? key.privateKey
|
|
||||||
: ecc.privateAdd(ecc.privateSub(N_LESS_1, key.privateKey), ONE);
|
|
||||||
const tweakHash = bitcoin.crypto.taggedHash(
|
|
||||||
'TapTweak',
|
|
||||||
key.publicKey.slice(1, 33)
|
|
||||||
);
|
|
||||||
const newPrivateKey = ecc.privateAdd(privateKey, tweakHash);
|
|
||||||
if (newPrivateKey === null) throw new Error('Invalid Tweak');
|
|
||||||
return ecc.signSchnorr(messageHash, newPrivateKey, Buffer.alloc(32));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function for creating signed tx
|
|
||||||
function createSigned(key, txid, vout, amountToSend, scriptPubkeys, values) {
|
|
||||||
const tx = new bitcoin.Transaction();
|
|
||||||
tx.version = 2;
|
|
||||||
// Add input
|
|
||||||
tx.addInput(Buffer.from(txid, 'hex').reverse(), vout);
|
|
||||||
// Add output
|
|
||||||
tx.addOutput(scriptPubkeys[0], amountToSend);
|
|
||||||
const sighash = tx.hashForWitnessV1(
|
|
||||||
0, // which input
|
|
||||||
scriptPubkeys, // All previous outputs of all inputs
|
|
||||||
values, // All previous values of all inputs
|
|
||||||
bitcoin.Transaction.SIGHASH_DEFAULT // sighash flag, DEFAULT is schnorr-only (DEFAULT == ALL)
|
|
||||||
);
|
|
||||||
const signature = Buffer.from(signTweaked(sighash, key));
|
|
||||||
// witness stack for keypath spend is just the signature.
|
|
||||||
// If sighash is not SIGHASH_DEFAULT (ALL) then you must add 1 byte with sighash value
|
|
||||||
tx.ins[0].witness = [signature];
|
|
||||||
return tx;
|
|
||||||
}
|
|
||||||
|
|
||||||
})().catch((err) => {
|
|
||||||
console.error(err);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
```
|
|
|
@ -1,122 +0,0 @@
|
||||||
import BIP32Factory from 'bip32';
|
|
||||||
import * as ecc from 'tiny-secp256k1';
|
|
||||||
import { describe, it } from 'mocha';
|
|
||||||
import * as bitcoin from '../..';
|
|
||||||
import { regtestUtils } from './_regtest';
|
|
||||||
const rng = require('randombytes');
|
|
||||||
const regtest = regtestUtils.network;
|
|
||||||
const bip32 = BIP32Factory(ecc);
|
|
||||||
|
|
||||||
describe('bitcoinjs-lib (transaction with taproot)', () => {
|
|
||||||
it('can create (and broadcast via 3PBP) a taproot keyspend Transaction', async () => {
|
|
||||||
const myKey = bip32.fromSeed(rng(64), regtest);
|
|
||||||
|
|
||||||
const output = createKeySpendOutput(myKey.publicKey);
|
|
||||||
const address = bitcoin.address.fromOutputScript(output, regtest);
|
|
||||||
// amount from faucet
|
|
||||||
const amount = 42e4;
|
|
||||||
// amount to send
|
|
||||||
const sendAmount = amount - 1e4;
|
|
||||||
// get faucet
|
|
||||||
const unspent = await regtestUtils.faucetComplex(output, amount);
|
|
||||||
|
|
||||||
const tx = createSigned(
|
|
||||||
myKey,
|
|
||||||
unspent.txId,
|
|
||||||
unspent.vout,
|
|
||||||
sendAmount,
|
|
||||||
[output],
|
|
||||||
[amount],
|
|
||||||
);
|
|
||||||
|
|
||||||
const hex = tx.toHex();
|
|
||||||
// console.log('Valid tx sent from:');
|
|
||||||
// console.log(address);
|
|
||||||
// console.log('tx hex:');
|
|
||||||
// console.log(hex);
|
|
||||||
await regtestUtils.broadcast(hex);
|
|
||||||
await regtestUtils.verify({
|
|
||||||
txId: tx.getId(),
|
|
||||||
address,
|
|
||||||
vout: 0,
|
|
||||||
value: sendAmount,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Order of the curve (N) - 1
|
|
||||||
const N_LESS_1 = Buffer.from(
|
|
||||||
'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140',
|
|
||||||
'hex',
|
|
||||||
);
|
|
||||||
// 1 represented as 32 bytes BE
|
|
||||||
const ONE = Buffer.from(
|
|
||||||
'0000000000000000000000000000000000000000000000000000000000000001',
|
|
||||||
'hex',
|
|
||||||
);
|
|
||||||
|
|
||||||
// Function for creating a tweaked p2tr key-spend only address
|
|
||||||
// (This is recommended by BIP341)
|
|
||||||
function createKeySpendOutput(publicKey: Buffer): Buffer {
|
|
||||||
// x-only pubkey (remove 1 byte y parity)
|
|
||||||
const myXOnlyPubkey = publicKey.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;
|
|
||||||
// scriptPubkey
|
|
||||||
return Buffer.concat([
|
|
||||||
// witness v1, PUSH_DATA 32 bytes
|
|
||||||
Buffer.from([0x51, 0x20]),
|
|
||||||
// x-only tweaked pubkey
|
|
||||||
tweaked,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function for signing for a tweaked p2tr key-spend only address
|
|
||||||
// (Required for the above address)
|
|
||||||
interface KeyPair {
|
|
||||||
publicKey: Buffer;
|
|
||||||
privateKey?: Buffer;
|
|
||||||
}
|
|
||||||
function signTweaked(messageHash: Buffer, key: KeyPair): Uint8Array {
|
|
||||||
const privateKey =
|
|
||||||
key.publicKey[0] === 2
|
|
||||||
? key.privateKey
|
|
||||||
: ecc.privateAdd(ecc.privateSub(N_LESS_1, key.privateKey!)!, ONE)!;
|
|
||||||
const tweakHash = bitcoin.crypto.taggedHash(
|
|
||||||
'TapTweak',
|
|
||||||
key.publicKey.slice(1, 33),
|
|
||||||
);
|
|
||||||
const newPrivateKey = ecc.privateAdd(privateKey!, tweakHash);
|
|
||||||
if (newPrivateKey === null) throw new Error('Invalid Tweak');
|
|
||||||
return ecc.signSchnorr(messageHash, newPrivateKey, Buffer.alloc(32));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function for creating signed tx
|
|
||||||
function createSigned(
|
|
||||||
key: KeyPair,
|
|
||||||
txid: string,
|
|
||||||
vout: number,
|
|
||||||
amountToSend: number,
|
|
||||||
scriptPubkeys: Buffer[],
|
|
||||||
values: number[],
|
|
||||||
): bitcoin.Transaction {
|
|
||||||
const tx = new bitcoin.Transaction();
|
|
||||||
tx.version = 2;
|
|
||||||
// Add input
|
|
||||||
tx.addInput(Buffer.from(txid, 'hex').reverse(), vout);
|
|
||||||
// Add output
|
|
||||||
tx.addOutput(scriptPubkeys[0], amountToSend);
|
|
||||||
const sighash = tx.hashForWitnessV1(
|
|
||||||
0, // which input
|
|
||||||
scriptPubkeys, // All previous outputs of all inputs
|
|
||||||
values, // All previous values of all inputs
|
|
||||||
bitcoin.Transaction.SIGHASH_DEFAULT, // sighash flag, DEFAULT is schnorr-only (DEFAULT == ALL)
|
|
||||||
);
|
|
||||||
const signature = Buffer.from(signTweaked(sighash, key));
|
|
||||||
// witness stack for keypath spend is just the signature.
|
|
||||||
// If sighash is not SIGHASH_DEFAULT (ALL) then you must add 1 byte with sighash value
|
|
||||||
tx.ins[0].witness = [signature];
|
|
||||||
return tx;
|
|
||||||
}
|
|
|
@ -1,15 +1,11 @@
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import BIP32Factory from 'bip32';
|
import * as bip32 from 'bip32';
|
||||||
import * as ecc from 'tiny-secp256k1';
|
import { ECPair } from 'ecpair';
|
||||||
import ECPairFactory from 'ecpair';
|
|
||||||
import { describe, it } from 'mocha';
|
import { describe, it } from 'mocha';
|
||||||
import * as bitcoin from '../..';
|
import * as bitcoin from '../..';
|
||||||
import { regtestUtils } from './_regtest';
|
import { regtestUtils } from './_regtest';
|
||||||
|
|
||||||
const ECPair = ECPairFactory(ecc);
|
|
||||||
const rng = require('randombytes');
|
const rng = require('randombytes');
|
||||||
const regtest = regtestUtils.network;
|
const regtest = regtestUtils.network;
|
||||||
const bip32 = BIP32Factory(ecc);
|
|
||||||
|
|
||||||
const validator = (
|
const validator = (
|
||||||
pubkey: Buffer,
|
pubkey: Buffer,
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import BIP32Factory from 'bip32';
|
import * as bip32 from 'bip32';
|
||||||
import * as ecc from 'tiny-secp256k1';
|
|
||||||
import * as crypto from 'crypto';
|
import * as crypto from 'crypto';
|
||||||
import ECPairFactory from 'ecpair';
|
import { ECPair } from 'ecpair';
|
||||||
import { describe, it } from 'mocha';
|
import { describe, it } from 'mocha';
|
||||||
|
|
||||||
const bip32 = BIP32Factory(ecc);
|
|
||||||
const ECPair = ECPairFactory(ecc);
|
|
||||||
|
|
||||||
import { networks as NETWORKS, payments, Psbt, Signer, SignerAsync } from '..';
|
import { networks as NETWORKS, payments, Psbt, Signer, SignerAsync } from '..';
|
||||||
|
|
||||||
import * as preFixtures from './fixtures/psbt.json';
|
import * as preFixtures from './fixtures/psbt.json';
|
||||||
|
|
|
@ -23,11 +23,6 @@ const FUTURE_SEGWIT_MIN_SIZE: number = 2;
|
||||||
const FUTURE_SEGWIT_MAX_VERSION: number = 16;
|
const FUTURE_SEGWIT_MAX_VERSION: number = 16;
|
||||||
const FUTURE_SEGWIT_MIN_VERSION: number = 1;
|
const FUTURE_SEGWIT_MIN_VERSION: number = 1;
|
||||||
const FUTURE_SEGWIT_VERSION_DIFF: number = 0x50;
|
const FUTURE_SEGWIT_VERSION_DIFF: number = 0x50;
|
||||||
const FUTURE_SEGWIT_VERSION_WARNING: string =
|
|
||||||
'WARNING: Sending to a future segwit version address can lead to loss of funds. ' +
|
|
||||||
'End users MUST be warned carefully in the GUI and asked if they wish to proceed ' +
|
|
||||||
'with caution. Wallets should verify the segwit version from the output of fromBech32, ' +
|
|
||||||
'then decide when it is safe to use which version of segwit.';
|
|
||||||
|
|
||||||
function _toFutureSegwitAddress(output: Buffer, network: Network): string {
|
function _toFutureSegwitAddress(output: Buffer, network: Network): string {
|
||||||
const data = output.slice(2);
|
const data = output.slice(2);
|
||||||
|
@ -49,8 +44,6 @@ function _toFutureSegwitAddress(output: Buffer, network: Network): string {
|
||||||
if (output[1] !== data.length)
|
if (output[1] !== data.length)
|
||||||
throw new TypeError('Invalid script for segwit address');
|
throw new TypeError('Invalid script for segwit address');
|
||||||
|
|
||||||
console.warn(FUTURE_SEGWIT_VERSION_WARNING);
|
|
||||||
|
|
||||||
return toBech32(data, version, network.bech32);
|
return toBech32(data, version, network.bech32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,16 +163,13 @@ export function toOutputScript(address: string, network?: Network): Buffer {
|
||||||
decodeBech32.version <= FUTURE_SEGWIT_MAX_VERSION &&
|
decodeBech32.version <= FUTURE_SEGWIT_MAX_VERSION &&
|
||||||
decodeBech32.data.length >= FUTURE_SEGWIT_MIN_SIZE &&
|
decodeBech32.data.length >= FUTURE_SEGWIT_MIN_SIZE &&
|
||||||
decodeBech32.data.length <= FUTURE_SEGWIT_MAX_SIZE
|
decodeBech32.data.length <= FUTURE_SEGWIT_MAX_SIZE
|
||||||
) {
|
)
|
||||||
console.warn(FUTURE_SEGWIT_VERSION_WARNING);
|
|
||||||
|
|
||||||
return bscript.compile([
|
return bscript.compile([
|
||||||
decodeBech32.version + FUTURE_SEGWIT_VERSION_DIFF,
|
decodeBech32.version + FUTURE_SEGWIT_VERSION_DIFF,
|
||||||
decodeBech32.data,
|
decodeBech32.data,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(address + ' has no matching Script');
|
throw new Error(address + ' has no matching Script');
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue