@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/bip66.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// Reference https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki
|
|
3
|
+
// Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S]
|
|
4
|
+
// NOTE: SIGHASH byte ignored AND restricted, truncate before use
|
|
5
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
6
|
+
exports.encode = exports.decode = exports.check = void 0;
|
|
7
|
+
function check(buffer) {
|
|
8
|
+
if (buffer.length < 8) return false;
|
|
9
|
+
if (buffer.length > 72) return false;
|
|
10
|
+
if (buffer[0] !== 0x30) return false;
|
|
11
|
+
if (buffer[1] !== buffer.length - 2) return false;
|
|
12
|
+
if (buffer[2] !== 0x02) return false;
|
|
13
|
+
const lenR = buffer[3];
|
|
14
|
+
if (lenR === 0) return false;
|
|
15
|
+
if (5 + lenR >= buffer.length) return false;
|
|
16
|
+
if (buffer[4 + lenR] !== 0x02) return false;
|
|
17
|
+
const lenS = buffer[5 + lenR];
|
|
18
|
+
if (lenS === 0) return false;
|
|
19
|
+
if (6 + lenR + lenS !== buffer.length) return false;
|
|
20
|
+
if (buffer[4] & 0x80) return false;
|
|
21
|
+
if (lenR > 1 && buffer[4] === 0x00 && !(buffer[5] & 0x80)) return false;
|
|
22
|
+
if (buffer[lenR + 6] & 0x80) return false;
|
|
23
|
+
if (lenS > 1 && buffer[lenR + 6] === 0x00 && !(buffer[lenR + 7] & 0x80))
|
|
24
|
+
return false;
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
exports.check = check;
|
|
28
|
+
function decode(buffer) {
|
|
29
|
+
if (buffer.length < 8) throw new Error('DER sequence length is too short');
|
|
30
|
+
if (buffer.length > 72) throw new Error('DER sequence length is too long');
|
|
31
|
+
if (buffer[0] !== 0x30) throw new Error('Expected DER sequence');
|
|
32
|
+
if (buffer[1] !== buffer.length - 2)
|
|
33
|
+
throw new Error('DER sequence length is invalid');
|
|
34
|
+
if (buffer[2] !== 0x02) throw new Error('Expected DER integer');
|
|
35
|
+
const lenR = buffer[3];
|
|
36
|
+
if (lenR === 0) throw new Error('R length is zero');
|
|
37
|
+
if (5 + lenR >= buffer.length) throw new Error('R length is too long');
|
|
38
|
+
if (buffer[4 + lenR] !== 0x02) throw new Error('Expected DER integer (2)');
|
|
39
|
+
const lenS = buffer[5 + lenR];
|
|
40
|
+
if (lenS === 0) throw new Error('S length is zero');
|
|
41
|
+
if (6 + lenR + lenS !== buffer.length)
|
|
42
|
+
throw new Error('S length is invalid');
|
|
43
|
+
if (buffer[4] & 0x80) throw new Error('R value is negative');
|
|
44
|
+
if (lenR > 1 && buffer[4] === 0x00 && !(buffer[5] & 0x80))
|
|
45
|
+
throw new Error('R value excessively padded');
|
|
46
|
+
if (buffer[lenR + 6] & 0x80) throw new Error('S value is negative');
|
|
47
|
+
if (lenS > 1 && buffer[lenR + 6] === 0x00 && !(buffer[lenR + 7] & 0x80))
|
|
48
|
+
throw new Error('S value excessively padded');
|
|
49
|
+
// non-BIP66 - extract R, S values
|
|
50
|
+
return {
|
|
51
|
+
r: buffer.slice(4, 4 + lenR),
|
|
52
|
+
s: buffer.slice(6 + lenR),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
exports.decode = decode;
|
|
56
|
+
/*
|
|
57
|
+
* Expects r and s to be positive DER integers.
|
|
58
|
+
*
|
|
59
|
+
* The DER format uses the most significant bit as a sign bit (& 0x80).
|
|
60
|
+
* If the significant bit is set AND the integer is positive, a 0x00 is prepended.
|
|
61
|
+
*
|
|
62
|
+
* Examples:
|
|
63
|
+
*
|
|
64
|
+
* 0 => 0x00
|
|
65
|
+
* 1 => 0x01
|
|
66
|
+
* -1 => 0xff
|
|
67
|
+
* 127 => 0x7f
|
|
68
|
+
* -127 => 0x81
|
|
69
|
+
* 128 => 0x0080
|
|
70
|
+
* -128 => 0x80
|
|
71
|
+
* 255 => 0x00ff
|
|
72
|
+
* -255 => 0xff01
|
|
73
|
+
* 16300 => 0x3fac
|
|
74
|
+
* -16300 => 0xc054
|
|
75
|
+
* 62300 => 0x00f35c
|
|
76
|
+
* -62300 => 0xff0ca4
|
|
77
|
+
*/
|
|
78
|
+
function encode(r, s) {
|
|
79
|
+
const lenR = r.length;
|
|
80
|
+
const lenS = s.length;
|
|
81
|
+
if (lenR === 0) throw new Error('R length is zero');
|
|
82
|
+
if (lenS === 0) throw new Error('S length is zero');
|
|
83
|
+
if (lenR > 33) throw new Error('R length is too long');
|
|
84
|
+
if (lenS > 33) throw new Error('S length is too long');
|
|
85
|
+
if (r[0] & 0x80) throw new Error('R value is negative');
|
|
86
|
+
if (s[0] & 0x80) throw new Error('S value is negative');
|
|
87
|
+
if (lenR > 1 && r[0] === 0x00 && !(r[1] & 0x80))
|
|
88
|
+
throw new Error('R value excessively padded');
|
|
89
|
+
if (lenS > 1 && s[0] === 0x00 && !(s[1] & 0x80))
|
|
90
|
+
throw new Error('S value excessively padded');
|
|
91
|
+
const signature = Buffer.allocUnsafe(6 + lenR + lenS);
|
|
92
|
+
// 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S]
|
|
93
|
+
signature[0] = 0x30;
|
|
94
|
+
signature[1] = signature.length - 2;
|
|
95
|
+
signature[2] = 0x02;
|
|
96
|
+
signature[3] = r.length;
|
|
97
|
+
r.copy(signature, 4);
|
|
98
|
+
signature[4 + lenR] = 0x02;
|
|
99
|
+
signature[5 + lenR] = s.length;
|
|
100
|
+
s.copy(signature, 6 + lenR);
|
|
101
|
+
return signature;
|
|
102
|
+
}
|
|
103
|
+
exports.encode = encode;
|
package/src/block.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Transaction } from './transaction';
|
|
3
|
+
export declare class Block {
|
|
4
|
+
version: number;
|
|
5
|
+
prevHash?: Buffer;
|
|
6
|
+
merkleRoot?: Buffer;
|
|
7
|
+
timestamp: number;
|
|
8
|
+
witnessCommit?: Buffer;
|
|
9
|
+
bits: number;
|
|
10
|
+
nonce: number;
|
|
11
|
+
transactions?: Transaction[];
|
|
12
|
+
static fromBuffer(buffer: Buffer): Block;
|
|
13
|
+
static fromHex(hex: string): Block;
|
|
14
|
+
static calculateTarget(bits: number): Buffer;
|
|
15
|
+
static calculateMerkleRoot(transactions: Transaction[], forWitness?: boolean): Buffer;
|
|
16
|
+
getWitnessCommit(): Buffer | null;
|
|
17
|
+
hasWitnessCommit(): boolean;
|
|
18
|
+
hasWitness(): boolean;
|
|
19
|
+
weight(): number;
|
|
20
|
+
byteLength(headersOnly?: boolean, allowWitness?: boolean): number;
|
|
21
|
+
getHash(): Buffer;
|
|
22
|
+
getId(): string;
|
|
23
|
+
getUTCDate(): Date;
|
|
24
|
+
toBuffer(headersOnly?: boolean): Buffer;
|
|
25
|
+
toHex(headersOnly?: boolean): string;
|
|
26
|
+
checkTxRoots(): boolean;
|
|
27
|
+
checkProofOfWork(): boolean;
|
|
28
|
+
private __checkMerkleRoot;
|
|
29
|
+
private __checkWitnessCommit;
|
|
30
|
+
}
|
package/src/block.js
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
exports.Block = void 0;
|
|
4
|
+
const bufferutils_1 = require('./bufferutils');
|
|
5
|
+
const bcrypto = require('./crypto');
|
|
6
|
+
const merkle_1 = require('./merkle');
|
|
7
|
+
const transaction_1 = require('./transaction');
|
|
8
|
+
const types = require('./types');
|
|
9
|
+
const { typeforce } = types;
|
|
10
|
+
const errorMerkleNoTxes = new TypeError(
|
|
11
|
+
'Cannot compute merkle root for zero transactions',
|
|
12
|
+
);
|
|
13
|
+
const errorWitnessNotSegwit = new TypeError(
|
|
14
|
+
'Cannot compute witness commit for non-segwit block',
|
|
15
|
+
);
|
|
16
|
+
class Block {
|
|
17
|
+
version = 1;
|
|
18
|
+
prevHash = undefined;
|
|
19
|
+
merkleRoot = undefined;
|
|
20
|
+
timestamp = 0;
|
|
21
|
+
witnessCommit = undefined;
|
|
22
|
+
bits = 0;
|
|
23
|
+
nonce = 0;
|
|
24
|
+
transactions = undefined;
|
|
25
|
+
static fromBuffer(buffer) {
|
|
26
|
+
if (buffer.length < 80)
|
|
27
|
+
throw new Error('Buffer too small (< 80 bytes)');
|
|
28
|
+
const bufferReader = new bufferutils_1.BufferReader(buffer);
|
|
29
|
+
const block = new Block();
|
|
30
|
+
block.version = bufferReader.readInt32();
|
|
31
|
+
block.prevHash = bufferReader.readSlice(32);
|
|
32
|
+
block.merkleRoot = bufferReader.readSlice(32);
|
|
33
|
+
block.timestamp = bufferReader.readUInt32();
|
|
34
|
+
block.bits = bufferReader.readUInt32();
|
|
35
|
+
block.nonce = bufferReader.readUInt32();
|
|
36
|
+
if (buffer.length === 80) return block;
|
|
37
|
+
const readTransaction = () => {
|
|
38
|
+
const tx = transaction_1.Transaction.fromBuffer(
|
|
39
|
+
bufferReader.buffer.slice(bufferReader.offset),
|
|
40
|
+
true,
|
|
41
|
+
);
|
|
42
|
+
bufferReader.offset += tx.byteLength();
|
|
43
|
+
return tx;
|
|
44
|
+
};
|
|
45
|
+
const nTransactions = bufferReader.readVarInt();
|
|
46
|
+
block.transactions = [];
|
|
47
|
+
for (let i = 0; i < nTransactions; ++i) {
|
|
48
|
+
const tx = readTransaction();
|
|
49
|
+
block.transactions.push(tx);
|
|
50
|
+
}
|
|
51
|
+
const witnessCommit = block.getWitnessCommit();
|
|
52
|
+
// This Block contains a witness commit
|
|
53
|
+
if (witnessCommit) block.witnessCommit = witnessCommit;
|
|
54
|
+
return block;
|
|
55
|
+
}
|
|
56
|
+
static fromHex(hex) {
|
|
57
|
+
return Block.fromBuffer(Buffer.from(hex, 'hex'));
|
|
58
|
+
}
|
|
59
|
+
static calculateTarget(bits) {
|
|
60
|
+
const exponent = ((bits & 0xff000000) >> 24) - 3;
|
|
61
|
+
const mantissa = bits & 0x007fffff;
|
|
62
|
+
const target = Buffer.alloc(32, 0);
|
|
63
|
+
target.writeUIntBE(mantissa, 29 - exponent, 3);
|
|
64
|
+
return target;
|
|
65
|
+
}
|
|
66
|
+
static calculateMerkleRoot(transactions, forWitness) {
|
|
67
|
+
typeforce([{ getHash: types.Function }], transactions);
|
|
68
|
+
if (transactions.length === 0) throw errorMerkleNoTxes;
|
|
69
|
+
if (forWitness && !txesHaveWitnessCommit(transactions))
|
|
70
|
+
throw errorWitnessNotSegwit;
|
|
71
|
+
const hashes = transactions.map(transaction =>
|
|
72
|
+
transaction.getHash(forWitness),
|
|
73
|
+
);
|
|
74
|
+
const rootHash = (0, merkle_1.fastMerkleRoot)(hashes, bcrypto.hash256);
|
|
75
|
+
return forWitness
|
|
76
|
+
? bcrypto.hash256(
|
|
77
|
+
Buffer.concat([rootHash, transactions[0].ins[0].witness[0]]),
|
|
78
|
+
)
|
|
79
|
+
: rootHash;
|
|
80
|
+
}
|
|
81
|
+
getWitnessCommit() {
|
|
82
|
+
if (!txesHaveWitnessCommit(this.transactions)) return null;
|
|
83
|
+
// The merkle root for the witness data is in an OP_RETURN output.
|
|
84
|
+
// There is no rule for the index of the output, so use filter to find it.
|
|
85
|
+
// The root is prepended with 0xaa21a9ed so check for 0x6a24aa21a9ed
|
|
86
|
+
// If multiple commits are found, the output with highest index is assumed.
|
|
87
|
+
const witnessCommits = this.transactions[0].outs
|
|
88
|
+
.filter(out =>
|
|
89
|
+
out.script
|
|
90
|
+
.slice(0, 6)
|
|
91
|
+
.equals(Buffer.from('6a24aa21a9ed', 'hex')),
|
|
92
|
+
)
|
|
93
|
+
.map(out => out.script.slice(6, 38));
|
|
94
|
+
if (witnessCommits.length === 0) return null;
|
|
95
|
+
// Use the commit with the highest output (should only be one though)
|
|
96
|
+
const result = witnessCommits[witnessCommits.length - 1];
|
|
97
|
+
if (!(result instanceof Buffer && result.length === 32)) return null;
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
hasWitnessCommit() {
|
|
101
|
+
if (
|
|
102
|
+
this.witnessCommit instanceof Buffer &&
|
|
103
|
+
this.witnessCommit.length === 32
|
|
104
|
+
)
|
|
105
|
+
return true;
|
|
106
|
+
if (this.getWitnessCommit() !== null) return true;
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
hasWitness() {
|
|
110
|
+
return anyTxHasWitness(this.transactions);
|
|
111
|
+
}
|
|
112
|
+
weight() {
|
|
113
|
+
const base = this.byteLength(false, false);
|
|
114
|
+
const total = this.byteLength(false, true);
|
|
115
|
+
return base * 3 + total;
|
|
116
|
+
}
|
|
117
|
+
byteLength(headersOnly, allowWitness = true) {
|
|
118
|
+
if (headersOnly || !this.transactions) return 80;
|
|
119
|
+
return (
|
|
120
|
+
80 +
|
|
121
|
+
bufferutils_1.varuint.encodingLength(this.transactions.length) +
|
|
122
|
+
this.transactions.reduce(
|
|
123
|
+
(a, x) => a + x.byteLength(allowWitness),
|
|
124
|
+
0,
|
|
125
|
+
)
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
getHash() {
|
|
129
|
+
return bcrypto.hash256(this.toBuffer(true));
|
|
130
|
+
}
|
|
131
|
+
getId() {
|
|
132
|
+
return (0, bufferutils_1.reverseBuffer)(this.getHash()).toString('hex');
|
|
133
|
+
}
|
|
134
|
+
getUTCDate() {
|
|
135
|
+
const date = new Date(0); // epoch
|
|
136
|
+
date.setUTCSeconds(this.timestamp);
|
|
137
|
+
return date;
|
|
138
|
+
}
|
|
139
|
+
// TODO: buffer, offset compatibility
|
|
140
|
+
toBuffer(headersOnly) {
|
|
141
|
+
const buffer = Buffer.allocUnsafe(this.byteLength(headersOnly));
|
|
142
|
+
const bufferWriter = new bufferutils_1.BufferWriter(buffer);
|
|
143
|
+
bufferWriter.writeInt32(this.version);
|
|
144
|
+
bufferWriter.writeSlice(this.prevHash);
|
|
145
|
+
bufferWriter.writeSlice(this.merkleRoot);
|
|
146
|
+
bufferWriter.writeUInt32(this.timestamp);
|
|
147
|
+
bufferWriter.writeUInt32(this.bits);
|
|
148
|
+
bufferWriter.writeUInt32(this.nonce);
|
|
149
|
+
if (headersOnly || !this.transactions) return buffer;
|
|
150
|
+
bufferutils_1.varuint.encode(
|
|
151
|
+
this.transactions.length,
|
|
152
|
+
buffer,
|
|
153
|
+
bufferWriter.offset,
|
|
154
|
+
);
|
|
155
|
+
bufferWriter.offset += bufferutils_1.varuint.encode.bytes;
|
|
156
|
+
this.transactions.forEach(tx => {
|
|
157
|
+
const txSize = tx.byteLength(); // TODO: extract from toBuffer?
|
|
158
|
+
tx.toBuffer(buffer, bufferWriter.offset);
|
|
159
|
+
bufferWriter.offset += txSize;
|
|
160
|
+
});
|
|
161
|
+
return buffer;
|
|
162
|
+
}
|
|
163
|
+
toHex(headersOnly) {
|
|
164
|
+
return this.toBuffer(headersOnly).toString('hex');
|
|
165
|
+
}
|
|
166
|
+
checkTxRoots() {
|
|
167
|
+
// If the Block has segwit transactions but no witness commit,
|
|
168
|
+
// there's no way it can be valid, so fail the check.
|
|
169
|
+
const hasWitnessCommit = this.hasWitnessCommit();
|
|
170
|
+
if (!hasWitnessCommit && this.hasWitness()) return false;
|
|
171
|
+
return (
|
|
172
|
+
this.__checkMerkleRoot() &&
|
|
173
|
+
(hasWitnessCommit ? this.__checkWitnessCommit() : true)
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
checkProofOfWork() {
|
|
177
|
+
const hash = (0, bufferutils_1.reverseBuffer)(this.getHash());
|
|
178
|
+
const target = Block.calculateTarget(this.bits);
|
|
179
|
+
return hash.compare(target) <= 0;
|
|
180
|
+
}
|
|
181
|
+
__checkMerkleRoot() {
|
|
182
|
+
if (!this.transactions) throw errorMerkleNoTxes;
|
|
183
|
+
const actualMerkleRoot = Block.calculateMerkleRoot(this.transactions);
|
|
184
|
+
return this.merkleRoot.compare(actualMerkleRoot) === 0;
|
|
185
|
+
}
|
|
186
|
+
__checkWitnessCommit() {
|
|
187
|
+
if (!this.transactions) throw errorMerkleNoTxes;
|
|
188
|
+
if (!this.hasWitnessCommit()) throw errorWitnessNotSegwit;
|
|
189
|
+
const actualWitnessCommit = Block.calculateMerkleRoot(
|
|
190
|
+
this.transactions,
|
|
191
|
+
true,
|
|
192
|
+
);
|
|
193
|
+
return this.witnessCommit.compare(actualWitnessCommit) === 0;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
exports.Block = Block;
|
|
197
|
+
function txesHaveWitnessCommit(transactions) {
|
|
198
|
+
return (
|
|
199
|
+
transactions instanceof Array &&
|
|
200
|
+
transactions[0] &&
|
|
201
|
+
transactions[0].ins &&
|
|
202
|
+
transactions[0].ins instanceof Array &&
|
|
203
|
+
transactions[0].ins[0] &&
|
|
204
|
+
transactions[0].ins[0].witness &&
|
|
205
|
+
transactions[0].ins[0].witness instanceof Array &&
|
|
206
|
+
transactions[0].ins[0].witness.length > 0
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
function anyTxHasWitness(transactions) {
|
|
210
|
+
return (
|
|
211
|
+
transactions instanceof Array &&
|
|
212
|
+
transactions.some(
|
|
213
|
+
tx =>
|
|
214
|
+
typeof tx === 'object' &&
|
|
215
|
+
tx.ins instanceof Array &&
|
|
216
|
+
tx.ins.some(
|
|
217
|
+
input =>
|
|
218
|
+
typeof input === 'object' &&
|
|
219
|
+
input.witness instanceof Array &&
|
|
220
|
+
input.witness.length > 0,
|
|
221
|
+
),
|
|
222
|
+
)
|
|
223
|
+
);
|
|
224
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import * as varuint from 'varuint-bitcoin';
|
|
3
|
+
export { varuint };
|
|
4
|
+
export declare function readUInt64LE(buffer: Buffer, offset: number): number;
|
|
5
|
+
/**
|
|
6
|
+
* Writes a 64-bit unsigned integer in little-endian format to the specified buffer at the given offset.
|
|
7
|
+
*
|
|
8
|
+
* @param buffer - The buffer to write the value to.
|
|
9
|
+
* @param value - The 64-bit unsigned integer value to write.
|
|
10
|
+
* @param offset - The offset in the buffer where the value should be written.
|
|
11
|
+
* @returns The new offset after writing the value.
|
|
12
|
+
*/
|
|
13
|
+
export declare function writeUInt64LE(buffer: Buffer, value: number, offset: number): number;
|
|
14
|
+
/**
|
|
15
|
+
* Reverses the order of bytes in a buffer.
|
|
16
|
+
* @param buffer - The buffer to reverse.
|
|
17
|
+
* @returns A new buffer with the bytes reversed.
|
|
18
|
+
*/
|
|
19
|
+
export declare function reverseBuffer(buffer: Buffer): Buffer;
|
|
20
|
+
export declare function cloneBuffer(buffer: Buffer): Buffer;
|
|
21
|
+
/**
|
|
22
|
+
* Helper class for serialization of bitcoin data types into a pre-allocated buffer.
|
|
23
|
+
*/
|
|
24
|
+
export declare class BufferWriter {
|
|
25
|
+
buffer: Buffer;
|
|
26
|
+
offset: number;
|
|
27
|
+
constructor(buffer: Buffer, offset?: number);
|
|
28
|
+
static withCapacity(size: number): BufferWriter;
|
|
29
|
+
writeUInt8(i: number): void;
|
|
30
|
+
writeInt32(i: number): void;
|
|
31
|
+
writeUInt32(i: number): void;
|
|
32
|
+
writeUInt64(i: number): void;
|
|
33
|
+
writeVarInt(i: number): void;
|
|
34
|
+
writeSlice(slice: Buffer): void;
|
|
35
|
+
writeVarSlice(slice: Buffer): void;
|
|
36
|
+
writeVector(vector: Buffer[]): void;
|
|
37
|
+
end(): Buffer;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Helper class for reading of bitcoin data types from a buffer.
|
|
41
|
+
*/
|
|
42
|
+
export declare class BufferReader {
|
|
43
|
+
buffer: Buffer;
|
|
44
|
+
offset: number;
|
|
45
|
+
constructor(buffer: Buffer, offset?: number);
|
|
46
|
+
readUInt8(): number;
|
|
47
|
+
readInt32(): number;
|
|
48
|
+
readUInt32(): number;
|
|
49
|
+
readUInt64(): number;
|
|
50
|
+
readVarInt(): number;
|
|
51
|
+
readSlice(n: number): Buffer;
|
|
52
|
+
readVarSlice(): Buffer;
|
|
53
|
+
readVector(): Buffer[];
|
|
54
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
exports.BufferReader =
|
|
4
|
+
exports.BufferWriter =
|
|
5
|
+
exports.cloneBuffer =
|
|
6
|
+
exports.reverseBuffer =
|
|
7
|
+
exports.writeUInt64LE =
|
|
8
|
+
exports.readUInt64LE =
|
|
9
|
+
exports.varuint =
|
|
10
|
+
void 0;
|
|
11
|
+
const types = require('./types');
|
|
12
|
+
const varuint = require('varuint-bitcoin');
|
|
13
|
+
exports.varuint = varuint;
|
|
14
|
+
const { typeforce } = types;
|
|
15
|
+
// https://github.com/feross/buffer/blob/master/index.js#L1127
|
|
16
|
+
function verifuint(value, max) {
|
|
17
|
+
if (typeof value !== 'number')
|
|
18
|
+
throw new Error('cannot write a non-number as a number');
|
|
19
|
+
if (value < 0)
|
|
20
|
+
throw new Error(
|
|
21
|
+
'specified a negative value for writing an unsigned value',
|
|
22
|
+
);
|
|
23
|
+
if (value > max) throw new Error('RangeError: value out of range');
|
|
24
|
+
if (Math.floor(value) !== value)
|
|
25
|
+
throw new Error('value has a fractional component');
|
|
26
|
+
}
|
|
27
|
+
function readUInt64LE(buffer, offset) {
|
|
28
|
+
const a = buffer.readUInt32LE(offset);
|
|
29
|
+
let b = buffer.readUInt32LE(offset + 4);
|
|
30
|
+
b *= 0x100000000;
|
|
31
|
+
verifuint(b + a, 0x001fffffffffffff);
|
|
32
|
+
return b + a;
|
|
33
|
+
}
|
|
34
|
+
exports.readUInt64LE = readUInt64LE;
|
|
35
|
+
/**
|
|
36
|
+
* Writes a 64-bit unsigned integer in little-endian format to the specified buffer at the given offset.
|
|
37
|
+
*
|
|
38
|
+
* @param buffer - The buffer to write the value to.
|
|
39
|
+
* @param value - The 64-bit unsigned integer value to write.
|
|
40
|
+
* @param offset - The offset in the buffer where the value should be written.
|
|
41
|
+
* @returns The new offset after writing the value.
|
|
42
|
+
*/
|
|
43
|
+
function writeUInt64LE(buffer, value, offset) {
|
|
44
|
+
verifuint(value, 0x001fffffffffffff);
|
|
45
|
+
buffer.writeInt32LE(value & -1, offset);
|
|
46
|
+
buffer.writeUInt32LE(Math.floor(value / 0x100000000), offset + 4);
|
|
47
|
+
return offset + 8;
|
|
48
|
+
}
|
|
49
|
+
exports.writeUInt64LE = writeUInt64LE;
|
|
50
|
+
/**
|
|
51
|
+
* Reverses the order of bytes in a buffer.
|
|
52
|
+
* @param buffer - The buffer to reverse.
|
|
53
|
+
* @returns A new buffer with the bytes reversed.
|
|
54
|
+
*/
|
|
55
|
+
function reverseBuffer(buffer) {
|
|
56
|
+
if (buffer.length < 1) return buffer;
|
|
57
|
+
let j = buffer.length - 1;
|
|
58
|
+
let tmp = 0;
|
|
59
|
+
for (let i = 0; i < buffer.length / 2; i++) {
|
|
60
|
+
tmp = buffer[i];
|
|
61
|
+
buffer[i] = buffer[j];
|
|
62
|
+
buffer[j] = tmp;
|
|
63
|
+
j--;
|
|
64
|
+
}
|
|
65
|
+
return buffer;
|
|
66
|
+
}
|
|
67
|
+
exports.reverseBuffer = reverseBuffer;
|
|
68
|
+
function cloneBuffer(buffer) {
|
|
69
|
+
const clone = Buffer.allocUnsafe(buffer.length);
|
|
70
|
+
buffer.copy(clone);
|
|
71
|
+
return clone;
|
|
72
|
+
}
|
|
73
|
+
exports.cloneBuffer = cloneBuffer;
|
|
74
|
+
/**
|
|
75
|
+
* Helper class for serialization of bitcoin data types into a pre-allocated buffer.
|
|
76
|
+
*/
|
|
77
|
+
class BufferWriter {
|
|
78
|
+
buffer;
|
|
79
|
+
offset;
|
|
80
|
+
constructor(buffer, offset = 0) {
|
|
81
|
+
this.buffer = buffer;
|
|
82
|
+
this.offset = offset;
|
|
83
|
+
typeforce(types.tuple(types.Buffer, types.UInt32), [buffer, offset]);
|
|
84
|
+
}
|
|
85
|
+
static withCapacity(size) {
|
|
86
|
+
return new BufferWriter(Buffer.alloc(size));
|
|
87
|
+
}
|
|
88
|
+
writeUInt8(i) {
|
|
89
|
+
this.offset = this.buffer.writeUInt8(i, this.offset);
|
|
90
|
+
}
|
|
91
|
+
writeInt32(i) {
|
|
92
|
+
this.offset = this.buffer.writeInt32LE(i, this.offset);
|
|
93
|
+
}
|
|
94
|
+
writeUInt32(i) {
|
|
95
|
+
this.offset = this.buffer.writeUInt32LE(i, this.offset);
|
|
96
|
+
}
|
|
97
|
+
writeUInt64(i) {
|
|
98
|
+
this.offset = writeUInt64LE(this.buffer, i, this.offset);
|
|
99
|
+
}
|
|
100
|
+
writeVarInt(i) {
|
|
101
|
+
varuint.encode(i, this.buffer, this.offset);
|
|
102
|
+
this.offset += varuint.encode.bytes;
|
|
103
|
+
}
|
|
104
|
+
writeSlice(slice) {
|
|
105
|
+
if (this.buffer.length < this.offset + slice.length) {
|
|
106
|
+
throw new Error('Cannot write slice out of bounds');
|
|
107
|
+
}
|
|
108
|
+
this.offset += slice.copy(this.buffer, this.offset);
|
|
109
|
+
}
|
|
110
|
+
writeVarSlice(slice) {
|
|
111
|
+
this.writeVarInt(slice.length);
|
|
112
|
+
this.writeSlice(slice);
|
|
113
|
+
}
|
|
114
|
+
writeVector(vector) {
|
|
115
|
+
this.writeVarInt(vector.length);
|
|
116
|
+
vector.forEach(buf => this.writeVarSlice(buf));
|
|
117
|
+
}
|
|
118
|
+
end() {
|
|
119
|
+
if (this.buffer.length === this.offset) {
|
|
120
|
+
return this.buffer;
|
|
121
|
+
}
|
|
122
|
+
throw new Error(
|
|
123
|
+
`buffer size ${this.buffer.length}, offset ${this.offset}`,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
exports.BufferWriter = BufferWriter;
|
|
128
|
+
/**
|
|
129
|
+
* Helper class for reading of bitcoin data types from a buffer.
|
|
130
|
+
*/
|
|
131
|
+
class BufferReader {
|
|
132
|
+
buffer;
|
|
133
|
+
offset;
|
|
134
|
+
constructor(buffer, offset = 0) {
|
|
135
|
+
this.buffer = buffer;
|
|
136
|
+
this.offset = offset;
|
|
137
|
+
typeforce(types.tuple(types.Buffer, types.UInt32), [buffer, offset]);
|
|
138
|
+
}
|
|
139
|
+
readUInt8() {
|
|
140
|
+
const result = this.buffer.readUInt8(this.offset);
|
|
141
|
+
this.offset++;
|
|
142
|
+
return result;
|
|
143
|
+
}
|
|
144
|
+
readInt32() {
|
|
145
|
+
const result = this.buffer.readInt32LE(this.offset);
|
|
146
|
+
this.offset += 4;
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
readUInt32() {
|
|
150
|
+
const result = this.buffer.readUInt32LE(this.offset);
|
|
151
|
+
this.offset += 4;
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
readUInt64() {
|
|
155
|
+
const result = readUInt64LE(this.buffer, this.offset);
|
|
156
|
+
this.offset += 8;
|
|
157
|
+
return result;
|
|
158
|
+
}
|
|
159
|
+
readVarInt() {
|
|
160
|
+
const vi = varuint.decode(this.buffer, this.offset);
|
|
161
|
+
this.offset += varuint.decode.bytes;
|
|
162
|
+
return vi;
|
|
163
|
+
}
|
|
164
|
+
readSlice(n) {
|
|
165
|
+
if (this.buffer.length < this.offset + n) {
|
|
166
|
+
throw new Error('Cannot read slice out of bounds');
|
|
167
|
+
}
|
|
168
|
+
const result = this.buffer.slice(this.offset, this.offset + n);
|
|
169
|
+
this.offset += n;
|
|
170
|
+
return result;
|
|
171
|
+
}
|
|
172
|
+
readVarSlice() {
|
|
173
|
+
return this.readSlice(this.readVarInt());
|
|
174
|
+
}
|
|
175
|
+
readVector() {
|
|
176
|
+
const count = this.readVarInt();
|
|
177
|
+
const vector = [];
|
|
178
|
+
for (let i = 0; i < count; i++) vector.push(this.readVarSlice());
|
|
179
|
+
return vector;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
exports.BufferReader = BufferReader;
|
package/src/crypto.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
export declare function ripemd160(buffer: Buffer): Buffer;
|
|
3
|
+
export declare function sha1(buffer: Buffer): Buffer;
|
|
4
|
+
export declare function sha256(buffer: Buffer): Buffer;
|
|
5
|
+
export declare function hash160(buffer: Buffer): Buffer;
|
|
6
|
+
export declare function hash256(buffer: Buffer): Buffer;
|
|
7
|
+
export declare const TAGS: readonly ["BIP0340/challenge", "BIP0340/aux", "BIP0340/nonce", "TapLeaf", "TapBranch", "TapSighash", "TapTweak", "KeyAgg list", "KeyAgg coefficient"];
|
|
8
|
+
export type TaggedHashPrefix = typeof TAGS[number];
|
|
9
|
+
type TaggedHashPrefixes = {
|
|
10
|
+
[key in TaggedHashPrefix]: Buffer;
|
|
11
|
+
};
|
|
12
|
+
/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */
|
|
13
|
+
/**
|
|
14
|
+
* Defines the tagged hash prefixes used in the crypto module.
|
|
15
|
+
*/
|
|
16
|
+
export declare const TAGGED_HASH_PREFIXES: TaggedHashPrefixes;
|
|
17
|
+
export declare function taggedHash(prefix: TaggedHashPrefix, data: Buffer): Buffer;
|
|
18
|
+
export {};
|