@btc-vision/bitcoin 6.3.1 → 6.3.2
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/.babelrc +4 -0
- package/.gitattributes +2 -0
- package/.nyc_output/6368a5b2-daa5-4821-8ed0-b742d6fc7eab.json +1 -0
- package/.nyc_output/processinfo/6368a5b2-daa5-4821-8ed0-b742d6fc7eab.json +1 -0
- package/.nyc_output/processinfo/index.json +1 -0
- package/.prettierrc.json +12 -0
- package/CHANGELOG.md +403 -0
- package/CONTRIBUTING.md +83 -0
- package/browser/address.d.ts +16 -0
- package/{src → browser}/bip66.d.ts +6 -7
- package/{src → browser}/block.d.ts +29 -30
- package/{src → browser}/bufferutils.d.ts +34 -54
- package/browser/crypto/crypto.d.ts +1 -0
- package/{src → browser}/crypto.d.ts +13 -18
- package/browser/ecc_lib.d.ts +3 -0
- package/browser/hooks/AdvancedSignatureManager.d.ts +16 -0
- package/{src → browser}/hooks/HookedSigner.d.ts +4 -4
- package/browser/hooks/SignatureManager.d.ts +13 -0
- package/browser/index.d.ts +58 -0
- package/browser/index.js +2 -0
- package/browser/index.js.LICENSE.txt +14 -0
- package/browser/merkle.d.ts +1 -0
- package/browser/networks.d.ts +23 -0
- package/{src → browser}/ops.d.ts +126 -126
- package/browser/payments/bip341.d.ts +23 -0
- package/browser/payments/embed.d.ts +2 -0
- package/browser/payments/index.d.ts +41 -0
- package/{src → browser}/payments/lazy.d.ts +2 -2
- package/browser/payments/p2ms.d.ts +2 -0
- package/browser/payments/p2pk.d.ts +2 -0
- package/browser/payments/p2pkh.d.ts +2 -0
- package/browser/payments/p2sh.d.ts +2 -0
- package/browser/payments/p2tr.d.ts +2 -0
- package/browser/payments/p2wpkh.d.ts +2 -0
- package/browser/payments/p2wsh.d.ts +2 -0
- package/browser/psbt/bip371.d.ts +16 -0
- package/browser/psbt/psbtutils.d.ts +26 -0
- package/{src → browser}/psbt.d.ts +167 -238
- package/browser/push_data.d.ts +7 -0
- package/browser/script.d.ts +17 -0
- package/browser/script_number.d.ts +2 -0
- package/browser/script_signature.d.ts +7 -0
- package/{src → browser}/transaction.d.ts +48 -60
- package/{src → browser}/types.d.ts +37 -54
- package/build/address.d.ts +16 -0
- package/build/address.js +148 -0
- package/build/bip66.d.ts +6 -0
- package/build/bip66.js +99 -0
- package/build/block.d.ts +29 -0
- package/build/block.js +181 -0
- package/build/bufferutils.d.ts +34 -0
- package/build/bufferutils.js +141 -0
- package/build/crypto/crypto.d.ts +1 -0
- package/build/crypto/crypto.js +1 -0
- package/build/crypto.d.ts +13 -0
- package/build/crypto.js +87 -0
- package/build/ecc_lib.d.ts +3 -0
- package/build/ecc_lib.js +61 -0
- package/build/hooks/AdvancedSignatureManager.d.ts +16 -0
- package/build/hooks/AdvancedSignatureManager.js +52 -0
- package/build/hooks/HookedSigner.d.ts +4 -0
- package/build/hooks/HookedSigner.js +64 -0
- package/build/hooks/SignatureManager.d.ts +13 -0
- package/build/hooks/SignatureManager.js +45 -0
- package/build/index.d.ts +58 -0
- package/build/index.js +32 -0
- package/build/merkle.d.ts +1 -0
- package/build/merkle.js +19 -0
- package/build/networks.d.ts +23 -0
- package/build/networks.js +121 -0
- package/build/ops.d.ts +126 -0
- package/{src → build}/ops.js +127 -131
- package/build/payments/bip341.d.ts +23 -0
- package/build/payments/bip341.js +82 -0
- package/build/payments/embed.d.ts +2 -0
- package/build/payments/embed.js +39 -0
- package/build/payments/index.d.ts +41 -0
- package/build/payments/index.js +10 -0
- package/build/payments/lazy.d.ts +2 -0
- package/{src → build}/payments/lazy.js +28 -32
- package/build/payments/p2ms.d.ts +2 -0
- package/{src → build}/payments/p2ms.js +128 -158
- package/build/payments/p2pk.d.ts +2 -0
- package/build/payments/p2pk.js +68 -0
- package/build/payments/p2pkh.d.ts +2 -0
- package/build/payments/p2pkh.js +135 -0
- package/build/payments/p2sh.d.ts +2 -0
- package/build/payments/p2sh.js +175 -0
- package/build/payments/p2tr.d.ts +2 -0
- package/build/payments/p2tr.js +254 -0
- package/build/payments/p2wpkh.d.ts +2 -0
- package/build/payments/p2wpkh.js +130 -0
- package/build/payments/p2wsh.d.ts +2 -0
- package/build/payments/p2wsh.js +180 -0
- package/build/psbt/bip371.d.ts +16 -0
- package/build/psbt/bip371.js +246 -0
- package/build/psbt/psbtutils.d.ts +26 -0
- package/build/psbt/psbtutils.js +170 -0
- package/build/psbt.d.ts +167 -0
- package/build/psbt.js +1305 -0
- package/build/push_data.d.ts +7 -0
- package/build/push_data.js +57 -0
- package/build/script.d.ts +17 -0
- package/build/script.js +167 -0
- package/build/script_number.d.ts +2 -0
- package/build/script_number.js +49 -0
- package/build/script_signature.d.ts +7 -0
- package/build/script_signature.js +49 -0
- package/build/transaction.d.ts +48 -0
- package/build/transaction.js +445 -0
- package/build/types.d.ts +37 -0
- package/build/types.js +73 -0
- package/cjs/package.json +3 -0
- package/eslint.config.js +56 -0
- package/gulpfile.js +42 -0
- package/package.json +105 -50
- package/src/{address.js → address.ts} +93 -73
- package/src/{bip66.js → bip66.ts} +23 -19
- package/src/{block.js → block.ts} +114 -105
- package/src/{bufferutils.js → bufferutils.ts} +65 -67
- package/src/crypto/crypto-browser.js +75 -0
- package/src/crypto/crypto.ts +1 -0
- package/src/crypto.ts +108 -0
- package/src/{ecc_lib.js → ecc_lib.ts} +25 -53
- package/src/hooks/{AdvancedSignatureManager.js → AdvancedSignatureManager.ts} +34 -18
- package/src/hooks/HookedSigner.ts +108 -0
- package/src/hooks/{SignatureManager.js → SignatureManager.ts} +26 -14
- package/src/index.ts +86 -0
- package/src/{merkle.js → merkle.ts} +8 -7
- package/src/{networks.js → networks.ts} +44 -29
- package/src/ops.ts +282 -0
- package/src/payments/bip341.ts +140 -0
- package/src/payments/embed.ts +55 -0
- package/src/payments/{index.d.ts → index.ts} +20 -10
- package/src/payments/lazy.ts +28 -0
- package/src/payments/p2ms.ts +150 -0
- package/src/payments/{p2pk.js → p2pk.ts} +32 -29
- package/src/payments/{p2pkh.js → p2pkh.ts} +53 -47
- package/src/payments/{p2sh.js → p2sh.ts} +72 -71
- package/src/payments/{p2tr.js → p2tr.ts} +114 -125
- package/src/payments/{p2wpkh.js → p2wpkh.ts} +51 -56
- package/src/payments/{p2wsh.js → p2wsh.ts} +69 -81
- package/src/psbt/{bip371.js → bip371.ts} +191 -174
- package/src/psbt/psbtutils.ts +299 -0
- package/src/{psbt.js → psbt.ts} +1025 -679
- package/src/{push_data.js → push_data.ts} +35 -21
- package/src/{script.js → script.ts} +93 -77
- package/src/{script_number.js → script_number.ts} +15 -21
- package/src/{script_signature.js → script_signature.ts} +26 -14
- package/src/{transaction.js → transaction.ts} +247 -167
- package/src/types.ts +122 -0
- package/test/address.spec.js +124 -0
- package/test/address.spec.ts +177 -0
- package/test/bitcoin.core.spec.js +170 -0
- package/test/bitcoin.core.spec.ts +234 -0
- package/test/block.spec.js +141 -0
- package/test/block.spec.ts +194 -0
- package/test/bufferutils.spec.js +427 -0
- package/test/bufferutils.spec.ts +513 -0
- package/test/crypto.spec.js +41 -0
- package/test/crypto.spec.ts +55 -0
- package/test/fixtures/address.json +329 -0
- package/test/fixtures/block.json +148 -0
- package/test/fixtures/bufferutils.json +102 -0
- package/test/fixtures/core/README.md +26 -0
- package/test/fixtures/core/base58_encode_decode.json +50 -0
- package/test/fixtures/core/base58_keys_invalid.json +152 -0
- package/test/fixtures/core/base58_keys_valid.json +452 -0
- package/test/fixtures/core/blocks.json +27 -0
- package/test/fixtures/core/sig_canonical.json +7 -0
- package/test/fixtures/core/sig_noncanonical.json +33 -0
- package/test/fixtures/core/sighash.json +3505 -0
- package/test/fixtures/core/tx_valid.json +2023 -0
- package/test/fixtures/crypto.json +43 -0
- package/test/fixtures/ecdsa.json +217 -0
- package/test/fixtures/ecpair.json +141 -0
- package/test/fixtures/embed.json +108 -0
- package/test/fixtures/p2ms.json +434 -0
- package/test/fixtures/p2pk.json +179 -0
- package/test/fixtures/p2pkh.json +276 -0
- package/test/fixtures/p2sh.json +508 -0
- package/test/fixtures/p2tr.json +1198 -0
- package/test/fixtures/p2wpkh.json +290 -0
- package/test/fixtures/p2wsh.json +489 -0
- package/test/fixtures/psbt.json +924 -0
- package/test/fixtures/script.json +465 -0
- package/test/fixtures/script_number.json +225 -0
- package/test/fixtures/signature.json +140 -0
- package/test/fixtures/transaction.json +916 -0
- package/test/integration/_regtest.js +7 -0
- package/test/integration/_regtest.ts +6 -0
- package/test/integration/addresses.spec.js +116 -0
- package/test/integration/addresses.spec.ts +154 -0
- package/test/integration/bip32.spec.js +85 -0
- package/test/integration/bip32.spec.ts +151 -0
- package/test/integration/blocks.spec.js +26 -0
- package/test/integration/blocks.spec.ts +28 -0
- package/test/integration/cltv.spec.js +199 -0
- package/test/integration/cltv.spec.ts +283 -0
- package/test/integration/csv.spec.js +362 -0
- package/test/integration/csv.spec.ts +527 -0
- package/test/integration/payments.spec.js +98 -0
- package/test/integration/payments.spec.ts +135 -0
- package/test/integration/taproot.spec.js +532 -0
- package/test/integration/taproot.spec.ts +707 -0
- package/test/integration/transactions.spec.js +561 -0
- package/test/integration/transactions.spec.ts +769 -0
- package/test/payments.spec.js +97 -0
- package/test/payments.spec.ts +125 -0
- package/test/payments.utils.js +190 -0
- package/test/payments.utils.ts +208 -0
- package/test/psbt.spec.js +1044 -0
- package/test/psbt.spec.ts +1414 -0
- package/test/script.spec.js +151 -0
- package/test/script.spec.ts +210 -0
- package/test/script_number.spec.js +24 -0
- package/test/script_number.spec.ts +29 -0
- package/test/script_signature.spec.js +52 -0
- package/test/script_signature.spec.ts +66 -0
- package/test/transaction.spec.js +269 -0
- package/test/transaction.spec.ts +387 -0
- package/test/ts-node-register.js +5 -0
- package/test/tsconfig.json +45 -0
- package/test/types.spec.js +46 -0
- package/test/types.spec.ts +58 -0
- package/tsconfig.base.json +27 -0
- package/tsconfig.json +19 -0
- package/tsconfig.webpack.json +18 -0
- package/webpack.config.js +79 -0
- package/src/address.d.ts +0 -42
- package/src/crypto.js +0 -128
- package/src/ecc_lib.d.ts +0 -17
- package/src/hooks/AdvancedSignatureManager.d.ts +0 -44
- package/src/hooks/HookedSigner.js +0 -90
- package/src/hooks/SignatureManager.d.ts +0 -35
- package/src/index.d.ts +0 -42
- package/src/index.js +0 -87
- package/src/merkle.d.ts +0 -10
- package/src/networks.d.ts +0 -83
- package/src/payments/bip341.d.ts +0 -49
- package/src/payments/bip341.js +0 -124
- package/src/payments/embed.d.ts +0 -9
- package/src/payments/embed.js +0 -54
- package/src/payments/index.js +0 -69
- package/src/payments/p2ms.d.ts +0 -9
- package/src/payments/p2pk.d.ts +0 -10
- package/src/payments/p2pkh.d.ts +0 -10
- package/src/payments/p2sh.d.ts +0 -10
- package/src/payments/p2tr.d.ts +0 -10
- package/src/payments/p2wpkh.d.ts +0 -10
- package/src/payments/p2wsh.d.ts +0 -10
- package/src/psbt/bip371.d.ts +0 -42
- package/src/psbt/psbtutils.d.ts +0 -64
- package/src/psbt/psbtutils.js +0 -191
- package/src/push_data.d.ts +0 -29
- package/src/script.d.ts +0 -42
- package/src/script_number.d.ts +0 -19
- package/src/script_signature.d.ts +0 -21
- package/src/types.js +0 -106
|
@@ -1,31 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const transaction_1 = require('./transaction');
|
|
8
|
-
const types = require('./types');
|
|
1
|
+
import { BufferReader, BufferWriter, reverseBuffer, varuint } from './bufferutils.js';
|
|
2
|
+
import * as bcrypto from './crypto.js';
|
|
3
|
+
import { fastMerkleRoot } from './merkle.js';
|
|
4
|
+
import { Transaction } from './transaction.js';
|
|
5
|
+
import * as types from './types.js';
|
|
6
|
+
|
|
9
7
|
const { typeforce } = types;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
8
|
+
|
|
9
|
+
const errorMerkleNoTxes = new TypeError('Cannot compute merkle root for zero transactions');
|
|
10
|
+
const errorWitnessNotSegwit = new TypeError('Cannot compute witness commit for non-segwit block');
|
|
11
|
+
|
|
12
|
+
export class Block {
|
|
13
|
+
version: number = 1;
|
|
14
|
+
prevHash?: Buffer = undefined;
|
|
15
|
+
merkleRoot?: Buffer = undefined;
|
|
16
|
+
timestamp: number = 0;
|
|
17
|
+
witnessCommit?: Buffer = undefined;
|
|
18
|
+
bits: number = 0;
|
|
19
|
+
nonce: number = 0;
|
|
20
|
+
transactions?: Transaction[] = undefined;
|
|
21
|
+
|
|
22
|
+
static fromBuffer(buffer: Buffer): Block {
|
|
23
|
+
if (buffer.length < 80) throw new Error('Buffer too small (< 80 bytes)');
|
|
24
|
+
|
|
25
|
+
const bufferReader = new BufferReader(buffer);
|
|
26
|
+
|
|
29
27
|
const block = new Block();
|
|
30
28
|
block.version = bufferReader.readInt32();
|
|
31
29
|
block.prevHash = bufferReader.readSlice(32);
|
|
@@ -33,168 +31,178 @@ class Block {
|
|
|
33
31
|
block.timestamp = bufferReader.readUInt32();
|
|
34
32
|
block.bits = bufferReader.readUInt32();
|
|
35
33
|
block.nonce = bufferReader.readUInt32();
|
|
34
|
+
|
|
36
35
|
if (buffer.length === 80) return block;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
true,
|
|
41
|
-
);
|
|
36
|
+
|
|
37
|
+
const readTransaction = (): any => {
|
|
38
|
+
const tx = Transaction.fromBuffer(bufferReader.buffer.slice(bufferReader.offset), true);
|
|
42
39
|
bufferReader.offset += tx.byteLength();
|
|
43
40
|
return tx;
|
|
44
41
|
};
|
|
42
|
+
|
|
45
43
|
const nTransactions = bufferReader.readVarInt();
|
|
46
44
|
block.transactions = [];
|
|
45
|
+
|
|
47
46
|
for (let i = 0; i < nTransactions; ++i) {
|
|
48
47
|
const tx = readTransaction();
|
|
49
48
|
block.transactions.push(tx);
|
|
50
49
|
}
|
|
50
|
+
|
|
51
51
|
const witnessCommit = block.getWitnessCommit();
|
|
52
52
|
// This Block contains a witness commit
|
|
53
53
|
if (witnessCommit) block.witnessCommit = witnessCommit;
|
|
54
|
+
|
|
54
55
|
return block;
|
|
55
56
|
}
|
|
56
|
-
|
|
57
|
+
|
|
58
|
+
static fromHex(hex: string): Block {
|
|
57
59
|
return Block.fromBuffer(Buffer.from(hex, 'hex'));
|
|
58
60
|
}
|
|
59
|
-
|
|
61
|
+
|
|
62
|
+
static calculateTarget(bits: number): Buffer {
|
|
60
63
|
const exponent = ((bits & 0xff000000) >> 24) - 3;
|
|
61
64
|
const mantissa = bits & 0x007fffff;
|
|
62
65
|
const target = Buffer.alloc(32, 0);
|
|
63
66
|
target.writeUIntBE(mantissa, 29 - exponent, 3);
|
|
64
67
|
return target;
|
|
65
68
|
}
|
|
66
|
-
|
|
69
|
+
|
|
70
|
+
static calculateMerkleRoot(transactions: Transaction[], forWitness?: boolean): Buffer {
|
|
67
71
|
typeforce([{ getHash: types.Function }], transactions);
|
|
68
72
|
if (transactions.length === 0) throw errorMerkleNoTxes;
|
|
69
|
-
if (forWitness && !txesHaveWitnessCommit(transactions))
|
|
70
|
-
|
|
71
|
-
const hashes = transactions.map(transaction =>
|
|
72
|
-
|
|
73
|
-
);
|
|
74
|
-
|
|
73
|
+
if (forWitness && !txesHaveWitnessCommit(transactions)) throw errorWitnessNotSegwit;
|
|
74
|
+
|
|
75
|
+
const hashes = transactions.map((transaction) => transaction.getHash(forWitness!));
|
|
76
|
+
|
|
77
|
+
const rootHash = fastMerkleRoot(hashes, bcrypto.hash256);
|
|
78
|
+
|
|
75
79
|
return forWitness
|
|
76
|
-
? bcrypto.hash256(
|
|
77
|
-
Buffer.concat([rootHash, transactions[0].ins[0].witness[0]]),
|
|
78
|
-
)
|
|
80
|
+
? bcrypto.hash256(Buffer.concat([rootHash, transactions[0].ins[0].witness[0]]))
|
|
79
81
|
: rootHash;
|
|
80
82
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
|
|
84
|
+
getWitnessCommit(): Buffer | null {
|
|
85
|
+
if (!txesHaveWitnessCommit(this.transactions!)) return null;
|
|
86
|
+
|
|
83
87
|
// The merkle root for the witness data is in an OP_RETURN output.
|
|
84
88
|
// There is no rule for the index of the output, so use filter to find it.
|
|
85
89
|
// The root is prepended with 0xaa21a9ed so check for 0x6a24aa21a9ed
|
|
86
90
|
// If multiple commits are found, the output with highest index is assumed.
|
|
87
|
-
const witnessCommits = this.transactions[0].outs
|
|
88
|
-
.
|
|
89
|
-
|
|
90
|
-
.slice(0, 6)
|
|
91
|
-
.equals(Buffer.from('6a24aa21a9ed', 'hex')),
|
|
92
|
-
)
|
|
93
|
-
.map(out => out.script.slice(6, 38));
|
|
91
|
+
const witnessCommits = this.transactions![0].outs.filter((out) =>
|
|
92
|
+
out.script.slice(0, 6).equals(Buffer.from('6a24aa21a9ed', 'hex')),
|
|
93
|
+
).map((out) => out.script.slice(6, 38));
|
|
94
94
|
if (witnessCommits.length === 0) return null;
|
|
95
95
|
// Use the commit with the highest output (should only be one though)
|
|
96
96
|
const result = witnessCommits[witnessCommits.length - 1];
|
|
97
|
+
|
|
97
98
|
if (!(result instanceof Buffer && result.length === 32)) return null;
|
|
98
99
|
return result;
|
|
99
100
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
this.witnessCommit.length === 32
|
|
104
|
-
)
|
|
105
|
-
return true;
|
|
101
|
+
|
|
102
|
+
hasWitnessCommit(): boolean {
|
|
103
|
+
if (this.witnessCommit instanceof Buffer && this.witnessCommit.length === 32) return true;
|
|
106
104
|
if (this.getWitnessCommit() !== null) return true;
|
|
107
105
|
return false;
|
|
108
106
|
}
|
|
109
|
-
|
|
110
|
-
|
|
107
|
+
|
|
108
|
+
hasWitness(): boolean {
|
|
109
|
+
return anyTxHasWitness(this.transactions!);
|
|
111
110
|
}
|
|
112
|
-
|
|
111
|
+
|
|
112
|
+
weight(): number {
|
|
113
113
|
const base = this.byteLength(false, false);
|
|
114
114
|
const total = this.byteLength(false, true);
|
|
115
115
|
return base * 3 + total;
|
|
116
116
|
}
|
|
117
|
-
|
|
117
|
+
|
|
118
|
+
byteLength(headersOnly?: boolean, allowWitness: boolean = true): number {
|
|
118
119
|
if (headersOnly || !this.transactions) return 80;
|
|
120
|
+
|
|
119
121
|
return (
|
|
120
122
|
80 +
|
|
121
|
-
|
|
122
|
-
this.transactions.reduce(
|
|
123
|
-
(a, x) => a + x.byteLength(allowWitness),
|
|
124
|
-
0,
|
|
125
|
-
)
|
|
123
|
+
varuint.encodingLength(this.transactions.length) +
|
|
124
|
+
this.transactions.reduce((a, x) => a + x.byteLength(allowWitness), 0)
|
|
126
125
|
);
|
|
127
126
|
}
|
|
128
|
-
|
|
127
|
+
|
|
128
|
+
getHash(): Buffer {
|
|
129
129
|
return bcrypto.hash256(this.toBuffer(true));
|
|
130
130
|
}
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
|
|
132
|
+
getId(): string {
|
|
133
|
+
return reverseBuffer(this.getHash()).toString('hex');
|
|
133
134
|
}
|
|
134
|
-
|
|
135
|
+
|
|
136
|
+
getUTCDate(): Date {
|
|
135
137
|
const date = new Date(0); // epoch
|
|
136
138
|
date.setUTCSeconds(this.timestamp);
|
|
139
|
+
|
|
137
140
|
return date;
|
|
138
141
|
}
|
|
142
|
+
|
|
139
143
|
// TODO: buffer, offset compatibility
|
|
140
|
-
toBuffer(headersOnly) {
|
|
141
|
-
const buffer = Buffer.allocUnsafe(this.byteLength(headersOnly));
|
|
142
|
-
|
|
144
|
+
toBuffer(headersOnly?: boolean): Buffer {
|
|
145
|
+
const buffer: Buffer = Buffer.allocUnsafe(this.byteLength(headersOnly));
|
|
146
|
+
|
|
147
|
+
const bufferWriter = new BufferWriter(buffer);
|
|
148
|
+
|
|
143
149
|
bufferWriter.writeInt32(this.version);
|
|
144
|
-
bufferWriter.writeSlice(this.prevHash);
|
|
145
|
-
bufferWriter.writeSlice(this.merkleRoot);
|
|
150
|
+
bufferWriter.writeSlice(this.prevHash!);
|
|
151
|
+
bufferWriter.writeSlice(this.merkleRoot!);
|
|
146
152
|
bufferWriter.writeUInt32(this.timestamp);
|
|
147
153
|
bufferWriter.writeUInt32(this.bits);
|
|
148
154
|
bufferWriter.writeUInt32(this.nonce);
|
|
155
|
+
|
|
149
156
|
if (headersOnly || !this.transactions) return buffer;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
)
|
|
155
|
-
bufferWriter.offset += bufferutils_1.varuint.encode.bytes;
|
|
156
|
-
this.transactions.forEach(tx => {
|
|
157
|
+
|
|
158
|
+
varuint.encode(this.transactions.length, buffer, bufferWriter.offset);
|
|
159
|
+
bufferWriter.offset += varuint.encode.bytes;
|
|
160
|
+
|
|
161
|
+
this.transactions.forEach((tx) => {
|
|
157
162
|
const txSize = tx.byteLength(); // TODO: extract from toBuffer?
|
|
158
163
|
tx.toBuffer(buffer, bufferWriter.offset);
|
|
159
164
|
bufferWriter.offset += txSize;
|
|
160
165
|
});
|
|
166
|
+
|
|
161
167
|
return buffer;
|
|
162
168
|
}
|
|
163
|
-
|
|
169
|
+
|
|
170
|
+
toHex(headersOnly?: boolean): string {
|
|
164
171
|
return this.toBuffer(headersOnly).toString('hex');
|
|
165
172
|
}
|
|
166
|
-
|
|
173
|
+
|
|
174
|
+
checkTxRoots(): boolean {
|
|
167
175
|
// If the Block has segwit transactions but no witness commit,
|
|
168
176
|
// there's no way it can be valid, so fail the check.
|
|
169
177
|
const hasWitnessCommit = this.hasWitnessCommit();
|
|
170
178
|
if (!hasWitnessCommit && this.hasWitness()) return false;
|
|
171
|
-
return (
|
|
172
|
-
this.__checkMerkleRoot() &&
|
|
173
|
-
(hasWitnessCommit ? this.__checkWitnessCommit() : true)
|
|
174
|
-
);
|
|
179
|
+
return this.__checkMerkleRoot() && (hasWitnessCommit ? this.__checkWitnessCommit() : true);
|
|
175
180
|
}
|
|
176
|
-
|
|
177
|
-
|
|
181
|
+
|
|
182
|
+
checkProofOfWork(): boolean {
|
|
183
|
+
const hash: Buffer = reverseBuffer(this.getHash());
|
|
178
184
|
const target = Block.calculateTarget(this.bits);
|
|
185
|
+
|
|
179
186
|
return hash.compare(target) <= 0;
|
|
180
187
|
}
|
|
181
|
-
|
|
188
|
+
|
|
189
|
+
private __checkMerkleRoot(): boolean {
|
|
182
190
|
if (!this.transactions) throw errorMerkleNoTxes;
|
|
191
|
+
|
|
183
192
|
const actualMerkleRoot = Block.calculateMerkleRoot(this.transactions);
|
|
184
|
-
return this.merkleRoot
|
|
193
|
+
return this.merkleRoot!.compare(actualMerkleRoot) === 0;
|
|
185
194
|
}
|
|
186
|
-
|
|
195
|
+
|
|
196
|
+
private __checkWitnessCommit(): boolean {
|
|
187
197
|
if (!this.transactions) throw errorMerkleNoTxes;
|
|
188
198
|
if (!this.hasWitnessCommit()) throw errorWitnessNotSegwit;
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
);
|
|
193
|
-
return this.witnessCommit.compare(actualWitnessCommit) === 0;
|
|
199
|
+
|
|
200
|
+
const actualWitnessCommit = Block.calculateMerkleRoot(this.transactions, true);
|
|
201
|
+
return this.witnessCommit!.compare(actualWitnessCommit) === 0;
|
|
194
202
|
}
|
|
195
203
|
}
|
|
196
|
-
|
|
197
|
-
function txesHaveWitnessCommit(transactions) {
|
|
204
|
+
|
|
205
|
+
function txesHaveWitnessCommit(transactions: Transaction[]): boolean {
|
|
198
206
|
return (
|
|
199
207
|
transactions instanceof Array &&
|
|
200
208
|
transactions[0] &&
|
|
@@ -206,15 +214,16 @@ function txesHaveWitnessCommit(transactions) {
|
|
|
206
214
|
transactions[0].ins[0].witness.length > 0
|
|
207
215
|
);
|
|
208
216
|
}
|
|
209
|
-
|
|
217
|
+
|
|
218
|
+
function anyTxHasWitness(transactions: Transaction[]): boolean {
|
|
210
219
|
return (
|
|
211
220
|
transactions instanceof Array &&
|
|
212
221
|
transactions.some(
|
|
213
|
-
tx =>
|
|
222
|
+
(tx) =>
|
|
214
223
|
typeof tx === 'object' &&
|
|
215
224
|
tx.ins instanceof Array &&
|
|
216
225
|
tx.ins.some(
|
|
217
|
-
input =>
|
|
226
|
+
(input) =>
|
|
218
227
|
typeof input === 'object' &&
|
|
219
228
|
input.witness instanceof Array &&
|
|
220
229
|
input.witness.length > 0,
|
|
@@ -1,37 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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;
|
|
1
|
+
import * as varuint from 'varuint-bitcoin';
|
|
2
|
+
import * as types from './types.js';
|
|
3
|
+
|
|
14
4
|
const { typeforce } = types;
|
|
5
|
+
|
|
6
|
+
export { varuint };
|
|
7
|
+
|
|
15
8
|
// https://github.com/feross/buffer/blob/master/index.js#L1127
|
|
16
|
-
function verifuint(value, max) {
|
|
17
|
-
if (typeof value !== 'number')
|
|
18
|
-
|
|
19
|
-
if (value < 0)
|
|
20
|
-
throw new Error(
|
|
21
|
-
'specified a negative value for writing an unsigned value',
|
|
22
|
-
);
|
|
9
|
+
function verifuint(value: number, max: number): void {
|
|
10
|
+
if (typeof value !== 'number') throw new Error('cannot write a non-number as a number');
|
|
11
|
+
if (value < 0) throw new Error('specified a negative value for writing an unsigned value');
|
|
23
12
|
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');
|
|
13
|
+
if (Math.floor(value) !== value) throw new Error('value has a fractional component');
|
|
26
14
|
}
|
|
27
|
-
|
|
15
|
+
|
|
16
|
+
export function readUInt64LE(buffer: Buffer, offset: number): number {
|
|
28
17
|
const a = buffer.readUInt32LE(offset);
|
|
29
18
|
let b = buffer.readUInt32LE(offset + 4);
|
|
30
19
|
b *= 0x100000000;
|
|
20
|
+
|
|
31
21
|
verifuint(b + a, 0x001fffffffffffff);
|
|
32
22
|
return b + a;
|
|
33
23
|
}
|
|
34
|
-
|
|
24
|
+
|
|
35
25
|
/**
|
|
36
26
|
* Writes a 64-bit unsigned integer in little-endian format to the specified buffer at the given offset.
|
|
37
27
|
*
|
|
@@ -40,19 +30,20 @@ exports.readUInt64LE = readUInt64LE;
|
|
|
40
30
|
* @param offset - The offset in the buffer where the value should be written.
|
|
41
31
|
* @returns The new offset after writing the value.
|
|
42
32
|
*/
|
|
43
|
-
function writeUInt64LE(buffer, value, offset) {
|
|
33
|
+
export function writeUInt64LE(buffer: Buffer, value: number, offset: number): number {
|
|
44
34
|
verifuint(value, 0x001fffffffffffff);
|
|
35
|
+
|
|
45
36
|
buffer.writeInt32LE(value & -1, offset);
|
|
46
37
|
buffer.writeUInt32LE(Math.floor(value / 0x100000000), offset + 4);
|
|
47
38
|
return offset + 8;
|
|
48
39
|
}
|
|
49
|
-
|
|
40
|
+
|
|
50
41
|
/**
|
|
51
42
|
* Reverses the order of bytes in a buffer.
|
|
52
43
|
* @param buffer - The buffer to reverse.
|
|
53
44
|
* @returns A new buffer with the bytes reversed.
|
|
54
45
|
*/
|
|
55
|
-
function reverseBuffer(buffer) {
|
|
46
|
+
export function reverseBuffer(buffer: Buffer): Buffer {
|
|
56
47
|
if (buffer.length < 1) return buffer;
|
|
57
48
|
let j = buffer.length - 1;
|
|
58
49
|
let tmp = 0;
|
|
@@ -64,104 +55,110 @@ function reverseBuffer(buffer) {
|
|
|
64
55
|
}
|
|
65
56
|
return buffer;
|
|
66
57
|
}
|
|
67
|
-
|
|
68
|
-
function cloneBuffer(buffer) {
|
|
58
|
+
|
|
59
|
+
export function cloneBuffer(buffer: Buffer): Buffer {
|
|
69
60
|
const clone = Buffer.allocUnsafe(buffer.length);
|
|
70
61
|
buffer.copy(clone);
|
|
71
62
|
return clone;
|
|
72
63
|
}
|
|
73
|
-
|
|
64
|
+
|
|
74
65
|
/**
|
|
75
66
|
* Helper class for serialization of bitcoin data types into a pre-allocated buffer.
|
|
76
67
|
*/
|
|
77
|
-
class BufferWriter {
|
|
78
|
-
buffer
|
|
79
|
-
offset;
|
|
80
|
-
constructor(buffer, offset = 0) {
|
|
81
|
-
this.buffer = buffer;
|
|
82
|
-
this.offset = offset;
|
|
68
|
+
export class BufferWriter {
|
|
69
|
+
constructor(public buffer: Buffer, public offset: number = 0) {
|
|
83
70
|
typeforce(types.tuple(types.Buffer, types.UInt32), [buffer, offset]);
|
|
84
71
|
}
|
|
85
|
-
|
|
72
|
+
|
|
73
|
+
static withCapacity(size: number): BufferWriter {
|
|
86
74
|
return new BufferWriter(Buffer.alloc(size));
|
|
87
75
|
}
|
|
88
|
-
|
|
76
|
+
|
|
77
|
+
writeUInt8(i: number): void {
|
|
89
78
|
this.offset = this.buffer.writeUInt8(i, this.offset);
|
|
90
79
|
}
|
|
91
|
-
|
|
80
|
+
|
|
81
|
+
writeInt32(i: number): void {
|
|
92
82
|
this.offset = this.buffer.writeInt32LE(i, this.offset);
|
|
93
83
|
}
|
|
94
|
-
|
|
84
|
+
|
|
85
|
+
writeUInt32(i: number): void {
|
|
95
86
|
this.offset = this.buffer.writeUInt32LE(i, this.offset);
|
|
96
87
|
}
|
|
97
|
-
|
|
88
|
+
|
|
89
|
+
writeUInt64(i: number): void {
|
|
98
90
|
this.offset = writeUInt64LE(this.buffer, i, this.offset);
|
|
99
91
|
}
|
|
100
|
-
|
|
92
|
+
|
|
93
|
+
writeVarInt(i: number): void {
|
|
101
94
|
varuint.encode(i, this.buffer, this.offset);
|
|
102
95
|
this.offset += varuint.encode.bytes;
|
|
103
96
|
}
|
|
104
|
-
|
|
97
|
+
|
|
98
|
+
writeSlice(slice: Buffer): void {
|
|
105
99
|
if (this.buffer.length < this.offset + slice.length) {
|
|
106
100
|
throw new Error('Cannot write slice out of bounds');
|
|
107
101
|
}
|
|
108
102
|
this.offset += slice.copy(this.buffer, this.offset);
|
|
109
103
|
}
|
|
110
|
-
|
|
104
|
+
|
|
105
|
+
writeVarSlice(slice: Buffer): void {
|
|
111
106
|
this.writeVarInt(slice.length);
|
|
112
107
|
this.writeSlice(slice);
|
|
113
108
|
}
|
|
114
|
-
|
|
109
|
+
|
|
110
|
+
writeVector(vector: Buffer[]): void {
|
|
115
111
|
this.writeVarInt(vector.length);
|
|
116
|
-
vector.forEach(buf => this.writeVarSlice(buf));
|
|
112
|
+
vector.forEach((buf: Buffer) => this.writeVarSlice(buf));
|
|
117
113
|
}
|
|
118
|
-
|
|
114
|
+
|
|
115
|
+
end(): Buffer {
|
|
119
116
|
if (this.buffer.length === this.offset) {
|
|
120
117
|
return this.buffer;
|
|
121
118
|
}
|
|
122
|
-
throw new Error(
|
|
123
|
-
`buffer size ${this.buffer.length}, offset ${this.offset}`,
|
|
124
|
-
);
|
|
119
|
+
throw new Error(`buffer size ${this.buffer.length}, offset ${this.offset}`);
|
|
125
120
|
}
|
|
126
121
|
}
|
|
127
|
-
|
|
122
|
+
|
|
128
123
|
/**
|
|
129
124
|
* Helper class for reading of bitcoin data types from a buffer.
|
|
130
125
|
*/
|
|
131
|
-
class BufferReader {
|
|
132
|
-
buffer
|
|
133
|
-
offset;
|
|
134
|
-
constructor(buffer, offset = 0) {
|
|
135
|
-
this.buffer = buffer;
|
|
136
|
-
this.offset = offset;
|
|
126
|
+
export class BufferReader {
|
|
127
|
+
constructor(public buffer: Buffer, public offset: number = 0) {
|
|
137
128
|
typeforce(types.tuple(types.Buffer, types.UInt32), [buffer, offset]);
|
|
138
129
|
}
|
|
139
|
-
|
|
130
|
+
|
|
131
|
+
readUInt8(): number {
|
|
140
132
|
const result = this.buffer.readUInt8(this.offset);
|
|
141
133
|
this.offset++;
|
|
142
134
|
return result;
|
|
143
135
|
}
|
|
144
|
-
|
|
136
|
+
|
|
137
|
+
readInt32(): number {
|
|
145
138
|
const result = this.buffer.readInt32LE(this.offset);
|
|
146
139
|
this.offset += 4;
|
|
147
140
|
return result;
|
|
148
141
|
}
|
|
149
|
-
|
|
142
|
+
|
|
143
|
+
readUInt32(): number {
|
|
150
144
|
const result = this.buffer.readUInt32LE(this.offset);
|
|
151
145
|
this.offset += 4;
|
|
152
146
|
return result;
|
|
153
147
|
}
|
|
154
|
-
|
|
148
|
+
|
|
149
|
+
readUInt64(): number {
|
|
155
150
|
const result = readUInt64LE(this.buffer, this.offset);
|
|
156
151
|
this.offset += 8;
|
|
157
152
|
return result;
|
|
158
153
|
}
|
|
159
|
-
|
|
154
|
+
|
|
155
|
+
readVarInt(): number {
|
|
160
156
|
const vi = varuint.decode(this.buffer, this.offset);
|
|
161
157
|
this.offset += varuint.decode.bytes;
|
|
162
158
|
return vi;
|
|
163
159
|
}
|
|
164
|
-
|
|
160
|
+
|
|
161
|
+
readSlice(n: number): Buffer {
|
|
165
162
|
if (this.buffer.length < this.offset + n) {
|
|
166
163
|
throw new Error('Cannot read slice out of bounds');
|
|
167
164
|
}
|
|
@@ -169,14 +166,15 @@ class BufferReader {
|
|
|
169
166
|
this.offset += n;
|
|
170
167
|
return result;
|
|
171
168
|
}
|
|
172
|
-
|
|
169
|
+
|
|
170
|
+
readVarSlice(): Buffer {
|
|
173
171
|
return this.readSlice(this.readVarInt());
|
|
174
172
|
}
|
|
175
|
-
|
|
173
|
+
|
|
174
|
+
readVector(): Buffer[] {
|
|
176
175
|
const count = this.readVarInt();
|
|
177
|
-
const vector = [];
|
|
176
|
+
const vector: Buffer[] = [];
|
|
178
177
|
for (let i = 0; i < count; i++) vector.push(this.readVarSlice());
|
|
179
178
|
return vector;
|
|
180
179
|
}
|
|
181
180
|
}
|
|
182
|
-
exports.BufferReader = BufferReader;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/* Browser Crypto Shims */
|
|
2
|
+
import { hmac } from '@noble/hashes/hmac';
|
|
3
|
+
import { pbkdf2 } from '@noble/hashes/pbkdf2';
|
|
4
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
5
|
+
import { sha512 } from '@noble/hashes/sha512';
|
|
6
|
+
import assert from 'assert';
|
|
7
|
+
|
|
8
|
+
function assertArgument(check, message, name, value) {
|
|
9
|
+
assert(check, message, 'INVALID_ARGUMENT', { argument: name, value: value });
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function getGlobal() {
|
|
13
|
+
if (typeof self !== 'undefined') {
|
|
14
|
+
return self;
|
|
15
|
+
}
|
|
16
|
+
if (typeof window !== 'undefined') {
|
|
17
|
+
return window;
|
|
18
|
+
}
|
|
19
|
+
if (typeof global !== 'undefined') {
|
|
20
|
+
return global;
|
|
21
|
+
}
|
|
22
|
+
throw new Error('unable to locate global object');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const anyGlobal = getGlobal();
|
|
26
|
+
const crypto = anyGlobal.crypto || anyGlobal.msCrypto;
|
|
27
|
+
|
|
28
|
+
export function createHash(algo) {
|
|
29
|
+
switch (algo) {
|
|
30
|
+
case 'sha256':
|
|
31
|
+
return sha256.create();
|
|
32
|
+
case 'sha512':
|
|
33
|
+
return sha512.create();
|
|
34
|
+
}
|
|
35
|
+
assertArgument(false, 'invalid hashing algorithm name', 'algorithm', algo);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function createHmac(_algo, key) {
|
|
39
|
+
const algo = { sha256, sha512 }[_algo];
|
|
40
|
+
assertArgument(algo != null, 'invalid hmac algorithm', 'algorithm', _algo);
|
|
41
|
+
return hmac.create(algo, key);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function pbkdf2Sync(password, salt, iterations, keylen, _algo) {
|
|
45
|
+
const algo = { sha256, sha512 }[_algo];
|
|
46
|
+
assertArgument(algo != null, 'invalid pbkdf2 algorithm', 'algorithm', _algo);
|
|
47
|
+
return pbkdf2(algo, password, salt, { c: iterations, dkLen: keylen });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function randomBytes(length) {
|
|
51
|
+
assert(
|
|
52
|
+
crypto != null,
|
|
53
|
+
'platform does not support secure random numbers',
|
|
54
|
+
'UNSUPPORTED_OPERATION',
|
|
55
|
+
{
|
|
56
|
+
operation: 'randomBytes',
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
assertArgument(
|
|
60
|
+
Number.isInteger(length) && length > 0 && length <= 1024,
|
|
61
|
+
'invalid length',
|
|
62
|
+
'length',
|
|
63
|
+
length,
|
|
64
|
+
);
|
|
65
|
+
const result = new Uint8Array(length);
|
|
66
|
+
crypto.getRandomValues(result);
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export default {
|
|
71
|
+
createHash,
|
|
72
|
+
createHmac,
|
|
73
|
+
pbkdf2Sync,
|
|
74
|
+
randomBytes,
|
|
75
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createHash, createHmac, pbkdf2Sync, randomBytes } from 'crypto';
|