|
@ -1,9 +1,11 @@ |
|
|
/* global describe, it, beforeEach */ |
|
|
/* global describe, it, beforeEach */ |
|
|
|
|
|
|
|
|
var assert = require('assert') |
|
|
var assert = require('assert') |
|
|
|
|
|
var ops = require('../src/opcodes') |
|
|
|
|
|
var scripts = require('../src/scripts') |
|
|
|
|
|
|
|
|
var Address = require('../src/address') |
|
|
var Address = require('../src/address') |
|
|
var BigInteger = require('bigi') |
|
|
var BigInteger = require('bigi') |
|
|
var bitcoin = require('../src') |
|
|
|
|
|
var ECKey = require('../src/eckey') |
|
|
var ECKey = require('../src/eckey') |
|
|
var Script = require('../src/script') |
|
|
var Script = require('../src/script') |
|
|
var Transaction = require('../src/transaction') |
|
|
var Transaction = require('../src/transaction') |
|
@ -225,51 +227,44 @@ describe('TransactionBuilder', function () { |
|
|
describe('multisig', function () { |
|
|
describe('multisig', function () { |
|
|
fixtures.valid.multisig.forEach(function (f) { |
|
|
fixtures.valid.multisig.forEach(function (f) { |
|
|
it(f.description, function () { |
|
|
it(f.description, function () { |
|
|
var signs = 0 |
|
|
construct(txb, f, false) |
|
|
f.inputs.forEach(function (input) { |
|
|
|
|
|
txb.addInput(input.txId, input.vout) |
|
|
|
|
|
signs = Math.max(signs, input.signs.length) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
f.outputs.forEach(function (output) { |
|
|
|
|
|
txb.addOutput(Script.fromASM(output.script), output.value) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
var tx |
|
|
var tx |
|
|
|
|
|
|
|
|
for (var i = 0; i < signs; i++) { |
|
|
f.inputs.forEach(function (input, i) { |
|
|
if (tx) { |
|
|
var redeemScript = Script.fromASM(input.redeemScript) |
|
|
txb = TransactionBuilder.fromTransaction(tx) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
f.inputs.forEach(function (input, index) { |
|
|
input.signs.forEach(function (sign) { |
|
|
var privKey = bitcoin.ECKey.fromWIF(input.signs[i].privKey) |
|
|
// rebuild the transaction each-time after the first
|
|
|
var redeemScript = bitcoin.Script.fromASM(input.redeemScript) |
|
|
if (tx) { |
|
|
txb.sign(index, privKey, redeemScript) |
|
|
// do we filter OP_0's beforehand?
|
|
|
}) |
|
|
if (sign.filterOP_0) { |
|
|
|
|
|
var scriptSig = tx.ins[i].script |
|
|
tx = txb.buildIncomplete() |
|
|
|
|
|
|
|
|
// ignore OP_0 on the front, ignore redeemScript
|
|
|
|
|
|
var signatures = scriptSig.chunks.slice(1, -1).filter(function(x) { return x !== ops.OP_0 }) |
|
|
|
|
|
|
|
|
|
|
|
// rebuild/replace the scriptSig without them
|
|
|
|
|
|
var replacement = scripts.scriptHashInput(scripts.multisigInput(signatures), redeemScript) |
|
|
|
|
|
tx.ins[i].script = replacement |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// now import it
|
|
|
|
|
|
txb = TransactionBuilder.fromTransaction(tx) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
f.inputs.forEach(function (input, index) { |
|
|
var privKey = ECKey.fromWIF(sign.privKey) |
|
|
assert(bitcoin.scripts.isCanonicalSignature(tx.ins[index].script.chunks[input.signs[i].pubKeyIndex + 1])) |
|
|
txb.sign(i, privKey, redeemScript, sign.hashType) |
|
|
assert(tx.ins[index].script.chunks.slice(1, -1).every(function (chunk) { |
|
|
|
|
|
return chunk === bitcoin.opcodes.OP_0 || bitcoin.scripts.isCanonicalSignature(chunk) |
|
|
|
|
|
})) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
// manually mess up the signatures
|
|
|
// update the tx
|
|
|
f.inputs.forEach(function (input, index) { |
|
|
tx = txb.buildIncomplete() |
|
|
// remove all OP_0s
|
|
|
|
|
|
if (input.signs[i].removeOp0s) { |
|
|
|
|
|
tx.ins[index].script.chunks = tx.ins[index].script.chunks.filter(function (chunk) { |
|
|
|
|
|
return chunk !== bitcoin.opcodes.OP_0 |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
// we removed one OP_0 too many, gotta add it back
|
|
|
// now verify the serialized transaction is as expected
|
|
|
tx.ins[index].script.chunks.unshift(bitcoin.opcodes.OP_0) |
|
|
if (sign.txHexIncomplete) { |
|
|
|
|
|
assert.equal(txb.buildIncomplete(), sign.txHexIncomplete) |
|
|
} |
|
|
} |
|
|
}) |
|
|
}) |
|
|
} |
|
|
}) |
|
|
|
|
|
|
|
|
assert.equal(tx.toHex(), f.txHexIncomplete, 'txHexIncomplete') |
|
|
assert.equal(tx.toHex(), f.txHexIncomplete, 'txHexIncomplete') |
|
|
|
|
|
|
|
|