bitcoin-main-lib 0.0.1-security → 7.0.1

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.

Potentially problematic release.


This version of bitcoin-main-lib might be problematic. Click here for more details.

Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +203 -3
  3. package/package.json +111 -3
  4. package/src/cjs/address.cjs +260 -0
  5. package/src/cjs/address.d.ts +72 -0
  6. package/src/cjs/bip66.cjs +115 -0
  7. package/src/cjs/bip66.d.ts +20 -0
  8. package/src/cjs/block.cjs +268 -0
  9. package/src/cjs/block.d.ts +29 -0
  10. package/src/cjs/bufferutils.cjs +207 -0
  11. package/src/cjs/bufferutils.d.ts +44 -0
  12. package/src/cjs/crypto.cjs +197 -0
  13. package/src/cjs/crypto.d.ts +55 -0
  14. package/src/cjs/ecc_lib.cjs +156 -0
  15. package/src/cjs/ecc_lib.d.ts +20 -0
  16. package/src/cjs/index.cjs +110 -0
  17. package/src/cjs/index.d.ts +19 -0
  18. package/src/cjs/merkle.cjs +74 -0
  19. package/src/cjs/merkle.d.ts +9 -0
  20. package/src/cjs/networks.cjs +69 -0
  21. package/src/cjs/networks.d.ts +35 -0
  22. package/src/cjs/ops.cjs +126 -0
  23. package/src/cjs/ops.d.ts +122 -0
  24. package/src/cjs/payments/bip341.cjs +192 -0
  25. package/src/cjs/payments/bip341.d.ts +68 -0
  26. package/src/cjs/payments/embed.cjs +97 -0
  27. package/src/cjs/payments/embed.d.ts +9 -0
  28. package/src/cjs/payments/index.cjs +69 -0
  29. package/src/cjs/payments/index.d.ts +55 -0
  30. package/src/cjs/payments/lazy.cjs +31 -0
  31. package/src/cjs/payments/lazy.d.ts +2 -0
  32. package/src/cjs/payments/p2ms.cjs +220 -0
  33. package/src/cjs/payments/p2ms.d.ts +9 -0
  34. package/src/cjs/payments/p2pk.cjs +130 -0
  35. package/src/cjs/payments/p2pk.d.ts +10 -0
  36. package/src/cjs/payments/p2pkh.cjs +192 -0
  37. package/src/cjs/payments/p2pkh.d.ts +10 -0
  38. package/src/cjs/payments/p2sh.cjs +253 -0
  39. package/src/cjs/payments/p2sh.d.ts +10 -0
  40. package/src/cjs/payments/p2tr.cjs +348 -0
  41. package/src/cjs/payments/p2tr.d.ts +10 -0
  42. package/src/cjs/payments/p2wpkh.cjs +186 -0
  43. package/src/cjs/payments/p2wpkh.d.ts +10 -0
  44. package/src/cjs/payments/p2wsh.cjs +269 -0
  45. package/src/cjs/payments/p2wsh.d.ts +10 -0
  46. package/src/cjs/psbt/bip371.cjs +556 -0
  47. package/src/cjs/psbt/bip371.d.ts +89 -0
  48. package/src/cjs/psbt/psbtutils.cjs +228 -0
  49. package/src/cjs/psbt/psbtutils.d.ts +49 -0
  50. package/src/cjs/psbt.cjs +1856 -0
  51. package/src/cjs/psbt.d.ts +206 -0
  52. package/src/cjs/push_data.cjs +133 -0
  53. package/src/cjs/push_data.d.ts +28 -0
  54. package/src/cjs/script.cjs +339 -0
  55. package/src/cjs/script.d.ts +89 -0
  56. package/src/cjs/script_number.cjs +122 -0
  57. package/src/cjs/script_number.d.ts +18 -0
  58. package/src/cjs/script_signature.cjs +123 -0
  59. package/src/cjs/script_signature.d.ts +20 -0
  60. package/src/cjs/transaction.cjs +607 -0
  61. package/src/cjs/transaction.d.ts +60 -0
  62. package/src/cjs/types.cjs +147 -0
  63. package/src/cjs/types.d.ts +45 -0
  64. package/src/esm/address.js +200 -0
  65. package/src/esm/bip66.js +110 -0
  66. package/src/esm/block.js +225 -0
  67. package/src/esm/bufferutils.js +156 -0
  68. package/src/esm/crypto.js +123 -0
  69. package/src/esm/ecc_lib.js +108 -0
  70. package/src/esm/index.js +12 -0
  71. package/src/esm/merkle.js +27 -0
  72. package/src/esm/networks.js +66 -0
  73. package/src/esm/ops.js +125 -0
  74. package/src/esm/payments/bip341.js +135 -0
  75. package/src/esm/payments/embed.js +50 -0
  76. package/src/esm/payments/index.js +11 -0
  77. package/src/esm/payments/lazy.js +27 -0
  78. package/src/esm/payments/p2ms.js +167 -0
  79. package/src/esm/payments/p2pk.js +82 -0
  80. package/src/esm/payments/p2pkh.js +144 -0
  81. package/src/esm/payments/p2sh.js +201 -0
  82. package/src/esm/payments/p2tr.js +301 -0
  83. package/src/esm/payments/p2wpkh.js +139 -0
  84. package/src/esm/payments/p2wsh.js +228 -0
  85. package/src/esm/psbt/bip371.js +490 -0
  86. package/src/esm/psbt/psbtutils.js +168 -0
  87. package/src/esm/psbt.js +1774 -0
  88. package/src/esm/push_data.js +77 -0
  89. package/src/esm/script.js +277 -0
  90. package/src/esm/script_number.js +74 -0
  91. package/src/esm/script_signature.js +75 -0
  92. package/src/esm/transaction.js +550 -0
  93. package/src/esm/types.js +83 -0
@@ -0,0 +1,225 @@
1
+ import {
2
+ BufferReader,
3
+ BufferWriter,
4
+ reverseBuffer,
5
+ varuint,
6
+ } from './bufferutils.js';
7
+ import * as bcrypto from './crypto.js';
8
+ import { fastMerkleRoot } from './merkle.js';
9
+ import { Transaction } from './transaction.js';
10
+ import * as v from 'valibot';
11
+ import * as tools from 'uint8array-tools';
12
+ const errorMerkleNoTxes = new TypeError(
13
+ 'Cannot compute merkle root for zero transactions',
14
+ );
15
+ const errorWitnessNotSegwit = new TypeError(
16
+ 'Cannot compute witness commit for non-segwit block',
17
+ );
18
+ export class Block {
19
+ static fromBuffer(buffer) {
20
+ if (buffer.length < 80) throw new Error('Buffer too small (< 80 bytes)');
21
+ const bufferReader = new BufferReader(buffer);
22
+ const block = new Block();
23
+ block.version = bufferReader.readInt32();
24
+ block.prevHash = bufferReader.readSlice(32);
25
+ block.merkleRoot = bufferReader.readSlice(32);
26
+ block.timestamp = bufferReader.readUInt32();
27
+ block.bits = bufferReader.readUInt32();
28
+ block.nonce = bufferReader.readUInt32();
29
+ if (buffer.length === 80) return block;
30
+ const readTransaction = () => {
31
+ const tx = Transaction.fromBuffer(
32
+ bufferReader.buffer.slice(bufferReader.offset),
33
+ true,
34
+ );
35
+ bufferReader.offset += tx.byteLength();
36
+ return tx;
37
+ };
38
+ const nTransactions = bufferReader.readVarInt();
39
+ block.transactions = [];
40
+ for (let i = 0; i < nTransactions; ++i) {
41
+ const tx = readTransaction();
42
+ block.transactions.push(tx);
43
+ }
44
+ const witnessCommit = block.getWitnessCommit();
45
+ // This Block contains a witness commit
46
+ if (witnessCommit) block.witnessCommit = witnessCommit;
47
+ return block;
48
+ }
49
+ static fromHex(hex) {
50
+ return Block.fromBuffer(tools.fromHex(hex));
51
+ }
52
+ static calculateTarget(bits) {
53
+ const exponent = ((bits & 0xff000000) >> 24) - 3;
54
+ const mantissa = bits & 0x007fffff;
55
+ const target = new Uint8Array(32);
56
+ target[29 - exponent] = (mantissa >> 16) & 0xff;
57
+ target[30 - exponent] = (mantissa >> 8) & 0xff;
58
+ target[31 - exponent] = mantissa & 0xff;
59
+ return target;
60
+ }
61
+ static calculateMerkleRoot(transactions, forWitness) {
62
+ v.parse(v.array(v.object({ getHash: v.function() })), transactions);
63
+ if (transactions.length === 0) throw errorMerkleNoTxes;
64
+ if (forWitness && !txesHaveWitnessCommit(transactions))
65
+ throw errorWitnessNotSegwit;
66
+ const hashes = transactions.map(transaction =>
67
+ transaction.getHash(forWitness),
68
+ );
69
+ const rootHash = fastMerkleRoot(hashes, bcrypto.hash256);
70
+ return forWitness
71
+ ? bcrypto.hash256(
72
+ tools.concat([rootHash, transactions[0].ins[0].witness[0]]),
73
+ )
74
+ : rootHash;
75
+ }
76
+ version = 1;
77
+ prevHash = undefined;
78
+ merkleRoot = undefined;
79
+ timestamp = 0;
80
+ witnessCommit = undefined;
81
+ bits = 0;
82
+ nonce = 0;
83
+ transactions = undefined;
84
+ getWitnessCommit() {
85
+ if (!txesHaveWitnessCommit(this.transactions)) return null;
86
+ // The merkle root for the witness data is in an OP_RETURN output.
87
+ // There is no rule for the index of the output, so use filter to find it.
88
+ // The root is prepended with 0xaa21a9ed so check for 0x6a24aa21a9ed
89
+ // If multiple commits are found, the output with highest index is assumed.
90
+ const witnessCommits = this.transactions[0].outs
91
+ .filter(
92
+ out =>
93
+ tools.compare(
94
+ out.script.slice(0, 6),
95
+ Uint8Array.from([0x6a, 0x24, 0xaa, 0x21, 0xa9, 0xed]),
96
+ ) === 0,
97
+ )
98
+ .map(out => out.script.slice(6, 38));
99
+ if (witnessCommits.length === 0) return null;
100
+ // Use the commit with the highest output (should only be one though)
101
+ const result = witnessCommits[witnessCommits.length - 1];
102
+ if (!(result instanceof Uint8Array && result.length === 32)) return null;
103
+ return result;
104
+ }
105
+ hasWitnessCommit() {
106
+ if (
107
+ this.witnessCommit instanceof Uint8Array &&
108
+ this.witnessCommit.length === 32
109
+ )
110
+ return true;
111
+ if (this.getWitnessCommit() !== null) return true;
112
+ return false;
113
+ }
114
+ hasWitness() {
115
+ return anyTxHasWitness(this.transactions);
116
+ }
117
+ weight() {
118
+ const base = this.byteLength(false, false);
119
+ const total = this.byteLength(false, true);
120
+ return base * 3 + total;
121
+ }
122
+ byteLength(headersOnly, allowWitness = true) {
123
+ if (headersOnly || !this.transactions) return 80;
124
+ return (
125
+ 80 +
126
+ varuint.encodingLength(this.transactions.length) +
127
+ this.transactions.reduce((a, x) => a + x.byteLength(allowWitness), 0)
128
+ );
129
+ }
130
+ getHash() {
131
+ return bcrypto.hash256(this.toBuffer(true));
132
+ }
133
+ getId() {
134
+ return tools.toHex(reverseBuffer(this.getHash()));
135
+ }
136
+ getUTCDate() {
137
+ const date = new Date(0); // epoch
138
+ date.setUTCSeconds(this.timestamp);
139
+ return date;
140
+ }
141
+ // TODO: buffer, offset compatibility
142
+ toBuffer(headersOnly) {
143
+ const buffer = new Uint8Array(this.byteLength(headersOnly));
144
+ const bufferWriter = new BufferWriter(buffer);
145
+ bufferWriter.writeInt32(this.version);
146
+ bufferWriter.writeSlice(this.prevHash);
147
+ bufferWriter.writeSlice(this.merkleRoot);
148
+ bufferWriter.writeUInt32(this.timestamp);
149
+ bufferWriter.writeUInt32(this.bits);
150
+ bufferWriter.writeUInt32(this.nonce);
151
+ if (headersOnly || !this.transactions) return buffer;
152
+ const { bytes } = varuint.encode(
153
+ this.transactions.length,
154
+ buffer,
155
+ bufferWriter.offset,
156
+ );
157
+ bufferWriter.offset += bytes;
158
+ this.transactions.forEach(tx => {
159
+ const txSize = tx.byteLength(); // TODO: extract from toBuffer?
160
+ tx.toBuffer(buffer, bufferWriter.offset);
161
+ bufferWriter.offset += txSize;
162
+ });
163
+ return buffer;
164
+ }
165
+ toHex(headersOnly) {
166
+ return tools.toHex(this.toBuffer(headersOnly));
167
+ }
168
+ checkTxRoots() {
169
+ // If the Block has segwit transactions but no witness commit,
170
+ // there's no way it can be valid, so fail the check.
171
+ const hasWitnessCommit = this.hasWitnessCommit();
172
+ if (!hasWitnessCommit && this.hasWitness()) return false;
173
+ return (
174
+ this.__checkMerkleRoot() &&
175
+ (hasWitnessCommit ? this.__checkWitnessCommit() : true)
176
+ );
177
+ }
178
+ checkProofOfWork() {
179
+ const hash = reverseBuffer(this.getHash());
180
+ const target = Block.calculateTarget(this.bits);
181
+ return tools.compare(hash, target) <= 0;
182
+ }
183
+ __checkMerkleRoot() {
184
+ if (!this.transactions) throw errorMerkleNoTxes;
185
+ const actualMerkleRoot = Block.calculateMerkleRoot(this.transactions);
186
+ return tools.compare(this.merkleRoot, actualMerkleRoot) === 0;
187
+ }
188
+ __checkWitnessCommit() {
189
+ if (!this.transactions) throw errorMerkleNoTxes;
190
+ if (!this.hasWitnessCommit()) throw errorWitnessNotSegwit;
191
+ const actualWitnessCommit = Block.calculateMerkleRoot(
192
+ this.transactions,
193
+ true,
194
+ );
195
+ return tools.compare(this.witnessCommit, actualWitnessCommit) === 0;
196
+ }
197
+ }
198
+ function txesHaveWitnessCommit(transactions) {
199
+ return (
200
+ transactions instanceof Array &&
201
+ transactions[0] &&
202
+ transactions[0].ins &&
203
+ transactions[0].ins instanceof Array &&
204
+ transactions[0].ins[0] &&
205
+ transactions[0].ins[0].witness &&
206
+ transactions[0].ins[0].witness instanceof Array &&
207
+ transactions[0].ins[0].witness.length > 0
208
+ );
209
+ }
210
+ function anyTxHasWitness(transactions) {
211
+ return (
212
+ transactions instanceof Array &&
213
+ transactions.some(
214
+ tx =>
215
+ typeof tx === 'object' &&
216
+ tx.ins instanceof Array &&
217
+ tx.ins.some(
218
+ input =>
219
+ typeof input === 'object' &&
220
+ input.witness instanceof Array &&
221
+ input.witness.length > 0,
222
+ ),
223
+ )
224
+ );
225
+ }
@@ -0,0 +1,156 @@
1
+ import * as types from './types.js';
2
+ import * as varuint from 'varuint-bitcoin';
3
+ import * as v from 'valibot';
4
+ export { varuint };
5
+ import * as tools from 'uint8array-tools';
6
+ const MAX_JS_NUMBER = 0x001fffffffffffff;
7
+ // https://github.com/feross/buffer/blob/master/index.js#L1127
8
+ function verifuint(value, max) {
9
+ if (typeof value !== 'number' && typeof value !== 'bigint')
10
+ throw new Error('cannot write a non-number as a number');
11
+ if (value < 0 && value < BigInt(0))
12
+ throw new Error('specified a negative value for writing an unsigned value');
13
+ if (value > max && value > BigInt(max))
14
+ throw new Error('RangeError: value out of range');
15
+ if (Math.floor(Number(value)) !== Number(value))
16
+ throw new Error('value has a fractional component');
17
+ }
18
+ /**
19
+ * Reverses the order of bytes in a buffer.
20
+ * @param buffer - The buffer to reverse.
21
+ * @returns A new buffer with the bytes reversed.
22
+ */
23
+ export function reverseBuffer(buffer) {
24
+ if (buffer.length < 1) return buffer;
25
+ let j = buffer.length - 1;
26
+ let tmp = 0;
27
+ for (let i = 0; i < buffer.length / 2; i++) {
28
+ tmp = buffer[i];
29
+ buffer[i] = buffer[j];
30
+ buffer[j] = tmp;
31
+ j--;
32
+ }
33
+ return buffer;
34
+ }
35
+ export function cloneBuffer(buffer) {
36
+ const clone = new Uint8Array(buffer.length);
37
+ clone.set(buffer);
38
+ return clone;
39
+ }
40
+ /**
41
+ * Helper class for serialization of bitcoin data types into a pre-allocated buffer.
42
+ */
43
+ export class BufferWriter {
44
+ buffer;
45
+ offset;
46
+ static withCapacity(size) {
47
+ return new BufferWriter(new Uint8Array(size));
48
+ }
49
+ constructor(buffer, offset = 0) {
50
+ this.buffer = buffer;
51
+ this.offset = offset;
52
+ v.parse(v.tuple([types.BufferSchema, types.UInt32Schema]), [
53
+ buffer,
54
+ offset,
55
+ ]);
56
+ }
57
+ writeUInt8(i) {
58
+ this.offset = tools.writeUInt8(this.buffer, this.offset, i);
59
+ }
60
+ writeInt32(i) {
61
+ this.offset = tools.writeInt32(this.buffer, this.offset, i, 'LE');
62
+ }
63
+ writeInt64(i) {
64
+ this.offset = tools.writeInt64(this.buffer, this.offset, BigInt(i), 'LE');
65
+ }
66
+ writeUInt32(i) {
67
+ this.offset = tools.writeUInt32(this.buffer, this.offset, i, 'LE');
68
+ }
69
+ writeUInt64(i) {
70
+ this.offset = tools.writeUInt64(this.buffer, this.offset, BigInt(i), 'LE');
71
+ }
72
+ writeVarInt(i) {
73
+ const { bytes } = varuint.encode(i, this.buffer, this.offset);
74
+ this.offset += bytes;
75
+ }
76
+ writeSlice(slice) {
77
+ if (this.buffer.length < this.offset + slice.length) {
78
+ throw new Error('Cannot write slice out of bounds');
79
+ }
80
+ this.buffer.set(slice, this.offset);
81
+ this.offset += slice.length;
82
+ }
83
+ writeVarSlice(slice) {
84
+ this.writeVarInt(slice.length);
85
+ this.writeSlice(slice);
86
+ }
87
+ writeVector(vector) {
88
+ this.writeVarInt(vector.length);
89
+ vector.forEach(buf => this.writeVarSlice(buf));
90
+ }
91
+ end() {
92
+ if (this.buffer.length === this.offset) {
93
+ return this.buffer;
94
+ }
95
+ throw new Error(`buffer size ${this.buffer.length}, offset ${this.offset}`);
96
+ }
97
+ }
98
+ /**
99
+ * Helper class for reading of bitcoin data types from a buffer.
100
+ */
101
+ export class BufferReader {
102
+ buffer;
103
+ offset;
104
+ constructor(buffer, offset = 0) {
105
+ this.buffer = buffer;
106
+ this.offset = offset;
107
+ v.parse(v.tuple([types.BufferSchema, types.UInt32Schema]), [
108
+ buffer,
109
+ offset,
110
+ ]);
111
+ }
112
+ readUInt8() {
113
+ const result = tools.readUInt8(this.buffer, this.offset);
114
+ this.offset++;
115
+ return result;
116
+ }
117
+ readInt32() {
118
+ const result = tools.readInt32(this.buffer, this.offset, 'LE');
119
+ this.offset += 4;
120
+ return result;
121
+ }
122
+ readUInt32() {
123
+ const result = tools.readUInt32(this.buffer, this.offset, 'LE');
124
+ this.offset += 4;
125
+ return result;
126
+ }
127
+ readInt64() {
128
+ const result = tools.readInt64(this.buffer, this.offset, 'LE');
129
+ this.offset += 8;
130
+ return result;
131
+ }
132
+ readVarInt() {
133
+ const { bigintValue, bytes } = varuint.decode(this.buffer, this.offset);
134
+ this.offset += bytes;
135
+ return bigintValue;
136
+ }
137
+ readSlice(n) {
138
+ verifuint(n, MAX_JS_NUMBER);
139
+ const num = Number(n);
140
+ if (this.buffer.length < this.offset + num) {
141
+ throw new Error('Cannot read slice out of bounds');
142
+ }
143
+ const result = this.buffer.slice(this.offset, this.offset + num);
144
+ this.offset += num;
145
+ return result;
146
+ }
147
+ readVarSlice() {
148
+ return this.readSlice(this.readVarInt());
149
+ }
150
+ readVector() {
151
+ const count = this.readVarInt();
152
+ const vector = [];
153
+ for (let i = 0; i < count; i++) vector.push(this.readVarSlice());
154
+ return vector;
155
+ }
156
+ }
@@ -0,0 +1,123 @@
1
+ /**
2
+ * A module for hashing functions.
3
+ * include ripemd160、sha1、sha256、hash160、hash256、taggedHash
4
+ *
5
+ * @packageDocumentation
6
+ */
7
+ import { ripemd160 } from '@noble/hashes/ripemd160';
8
+ import { sha256 } from '@noble/hashes/sha256';
9
+ import * as tools from 'uint8array-tools';
10
+ export { ripemd160, sha256 };
11
+ export { sha1 } from '@noble/hashes/sha1';
12
+ /**
13
+ * Computes the HASH160 (RIPEMD-160 after SHA-256) of the given buffer.
14
+ *
15
+ * @param buffer - The input data to be hashed.
16
+ * @returns The HASH160 of the input buffer.
17
+ */
18
+ export function hash160(buffer) {
19
+ return ripemd160(sha256(buffer));
20
+ }
21
+ /**
22
+ * Computes the double SHA-256 hash of the given buffer.
23
+ *
24
+ * @param buffer - The input data to be hashed.
25
+ * @returns The double SHA-256 hash of the input buffer.
26
+ */
27
+ export function hash256(buffer) {
28
+ return sha256(sha256(buffer));
29
+ }
30
+ export const TAGS = [
31
+ 'BIP0340/challenge',
32
+ 'BIP0340/aux',
33
+ 'BIP0340/nonce',
34
+ 'TapLeaf',
35
+ 'TapBranch',
36
+ 'TapSighash',
37
+ 'TapTweak',
38
+ 'KeyAgg list',
39
+ 'KeyAgg coefficient',
40
+ ];
41
+ /**
42
+ * A collection of tagged hash prefixes used in various BIP (Bitcoin Improvement Proposals)
43
+ * and Taproot-related operations. Each prefix is represented as a `Uint8Array`.
44
+ *
45
+ * @constant
46
+ * @type {TaggedHashPrefixes}
47
+ *
48
+ * @property {'BIP0340/challenge'} - Prefix for BIP0340 challenge.
49
+ * @property {'BIP0340/aux'} - Prefix for BIP0340 auxiliary data.
50
+ * @property {'BIP0340/nonce'} - Prefix for BIP0340 nonce.
51
+ * @property {TapLeaf} - Prefix for Taproot leaf.
52
+ * @property {TapBranch} - Prefix for Taproot branch.
53
+ * @property {TapSighash} - Prefix for Taproot sighash.
54
+ * @property {TapTweak} - Prefix for Taproot tweak.
55
+ * @property {'KeyAgg list'} - Prefix for key aggregation list.
56
+ * @property {'KeyAgg coefficient'} - Prefix for key aggregation coefficient.
57
+ */
58
+ export const TAGGED_HASH_PREFIXES = {
59
+ 'BIP0340/challenge': Uint8Array.from([
60
+ 123, 181, 45, 122, 159, 239, 88, 50, 62, 177, 191, 122, 64, 125, 179, 130,
61
+ 210, 243, 242, 216, 27, 177, 34, 79, 73, 254, 81, 143, 109, 72, 211, 124,
62
+ 123, 181, 45, 122, 159, 239, 88, 50, 62, 177, 191, 122, 64, 125, 179, 130,
63
+ 210, 243, 242, 216, 27, 177, 34, 79, 73, 254, 81, 143, 109, 72, 211, 124,
64
+ ]),
65
+ 'BIP0340/aux': Uint8Array.from([
66
+ 241, 239, 78, 94, 192, 99, 202, 218, 109, 148, 202, 250, 157, 152, 126, 160,
67
+ 105, 38, 88, 57, 236, 193, 31, 151, 45, 119, 165, 46, 216, 193, 204, 144,
68
+ 241, 239, 78, 94, 192, 99, 202, 218, 109, 148, 202, 250, 157, 152, 126, 160,
69
+ 105, 38, 88, 57, 236, 193, 31, 151, 45, 119, 165, 46, 216, 193, 204, 144,
70
+ ]),
71
+ 'BIP0340/nonce': Uint8Array.from([
72
+ 7, 73, 119, 52, 167, 155, 203, 53, 91, 155, 140, 125, 3, 79, 18, 28, 244,
73
+ 52, 215, 62, 247, 45, 218, 25, 135, 0, 97, 251, 82, 191, 235, 47, 7, 73,
74
+ 119, 52, 167, 155, 203, 53, 91, 155, 140, 125, 3, 79, 18, 28, 244, 52, 215,
75
+ 62, 247, 45, 218, 25, 135, 0, 97, 251, 82, 191, 235, 47,
76
+ ]),
77
+ TapLeaf: Uint8Array.from([
78
+ 174, 234, 143, 220, 66, 8, 152, 49, 5, 115, 75, 88, 8, 29, 30, 38, 56, 211,
79
+ 95, 28, 181, 64, 8, 212, 211, 87, 202, 3, 190, 120, 233, 238, 174, 234, 143,
80
+ 220, 66, 8, 152, 49, 5, 115, 75, 88, 8, 29, 30, 38, 56, 211, 95, 28, 181,
81
+ 64, 8, 212, 211, 87, 202, 3, 190, 120, 233, 238,
82
+ ]),
83
+ TapBranch: Uint8Array.from([
84
+ 25, 65, 161, 242, 229, 110, 185, 95, 162, 169, 241, 148, 190, 92, 1, 247,
85
+ 33, 111, 51, 237, 130, 176, 145, 70, 52, 144, 208, 91, 245, 22, 160, 21, 25,
86
+ 65, 161, 242, 229, 110, 185, 95, 162, 169, 241, 148, 190, 92, 1, 247, 33,
87
+ 111, 51, 237, 130, 176, 145, 70, 52, 144, 208, 91, 245, 22, 160, 21,
88
+ ]),
89
+ TapSighash: Uint8Array.from([
90
+ 244, 10, 72, 223, 75, 42, 112, 200, 180, 146, 75, 242, 101, 70, 97, 237, 61,
91
+ 149, 253, 102, 163, 19, 235, 135, 35, 117, 151, 198, 40, 228, 160, 49, 244,
92
+ 10, 72, 223, 75, 42, 112, 200, 180, 146, 75, 242, 101, 70, 97, 237, 61, 149,
93
+ 253, 102, 163, 19, 235, 135, 35, 117, 151, 198, 40, 228, 160, 49,
94
+ ]),
95
+ TapTweak: Uint8Array.from([
96
+ 232, 15, 225, 99, 156, 156, 160, 80, 227, 175, 27, 57, 193, 67, 198, 62, 66,
97
+ 156, 188, 235, 21, 217, 64, 251, 181, 197, 161, 244, 175, 87, 197, 233, 232,
98
+ 15, 225, 99, 156, 156, 160, 80, 227, 175, 27, 57, 193, 67, 198, 62, 66, 156,
99
+ 188, 235, 21, 217, 64, 251, 181, 197, 161, 244, 175, 87, 197, 233,
100
+ ]),
101
+ 'KeyAgg list': Uint8Array.from([
102
+ 72, 28, 151, 28, 60, 11, 70, 215, 240, 178, 117, 174, 89, 141, 78, 44, 126,
103
+ 215, 49, 156, 89, 74, 92, 110, 199, 158, 160, 212, 153, 2, 148, 240, 72, 28,
104
+ 151, 28, 60, 11, 70, 215, 240, 178, 117, 174, 89, 141, 78, 44, 126, 215, 49,
105
+ 156, 89, 74, 92, 110, 199, 158, 160, 212, 153, 2, 148, 240,
106
+ ]),
107
+ 'KeyAgg coefficient': Uint8Array.from([
108
+ 191, 201, 4, 3, 77, 28, 136, 232, 200, 14, 34, 229, 61, 36, 86, 109, 100,
109
+ 130, 78, 214, 66, 114, 129, 192, 145, 0, 249, 77, 205, 82, 201, 129, 191,
110
+ 201, 4, 3, 77, 28, 136, 232, 200, 14, 34, 229, 61, 36, 86, 109, 100, 130,
111
+ 78, 214, 66, 114, 129, 192, 145, 0, 249, 77, 205, 82, 201, 129,
112
+ ]),
113
+ };
114
+ /**
115
+ * Computes a tagged hash using the specified prefix and data.
116
+ *
117
+ * @param prefix - The prefix to use for the tagged hash. This should be one of the values from the `TaggedHashPrefix` enum.
118
+ * @param data - The data to hash, provided as a `Uint8Array`.
119
+ * @returns The resulting tagged hash as a `Uint8Array`.
120
+ */
121
+ export function taggedHash(prefix, data) {
122
+ return sha256(tools.concat([TAGGED_HASH_PREFIXES[prefix], data]));
123
+ }
@@ -0,0 +1,108 @@
1
+ import * as tools from 'uint8array-tools';
2
+ const _ECCLIB_CACHE = {};
3
+ /**
4
+ * Initializes the ECC library with the provided instance.
5
+ * If `eccLib` is `undefined`, the library will be cleared.
6
+ * If `eccLib` is a new instance, it will be verified before setting it as the active library.
7
+ *
8
+ * @param eccLib The instance of the ECC library to initialize.
9
+ * @param opts Extra initialization options. Use {DANGER_DO_NOT_VERIFY_ECCLIB:true} if ecc verification should not be executed. Not recommended!
10
+ */
11
+ export function initEccLib(eccLib, opts) {
12
+ if (!eccLib) {
13
+ // allow clearing the library
14
+ _ECCLIB_CACHE.eccLib = eccLib;
15
+ } else if (eccLib !== _ECCLIB_CACHE.eccLib) {
16
+ if (!opts?.DANGER_DO_NOT_VERIFY_ECCLIB)
17
+ // new instance, verify it
18
+ verifyEcc(eccLib);
19
+ _ECCLIB_CACHE.eccLib = eccLib;
20
+ }
21
+ }
22
+ /**
23
+ * Retrieves the ECC Library instance.
24
+ * Throws an error if the ECC Library is not provided.
25
+ * You must call initEccLib() with a valid TinySecp256k1Interface instance before calling this function.
26
+ * @returns The ECC Library instance.
27
+ * @throws Error if the ECC Library is not provided.
28
+ */
29
+ export function getEccLib() {
30
+ if (!_ECCLIB_CACHE.eccLib)
31
+ throw new Error(
32
+ 'No ECC Library provided. You must call initEccLib() with a valid TinySecp256k1Interface instance',
33
+ );
34
+ return _ECCLIB_CACHE.eccLib;
35
+ }
36
+ const h = hex => tools.fromHex(hex);
37
+ /**
38
+ * Verifies the ECC functionality.
39
+ *
40
+ * @param ecc - The TinySecp256k1Interface object.
41
+ */
42
+ function verifyEcc(ecc) {
43
+ assert(typeof ecc.isXOnlyPoint === 'function');
44
+ assert(
45
+ ecc.isXOnlyPoint(
46
+ h('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'),
47
+ ),
48
+ );
49
+ assert(
50
+ ecc.isXOnlyPoint(
51
+ h('fffffffffffffffffffffffffffffffffffffffffffffffffffffffeeffffc2e'),
52
+ ),
53
+ );
54
+ assert(
55
+ ecc.isXOnlyPoint(
56
+ h('f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9'),
57
+ ),
58
+ );
59
+ assert(
60
+ ecc.isXOnlyPoint(
61
+ h('0000000000000000000000000000000000000000000000000000000000000001'),
62
+ ),
63
+ );
64
+ assert(
65
+ !ecc.isXOnlyPoint(
66
+ h('0000000000000000000000000000000000000000000000000000000000000000'),
67
+ ),
68
+ );
69
+ assert(
70
+ !ecc.isXOnlyPoint(
71
+ h('fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'),
72
+ ),
73
+ );
74
+ assert(typeof ecc.xOnlyPointAddTweak === 'function');
75
+ tweakAddVectors.forEach(t => {
76
+ const r = ecc.xOnlyPointAddTweak(h(t.pubkey), h(t.tweak));
77
+ if (t.result === null) {
78
+ assert(r === null);
79
+ } else {
80
+ assert(r !== null);
81
+ assert(r.parity === t.parity);
82
+ assert(tools.compare(r.xOnlyPubkey, h(t.result)) === 0);
83
+ }
84
+ });
85
+ }
86
+ function assert(bool) {
87
+ if (!bool) throw new Error('ecc library invalid');
88
+ }
89
+ const tweakAddVectors = [
90
+ {
91
+ pubkey: '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
92
+ tweak: 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140',
93
+ parity: -1,
94
+ result: null,
95
+ },
96
+ {
97
+ pubkey: '1617d38ed8d8657da4d4761e8057bc396ea9e4b9d29776d4be096016dbd2509b',
98
+ tweak: 'a8397a935f0dfceba6ba9618f6451ef4d80637abf4e6af2669fbc9de6a8fd2ac',
99
+ parity: 1,
100
+ result: 'e478f99dab91052ab39a33ea35fd5e6e4933f4d28023cd597c9a1f6760346adf',
101
+ },
102
+ {
103
+ pubkey: '2c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991',
104
+ tweak: '823c3cd2142744b075a87eade7e1b8678ba308d566226a0056ca2b7a76f86b47',
105
+ parity: 0,
106
+ result: '9534f8dc8c6deda2dc007655981c78b49c5d96c778fbf363462a11ec9dfd948c',
107
+ },
108
+ ];
@@ -0,0 +1,12 @@
1
+ import * as address from './address.js';
2
+ import * as crypto from './crypto.js';
3
+ import * as networks from './networks.js';
4
+ import * as payments from './payments/index.js';
5
+ import * as script from './script.js';
6
+ export { address, crypto, networks, payments, script };
7
+ export { Block } from './block.js';
8
+ export { Psbt, toXOnly } from './psbt.js';
9
+ /** @hidden */
10
+ export { OPS as opcodes } from './ops.js';
11
+ export { Transaction } from './transaction.js';
12
+ export { initEccLib } from './ecc_lib.js';
@@ -0,0 +1,27 @@
1
+ import * as tools from 'uint8array-tools';
2
+ /**
3
+ * Calculates the Merkle root of an array of buffers using a specified digest function.
4
+ *
5
+ * @param values - The array of buffers.
6
+ * @param digestFn - The digest function used to calculate the hash of the concatenated buffers.
7
+ * @returns The Merkle root as a buffer.
8
+ * @throws {TypeError} If the values parameter is not an array or the digestFn parameter is not a function.
9
+ */
10
+ export function fastMerkleRoot(values, digestFn) {
11
+ if (!Array.isArray(values)) throw TypeError('Expected values Array');
12
+ if (typeof digestFn !== 'function')
13
+ throw TypeError('Expected digest Function');
14
+ let length = values.length;
15
+ const results = values.concat();
16
+ while (length > 1) {
17
+ let j = 0;
18
+ for (let i = 0; i < length; i += 2, ++j) {
19
+ const left = results[i];
20
+ const right = i + 1 === length ? left : results[i + 1];
21
+ const data = tools.concat([left, right]);
22
+ results[j] = digestFn(data);
23
+ }
24
+ length = j;
25
+ }
26
+ return results[0];
27
+ }