|
@ -11,7 +11,7 @@ const NETWORKS = require('../src/networks') |
|
|
|
|
|
|
|
|
const fixtures = require('./fixtures/transaction_builder') |
|
|
const fixtures = require('./fixtures/transaction_builder') |
|
|
|
|
|
|
|
|
function constructSign (f, txb) { |
|
|
function constructSign (f, txb, useOldSignArgs) { |
|
|
const network = NETWORKS[f.network] |
|
|
const network = NETWORKS[f.network] |
|
|
const stages = f.stages && f.stages.concat() |
|
|
const stages = f.stages && f.stages.concat() |
|
|
|
|
|
|
|
@ -21,21 +21,36 @@ function constructSign (f, txb) { |
|
|
const keyPair = ECPair.fromWIF(sign.keyPair, network) |
|
|
const keyPair = ECPair.fromWIF(sign.keyPair, network) |
|
|
let redeemScript |
|
|
let redeemScript |
|
|
let witnessScript |
|
|
let witnessScript |
|
|
let value |
|
|
let witnessValue |
|
|
|
|
|
|
|
|
if (sign.redeemScript) { |
|
|
if (sign.redeemScript) { |
|
|
redeemScript = bscript.fromASM(sign.redeemScript) |
|
|
redeemScript = bscript.fromASM(sign.redeemScript) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (sign.value) { |
|
|
if (sign.value) { |
|
|
value = sign.value |
|
|
witnessValue = sign.value |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (sign.witnessScript) { |
|
|
if (sign.witnessScript) { |
|
|
witnessScript = bscript.fromASM(sign.witnessScript) |
|
|
witnessScript = bscript.fromASM(sign.witnessScript) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
txb.sign(index, keyPair, redeemScript, sign.hashType, value, witnessScript) |
|
|
if (useOldSignArgs) { |
|
|
|
|
|
// DEPRECATED: v6 will remove this interface
|
|
|
|
|
|
txb.sign(index, keyPair, redeemScript, sign.hashType, witnessValue, witnessScript) |
|
|
|
|
|
} else { |
|
|
|
|
|
// prevOutScriptType is required, see /ts_src/transaction_builder.ts
|
|
|
|
|
|
// The PREVOUT_TYPES constant is a Set with all possible values.
|
|
|
|
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: sign.prevOutScriptType, |
|
|
|
|
|
vin: index, |
|
|
|
|
|
keyPair, |
|
|
|
|
|
redeemScript, |
|
|
|
|
|
hashType: sign.hashType, |
|
|
|
|
|
witnessValue, |
|
|
|
|
|
witnessScript, |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (sign.stage) { |
|
|
if (sign.stage) { |
|
|
const tx = txb.buildIncomplete() |
|
|
const tx = txb.buildIncomplete() |
|
@ -48,7 +63,7 @@ function constructSign (f, txb) { |
|
|
return txb |
|
|
return txb |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function construct (f, dontSign) { |
|
|
function construct (f, dontSign, useOldSignArgs) { |
|
|
const network = NETWORKS[f.network] |
|
|
const network = NETWORKS[f.network] |
|
|
const txb = new TransactionBuilder(network) |
|
|
const txb = new TransactionBuilder(network) |
|
|
|
|
|
|
|
@ -84,10 +99,20 @@ function construct (f, dontSign) { |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
|
if (dontSign) return txb |
|
|
if (dontSign) return txb |
|
|
return constructSign(f, txb) |
|
|
return constructSign(f, txb, useOldSignArgs) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
describe('TransactionBuilder', () => { |
|
|
// TODO: Remove loop in v6
|
|
|
|
|
|
for (const useOldSignArgs of [ false, true ]) { |
|
|
|
|
|
// Search for "useOldSignArgs"
|
|
|
|
|
|
// to find the second part of this console.warn replace
|
|
|
|
|
|
let consoleWarn; |
|
|
|
|
|
if (useOldSignArgs) { |
|
|
|
|
|
consoleWarn = console.warn; |
|
|
|
|
|
// Silence console.warn during these tests
|
|
|
|
|
|
console.warn = () => undefined; |
|
|
|
|
|
} |
|
|
|
|
|
describe(`TransactionBuilder: useOldSignArgs === ${useOldSignArgs}`, () => { |
|
|
// constants
|
|
|
// constants
|
|
|
const keyPair = ECPair.fromPrivateKey(Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex')) |
|
|
const keyPair = ECPair.fromPrivateKey(Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex')) |
|
|
const scripts = [ |
|
|
const scripts = [ |
|
@ -149,7 +174,7 @@ describe('TransactionBuilder', () => { |
|
|
assert.strictEqual(bscript.toASM(input.script), f.inputs[i].scriptSig) |
|
|
assert.strictEqual(bscript.toASM(input.script), f.inputs[i].scriptSig) |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
|
constructSign(f, txb) |
|
|
constructSign(f, txb, useOldSignArgs) |
|
|
const txAfter = f.incomplete ? txb.buildIncomplete() : txb.build() |
|
|
const txAfter = f.incomplete ? txb.buildIncomplete() : txb.build() |
|
|
|
|
|
|
|
|
txAfter.ins.forEach((input, i) => { |
|
|
txAfter.ins.forEach((input, i) => { |
|
@ -232,7 +257,11 @@ describe('TransactionBuilder', () => { |
|
|
it('throws if SIGHASH_ALL has been used to sign any existing scriptSigs', () => { |
|
|
it('throws if SIGHASH_ALL has been used to sign any existing scriptSigs', () => { |
|
|
txb.addInput(txHash, 0) |
|
|
txb.addInput(txHash, 0) |
|
|
txb.addOutput(scripts[0], 1000) |
|
|
txb.addOutput(scripts[0], 1000) |
|
|
txb.sign(0, keyPair) |
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2pkh', |
|
|
|
|
|
vin: 0, |
|
|
|
|
|
keyPair, |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
assert.throws(() => { |
|
|
assert.throws(() => { |
|
|
txb.addInput(txHash, 0) |
|
|
txb.addInput(txHash, 0) |
|
@ -274,26 +303,46 @@ describe('TransactionBuilder', () => { |
|
|
it('add second output after signed first input with SIGHASH_NONE', () => { |
|
|
it('add second output after signed first input with SIGHASH_NONE', () => { |
|
|
txb.addInput(txHash, 0) |
|
|
txb.addInput(txHash, 0) |
|
|
txb.addOutput(scripts[0], 2000) |
|
|
txb.addOutput(scripts[0], 2000) |
|
|
txb.sign(0, keyPair, undefined, Transaction.SIGHASH_NONE) |
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2pkh', |
|
|
|
|
|
vin: 0, |
|
|
|
|
|
keyPair, |
|
|
|
|
|
hashType: Transaction.SIGHASH_NONE, |
|
|
|
|
|
}) |
|
|
assert.strictEqual(txb.addOutput(scripts[1], 9000), 1) |
|
|
assert.strictEqual(txb.addOutput(scripts[1], 9000), 1) |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
|
it('add first output after signed first input with SIGHASH_NONE', () => { |
|
|
it('add first output after signed first input with SIGHASH_NONE', () => { |
|
|
txb.addInput(txHash, 0) |
|
|
txb.addInput(txHash, 0) |
|
|
txb.sign(0, keyPair, undefined, Transaction.SIGHASH_NONE) |
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2pkh', |
|
|
|
|
|
vin: 0, |
|
|
|
|
|
keyPair, |
|
|
|
|
|
hashType: Transaction.SIGHASH_NONE, |
|
|
|
|
|
}) |
|
|
assert.strictEqual(txb.addOutput(scripts[0], 2000), 0) |
|
|
assert.strictEqual(txb.addOutput(scripts[0], 2000), 0) |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
|
it('add second output after signed first input with SIGHASH_SINGLE', () => { |
|
|
it('add second output after signed first input with SIGHASH_SINGLE', () => { |
|
|
txb.addInput(txHash, 0) |
|
|
txb.addInput(txHash, 0) |
|
|
txb.addOutput(scripts[0], 2000) |
|
|
txb.addOutput(scripts[0], 2000) |
|
|
txb.sign(0, keyPair, undefined, Transaction.SIGHASH_SINGLE) |
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2pkh', |
|
|
|
|
|
vin: 0, |
|
|
|
|
|
keyPair, |
|
|
|
|
|
hashType: Transaction.SIGHASH_SINGLE, |
|
|
|
|
|
}) |
|
|
assert.strictEqual(txb.addOutput(scripts[1], 9000), 1) |
|
|
assert.strictEqual(txb.addOutput(scripts[1], 9000), 1) |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
|
it('add first output after signed first input with SIGHASH_SINGLE', () => { |
|
|
it('add first output after signed first input with SIGHASH_SINGLE', () => { |
|
|
txb.addInput(txHash, 0) |
|
|
txb.addInput(txHash, 0) |
|
|
txb.sign(0, keyPair, undefined, Transaction.SIGHASH_SINGLE) |
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2pkh', |
|
|
|
|
|
vin: 0, |
|
|
|
|
|
keyPair, |
|
|
|
|
|
hashType: Transaction.SIGHASH_SINGLE, |
|
|
|
|
|
}) |
|
|
assert.throws(() => { |
|
|
assert.throws(() => { |
|
|
txb.addOutput(scripts[0], 2000) |
|
|
txb.addOutput(scripts[0], 2000) |
|
|
}, /No, this would invalidate signatures/) |
|
|
}, /No, this would invalidate signatures/) |
|
@ -302,7 +351,11 @@ describe('TransactionBuilder', () => { |
|
|
it('throws if SIGHASH_ALL has been used to sign any existing scriptSigs', () => { |
|
|
it('throws if SIGHASH_ALL has been used to sign any existing scriptSigs', () => { |
|
|
txb.addInput(txHash, 0) |
|
|
txb.addInput(txHash, 0) |
|
|
txb.addOutput(scripts[0], 2000) |
|
|
txb.addOutput(scripts[0], 2000) |
|
|
txb.sign(0, keyPair) |
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2pkh', |
|
|
|
|
|
vin: 0, |
|
|
|
|
|
keyPair, |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
assert.throws(() => { |
|
|
assert.throws(() => { |
|
|
txb.addOutput(scripts[1], 9000) |
|
|
txb.addOutput(scripts[1], 9000) |
|
@ -315,7 +368,11 @@ describe('TransactionBuilder', () => { |
|
|
const txb = new TransactionBuilder() |
|
|
const txb = new TransactionBuilder() |
|
|
txb.addInput(txHash, 0) |
|
|
txb.addInput(txHash, 0) |
|
|
txb.addOutput(scripts[0], 100) |
|
|
txb.addOutput(scripts[0], 100) |
|
|
txb.sign(0, keyPair) |
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2pkh', |
|
|
|
|
|
vin: 0, |
|
|
|
|
|
keyPair, |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
assert.throws(() => { |
|
|
assert.throws(() => { |
|
|
txb.setLockTime(65535) |
|
|
txb.setLockTime(65535) |
|
@ -334,7 +391,11 @@ describe('TransactionBuilder', () => { |
|
|
txb.setVersion(1) |
|
|
txb.setVersion(1) |
|
|
txb.addInput('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 1) |
|
|
txb.addInput('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 1) |
|
|
txb.addOutput('1111111111111111111114oLvT2', 100000) |
|
|
txb.addOutput('1111111111111111111114oLvT2', 100000) |
|
|
txb.sign(0, keyPair) |
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2pkh', |
|
|
|
|
|
vin: 0, |
|
|
|
|
|
keyPair, |
|
|
|
|
|
}) |
|
|
assert.strictEqual(txb.build().toHex(), '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010000006a47304402205f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f02205f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f0121031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078fffffffff01a0860100000000001976a914000000000000000000000000000000000000000088ac00000000') |
|
|
assert.strictEqual(txb.build().toHex(), '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010000006a47304402205f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f02205f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f0121031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078fffffffff01a0860100000000001976a914000000000000000000000000000000000000000088ac00000000') |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
@ -343,7 +404,11 @@ describe('TransactionBuilder', () => { |
|
|
txb.setVersion(1) |
|
|
txb.setVersion(1) |
|
|
txb.addInput('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 1) |
|
|
txb.addInput('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 1) |
|
|
txb.addOutput('1111111111111111111114oLvT2', 100000) |
|
|
txb.addOutput('1111111111111111111114oLvT2', 100000) |
|
|
txb.sign(0, keyPair) |
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2pkh', |
|
|
|
|
|
vin: 0, |
|
|
|
|
|
keyPair, |
|
|
|
|
|
}) |
|
|
// high R
|
|
|
// high R
|
|
|
assert.strictEqual(txb.build().toHex(), '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010000006b483045022100b872677f35c9c14ad9c41d83649fb049250f32574e0b2547d67e209ed14ff05d022059b36ad058be54e887a1a311d5c393cb4941f6b93a0b090845ec67094de8972b01210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff01a0860100000000001976a914000000000000000000000000000000000000000088ac00000000') |
|
|
assert.strictEqual(txb.build().toHex(), '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010000006b483045022100b872677f35c9c14ad9c41d83649fb049250f32574e0b2547d67e209ed14ff05d022059b36ad058be54e887a1a311d5c393cb4941f6b93a0b090845ec67094de8972b01210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff01a0860100000000001976a914000000000000000000000000000000000000000088ac00000000') |
|
|
|
|
|
|
|
@ -352,11 +417,58 @@ describe('TransactionBuilder', () => { |
|
|
txb.addInput('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 1) |
|
|
txb.addInput('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 1) |
|
|
txb.addOutput('1111111111111111111114oLvT2', 100000) |
|
|
txb.addOutput('1111111111111111111114oLvT2', 100000) |
|
|
txb.setLowR() |
|
|
txb.setLowR() |
|
|
txb.sign(0, keyPair) |
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2pkh', |
|
|
|
|
|
vin: 0, |
|
|
|
|
|
keyPair, |
|
|
|
|
|
}) |
|
|
// low R
|
|
|
// low R
|
|
|
assert.strictEqual(txb.build().toHex(), '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010000006a473044022012a601efa8756ebe83e9ac7a7db061c3147e3b49d8be67685799fe51a4c8c62f02204d568d301d5ce14af390d566d4fd50e7b8ee48e71ec67786c029e721194dae3601210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff01a0860100000000001976a914000000000000000000000000000000000000000088ac00000000') |
|
|
assert.strictEqual(txb.build().toHex(), '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010000006a473044022012a601efa8756ebe83e9ac7a7db061c3147e3b49d8be67685799fe51a4c8c62f02204d568d301d5ce14af390d566d4fd50e7b8ee48e71ec67786c029e721194dae3601210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff01a0860100000000001976a914000000000000000000000000000000000000000088ac00000000') |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
it('fails when missing required arguments', () => { |
|
|
|
|
|
let txb = new TransactionBuilder() |
|
|
|
|
|
txb.setVersion(1) |
|
|
|
|
|
txb.addInput('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 1) |
|
|
|
|
|
txb.addOutput('1111111111111111111114oLvT2', 100000) |
|
|
|
|
|
assert.throws(() => { |
|
|
|
|
|
txb.sign() |
|
|
|
|
|
}, /TransactionBuilder sign first arg must be TxbSignArg or number/) |
|
|
|
|
|
assert.throws(() => { |
|
|
|
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2pkh', |
|
|
|
|
|
vin: 1, |
|
|
|
|
|
keyPair, |
|
|
|
|
|
}) |
|
|
|
|
|
}, /No input at index: 1/) |
|
|
|
|
|
assert.throws(() => { |
|
|
|
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2pkh', |
|
|
|
|
|
keyPair, |
|
|
|
|
|
}) |
|
|
|
|
|
}, /sign must include vin parameter as Number \(input index\)/) |
|
|
|
|
|
assert.throws(() => { |
|
|
|
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2pkh', |
|
|
|
|
|
vin: 0, |
|
|
|
|
|
keyPair: {}, |
|
|
|
|
|
}) |
|
|
|
|
|
}, /sign must include keyPair parameter as Signer interface/) |
|
|
|
|
|
assert.throws(() => { |
|
|
|
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2pkh', |
|
|
|
|
|
vin: 0, |
|
|
|
|
|
keyPair, |
|
|
|
|
|
hashType: 'string', |
|
|
|
|
|
}) |
|
|
|
|
|
}, /sign hashType parameter must be a number/) |
|
|
|
|
|
if (useOldSignArgs) { |
|
|
|
|
|
assert.throws(() => { |
|
|
|
|
|
txb.sign(0) |
|
|
|
|
|
}, /sign requires keypair/) |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
fixtures.invalid.sign.forEach(f => { |
|
|
fixtures.invalid.sign.forEach(f => { |
|
|
it('throws ' + f.exception + (f.description ? ' (' + f.description + ')' : ''), () => { |
|
|
it('throws ' + f.exception + (f.description ? ' (' + f.description + ')' : ''), () => { |
|
|
const txb = construct(f, true) |
|
|
const txb = construct(f, true) |
|
@ -379,11 +491,27 @@ describe('TransactionBuilder', () => { |
|
|
|
|
|
|
|
|
if (sign.throws) { |
|
|
if (sign.throws) { |
|
|
assert.throws(() => { |
|
|
assert.throws(() => { |
|
|
txb.sign(index, keyPair2, redeemScript, sign.hashType, sign.value, witnessScript) |
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: sign.prevOutScriptType, |
|
|
|
|
|
vin: index, |
|
|
|
|
|
keyPair: keyPair2, |
|
|
|
|
|
redeemScript, |
|
|
|
|
|
hashType: sign.hashType, |
|
|
|
|
|
witnessValue: sign.value, |
|
|
|
|
|
witnessScript, |
|
|
|
|
|
}) |
|
|
}, new RegExp(f.exception)) |
|
|
}, new RegExp(f.exception)) |
|
|
threw = true |
|
|
threw = true |
|
|
} else { |
|
|
} else { |
|
|
txb.sign(index, keyPair2, redeemScript, sign.hashType, sign.value, witnessScript) |
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: sign.prevOutScriptType, |
|
|
|
|
|
vin: index, |
|
|
|
|
|
keyPair: keyPair2, |
|
|
|
|
|
redeemScript, |
|
|
|
|
|
hashType: sign.hashType, |
|
|
|
|
|
witnessValue: sign.value, |
|
|
|
|
|
witnessScript, |
|
|
|
|
|
}) |
|
|
} |
|
|
} |
|
|
}) |
|
|
}) |
|
|
}) |
|
|
}) |
|
@ -396,7 +524,7 @@ describe('TransactionBuilder', () => { |
|
|
describe('build', () => { |
|
|
describe('build', () => { |
|
|
fixtures.valid.build.forEach(f => { |
|
|
fixtures.valid.build.forEach(f => { |
|
|
it('builds "' + f.description + '"', () => { |
|
|
it('builds "' + f.description + '"', () => { |
|
|
const txb = construct(f) |
|
|
const txb = construct(f, undefined, useOldSignArgs) |
|
|
const tx = f.incomplete ? txb.buildIncomplete() : txb.build() |
|
|
const tx = f.incomplete ? txb.buildIncomplete() : txb.build() |
|
|
|
|
|
|
|
|
assert.strictEqual(tx.toHex(), f.txHex) |
|
|
assert.strictEqual(tx.toHex(), f.txHex) |
|
@ -412,7 +540,7 @@ describe('TransactionBuilder', () => { |
|
|
if (f.txHex) { |
|
|
if (f.txHex) { |
|
|
txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex)) |
|
|
txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex)) |
|
|
} else { |
|
|
} else { |
|
|
txb = construct(f) |
|
|
txb = construct(f, undefined, useOldSignArgs) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
txb.build() |
|
|
txb.build() |
|
@ -427,7 +555,7 @@ describe('TransactionBuilder', () => { |
|
|
if (f.txHex) { |
|
|
if (f.txHex) { |
|
|
txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex)) |
|
|
txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex)) |
|
|
} else { |
|
|
} else { |
|
|
txb = construct(f) |
|
|
txb = construct(f, undefined, useOldSignArgs) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
txb.buildIncomplete() |
|
|
txb.buildIncomplete() |
|
@ -439,7 +567,7 @@ describe('TransactionBuilder', () => { |
|
|
if (f.txHex) { |
|
|
if (f.txHex) { |
|
|
txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex)) |
|
|
txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex)) |
|
|
} else { |
|
|
} else { |
|
|
txb = construct(f) |
|
|
txb = construct(f, undefined, useOldSignArgs) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
txb.buildIncomplete() |
|
|
txb.buildIncomplete() |
|
@ -516,7 +644,13 @@ describe('TransactionBuilder', () => { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const keyPair2 = ECPair.fromWIF(sign.keyPair, network) |
|
|
const keyPair2 = ECPair.fromWIF(sign.keyPair, network) |
|
|
txb.sign(i, keyPair2, redeemScript, sign.hashType) |
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: sign.prevOutScriptType, |
|
|
|
|
|
vin: i, |
|
|
|
|
|
keyPair: keyPair2, |
|
|
|
|
|
redeemScript, |
|
|
|
|
|
hashType: sign.hashType, |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
// update the tx
|
|
|
// update the tx
|
|
|
tx = txb.buildIncomplete() |
|
|
tx = txb.buildIncomplete() |
|
@ -571,7 +705,14 @@ describe('TransactionBuilder', () => { |
|
|
txb.setVersion(1) |
|
|
txb.setVersion(1) |
|
|
txb.addInput('a4696c4b0cd27ec2e173ab1fa7d1cc639a98ee237cec95a77ca7ff4145791529', 1, 0xffffffff, scriptPubKey) |
|
|
txb.addInput('a4696c4b0cd27ec2e173ab1fa7d1cc639a98ee237cec95a77ca7ff4145791529', 1, 0xffffffff, scriptPubKey) |
|
|
txb.addOutput(scriptPubKey, 99000) |
|
|
txb.addOutput(scriptPubKey, 99000) |
|
|
txb.sign(0, keyPair, redeemScript, null, 100000, witnessScript) |
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2sh-p2wsh-p2ms', |
|
|
|
|
|
vin: 0, |
|
|
|
|
|
keyPair, |
|
|
|
|
|
redeemScript, |
|
|
|
|
|
witnessValue: 100000, |
|
|
|
|
|
witnessScript, |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
// 2-of-2 signed only once
|
|
|
// 2-of-2 signed only once
|
|
|
const tx = txb.buildIncomplete() |
|
|
const tx = txb.buildIncomplete() |
|
@ -596,7 +737,12 @@ describe('TransactionBuilder', () => { |
|
|
const txb = TransactionBuilder.fromTransaction(tx, NETWORKS.testnet) |
|
|
const txb = TransactionBuilder.fromTransaction(tx, NETWORKS.testnet) |
|
|
|
|
|
|
|
|
const keyPair2 = ECPair.fromWIF('91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe', network) |
|
|
const keyPair2 = ECPair.fromWIF('91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe', network) |
|
|
txb.sign(0, keyPair2, redeemScript) |
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2sh-p2ms', |
|
|
|
|
|
vin: 0, |
|
|
|
|
|
keyPair: keyPair2, |
|
|
|
|
|
redeemScript, |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
const tx2 = txb.build() |
|
|
const tx2 = txb.build() |
|
|
assert.strictEqual(tx2.getId(), 'eab59618a564e361adef6d918bd792903c3d41bcf1220137364fb847880467f9') |
|
|
assert.strictEqual(tx2.getId(), 'eab59618a564e361adef6d918bd792903c3d41bcf1220137364fb847880467f9') |
|
@ -613,16 +759,29 @@ describe('TransactionBuilder', () => { |
|
|
|
|
|
|
|
|
// sign, as expected
|
|
|
// sign, as expected
|
|
|
txb.addOutput('1Gokm82v6DmtwKEB8AiVhm82hyFSsEvBDK', 15000) |
|
|
txb.addOutput('1Gokm82v6DmtwKEB8AiVhm82hyFSsEvBDK', 15000) |
|
|
txb.sign(0, keyPair) |
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2pkh', |
|
|
|
|
|
vin: 0, |
|
|
|
|
|
keyPair, |
|
|
|
|
|
}) |
|
|
const txId = txb.build().getId() |
|
|
const txId = txb.build().getId() |
|
|
assert.strictEqual(txId, '54f097315acbaedb92a95455da3368eb45981cdae5ffbc387a9afc872c0f29b3') |
|
|
assert.strictEqual(txId, '54f097315acbaedb92a95455da3368eb45981cdae5ffbc387a9afc872c0f29b3') |
|
|
|
|
|
|
|
|
// and, repeat
|
|
|
// and, repeat
|
|
|
txb = TransactionBuilder.fromTransaction(Transaction.fromHex(incomplete)) |
|
|
txb = TransactionBuilder.fromTransaction(Transaction.fromHex(incomplete)) |
|
|
txb.addOutput('1Gokm82v6DmtwKEB8AiVhm82hyFSsEvBDK', 15000) |
|
|
txb.addOutput('1Gokm82v6DmtwKEB8AiVhm82hyFSsEvBDK', 15000) |
|
|
txb.sign(0, keyPair) |
|
|
txb.sign({ |
|
|
|
|
|
prevOutScriptType: 'p2pkh', |
|
|
|
|
|
vin: 0, |
|
|
|
|
|
keyPair, |
|
|
|
|
|
}) |
|
|
const txId2 = txb.build().getId() |
|
|
const txId2 = txb.build().getId() |
|
|
assert.strictEqual(txId, txId2) |
|
|
assert.strictEqual(txId, txId2) |
|
|
|
|
|
// TODO: Remove me in v6
|
|
|
|
|
|
if (useOldSignArgs) { |
|
|
|
|
|
console.warn = consoleWarn; |
|
|
|
|
|
} |
|
|
}) |
|
|
}) |
|
|
}) |
|
|
}) |
|
|
}) |
|
|
}) |
|
|
|
|
|
} |
|
|