@btc-vision/bitcoin 6.3.0
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/LICENSE +21 -0
- package/README.md +201 -0
- package/package.json +95 -0
- package/src/address.d.ts +42 -0
- package/src/address.js +191 -0
- package/src/bip66.d.ts +7 -0
- package/src/bip66.js +103 -0
- package/src/block.d.ts +30 -0
- package/src/block.js +224 -0
- package/src/bufferutils.d.ts +54 -0
- package/src/bufferutils.js +182 -0
- package/src/crypto.d.ts +18 -0
- package/src/crypto.js +128 -0
- package/src/ecc_lib.d.ts +17 -0
- package/src/ecc_lib.js +122 -0
- package/src/hooks/AdvancedSignatureManager.d.ts +44 -0
- package/src/hooks/AdvancedSignatureManager.js +88 -0
- package/src/hooks/HookedSigner.d.ts +4 -0
- package/src/hooks/HookedSigner.js +90 -0
- package/src/hooks/SignatureManager.d.ts +35 -0
- package/src/hooks/SignatureManager.js +72 -0
- package/src/index.d.ts +42 -0
- package/src/index.js +87 -0
- package/src/merkle.d.ts +10 -0
- package/src/merkle.js +30 -0
- package/src/networks.d.ts +29 -0
- package/src/networks.js +71 -0
- package/src/ops.d.ts +126 -0
- package/src/ops.js +131 -0
- package/src/payments/bip341.d.ts +49 -0
- package/src/payments/bip341.js +124 -0
- package/src/payments/embed.d.ts +9 -0
- package/src/payments/embed.js +54 -0
- package/src/payments/index.d.ts +48 -0
- package/src/payments/index.js +69 -0
- package/src/payments/lazy.d.ts +2 -0
- package/src/payments/lazy.js +32 -0
- package/src/payments/p2ms.d.ts +9 -0
- package/src/payments/p2ms.js +158 -0
- package/src/payments/p2pk.d.ts +10 -0
- package/src/payments/p2pk.js +82 -0
- package/src/payments/p2pkh.d.ts +10 -0
- package/src/payments/p2pkh.js +143 -0
- package/src/payments/p2sh.d.ts +10 -0
- package/src/payments/p2sh.js +204 -0
- package/src/payments/p2tr.d.ts +10 -0
- package/src/payments/p2tr.js +315 -0
- package/src/payments/p2wpkh.d.ts +10 -0
- package/src/payments/p2wpkh.js +146 -0
- package/src/payments/p2wsh.d.ts +10 -0
- package/src/payments/p2wsh.js +226 -0
- package/src/psbt/bip371.d.ts +42 -0
- package/src/psbt/bip371.js +424 -0
- package/src/psbt/psbtutils.d.ts +64 -0
- package/src/psbt/psbtutils.js +191 -0
- package/src/psbt.d.ts +235 -0
- package/src/psbt.js +1825 -0
- package/src/push_data.d.ts +29 -0
- package/src/push_data.js +83 -0
- package/src/script.d.ts +42 -0
- package/src/script.js +231 -0
- package/src/script_number.d.ts +19 -0
- package/src/script_number.js +78 -0
- package/src/script_signature.d.ts +21 -0
- package/src/script_signature.js +79 -0
- package/src/transaction.d.ts +60 -0
- package/src/transaction.js +571 -0
- package/src/types.d.ts +54 -0
- package/src/types.js +106 -0
package/src/crypto.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
exports.taggedHash =
|
|
4
|
+
exports.TAGGED_HASH_PREFIXES =
|
|
5
|
+
exports.TAGS =
|
|
6
|
+
exports.hash256 =
|
|
7
|
+
exports.hash160 =
|
|
8
|
+
exports.sha256 =
|
|
9
|
+
exports.sha1 =
|
|
10
|
+
exports.ripemd160 =
|
|
11
|
+
void 0;
|
|
12
|
+
/**
|
|
13
|
+
* A module for hashing functions.
|
|
14
|
+
* include ripemd160、sha1、sha256、hash160、hash256、taggedHash
|
|
15
|
+
*
|
|
16
|
+
* @packageDocumentation
|
|
17
|
+
*/
|
|
18
|
+
const ripemd160_1 = require('@noble/hashes/ripemd160');
|
|
19
|
+
const sha1_1 = require('@noble/hashes/sha1');
|
|
20
|
+
const sha256_1 = require('@noble/hashes/sha256');
|
|
21
|
+
function ripemd160(buffer) {
|
|
22
|
+
return Buffer.from((0, ripemd160_1.ripemd160)(Uint8Array.from(buffer)));
|
|
23
|
+
}
|
|
24
|
+
exports.ripemd160 = ripemd160;
|
|
25
|
+
function sha1(buffer) {
|
|
26
|
+
return Buffer.from((0, sha1_1.sha1)(Uint8Array.from(buffer)));
|
|
27
|
+
}
|
|
28
|
+
exports.sha1 = sha1;
|
|
29
|
+
function sha256(buffer) {
|
|
30
|
+
return Buffer.from((0, sha256_1.sha256)(Uint8Array.from(buffer)));
|
|
31
|
+
}
|
|
32
|
+
exports.sha256 = sha256;
|
|
33
|
+
function hash160(buffer) {
|
|
34
|
+
return Buffer.from(
|
|
35
|
+
(0, ripemd160_1.ripemd160)(
|
|
36
|
+
(0, sha256_1.sha256)(Uint8Array.from(buffer)),
|
|
37
|
+
),
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
exports.hash160 = hash160;
|
|
41
|
+
function hash256(buffer) {
|
|
42
|
+
return Buffer.from(
|
|
43
|
+
(0, sha256_1.sha256)((0, sha256_1.sha256)(Uint8Array.from(buffer))),
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
exports.hash256 = hash256;
|
|
47
|
+
exports.TAGS = [
|
|
48
|
+
'BIP0340/challenge',
|
|
49
|
+
'BIP0340/aux',
|
|
50
|
+
'BIP0340/nonce',
|
|
51
|
+
'TapLeaf',
|
|
52
|
+
'TapBranch',
|
|
53
|
+
'TapSighash',
|
|
54
|
+
'TapTweak',
|
|
55
|
+
'KeyAgg list',
|
|
56
|
+
'KeyAgg coefficient',
|
|
57
|
+
];
|
|
58
|
+
/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */
|
|
59
|
+
/**
|
|
60
|
+
* Defines the tagged hash prefixes used in the crypto module.
|
|
61
|
+
*/
|
|
62
|
+
exports.TAGGED_HASH_PREFIXES = {
|
|
63
|
+
'BIP0340/challenge': Buffer.from([
|
|
64
|
+
123, 181, 45, 122, 159, 239, 88, 50, 62, 177, 191, 122, 64, 125, 179,
|
|
65
|
+
130, 210, 243, 242, 216, 27, 177, 34, 79, 73, 254, 81, 143, 109, 72,
|
|
66
|
+
211, 124, 123, 181, 45, 122, 159, 239, 88, 50, 62, 177, 191, 122, 64,
|
|
67
|
+
125, 179, 130, 210, 243, 242, 216, 27, 177, 34, 79, 73, 254, 81, 143,
|
|
68
|
+
109, 72, 211, 124,
|
|
69
|
+
]),
|
|
70
|
+
'BIP0340/aux': Buffer.from([
|
|
71
|
+
241, 239, 78, 94, 192, 99, 202, 218, 109, 148, 202, 250, 157, 152, 126,
|
|
72
|
+
160, 105, 38, 88, 57, 236, 193, 31, 151, 45, 119, 165, 46, 216, 193,
|
|
73
|
+
204, 144, 241, 239, 78, 94, 192, 99, 202, 218, 109, 148, 202, 250, 157,
|
|
74
|
+
152, 126, 160, 105, 38, 88, 57, 236, 193, 31, 151, 45, 119, 165, 46,
|
|
75
|
+
216, 193, 204, 144,
|
|
76
|
+
]),
|
|
77
|
+
'BIP0340/nonce': Buffer.from([
|
|
78
|
+
7, 73, 119, 52, 167, 155, 203, 53, 91, 155, 140, 125, 3, 79, 18, 28,
|
|
79
|
+
244, 52, 215, 62, 247, 45, 218, 25, 135, 0, 97, 251, 82, 191, 235, 47,
|
|
80
|
+
7, 73, 119, 52, 167, 155, 203, 53, 91, 155, 140, 125, 3, 79, 18, 28,
|
|
81
|
+
244, 52, 215, 62, 247, 45, 218, 25, 135, 0, 97, 251, 82, 191, 235, 47,
|
|
82
|
+
]),
|
|
83
|
+
TapLeaf: Buffer.from([
|
|
84
|
+
174, 234, 143, 220, 66, 8, 152, 49, 5, 115, 75, 88, 8, 29, 30, 38, 56,
|
|
85
|
+
211, 95, 28, 181, 64, 8, 212, 211, 87, 202, 3, 190, 120, 233, 238, 174,
|
|
86
|
+
234, 143, 220, 66, 8, 152, 49, 5, 115, 75, 88, 8, 29, 30, 38, 56, 211,
|
|
87
|
+
95, 28, 181, 64, 8, 212, 211, 87, 202, 3, 190, 120, 233, 238,
|
|
88
|
+
]),
|
|
89
|
+
TapBranch: Buffer.from([
|
|
90
|
+
25, 65, 161, 242, 229, 110, 185, 95, 162, 169, 241, 148, 190, 92, 1,
|
|
91
|
+
247, 33, 111, 51, 237, 130, 176, 145, 70, 52, 144, 208, 91, 245, 22,
|
|
92
|
+
160, 21, 25, 65, 161, 242, 229, 110, 185, 95, 162, 169, 241, 148, 190,
|
|
93
|
+
92, 1, 247, 33, 111, 51, 237, 130, 176, 145, 70, 52, 144, 208, 91, 245,
|
|
94
|
+
22, 160, 21,
|
|
95
|
+
]),
|
|
96
|
+
TapSighash: Buffer.from([
|
|
97
|
+
244, 10, 72, 223, 75, 42, 112, 200, 180, 146, 75, 242, 101, 70, 97, 237,
|
|
98
|
+
61, 149, 253, 102, 163, 19, 235, 135, 35, 117, 151, 198, 40, 228, 160,
|
|
99
|
+
49, 244, 10, 72, 223, 75, 42, 112, 200, 180, 146, 75, 242, 101, 70, 97,
|
|
100
|
+
237, 61, 149, 253, 102, 163, 19, 235, 135, 35, 117, 151, 198, 40, 228,
|
|
101
|
+
160, 49,
|
|
102
|
+
]),
|
|
103
|
+
TapTweak: Buffer.from([
|
|
104
|
+
232, 15, 225, 99, 156, 156, 160, 80, 227, 175, 27, 57, 193, 67, 198, 62,
|
|
105
|
+
66, 156, 188, 235, 21, 217, 64, 251, 181, 197, 161, 244, 175, 87, 197,
|
|
106
|
+
233, 232, 15, 225, 99, 156, 156, 160, 80, 227, 175, 27, 57, 193, 67,
|
|
107
|
+
198, 62, 66, 156, 188, 235, 21, 217, 64, 251, 181, 197, 161, 244, 175,
|
|
108
|
+
87, 197, 233,
|
|
109
|
+
]),
|
|
110
|
+
'KeyAgg list': Buffer.from([
|
|
111
|
+
72, 28, 151, 28, 60, 11, 70, 215, 240, 178, 117, 174, 89, 141, 78, 44,
|
|
112
|
+
126, 215, 49, 156, 89, 74, 92, 110, 199, 158, 160, 212, 153, 2, 148,
|
|
113
|
+
240, 72, 28, 151, 28, 60, 11, 70, 215, 240, 178, 117, 174, 89, 141, 78,
|
|
114
|
+
44, 126, 215, 49, 156, 89, 74, 92, 110, 199, 158, 160, 212, 153, 2, 148,
|
|
115
|
+
240,
|
|
116
|
+
]),
|
|
117
|
+
'KeyAgg coefficient': Buffer.from([
|
|
118
|
+
191, 201, 4, 3, 77, 28, 136, 232, 200, 14, 34, 229, 61, 36, 86, 109,
|
|
119
|
+
100, 130, 78, 214, 66, 114, 129, 192, 145, 0, 249, 77, 205, 82, 201,
|
|
120
|
+
129, 191, 201, 4, 3, 77, 28, 136, 232, 200, 14, 34, 229, 61, 36, 86,
|
|
121
|
+
109, 100, 130, 78, 214, 66, 114, 129, 192, 145, 0, 249, 77, 205, 82,
|
|
122
|
+
201, 129,
|
|
123
|
+
]),
|
|
124
|
+
};
|
|
125
|
+
function taggedHash(prefix, data) {
|
|
126
|
+
return sha256(Buffer.concat([exports.TAGGED_HASH_PREFIXES[prefix], data]));
|
|
127
|
+
}
|
|
128
|
+
exports.taggedHash = taggedHash;
|
package/src/ecc_lib.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { TinySecp256k1Interface } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Initializes the ECC library with the provided instance.
|
|
4
|
+
* If `eccLib` is `undefined`, the library will be cleared.
|
|
5
|
+
* If `eccLib` is a new instance, it will be verified before setting it as the active library.
|
|
6
|
+
*
|
|
7
|
+
* @param eccLib The instance of the ECC library to initialize.
|
|
8
|
+
*/
|
|
9
|
+
export declare function initEccLib(eccLib: TinySecp256k1Interface | undefined): void;
|
|
10
|
+
/**
|
|
11
|
+
* Retrieves the ECC Library instance.
|
|
12
|
+
* Throws an error if the ECC Library is not provided.
|
|
13
|
+
* You must call initEccLib() with a valid TinySecp256k1Interface instance before calling this function.
|
|
14
|
+
* @returns The ECC Library instance.
|
|
15
|
+
* @throws Error if the ECC Library is not provided.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getEccLib(): TinySecp256k1Interface;
|
package/src/ecc_lib.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
exports.getEccLib = exports.initEccLib = void 0;
|
|
4
|
+
const _ECCLIB_CACHE = {};
|
|
5
|
+
/**
|
|
6
|
+
* Initializes the ECC library with the provided instance.
|
|
7
|
+
* If `eccLib` is `undefined`, the library will be cleared.
|
|
8
|
+
* If `eccLib` is a new instance, it will be verified before setting it as the active library.
|
|
9
|
+
*
|
|
10
|
+
* @param eccLib The instance of the ECC library to initialize.
|
|
11
|
+
*/
|
|
12
|
+
function initEccLib(eccLib) {
|
|
13
|
+
if (!eccLib) {
|
|
14
|
+
// allow clearing the library
|
|
15
|
+
_ECCLIB_CACHE.eccLib = eccLib;
|
|
16
|
+
} else if (eccLib !== _ECCLIB_CACHE.eccLib) {
|
|
17
|
+
// new instance, verify it
|
|
18
|
+
verifyEcc(eccLib);
|
|
19
|
+
_ECCLIB_CACHE.eccLib = eccLib;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.initEccLib = initEccLib;
|
|
23
|
+
/**
|
|
24
|
+
* Retrieves the ECC Library instance.
|
|
25
|
+
* Throws an error if the ECC Library is not provided.
|
|
26
|
+
* You must call initEccLib() with a valid TinySecp256k1Interface instance before calling this function.
|
|
27
|
+
* @returns The ECC Library instance.
|
|
28
|
+
* @throws Error if the ECC Library is not provided.
|
|
29
|
+
*/
|
|
30
|
+
function getEccLib() {
|
|
31
|
+
if (!_ECCLIB_CACHE.eccLib)
|
|
32
|
+
throw new Error(
|
|
33
|
+
'No ECC Library provided. You must call initEccLib() with a valid TinySecp256k1Interface instance',
|
|
34
|
+
);
|
|
35
|
+
return _ECCLIB_CACHE.eccLib;
|
|
36
|
+
}
|
|
37
|
+
exports.getEccLib = getEccLib;
|
|
38
|
+
const h = hex => Buffer.from(hex, 'hex');
|
|
39
|
+
/**
|
|
40
|
+
* Verifies the ECC functionality.
|
|
41
|
+
*
|
|
42
|
+
* @param ecc - The TinySecp256k1Interface object.
|
|
43
|
+
*/
|
|
44
|
+
function verifyEcc(ecc) {
|
|
45
|
+
assert(typeof ecc.isXOnlyPoint === 'function');
|
|
46
|
+
assert(
|
|
47
|
+
ecc.isXOnlyPoint(
|
|
48
|
+
h(
|
|
49
|
+
'79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
|
|
50
|
+
),
|
|
51
|
+
),
|
|
52
|
+
);
|
|
53
|
+
assert(
|
|
54
|
+
ecc.isXOnlyPoint(
|
|
55
|
+
h(
|
|
56
|
+
'fffffffffffffffffffffffffffffffffffffffffffffffffffffffeeffffc2e',
|
|
57
|
+
),
|
|
58
|
+
),
|
|
59
|
+
);
|
|
60
|
+
assert(
|
|
61
|
+
ecc.isXOnlyPoint(
|
|
62
|
+
h(
|
|
63
|
+
'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9',
|
|
64
|
+
),
|
|
65
|
+
),
|
|
66
|
+
);
|
|
67
|
+
assert(
|
|
68
|
+
ecc.isXOnlyPoint(
|
|
69
|
+
h(
|
|
70
|
+
'0000000000000000000000000000000000000000000000000000000000000001',
|
|
71
|
+
),
|
|
72
|
+
),
|
|
73
|
+
);
|
|
74
|
+
assert(
|
|
75
|
+
!ecc.isXOnlyPoint(
|
|
76
|
+
h(
|
|
77
|
+
'0000000000000000000000000000000000000000000000000000000000000000',
|
|
78
|
+
),
|
|
79
|
+
),
|
|
80
|
+
);
|
|
81
|
+
assert(
|
|
82
|
+
!ecc.isXOnlyPoint(
|
|
83
|
+
h(
|
|
84
|
+
'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f',
|
|
85
|
+
),
|
|
86
|
+
),
|
|
87
|
+
);
|
|
88
|
+
assert(typeof ecc.xOnlyPointAddTweak === 'function');
|
|
89
|
+
tweakAddVectors.forEach(t => {
|
|
90
|
+
const r = ecc.xOnlyPointAddTweak(h(t.pubkey), h(t.tweak));
|
|
91
|
+
if (t.result === null) {
|
|
92
|
+
assert(r === null);
|
|
93
|
+
} else {
|
|
94
|
+
assert(r !== null);
|
|
95
|
+
assert(r.parity === t.parity);
|
|
96
|
+
assert(Buffer.from(r.xOnlyPubkey).equals(h(t.result)));
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
function assert(bool) {
|
|
101
|
+
if (!bool) throw new Error('ecc library invalid');
|
|
102
|
+
}
|
|
103
|
+
const tweakAddVectors = [
|
|
104
|
+
{
|
|
105
|
+
pubkey: '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
|
|
106
|
+
tweak: 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140',
|
|
107
|
+
parity: -1,
|
|
108
|
+
result: null,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
pubkey: '1617d38ed8d8657da4d4761e8057bc396ea9e4b9d29776d4be096016dbd2509b',
|
|
112
|
+
tweak: 'a8397a935f0dfceba6ba9618f6451ef4d80637abf4e6af2669fbc9de6a8fd2ac',
|
|
113
|
+
parity: 1,
|
|
114
|
+
result: 'e478f99dab91052ab39a33ea35fd5e6e4933f4d28023cd597c9a1f6760346adf',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
pubkey: '2c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991',
|
|
118
|
+
tweak: '823c3cd2142744b075a87eade7e1b8678ba308d566226a0056ca2b7a76f86b47',
|
|
119
|
+
parity: 0,
|
|
120
|
+
result: '9534f8dc8c6deda2dc007655981c78b49c5d96c778fbf363462a11ec9dfd948c',
|
|
121
|
+
},
|
|
122
|
+
];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
export interface CacheEntry {
|
|
3
|
+
pubKey: string;
|
|
4
|
+
dataRef: WeakRef<Buffer>;
|
|
5
|
+
signature: Buffer;
|
|
6
|
+
}
|
|
7
|
+
export declare class AdvancedSignatureManager {
|
|
8
|
+
private static instance;
|
|
9
|
+
/**
|
|
10
|
+
* Map to index cache entries by signer public key.
|
|
11
|
+
* Key: Public Key (string)
|
|
12
|
+
* Value: Set of CacheEntries
|
|
13
|
+
*/
|
|
14
|
+
private cacheBySigner;
|
|
15
|
+
/**
|
|
16
|
+
* FinalizationRegistry to clean up cache entries when their data buffers are garbage collected.
|
|
17
|
+
*/
|
|
18
|
+
private registry;
|
|
19
|
+
private constructor();
|
|
20
|
+
static getInstance(): AdvancedSignatureManager;
|
|
21
|
+
/**
|
|
22
|
+
* Adds (caches) the signature for the given data buffer and signer public key.
|
|
23
|
+
* @param pubKey The signer's public key.
|
|
24
|
+
* @param data The data buffer.
|
|
25
|
+
* @param signature The signature buffer.
|
|
26
|
+
*/
|
|
27
|
+
addSignature(pubKey: string, data: Buffer, signature: Buffer): Buffer;
|
|
28
|
+
/**
|
|
29
|
+
* Retrieves the signature for the given data buffer and signer public key.
|
|
30
|
+
* @param pubKey The signer's public key.
|
|
31
|
+
* @param data The data buffer.
|
|
32
|
+
* @returns The signature buffer if found; otherwise, undefined.
|
|
33
|
+
*/
|
|
34
|
+
getSignature(pubKey: string, data: Buffer): Buffer | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Use with caution as it removes all cached signatures for all signers.
|
|
37
|
+
*/
|
|
38
|
+
clearCache(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Clears the cache for a specific signer.
|
|
41
|
+
* @param pubKey The signer's public key.
|
|
42
|
+
*/
|
|
43
|
+
clearCacheForSigner(pubKey: string): void;
|
|
44
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
exports.AdvancedSignatureManager = void 0;
|
|
4
|
+
class AdvancedSignatureManager {
|
|
5
|
+
static instance;
|
|
6
|
+
/**
|
|
7
|
+
* Map to index cache entries by signer public key.
|
|
8
|
+
* Key: Public Key (string)
|
|
9
|
+
* Value: Set of CacheEntries
|
|
10
|
+
*/
|
|
11
|
+
cacheBySigner = new Map();
|
|
12
|
+
/**
|
|
13
|
+
* FinalizationRegistry to clean up cache entries when their data buffers are garbage collected.
|
|
14
|
+
*/
|
|
15
|
+
registry;
|
|
16
|
+
constructor() {
|
|
17
|
+
this.registry = new FinalizationRegistry(entry => {
|
|
18
|
+
// Remove the entry directly using its pubKey
|
|
19
|
+
const set = this.cacheBySigner.get(entry.pubKey);
|
|
20
|
+
if (set) {
|
|
21
|
+
set.delete(entry);
|
|
22
|
+
// Clean up the set if it's empty
|
|
23
|
+
if (set.size === 0) {
|
|
24
|
+
this.cacheBySigner.delete(entry.pubKey);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
// Singleton instance accessor
|
|
30
|
+
static getInstance() {
|
|
31
|
+
if (!AdvancedSignatureManager.instance) {
|
|
32
|
+
AdvancedSignatureManager.instance = new AdvancedSignatureManager();
|
|
33
|
+
}
|
|
34
|
+
return AdvancedSignatureManager.instance;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Adds (caches) the signature for the given data buffer and signer public key.
|
|
38
|
+
* @param pubKey The signer's public key.
|
|
39
|
+
* @param data The data buffer.
|
|
40
|
+
* @param signature The signature buffer.
|
|
41
|
+
*/
|
|
42
|
+
addSignature(pubKey, data, signature) {
|
|
43
|
+
const entry = {
|
|
44
|
+
pubKey,
|
|
45
|
+
dataRef: new WeakRef(data),
|
|
46
|
+
signature,
|
|
47
|
+
};
|
|
48
|
+
if (!this.cacheBySigner.has(pubKey)) {
|
|
49
|
+
this.cacheBySigner.set(pubKey, new Set());
|
|
50
|
+
}
|
|
51
|
+
const set = this.cacheBySigner.get(pubKey);
|
|
52
|
+
set.add(entry);
|
|
53
|
+
// Register the data buffer with the FinalizationRegistry.
|
|
54
|
+
this.registry.register(data, entry);
|
|
55
|
+
return signature;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Retrieves the signature for the given data buffer and signer public key.
|
|
59
|
+
* @param pubKey The signer's public key.
|
|
60
|
+
* @param data The data buffer.
|
|
61
|
+
* @returns The signature buffer if found; otherwise, undefined.
|
|
62
|
+
*/
|
|
63
|
+
getSignature(pubKey, data) {
|
|
64
|
+
const set = this.cacheBySigner.get(pubKey);
|
|
65
|
+
if (!set) return undefined;
|
|
66
|
+
for (const entry of set) {
|
|
67
|
+
const cachedData = entry.dataRef.deref();
|
|
68
|
+
if (cachedData && cachedData.equals(data)) {
|
|
69
|
+
return entry.signature;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Use with caution as it removes all cached signatures for all signers.
|
|
76
|
+
*/
|
|
77
|
+
clearCache() {
|
|
78
|
+
this.cacheBySigner.clear();
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Clears the cache for a specific signer.
|
|
82
|
+
* @param pubKey The signer's public key.
|
|
83
|
+
*/
|
|
84
|
+
clearCacheForSigner(pubKey) {
|
|
85
|
+
this.cacheBySigner.delete(pubKey);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.AdvancedSignatureManager = AdvancedSignatureManager;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { BIP32Interface } from 'bip32';
|
|
2
|
+
import { ECPairInterface } from 'ecpair';
|
|
3
|
+
import { Signer, SignerAlternative, SignerAsync } from '../psbt.js';
|
|
4
|
+
export declare function hookSigner(keyPair: Signer | SignerAlternative | SignerAsync | BIP32Interface | ECPairInterface): void;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
exports.hookSigner = void 0;
|
|
4
|
+
const SignatureManager_js_1 = require('./SignatureManager.js');
|
|
5
|
+
const AdvancedSignatureManager_js_1 = require('./AdvancedSignatureManager.js');
|
|
6
|
+
const advancedSignatureManager =
|
|
7
|
+
AdvancedSignatureManager_js_1.AdvancedSignatureManager.getInstance();
|
|
8
|
+
function getPublicKey(keyPair) {
|
|
9
|
+
if (keyPair.publicKey && Buffer.isBuffer(keyPair.publicKey)) {
|
|
10
|
+
return keyPair.publicKey.toString('hex');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function hookKeyPair(keyPair) {
|
|
14
|
+
const oldSign = keyPair.sign;
|
|
15
|
+
if (oldSign) {
|
|
16
|
+
keyPair.sign = new Proxy(oldSign, {
|
|
17
|
+
apply: function (target, thisArg, argumentsList) {
|
|
18
|
+
const publicKey = getPublicKey(keyPair);
|
|
19
|
+
const hash = argumentsList[0];
|
|
20
|
+
if (publicKey) {
|
|
21
|
+
let possibleSignature =
|
|
22
|
+
advancedSignatureManager.getSignature(publicKey, hash);
|
|
23
|
+
if (!possibleSignature) {
|
|
24
|
+
possibleSignature =
|
|
25
|
+
advancedSignatureManager.addSignature(
|
|
26
|
+
publicKey,
|
|
27
|
+
hash,
|
|
28
|
+
Reflect.apply(target, thisArg, argumentsList),
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return possibleSignature;
|
|
32
|
+
} else {
|
|
33
|
+
let possibleSignature =
|
|
34
|
+
keyPair.signatureManager.getSignature(hash);
|
|
35
|
+
if (!possibleSignature) {
|
|
36
|
+
possibleSignature =
|
|
37
|
+
keyPair.signatureManager.addSignature(
|
|
38
|
+
hash,
|
|
39
|
+
Reflect.apply(target, thisArg, argumentsList),
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
return possibleSignature;
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
const oldSignSchnorr = keyPair.signSchnorr;
|
|
48
|
+
if (oldSignSchnorr) {
|
|
49
|
+
keyPair.signSchnorr = new Proxy(oldSignSchnorr, {
|
|
50
|
+
apply: function (target, thisArg, argumentsList) {
|
|
51
|
+
const publicKey = getPublicKey(keyPair);
|
|
52
|
+
const hash = argumentsList[0];
|
|
53
|
+
if (publicKey) {
|
|
54
|
+
let possibleSignature =
|
|
55
|
+
advancedSignatureManager.getSignature(publicKey, hash);
|
|
56
|
+
if (!possibleSignature) {
|
|
57
|
+
possibleSignature =
|
|
58
|
+
advancedSignatureManager.addSignature(
|
|
59
|
+
publicKey,
|
|
60
|
+
hash,
|
|
61
|
+
Reflect.apply(target, thisArg, argumentsList),
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
return possibleSignature;
|
|
65
|
+
} else {
|
|
66
|
+
let possibleSignature =
|
|
67
|
+
keyPair.signatureManager.getSignature(hash);
|
|
68
|
+
if (!possibleSignature) {
|
|
69
|
+
possibleSignature =
|
|
70
|
+
keyPair.signatureManager.addSignature(
|
|
71
|
+
hash,
|
|
72
|
+
Reflect.apply(target, thisArg, argumentsList),
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
return possibleSignature;
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function hookSigner(keyPair) {
|
|
82
|
+
const newKeypair = keyPair;
|
|
83
|
+
if (!newKeypair.hasHook) {
|
|
84
|
+
newKeypair.hasHook = true;
|
|
85
|
+
newKeypair.signatureManager =
|
|
86
|
+
new SignatureManager_js_1.SignatureManager();
|
|
87
|
+
hookKeyPair(newKeypair);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
exports.hookSigner = hookSigner;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
export interface CacheEntry {
|
|
3
|
+
length: number;
|
|
4
|
+
dataRef: WeakRef<Buffer>;
|
|
5
|
+
signature: Buffer;
|
|
6
|
+
}
|
|
7
|
+
export declare class SignatureManager {
|
|
8
|
+
/**
|
|
9
|
+
* Map to index cache entries by buffer length.
|
|
10
|
+
* Key: Buffer length
|
|
11
|
+
* Value: Set of CacheEntries with that buffer length
|
|
12
|
+
*/
|
|
13
|
+
private cacheByLength;
|
|
14
|
+
/**
|
|
15
|
+
* FinalizationRegistry to clean up cache entries when their data buffers are garbage collected.
|
|
16
|
+
*/
|
|
17
|
+
private registry;
|
|
18
|
+
constructor();
|
|
19
|
+
/**
|
|
20
|
+
* Adds (caches) the signature for the given data buffer.
|
|
21
|
+
* @param data The data buffer.
|
|
22
|
+
* @param signature The signature buffer.
|
|
23
|
+
*/
|
|
24
|
+
addSignature(data: Buffer, signature: Buffer): Buffer;
|
|
25
|
+
/**
|
|
26
|
+
* Retrieves the signature for the given data buffer.
|
|
27
|
+
* @param data The data buffer.
|
|
28
|
+
* @returns The signature buffer if found; otherwise, undefined.
|
|
29
|
+
*/
|
|
30
|
+
getSignature(data: Buffer): Buffer | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Use with caution as it removes all cached signatures.
|
|
33
|
+
*/
|
|
34
|
+
clearCache(): void;
|
|
35
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
exports.SignatureManager = void 0;
|
|
4
|
+
class SignatureManager {
|
|
5
|
+
/**
|
|
6
|
+
* Map to index cache entries by buffer length.
|
|
7
|
+
* Key: Buffer length
|
|
8
|
+
* Value: Set of CacheEntries with that buffer length
|
|
9
|
+
*/
|
|
10
|
+
cacheByLength = new Map();
|
|
11
|
+
/**
|
|
12
|
+
* FinalizationRegistry to clean up cache entries when their data buffers are garbage collected.
|
|
13
|
+
*/
|
|
14
|
+
registry;
|
|
15
|
+
constructor() {
|
|
16
|
+
this.registry = new FinalizationRegistry(entry => {
|
|
17
|
+
const set = this.cacheByLength.get(entry.length);
|
|
18
|
+
if (set) {
|
|
19
|
+
set.delete(entry);
|
|
20
|
+
// Clean up the set if it's empty
|
|
21
|
+
if (set.size === 0) {
|
|
22
|
+
this.cacheByLength.delete(entry.length);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Adds (caches) the signature for the given data buffer.
|
|
29
|
+
* @param data The data buffer.
|
|
30
|
+
* @param signature The signature buffer.
|
|
31
|
+
*/
|
|
32
|
+
addSignature(data, signature) {
|
|
33
|
+
const length = data.length;
|
|
34
|
+
const entry = {
|
|
35
|
+
length,
|
|
36
|
+
dataRef: new WeakRef(data),
|
|
37
|
+
signature,
|
|
38
|
+
};
|
|
39
|
+
if (!this.cacheByLength.has(length)) {
|
|
40
|
+
this.cacheByLength.set(length, new Set());
|
|
41
|
+
}
|
|
42
|
+
const set = this.cacheByLength.get(length);
|
|
43
|
+
set.add(entry);
|
|
44
|
+
// Register the data buffer with the FinalizationRegistry.
|
|
45
|
+
this.registry.register(data, entry);
|
|
46
|
+
return signature;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Retrieves the signature for the given data buffer.
|
|
50
|
+
* @param data The data buffer.
|
|
51
|
+
* @returns The signature buffer if found; otherwise, undefined.
|
|
52
|
+
*/
|
|
53
|
+
getSignature(data) {
|
|
54
|
+
const length = data.length;
|
|
55
|
+
const set = this.cacheByLength.get(length);
|
|
56
|
+
if (!set) return undefined;
|
|
57
|
+
for (const entry of set) {
|
|
58
|
+
const cachedData = entry.dataRef.deref();
|
|
59
|
+
if (cachedData && cachedData.equals(data)) {
|
|
60
|
+
return entry.signature;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Use with caution as it removes all cached signatures.
|
|
67
|
+
*/
|
|
68
|
+
clearCache() {
|
|
69
|
+
this.cacheByLength.clear();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.SignatureManager = SignatureManager;
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as address from './address';
|
|
2
|
+
import * as crypto from './crypto';
|
|
3
|
+
import * as networks from './networks';
|
|
4
|
+
import * as payments from './payments';
|
|
5
|
+
import * as script from './script';
|
|
6
|
+
import { PsbtInput as _PsbtInput, PsbtInputUpdate as _PsbtInputUpdate, PsbtOutput as _PsbtOutput, TapBip32Derivation as _TapBip32Derivation, TapInternalKey as _TapInternalKey, TapKeySig as _TapKeySig, TapLeaf as _TapLeaf, TapLeafScript as _TapLeafScript, TapMerkleRoot as _TapMerkleRoot, TapScriptSig as _TapScriptSig, TapTree as _TapTree } from 'bip174/src/lib/interfaces';
|
|
7
|
+
export { address, crypto, networks, payments, script };
|
|
8
|
+
export { Block } from './block';
|
|
9
|
+
/** @hidden */
|
|
10
|
+
export { TaggedHashPrefix } from './crypto';
|
|
11
|
+
export * from './psbt';
|
|
12
|
+
/** @hidden */
|
|
13
|
+
export { OPS as opcodes } from './ops';
|
|
14
|
+
export { Transaction } from './transaction';
|
|
15
|
+
/** @hidden */
|
|
16
|
+
export { Network } from './networks';
|
|
17
|
+
/** @hidden */
|
|
18
|
+
export { Payment, PaymentCreator, PaymentOpts, Stack, StackElement, } from './payments';
|
|
19
|
+
export { Input as TxInput, Output as TxOutput } from './transaction';
|
|
20
|
+
export { initEccLib } from './ecc_lib';
|
|
21
|
+
export interface PsbtInput extends _PsbtInput {
|
|
22
|
+
}
|
|
23
|
+
export interface PsbtOutput extends _PsbtOutput {
|
|
24
|
+
}
|
|
25
|
+
export interface TapInternalKey extends _TapInternalKey {
|
|
26
|
+
}
|
|
27
|
+
export interface TapLeaf extends _TapLeaf {
|
|
28
|
+
}
|
|
29
|
+
export interface TapScriptSig extends _TapScriptSig {
|
|
30
|
+
}
|
|
31
|
+
export interface TapKeySig extends _TapKeySig {
|
|
32
|
+
}
|
|
33
|
+
export interface TapTree extends _TapTree {
|
|
34
|
+
}
|
|
35
|
+
export interface TapMerkleRoot extends _TapMerkleRoot {
|
|
36
|
+
}
|
|
37
|
+
export interface TapLeafScript extends _TapLeafScript {
|
|
38
|
+
}
|
|
39
|
+
export interface TapBip32Derivation extends _TapBip32Derivation {
|
|
40
|
+
}
|
|
41
|
+
export interface PsbtInputUpdate extends _PsbtInputUpdate {
|
|
42
|
+
}
|