TxBuilder: sign now signs inputs in known publicKey order
This commit is contained in:
parent
c29b233744
commit
dfe74fa0d2
2 changed files with 51 additions and 10 deletions
|
@ -33,10 +33,9 @@ function extractSignature(txIn) {
|
||||||
switch (scriptType) {
|
switch (scriptType) {
|
||||||
case 'pubkeyhash':
|
case 'pubkeyhash':
|
||||||
parsed = ECSignature.parseScriptSignature(scriptSig.chunks[0])
|
parsed = ECSignature.parseScriptSignature(scriptSig.chunks[0])
|
||||||
var pubKey = ECPubKey.fromBuffer(scriptSig.chunks[1])
|
|
||||||
|
|
||||||
hashType = parsed.hashType
|
hashType = parsed.hashType
|
||||||
pubKeys = [pubKey]
|
|
||||||
|
pubKeys = [ECPubKey.fromBuffer(scriptSig.chunks[1])]
|
||||||
signatures = [parsed.signature]
|
signatures = [parsed.signature]
|
||||||
|
|
||||||
break
|
break
|
||||||
|
@ -50,6 +49,10 @@ function extractSignature(txIn) {
|
||||||
pubKeys = []
|
pubKeys = []
|
||||||
signatures = parsed.map(function(p) { return p.signature })
|
signatures = parsed.map(function(p) { return p.signature })
|
||||||
|
|
||||||
|
if (redeemScript) {
|
||||||
|
pubKeys = redeemScript.chunks.slice(1, -2).map(ECPubKey.fromBuffer)
|
||||||
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'pubkey':
|
case 'pubkey':
|
||||||
|
@ -59,6 +62,10 @@ function extractSignature(txIn) {
|
||||||
pubKeys = []
|
pubKeys = []
|
||||||
signatures = [parsed.signature]
|
signatures = [parsed.signature]
|
||||||
|
|
||||||
|
if (redeemScript) {
|
||||||
|
pubKeys = [ECPubKey.fromBuffer(redeemScript.chunks[0])]
|
||||||
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -249,15 +256,26 @@ TransactionBuilder.prototype.sign = function(index, privKey, redeemScript, hashT
|
||||||
|
|
||||||
var input = this.signatures[index]
|
var input = this.signatures[index]
|
||||||
if (!input) {
|
if (!input) {
|
||||||
|
var pubKeys = []
|
||||||
|
|
||||||
|
if (redeemScript && scriptType === 'multisig') {
|
||||||
|
pubKeys = redeemScript.chunks.slice(1, -2).map(ECPubKey.fromBuffer)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
pubKeys.push(privKey.pub)
|
||||||
|
}
|
||||||
|
|
||||||
input = {
|
input = {
|
||||||
hashType: hashType,
|
hashType: hashType,
|
||||||
pubKeys: [],
|
pubKeys: pubKeys,
|
||||||
redeemScript: redeemScript,
|
redeemScript: redeemScript,
|
||||||
scriptType: scriptType,
|
scriptType: scriptType,
|
||||||
signatures: []
|
signatures: []
|
||||||
}
|
}
|
||||||
|
|
||||||
this.signatures[index] = input
|
this.signatures[index] = input
|
||||||
|
this.prevOutScripts[index] = prevOutScript
|
||||||
|
this.prevOutTypes[index] = prevOutType
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
assert.equal(scriptType, 'multisig', scriptType + ' doesn\'t support multiple signatures')
|
assert.equal(scriptType, 'multisig', scriptType + ' doesn\'t support multiple signatures')
|
||||||
|
@ -265,13 +283,15 @@ TransactionBuilder.prototype.sign = function(index, privKey, redeemScript, hashT
|
||||||
assert.deepEqual(input.redeemScript, redeemScript, 'Inconsistent redeemScript')
|
assert.deepEqual(input.redeemScript, redeemScript, 'Inconsistent redeemScript')
|
||||||
}
|
}
|
||||||
|
|
||||||
this.prevOutScripts[index] = prevOutScript
|
// enforce signing in order of public keys
|
||||||
this.prevOutTypes[index] = prevOutType
|
assert(input.pubKeys.some(function(pubKey, i) {
|
||||||
|
if (!privKey.pub.Q.equals(pubKey.Q)) return false // FIXME: could be better?
|
||||||
|
|
||||||
// TODO: order signatures for multisig, enforce m < n
|
assert(!input.signatures[i], 'Signature already exists')
|
||||||
var signature = privKey.sign(hash)
|
input.signatures[i] = privKey.sign(hash)
|
||||||
input.pubKeys.push(privKey.pub)
|
|
||||||
input.signatures.push(signature)
|
return true
|
||||||
|
}), 'privateKey cannot sign for this input')
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = TransactionBuilder
|
module.exports = TransactionBuilder
|
||||||
|
|
|
@ -184,6 +184,27 @@ describe('TransactionBuilder', function() {
|
||||||
}, /RedeemScript not supported \(nonstandard\)/)
|
}, /RedeemScript not supported \(nonstandard\)/)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('throws if signature already exists', function() {
|
||||||
|
var redeemScript = scripts.multisigOutput(1, [privKey.pub])
|
||||||
|
|
||||||
|
txb.addInput(prevTxHash, 0)
|
||||||
|
txb.sign(0, privKey, redeemScript)
|
||||||
|
|
||||||
|
assert.throws(function() {
|
||||||
|
txb.sign(0, privKey, redeemScript)
|
||||||
|
}, /Signature already exists/)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws if private key is unable to sign for that input', function() {
|
||||||
|
var redeemScript = scripts.multisigOutput(1, [privKey.pub])
|
||||||
|
|
||||||
|
txb.addInput(prevTxHash, 0)
|
||||||
|
|
||||||
|
assert.throws(function() {
|
||||||
|
txb.sign(0, ECKey.makeRandom(), redeemScript)
|
||||||
|
}, /privateKey cannot sign for this input/)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('build', function() {
|
describe('build', function() {
|
||||||
|
|
Loading…
Reference in a new issue