|
|
@ -43,7 +43,7 @@ describe('bitcoinjs-lib (transactions)', function () { |
|
|
|
assert.strictEqual(txb.build().toHex(), '01000000024c94e48a870b85f41228d33cf25213dfcc8dd796e7211ed6b1f9a014809dbbb5060000006a473044022041450c258ce7cac7da97316bf2ea1ce66d88967c4df94f3e91f4c2a30f5d08cb02203674d516e6bb2b0afd084c3551614bd9cec3c2945231245e891b145f2d6951f0012103e05ce435e462ec503143305feb6c00e06a3ad52fbf939e85c65f3a765bb7baacffffffff3077d9de049574c3af9bc9c09a7c9db80f2d94caaf63988c9166249b955e867d000000006b483045022100aeb5f1332c79c446d3f906e4499b2e678500580a3f90329edf1ba502eec9402e022072c8b863f8c8d6c26f4c691ac9a6610aa4200edc697306648ee844cfbc089d7a012103df7940ee7cddd2f97763f67e1fb13488da3fbdd7f9c68ec5ef0864074745a289ffffffff0220bf0200000000001976a9147dd65592d0ab2fe0d0257d571abf032cd9db93dc88ac10980200000000001976a914c42e7ef92fdb603af844d064faad95db9bcdfd3d88ac00000000') |
|
|
|
}) |
|
|
|
|
|
|
|
it('can create (and broadcast via 3PBP) a typical Transaction', function (done) { |
|
|
|
it('can create (and broadcast via 3PBP) a typical Transaction', async () => { |
|
|
|
const alice1 = bitcoin.ECPair.makeRandom({ network: regtest }) |
|
|
|
const alice2 = bitcoin.ECPair.makeRandom({ network: regtest }) |
|
|
|
const aliceChange = bitcoin.ECPair.makeRandom({ network: regtest, rng: rng }) |
|
|
@ -53,51 +53,45 @@ describe('bitcoinjs-lib (transactions)', function () { |
|
|
|
const aliceCpkh = bitcoin.payments.p2pkh({ pubkey: aliceChange.publicKey, network: regtest }) |
|
|
|
|
|
|
|
// give Alice 2 unspent outputs
|
|
|
|
regtestUtils.faucet(alice1pkh.address, 5e4, function (err, unspent0) { |
|
|
|
if (err) return done(err) |
|
|
|
|
|
|
|
regtestUtils.faucet(alice2pkh.address, 7e4, function (err, unspent1) { |
|
|
|
if (err) return done(err) |
|
|
|
|
|
|
|
const txb = new bitcoin.TransactionBuilder(regtest) |
|
|
|
txb.addInput(unspent0.txId, unspent0.vout) // alice1 unspent
|
|
|
|
txb.addInput(unspent1.txId, unspent1.vout) // alice2 unspent
|
|
|
|
txb.addOutput('mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf', 8e4) // the actual "spend"
|
|
|
|
txb.addOutput(aliceCpkh.address, 1e4) // Alice's change
|
|
|
|
// (in)(5e4 + 7e4) - (out)(8e4 + 1e4) = (fee)3e4 = 30000, this is the miner fee
|
|
|
|
|
|
|
|
// Alice signs each input with the respective private keys
|
|
|
|
txb.sign(0, alice1) |
|
|
|
txb.sign(1, alice2) |
|
|
|
|
|
|
|
// build and broadcast our RegTest network
|
|
|
|
regtestUtils.broadcast(txb.build().toHex(), done) |
|
|
|
// to build and broadcast to the actual Bitcoin network, see https://github.com/bitcoinjs/bitcoinjs-lib/issues/839
|
|
|
|
}) |
|
|
|
}) |
|
|
|
const unspent0 = await regtestUtils.faucet(alice1pkh.address, 5e4) |
|
|
|
|
|
|
|
const unspent1 = await regtestUtils.faucet(alice2pkh.address, 7e4) |
|
|
|
|
|
|
|
const txb = new bitcoin.TransactionBuilder(regtest) |
|
|
|
txb.addInput(unspent0.txId, unspent0.vout) // alice1 unspent
|
|
|
|
txb.addInput(unspent1.txId, unspent1.vout) // alice2 unspent
|
|
|
|
txb.addOutput('mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf', 8e4) // the actual "spend"
|
|
|
|
txb.addOutput(aliceCpkh.address, 1e4) // Alice's change
|
|
|
|
// (in)(5e4 + 7e4) - (out)(8e4 + 1e4) = (fee)3e4 = 30000, this is the miner fee
|
|
|
|
|
|
|
|
// Alice signs each input with the respective private keys
|
|
|
|
txb.sign(0, alice1) |
|
|
|
txb.sign(1, alice2) |
|
|
|
|
|
|
|
// build and broadcast our RegTest network
|
|
|
|
await regtestUtils.broadcast(txb.build().toHex()) |
|
|
|
// to build and broadcast to the actual Bitcoin network, see https://github.com/bitcoinjs/bitcoinjs-lib/issues/839
|
|
|
|
}) |
|
|
|
|
|
|
|
it('can create (and broadcast via 3PBP) a Transaction with an OP_RETURN output', function (done) { |
|
|
|
it('can create (and broadcast via 3PBP) a Transaction with an OP_RETURN output', async () => { |
|
|
|
const keyPair = bitcoin.ECPair.makeRandom({ network: regtest }) |
|
|
|
const p2pkh = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey, network: regtest }) |
|
|
|
|
|
|
|
regtestUtils.faucet(p2pkh.address, 2e5, function (err, unspent) { |
|
|
|
if (err) return done(err) |
|
|
|
const unspent = await regtestUtils.faucet(p2pkh.address, 2e5) |
|
|
|
|
|
|
|
const txb = new bitcoin.TransactionBuilder(regtest) |
|
|
|
const data = Buffer.from('bitcoinjs-lib', 'utf8') |
|
|
|
const embed = bitcoin.payments.embed({ data: [data] }) |
|
|
|
txb.addInput(unspent.txId, unspent.vout) |
|
|
|
txb.addOutput(embed.output, 1000) |
|
|
|
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e5) |
|
|
|
txb.sign(0, keyPair) |
|
|
|
const txb = new bitcoin.TransactionBuilder(regtest) |
|
|
|
const data = Buffer.from('bitcoinjs-lib', 'utf8') |
|
|
|
const embed = bitcoin.payments.embed({ data: [data] }) |
|
|
|
txb.addInput(unspent.txId, unspent.vout) |
|
|
|
txb.addOutput(embed.output, 1000) |
|
|
|
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e5) |
|
|
|
txb.sign(0, keyPair) |
|
|
|
|
|
|
|
// build and broadcast to the RegTest network
|
|
|
|
regtestUtils.broadcast(txb.build().toHex(), done) |
|
|
|
}) |
|
|
|
// build and broadcast to the RegTest network
|
|
|
|
await regtestUtils.broadcast(txb.build().toHex()) |
|
|
|
}) |
|
|
|
|
|
|
|
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2MS(2 of 4)) (multisig) input', function (done) { |
|
|
|
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2MS(2 of 4)) (multisig) input', async () => { |
|
|
|
const keyPairs = [ |
|
|
|
bitcoin.ECPair.makeRandom({ network: regtest }), |
|
|
|
bitcoin.ECPair.makeRandom({ network: regtest }), |
|
|
@ -108,118 +102,102 @@ describe('bitcoinjs-lib (transactions)', function () { |
|
|
|
const p2ms = bitcoin.payments.p2ms({ m: 2, pubkeys: pubkeys, network: regtest }) |
|
|
|
const p2sh = bitcoin.payments.p2sh({ redeem: p2ms, network: regtest }) |
|
|
|
|
|
|
|
regtestUtils.faucet(p2sh.address, 2e4, function (err, unspent) { |
|
|
|
if (err) return done(err) |
|
|
|
const unspent = await regtestUtils.faucet(p2sh.address, 2e4) |
|
|
|
|
|
|
|
const txb = new bitcoin.TransactionBuilder(regtest) |
|
|
|
txb.addInput(unspent.txId, unspent.vout) |
|
|
|
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e4) |
|
|
|
const txb = new bitcoin.TransactionBuilder(regtest) |
|
|
|
txb.addInput(unspent.txId, unspent.vout) |
|
|
|
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e4) |
|
|
|
|
|
|
|
txb.sign(0, keyPairs[0], p2sh.redeem.output) |
|
|
|
txb.sign(0, keyPairs[2], p2sh.redeem.output) |
|
|
|
const tx = txb.build() |
|
|
|
txb.sign(0, keyPairs[0], p2sh.redeem.output) |
|
|
|
txb.sign(0, keyPairs[2], p2sh.redeem.output) |
|
|
|
const tx = txb.build() |
|
|
|
|
|
|
|
// build and broadcast to the Bitcoin RegTest network
|
|
|
|
regtestUtils.broadcast(tx.toHex(), function (err) { |
|
|
|
if (err) return done(err) |
|
|
|
// build and broadcast to the Bitcoin RegTest network
|
|
|
|
await regtestUtils.broadcast(tx.toHex()) |
|
|
|
|
|
|
|
regtestUtils.verify({ |
|
|
|
txId: tx.getId(), |
|
|
|
address: regtestUtils.RANDOM_ADDRESS, |
|
|
|
vout: 0, |
|
|
|
value: 1e4 |
|
|
|
}, done) |
|
|
|
}) |
|
|
|
await regtestUtils.verify({ |
|
|
|
txId: tx.getId(), |
|
|
|
address: regtestUtils.RANDOM_ADDRESS, |
|
|
|
vout: 0, |
|
|
|
value: 1e4 |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WPKH) input', function (done) { |
|
|
|
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WPKH) input', async () => { |
|
|
|
const keyPair = bitcoin.ECPair.makeRandom({ network: regtest }) |
|
|
|
const p2wpkh = bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey, network: regtest }) |
|
|
|
const p2sh = bitcoin.payments.p2sh({ redeem: p2wpkh, network: regtest }) |
|
|
|
|
|
|
|
regtestUtils.faucet(p2sh.address, 5e4, function (err, unspent) { |
|
|
|
if (err) return done(err) |
|
|
|
const unspent = await regtestUtils.faucet(p2sh.address, 5e4) |
|
|
|
|
|
|
|
const txb = new bitcoin.TransactionBuilder(regtest) |
|
|
|
txb.addInput(unspent.txId, unspent.vout) |
|
|
|
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4) |
|
|
|
txb.sign(0, keyPair, p2sh.redeem.output, null, unspent.value) |
|
|
|
const txb = new bitcoin.TransactionBuilder(regtest) |
|
|
|
txb.addInput(unspent.txId, unspent.vout) |
|
|
|
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4) |
|
|
|
txb.sign(0, keyPair, p2sh.redeem.output, null, unspent.value) |
|
|
|
|
|
|
|
const tx = txb.build() |
|
|
|
const tx = txb.build() |
|
|
|
|
|
|
|
// build and broadcast to the Bitcoin RegTest network
|
|
|
|
regtestUtils.broadcast(tx.toHex(), function (err) { |
|
|
|
if (err) return done(err) |
|
|
|
// build and broadcast to the Bitcoin RegTest network
|
|
|
|
await regtestUtils.broadcast(tx.toHex()) |
|
|
|
|
|
|
|
regtestUtils.verify({ |
|
|
|
txId: tx.getId(), |
|
|
|
address: regtestUtils.RANDOM_ADDRESS, |
|
|
|
vout: 0, |
|
|
|
value: 2e4 |
|
|
|
}, done) |
|
|
|
}) |
|
|
|
await regtestUtils.verify({ |
|
|
|
txId: tx.getId(), |
|
|
|
address: regtestUtils.RANDOM_ADDRESS, |
|
|
|
vout: 0, |
|
|
|
value: 2e4 |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WPKH input', function (done) { |
|
|
|
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WPKH input', async () => { |
|
|
|
const keyPair = bitcoin.ECPair.makeRandom({ network: regtest }) |
|
|
|
const p2wpkh = bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey, network: regtest }) |
|
|
|
|
|
|
|
regtestUtils.faucetComplex(p2wpkh.address, 5e4, function (err, unspent) { |
|
|
|
if (err) return done(err) |
|
|
|
|
|
|
|
// XXX: build the Transaction w/ a P2WPKH input
|
|
|
|
const txb = new bitcoin.TransactionBuilder(regtest) |
|
|
|
txb.addInput(unspent.txId, unspent.vout, null, p2wpkh.output) // NOTE: provide the prevOutScript!
|
|
|
|
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4) |
|
|
|
txb.sign(0, keyPair, null, null, unspent.value) // NOTE: no redeem script
|
|
|
|
const tx = txb.build() |
|
|
|
|
|
|
|
// build and broadcast (the P2WPKH transaction) to the Bitcoin RegTest network
|
|
|
|
regtestUtils.broadcast(tx.toHex(), function (err) { |
|
|
|
if (err) return done(err) |
|
|
|
|
|
|
|
regtestUtils.verify({ |
|
|
|
txId: tx.getId(), |
|
|
|
address: regtestUtils.RANDOM_ADDRESS, |
|
|
|
vout: 0, |
|
|
|
value: 2e4 |
|
|
|
}, done) |
|
|
|
}) |
|
|
|
const unspent = await regtestUtils.faucetComplex(p2wpkh.address, 5e4) |
|
|
|
|
|
|
|
// XXX: build the Transaction w/ a P2WPKH input
|
|
|
|
const txb = new bitcoin.TransactionBuilder(regtest) |
|
|
|
txb.addInput(unspent.txId, unspent.vout, null, p2wpkh.output) // NOTE: provide the prevOutScript!
|
|
|
|
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4) |
|
|
|
txb.sign(0, keyPair, null, null, unspent.value) // NOTE: no redeem script
|
|
|
|
const tx = txb.build() |
|
|
|
|
|
|
|
// build and broadcast (the P2WPKH transaction) to the Bitcoin RegTest network
|
|
|
|
await regtestUtils.broadcast(tx.toHex()) |
|
|
|
|
|
|
|
await regtestUtils.verify({ |
|
|
|
txId: tx.getId(), |
|
|
|
address: regtestUtils.RANDOM_ADDRESS, |
|
|
|
vout: 0, |
|
|
|
value: 2e4 |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WSH(P2PK) input', function (done) { |
|
|
|
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WSH(P2PK) input', async () => { |
|
|
|
const keyPair = bitcoin.ECPair.makeRandom({ network: regtest }) |
|
|
|
const p2pk = bitcoin.payments.p2pk({ pubkey: keyPair.publicKey, network: regtest }) |
|
|
|
const p2wsh = bitcoin.payments.p2wsh({ redeem: p2pk, network: regtest }) |
|
|
|
|
|
|
|
regtestUtils.faucetComplex(p2wsh.address, 5e4, function (err, unspent) { |
|
|
|
if (err) return done(err) |
|
|
|
|
|
|
|
// XXX: build the Transaction w/ a P2WSH input
|
|
|
|
const txb = new bitcoin.TransactionBuilder(regtest) |
|
|
|
txb.addInput(unspent.txId, unspent.vout, null, p2wsh.output) // NOTE: provide the prevOutScript!
|
|
|
|
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4) |
|
|
|
txb.sign(0, keyPair, null, null, 5e4, p2wsh.redeem.output) // NOTE: provide a witnessScript!
|
|
|
|
const tx = txb.build() |
|
|
|
|
|
|
|
// build and broadcast (the P2WSH transaction) to the Bitcoin RegTest network
|
|
|
|
regtestUtils.broadcast(tx.toHex(), function (err) { |
|
|
|
if (err) return done(err) |
|
|
|
|
|
|
|
regtestUtils.verify({ |
|
|
|
txId: tx.getId(), |
|
|
|
address: regtestUtils.RANDOM_ADDRESS, |
|
|
|
vout: 0, |
|
|
|
value: 2e4 |
|
|
|
}, done) |
|
|
|
}) |
|
|
|
const unspent = await regtestUtils.faucetComplex(p2wsh.address, 5e4) |
|
|
|
|
|
|
|
// XXX: build the Transaction w/ a P2WSH input
|
|
|
|
const txb = new bitcoin.TransactionBuilder(regtest) |
|
|
|
txb.addInput(unspent.txId, unspent.vout, null, p2wsh.output) // NOTE: provide the prevOutScript!
|
|
|
|
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4) |
|
|
|
txb.sign(0, keyPair, null, null, 5e4, p2wsh.redeem.output) // NOTE: provide a witnessScript!
|
|
|
|
const tx = txb.build() |
|
|
|
|
|
|
|
// build and broadcast (the P2WSH transaction) to the Bitcoin RegTest network
|
|
|
|
await regtestUtils.broadcast(tx.toHex()) |
|
|
|
|
|
|
|
await regtestUtils.verify({ |
|
|
|
txId: tx.getId(), |
|
|
|
address: regtestUtils.RANDOM_ADDRESS, |
|
|
|
vout: 0, |
|
|
|
value: 2e4 |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WSH(P2MS(3 of 4))) (SegWit multisig) input', function (done) { |
|
|
|
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WSH(P2MS(3 of 4))) (SegWit multisig) input', async () => { |
|
|
|
const keyPairs = [ |
|
|
|
bitcoin.ECPair.makeRandom({ network: regtest }), |
|
|
|
bitcoin.ECPair.makeRandom({ network: regtest }), |
|
|
@ -232,29 +210,25 @@ describe('bitcoinjs-lib (transactions)', function () { |
|
|
|
const p2wsh = bitcoin.payments.p2wsh({ redeem: p2ms, network: regtest }) |
|
|
|
const p2sh = bitcoin.payments.p2sh({ redeem: p2wsh, network: regtest }) |
|
|
|
|
|
|
|
regtestUtils.faucet(p2sh.address, 6e4, function (err, unspent) { |
|
|
|
if (err) return done(err) |
|
|
|
const unspent = await regtestUtils.faucet(p2sh.address, 6e4) |
|
|
|
|
|
|
|
const txb = new bitcoin.TransactionBuilder(regtest) |
|
|
|
txb.addInput(unspent.txId, unspent.vout, null, p2sh.output) |
|
|
|
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 3e4) |
|
|
|
txb.sign(0, keyPairs[0], p2sh.redeem.output, null, unspent.value, p2wsh.redeem.output) |
|
|
|
txb.sign(0, keyPairs[2], p2sh.redeem.output, null, unspent.value, p2wsh.redeem.output) |
|
|
|
txb.sign(0, keyPairs[3], p2sh.redeem.output, null, unspent.value, p2wsh.redeem.output) |
|
|
|
const txb = new bitcoin.TransactionBuilder(regtest) |
|
|
|
txb.addInput(unspent.txId, unspent.vout, null, p2sh.output) |
|
|
|
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 3e4) |
|
|
|
txb.sign(0, keyPairs[0], p2sh.redeem.output, null, unspent.value, p2wsh.redeem.output) |
|
|
|
txb.sign(0, keyPairs[2], p2sh.redeem.output, null, unspent.value, p2wsh.redeem.output) |
|
|
|
txb.sign(0, keyPairs[3], p2sh.redeem.output, null, unspent.value, p2wsh.redeem.output) |
|
|
|
|
|
|
|
const tx = txb.build() |
|
|
|
const tx = txb.build() |
|
|
|
|
|
|
|
// build and broadcast to the Bitcoin RegTest network
|
|
|
|
regtestUtils.broadcast(tx.toHex(), function (err) { |
|
|
|
if (err) return done(err) |
|
|
|
// build and broadcast to the Bitcoin RegTest network
|
|
|
|
await regtestUtils.broadcast(tx.toHex()) |
|
|
|
|
|
|
|
regtestUtils.verify({ |
|
|
|
txId: tx.getId(), |
|
|
|
address: regtestUtils.RANDOM_ADDRESS, |
|
|
|
vout: 0, |
|
|
|
value: 3e4 |
|
|
|
}, done) |
|
|
|
}) |
|
|
|
await regtestUtils.verify({ |
|
|
|
txId: tx.getId(), |
|
|
|
address: regtestUtils.RANDOM_ADDRESS, |
|
|
|
vout: 0, |
|
|
|
value: 3e4 |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|