Skip to content

Commit 6d0a20c

Browse files
committed
tests: add P2WPK, P2WSH spend example
1 parent 5b1d443 commit 6d0a20c

File tree

3 files changed

+108
-35
lines changed

3 files changed

+108
-35
lines changed

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,19 +97,22 @@ Some examples interact (via HTTPS) with a 3rd Party Blockchain Provider (3PBP).
9797
- [Generate a random address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/addresses.js#L12)
9898
- [Generate an address from a SHA256 hash](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/addresses.js#L19)
9999
- [Import an address via WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/addresses.js#L29)
100-
- [Generate a 2-of-3 multisig P2SH address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/addresses.js#L36)
100+
- [Generate a 2-of-3 P2SH multisig address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/addresses.js#L36)
101101
- [Generate a SegWit address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/addresses.js:61)
102-
- [Generate a SegWit address (via P2SH)](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/addresses.js:50)
102+
- [Generate a SegWit P2SH address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/addresses.js:50)
103103
- [Generate a SegWit 3-of-4 multisig address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/addresses.js:85)
104-
- [Generate a SegWit 2-of-2 multisig address (via P2SH)](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/addresses.js:71)
104+
- [Generate a SegWit 2-of-2 P2SH multisig address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/addresses.js:71)
105105
- [Support the retrieval of transactions for an address (3rd party blockchain)](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/addresses.js#L52)
106106
- [Generate a Testnet address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/addresses.js#L73)
107107
- [Generate a Litecoin address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/addresses.js#L83)
108108
- [Create a 1-to-1 Transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/transactions.js#L14)
109109
- [Create a 2-to-2 Transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/transactions.js#L28)
110110
- [Create (and broadcast via 3PBP) a typical Transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/transactions.js#L46)
111111
- [Create (and broadcast via 3PBP) a Transaction with an OP\_RETURN output](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/transactions.js#L88)
112-
- [Create (and broadcast via 3PBP) a Transaction with a 2-of-4 multisig P2SH input](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/transactions.js#L115)
112+
- [Create (and broadcast via 3PBP) a Transaction with a 2-of-4 P2SH(multisig) input](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/transactions
113+
.js#L115)
114+
- [Create (and broadcast via 3PBP) a Transaction with a SegWit P2SH(P2WPKH) input](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/transactions.js#L155)
115+
- [Create (and broadcast via 3PBP) a Transaction with a SegWit 3-of-4 P2SH(P2WSH(multisig)) input](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/transactions.js#L182)
113116
- [Import a BIP32 testnet xpriv and export to WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/bip32.js#L8)
114117
- [Export a BIP32 xpriv, then import it](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/bip32.js#L15)
115118
- [Export a BIP32 xpub](https://github.com/bitcoinjs/bitcoinjs-lib/blob/ae8422d/test/integration/bip32.js#L26)

test/integration/_testnet.js

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ var async = require('async')
22
var bitcoin = require('../../')
33
var Blockchain = require('cb-http-client')
44
var coinSelect = require('coinselect')
5+
var dhttp = require('dhttp/200')
56
var typeforce = require('typeforce')
67
var types = require('../../src/types')
78

@@ -26,6 +27,7 @@ function fundAddress (unspents, outputs, callback) {
2627
})
2728

2829
result.outputs.forEach(function (x) {
30+
if (x.address) console.warn('funding ' + x.address + ' w/ ' + x.value)
2931
txb.addOutput(x.address || kpAddress, x.value)
3032
})
3133

@@ -34,17 +36,14 @@ function fundAddress (unspents, outputs, callback) {
3436
})
3537

3638
var tx = txb.build()
37-
var txId = tx.getId()
3839

3940
blockchain.transactions.propagate(tx.toHex(), function (err) {
4041
if (err) return callback(err)
4142

42-
// FIXME: @blocktrail can be very slow, give it time
43-
setTimeout(function () {
44-
callback(null, outputs.map(function (_, i) {
45-
return { txId: txId, vout: i }
46-
}))
47-
}, 3000)
43+
var txId = tx.getId()
44+
callback(null, outputs.map(function (x, i) {
45+
return { txId: txId, vout: i, value: x.value }
46+
}))
4847
})
4948
}
5049

@@ -73,17 +72,26 @@ blockchain.verify = function (address, txId, value, done) {
7372
async.retry(5, function (callback) {
7473
setTimeout(function () {
7574
// check that the above transaction included the intended address
76-
blockchain.addresses.unspents(blockchain.RETURN_ADDRESS, function (err, unspents) {
75+
dhttp({
76+
method: 'POST',
77+
url: 'https://api.ei8ht.com.au:9443/3/txs',
78+
body: [txId]
79+
}, function (err, result) {
7780
if (err) return callback(err)
78-
if (!unspents.some(function (x) {
79-
return x.txId === txId && x.value === value
80-
})) return callback(new Error('Could not find unspent'))
81-
81+
if (!result[txId]) return callback(new Error('Could not find ' + txId))
8282
callback()
8383
})
84-
}, 600)
84+
}, 400)
8585
}, done)
8686
}
8787

88+
blockchain.transactions.propagate = function (txHex, callback) {
89+
dhttp({
90+
method: 'POST',
91+
url: 'https://api.ei8ht.com.au:9443/3/pushtx',
92+
body: txHex
93+
}, callback)
94+
}
95+
8896
blockchain.RETURN_ADDRESS = kpAddress
8997
module.exports = blockchain

test/integration/transactions.js

Lines changed: 80 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ describe('bitcoinjs-lib (transactions)', function () {
2121

2222
tx.sign(0, alice)
2323

24-
// build, prepare for broadcast to the Bitcoin network, see "can broadcast a Transaction" below
24+
// prepare for broadcast to the Bitcoin network, see "can broadcast a Transaction" below
2525
assert.strictEqual(tx.build().toHex(), '01000000019d344070eac3fe6e394a16d06d7704a7d5c0a10eb2a2c16bc98842b7cc20d561000000006b48304502210088828c0bdfcdca68d8ae0caeb6ec62cd3fd5f9b2191848edae33feb533df35d302202e0beadd35e17e7f83a733f5277028a9b453d525553e3f5d2d7a7aa8010a81d60121029f50f51d63b345039a290c94bffd3180c99ed659ff6ea6b1242bca47eb93b59fffffffff01e02e0000000000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac00000000')
2626
})
2727

@@ -39,7 +39,7 @@ describe('bitcoinjs-lib (transactions)', function () {
3939
tx.sign(1, bob) // Bob signs his input, which was the second input (1th)
4040
tx.sign(0, alice) // Alice signs her input, which was the first input (0th)
4141

42-
// build, prepare for broadcast to the Bitcoin network, see "can broadcast a Transaction" below
42+
// prepare for broadcast to the Bitcoin network, see "can broadcast a Transaction" below
4343
assert.strictEqual(tx.build().toHex(), '01000000024c94e48a870b85f41228d33cf25213dfcc8dd796e7211ed6b1f9a014809dbbb5060000006a473044022041450c258ce7cac7da97316bf2ea1ce66d88967c4df94f3e91f4c2a30f5d08cb02203674d516e6bb2b0afd084c3551614bd9cec3c2945231245e891b145f2d6951f0012103e05ce435e462ec503143305feb6c00e06a3ad52fbf939e85c65f3a765bb7baacffffffff3077d9de049574c3af9bc9c09a7c9db80f2d94caaf63988c9166249b955e867d000000006b483045022100aeb5f1332c79c446d3f906e4499b2e678500580a3f90329edf1ba502eec9402e022072c8b863f8c8d6c26f4c691ac9a6610aa4200edc697306648ee844cfbc089d7a012103df7940ee7cddd2f97763f67e1fb13488da3fbdd7f9c68ec5ef0864074745a289ffffffff0220bf0200000000001976a9147dd65592d0ab2fe0d0257d571abf032cd9db93dc88ac10980200000000001976a914c42e7ef92fdb603af844d064faad95db9bcdfd3d88ac00000000')
4444
})
4545

@@ -54,20 +54,20 @@ describe('bitcoinjs-lib (transactions)', function () {
5454
testnetUtils.faucetMany([
5555
{
5656
address: alice1.getAddress(),
57-
value: 4e4
57+
value: 5e4
5858
},
5959
{
6060
address: alice2.getAddress(),
61-
value: 2e4
61+
value: 7e4
6262
}
6363
], function (err, unspents) {
6464
if (err) return done(err)
6565

6666
var tx = new bitcoin.TransactionBuilder(testnet)
6767
tx.addInput(unspents[0].txId, unspents[0].vout) // alice1 unspent
6868
tx.addInput(unspents[1].txId, unspents[1].vout) // alice2 unspent
69-
tx.addOutput('mvGVHWi6gbkBZZPaqBVRcxvKVPYd9r3fp7', 1e4) // the actual "spend"
70-
tx.addOutput(aliceChange.getAddress(), 3e4) // Alice's change
69+
tx.addOutput('mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf', 8e4) // the actual "spend"
70+
tx.addOutput(aliceChange.getAddress(), 1e4) // Alice's change
7171
// (in)(4e4 + 2e4) - (out)(1e4 + 3e4) = (fee)2e4 = 20000, this is the miner fee
7272

7373
// Alice signs each input with the respective private keys
@@ -112,7 +112,7 @@ describe('bitcoinjs-lib (transactions)', function () {
112112
})
113113
})
114114

115-
it('can create (and broadcast via 3PBP) a Transaction with a 2-of-4 multisig P2SH input', function (done) {
115+
it('can create (and broadcast via 3PBP) a Transaction with a 2-of-4 P2SH(multisig) input', function (done) {
116116
this.timeout(30000)
117117

118118
var keyPairs = [
@@ -123,34 +123,96 @@ describe('bitcoinjs-lib (transactions)', function () {
123123
].map(function (wif) { return bitcoin.ECPair.fromWIF(wif, testnet) })
124124
var pubKeys = keyPairs.map(function (x) { return x.getPublicKeyBuffer() })
125125

126-
var redeemScript = bitcoin.script.multisig.output.encode(2, pubKeys) // 2 of 4
126+
var redeemScript = bitcoin.script.multisig.output.encode(2, pubKeys)
127127
var scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
128128
var address = bitcoin.address.fromOutputScript(scriptPubKey, testnet)
129129

130-
// attempt to send funds to the source address
131130
testnetUtils.faucet(address, 2e4, function (err, unspent) {
132131
if (err) return done(err)
133132

134133
var txb = new bitcoin.TransactionBuilder(testnet)
135134
txb.addInput(unspent.txId, unspent.vout)
136135
txb.addOutput(testnetUtils.RETURN_ADDRESS, 1e4)
137136

138-
// sign with 1st and 3rd key
139137
txb.sign(0, keyPairs[0], redeemScript)
140138
txb.sign(0, keyPairs[2], redeemScript)
141139

142-
// broadcast our transaction
143140
var tx = txb.build()
144-
var txId = tx.getId()
145141

146-
dhttp({
147-
method: 'POST',
148-
url: 'https://api.ei8ht.com.au:9443/3/pushtx',
149-
body: tx.toHex()
150-
}, function (err) {
142+
// build and broadcast to the Bitcoin Testnet network
143+
testnetUtils.transactions.propagate(tx.toHex(), function (err) {
144+
if (err) return done(err)
145+
146+
testnetUtils.verify(address, tx.getId(), 1e4, done)
147+
})
148+
})
149+
})
150+
151+
it('can create (and broadcast via 3PBP) a Transaction with a SegWit P2SH(P2WPKH) input', function (done) {
152+
this.timeout(30000)
153+
154+
var keyPair = bitcoin.ECPair.fromWIF('cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN87JcbXMTcA', testnet)
155+
var pubKey = keyPair.getPublicKeyBuffer()
156+
var pubKeyHash = bitcoin.crypto.hash160(pubKey)
157+
158+
var redeemScript = bitcoin.script.witnessPubKeyHash.output.encode(pubKeyHash)
159+
var redeemScriptHash = bitcoin.crypto.hash160(redeemScript)
160+
161+
var scriptPubKey = bitcoin.script.scriptHash.output.encode(redeemScriptHash)
162+
var address = bitcoin.address.fromOutputScript(scriptPubKey, testnet)
163+
164+
testnetUtils.faucet(address, 5e4, function (err, unspent) {
165+
if (err) return done(err)
166+
167+
var txb = new bitcoin.TransactionBuilder(testnet)
168+
txb.addInput(unspent.txId, unspent.vout)
169+
txb.addOutput(testnetUtils.RETURN_ADDRESS, 4e4)
170+
txb.sign(0, keyPair, redeemScript, null, unspent.value)
171+
172+
var tx = txb.build()
173+
174+
// build and broadcast to the Bitcoin Testnet network
175+
testnetUtils.transactions.propagate(tx.toHex(), function (err) {
176+
if (err) return done(err)
177+
178+
testnetUtils.verify(address, tx.getId(), 1e4, done)
179+
})
180+
})
181+
})
182+
183+
it('can create (and broadcast via 3PBP) a Transaction with a SegWit 3-of-4 P2SH(P2WSH(multisig)) input', function (done) {
184+
this.timeout(50000)
185+
186+
var keyPairs = [
187+
'cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN87JcbXMTcA',
188+
'cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN87K7XCyj5v',
189+
'cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN87KcLPVfXz',
190+
'cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN87L7FgDCKE'
191+
].map(function (wif) { return bitcoin.ECPair.fromWIF(wif, testnet) })
192+
var pubKeys = keyPairs.map(function (x) { return x.getPublicKeyBuffer() })
193+
194+
var witnessScript = bitcoin.script.multisig.output.encode(3, pubKeys)
195+
var redeemScript = bitcoin.script.witnessScriptHash.output.encode(bitcoin.crypto.sha256(witnessScript))
196+
var scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
197+
var address = bitcoin.address.fromOutputScript(scriptPubKey, testnet)
198+
199+
testnetUtils.faucet(address, 6e4, function (err, unspent) {
200+
if (err) return done(err)
201+
202+
var txb = new bitcoin.TransactionBuilder(testnet)
203+
txb.addInput(unspent.txId, unspent.vout)
204+
txb.addOutput(testnetUtils.RETURN_ADDRESS, 4e4)
205+
txb.sign(0, keyPairs[0], redeemScript, null, unspent.value, witnessScript)
206+
txb.sign(0, keyPairs[2], redeemScript, null, unspent.value, witnessScript)
207+
txb.sign(0, keyPairs[3], redeemScript, null, unspent.value, witnessScript)
208+
209+
var tx = txb.build()
210+
211+
// build and broadcast to the Bitcoin Testnet network
212+
testnetUtils.transactions.propagate(tx.toHex(), function (err) {
151213
if (err) return done(err)
152214

153-
testnetUtils.verify(address, txId, 1e4, done)
215+
testnetUtils.verify(address, tx.getId(), 4e4, done)
154216
})
155217
})
156218
})

0 commit comments

Comments
 (0)