@btc-vision/bitcoin 7.0.0-beta.0 → 7.0.0-beta.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.
- package/README.md +112 -13
- package/benchmark-compare/BENCHMARK.md +74 -59
- package/benchmark-compare/compare.bench.ts +249 -96
- package/benchmark-compare/harness.ts +23 -25
- package/benchmark-compare/package.json +1 -0
- package/browser/address.d.ts +4 -4
- package/browser/address.d.ts.map +1 -1
- package/browser/chunks/{psbt-parallel-B-dfm5GZ.js → psbt-parallel-jZ6QcCnM.js} +3128 -2731
- package/browser/index.d.ts +1 -1
- package/browser/index.d.ts.map +1 -1
- package/browser/index.js +603 -585
- package/browser/io/base58check.d.ts +1 -25
- package/browser/io/base58check.d.ts.map +1 -1
- package/browser/io/base64.d.ts.map +1 -1
- package/browser/networks.d.ts +1 -0
- package/browser/networks.d.ts.map +1 -1
- package/browser/payments/bip341.d.ts +17 -0
- package/browser/payments/bip341.d.ts.map +1 -1
- package/browser/payments/index.d.ts +3 -2
- package/browser/payments/index.d.ts.map +1 -1
- package/browser/payments/p2mr.d.ts +169 -0
- package/browser/payments/p2mr.d.ts.map +1 -0
- package/browser/payments/types.d.ts +11 -1
- package/browser/payments/types.d.ts.map +1 -1
- package/browser/psbt/bip371.d.ts +30 -0
- package/browser/psbt/bip371.d.ts.map +1 -1
- package/browser/psbt/psbtutils.d.ts +1 -0
- package/browser/psbt/psbtutils.d.ts.map +1 -1
- package/browser/psbt.d.ts.map +1 -1
- package/browser/workers/index.js +9 -9
- package/build/address.d.ts +4 -4
- package/build/address.d.ts.map +1 -1
- package/build/address.js +11 -1
- package/build/address.js.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js.map +1 -1
- package/build/io/base58check.d.ts +1 -25
- package/build/io/base58check.d.ts.map +1 -1
- package/build/io/base58check.js +1 -31
- package/build/io/base58check.js.map +1 -1
- package/build/io/base64.d.ts.map +1 -1
- package/build/io/base64.js +3 -0
- package/build/io/base64.js.map +1 -1
- package/build/networks.d.ts +1 -0
- package/build/networks.d.ts.map +1 -1
- package/build/networks.js +12 -0
- package/build/networks.js.map +1 -1
- package/build/payments/bip341.d.ts +17 -0
- package/build/payments/bip341.d.ts.map +1 -1
- package/build/payments/bip341.js +32 -1
- package/build/payments/bip341.js.map +1 -1
- package/build/payments/index.d.ts +3 -2
- package/build/payments/index.d.ts.map +1 -1
- package/build/payments/index.js +2 -1
- package/build/payments/index.js.map +1 -1
- package/build/payments/p2mr.d.ts +178 -0
- package/build/payments/p2mr.d.ts.map +1 -0
- package/build/payments/p2mr.js +555 -0
- package/build/payments/p2mr.js.map +1 -0
- package/build/payments/types.d.ts +11 -1
- package/build/payments/types.d.ts.map +1 -1
- package/build/payments/types.js +1 -0
- package/build/payments/types.js.map +1 -1
- package/build/psbt/bip371.d.ts +30 -0
- package/build/psbt/bip371.d.ts.map +1 -1
- package/build/psbt/bip371.js +80 -15
- package/build/psbt/bip371.js.map +1 -1
- package/build/psbt/psbtutils.d.ts +1 -0
- package/build/psbt/psbtutils.d.ts.map +1 -1
- package/build/psbt/psbtutils.js +2 -0
- package/build/psbt/psbtutils.js.map +1 -1
- package/build/psbt.d.ts.map +1 -1
- package/build/psbt.js +3 -2
- package/build/psbt.js.map +1 -1
- package/build/pubkey.js +1 -1
- package/build/pubkey.js.map +1 -1
- package/build/tsconfig.build.tsbuildinfo +1 -1
- package/documentation/README.md +122 -0
- package/documentation/address.md +820 -0
- package/documentation/block.md +679 -0
- package/documentation/crypto.md +461 -0
- package/documentation/ecc.md +584 -0
- package/documentation/errors.md +656 -0
- package/documentation/io.md +942 -0
- package/documentation/networks.md +625 -0
- package/documentation/p2mr.md +380 -0
- package/documentation/payments.md +1485 -0
- package/documentation/psbt.md +1400 -0
- package/documentation/script.md +730 -0
- package/documentation/taproot.md +670 -0
- package/documentation/transaction.md +943 -0
- package/documentation/types.md +587 -0
- package/documentation/workers.md +1007 -0
- package/eslint.config.js +3 -0
- package/package.json +17 -14
- package/src/address.ts +22 -10
- package/src/index.ts +1 -0
- package/src/io/base58check.ts +1 -35
- package/src/io/base64.ts +5 -0
- package/src/networks.ts +13 -0
- package/src/payments/bip341.ts +36 -1
- package/src/payments/index.ts +4 -0
- package/src/payments/p2mr.ts +660 -0
- package/src/payments/types.ts +12 -0
- package/src/psbt/bip371.ts +84 -13
- package/src/psbt/psbtutils.ts +2 -0
- package/src/psbt.ts +4 -2
- package/src/pubkey.ts +1 -1
- package/test/bitcoin.core.spec.ts +1 -1
- package/test/fixtures/p2mr.json +270 -0
- package/test/integration/taproot.spec.ts +7 -3
- package/test/opnetTestnet.spec.ts +302 -0
- package/test/payments.spec.ts +3 -1
- package/test/psbt.spec.ts +297 -2
- package/test/tsconfig.json +2 -2
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
# Cryptographic Hash Functions
|
|
2
|
+
|
|
3
|
+
This module provides all cryptographic hashing primitives used throughout the Bitcoin protocol. It exposes single-pass hashes (`sha256`, `sha1`, `ripemd160`), composite hashes (`hash160`, `hash256`), and BIP340 tagged hashes (`taggedHash`) used by Taproot.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
| Function | Algorithm | Output Size | Primary Bitcoin Use |
|
|
8
|
+
|----------|-----------|-------------|---------------------|
|
|
9
|
+
| `sha256` | SHA-256 | 32 bytes (`Bytes32`) | SegWit v1 sighash components, witness commitments |
|
|
10
|
+
| `sha1` | SHA-1 | 20 bytes (`Bytes20`) | `OP_SHA1` script opcode |
|
|
11
|
+
| `ripemd160` | RIPEMD-160 | 20 bytes (`Bytes20`) | `OP_RIPEMD160` script opcode |
|
|
12
|
+
| `hash160` | RIPEMD-160(SHA-256(x)) | 20 bytes (`Bytes20`) | P2PKH addresses, P2SH addresses, P2WPKH witness programs |
|
|
13
|
+
| `hash256` | SHA-256(SHA-256(x)) | 32 bytes (`Bytes32`) | Block headers, transaction IDs (txid), legacy sighash |
|
|
14
|
+
| `taggedHash` | SHA-256(tag_prefix \|\| data) | 32 bytes (`Bytes32`) | Taproot (BIP340/341): key tweaking, leaf/branch hashing, Schnorr signatures |
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import {
|
|
22
|
+
sha256,
|
|
23
|
+
sha1,
|
|
24
|
+
ripemd160,
|
|
25
|
+
hash160,
|
|
26
|
+
hash256,
|
|
27
|
+
taggedHash,
|
|
28
|
+
TAGS,
|
|
29
|
+
TAGGED_HASH_PREFIXES,
|
|
30
|
+
} from '@btc-vision/bitcoin';
|
|
31
|
+
|
|
32
|
+
// Or via the crypto namespace
|
|
33
|
+
import { crypto } from '@btc-vision/bitcoin';
|
|
34
|
+
crypto.sha256(data);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## sha256
|
|
40
|
+
|
|
41
|
+
Computes the SHA-256 hash of the input data.
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
function sha256(data: Uint8Array): Bytes32
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
| Parameter | Type | Description |
|
|
48
|
+
|-----------|------|-------------|
|
|
49
|
+
| `data` | `Uint8Array` | Arbitrary input bytes |
|
|
50
|
+
| **Returns** | `Bytes32` | 32-byte SHA-256 digest |
|
|
51
|
+
|
|
52
|
+
SHA-256 is the foundational hash in Bitcoin. While it is rarely used as a single pass for addresses or block identification (those use `hash256` or `hash160`), it is used directly in SegWit v1 (BIP 143 / BIP 341) sighash computation to hash individual transaction components (prevouts, sequences, amounts, outputs, script pubkeys) before they are assembled into the final sighash message.
|
|
53
|
+
|
|
54
|
+
### Example
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { sha256 } from '@btc-vision/bitcoin';
|
|
58
|
+
|
|
59
|
+
const data = new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f]); // "Hello"
|
|
60
|
+
const digest = sha256(data);
|
|
61
|
+
// digest is a 32-byte Uint8Array (Bytes32)
|
|
62
|
+
console.log(digest.length); // 32
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## sha1
|
|
68
|
+
|
|
69
|
+
Computes the SHA-1 hash of the input data.
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
function sha1(data: Uint8Array): Bytes20
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
| Parameter | Type | Description |
|
|
76
|
+
|-----------|------|-------------|
|
|
77
|
+
| `data` | `Uint8Array` | Arbitrary input bytes |
|
|
78
|
+
| **Returns** | `Bytes20` | 20-byte SHA-1 digest |
|
|
79
|
+
|
|
80
|
+
SHA-1 is available in Bitcoin Script via the `OP_SHA1` opcode. It is not used in standard transaction workflows but is required for certain specialized scripts.
|
|
81
|
+
|
|
82
|
+
### Example
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { sha1 } from '@btc-vision/bitcoin';
|
|
86
|
+
|
|
87
|
+
const data = new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f]);
|
|
88
|
+
const digest = sha1(data);
|
|
89
|
+
console.log(digest.length); // 20
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## ripemd160
|
|
95
|
+
|
|
96
|
+
Computes the RIPEMD-160 hash of the input data.
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
function ripemd160(data: Uint8Array): Bytes20
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
| Parameter | Type | Description |
|
|
103
|
+
|-----------|------|-------------|
|
|
104
|
+
| `data` | `Uint8Array` | Arbitrary input bytes |
|
|
105
|
+
| **Returns** | `Bytes20` | 20-byte RIPEMD-160 digest |
|
|
106
|
+
|
|
107
|
+
RIPEMD-160 is available in Bitcoin Script via the `OP_RIPEMD160` opcode. On its own it is not commonly used in standard Bitcoin payments, but it is a core component of the `hash160` composite hash (see below).
|
|
108
|
+
|
|
109
|
+
### Example
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
import { ripemd160 } from '@btc-vision/bitcoin';
|
|
113
|
+
|
|
114
|
+
const data = new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f]);
|
|
115
|
+
const digest = ripemd160(data);
|
|
116
|
+
console.log(digest.length); // 20
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## hash160
|
|
122
|
+
|
|
123
|
+
Computes RIPEMD-160(SHA-256(data)), the standard 20-byte address hash used throughout Bitcoin.
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
function hash160(data: Uint8Array): Bytes20
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
| Parameter | Type | Description |
|
|
130
|
+
|-----------|------|-------------|
|
|
131
|
+
| `data` | `Uint8Array` | Arbitrary input bytes (typically a public key or redeem script) |
|
|
132
|
+
| **Returns** | `Bytes20` | 20-byte composite digest |
|
|
133
|
+
|
|
134
|
+
`hash160` is the most widely used address-derivation hash in Bitcoin:
|
|
135
|
+
|
|
136
|
+
- **P2PKH** (Pay-to-Public-Key-Hash): The output script contains `hash160(compressed_pubkey)`. This is what produces classic `1...` Bitcoin addresses.
|
|
137
|
+
- **P2SH** (Pay-to-Script-Hash): The output script contains `hash160(redeem_script)`. This produces `3...` addresses.
|
|
138
|
+
- **P2WPKH** (Pay-to-Witness-Public-Key-Hash): The witness program is `hash160(compressed_pubkey)`. This produces `bc1q...` bech32 addresses.
|
|
139
|
+
|
|
140
|
+
The `OP_HASH160` opcode in Bitcoin Script performs exactly this operation.
|
|
141
|
+
|
|
142
|
+
### Example
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { hash160 } from '@btc-vision/bitcoin';
|
|
146
|
+
|
|
147
|
+
// Hash a compressed public key to derive a P2PKH address hash
|
|
148
|
+
const compressedPubkey = new Uint8Array(33); // 33-byte compressed public key
|
|
149
|
+
const pubkeyHash = hash160(compressedPubkey);
|
|
150
|
+
console.log(pubkeyHash.length); // 20
|
|
151
|
+
|
|
152
|
+
// This 20-byte hash is what goes into a P2PKH output script:
|
|
153
|
+
// OP_DUP OP_HASH160 <pubkeyHash> OP_EQUALVERIFY OP_CHECKSIG
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Usage in P2PKH Address Derivation
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
import { payments } from '@btc-vision/bitcoin';
|
|
160
|
+
import type { PublicKey } from '@btc-vision/bitcoin';
|
|
161
|
+
|
|
162
|
+
// P2PKH internally calls hash160(pubkey) to derive the address
|
|
163
|
+
const payment = payments.P2PKH.fromPubkey(compressedPubkey as PublicKey);
|
|
164
|
+
console.log(payment.hash); // 20-byte hash160 of the public key (Bytes20 | undefined)
|
|
165
|
+
console.log(payment.address); // Base58Check-encoded address (string | undefined)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Usage in P2SH
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { payments } from '@btc-vision/bitcoin';
|
|
172
|
+
|
|
173
|
+
// P2SH internally calls hash160(redeemScript) for the script hash
|
|
174
|
+
const payment = payments.P2SH.fromRedeem({ output: redeemScript });
|
|
175
|
+
console.log(payment.hash); // 20-byte hash160 of the redeem script (Bytes20 | undefined)
|
|
176
|
+
console.log(payment.address); // Base58Check-encoded address (string | undefined)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## hash256
|
|
182
|
+
|
|
183
|
+
Computes SHA-256(SHA-256(data)), the double-SHA-256 hash used for block headers and transaction identifiers.
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
function hash256(data: Uint8Array): Bytes32
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
| Parameter | Type | Description |
|
|
190
|
+
|-----------|------|-------------|
|
|
191
|
+
| `data` | `Uint8Array` | Arbitrary input bytes (typically a serialized block header or transaction) |
|
|
192
|
+
| **Returns** | `Bytes32` | 32-byte double-SHA-256 digest |
|
|
193
|
+
|
|
194
|
+
`hash256` (double SHA-256) is the backbone of Bitcoin's proof-of-work and transaction identification:
|
|
195
|
+
|
|
196
|
+
- **Block header hashing**: The 80-byte block header is double-SHA-256 hashed to produce the block hash. Miners must find a nonce such that this hash is below the target threshold.
|
|
197
|
+
- **Transaction IDs (txid)**: Every transaction is identified by the double-SHA-256 of its serialized form (excluding witness data).
|
|
198
|
+
- **Merkle tree construction**: The transaction merkle root in each block is built by pairwise double-SHA-256 hashing of transaction IDs.
|
|
199
|
+
- **Legacy sighash**: Pre-SegWit signature hashes use `hash256` over the sighash preimage.
|
|
200
|
+
- **BIP 143 sighash (SegWit v0)**: The intermediate components (hashPrevouts, hashSequence, hashOutputs) and the final sighash digest are computed with `hash256`.
|
|
201
|
+
|
|
202
|
+
### Example
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
import { hash256 } from '@btc-vision/bitcoin';
|
|
206
|
+
|
|
207
|
+
// Double-SHA-256 of arbitrary data
|
|
208
|
+
const data = new Uint8Array([0x01, 0x00, 0x00, 0x00]);
|
|
209
|
+
const digest = hash256(data);
|
|
210
|
+
console.log(digest.length); // 32
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Block Header Hashing
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
import { Block } from '@btc-vision/bitcoin';
|
|
217
|
+
|
|
218
|
+
const block = Block.fromHex(blockHex);
|
|
219
|
+
|
|
220
|
+
// Block.getHash() internally calls hash256(serialized_80_byte_header)
|
|
221
|
+
const blockHash = block.getHash();
|
|
222
|
+
console.log(blockHash.length); // 32
|
|
223
|
+
|
|
224
|
+
// The block ID is the hash in reversed byte order (display convention)
|
|
225
|
+
console.log(block.getId()); // hex string as shown in block explorers
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Transaction ID Computation
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
import { Transaction } from '@btc-vision/bitcoin';
|
|
232
|
+
|
|
233
|
+
const tx = Transaction.fromHex(txHex);
|
|
234
|
+
|
|
235
|
+
// tx.getHash() internally calls hash256(serialized_tx_without_witness)
|
|
236
|
+
const txid = tx.getHash();
|
|
237
|
+
console.log(txid.length); // 32
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Merkle Tree
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
import { Block } from '@btc-vision/bitcoin';
|
|
244
|
+
|
|
245
|
+
// Block.calculateMerkleRoot uses hash256 for pairwise merkle node hashing
|
|
246
|
+
const merkleRoot = Block.calculateMerkleRoot(transactions);
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## taggedHash
|
|
252
|
+
|
|
253
|
+
Computes a BIP340-style tagged hash: `SHA-256(SHA-256(tag) || SHA-256(tag) || data)`.
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
function taggedHash(prefix: TaggedHashPrefix, data: Uint8Array): Bytes32
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
| Parameter | Type | Description |
|
|
260
|
+
|-----------|------|-------------|
|
|
261
|
+
| `prefix` | `TaggedHashPrefix` | One of the predefined tag names (see TAGS below) |
|
|
262
|
+
| `data` | `Uint8Array` | Input data to hash |
|
|
263
|
+
| **Returns** | `Bytes32` | 32-byte tagged hash digest |
|
|
264
|
+
|
|
265
|
+
Tagged hashing was introduced by BIP340 (Schnorr signatures) and BIP341 (Taproot) to provide domain separation. Each tag produces a different hash function, ensuring that a hash computed in one context cannot collide with a hash in another context. The tag prefix (`SHA-256(tag) || SHA-256(tag)`) is prepended to the data before the final SHA-256, making it impossible for two different tags to produce the same output for the same input.
|
|
266
|
+
|
|
267
|
+
The library precomputes the 64-byte tag prefixes in `TAGGED_HASH_PREFIXES` for performance, avoiding redundant SHA-256 computations of the tag string on every call.
|
|
268
|
+
|
|
269
|
+
### Example
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
import { taggedHash } from '@btc-vision/bitcoin';
|
|
273
|
+
|
|
274
|
+
// Compute a TapTweak tagged hash (used when tweaking an internal public key)
|
|
275
|
+
const tweakData = new Uint8Array(64); // e.g., internal_pubkey || merkle_root
|
|
276
|
+
const tweakHash = taggedHash('TapTweak', tweakData);
|
|
277
|
+
console.log(tweakHash.length); // 32
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Taproot Leaf Hashing
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
import { tapleafHash, LEAF_VERSION_TAPSCRIPT } from '@btc-vision/bitcoin';
|
|
284
|
+
|
|
285
|
+
// tapleafHash internally calls taggedHash('TapLeaf', version || script_length || script)
|
|
286
|
+
const leafHash = tapleafHash({
|
|
287
|
+
output: leafScript,
|
|
288
|
+
version: LEAF_VERSION_TAPSCRIPT,
|
|
289
|
+
});
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Taproot Branch Hashing
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
import { tapBranchHash } from '@btc-vision/bitcoin';
|
|
296
|
+
|
|
297
|
+
// tapBranchHash internally calls taggedHash('TapBranch', left || right)
|
|
298
|
+
const branchHash = tapBranchHash(leftHash, rightHash);
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Taproot Sighash
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
// The BIP341 sighash for SegWit v1 transactions uses taggedHash('TapSighash', ...)
|
|
305
|
+
// This is handled internally by Transaction.hashForWitnessV1()
|
|
306
|
+
const sighash = tx.hashForWitnessV1(inputIndex, prevOutScripts, values, hashType);
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## TAGS
|
|
312
|
+
|
|
313
|
+
A readonly tuple of all recognized BIP340/BIP341/MuSig2 tag names.
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
const TAGS = [
|
|
317
|
+
'BIP0340/challenge',
|
|
318
|
+
'BIP0340/aux',
|
|
319
|
+
'BIP0340/nonce',
|
|
320
|
+
'TapLeaf',
|
|
321
|
+
'TapBranch',
|
|
322
|
+
'TapSighash',
|
|
323
|
+
'TapTweak',
|
|
324
|
+
'KeyAgg list',
|
|
325
|
+
'KeyAgg coefficient',
|
|
326
|
+
] as const;
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
| Tag | BIP | Purpose |
|
|
330
|
+
|-----|-----|---------|
|
|
331
|
+
| `BIP0340/challenge` | BIP 340 | Schnorr signature challenge hash `e = H(R \|\| P \|\| m)` |
|
|
332
|
+
| `BIP0340/aux` | BIP 340 | Auxiliary randomness in nonce generation |
|
|
333
|
+
| `BIP0340/nonce` | BIP 340 | Deterministic nonce derivation |
|
|
334
|
+
| `TapLeaf` | BIP 341 | Hashing individual tapscript leaves |
|
|
335
|
+
| `TapBranch` | BIP 341 | Hashing pairs of child nodes in the Taproot Merkle tree |
|
|
336
|
+
| `TapSighash` | BIP 341 | Computing the sighash for SegWit v1 (Taproot) inputs |
|
|
337
|
+
| `TapTweak` | BIP 341 | Tweaking the internal public key with the Merkle root |
|
|
338
|
+
| `KeyAgg list` | BIP 327 (MuSig2) | Key aggregation list commitment |
|
|
339
|
+
| `KeyAgg coefficient` | BIP 327 (MuSig2) | Key aggregation coefficient derivation |
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
## TaggedHashPrefix
|
|
344
|
+
|
|
345
|
+
A union type of all valid tag strings. Only these strings are accepted by `taggedHash()`.
|
|
346
|
+
|
|
347
|
+
```typescript
|
|
348
|
+
type TaggedHashPrefix = (typeof TAGS)[number];
|
|
349
|
+
// Equivalent to:
|
|
350
|
+
// 'BIP0340/challenge' | 'BIP0340/aux' | 'BIP0340/nonce' |
|
|
351
|
+
// 'TapLeaf' | 'TapBranch' | 'TapSighash' | 'TapTweak' |
|
|
352
|
+
// 'KeyAgg list' | 'KeyAgg coefficient'
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## TAGGED_HASH_PREFIXES
|
|
358
|
+
|
|
359
|
+
A precomputed map from each `TaggedHashPrefix` to its 64-byte prefix (`SHA-256(tag) || SHA-256(tag)`). These are computed once and reused on every call to `taggedHash()`, avoiding the overhead of hashing the tag string each time.
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
const TAGGED_HASH_PREFIXES: { [key in TaggedHashPrefix]: Uint8Array }
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
Each entry is exactly 64 bytes: the first 32 bytes are `SHA-256(tag)` and the second 32 bytes are an identical copy. When `taggedHash(prefix, data)` is called, it computes:
|
|
366
|
+
|
|
367
|
+
```
|
|
368
|
+
SHA-256( TAGGED_HASH_PREFIXES[prefix] || data )
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
This follows the BIP340 specification:
|
|
372
|
+
|
|
373
|
+
```
|
|
374
|
+
tagged_hash(tag, msg) = SHA-256(SHA-256(tag) || SHA-256(tag) || msg)
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Example: Verifying a Prefix
|
|
378
|
+
|
|
379
|
+
```typescript
|
|
380
|
+
import { sha256, TAGGED_HASH_PREFIXES } from '@btc-vision/bitcoin';
|
|
381
|
+
|
|
382
|
+
// The prefix for 'TapTweak' should be SHA-256("TapTweak") repeated twice
|
|
383
|
+
const tagBytes = new TextEncoder().encode('TapTweak');
|
|
384
|
+
const tagHash = sha256(tagBytes);
|
|
385
|
+
|
|
386
|
+
const prefix = TAGGED_HASH_PREFIXES['TapTweak'];
|
|
387
|
+
console.log(prefix.length); // 64
|
|
388
|
+
|
|
389
|
+
// First 32 bytes === SHA-256("TapTweak")
|
|
390
|
+
console.log(prefix.subarray(0, 32)); // equals tagHash
|
|
391
|
+
// Second 32 bytes === SHA-256("TapTweak")
|
|
392
|
+
console.log(prefix.subarray(32, 64)); // equals tagHash
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## Return Types
|
|
398
|
+
|
|
399
|
+
The crypto module uses branded `Uint8Array` subtypes for type safety:
|
|
400
|
+
|
|
401
|
+
| Type | Length | Used By |
|
|
402
|
+
|------|--------|---------|
|
|
403
|
+
| `Bytes32` | 32 bytes | `sha256`, `hash256`, `taggedHash` |
|
|
404
|
+
| `Bytes20` | 20 bytes | `sha1`, `ripemd160`, `hash160` |
|
|
405
|
+
|
|
406
|
+
These types help catch misuse at compile time. A `Bytes32` cannot be accidentally passed where a `Bytes20` is expected, and vice versa.
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
import { isBytes32, isBytes20, toBytes32, toBytes20 } from '@btc-vision/bitcoin';
|
|
410
|
+
|
|
411
|
+
// Runtime validation
|
|
412
|
+
if (isBytes32(value)) {
|
|
413
|
+
// value is Bytes32
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Runtime conversion (throws if length is wrong)
|
|
417
|
+
const b32 = toBytes32(someUint8Array); // asserts 32 bytes
|
|
418
|
+
const b20 = toBytes20(someUint8Array); // asserts 20 bytes
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## Underlying Implementation
|
|
424
|
+
|
|
425
|
+
The raw hash functions are provided by the `@noble/hashes` library:
|
|
426
|
+
|
|
427
|
+
```typescript
|
|
428
|
+
// src/crypto-hashes.ts
|
|
429
|
+
import { ripemd160, sha1 } from '@noble/hashes/legacy.js';
|
|
430
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
The `crypto.ts` module wraps these with proper return types (`Bytes20`, `Bytes32`) and builds the composite functions (`hash160`, `hash256`, `taggedHash`) on top of them.
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## Hash Function Usage Summary by Bitcoin Feature
|
|
438
|
+
|
|
439
|
+
| Bitcoin Feature | Hash Function | Details |
|
|
440
|
+
|-----------------|---------------|---------|
|
|
441
|
+
| P2PKH addresses (`1...`) | `hash160` | `RIPEMD-160(SHA-256(pubkey))` produces the 20-byte pubkey hash |
|
|
442
|
+
| P2SH addresses (`3...`) | `hash160` | `RIPEMD-160(SHA-256(redeemScript))` produces the 20-byte script hash |
|
|
443
|
+
| P2WPKH addresses (`bc1q...`) | `hash160` | 20-byte witness program is `hash160(pubkey)` |
|
|
444
|
+
| P2WSH addresses (`bc1q...`) | `sha256` | 32-byte witness program is `SHA-256(witnessScript)` |
|
|
445
|
+
| Block header hash | `hash256` | Double-SHA-256 of the 80-byte header; basis for proof-of-work |
|
|
446
|
+
| Transaction ID (txid) | `hash256` | Double-SHA-256 of the serialized transaction (no witness) |
|
|
447
|
+
| Merkle root (block) | `hash256` | Pairwise double-SHA-256 of txids |
|
|
448
|
+
| Legacy sighash (pre-SegWit) | `hash256` | Double-SHA-256 of the sighash preimage |
|
|
449
|
+
| SegWit v0 sighash (BIP 143) | `hash256` | Double-SHA-256 for intermediate components and final digest |
|
|
450
|
+
| SegWit v1 sighash (BIP 341) | `sha256` + `taggedHash` | Single SHA-256 for intermediate components; `taggedHash('TapSighash', ...)` for the final digest |
|
|
451
|
+
| Taproot key tweaking | `taggedHash` | `taggedHash('TapTweak', pubkey \|\| merkleRoot)` |
|
|
452
|
+
| Tapscript leaf hash | `taggedHash` | `taggedHash('TapLeaf', version \|\| scriptLen \|\| script)` |
|
|
453
|
+
| Tapscript branch hash | `taggedHash` | `taggedHash('TapBranch', left \|\| right)` |
|
|
454
|
+
| Schnorr signature challenge | `taggedHash` | `taggedHash('BIP0340/challenge', R \|\| P \|\| m)` |
|
|
455
|
+
| Schnorr nonce generation | `taggedHash` | `taggedHash('BIP0340/nonce', ...)` and `taggedHash('BIP0340/aux', ...)` |
|
|
456
|
+
| MuSig2 key aggregation | `taggedHash` | `taggedHash('KeyAgg list', ...)` and `taggedHash('KeyAgg coefficient', ...)` |
|
|
457
|
+
| `OP_SHA1` script opcode | `sha1` | Rarely used; available for specialized scripts |
|
|
458
|
+
| `OP_RIPEMD160` script opcode | `ripemd160` | Rarely used directly; component of `hash160` |
|
|
459
|
+
| `OP_SHA256` script opcode | `sha256` | Single SHA-256 in script evaluation |
|
|
460
|
+
| `OP_HASH160` script opcode | `hash160` | RIPEMD-160(SHA-256(x)) in script evaluation |
|
|
461
|
+
| `OP_HASH256` script opcode | `hash256` | SHA-256(SHA-256(x)) in script evaluation |
|