@btc-vision/bitcoin 7.0.0-alpha.1 → 7.0.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +334 -161
- package/browser/address.d.ts +5 -1
- package/browser/address.d.ts.map +1 -1
- package/browser/branded.d.ts +3 -14
- package/browser/branded.d.ts.map +1 -1
- package/browser/ecc/context.d.ts +22 -21
- package/browser/ecc/context.d.ts.map +1 -1
- package/browser/ecc/index.d.ts +1 -1
- package/browser/ecc/index.d.ts.map +1 -1
- package/browser/ecc/types.d.ts +10 -123
- package/browser/ecc/types.d.ts.map +1 -1
- package/browser/index.d.ts +3 -2
- package/browser/index.d.ts.map +1 -1
- package/browser/index.js +6465 -4692
- package/browser/opcodes.d.ts +11 -0
- package/browser/opcodes.d.ts.map +1 -1
- package/browser/payments/p2tr.d.ts.map +1 -1
- package/browser/psbt/PsbtCache.d.ts +54 -0
- package/browser/psbt/PsbtCache.d.ts.map +1 -0
- package/browser/psbt/PsbtFinalizer.d.ts +21 -0
- package/browser/psbt/PsbtFinalizer.d.ts.map +1 -0
- package/browser/psbt/PsbtSigner.d.ts +32 -0
- package/browser/psbt/PsbtSigner.d.ts.map +1 -0
- package/browser/psbt/PsbtTransaction.d.ts +25 -0
- package/browser/psbt/PsbtTransaction.d.ts.map +1 -0
- package/browser/psbt/types.d.ts +4 -70
- package/browser/psbt/types.d.ts.map +1 -1
- package/browser/psbt/validation.d.ts +1 -1
- package/browser/psbt/validation.d.ts.map +1 -1
- package/browser/psbt.d.ts +26 -40
- package/browser/psbt.d.ts.map +1 -1
- package/browser/script.d.ts.map +1 -1
- package/browser/transaction.d.ts +4 -4
- package/browser/transaction.d.ts.map +1 -1
- package/browser/types.d.ts +5 -3
- package/browser/types.d.ts.map +1 -1
- package/browser/workers/index.d.ts +3 -50
- package/browser/workers/index.d.ts.map +1 -1
- package/browser/workers/index.node.d.ts +24 -0
- package/browser/workers/index.node.d.ts.map +1 -0
- package/build/address.d.ts +5 -1
- package/build/address.d.ts.map +1 -1
- package/build/address.js +29 -17
- package/build/address.js.map +1 -1
- package/build/branded.d.ts +3 -14
- package/build/branded.d.ts.map +1 -1
- package/build/branded.js +0 -5
- package/build/branded.js.map +1 -1
- package/build/ecc/context.d.ts +22 -21
- package/build/ecc/context.d.ts.map +1 -1
- package/build/ecc/context.js +23 -95
- package/build/ecc/context.js.map +1 -1
- package/build/ecc/index.d.ts +1 -1
- package/build/ecc/index.d.ts.map +1 -1
- package/build/ecc/types.d.ts +7 -126
- package/build/ecc/types.d.ts.map +1 -1
- package/build/ecc/types.js +4 -1
- package/build/ecc/types.js.map +1 -1
- package/build/index.d.ts +3 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/build/opcodes.d.ts +11 -0
- package/build/opcodes.d.ts.map +1 -1
- package/build/opcodes.js +19 -4
- package/build/opcodes.js.map +1 -1
- package/build/payments/p2tr.d.ts.map +1 -1
- package/build/payments/p2tr.js +2 -3
- package/build/payments/p2tr.js.map +1 -1
- package/build/psbt/PsbtCache.d.ts +54 -0
- package/build/psbt/PsbtCache.d.ts.map +1 -0
- package/build/psbt/PsbtCache.js +249 -0
- package/build/psbt/PsbtCache.js.map +1 -0
- package/build/psbt/PsbtFinalizer.d.ts +21 -0
- package/build/psbt/PsbtFinalizer.d.ts.map +1 -0
- package/build/psbt/PsbtFinalizer.js +157 -0
- package/build/psbt/PsbtFinalizer.js.map +1 -0
- package/build/psbt/PsbtSigner.d.ts +32 -0
- package/build/psbt/PsbtSigner.d.ts.map +1 -0
- package/build/psbt/PsbtSigner.js +192 -0
- package/build/psbt/PsbtSigner.js.map +1 -0
- package/build/psbt/PsbtTransaction.d.ts +25 -0
- package/build/psbt/PsbtTransaction.d.ts.map +1 -0
- package/build/psbt/PsbtTransaction.js +61 -0
- package/build/psbt/PsbtTransaction.js.map +1 -0
- package/build/psbt/types.d.ts +4 -70
- package/build/psbt/types.d.ts.map +1 -1
- package/build/psbt/validation.d.ts +1 -1
- package/build/psbt/validation.d.ts.map +1 -1
- package/build/psbt.d.ts +26 -40
- package/build/psbt.d.ts.map +1 -1
- package/build/psbt.js +177 -799
- package/build/psbt.js.map +1 -1
- package/build/script.d.ts.map +1 -1
- package/build/script.js +2 -2
- package/build/script.js.map +1 -1
- package/build/transaction.d.ts +4 -4
- package/build/transaction.d.ts.map +1 -1
- package/build/transaction.js +5 -4
- package/build/transaction.js.map +1 -1
- package/build/tsconfig.build.tsbuildinfo +1 -1
- package/build/types.d.ts +5 -3
- package/build/types.d.ts.map +1 -1
- package/build/types.js +9 -0
- package/build/types.js.map +1 -1
- package/build/workers/WorkerSigningPool.js +1 -1
- package/build/workers/WorkerSigningPool.js.map +1 -1
- package/build/workers/index.d.ts +3 -3
- package/build/workers/index.d.ts.map +1 -1
- package/build/workers/index.js +0 -3
- package/build/workers/index.js.map +1 -1
- package/build/workers/index.node.d.ts +24 -0
- package/build/workers/index.node.d.ts.map +1 -0
- package/build/workers/index.node.js +26 -0
- package/build/workers/index.node.js.map +1 -0
- package/package.json +27 -8
- package/src/address.ts +41 -18
- package/src/branded.ts +15 -13
- package/src/ecc/context.ts +30 -133
- package/src/ecc/index.ts +2 -2
- package/src/ecc/types.ts +7 -138
- package/src/index.ts +36 -2
- package/src/opcodes.ts +21 -4
- package/src/payments/p2tr.ts +2 -2
- package/src/psbt/PsbtCache.ts +325 -0
- package/src/psbt/PsbtFinalizer.ts +213 -0
- package/src/psbt/PsbtSigner.ts +302 -0
- package/src/psbt/PsbtTransaction.ts +82 -0
- package/src/psbt/types.ts +4 -86
- package/src/psbt/validation.ts +1 -1
- package/src/psbt.ts +348 -1197
- package/src/script.ts +2 -2
- package/src/transaction.ts +9 -8
- package/src/types.ts +14 -1
- package/src/workers/WorkerSigningPool.ts +1 -1
- package/src/workers/index.node.ts +27 -0
- package/src/workers/index.ts +7 -9
- package/test/address.spec.ts +2 -2
- package/test/bitcoin.core.spec.ts +5 -2
- package/test/browser/payments.spec.ts +151 -0
- package/test/browser/psbt.spec.ts +1510 -0
- package/test/browser/script.spec.ts +223 -0
- package/test/browser/setup.ts +13 -0
- package/test/browser/workers-signing.spec.ts +537 -0
- package/test/crypto.spec.ts +2 -2
- package/test/fixtures/core/base58_encode_decode.json +12 -48
- package/test/fixtures/core/base58_keys_invalid.json +50 -150
- package/test/fixtures/core/sighash.json +1 -3
- package/test/fixtures/core/tx_valid.json +133 -501
- package/test/fixtures/embed.json +3 -11
- package/test/fixtures/p2ms.json +21 -91
- package/test/fixtures/p2pk.json +5 -24
- package/test/fixtures/p2pkh.json +7 -36
- package/test/fixtures/p2sh.json +8 -54
- package/test/fixtures/p2tr.json +2 -6
- package/test/fixtures/p2wpkh.json +7 -36
- package/test/fixtures/p2wsh.json +14 -59
- package/test/fixtures/psbt.json +2 -6
- package/test/fixtures/script.json +12 -48
- package/test/integration/addresses.spec.ts +11 -5
- package/test/integration/bip32.spec.ts +1 -1
- package/test/integration/cltv.spec.ts +10 -6
- package/test/integration/csv.spec.ts +10 -9
- package/test/integration/payments.spec.ts +8 -4
- package/test/integration/taproot.spec.ts +26 -6
- package/test/integration/transactions.spec.ts +22 -8
- package/test/payments.spec.ts +1 -1
- package/test/payments.utils.ts +1 -1
- package/test/psbt.spec.ts +250 -64
- package/test/script_signature.spec.ts +1 -1
- package/test/transaction.spec.ts +18 -5
- package/test/tsconfig.json +6 -20
- package/test/workers-pool.spec.ts +22 -23
- package/test/workers-signing.spec.ts +7 -3
- package/test/workers.spec.ts +6 -7
- package/typedoc.json +11 -1
- package/vitest.config.browser.ts +68 -0
- package/browser/ecpair.d.ts +0 -99
- package/src/ecpair.d.ts +0 -99
- package/test/taproot-cache.spec.ts +0 -694
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/workers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/workers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAIH,eAAe;AACf,OAAO,EACH,aAAa,EAeb,cAAc,EACd,eAAe,EACf,aAAa,EACb,aAAa,EAMb,WAAW,GAEd,MAAM,YAAY,CAAC;AAEpB,sBAAsB;AACtB,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE3E,sDAAsD;AACtD,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAEnG,+CAA+C;AAC/C,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAE9D,oCAAoC;AACpC,OAAO,EACH,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,GAGxB,MAAM,oBAAoB,CAAC;AAE5B;;;;GAIG;AACH,MAAM,UAAU,aAAa;IACzB,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC3D,OAAO,MAAM,CAAC;IAClB,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QACjE,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAyB;IAa7D,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAEhC,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACrB,MAAM,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAC;QAC9E,MAAM,IAAI,GAAG,qBAAqB,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACvD,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IAChB,CAAC;SAAM,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,iBAAiB,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACnD,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IAChB,CAAC;SAAM,CAAC;QACJ,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACnE,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js worker pool entry point.
|
|
3
|
+
*
|
|
4
|
+
* This module provides direct access to Node.js-specific worker functionality.
|
|
5
|
+
* It re-exports everything from the base index plus Node.js specific exports.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { NodeWorkerSigningPool } from '@btc-vision/bitcoin/workers';
|
|
10
|
+
*
|
|
11
|
+
* const pool = NodeWorkerSigningPool.getInstance({ workerCount: 4 });
|
|
12
|
+
* await pool.initialize();
|
|
13
|
+
* pool.preserveWorkers();
|
|
14
|
+
*
|
|
15
|
+
* const result = await pool.signBatch(tasks, keyPair);
|
|
16
|
+
*
|
|
17
|
+
* await pool.shutdown();
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @packageDocumentation
|
|
21
|
+
*/
|
|
22
|
+
export * from './index.js';
|
|
23
|
+
export { NodeWorkerSigningPool, type NodeWorkerPoolConfig } from './WorkerSigningPool.node.js';
|
|
24
|
+
//# sourceMappingURL=index.node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.node.d.ts","sourceRoot":"","sources":["../../src/workers/index.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js worker pool entry point.
|
|
3
|
+
*
|
|
4
|
+
* This module provides direct access to Node.js-specific worker functionality.
|
|
5
|
+
* It re-exports everything from the base index plus Node.js specific exports.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { NodeWorkerSigningPool } from '@btc-vision/bitcoin/workers';
|
|
10
|
+
*
|
|
11
|
+
* const pool = NodeWorkerSigningPool.getInstance({ workerCount: 4 });
|
|
12
|
+
* await pool.initialize();
|
|
13
|
+
* pool.preserveWorkers();
|
|
14
|
+
*
|
|
15
|
+
* const result = await pool.signBatch(tasks, keyPair);
|
|
16
|
+
*
|
|
17
|
+
* await pool.shutdown();
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @packageDocumentation
|
|
21
|
+
*/
|
|
22
|
+
// Re-export everything from browser-safe index
|
|
23
|
+
export * from './index.js';
|
|
24
|
+
// Node.js specific exports
|
|
25
|
+
export { NodeWorkerSigningPool } from './WorkerSigningPool.node.js';
|
|
26
|
+
//# sourceMappingURL=index.node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.node.js","sourceRoot":"","sources":["../../src/workers/index.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,+CAA+C;AAC/C,cAAc,YAAY,CAAC;AAE3B,2BAA2B;AAC3B,OAAO,EAAE,qBAAqB,EAA6B,MAAM,6BAA6B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@btc-vision/bitcoin",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "7.0.0-alpha.
|
|
4
|
+
"version": "7.0.0-alpha.3",
|
|
5
5
|
"sideEffects": false,
|
|
6
|
-
"overrides": {
|
|
7
|
-
"ecpair": {
|
|
8
|
-
"valibot": "^1.2.0"
|
|
9
|
-
}
|
|
10
|
-
},
|
|
11
6
|
"description": "Client-side Bitcoin JavaScript library",
|
|
12
7
|
"engines": {
|
|
13
8
|
"node": ">=24.0.0"
|
|
@@ -33,6 +28,21 @@
|
|
|
33
28
|
"import": "./browser/index.js",
|
|
34
29
|
"default": "./browser/index.js"
|
|
35
30
|
},
|
|
31
|
+
"./workers": {
|
|
32
|
+
"browser": {
|
|
33
|
+
"types": "./browser/workers/index.d.ts",
|
|
34
|
+
"import": "./browser/workers/index.js",
|
|
35
|
+
"default": "./browser/workers/index.js"
|
|
36
|
+
},
|
|
37
|
+
"node": {
|
|
38
|
+
"types": "./build/workers/index.node.d.ts",
|
|
39
|
+
"import": "./build/workers/index.node.js",
|
|
40
|
+
"default": "./build/workers/index.node.js"
|
|
41
|
+
},
|
|
42
|
+
"types": "./build/workers/index.d.ts",
|
|
43
|
+
"import": "./build/workers/index.js",
|
|
44
|
+
"default": "./build/workers/index.js"
|
|
45
|
+
},
|
|
36
46
|
"./address": {
|
|
37
47
|
"types": "./build/address.d.ts",
|
|
38
48
|
"import": "./build/address.js"
|
|
@@ -89,6 +99,8 @@
|
|
|
89
99
|
"browser": {
|
|
90
100
|
"./build/index.js": "./browser/index.js",
|
|
91
101
|
"./build/index.d.ts": "./browser/index.d.ts",
|
|
102
|
+
"./build/workers/index.node.js": "./browser/workers/index.js",
|
|
103
|
+
"./build/workers/index.node.d.ts": "./browser/workers/index.d.ts",
|
|
92
104
|
"Buffer": "buffer",
|
|
93
105
|
"crypto": "./src/crypto/crypto-browser.js",
|
|
94
106
|
"stream": "stream-browserify",
|
|
@@ -132,6 +144,8 @@
|
|
|
132
144
|
"test": "npm run build && npm run lint && vitest run",
|
|
133
145
|
"test:watch": "vitest",
|
|
134
146
|
"unit": "vitest run",
|
|
147
|
+
"test:browser": "vitest run --config vitest.config.browser.ts",
|
|
148
|
+
"test:browser:watch": "vitest --config vitest.config.browser.ts",
|
|
135
149
|
"bench": "vitest bench benchmark/",
|
|
136
150
|
"bench:run": "npx tsx benchmark/signing.bench.ts",
|
|
137
151
|
"check:circular": "madge --circular --extensions ts,tsx src/",
|
|
@@ -143,6 +157,8 @@
|
|
|
143
157
|
"@types/bs58check": "^3.0.1",
|
|
144
158
|
"@types/node": "^25.0.10",
|
|
145
159
|
"@types/randombytes": "^2.0.3",
|
|
160
|
+
"@vitest/browser": "^4.0.18",
|
|
161
|
+
"@vitest/browser-playwright": "^4.0.18",
|
|
146
162
|
"@vitest/coverage-v8": "^4.0.18",
|
|
147
163
|
"better-npm-audit": "^3.11.0",
|
|
148
164
|
"bip39": "^3.1.0",
|
|
@@ -150,12 +166,12 @@
|
|
|
150
166
|
"bip68": "^1.0.4",
|
|
151
167
|
"bs58": "^6.0.0",
|
|
152
168
|
"dhttp": "^3.0.3",
|
|
153
|
-
"ecpair": "^3.0.0",
|
|
154
169
|
"eslint": "^9.39.2",
|
|
155
170
|
"https-browserify": "^1.0.0",
|
|
156
171
|
"madge": "^8.0.0",
|
|
157
172
|
"minimaldata": "^1.0.2",
|
|
158
173
|
"os-browserify": "^0.3.0",
|
|
174
|
+
"playwright": "^1.58.0",
|
|
159
175
|
"prettier": "^3.8.1",
|
|
160
176
|
"randombytes": "^2.1.0",
|
|
161
177
|
"regtest-client": "0.2.1",
|
|
@@ -171,10 +187,13 @@
|
|
|
171
187
|
"vite": "^7.3.1",
|
|
172
188
|
"vite-plugin-dts": "^4.5.4",
|
|
173
189
|
"vite-plugin-node-polyfills": "^0.25.0",
|
|
190
|
+
"vite-plugin-top-level-await": "^1.6.0",
|
|
191
|
+
"vite-plugin-wasm": "^3.5.0",
|
|
174
192
|
"vitest": "^4.0.18"
|
|
175
193
|
},
|
|
176
194
|
"dependencies": {
|
|
177
|
-
"@btc-vision/bip32": "^
|
|
195
|
+
"@btc-vision/bip32": "^7.0.2",
|
|
196
|
+
"@btc-vision/ecpair": "^4.0.2",
|
|
178
197
|
"@btc-vision/logger": "^1.0.8",
|
|
179
198
|
"@noble/hashes": "^2.0.1",
|
|
180
199
|
"@noble/secp256k1": "^3.0.0",
|
package/src/address.ts
CHANGED
|
@@ -25,7 +25,6 @@ import {
|
|
|
25
25
|
type Bytes20,
|
|
26
26
|
isBytes20,
|
|
27
27
|
isUInt8,
|
|
28
|
-
type Script,
|
|
29
28
|
toBytes20,
|
|
30
29
|
toBytes32,
|
|
31
30
|
type XOnlyPublicKey,
|
|
@@ -188,27 +187,51 @@ export function toBech32(
|
|
|
188
187
|
}
|
|
189
188
|
|
|
190
189
|
/**
|
|
191
|
-
* decode address from output script with network, return address if matched
|
|
190
|
+
* decode address from output script with network, return address if matched.
|
|
191
|
+
*
|
|
192
|
+
* Uses fast byte-pattern matching for common script types (P2PKH, P2SH,
|
|
193
|
+
* P2WPKH, P2WSH, P2TR) to avoid constructing payment objects and catching
|
|
194
|
+
* exceptions. Falls back to payment constructors for exotic types.
|
|
192
195
|
*/
|
|
193
196
|
export function fromOutputScript(output: Uint8Array, network?: Network): string {
|
|
194
|
-
// TODO: Network
|
|
195
197
|
network = network || networks.bitcoin;
|
|
198
|
+
const len = output.length;
|
|
199
|
+
|
|
200
|
+
// P2PKH: OP_DUP(0x76) OP_HASH160(0xa9) 0x14 <20-byte hash> OP_EQUALVERIFY(0x88) OP_CHECKSIG(0xac)
|
|
201
|
+
if (
|
|
202
|
+
len === 25 &&
|
|
203
|
+
output[0] === 0x76 &&
|
|
204
|
+
output[1] === 0xa9 &&
|
|
205
|
+
output[2] === 0x14 &&
|
|
206
|
+
output[23] === 0x88 &&
|
|
207
|
+
output[24] === 0xac
|
|
208
|
+
) {
|
|
209
|
+
return toBase58Check(output.subarray(3, 23) as Bytes20, network.pubKeyHash);
|
|
210
|
+
}
|
|
196
211
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
return
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
+
// P2SH: OP_HASH160(0xa9) 0x14 <20-byte hash> OP_EQUAL(0x87)
|
|
213
|
+
if (len === 23 && output[0] === 0xa9 && output[1] === 0x14 && output[22] === 0x87) {
|
|
214
|
+
return toBase58Check(output.subarray(2, 22) as Bytes20, network.scriptHash);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// P2WPKH: OP_0(0x00) 0x14 <20-byte hash>
|
|
218
|
+
if (len === 22 && output[0] === 0x00 && output[1] === 0x14) {
|
|
219
|
+
return toBech32(output.subarray(2, 22), 0, network.bech32);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// P2WSH: OP_0(0x00) 0x20 <32-byte hash>
|
|
223
|
+
if (len === 34 && output[0] === 0x00 && output[1] === 0x20) {
|
|
224
|
+
return toBech32(output.subarray(2, 34), 0, network.bech32);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// P2TR: OP_1(0x51) 0x20 <32-byte x-only pubkey>
|
|
228
|
+
if (len === 34 && output[0] === 0x51 && output[1] === 0x20) {
|
|
229
|
+
const words = bech32m.toWords(output.subarray(2, 34));
|
|
230
|
+
words.unshift(1);
|
|
231
|
+
return bech32m.encode(network.bech32, words);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Fallback for exotic types
|
|
212
235
|
try {
|
|
213
236
|
return toFutureOPNetAddress(output, network);
|
|
214
237
|
} catch (e) {}
|
package/src/branded.ts
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Branded type definitions for type-safe primitives.
|
|
3
3
|
*
|
|
4
|
+
* Re-exported from @btc-vision/ecpair to ensure cross-package type compatibility.
|
|
5
|
+
*
|
|
4
6
|
* @packageDocumentation
|
|
5
7
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
8
|
+
export type {
|
|
9
|
+
Brand,
|
|
10
|
+
Bytes32,
|
|
11
|
+
Bytes20,
|
|
12
|
+
PublicKey,
|
|
13
|
+
XOnlyPublicKey,
|
|
14
|
+
Satoshi,
|
|
15
|
+
PrivateKey,
|
|
16
|
+
Signature,
|
|
17
|
+
SchnorrSignature,
|
|
18
|
+
MessageHash,
|
|
19
|
+
Script,
|
|
20
|
+
} from '@btc-vision/ecpair';
|
package/src/ecc/context.ts
CHANGED
|
@@ -4,9 +4,8 @@
|
|
|
4
4
|
*
|
|
5
5
|
* @packageDocumentation
|
|
6
6
|
*/
|
|
7
|
-
import type {
|
|
8
|
-
import {
|
|
9
|
-
import type { Bytes32, XOnlyPublicKey } from '../types.js';
|
|
7
|
+
import type { CryptoBackend } from '@btc-vision/ecpair';
|
|
8
|
+
import { verifyCryptoBackend } from '@btc-vision/ecpair';
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* Context class for managing the ECC library instance.
|
|
@@ -15,10 +14,11 @@ import type { Bytes32, XOnlyPublicKey } from '../types.js';
|
|
|
15
14
|
* @example
|
|
16
15
|
* ```typescript
|
|
17
16
|
* import { EccContext } from '@btc-vision/bitcoin';
|
|
18
|
-
* import
|
|
17
|
+
* import { createNobleBackend } from '@btc-vision/ecpair';
|
|
19
18
|
*
|
|
20
19
|
* // Initialize once at app startup
|
|
21
|
-
*
|
|
20
|
+
* const backend = createNobleBackend();
|
|
21
|
+
* EccContext.init(backend);
|
|
22
22
|
*
|
|
23
23
|
* // Get instance anywhere in your code
|
|
24
24
|
* const ecc = EccContext.get();
|
|
@@ -29,16 +29,16 @@ import type { Bytes32, XOnlyPublicKey } from '../types.js';
|
|
|
29
29
|
*/
|
|
30
30
|
export class EccContext {
|
|
31
31
|
static #instance: EccContext | undefined;
|
|
32
|
-
readonly #lib:
|
|
32
|
+
readonly #lib: CryptoBackend;
|
|
33
33
|
|
|
34
|
-
private constructor(lib:
|
|
34
|
+
private constructor(lib: CryptoBackend) {
|
|
35
35
|
this.#lib = lib;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
* The underlying ECC library instance.
|
|
40
40
|
*/
|
|
41
|
-
get lib():
|
|
41
|
+
get lib(): CryptoBackend {
|
|
42
42
|
return this.#lib;
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -46,20 +46,24 @@ export class EccContext {
|
|
|
46
46
|
* Initializes the ECC context with the provided library.
|
|
47
47
|
* The library is verified before being set as active.
|
|
48
48
|
*
|
|
49
|
-
* @param lib - The
|
|
49
|
+
* @param lib - The CryptoBackend instance to initialize
|
|
50
50
|
* @returns The initialized EccContext instance
|
|
51
|
-
* @throws Error if the
|
|
51
|
+
* @throws Error if the CryptoBackend fails verification
|
|
52
52
|
*
|
|
53
53
|
* @example
|
|
54
54
|
* ```typescript
|
|
55
55
|
* import { EccContext } from '@btc-vision/bitcoin';
|
|
56
|
-
* import
|
|
56
|
+
* import { createNobleBackend } from '@btc-vision/ecpair';
|
|
57
57
|
*
|
|
58
|
-
* const context = EccContext.init(
|
|
58
|
+
* const context = EccContext.init(createNobleBackend());
|
|
59
59
|
* ```
|
|
60
60
|
*/
|
|
61
|
-
static init(lib:
|
|
62
|
-
|
|
61
|
+
static init(lib: CryptoBackend): EccContext {
|
|
62
|
+
// Skip re-verification if same lib is already initialized
|
|
63
|
+
if (EccContext.#instance && EccContext.#instance.#lib === lib) {
|
|
64
|
+
return EccContext.#instance;
|
|
65
|
+
}
|
|
66
|
+
verifyCryptoBackend(lib);
|
|
63
67
|
EccContext.#instance = new EccContext(lib);
|
|
64
68
|
return EccContext.#instance;
|
|
65
69
|
}
|
|
@@ -75,7 +79,7 @@ export class EccContext {
|
|
|
75
79
|
* import { EccContext } from '@btc-vision/bitcoin';
|
|
76
80
|
*
|
|
77
81
|
* const context = EccContext.get();
|
|
78
|
-
* const
|
|
82
|
+
* const tweaked = context.lib.xOnlyPointAddTweak(key, tweak);
|
|
79
83
|
* ```
|
|
80
84
|
*/
|
|
81
85
|
static get(): EccContext {
|
|
@@ -113,7 +117,7 @@ export class EccContext {
|
|
|
113
117
|
* import { EccContext } from '@btc-vision/bitcoin';
|
|
114
118
|
*
|
|
115
119
|
* if (!EccContext.isInitialized()) {
|
|
116
|
-
* EccContext.init(
|
|
120
|
+
* EccContext.init(createNobleBackend());
|
|
117
121
|
* }
|
|
118
122
|
* ```
|
|
119
123
|
*/
|
|
@@ -127,22 +131,22 @@ export class EccContext {
|
|
|
127
131
|
* This is a convenience function that wraps EccContext.init().
|
|
128
132
|
* Pass `undefined` to clear the library.
|
|
129
133
|
*
|
|
130
|
-
* @param eccLib - The
|
|
131
|
-
* @throws Error if the
|
|
134
|
+
* @param eccLib - The CryptoBackend instance to initialize, or undefined to clear
|
|
135
|
+
* @throws Error if the CryptoBackend fails verification
|
|
132
136
|
*
|
|
133
137
|
* @example
|
|
134
138
|
* ```typescript
|
|
135
139
|
* import { initEccLib } from '@btc-vision/bitcoin';
|
|
136
|
-
* import
|
|
140
|
+
* import { createNobleBackend } from '@btc-vision/ecpair';
|
|
137
141
|
*
|
|
138
142
|
* // Initialize the ECC library
|
|
139
|
-
* initEccLib(
|
|
143
|
+
* initEccLib(createNobleBackend());
|
|
140
144
|
*
|
|
141
145
|
* // Clear the library
|
|
142
146
|
* initEccLib(undefined);
|
|
143
147
|
* ```
|
|
144
148
|
*/
|
|
145
|
-
export function initEccLib(eccLib:
|
|
149
|
+
export function initEccLib(eccLib: CryptoBackend | undefined): void {
|
|
146
150
|
if (eccLib === undefined) {
|
|
147
151
|
EccContext.clear();
|
|
148
152
|
return;
|
|
@@ -154,127 +158,20 @@ export function initEccLib(eccLib: EccLib | undefined): void {
|
|
|
154
158
|
* Retrieves the initialized ECC library instance.
|
|
155
159
|
* This is a convenience function that wraps EccContext.get().lib.
|
|
156
160
|
*
|
|
157
|
-
* @returns The
|
|
161
|
+
* @returns The CryptoBackend instance
|
|
158
162
|
* @throws Error if the ECC library has not been initialized
|
|
159
163
|
*
|
|
160
164
|
* @example
|
|
161
165
|
* ```typescript
|
|
162
166
|
* import { getEccLib, initEccLib } from '@btc-vision/bitcoin';
|
|
163
|
-
* import
|
|
167
|
+
* import { createNobleBackend } from '@btc-vision/ecpair';
|
|
164
168
|
*
|
|
165
|
-
* initEccLib(
|
|
169
|
+
* initEccLib(createNobleBackend());
|
|
166
170
|
*
|
|
167
171
|
* const ecc = getEccLib();
|
|
168
|
-
* const
|
|
172
|
+
* const tweaked = ecc.xOnlyPointAddTweak(pubkey, tweak);
|
|
169
173
|
* ```
|
|
170
174
|
*/
|
|
171
|
-
export function getEccLib():
|
|
175
|
+
export function getEccLib(): CryptoBackend {
|
|
172
176
|
return EccContext.get().lib;
|
|
173
177
|
}
|
|
174
|
-
|
|
175
|
-
// ============================================================================
|
|
176
|
-
// Verification
|
|
177
|
-
// ============================================================================
|
|
178
|
-
|
|
179
|
-
interface TweakAddVector {
|
|
180
|
-
pubkey: string;
|
|
181
|
-
tweak: string;
|
|
182
|
-
parity: 0 | 1 | -1;
|
|
183
|
-
result: string | null;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const TWEAK_ADD_VECTORS: TweakAddVector[] = [
|
|
187
|
-
{
|
|
188
|
-
pubkey: '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
|
|
189
|
-
tweak: 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140',
|
|
190
|
-
parity: -1,
|
|
191
|
-
result: null,
|
|
192
|
-
},
|
|
193
|
-
{
|
|
194
|
-
pubkey: '1617d38ed8d8657da4d4761e8057bc396ea9e4b9d29776d4be096016dbd2509b',
|
|
195
|
-
tweak: 'a8397a935f0dfceba6ba9618f6451ef4d80637abf4e6af2669fbc9de6a8fd2ac',
|
|
196
|
-
parity: 1,
|
|
197
|
-
result: 'e478f99dab91052ab39a33ea35fd5e6e4933f4d28023cd597c9a1f6760346adf',
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
pubkey: '2c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991',
|
|
201
|
-
tweak: '823c3cd2142744b075a87eade7e1b8678ba308d566226a0056ca2b7a76f86b47',
|
|
202
|
-
parity: 0,
|
|
203
|
-
result: '9534f8dc8c6deda2dc007655981c78b49c5d96c778fbf363462a11ec9dfd948c',
|
|
204
|
-
},
|
|
205
|
-
];
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Verifies that the ECC library implementation is correct.
|
|
209
|
-
* Tests `isXOnlyPoint` and `xOnlyPointAddTweak` with known test vectors.
|
|
210
|
-
*
|
|
211
|
-
* @param ecc - The ECC library to verify
|
|
212
|
-
* @throws Error if any verification test fails
|
|
213
|
-
*/
|
|
214
|
-
function verifyEcc(ecc: EccLib): void {
|
|
215
|
-
if (typeof ecc.isXOnlyPoint !== 'function') {
|
|
216
|
-
throw new Error('ECC library missing isXOnlyPoint function');
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Test isXOnlyPoint with valid points
|
|
220
|
-
const validPoints = [
|
|
221
|
-
'79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
|
|
222
|
-
'fffffffffffffffffffffffffffffffffffffffffffffffffffffffeeffffc2e',
|
|
223
|
-
'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9',
|
|
224
|
-
'0000000000000000000000000000000000000000000000000000000000000001',
|
|
225
|
-
];
|
|
226
|
-
|
|
227
|
-
for (const hex of validPoints) {
|
|
228
|
-
if (!ecc.isXOnlyPoint(fromHex(hex))) {
|
|
229
|
-
throw new Error(`ECC library isXOnlyPoint failed for valid point: ${hex}`);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Test isXOnlyPoint with invalid points
|
|
234
|
-
const invalidPoints = [
|
|
235
|
-
'0000000000000000000000000000000000000000000000000000000000000000',
|
|
236
|
-
'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f',
|
|
237
|
-
];
|
|
238
|
-
|
|
239
|
-
for (const hex of invalidPoints) {
|
|
240
|
-
if (ecc.isXOnlyPoint(fromHex(hex))) {
|
|
241
|
-
throw new Error(`ECC library isXOnlyPoint should reject invalid point: ${hex}`);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// Test xOnlyPointAddTweak
|
|
246
|
-
if (typeof ecc.xOnlyPointAddTweak !== 'function') {
|
|
247
|
-
throw new Error('ECC library missing xOnlyPointAddTweak function');
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
for (const vector of TWEAK_ADD_VECTORS) {
|
|
251
|
-
const result = ecc.xOnlyPointAddTweak(
|
|
252
|
-
fromHex(vector.pubkey) as XOnlyPublicKey,
|
|
253
|
-
fromHex(vector.tweak) as Bytes32,
|
|
254
|
-
);
|
|
255
|
-
|
|
256
|
-
if (vector.result === null) {
|
|
257
|
-
if (result !== null) {
|
|
258
|
-
throw new Error(
|
|
259
|
-
`ECC library xOnlyPointAddTweak should return null for: ${vector.pubkey}`,
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
} else {
|
|
263
|
-
if (result === null) {
|
|
264
|
-
throw new Error(
|
|
265
|
-
`ECC library xOnlyPointAddTweak returned null unexpectedly for: ${vector.pubkey}`,
|
|
266
|
-
);
|
|
267
|
-
}
|
|
268
|
-
if (result.parity !== vector.parity) {
|
|
269
|
-
throw new Error(
|
|
270
|
-
`ECC library xOnlyPointAddTweak parity mismatch for: ${vector.pubkey}`,
|
|
271
|
-
);
|
|
272
|
-
}
|
|
273
|
-
if (!equals(result.xOnlyPubkey, fromHex(vector.result))) {
|
|
274
|
-
throw new Error(
|
|
275
|
-
`ECC library xOnlyPointAddTweak result mismatch for: ${vector.pubkey}`,
|
|
276
|
-
);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
package/src/ecc/index.ts
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* @packageDocumentation
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
// Core types
|
|
11
|
-
export type { EccLib, XOnlyPointAddTweakResult, Parity } from './types.js';
|
|
10
|
+
// Core types (CryptoBackend is the canonical name; EccLib is a deprecated alias)
|
|
11
|
+
export type { CryptoBackend, EccLib, XOnlyPointAddTweakResult, Parity } from './types.js';
|
|
12
12
|
|
|
13
13
|
// Context management
|
|
14
14
|
export { EccContext, initEccLib, getEccLib } from './context.js';
|