TransactionBuilder: simplify buildInput logic
This commit is contained in:
parent
090b8177d1
commit
f3cc71a75f
1 changed files with 25 additions and 48 deletions
|
@ -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)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue