@@ -20,7 +20,7 @@ function vectorSize(someVector) {
2020 } , 0 )
2121 ) ;
2222}
23- const EMPTY_SCRIPT = Buffer . allocUnsafe ( 0 ) ;
23+ const EMPTY_BUFFER = Buffer . allocUnsafe ( 0 ) ;
2424const EMPTY_WITNESS = [ ] ;
2525const ZERO = Buffer . from (
2626 '0000000000000000000000000000000000000000000000000000000000000000' ,
@@ -32,7 +32,7 @@ const ONE = Buffer.from(
3232) ;
3333const VALUE_UINT64_MAX = Buffer . from ( 'ffffffffffffffff' , 'hex' ) ;
3434const BLANK_OUTPUT = {
35- script : EMPTY_SCRIPT ,
35+ script : EMPTY_BUFFER ,
3636 valueBuffer : VALUE_UINT64_MAX ,
3737} ;
3838function isOutput ( out ) {
@@ -124,7 +124,7 @@ class Transaction {
124124 this . ins . push ( {
125125 hash,
126126 index,
127- script : scriptSig || EMPTY_SCRIPT ,
127+ script : scriptSig || EMPTY_BUFFER ,
128128 sequence : sequence ,
129129 witness : EMPTY_WITNESS ,
130130 } ) - 1
@@ -247,7 +247,7 @@ class Transaction {
247247 } else {
248248 // "blank" others input scripts
249249 txTmp . ins . forEach ( input => {
250- input . script = EMPTY_SCRIPT ;
250+ input . script = EMPTY_BUFFER ;
251251 } ) ;
252252 txTmp . ins [ inIndex ] . script = ourScript ;
253253 }
@@ -257,6 +257,141 @@ class Transaction {
257257 txTmp . __toBuffer ( buffer , 0 , false ) ;
258258 return bcrypto . hash256 ( buffer ) ;
259259 }
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+ }
260395 hashForWitnessV0 ( inIndex , prevOutScript , value , hashType ) {
261396 typeforce (
262397 types . tuple ( types . UInt32 , types . Buffer , types . Satoshi , types . UInt32 ) ,
@@ -396,9 +531,12 @@ class Transaction {
396531}
397532exports . Transaction = Transaction ;
398533Transaction . DEFAULT_SEQUENCE = 0xffffffff ;
534+ Transaction . SIGHASH_DEFAULT = 0x00 ;
399535Transaction . SIGHASH_ALL = 0x01 ;
400536Transaction . SIGHASH_NONE = 0x02 ;
401537Transaction . SIGHASH_SINGLE = 0x03 ;
402538Transaction . SIGHASH_ANYONECANPAY = 0x80 ;
539+ Transaction . SIGHASH_OUTPUT_MASK = 0x03 ;
540+ Transaction . SIGHASH_INPUT_MASK = 0x80 ;
403541Transaction . ADVANCED_TRANSACTION_MARKER = 0x00 ;
404542Transaction . ADVANCED_TRANSACTION_FLAG = 0x01 ;
0 commit comments