@@ -7,19 +7,20 @@ var ops = require('bitcoin-ops')
77var typeforce = require ( 'typeforce' )
88var types = require ( './types' )
99var scriptTypes = bscript . types
10- var SIGNABLE = [ bscript . types . P2PKH , bscript . types . P2PK , bscript . types . MULTISIG ]
11- var P2SH = SIGNABLE . concat ( [ bscript . types . P2WPKH , bscript . types . P2WSH ] )
1210
1311var ECPair = require ( './ecpair' )
1412var ECSignature = require ( './ecsignature' )
1513var Transaction = require ( './transaction' )
1614
1715function supportedType ( type ) {
18- return SIGNABLE . indexOf ( type ) !== - 1
16+ return [
17+ bscript . types . P2PKH , bscript . types . P2PK , bscript . types . MULTISIG
18+ ] . indexOf ( type ) !== - 1
1919}
2020
2121function supportedP2SHType ( type ) {
22- return P2SH . indexOf ( type ) !== - 1
22+ return supportedType ( type ) ||
23+ [ bscript . types . P2WPKH , bscript . types . P2WSH ] . indexOf ( type ) !== - 1
2324}
2425
2526function extractChunks ( type , chunks , script ) {
@@ -381,91 +382,92 @@ function prepareInput (input, kpPubKey, redeemScript, witnessValue, witnessScrip
381382 input . witness = witness
382383}
383384
385+ function enforceMinSigs ( allowIncomplete , signatures , pubKeys , n , m ) {
386+ if ( allowIncomplete ) {
387+ if ( signatures . length !== n ) return
388+ if ( pubKeys . length !== m ) return
389+ return true
390+ }
391+
392+ if ( signatures . length !== n ) throw new Error ( 'Not enough signatures provided' )
393+ if ( pubKeys . length !== m ) throw new Error ( 'Invalid number of pubKeys' )
394+ return true
395+ }
396+
384397function buildRawScriptSig ( type , signatures , pubKeys , allowIncomplete ) {
385398 if ( type === scriptTypes . P2WPKH ) {
386- if ( signatures . length === 1 && Buffer . isBuffer ( signatures [ 0 ] ) && pubKeys . length === 1 ) return bscript . witnessPubKeyHash . input . encodeRaw ( signatures [ 0 ] , pubKeys [ 0 ] )
387- } else if ( type === scriptTypes . P2PKH ) {
388- if ( signatures . length === 1 && Buffer . isBuffer ( signatures [ 0 ] ) && pubKeys . length === 1 ) return bscript . pubKeyHash . input . encodeRaw ( signatures [ 0 ] , pubKeys [ 0 ] )
389- } else if ( type === scriptTypes . P2PK ) {
390- if ( signatures . length === 1 && Buffer . isBuffer ( signatures [ 0 ] ) ) return bscript . pubKey . input . encodeRaw ( signatures [ 0 ] )
391- } else if ( type === scriptTypes . MULTISIG ) {
392- if ( signatures . length > 0 ) {
393- signatures = signatures . map ( function ( signature ) {
394- return signature || ops . OP_0
395- } )
399+ if ( ! enforceMinSigs ( allowIncomplete , signatures , pubKeys , 1 , 1 ) ) return [ ]
400+ return bscript . witnessPubKeyHash . input . encodeRaw ( signatures [ 0 ] , pubKeys [ 0 ] )
401+ }
396402
397- if ( ! allowIncomplete ) {
398- // remove blank signatures
399- signatures = signatures . filter ( function ( x ) { return x !== ops . OP_0 } )
400- }
403+ if ( type === scriptTypes . P2PKH ) {
404+ if ( ! enforceMinSigs ( allowIncomplete , signatures , pubKeys , 1 , 1 ) ) return [ ]
405+ return bscript . pubKeyHash . input . encodeRaw ( signatures [ 0 ] , pubKeys [ 0 ] )
406+ }
407+
408+ if ( type === scriptTypes . MULTISIG ) {
409+ signatures = signatures . map ( function ( signature ) {
410+ return signature || ops . OP_0
411+ } )
401412
402- return bscript . multisig . input . encodeRaw ( signatures )
413+ if ( ! allowIncomplete ) {
414+ // remove blank signatures
415+ signatures = signatures . filter ( function ( x ) { return x !== ops . OP_0 } )
403416 }
404- } else {
405- throw new Error ( 'Not yet supported' )
417+
418+ return bscript . multisig . input . encodeRaw ( signatures )
419+ }
420+
421+ if ( type === scriptTypes . P2PK ) {
422+ if ( ! enforceMinSigs ( allowIncomplete , signatures , [ ] , 1 , 0 ) ) return [ ]
423+ return bscript . pubKey . input . encodeRaw ( signatures [ 0 ] )
406424 }
407425
408- if ( ! allowIncomplete ) throw new Error ( 'Not enough signatures provided' )
409426 return [ ]
410427}
411428
412429function buildInput ( input , allowIncomplete ) {
413430 var scriptType = input . prevOutType
414- var rawScript = [ ]
431+ var rawScript = buildRawScriptSig ( scriptType , input . signatures , input . pubKeys , allowIncomplete )
415432 var rawWitness = [ ]
416433
417- if ( supportedType ( scriptType ) ) {
418- rawScript = buildRawScriptSig ( scriptType , input . signatures , input . pubKeys , allowIncomplete )
419- }
420-
421- var p2sh = false
434+ var isP2SH = false
422435 if ( scriptType === bscript . types . P2SH ) {
423- // We can remove this error later when we have a guarantee prepareInput
424- // rejects unsignable scripts - it MUST be signable at this point.
425- if ( ! allowIncomplete && ! supportedP2SHType ( input . redeemScriptType ) ) {
426- throw new Error ( 'Impossible to sign this type' )
427- }
428-
429- if ( supportedType ( input . redeemScriptType ) ) {
430- rawScript = buildRawScriptSig ( input . redeemScriptType , input . signatures , input . pubKeys , allowIncomplete )
431- }
436+ scriptType = input . redeemScriptType
432437
433- // If it wasn't SIGNABLE, it's witness, defer to that
434- if ( input . redeemScriptType ) {
435- p2sh = true
436- scriptType = input . redeemScriptType
438+ if ( scriptType !== bscript . types . P2WSH ) {
439+ rawScript = buildRawScriptSig ( scriptType , input . signatures , input . pubKeys , allowIncomplete )
440+ if ( ! allowIncomplete && ! rawScript . length ) throw new Error ( 'Cannot build script for ' + scriptType )
437441 }
442+ isP2SH = true
438443 }
439444
440445 switch ( scriptType ) {
441446 case bscript . types . P2WPKH :
442- rawWitness = buildRawScriptSig ( scriptType , input . signatures , input . pubKeys , allowIncomplete )
447+ rawWitness = rawScript
448+ rawScript = [ ]
443449 break
444450
445451 case bscript . types . P2WSH :
446- // We can remove this check later
447- if ( ! allowIncomplete && ! supportedType ( input . witnessScriptType ) ) {
448- throw new Error ( 'Impossible to sign this type' )
449- }
452+ scriptType = input . witnessScriptType
453+ rawWitness = buildRawScriptSig ( scriptType , input . signatures , input . pubKeys , allowIncomplete )
454+ if ( ! allowIncomplete && ! rawWitness . length ) throw new Error ( 'Cannot build witness for ' + scriptType )
450455
451- if ( supportedType ( input . witnessScriptType ) ) {
452- rawWitness = buildRawScriptSig ( input . witnessScriptType , input . signatures , input . pubKeys , allowIncomplete )
456+ if ( input . witnessScript ) {
453457 rawWitness . push ( input . witnessScript )
454- scriptType = input . witnessScriptType
455458 }
456459
457460 break
458461 }
459462
460- // append redeemScript if necessary
461- if ( p2sh ) {
463+ if ( isP2SH ) {
462464 rawScript . push ( input . redeemScript )
463465 }
464466
465467 return {
466468 type : scriptType ,
467- script : bscript . compile ( rawScript ) ,
468- witness : bscript . toStack ( rawWitness )
469+ rawScript : rawScript ,
470+ rawWitness : rawWitness
469471 }
470472}
471473
@@ -638,14 +640,15 @@ TransactionBuilder.prototype.__build = function (allowIncomplete) {
638640 var result = buildInput ( input , allowIncomplete )
639641
640642 // skip if no result
641- if ( ! allowIncomplete ) {
642- if ( ! supportedType ( result . type ) && result . type !== bscript . types . P2WPKH ) {
643- throw new Error ( result . type + ' not supported' )
644- }
643+ if ( ! allowIncomplete &&
644+ result . rawScript . length === 0 &&
645+ result . rawWitness . length === 0
646+ ) {
647+ throw new Error ( result . type + ' not supported' )
645648 }
646649
647- tx . setInputScript ( i , result . script )
648- tx . setWitness ( i , result . witness )
650+ tx . setInputScript ( i , bscript . compile ( result . rawScript ) )
651+ tx . setWitness ( i , bscript . toStack ( result . rawWitness ) )
649652 } )
650653
651654 if ( ! allowIncomplete ) {
0 commit comments