TransactionBuilder: simplify buildInput logic

This commit is contained in:
Daniel Cousens 2016-10-12 11:11:15 +11:00 committed by Daniel Cousens
parent 090b8177d1
commit f3cc71a75f

View file

@ -125,51 +125,40 @@ function expandOutput (script, scriptType, ourPubKey) {
} }
} }
function buildInput (input, scriptType, allowIncomplete) { function buildInput (input, allowIncomplete) {
var signatures = input.signatures var signatures = input.signatures
var scriptType = input.redeemScriptType || input.prevOutType
var scriptSig var scriptSig
switch (scriptType) { switch (scriptType) {
case 'pubkeyhash': case 'pubkeyhash':
// remove blank signatures
signatures = signatures.filter(function (x) { return x })
if (signatures.length < 1) throw new Error('Not enough signatures provided')
if (signatures.length > 1) throw new Error('Too many signatures provided')
var pkhSignature = signatures[0].toScriptSignature(input.hashType)
scriptSig = bscript.pubKeyHashInput(pkhSignature, input.pubKeys[0])
break
case 'pubkey': case 'pubkey':
// remove blank signatures if (signatures.length < 1 || !signatures[0]) throw new Error('Not enough signatures provided')
signatures = signatures.filter(function (x) { return x })
if (signatures.length < 1) throw new Error('Not enough signatures provided')
if (signatures.length > 1) throw new Error('Too many signatures provided')
var pkSignature = signatures[0].toScriptSignature(input.hashType) var pkSignature = signatures[0].toScriptSignature(input.hashType)
scriptSig = bscript.pubKeyInput(pkSignature) if (scriptType === 'pubkeyhash') {
scriptSig = bscript.pubKeyHashInput(pkSignature, input.pubKeys[0])
} else {
scriptSig = bscript.pubKeyInput(pkSignature)
}
break break
// ref https://github.com/bitcoin/bitcoin/blob/d612837814020ae832499d18e6ee5eb919a87907/src/script/sign.cpp#L232 // ref https://github.com/bitcoin/bitcoin/blob/d612837814020ae832499d18e6ee5eb919a87907/src/script/sign.cpp#L232
case 'multisig': case 'multisig':
signatures = signatures.map(function (signature) { signatures = signatures.map(function (signature) {
return signature && signature.toScriptSignature(input.hashType) return (signature && signature.toScriptSignature(input.hashType)) || ops.OP_0
}) })
if (allowIncomplete) { if (!allowIncomplete) {
// fill in blanks with OP_0
for (var i = 0; i < signatures.length; ++i) {
signatures[i] = signatures[i] || ops.OP_0
}
} else {
// remove blank signatures // remove blank signatures
signatures = signatures.filter(function (x) { return x }) signatures = signatures.filter(function (x) { return x !== ops.OP_0 })
} }
scriptSig = bscript.multisigInput(signatures, allowIncomplete ? undefined : input.redeemScript) scriptSig = bscript.multisigInput(signatures, allowIncomplete ? undefined : input.redeemScript)
break break
default: return
} }
// wrap as scriptHash if necessary // wrap as scriptHash if necessary
@ -207,13 +196,12 @@ function prepareInput (input, kpPubKey, redeemScript, hashType) {
input.redeemScriptType = expanded.scriptType input.redeemScriptType = expanded.scriptType
input.signatures = expanded.signatures input.signatures = expanded.signatures
// maybe we have some prior knowledge // maybe we have some prevOut knowledge
} else if (input.prevOutType) { } else if (input.prevOutType) {
// pay-to-scriptHash is not possible without a redeemScript // pay-to-scriptHash is not possible without a redeemScript
if (input.prevOutType === 'scripthash') throw new Error('PrevOutScript is P2SH, missing redeemScript') if (input.prevOutType === 'scripthash') throw new Error('PrevOutScript is P2SH, missing redeemScript')
// try to derive the missing information about the script now that we // try to derive missing information using our kpPubKey
// have a kpPubKey
expanded = expandOutput(input.prevOutScript, input.prevOutType, kpPubKey) expanded = expandOutput(input.prevOutScript, input.prevOutType, kpPubKey)
if (!expanded.pubKeys) return if (!expanded.pubKeys) return
@ -224,7 +212,6 @@ function prepareInput (input, kpPubKey, redeemScript, hashType) {
} else { } else {
input.prevOutScript = bscript.pubKeyHashOutput(bcrypto.hash160(kpPubKey)) input.prevOutScript = bscript.pubKeyHashOutput(bcrypto.hash160(kpPubKey))
input.prevOutType = 'pubkeyhash' input.prevOutType = 'pubkeyhash'
input.pubKeys = [kpPubKey] input.pubKeys = [kpPubKey]
input.signatures = [undefined] input.signatures = [undefined]
} }
@ -408,12 +395,6 @@ TransactionBuilder.prototype.buildIncomplete = function () {
return this.__build(true) return this.__build(true)
} }
var canBuildTypes = {
'multisig': true,
'pubkey': true,
'pubkeyhash': true
}
TransactionBuilder.prototype.__build = function (allowIncomplete) { TransactionBuilder.prototype.__build = function (allowIncomplete) {
if (!allowIncomplete) { if (!allowIncomplete) {
if (!this.tx.ins.length) throw new Error('Transaction has no inputs') if (!this.tx.ins.length) throw new Error('Transaction has no inputs')
@ -425,21 +406,17 @@ TransactionBuilder.prototype.__build = function (allowIncomplete) {
// Create script signatures from inputs // Create script signatures from inputs
this.inputs.forEach(function (input, i) { this.inputs.forEach(function (input, i) {
var scriptType = input.redeemScriptType || input.prevOutType var scriptType = input.redeemScriptType || input.prevOutType
if (!scriptType && !allowIncomplete) throw new Error('Transaction is not complete')
if (!allowIncomplete) {
if (!scriptType) throw new Error('Transaction is not complete')
if (!canBuildTypes[scriptType]) throw new Error(scriptType + ' not supported')
// FIXME: only relevant to types that need signatures
if (!input.signatures) throw new Error('Transaction is missing signatures')
}
// FIXME: only relevant to types that need signatures
// skip if no scriptSig exists
if (!input.signatures) return
// build a scriptSig // build a scriptSig
var scriptSig = buildInput(input, scriptType, allowIncomplete) var scriptSig = buildInput(input, allowIncomplete)
// skip if no scriptSig exists
if (!scriptSig) {
if (!allowIncomplete) throw new Error(scriptType + ' not supported')
return
}
tx.setInputScript(i, scriptSig) tx.setInputScript(i, scriptSig)
}) })