@bsv/sdk 2.0.8 → 2.0.10
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/dist/cjs/package.json +1 -1
- package/dist/cjs/src/auth/certificates/Certificate.js +1 -1
- package/dist/cjs/src/auth/certificates/Certificate.js.map +1 -1
- package/dist/cjs/src/primitives/BigNumber.js +4 -5
- package/dist/cjs/src/primitives/BigNumber.js.map +1 -1
- package/dist/cjs/src/primitives/index.js.map +1 -1
- package/dist/cjs/src/script/OP.js +22 -16
- package/dist/cjs/src/script/OP.js.map +1 -1
- package/dist/cjs/src/script/Spend.js +21 -78
- package/dist/cjs/src/script/Spend.js.map +1 -1
- package/dist/cjs/src/transaction/Transaction.js +45 -0
- package/dist/cjs/src/transaction/Transaction.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/auth/certificates/Certificate.js +1 -1
- package/dist/esm/src/auth/certificates/Certificate.js.map +1 -1
- package/dist/esm/src/primitives/BigNumber.js +4 -5
- package/dist/esm/src/primitives/BigNumber.js.map +1 -1
- package/dist/esm/src/primitives/index.js.map +1 -1
- package/dist/esm/src/script/OP.js +22 -16
- package/dist/esm/src/script/OP.js.map +1 -1
- package/dist/esm/src/script/Spend.js +21 -78
- package/dist/esm/src/script/Spend.js.map +1 -1
- package/dist/esm/src/transaction/Transaction.js +45 -0
- package/dist/esm/src/transaction/Transaction.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/primitives/BigNumber.d.ts.map +1 -1
- package/dist/types/src/primitives/index.d.ts +1 -1
- package/dist/types/src/primitives/index.d.ts.map +1 -1
- package/dist/types/src/script/OP.d.ts +9 -7
- package/dist/types/src/script/OP.d.ts.map +1 -1
- package/dist/types/src/script/Spend.d.ts.map +1 -1
- package/dist/types/src/transaction/Transaction.d.ts +9 -0
- package/dist/types/src/transaction/Transaction.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +3 -3
- package/dist/umd/bundle.js.map +1 -1
- package/docs/reference/script.md +76 -0
- package/docs/reference/transaction.md +87 -7
- package/docs/reference/wallet.md +285 -1094
- package/package.json +1 -1
- package/src/auth/certificates/Certificate.ts +1 -1
- package/src/primitives/BigNumber.ts +4 -5
- package/src/primitives/__tests/BigNumber.constructor.test.ts +3 -3
- package/src/primitives/index.ts +1 -1
- package/src/script/OP.ts +21 -16
- package/src/script/Spend.ts +21 -28
- package/src/script/__tests/Chronicle.test.ts +39 -103
- package/src/script/__tests/ChronicleOpcodes.test.ts +548 -0
- package/src/transaction/Transaction.ts +46 -0
- package/src/transaction/__tests/Transaction.test.ts +170 -0
package/package.json
CHANGED
|
@@ -113,7 +113,7 @@ export default class Certificate {
|
|
|
113
113
|
|
|
114
114
|
// Write fields
|
|
115
115
|
// Sort field names lexicographically
|
|
116
|
-
const fieldNames = Object.keys(this.fields).sort()
|
|
116
|
+
const fieldNames = Object.keys(this.fields).sort((a, b) => a.localeCompare(b))
|
|
117
117
|
writer.writeVarIntNum(fieldNames.length)
|
|
118
118
|
for (const fieldName of fieldNames) {
|
|
119
119
|
const fieldValue = this.fields[fieldName]
|
|
@@ -664,9 +664,8 @@ export default class BigNumber {
|
|
|
664
664
|
neg (): BigNumber { return this.clone().ineg() }
|
|
665
665
|
ineg (): this { if (this._magnitude !== 0n) this._sign = this._sign === 1 ? 0 : 1; return this }
|
|
666
666
|
|
|
667
|
-
private _iuop (num: BigNumber, op: (a: bigint, b: bigint) => bigint): this {
|
|
667
|
+
private _iuop (num: BigNumber, op: (a: bigint, b: bigint) => bigint, isXor: boolean = false): this {
|
|
668
668
|
const newMag = op(this._magnitude, num._magnitude)
|
|
669
|
-
const isXor = op === ((a: bigint, b: bigint) => a ^ b)
|
|
670
669
|
let targetNominalLength = this._nominalWordLength
|
|
671
670
|
if (isXor) targetNominalLength = Math.max(this.length, num.length)
|
|
672
671
|
|
|
@@ -678,11 +677,11 @@ export default class BigNumber {
|
|
|
678
677
|
|
|
679
678
|
iuor (num: BigNumber): this { return this._iuop(num, (a, b) => a | b) }
|
|
680
679
|
iuand (num: BigNumber): this { return this._iuop(num, (a, b) => a & b) }
|
|
681
|
-
iuxor (num: BigNumber): this { return this._iuop(num, (a, b) => a ^ b) }
|
|
682
|
-
private _iop (num: BigNumber, op: (a: bigint, b: bigint) => bigint): this { this.assert(this._sign === 0 && num._sign === 0); return this._iuop(num, op) }
|
|
680
|
+
iuxor (num: BigNumber): this { return this._iuop(num, (a, b) => a ^ b, true) }
|
|
681
|
+
private _iop (num: BigNumber, op: (a: bigint, b: bigint) => bigint, isXor: boolean = false): this { this.assert(this._sign === 0 && num._sign === 0); return this._iuop(num, op, isXor) }
|
|
683
682
|
ior (num: BigNumber): this { return this._iop(num, (a, b) => a | b) }
|
|
684
683
|
iand (num: BigNumber): this { return this._iop(num, (a, b) => a & b) }
|
|
685
|
-
ixor (num: BigNumber): this { return this._iop(num, (a, b) => a ^ b) }
|
|
684
|
+
ixor (num: BigNumber): this { return this._iop(num, (a, b) => a ^ b, true) }
|
|
686
685
|
private _uop_new (num: BigNumber, opName: 'iuor' | 'iuand' | 'iuxor'): BigNumber { if (this.length >= num.length) return this.clone()[opName](num); return num.clone()[opName](this) }
|
|
687
686
|
or (num: BigNumber): BigNumber { this.assert(this._sign === 0 && num._sign === 0); return this._uop_new(num, 'iuor') }
|
|
688
687
|
uor (num: BigNumber): BigNumber { return this._uop_new(num, 'iuor') }
|
|
@@ -117,11 +117,11 @@ describe('BN.js/Constructor', () => {
|
|
|
117
117
|
|
|
118
118
|
it('should not accept decimal', () => {
|
|
119
119
|
expect(() => {
|
|
120
|
-
new BigNumber('10.00', 10)
|
|
120
|
+
return new BigNumber('10.00', 10)
|
|
121
121
|
}).toThrow(new Error('Invalid character'))
|
|
122
122
|
|
|
123
123
|
expect(() => {
|
|
124
|
-
new BigNumber('16.00', 16)
|
|
124
|
+
return new BigNumber('16.00', 16)
|
|
125
125
|
}).toThrow(/* new Error('Invalid character') */)
|
|
126
126
|
})
|
|
127
127
|
|
|
@@ -137,7 +137,7 @@ describe('BN.js/Constructor', () => {
|
|
|
137
137
|
'hexadecimal'
|
|
138
138
|
].forEach(function (str) {
|
|
139
139
|
expect(() => {
|
|
140
|
-
new BigNumber(str, 16)
|
|
140
|
+
return new BigNumber(str, 16)
|
|
141
141
|
}).toThrow(/* Invalid character in */)
|
|
142
142
|
})
|
|
143
143
|
})
|
package/src/primitives/index.ts
CHANGED
|
@@ -9,7 +9,7 @@ export * as ECDSA from './ECDSA.js'
|
|
|
9
9
|
export * as Utils from './utils.js'
|
|
10
10
|
export * as Hash from './Hash.js'
|
|
11
11
|
export { default as Random } from './Random.js'
|
|
12
|
-
export { default as TransactionSignature } from './TransactionSignature.js'
|
|
12
|
+
export { default as TransactionSignature, type SignatureHashCache } from './TransactionSignature.js'
|
|
13
13
|
export { default as Polynomial, PointInFiniteField } from './Polynomial.js'
|
|
14
14
|
export { default as Schnorr } from './Schnorr.js'
|
|
15
15
|
export { default as Secp256r1 } from './Secp256r1.js'
|
package/src/script/OP.ts
CHANGED
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
*/
|
|
4
4
|
const OP = {
|
|
5
5
|
// push value
|
|
6
|
+
OP_0: 0x00, // when two op codes have the same value, the top one will be used in standard ASM output
|
|
6
7
|
OP_FALSE: 0x00,
|
|
7
|
-
OP_0: 0x00,
|
|
8
8
|
OP_PUSHDATA1: 0x4c,
|
|
9
9
|
OP_PUSHDATA2: 0x4d,
|
|
10
10
|
OP_PUSHDATA4: 0x4e,
|
|
11
11
|
OP_1NEGATE: 0x4f,
|
|
12
12
|
OP_RESERVED: 0x50,
|
|
13
|
-
OP_TRUE: 0x51,
|
|
14
13
|
OP_1: 0x51,
|
|
14
|
+
OP_TRUE: 0x51,
|
|
15
15
|
OP_2: 0x52,
|
|
16
16
|
OP_3: 0x53,
|
|
17
17
|
OP_4: 0x54,
|
|
@@ -124,20 +124,24 @@ const OP = {
|
|
|
124
124
|
|
|
125
125
|
// expansion
|
|
126
126
|
OP_NOP1: 0xb0,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
127
|
+
OP_CHECKLOCKTIMEVERIFY: 0xb1, // BIP65 - on BSV post-genesis acts as NOP
|
|
128
|
+
OP_NOP2: 0xb1, // alias for OP_CHECKLOCKTIMEVERIFY
|
|
129
|
+
OP_CHECKSEQUENCEVERIFY: 0xb2, // BIP112 - on BSV post-genesis acts as NOP
|
|
130
|
+
OP_NOP3: 0xb2, // alias for OP_CHECKSEQUENCEVERIFY
|
|
131
|
+
OP_SUBSTR: 0xb3, // restored in 2026 CHRONICLE upgrade (was OP_NOP4)
|
|
132
|
+
OP_NOP4: 0xb3, // alias for OP_SUBSTR
|
|
133
|
+
OP_LEFT: 0xb4, // restored in 2026 CHRONICLE upgrade (was OP_NOP5)
|
|
134
|
+
OP_NOP5: 0xb4, // alias for OP_LEFT
|
|
135
|
+
OP_RIGHT: 0xb5, // restored in 2026 CHRONICLE upgrade (was OP_NOP6)
|
|
136
|
+
OP_NOP6: 0xb5, // alias for OP_RIGHT
|
|
137
|
+
OP_LSHIFTNUM: 0xb6, // restored in 2026 CHRONICLE upgrade (was OP_NOP7)
|
|
138
|
+
OP_NOP7: 0xb6, // alias for OP_LSHIFTNUM
|
|
139
|
+
OP_RSHIFTNUM: 0xb7, // restored in 2026 CHRONICLE upgrade (was OP_NOP8)
|
|
140
|
+
OP_NOP8: 0xb7, // alias for OP_RSHIFTNUM
|
|
139
141
|
OP_NOP9: 0xb8,
|
|
140
142
|
OP_NOP10: 0xb9,
|
|
143
|
+
// 0xba–0xf9 are FIRST_UNDEFINED_OP_VALUE in node v1.2.0 and return SCRIPT_ERR_BAD_OPCODE
|
|
144
|
+
// when executed. The names below are retained for ASM parsing/serialisation only.
|
|
141
145
|
OP_NOP11: 0xba,
|
|
142
146
|
OP_NOP12: 0xbb,
|
|
143
147
|
OP_NOP13: 0xbc,
|
|
@@ -203,7 +207,8 @@ const OP = {
|
|
|
203
207
|
OP_NOP73: 0xf8,
|
|
204
208
|
OP_NOP77: 0xfc,
|
|
205
209
|
|
|
206
|
-
// template matching params
|
|
210
|
+
// template matching params (not executable opcodes; 0xf9 was removed from node v1.2.0 opcodes.h
|
|
211
|
+
// but retained here for ASM round-trip compatibility)
|
|
207
212
|
OP_SMALLDATA: 0xf9,
|
|
208
213
|
OP_SMALLINTEGER: 0xfa,
|
|
209
214
|
OP_PUBKEYS: 0xfb,
|
|
@@ -214,7 +219,7 @@ const OP = {
|
|
|
214
219
|
}
|
|
215
220
|
|
|
216
221
|
for (const name in OP) {
|
|
217
|
-
OP[OP[name]] = name
|
|
222
|
+
if (OP[OP[name]] === undefined) OP[OP[name]] = name
|
|
218
223
|
}
|
|
219
224
|
|
|
220
225
|
export default OP
|
package/src/script/Spend.ts
CHANGED
|
@@ -419,9 +419,12 @@ export default class Spend {
|
|
|
419
419
|
let i: number, ikey: number, isig: number, nKeysCount: number, nSigsCount: number, fOk: boolean
|
|
420
420
|
|
|
421
421
|
switch (currentOpcode) {
|
|
422
|
-
case OP.OP_VER:
|
|
423
|
-
|
|
422
|
+
case OP.OP_VER: {
|
|
423
|
+
// Node v1.2.0: pushes tx_version as a 4-byte little-endian integer (to_le encoding)
|
|
424
|
+
const ver = this.transactionVersion
|
|
425
|
+
this.pushStack([ver & 0xff, (ver >>> 8) & 0xff, (ver >>> 16) & 0xff, (ver >>> 24) & 0xff])
|
|
424
426
|
break
|
|
427
|
+
}
|
|
425
428
|
case OP.OP_SUBSTR: {
|
|
426
429
|
if (this.stack.length < 3) this.scriptEvaluationError('OP_SUBSTR requires at least three items to be on the stack.')
|
|
427
430
|
const len = BigNumber.fromScriptNum(this.popStack(), !this.isRelaxed()).toNumber()
|
|
@@ -459,7 +462,7 @@ export default class Spend {
|
|
|
459
462
|
this.scriptEvaluationError(`OP_RIGHT length (${len}) must be in range [0, ${size}]`)
|
|
460
463
|
}
|
|
461
464
|
|
|
462
|
-
this.pushStack(buf.slice(size - len
|
|
465
|
+
this.pushStack(buf.slice(size - len))
|
|
463
466
|
break
|
|
464
467
|
}
|
|
465
468
|
case OP.OP_LSHIFTNUM: {
|
|
@@ -501,32 +504,18 @@ export default class Spend {
|
|
|
501
504
|
break
|
|
502
505
|
|
|
503
506
|
case OP.OP_NOP:
|
|
507
|
+
// OP_NOP1 (0xb0), OP_NOP9 (0xb8), OP_NOP10 (0xb9) are the only defined upgrade-NOP slots
|
|
508
|
+
// in node v1.2.0. All other values above 0xb9 are FIRST_UNDEFINED_OP_VALUE and invalid.
|
|
509
|
+
// falls through
|
|
504
510
|
case OP.OP_NOP1:
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
//
|
|
509
|
-
//
|
|
510
|
-
|
|
511
|
-
case OP.OP_NOP7:
|
|
512
|
-
case OP.OP_NOP8:
|
|
511
|
+
// OP_NOP2 (0xb1) = OP_CHECKLOCKTIMEVERIFY: on BSV post-genesis treated as NOP
|
|
512
|
+
// falls through
|
|
513
|
+
case OP.OP_CHECKLOCKTIMEVERIFY:
|
|
514
|
+
// OP_NOP3 (0xb2) = OP_CHECKSEQUENCEVERIFY: on BSV post-genesis treated as NOP
|
|
515
|
+
// falls through
|
|
516
|
+
case OP.OP_CHECKSEQUENCEVERIFY:
|
|
513
517
|
case OP.OP_NOP9:
|
|
514
518
|
case OP.OP_NOP10:
|
|
515
|
-
// eslint-disable-next-line no-fallthrough
|
|
516
|
-
case OP.OP_NOP11: case OP.OP_NOP12: case OP.OP_NOP13: case OP.OP_NOP14: case OP.OP_NOP15:
|
|
517
|
-
case OP.OP_NOP16: case OP.OP_NOP17: case OP.OP_NOP18: case OP.OP_NOP19: case OP.OP_NOP20:
|
|
518
|
-
case OP.OP_NOP21: case OP.OP_NOP22: case OP.OP_NOP23: case OP.OP_NOP24: case OP.OP_NOP25:
|
|
519
|
-
case OP.OP_NOP26: case OP.OP_NOP27: case OP.OP_NOP28: case OP.OP_NOP29: case OP.OP_NOP30:
|
|
520
|
-
case OP.OP_NOP31: case OP.OP_NOP32: case OP.OP_NOP33: case OP.OP_NOP34: case OP.OP_NOP35:
|
|
521
|
-
case OP.OP_NOP36: case OP.OP_NOP37: case OP.OP_NOP38: case OP.OP_NOP39: case OP.OP_NOP40:
|
|
522
|
-
case OP.OP_NOP41: case OP.OP_NOP42: case OP.OP_NOP43: case OP.OP_NOP44: case OP.OP_NOP45:
|
|
523
|
-
case OP.OP_NOP46: case OP.OP_NOP47: case OP.OP_NOP48: case OP.OP_NOP49: case OP.OP_NOP50:
|
|
524
|
-
case OP.OP_NOP51: case OP.OP_NOP52: case OP.OP_NOP53: case OP.OP_NOP54: case OP.OP_NOP55:
|
|
525
|
-
case OP.OP_NOP56: case OP.OP_NOP57: case OP.OP_NOP58: case OP.OP_NOP59: case OP.OP_NOP60:
|
|
526
|
-
case OP.OP_NOP61: case OP.OP_NOP62: case OP.OP_NOP63: case OP.OP_NOP64: case OP.OP_NOP65:
|
|
527
|
-
case OP.OP_NOP66: case OP.OP_NOP67: case OP.OP_NOP68: case OP.OP_NOP69: case OP.OP_NOP70:
|
|
528
|
-
case OP.OP_NOP71: case OP.OP_NOP72: case OP.OP_NOP73:
|
|
529
|
-
case OP.OP_NOP77:
|
|
530
519
|
break
|
|
531
520
|
|
|
532
521
|
case OP.OP_VERIF:
|
|
@@ -534,9 +523,13 @@ export default class Spend {
|
|
|
534
523
|
fValue = false
|
|
535
524
|
if (isScriptExecuting) {
|
|
536
525
|
if (this.stack.length < 1) this.scriptEvaluationError('OP_VERIF and OP_VERNOTIF require at least one item on the stack when they are used!')
|
|
537
|
-
buf2 = new BigNumber(this.transactionVersion).toScriptNum()
|
|
538
526
|
buf1 = this.popStack()
|
|
539
|
-
|
|
527
|
+
// Node v1.2.0: compares against 4-byte little-endian tx_version (only matches when item is exactly 4 bytes)
|
|
528
|
+
if (buf1.length === 4) {
|
|
529
|
+
const ver = this.transactionVersion
|
|
530
|
+
buf2 = [ver & 0xff, (ver >>> 8) & 0xff, (ver >>> 16) & 0xff, (ver >>> 24) & 0xff]
|
|
531
|
+
fValue = compareNumberArrays(buf1, buf2)
|
|
532
|
+
}
|
|
540
533
|
if (currentOpcode === OP.OP_VERNOTIF) fValue = !fValue
|
|
541
534
|
}
|
|
542
535
|
this.ifStack.push(fValue)
|
|
@@ -37,120 +37,56 @@ describe('Chronicle Tests', () => {
|
|
|
37
37
|
})
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
|
-
* At present only the first
|
|
40
|
+
* At present only the first test vector added as real transaction (pre and post fork) compute a sighash known to match a valid signagure.
|
|
41
41
|
* The remaining test vectors come from bitcoin-sv-staging repo as of 2025-06-23, but appear to be at least somewhat randomly generated.
|
|
42
42
|
* The "scope" (SigHashType) values are all over the place.
|
|
43
43
|
* Working with Teranode team to determine correct preimage values...
|
|
44
44
|
*/
|
|
45
|
-
it('sighashTestData', () => {
|
|
46
|
-
let log = ''
|
|
47
|
-
let i = -1
|
|
48
|
-
for (const t of sighashTestData) {
|
|
49
|
-
i++
|
|
50
|
-
const tx = Transaction.fromHex(t.rawTxHex)
|
|
51
|
-
const script = Script.fromHex(t.scriptHex)
|
|
52
|
-
const input = tx.inputs[t.inputIndex]
|
|
53
|
-
if (input.unlockingScript?.chunks.length != 2)
|
|
54
|
-
continue;
|
|
55
|
-
const otherInputs = [...tx.inputs]
|
|
56
|
-
otherInputs.splice(t.inputIndex, 1)
|
|
57
|
-
const params = {
|
|
58
|
-
sourceTXID: input.sourceTXID!,
|
|
59
|
-
sourceOutputIndex: input.sourceOutputIndex,
|
|
60
|
-
sourceSatoshis: t.satoshis,
|
|
61
|
-
transactionVersion: tx.version,
|
|
62
|
-
otherInputs,
|
|
63
|
-
outputs: tx.outputs,
|
|
64
|
-
inputIndex: t.inputIndex,
|
|
65
|
-
subscript: Script.fromHex(t.scriptHex),
|
|
66
|
-
inputSequence: input.sequence ?? 0xffffffff, // Default to max sequence number
|
|
67
|
-
lockTime: tx.lockTime,
|
|
68
|
-
scope: t.hashType,
|
|
69
|
-
}
|
|
70
|
-
let ok = false
|
|
71
|
-
let okReg = false
|
|
72
|
-
let okOTDA = false
|
|
73
|
-
{
|
|
74
|
-
const sighash = t.sighashReg
|
|
75
|
-
const buf = TransactionSignature.format(params)
|
|
76
|
-
const ret = Utils.toHex(Hash.hash256(buf).reverse())
|
|
77
|
-
if (ret === sighash) {
|
|
78
|
-
ok = true
|
|
79
|
-
okReg = true
|
|
80
|
-
}
|
|
81
|
-
if (!okReg)
|
|
82
|
-
log += `${i+1} Reg ${okReg} ${!okReg ? ret : ''}\n`
|
|
83
|
-
}
|
|
84
|
-
{
|
|
85
|
-
const sighash = t.sighashOTDA
|
|
86
|
-
const buf = TransactionSignature.formatOTDA(params)
|
|
87
|
-
const ret = Utils.toHex(Hash.hash256(buf).reverse())
|
|
88
|
-
if (ret === sighash) {
|
|
89
|
-
ok = true
|
|
90
|
-
okOTDA = true
|
|
91
|
-
}
|
|
92
|
-
if (!okOTDA)
|
|
93
|
-
log += `${i+1} OTDA ${okOTDA} ${!okOTDA ? ret : ''}\n`
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
//console.log(log)
|
|
97
|
-
//expect(log).toBe('')
|
|
98
|
-
})
|
|
99
45
|
|
|
100
46
|
it('wip sighashTestData', () => {
|
|
101
|
-
|
|
102
|
-
let i = -1
|
|
103
|
-
for (const t of sighashTestDataWip) {
|
|
104
|
-
i++
|
|
105
|
-
const tx = Transaction.fromHex(t.rawTxHex)
|
|
106
|
-
const script = Script.fromHex(t.scriptHex)
|
|
107
|
-
const input = tx.inputs[t.inputIndex]
|
|
108
|
-
const otherInputs = [...tx.inputs]
|
|
109
|
-
otherInputs.splice(t.inputIndex, 1)
|
|
110
|
-
const params = {
|
|
111
|
-
sourceTXID: input.sourceTXID!,
|
|
112
|
-
sourceOutputIndex: input.sourceOutputIndex,
|
|
113
|
-
sourceSatoshis: t.satoshis,
|
|
114
|
-
transactionVersion: tx.version,
|
|
115
|
-
otherInputs,
|
|
116
|
-
outputs: tx.outputs,
|
|
117
|
-
inputIndex: t.inputIndex,
|
|
118
|
-
subscript: Script.fromHex(t.scriptHex),
|
|
119
|
-
inputSequence: input.sequence ?? 0xffffffff, // Default to max sequence number
|
|
120
|
-
lockTime: tx.lockTime,
|
|
121
|
-
scope: t.hashType,
|
|
122
|
-
}
|
|
123
|
-
let ok = false
|
|
124
|
-
let okReg = false
|
|
125
|
-
let okOTDA = false
|
|
126
|
-
{
|
|
127
|
-
const sighash = t.sighashReg
|
|
128
|
-
const buf = TransactionSignature.format(params)
|
|
129
|
-
const ret = Utils.toHex(Hash.hash256(buf).reverse())
|
|
130
|
-
if (ret === sighash) {
|
|
131
|
-
ok = true
|
|
132
|
-
okReg = true
|
|
133
|
-
}
|
|
134
|
-
if (!okReg)
|
|
135
|
-
log += `${i+1} Reg ${okReg} ${!okReg ? ret : ''}\n`
|
|
136
|
-
}
|
|
137
|
-
{
|
|
138
|
-
const sighash = t.sighashOTDA
|
|
139
|
-
const buf = TransactionSignature.formatOTDA(params)
|
|
140
|
-
const ret = Utils.toHex(Hash.hash256(buf).reverse())
|
|
141
|
-
if (ret === sighash) {
|
|
142
|
-
ok = true
|
|
143
|
-
okOTDA = true
|
|
144
|
-
}
|
|
145
|
-
if (!okOTDA)
|
|
146
|
-
log += `${i+1} OTDA ${okOTDA} ${!okOTDA ? ret : ''}\n`
|
|
147
|
-
}
|
|
148
|
-
}
|
|
47
|
+
const log = computeSighashLog(sighashTestDataWip)
|
|
149
48
|
console.log(log)
|
|
150
49
|
expect(log).toBe('')
|
|
151
50
|
})
|
|
152
51
|
})
|
|
153
52
|
|
|
53
|
+
function computeSighashLog (
|
|
54
|
+
data: typeof sighashTestData,
|
|
55
|
+
filterByUnlockingChunks: boolean = false
|
|
56
|
+
): string {
|
|
57
|
+
let log = ''
|
|
58
|
+
let i = -1
|
|
59
|
+
for (const t of data) {
|
|
60
|
+
i++
|
|
61
|
+
const tx = Transaction.fromHex(t.rawTxHex)
|
|
62
|
+
const input = tx.inputs[t.inputIndex]
|
|
63
|
+
if (filterByUnlockingChunks && input.unlockingScript?.chunks.length !== 2)
|
|
64
|
+
continue
|
|
65
|
+
const otherInputs = [...tx.inputs]
|
|
66
|
+
otherInputs.splice(t.inputIndex, 1)
|
|
67
|
+
const params = {
|
|
68
|
+
sourceTXID: input.sourceTXID!,
|
|
69
|
+
sourceOutputIndex: input.sourceOutputIndex,
|
|
70
|
+
sourceSatoshis: t.satoshis,
|
|
71
|
+
transactionVersion: tx.version,
|
|
72
|
+
otherInputs,
|
|
73
|
+
outputs: tx.outputs,
|
|
74
|
+
inputIndex: t.inputIndex,
|
|
75
|
+
subscript: Script.fromHex(t.scriptHex),
|
|
76
|
+
inputSequence: input.sequence ?? 0xffffffff,
|
|
77
|
+
lockTime: tx.lockTime,
|
|
78
|
+
scope: t.hashType,
|
|
79
|
+
}
|
|
80
|
+
const reg = Utils.toHex(Hash.hash256(TransactionSignature.format(params)).reverse())
|
|
81
|
+
if (reg !== t.sighashReg)
|
|
82
|
+
log += `${i+1} Reg false ${reg}\n`
|
|
83
|
+
const otda = Utils.toHex(Hash.hash256(TransactionSignature.formatOTDA(params)).reverse())
|
|
84
|
+
if (otda !== t.sighashOTDA)
|
|
85
|
+
log += `${i+1} OTDA false ${otda}\n`
|
|
86
|
+
}
|
|
87
|
+
return log
|
|
88
|
+
}
|
|
89
|
+
|
|
154
90
|
function verifyTruthy<T> (v: T | undefined): T {
|
|
155
91
|
if (v == null) throw new Error('must have value')
|
|
156
92
|
return v
|