@@ -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 ) {
@@ -385,91 +386,92 @@ function prepareInput (input, kpPubKey, redeemScript, witnessValue, witnessScrip
385386 input . witness = witness
386387}
387388
389+ function enforceMinSigs ( allowIncomplete , signatures , pubKeys , n , m ) {
390+ if ( allowIncomplete ) {
391+ if ( signatures . length !== n ) return
392+ if ( pubKeys . length !== m ) return
393+ return true
394+ }
395+
396+ if ( signatures . length !== n ) throw new Error ( 'Not enough signatures provided' )
397+ if ( pubKeys . length !== m ) throw new Error ( 'Invalid number of pubKeys' )
398+ return true
399+ }
400+
388401function buildRawScriptSig ( type , signatures , pubKeys , allowIncomplete ) {
389402 if ( type === scriptTypes . P2WPKH ) {
390- if ( signatures . length === 1 && Buffer . isBuffer ( signatures [ 0 ] ) && pubKeys . length === 1 ) return bscript . witnessPubKeyHash . input . encodeRaw ( signatures [ 0 ] , pubKeys [ 0 ] )
391- } else if ( type === scriptTypes . P2PKH ) {
392- if ( signatures . length === 1 && Buffer . isBuffer ( signatures [ 0 ] ) && pubKeys . length === 1 ) return bscript . pubKeyHash . input . encodeRaw ( signatures [ 0 ] , pubKeys [ 0 ] )
393- } else if ( type === scriptTypes . P2PK ) {
394- if ( signatures . length === 1 && Buffer . isBuffer ( signatures [ 0 ] ) ) return bscript . pubKey . input . encodeRaw ( signatures [ 0 ] )
395- } else if ( type === scriptTypes . MULTISIG ) {
396- if ( signatures . length > 0 ) {
397- signatures = signatures . map ( function ( signature ) {
398- return signature || ops . OP_0
399- } )
403+ if ( ! enforceMinSigs ( allowIncomplete , signatures , pubKeys , 1 , 1 ) ) return [ ]
404+ return bscript . witnessPubKeyHash . input . encodeRaw ( signatures [ 0 ] , pubKeys [ 0 ] )
405+ }
400406
401- if ( ! allowIncomplete ) {
402- // remove blank signatures
403- signatures = signatures . filter ( function ( x ) { return x !== ops . OP_0 } )
404- }
407+ if ( type === scriptTypes . P2PKH ) {
408+ if ( ! enforceMinSigs ( allowIncomplete , signatures , pubKeys , 1 , 1 ) ) return [ ]
409+ return bscript . pubKeyHash . input . encodeRaw ( signatures [ 0 ] , pubKeys [ 0 ] )
410+ }
411+
412+ if ( type === scriptTypes . MULTISIG ) {
413+ signatures = signatures . map ( function ( signature ) {
414+ return signature || ops . OP_0
415+ } )
405416
406- return bscript . multisig . input . encodeRaw ( signatures )
417+ if ( ! allowIncomplete ) {
418+ // remove blank signatures
419+ signatures = signatures . filter ( function ( x ) { return x !== ops . OP_0 } )
407420 }
408- } else {
409- throw new Error ( 'Not yet supported' )
421+
422+ return bscript . multisig . input . encodeRaw ( signatures )
423+ }
424+
425+ if ( type === scriptTypes . P2PK ) {
426+ if ( ! enforceMinSigs ( allowIncomplete , signatures , [ ] , 1 , 0 ) ) return [ ]
427+ return bscript . pubKey . input . encodeRaw ( signatures [ 0 ] )
410428 }
411429
412- if ( ! allowIncomplete ) throw new Error ( 'Not enough signatures provided' )
413430 return [ ]
414431}
415432
416433function buildInput ( input , allowIncomplete ) {
417434 var scriptType = input . prevOutType
418- var rawScript = [ ]
435+ var rawScript = buildRawScriptSig ( scriptType , input . signatures , input . pubKeys , allowIncomplete )
419436 var rawWitness = [ ]
420437
421- if ( supportedType ( scriptType ) ) {
422- rawScript = buildRawScriptSig ( scriptType , input . signatures , input . pubKeys , allowIncomplete )
423- }
424-
425- var p2sh = false
438+ var isP2SH = false
426439 if ( scriptType === bscript . types . P2SH ) {
427- // We can remove this error later when we have a guarantee prepareInput
428- // rejects unsignable scripts - it MUST be signable at this point.
429- if ( ! allowIncomplete && ! supportedP2SHType ( input . redeemScriptType ) ) {
430- throw new Error ( 'Impossible to sign this type' )
431- }
432-
433- if ( supportedType ( input . redeemScriptType ) ) {
434- rawScript = buildRawScriptSig ( input . redeemScriptType , input . signatures , input . pubKeys , allowIncomplete )
435- }
440+ scriptType = input . redeemScriptType
436441
437- // If it wasn't SIGNABLE, it's witness, defer to that
438- if ( input . redeemScriptType ) {
439- p2sh = true
440- scriptType = input . redeemScriptType
442+ if ( scriptType !== bscript . types . P2WSH ) {
443+ rawScript = buildRawScriptSig ( scriptType , input . signatures , input . pubKeys , allowIncomplete )
444+ if ( ! allowIncomplete && ! rawScript . length ) throw new Error ( 'Cannot build script for ' + scriptType )
441445 }
446+ isP2SH = true
442447 }
443448
444449 switch ( scriptType ) {
445450 case bscript . types . P2WPKH :
446- rawWitness = buildRawScriptSig ( scriptType , input . signatures , input . pubKeys , allowIncomplete )
451+ rawWitness = rawScript
452+ rawScript = [ ]
447453 break
448454
449455 case bscript . types . P2WSH :
450- // We can remove this check later
451- if ( ! allowIncomplete && ! supportedType ( input . witnessScriptType ) ) {
452- throw new Error ( 'Impossible to sign this type' )
453- }
456+ scriptType = input . witnessScriptType
457+ rawWitness = buildRawScriptSig ( scriptType , input . signatures , input . pubKeys , allowIncomplete )
458+ if ( ! allowIncomplete && ! rawWitness . length ) throw new Error ( 'Cannot build witness for ' + scriptType )
454459
455- if ( supportedType ( input . witnessScriptType ) ) {
456- rawWitness = buildRawScriptSig ( input . witnessScriptType , input . signatures , input . pubKeys , allowIncomplete )
460+ if ( input . witnessScript ) {
457461 rawWitness . push ( input . witnessScript )
458- scriptType = input . witnessScriptType
459462 }
460463
461464 break
462465 }
463466
464- // append redeemScript if necessary
465- if ( p2sh ) {
467+ if ( isP2SH ) {
466468 rawScript . push ( input . redeemScript )
467469 }
468470
469471 return {
470472 type : scriptType ,
471- script : bscript . compile ( rawScript ) ,
472- witness : bscript . toStack ( rawWitness )
473+ rawScript : rawScript ,
474+ rawWitness : rawWitness
473475 }
474476}
475477
@@ -642,14 +644,15 @@ TransactionBuilder.prototype.__build = function (allowIncomplete) {
642644 var result = buildInput ( input , allowIncomplete )
643645
644646 // skip if no result
645- if ( ! allowIncomplete ) {
646- if ( ! supportedType ( result . type ) && result . type !== bscript . types . P2WPKH ) {
647- throw new Error ( result . type + ' not supported' )
648- }
647+ if ( ! allowIncomplete &&
648+ result . rawScript . length === 0 &&
649+ result . rawWitness . length === 0
650+ ) {
651+ throw new Error ( result . type + ' not supported' )
649652 }
650653
651- tx . setInputScript ( i , result . script )
652- tx . setWitness ( i , result . witness )
654+ tx . setInputScript ( i , bscript . compile ( result . rawScript ) )
655+ tx . setWitness ( i , bscript . toStack ( result . rawWitness ) )
653656 } )
654657
655658 if ( ! allowIncomplete ) {
0 commit comments