@ -108,8 +108,8 @@ function TransactionBuilder(opts) {
this . signhash = opts . signhash || Transaction . SIGHASH_ALL ;
this . signhash = opts . signhash || Transaction . SIGHASH_ALL ;
this . tx = { } ;
this . tx = { } ;
this . inputsSigned = 0 ;
this . inputsSigned = 0 ;
this . signaturesAdded = 0 ;
this . signaturesAdded = 0 ;
return this ;
return this ;
}
}
@ -119,10 +119,10 @@ TransactionBuilder.FEE_PER_1000B_SAT = FEE_PER_1000B_SAT;
TransactionBuilder . _ scriptForPubkeys = function ( out ) {
TransactionBuilder . _ scriptForPubkeys = function ( out ) {
var l = out . pubkeys . length ;
var l = out . pubkeys . length ;
var pubKeyBuf = [ ] ;
var pubKeyBuf = [ ] ;
for ( var i = 0 ; i < l ; i ++ ) {
for ( var i = 0 ; i < l ; i ++ ) {
pubKeyBuf . push ( new Buffer ( out . pubkeys [ i ] , 'hex' ) ) ;
pubKeyBuf . push ( new Buffer ( out . pubkeys [ i ] , 'hex' ) ) ;
}
}
return Script . createMultisig ( out . nreq , pubKeyBuf ) ;
return Script . createMultisig ( out . nreq , pubKeyBuf ) ;
@ -271,7 +271,7 @@ TransactionBuilder.prototype._setInputs = function(txobj) {
var l = ins . length ;
var l = ins . length ;
var valueInSat = bignum ( 0 ) ;
var valueInSat = bignum ( 0 ) ;
txobj . ins = [ ] ;
txobj . ins = [ ] ;
for ( var i = 0 ; i < l ; i ++ ) {
for ( var i = 0 ; i < l ; i ++ ) {
valueInSat = valueInSat . add ( util . parseValue ( ins [ i ] . amount ) ) ;
valueInSat = valueInSat . add ( util . parseValue ( ins [ i ] . amount ) ) ;
@ -294,7 +294,7 @@ TransactionBuilder.prototype._setInputs = function(txobj) {
} ;
} ;
TransactionBuilder . prototype . _ setFee = function ( feeSat ) {
TransactionBuilder . prototype . _ setFee = function ( feeSat ) {
if ( typeof this . valueOutSat === 'undefined' )
if ( typeof this . valueOutSat === 'undefined' )
throw new Error ( 'valueOutSat undefined' ) ;
throw new Error ( 'valueOutSat undefined' ) ;
@ -312,13 +312,13 @@ TransactionBuilder.prototype._setFee = function(feeSat) {
TransactionBuilder . prototype . _ setRemainder = function ( txobj , remainderIndex ) {
TransactionBuilder . prototype . _ setRemainder = function ( txobj , remainderIndex ) {
if ( typeof this . valueInSat === 'undefined' ||
if ( typeof this . valueInSat === 'undefined' ||
typeof this . valueOutSat === 'undefined' )
typeof this . valueOutSat === 'undefined' )
throw new Error ( 'valueInSat / valueOutSat undefined' ) ;
throw new Error ( 'valueInSat / valueOutSat undefined' ) ;
/* add remainder (without modifying outs[]) */
/* add remainder (without modifying outs[]) */
var remainderSat = this . valueInSat . sub ( this . valueOutSat ) . sub ( this . feeSat ) ;
var remainderSat = this . valueInSat . sub ( this . valueOutSat ) . sub ( this . feeSat ) ;
var l = txobj . outs . length ;
var l = txobj . outs . length ;
this . remainderSat = bignum ( 0 ) ;
this . remainderSat = bignum ( 0 ) ;
/*remove old remainder? */
/*remove old remainder? */
@ -344,7 +344,8 @@ TransactionBuilder.prototype._setRemainder = function(txobj, remainderIndex) {
TransactionBuilder . prototype . _ setFeeAndRemainder = function ( txobj ) {
TransactionBuilder . prototype . _ setFeeAndRemainder = function ( txobj ) {
/* starting size estimation */
/* starting size estimation */
var size = 500 , maxSizeK , remainderIndex = txobj . outs . length ;
var size = 500 ,
maxSizeK , remainderIndex = txobj . outs . length ;
do {
do {
/* based on https://en.bitcoin.it/wiki/Transaction_fees */
/* based on https://en.bitcoin.it/wiki/Transaction_fees */
maxSizeK = parseInt ( size / 1000 ) + 1 ;
maxSizeK = parseInt ( size / 1000 ) + 1 ;
@ -389,7 +390,7 @@ TransactionBuilder.prototype.setOutputs = function(outs) {
txobj . ins = [ ] ;
txobj . ins = [ ] ;
txobj . outs = [ ] ;
txobj . outs = [ ] ;
var l = outs . length ;
var l = outs . length ;
for ( var i = 0 ; i < l ; i ++ ) {
for ( var i = 0 ; i < l ; i ++ ) {
var amountSat = outs [ i ] . amountSat || util . parseValue ( outs [ i ] . amount ) ;
var amountSat = outs [ i ] . amountSat || util . parseValue ( outs [ i ] . amount ) ;
var value = util . bigIntToValue ( amountSat ) ;
var value = util . bigIntToValue ( amountSat ) ;
@ -422,13 +423,15 @@ TransactionBuilder._mapKeys = function(keys) {
if ( typeof k === 'string' ) {
if ( typeof k === 'string' ) {
var pk = new PrivateKey ( k ) ;
var pk = new PrivateKey ( k ) ;
wk = new WalletKey ( { network : pk . network ( ) } ) ;
wk = new WalletKey ( {
wk . fromObj ( { priv : k } ) ;
network : pk . network ( )
}
} ) ;
else if ( k instanceof WalletKey ) {
wk . fromObj ( {
priv : k
} ) ;
} else if ( k instanceof WalletKey ) {
wk = k ;
wk = k ;
}
} else {
else {
throw new Error ( 'argument must be an array of strings (WIF format) or WalletKey objects' ) ;
throw new Error ( 'argument must be an array of strings (WIF format) or WalletKey objects' ) ;
}
}
walletKeyMap [ wk . storeObj ( ) . addr ] = wk ;
walletKeyMap [ wk . storeObj ( ) . addr ] = wk ;
@ -437,30 +440,31 @@ TransactionBuilder._mapKeys = function(keys) {
} ;
} ;
TransactionBuilder . _ signHashAndVerify = function ( wk , txSigHash ) {
TransactionBuilder . _ signHashAndVerify = function ( wk , txSigHash ) {
var triesLeft = 10 , sigRaw ;
var triesLeft = 10 ,
sigRaw ;
do {
do {
sigRaw = wk . privKey . signSync ( txSigHash ) ;
sigRaw = wk . privKey . signSync ( txSigHash ) ;
} while ( wk . privKey . verifySignatureSync ( txSigHash , sigRaw ) === false &&
} while ( wk . privKey . verifySignatureSync ( txSigHash , sigRaw ) === false &&
triesLeft -- ) ;
triesLeft -- ) ;
if ( triesLeft < 0 )
if ( triesLeft < 0 )
throw new Error ( 'could not sign input: verification failed' ) ;
throw new Error ( 'could not sign input: verification failed' ) ;
return sigRaw ;
return sigRaw ;
} ;
} ;
TransactionBuilder . prototype . _ checkTx = function ( ) {
TransactionBuilder . prototype . _ checkTx = function ( ) {
if ( ! this . tx || ! this . tx . ins . length || ! this . tx . outs . length )
if ( ! this . tx || ! this . tx . ins . length || ! this . tx . outs . length )
throw new Error ( 'tx is not defined' ) ;
throw new Error ( 'tx is not defined' ) ;
} ;
} ;
TransactionBuilder . prototype . _ multiFindKey = function ( walletKeyMap , pubKeyHash ) {
TransactionBuilder . prototype . _ multiFindKey = function ( walletKeyMap , pubKeyHash ) {
var wk ;
var wk ;
[ networks . livenet , networks . testnet ] . forEach ( function ( n ) {
[ networks . livenet , networks . testnet ] . forEach ( function ( n ) {
[ n . addressVersion , n . P2SHVersion ] . forEach ( function ( v ) {
[ n . addressVersion , n . P2SHVersion ] . forEach ( function ( v ) {
var a = new Address ( v , pubKeyHash ) ;
var a = new Address ( v , pubKeyHash ) ;
if ( ! wk && walletKeyMap [ a ] ) {
if ( ! wk && walletKeyMap [ a ] ) {
wk = walletKeyMap [ a ] ;
wk = walletKeyMap [ a ] ;
}
}
@ -475,11 +479,9 @@ TransactionBuilder.prototype._findWalletKey = function(walletKeyMap, input) {
if ( input . address ) {
if ( input . address ) {
wk = walletKeyMap [ input . address ] ;
wk = walletKeyMap [ input . address ] ;
}
} else if ( input . pubKeyHash ) {
else if ( input . pubKeyHash ) {
wk = this . _ multiFindKey ( walletKeyMap , input . pubKeyHash ) ;
wk = this . _ multiFindKey ( walletKeyMap , input . pubKeyHash ) ;
}
} else if ( input . pubKeyBuf ) {
else if ( input . pubKeyBuf ) {
var pubKeyHash = util . sha256ripe160 ( input . pubKeyBuf ) ;
var pubKeyHash = util . sha256ripe160 ( input . pubKeyBuf ) ;
wk = this . _ multiFindKey ( walletKeyMap , pubKeyHash ) ;
wk = this . _ multiFindKey ( walletKeyMap , pubKeyHash ) ;
} else {
} else {
@ -502,7 +504,11 @@ TransactionBuilder.prototype._signPubKey = function(walletKeyMap, input, txSigHa
var scriptSig = new Script ( ) ;
var scriptSig = new Script ( ) ;
scriptSig . chunks . push ( sig ) ;
scriptSig . chunks . push ( sig ) ;
scriptSig . updateBuffer ( ) ;
scriptSig . updateBuffer ( ) ;
return { inputFullySigned : true , signaturesAdded : 1 , script : scriptSig . getBuffer ( ) } ;
return {
inputFullySigned : true ,
signaturesAdded : 1 ,
script : scriptSig . getBuffer ( )
} ;
} ;
} ;
TransactionBuilder . prototype . _ signPubKeyHash = function ( walletKeyMap , input , txSigHash ) {
TransactionBuilder . prototype . _ signPubKeyHash = function ( walletKeyMap , input , txSigHash ) {
@ -521,7 +527,11 @@ TransactionBuilder.prototype._signPubKeyHash = function(walletKeyMap, input, txS
scriptSig . chunks . push ( sig ) ;
scriptSig . chunks . push ( sig ) ;
scriptSig . chunks . push ( wk . privKey . public ) ;
scriptSig . chunks . push ( wk . privKey . public ) ;
scriptSig . updateBuffer ( ) ;
scriptSig . updateBuffer ( ) ;
return { inputFullySigned : true , signaturesAdded : 1 , script : scriptSig . getBuffer ( ) } ;
return {
inputFullySigned : true ,
signaturesAdded : 1 ,
script : scriptSig . getBuffer ( )
} ;
} ;
} ;
/ * F O R T E S T I N G
/ * F O R T E S T I N G
@ -537,13 +547,13 @@ var _dumpChunks = function (scriptSig, label) {
TransactionBuilder . prototype . _ chunkSignedWithKey = function ( scriptSig , txSigHash , publicKey ) {
TransactionBuilder . prototype . _ chunkSignedWithKey = function ( scriptSig , txSigHash , publicKey ) {
var ret ;
var ret ;
var k = new Key ( ) ;
var k = new Key ( ) ;
k . public = publicKey ;
k . public = publicKey ;
for ( var i = 1 ; i <= scriptSig . countSignatures ( ) ; i ++ ) {
for ( var i = 1 ; i <= scriptSig . countSignatures ( ) ; i ++ ) {
var chunk = scriptSig . chunks [ i ] ;
var chunk = scriptSig . chunks [ i ] ;
var sigRaw = new Buffer ( chunk . slice ( 0 , chunk . length - 1 ) ) ;
var sigRaw = new Buffer ( chunk . slice ( 0 , chunk . length - 1 ) ) ;
if ( k . verifySignatureSync ( txSigHash , sigRaw ) ) {
if ( k . verifySignatureSync ( txSigHash , sigRaw ) ) {
ret = chunk ;
ret = chunk ;
}
}
}
}
return ret ;
return ret ;
@ -551,10 +561,10 @@ TransactionBuilder.prototype._chunkSignedWithKey = function(scriptSig, txSigHash
TransactionBuilder . prototype . _ getSignatureOrder = function ( sigPrio , sigRaw , txSigHash , pubkeys ) {
TransactionBuilder . prototype . _ getSignatureOrder = function ( sigPrio , sigRaw , txSigHash , pubkeys ) {
var l = pubkeys . length ;
var l = pubkeys . length ;
for ( var j = 0 ; j < l ; j ++ ) {
for ( var j = 0 ; j < l ; j ++ ) {
var k = new Key ( ) ;
var k = new Key ( ) ;
k . public = new Buffer ( pubkeys [ j ] , 'hex' ) ;
k . public = new Buffer ( pubkeys [ j ] , 'hex' ) ;
if ( k . verifySignatureSync ( txSigHash , sigRaw ) )
if ( k . verifySignatureSync ( txSigHash , sigRaw ) )
break ;
break ;
}
}
@ -563,13 +573,13 @@ TransactionBuilder.prototype._getSignatureOrder = function(sigPrio, sigRaw, txSi
TransactionBuilder . prototype . _ getNewSignatureOrder = function ( sigPrio , scriptSig , txSigHash , pubkeys ) {
TransactionBuilder . prototype . _ getNewSignatureOrder = function ( sigPrio , scriptSig , txSigHash , pubkeys ) {
var iPrio ;
var iPrio ;
for ( var i = 1 ; i <= scriptSig . countSignatures ( ) ; i ++ ) {
for ( var i = 1 ; i <= scriptSig . countSignatures ( ) ; i ++ ) {
var chunk = scriptSig . chunks [ i ] ;
var chunk = scriptSig . chunks [ i ] ;
var sigRaw = new Buffer ( chunk . slice ( 0 , chunk . length - 1 ) ) ;
var sigRaw = new Buffer ( chunk . slice ( 0 , chunk . length - 1 ) ) ;
iPrio = this . _ getSignatureOrder ( sigPrio , sigRaw , txSigHash , pubkeys ) ;
iPrio = this . _ getSignatureOrder ( sigPrio , sigRaw , txSigHash , pubkeys ) ;
if ( sigPrio <= iPrio ) break ;
if ( sigPrio <= iPrio ) break ;
}
}
return ( sigPrio === iPrio ? - 1 : i - 1 ) ;
return ( sigPrio === iPrio ? - 1 : i - 1 ) ;
} ;
} ;
TransactionBuilder . prototype . _ chunkIsEmpty = function ( chunk ) {
TransactionBuilder . prototype . _ chunkIsEmpty = function ( chunk ) {
@ -599,10 +609,10 @@ TransactionBuilder.prototype._updateMultiSig = function(sigPrio, wk, scriptSig,
var sig = Buffer . concat ( [ sigRaw , sigType ] ) ;
var sig = Buffer . concat ( [ sigRaw , sigType ] ) ;
// Add signature
// Add signature
var order = this . _ getNewSignatureOrder ( sigPrio , scriptSig , txSigHash , pubkeys ) ;
var order = this . _ getNewSignatureOrder ( sigPrio , scriptSig , txSigHash , pubkeys ) ;
scriptSig . chunks . splice ( order + 1 , 0 , sig ) ;
scriptSig . chunks . splice ( order + 1 , 0 , sig ) ;
scriptSig . updateBuffer ( ) ;
scriptSig . updateBuffer ( ) ;
wasUpdated = true ;
wasUpdated = true ;
return wasUpdated ? scriptSig : null ;
return wasUpdated ? scriptSig : null ;
} ;
} ;
@ -614,11 +624,13 @@ TransactionBuilder.prototype._signMultiSig = function(walletKeyMap, input, txSig
l = pubkeys . length ,
l = pubkeys . length ,
originalScriptBuf = this . tx . ins [ input . i ] . s ;
originalScriptBuf = this . tx . ins [ input . i ] . s ;
var scriptSig = new Script ( originalScriptBuf ) ;
var scriptSig = new Script ( originalScriptBuf ) ;
var signaturesAdded = 0 ;
var signaturesAdded = 0 ;
for ( var j = 0 ; j < l && scriptSig . countSignatures ( ) < nreq ; j ++ ) {
for ( var j = 0 ; j < l && scriptSig . countSignatures ( ) < nreq ; j ++ ) {
var wk = this . _ findWalletKey ( walletKeyMap , { pubKeyBuf : pubkeys [ j ] } ) ;
var wk = this . _ findWalletKey ( walletKeyMap , {
pubKeyBuf : pubkeys [ j ]
} ) ;
if ( ! wk ) continue ;
if ( ! wk ) continue ;
var newScriptSig = this . _ updateMultiSig ( j , wk , scriptSig , txSigHash , pubkeys ) ;
var newScriptSig = this . _ updateMultiSig ( j , wk , scriptSig , txSigHash , pubkeys ) ;
@ -640,11 +652,11 @@ var fnToSign = {};
TransactionBuilder . prototype . _ scriptIsAppended = function ( script , scriptToAddBuf ) {
TransactionBuilder . prototype . _ scriptIsAppended = function ( script , scriptToAddBuf ) {
var len = script . chunks . length ;
var len = script . chunks . length ;
if ( script . chunks [ len - 1 ] === undefined )
if ( script . chunks [ len - 1 ] === undefined )
return false ;
return false ;
if ( typeof script . chunks [ len - 1 ] === 'number' )
if ( typeof script . chunks [ len - 1 ] === 'number' )
return false ;
return false ;
if ( buffertools . compare ( script . chunks [ len - 1 ] , scriptToAddBuf ) !== 0 )
if ( buffertools . compare ( script . chunks [ len - 1 ] , scriptToAddBuf ) !== 0 )
return false ;
return false ;
return true ;
return true ;
@ -664,7 +676,7 @@ TransactionBuilder.prototype._getInputForP2sh = function(script, index) {
var scriptType = script . classify ( ) ;
var scriptType = script . classify ( ) ;
/* pubKeyHash is needed for TX_PUBKEYHASH and TX_PUBKEY to retrieve the keys. */
/* pubKeyHash is needed for TX_PUBKEYHASH and TX_PUBKEY to retrieve the keys. */
var pubKeyHash ;
var pubKeyHash ;
switch ( scriptType ) {
switch ( scriptType ) {
case Script . TX_PUBKEYHASH :
case Script . TX_PUBKEYHASH :
pubKeyHash = script . captureOne ( ) ;
pubKeyHash = script . captureOne ( ) ;
break ;
break ;
@ -689,16 +701,16 @@ TransactionBuilder.prototype._p2shInput = function(input) {
var scriptHex = this . hashToScriptMap [ input . address ] ;
var scriptHex = this . hashToScriptMap [ input . address ] ;
if ( ! scriptHex ) return ;
if ( ! scriptHex ) return ;
var scriptBuf = new Buffer ( scriptHex , 'hex' ) ;
var scriptBuf = new Buffer ( scriptHex , 'hex' ) ;
var script = new Script ( scriptBuf ) ;
var script = new Script ( scriptBuf ) ;
var scriptType = script . classify ( ) ;
var scriptType = script . classify ( ) ;
if ( ! fnToSign [ scriptType ] || scriptType === Script . TX_SCRIPTHASH )
if ( ! fnToSign [ scriptType ] || scriptType === Script . TX_SCRIPTHASH )
throw new Error ( 'dont know how to sign p2sh script type:' + script . getRawOutType ( ) ) ;
throw new Error ( 'dont know how to sign p2sh script type:' + script . getRawOutType ( ) ) ;
return {
return {
input : this . _ getInputForP2sh ( script , input . i ) ,
input : this . _ getInputForP2sh ( script , input . i ) ,
txSigHash : this . tx . hashForSignature ( script , input . i , this . signhash ) ,
txSigHash : this . tx . hashForSignature ( script , input . i , this . signhash ) ,
scriptType : script . classify ( ) ,
scriptType : script . classify ( ) ,
scriptBuf : scriptBuf ,
scriptBuf : scriptBuf ,
} ;
} ;
@ -751,7 +763,7 @@ TransactionBuilder.prototype.sign = function(keys) {
if ( ret && ret . script ) {
if ( ret && ret . script ) {
tx . ins [ i ] . s = ret . script ;
tx . ins [ i ] . s = ret . script ;
if ( ret . inputFullySigned ) this . inputsSigned ++ ;
if ( ret . inputFullySigned ) this . inputsSigned ++ ;
if ( ret . signaturesAdded ) this . signaturesAdded += ret . signaturesAdded ;
if ( ret . signaturesAdded ) this . signaturesAdded += ret . signaturesAdded ;
}
}
}
}
return this ;
return this ;
@ -764,7 +776,7 @@ TransactionBuilder.prototype.sign = function(keys) {
// for generate the input for this call.
// for generate the input for this call.
//
//
TransactionBuilder . prototype . setHashToScriptMap = function ( hashToScriptMap ) {
TransactionBuilder . prototype . setHashToScriptMap = function ( hashToScriptMap ) {
this . hashToScriptMap = hashToScriptMap ;
this . hashToScriptMap = hashToScriptMap ;
return this ;
return this ;
} ;
} ;
@ -793,22 +805,22 @@ TransactionBuilder.prototype.build = function() {
//
//
TransactionBuilder . prototype . toObj = function ( ) {
TransactionBuilder . prototype . toObj = function ( ) {
var data = {
var data = {
valueInSat : this . valueInSat . toString ( ) ,
valueInSat : this . valueInSat . toString ( ) ,
valueOutSat : this . valueOutSat . toString ( ) ,
valueOutSat : this . valueOutSat . toString ( ) ,
feeSat : this . feeSat . toString ( ) ,
feeSat : this . feeSat . toString ( ) ,
remainderSat : this . remainderSat . toString ( ) ,
remainderSat : this . remainderSat . toString ( ) ,
hashToScriptMap : this . hashToScriptMap ,
hashToScriptMap : this . hashToScriptMap ,
selectedUtxos : this . selectedUtxos ,
selectedUtxos : this . selectedUtxos ,
inputsSigned : this . inputsSigned ,
inputsSigned : this . inputsSigned ,
signaturesAdded : this . signaturesAdded ,
signaturesAdded : this . signaturesAdded ,
signhash : this . signhash ,
signhash : this . signhash ,
spendUnconfirmed : this . spendUnconfirmed ,
spendUnconfirmed : this . spendUnconfirmed ,
} ;
} ;
if ( this . tx ) {
if ( this . tx ) {
data . tx = this . tx . serialize ( ) . toString ( 'hex' ) ;
data . tx = this . tx . serialize ( ) . toString ( 'hex' ) ;
}
}
return data ;
return data ;
} ;
} ;
@ -840,7 +852,7 @@ TransactionBuilder.fromObj = function(data) {
if ( data . tx ) {
if ( data . tx ) {
// Tx may have signatures, that are not on txobj
// Tx may have signatures, that are not on txobj
var t = new Transaction ( ) ;
var t = new Transaction ( ) ;
t . parse ( new Buffer ( data . tx , 'hex' ) ) ;
t . parse ( new Buffer ( data . tx , 'hex' ) ) ;
b . tx = t ;
b . tx = t ;
}
}
return b ;
return b ;
@ -848,65 +860,66 @@ TransactionBuilder.fromObj = function(data) {
TransactionBuilder . prototype . _ checkMergeability = function ( b ) {
TransactionBuilder . prototype . _ checkMergeability = function ( b ) {
var self = this ;
var self = this ;
// Builder should have the same params
// Builder should have the same params
[ 'valueInSat' , 'valueOutSat' , 'feeSat' , 'remainderSat' , 'signhash' , 'spendUnconfirmed' ]
[ 'valueInSat' , 'valueOutSat' , 'feeSat' , 'remainderSat' , 'signhash' , 'spendUnconfirmed' ]
. forEach ( function ( k ) {
. forEach ( function ( k ) {
if ( self [ k ] . toString ( ) !== b [ k ] . toString ( ) ) {
if ( self [ k ] . toString ( ) !== b [ k ] . toString ( ) ) {
throw new Error ( 'mismatch at TransactionBuilder match: '
throw new Error ( 'mismatch at TransactionBuilder match: ' + k + ': ' + self [ k ] + ' vs. ' + b [ k ] ) ;
+ k + ': ' + self [ k ] + ' vs. ' + b [ k ] ) ;
}
}
} ) ;
} ) ;
if ( self . hashToScriptMap ) {
if ( self . hashToScriptMap ) {
var err = 0 ;
var err = 0 ;
if ( ! b . hashToScriptMap ) err = 1 ;
if ( ! b . hashToScriptMap ) err = 1 ;
Object . keys ( self . hashToScriptMap ) . forEach ( function ( k ) {
Object . keys ( self . hashToScriptMap ) . forEach ( function ( k ) {
if ( ! b . hashToScriptMap [ k ] ) err = 1 ;
if ( ! b . hashToScriptMap [ k ] ) err = 1 ;
if ( self . hashToScriptMap [ k ] !== b . hashToScriptMap [ k ] ) err = 1 ;
if ( self . hashToScriptMap [ k ] !== b . hashToScriptMap [ k ] ) err = 1 ;
} ) ;
} ) ;
if ( err )
if ( err )
throw new Error ( 'mismatch at TransactionBuilder hashToScriptMap' ) ;
throw new Error ( 'mismatch at TransactionBuilder hashToScriptMap' ) ;
}
}
var err = 0 , i = 0 ; ;
var err = 0 ,
i = 0 ; ;
self . selectedUtxos . forEach ( function ( u ) {
self . selectedUtxos . forEach ( function ( u ) {
if ( ! err ) {
if ( ! err ) {
var v = b . selectedUtxos [ i ++ ] ;
var v = b . selectedUtxos [ i ++ ] ;
if ( ! v ) err = 1 ;
if ( ! v ) err = 1 ;
// confirmations could differ
// confirmations could differ
[ 'address' , 'hash' , 'scriptPubKey' , 'vout' , 'amount' ] . forEach ( function ( k ) {
[ 'address' , 'hash' , 'scriptPubKey' , 'vout' , 'amount' ] . forEach ( function ( k ) {
if ( u [ k ] !== v [ k ] )
if ( u [ k ] !== v [ k ] )
err = k ;
err = k ;
} ) ;
} ) ;
}
}
} ) ;
} ) ;
if ( err )
if ( err )
throw new Error ( 'mismatch at TransactionBuilder selectedUtxos #' + i - 1 + ' Key:' + err ) ;
throw new Error ( 'mismatch at TransactionBuilder selectedUtxos #' + i - 1 + ' Key:' + err ) ;
err = 0 ; i = 0 ; ;
err = 0 ;
i = 0 ; ;
self . inputMap . forEach ( function ( u ) {
self . inputMap . forEach ( function ( u ) {
if ( ! err ) {
if ( ! err ) {
var v = b . inputMap [ i ++ ] ;
var v = b . inputMap [ i ++ ] ;
if ( ! v ) err = 1 ;
if ( ! v ) err = 1 ;
// confirmations could differ
// confirmations could differ
[ 'address' , 'scriptType' , 'scriptPubKey' , 'i' ] . forEach ( function ( k ) {
[ 'address' , 'scriptType' , 'scriptPubKey' , 'i' ] . forEach ( function ( k ) {
if ( u [ k ] . toString ( ) !== v [ k ] . toString ( ) )
if ( u [ k ] . toString ( ) !== v [ k ] . toString ( ) )
err = k ;
err = k ;
} ) ;
} ) ;
}
}
} ) ;
} ) ;
if ( err )
if ( err )
throw new Error ( 'mismatch at TransactionBuilder inputMap #' + i - 1 + ' Key:' + err ) ;
throw new Error ( 'mismatch at TransactionBuilder inputMap #' + i - 1 + ' Key:' + err ) ;
} ;
} ;
// TODO this could be on Script class
// TODO this could be on Script class
TransactionBuilder . prototype . _ mergeInputSigP2sh = function ( input , s0 , s1 ) {
TransactionBuilder . prototype . _ mergeInputSigP2sh = function ( input , s0 , s1 ) {
var p2sh = this . _ p2shInput ( input ) ;
var p2sh = this . _ p2shInput ( input ) ;
var redeemScript = new Script ( p2sh . scriptBuf ) ;
var redeemScript = new Script ( p2sh . scriptBuf ) ;
var pubkeys = redeemScript . capture ( ) ;
var pubkeys = redeemScript . capture ( ) ;
@ -914,13 +927,13 @@ TransactionBuilder.prototype._mergeInputSigP2sh = function(input,s0,s1) {
// Look for differences
// Look for differences
var s0keys = { } ;
var s0keys = { } ;
var l = pubkeys . length ;
var l = pubkeys . length ;
for ( var j = 0 ; j < l ; j ++ ) {
for ( var j = 0 ; j < l ; j ++ ) {
if ( this . _ chunkSignedWithKey ( s0 , p2sh . txSigHash , pubkeys [ j ] ) )
if ( this . _ chunkSignedWithKey ( s0 , p2sh . txSigHash , pubkeys [ j ] ) )
s0keys [ pubkeys [ j ] . toString ( 'hex' ) ] = 1 ;
s0keys [ pubkeys [ j ] . toString ( 'hex' ) ] = 1 ;
}
}
var diff = [ ] ;
var diff = [ ] ;
for ( var j = 0 ; j < l ; j ++ ) {
for ( var j = 0 ; j < l ; j ++ ) {
var chunk = this . _ chunkSignedWithKey ( s1 , p2sh . txSigHash , pubkeys [ j ] ) ;
var chunk = this . _ chunkSignedWithKey ( s1 , p2sh . txSigHash , pubkeys [ j ] ) ;
var pubHex = pubkeys [ j ] . toString ( 'hex' ) ;
var pubHex = pubkeys [ j ] . toString ( 'hex' ) ;
if ( chunk && ! s0keys [ pubHex ] ) {
if ( chunk && ! s0keys [ pubHex ] ) {
@ -933,10 +946,10 @@ TransactionBuilder.prototype._mergeInputSigP2sh = function(input,s0,s1) {
}
}
// Add signatures
// Add signatures
for ( var j in diff ) {
for ( var j in diff ) {
var newSig = diff [ j ] ;
var newSig = diff [ j ] ;
var order = this . _ getNewSignatureOrder ( newSig . prio , s0 , p2sh . txSigHash , pubkeys ) ;
var order = this . _ getNewSignatureOrder ( newSig . prio , s0 , p2sh . txSigHash , pubkeys ) ;
s0 . chunks . splice ( order + 1 , 0 , newSig . chunk ) ;
s0 . chunks . splice ( order + 1 , 0 , newSig . chunk ) ;
this . signaturesAdded ++ ;
this . signaturesAdded ++ ;
}
}
s0 . updateBuffer ( ) ;
s0 . updateBuffer ( ) ;
@ -945,7 +958,7 @@ TransactionBuilder.prototype._mergeInputSigP2sh = function(input,s0,s1) {
// TODO this could be on Script class
// TODO this could be on Script class
TransactionBuilder . prototype . _ mergeInputSig = function ( index , s0buf , s1buf ) {
TransactionBuilder . prototype . _ mergeInputSig = function ( index , s0buf , s1buf ) {
if ( buffertools . compare ( s0buf , s1buf ) === 0 )
if ( buffertools . compare ( s0buf , s1buf ) === 0 )
return s0buf ;
return s0buf ;
var s0 = new Script ( s0buf ) ;
var s0 = new Script ( s0buf ) ;
@ -954,10 +967,10 @@ TransactionBuilder.prototype._mergeInputSig = function(index, s0buf, s1buf) {
var l1 = s1 . chunks . length ;
var l1 = s1 . chunks . length ;
var s0map = { } ;
var s0map = { } ;
if ( l0 && l1 && ( ( l0 < 2 && l1 > 2 ) || ( l1 < 2 && l0 > 2 ) ) )
if ( l0 && l1 && ( ( l0 < 2 && l1 > 2 ) || ( l1 < 2 && l0 > 2 ) ) )
throw new Error ( 'TX sig types mismatch in merge' ) ;
throw new Error ( 'TX sig types mismatch in merge' ) ;
if ( ( ! l0 && ! l1 ) || ( l0 && ! l1 ) || ( ! l0 && l1 ) )
if ( ( ! l0 && ! l1 ) || ( l0 && ! l1 ) || ( ! l0 && l1 ) )
return s1buf ;
return s1buf ;
// Get the pubkeys
// Get the pubkeys
@ -969,12 +982,11 @@ TransactionBuilder.prototype._mergeInputSig = function(index, s0buf, s1buf) {
log . debug ( 'Merging two signed inputs type:' +
log . debug ( 'Merging two signed inputs type:' +
input . scriptPubKey . getRawOutType ( ) + '. Signatures differs. Using the first version.' ) ;
input . scriptPubKey . getRawOutType ( ) + '. Signatures differs. Using the first version.' ) ;
return s0buf ;
return s0buf ;
}
} else if ( type !== Script . TX_SCRIPTHASH ) {
else if ( type !== Script . TX_SCRIPTHASH ) {
// No support for normal multisig or strange txs.
// No support for normal multisig or strange txs.
throw new Error ( 'Script type:' + input . scriptPubKey . getRawOutType ( ) + 'not supported at #merge' ) ;
throw new Error ( 'Script type:' + input . scriptPubKey . getRawOutType ( ) + 'not supported at #merge' ) ;
}
}
return this . _ mergeInputSigP2sh ( input , s0 , s1 ) ;
return this . _ mergeInputSigP2sh ( input , s0 , s1 ) ;
} ;
} ;
// TODO this could be on Transaction class
// TODO this could be on Transaction class
@ -986,18 +998,18 @@ TransactionBuilder.prototype._mergeTx = function(tx) {
if ( l !== v1 . ins . length )
if ( l !== v1 . ins . length )
throw new Error ( 'TX in length mismatch in merge' ) ;
throw new Error ( 'TX in length mismatch in merge' ) ;
this . inputsSigned = 0 ;
this . inputsSigned = 0 ;
for ( var i = 0 ; i < l ; i ++ ) {
for ( var i = 0 ; i < l ; i ++ ) {
var i0 = v0 . ins [ i ] ;
var i0 = v0 . ins [ i ] ;
var i1 = v1 . ins [ i ] ;
var i1 = v1 . ins [ i ] ;
if ( i0 . q !== i1 . q )
if ( i0 . q !== i1 . q )
throw new Error ( 'TX sequence ins mismatch in merge. Input:' , i ) ;
throw new Error ( 'TX sequence ins mismatch in merge. Input:' , i ) ;
if ( buffertools . compare ( i0 . o , i1 . o ) !== 0 )
if ( buffertools . compare ( i0 . o , i1 . o ) !== 0 )
throw new Error ( 'TX .o in mismatch in merge. Input:' , i ) ;
throw new Error ( 'TX .o in mismatch in merge. Input:' , i ) ;
i0 . s = this . _ mergeInputSig ( i , i0 . s , i1 . s ) ;
i0 . s = this . _ mergeInputSig ( i , i0 . s , i1 . s ) ;
if ( v0 . isInputComplete ( i ) ) this . inputsSigned ++ ;
if ( v0 . isInputComplete ( i ) ) this . inputsSigned ++ ;
}
}
@ -1013,8 +1025,7 @@ TransactionBuilder.prototype.merge = function(b) {
// Does this tX have any signature already?
// Does this tX have any signature already?
if ( this . tx || b . tx ) {
if ( this . tx || b . tx ) {
if ( this . tx . getNormalizedHash ( ) . toString ( 'hex' )
if ( this . tx . getNormalizedHash ( ) . toString ( 'hex' ) !== b . tx . getNormalizedHash ( ) . toString ( 'hex' ) )
!== b . tx . getNormalizedHash ( ) . toString ( 'hex' ) )
throw new Error ( 'mismatch at TransactionBuilder NTXID' ) ;
throw new Error ( 'mismatch at TransactionBuilder NTXID' ) ;
this . _ mergeTx ( b . tx ) ;
this . _ mergeTx ( b . tx ) ;