@@ -20,7 +20,7 @@ function vectorSize(someVector) {
20
20
} , 0 )
21
21
) ;
22
22
}
23
- const EMPTY_SCRIPT = Buffer . allocUnsafe ( 0 ) ;
23
+ const EMPTY_BUFFER = Buffer . allocUnsafe ( 0 ) ;
24
24
const EMPTY_WITNESS = [ ] ;
25
25
const ZERO = Buffer . from (
26
26
'0000000000000000000000000000000000000000000000000000000000000000' ,
@@ -32,7 +32,7 @@ const ONE = Buffer.from(
32
32
) ;
33
33
const VALUE_UINT64_MAX = Buffer . from ( 'ffffffffffffffff' , 'hex' ) ;
34
34
const BLANK_OUTPUT = {
35
- script : EMPTY_SCRIPT ,
35
+ script : EMPTY_BUFFER ,
36
36
valueBuffer : VALUE_UINT64_MAX ,
37
37
} ;
38
38
function isOutput ( out ) {
@@ -124,7 +124,7 @@ class Transaction {
124
124
this . ins . push ( {
125
125
hash,
126
126
index,
127
- script : scriptSig || EMPTY_SCRIPT ,
127
+ script : scriptSig || EMPTY_BUFFER ,
128
128
sequence : sequence ,
129
129
witness : EMPTY_WITNESS ,
130
130
} ) - 1
@@ -247,7 +247,7 @@ class Transaction {
247
247
} else {
248
248
// "blank" others input scripts
249
249
txTmp . ins . forEach ( input => {
250
- input . script = EMPTY_SCRIPT ;
250
+ input . script = EMPTY_BUFFER ;
251
251
} ) ;
252
252
txTmp . ins [ inIndex ] . script = ourScript ;
253
253
}
@@ -257,6 +257,141 @@ class Transaction {
257
257
txTmp . __toBuffer ( buffer , 0 , false ) ;
258
258
return bcrypto . hash256 ( buffer ) ;
259
259
}
260
+ hashForWitnessV1 ( inIndex , prevOutScripts , values , hashType , leafHash , annex ) {
261
+ // https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#common-signature-message
262
+ typeforce (
263
+ types . tuple (
264
+ types . UInt32 ,
265
+ typeforce . arrayOf ( types . Buffer ) ,
266
+ typeforce . arrayOf ( types . Satoshi ) ,
267
+ types . UInt32 ,
268
+ ) ,
269
+ arguments ,
270
+ ) ;
271
+ if (
272
+ values . length !== this . ins . length ||
273
+ prevOutScripts . length !== this . ins . length
274
+ ) {
275
+ throw new Error ( 'Must supply prevout script and value for all inputs' ) ;
276
+ }
277
+ const outputType =
278
+ hashType === Transaction . SIGHASH_DEFAULT
279
+ ? Transaction . SIGHASH_ALL
280
+ : hashType & Transaction . SIGHASH_OUTPUT_MASK ;
281
+ const inputType = hashType & Transaction . SIGHASH_INPUT_MASK ;
282
+ const isAnyoneCanPay = inputType === Transaction . SIGHASH_ANYONECANPAY ;
283
+ const isNone = outputType === Transaction . SIGHASH_NONE ;
284
+ const isSingle = outputType === Transaction . SIGHASH_SINGLE ;
285
+ let hashPrevouts = EMPTY_BUFFER ;
286
+ let hashAmounts = EMPTY_BUFFER ;
287
+ let hashScriptPubKeys = EMPTY_BUFFER ;
288
+ let hashSequences = EMPTY_BUFFER ;
289
+ let hashOutputs = EMPTY_BUFFER ;
290
+ if ( ! isAnyoneCanPay ) {
291
+ let bufferWriter = bufferutils_1 . BufferWriter . withCapacity (
292
+ 36 * this . ins . length ,
293
+ ) ;
294
+ this . ins . forEach ( txIn => {
295
+ bufferWriter . writeSlice ( txIn . hash ) ;
296
+ bufferWriter . writeUInt32 ( txIn . index ) ;
297
+ } ) ;
298
+ hashPrevouts = bcrypto . sha256 ( bufferWriter . end ( ) ) ;
299
+ bufferWriter = bufferutils_1 . BufferWriter . withCapacity (
300
+ 8 * this . ins . length ,
301
+ ) ;
302
+ values . forEach ( value => bufferWriter . writeUInt64 ( value ) ) ;
303
+ hashAmounts = bcrypto . sha256 ( bufferWriter . end ( ) ) ;
304
+ bufferWriter = bufferutils_1 . BufferWriter . withCapacity (
305
+ prevOutScripts . map ( varSliceSize ) . reduce ( ( a , b ) => a + b ) ,
306
+ ) ;
307
+ prevOutScripts . forEach ( prevOutScript =>
308
+ bufferWriter . writeVarSlice ( prevOutScript ) ,
309
+ ) ;
310
+ hashScriptPubKeys = bcrypto . sha256 ( bufferWriter . end ( ) ) ;
311
+ bufferWriter = bufferutils_1 . BufferWriter . withCapacity (
312
+ 4 * this . ins . length ,
313
+ ) ;
314
+ this . ins . forEach ( txIn => bufferWriter . writeUInt32 ( txIn . sequence ) ) ;
315
+ hashSequences = bcrypto . sha256 ( bufferWriter . end ( ) ) ;
316
+ }
317
+ if ( ! ( isNone || isSingle ) ) {
318
+ const txOutsSize = this . outs
319
+ . map ( output => 8 + varSliceSize ( output . script ) )
320
+ . reduce ( ( a , b ) => a + b ) ;
321
+ const bufferWriter = bufferutils_1 . BufferWriter . withCapacity ( txOutsSize ) ;
322
+ this . outs . forEach ( out => {
323
+ bufferWriter . writeUInt64 ( out . value ) ;
324
+ bufferWriter . writeVarSlice ( out . script ) ;
325
+ } ) ;
326
+ hashOutputs = bcrypto . sha256 ( bufferWriter . end ( ) ) ;
327
+ } else if ( isSingle && inIndex < this . outs . length ) {
328
+ const output = this . outs [ inIndex ] ;
329
+ const bufferWriter = bufferutils_1 . BufferWriter . withCapacity (
330
+ 8 + varSliceSize ( output . script ) ,
331
+ ) ;
332
+ bufferWriter . writeUInt64 ( output . value ) ;
333
+ bufferWriter . writeVarSlice ( output . script ) ;
334
+ hashOutputs = bcrypto . sha256 ( bufferWriter . end ( ) ) ;
335
+ }
336
+ const spendType = ( leafHash ? 2 : 0 ) + ( annex ? 1 : 0 ) ;
337
+ // Length calculation from:
338
+ // https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#cite_note-14
339
+ // With extension from:
340
+ // https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki#signature-validation
341
+ const sigMsgSize =
342
+ 174 -
343
+ ( isAnyoneCanPay ? 49 : 0 ) -
344
+ ( isNone ? 32 : 0 ) +
345
+ ( annex ? 32 : 0 ) +
346
+ ( leafHash ? 37 : 0 ) ;
347
+ const sigMsgWriter = bufferutils_1 . BufferWriter . withCapacity ( sigMsgSize ) ;
348
+ sigMsgWriter . writeUInt8 ( hashType ) ;
349
+ // Transaction
350
+ sigMsgWriter . writeInt32 ( this . version ) ;
351
+ sigMsgWriter . writeUInt32 ( this . locktime ) ;
352
+ sigMsgWriter . writeSlice ( hashPrevouts ) ;
353
+ sigMsgWriter . writeSlice ( hashAmounts ) ;
354
+ sigMsgWriter . writeSlice ( hashScriptPubKeys ) ;
355
+ sigMsgWriter . writeSlice ( hashSequences ) ;
356
+ if ( ! ( isNone || isSingle ) ) {
357
+ sigMsgWriter . writeSlice ( hashOutputs ) ;
358
+ }
359
+ // Input
360
+ sigMsgWriter . writeUInt8 ( spendType ) ;
361
+ if ( isAnyoneCanPay ) {
362
+ const input = this . ins [ inIndex ] ;
363
+ sigMsgWriter . writeSlice ( input . hash ) ;
364
+ sigMsgWriter . writeUInt32 ( input . index ) ;
365
+ sigMsgWriter . writeUInt64 ( values [ inIndex ] ) ;
366
+ sigMsgWriter . writeVarSlice ( prevOutScripts [ inIndex ] ) ;
367
+ sigMsgWriter . writeUInt32 ( input . sequence ) ;
368
+ } else {
369
+ sigMsgWriter . writeUInt32 ( inIndex ) ;
370
+ }
371
+ if ( annex ) {
372
+ const bufferWriter = bufferutils_1 . BufferWriter . withCapacity (
373
+ varSliceSize ( annex ) ,
374
+ ) ;
375
+ bufferWriter . writeVarSlice ( annex ) ;
376
+ sigMsgWriter . writeSlice ( bcrypto . sha256 ( bufferWriter . end ( ) ) ) ;
377
+ }
378
+ // Output
379
+ if ( isSingle ) {
380
+ sigMsgWriter . writeSlice ( hashOutputs ) ;
381
+ }
382
+ // BIP342 extension
383
+ if ( leafHash ) {
384
+ sigMsgWriter . writeSlice ( leafHash ) ;
385
+ sigMsgWriter . writeUInt8 ( 0 ) ;
386
+ sigMsgWriter . writeUInt32 ( 0xffffffff ) ;
387
+ }
388
+ // Extra zero byte because:
389
+ // https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#cite_note-19
390
+ return bcrypto . taggedHash (
391
+ 'TapSighash' ,
392
+ Buffer . concat ( [ Buffer . of ( 0x00 ) , sigMsgWriter . end ( ) ] ) ,
393
+ ) ;
394
+ }
260
395
hashForWitnessV0 ( inIndex , prevOutScript , value , hashType ) {
261
396
typeforce (
262
397
types . tuple ( types . UInt32 , types . Buffer , types . Satoshi , types . UInt32 ) ,
@@ -396,9 +531,12 @@ class Transaction {
396
531
}
397
532
exports . Transaction = Transaction ;
398
533
Transaction . DEFAULT_SEQUENCE = 0xffffffff ;
534
+ Transaction . SIGHASH_DEFAULT = 0x00 ;
399
535
Transaction . SIGHASH_ALL = 0x01 ;
400
536
Transaction . SIGHASH_NONE = 0x02 ;
401
537
Transaction . SIGHASH_SINGLE = 0x03 ;
402
538
Transaction . SIGHASH_ANYONECANPAY = 0x80 ;
539
+ Transaction . SIGHASH_OUTPUT_MASK = 0x03 ;
540
+ Transaction . SIGHASH_INPUT_MASK = 0x80 ;
403
541
Transaction . ADVANCED_TRANSACTION_MARKER = 0x00 ;
404
542
Transaction . ADVANCED_TRANSACTION_FLAG = 0x01 ;
0 commit comments