Merge Integration test changes from master
This commit is contained in:
parent
4c6ea80459
commit
5990ece108
2 changed files with 75 additions and 54 deletions
|
@ -2,34 +2,35 @@ const { describe, it } = require('mocha')
|
|||
const assert = require('assert')
|
||||
const bitcoin = require('../../')
|
||||
const dhttp = require('dhttp/200')
|
||||
|
||||
const LITECOIN = {
|
||||
messagePrefix: '\x19Litecoin Signed Message:\n',
|
||||
bip32: {
|
||||
public: 0x019da462,
|
||||
private: 0x019d9cfe
|
||||
},
|
||||
pubKeyHash: 0x30,
|
||||
scriptHash: 0x32,
|
||||
wif: 0xb0
|
||||
}
|
||||
|
||||
// deterministic RNG for testing only
|
||||
function rng () { return Buffer.from('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz') }
|
||||
const TESTNET = bitcoin.networks.testnet
|
||||
|
||||
describe('bitcoinjs-lib (addresses)', function () {
|
||||
it('can generate a random address', function () {
|
||||
const keyPair = bitcoin.ECPair.makeRandom({ rng: rng })
|
||||
it('can generate a random address [and support the retrieval of transactions for that address (via 3PBP)', function (done) {
|
||||
const keyPair = bitcoin.ECPair.makeRandom()
|
||||
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey })
|
||||
|
||||
assert.strictEqual(address, '1F5VhMHukdnUES9kfXqzPzMeF1GPHKiF64')
|
||||
// bitcoin P2PKH addresses start with a '1'
|
||||
assert.strictEqual(address.startsWith('1'), true)
|
||||
|
||||
dhttp({
|
||||
method: 'GET',
|
||||
url: 'https://blockchain.info/rawaddr/' + address
|
||||
}, function (err, result) {
|
||||
if (err) return done(err)
|
||||
|
||||
// random private keys [probably!] have no transactions
|
||||
assert.strictEqual(result.n_tx, 0)
|
||||
assert.strictEqual(result.total_received, 0)
|
||||
assert.strictEqual(result.total_sent, 0)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('can import an address via WIF', function () {
|
||||
const keyPair = bitcoin.ECPair.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct')
|
||||
const keyPair = bitcoin.ECPair.fromWIF('KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn')
|
||||
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey })
|
||||
|
||||
assert.strictEqual(address, '19AAjaTUbRjQCMuVczepkoPswiZRhjtg31')
|
||||
assert.strictEqual(address, '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH')
|
||||
})
|
||||
|
||||
it('can generate a P2SH, pay-to-multisig (2-of-3) address', function () {
|
||||
|
@ -46,19 +47,19 @@ describe('bitcoinjs-lib (addresses)', function () {
|
|||
})
|
||||
|
||||
it('can generate a SegWit address', function () {
|
||||
const keyPair = bitcoin.ECPair.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct')
|
||||
const keyPair = bitcoin.ECPair.fromWIF('KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn')
|
||||
const { address } = bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey })
|
||||
|
||||
assert.strictEqual(address, 'bc1qt97wqg464zrhnx23upykca5annqvwkwujjglky')
|
||||
assert.strictEqual(address, 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4')
|
||||
})
|
||||
|
||||
it('can generate a SegWit address (via P2SH)', function () {
|
||||
const keyPair = bitcoin.ECPair.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct')
|
||||
const keyPair = bitcoin.ECPair.fromWIF('KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn')
|
||||
const { address } = bitcoin.payments.p2sh({
|
||||
redeem: bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey })
|
||||
})
|
||||
|
||||
assert.strictEqual(address, '34AgLJhwXrvmkZS1o5TrcdeevMt22Nar53')
|
||||
assert.strictEqual(address, '3JvL6Ymt8MVWiCNHC7oWU6nLeHNJKLZGLN')
|
||||
})
|
||||
|
||||
it('can generate a P2WSH (SegWit), pay-to-multisig (3-of-4) address', function () {
|
||||
|
@ -89,41 +90,31 @@ describe('bitcoinjs-lib (addresses)', function () {
|
|||
assert.strictEqual(address, '3P4mrxQfmExfhxqjLnR2Ah4WES5EB1KBrN')
|
||||
})
|
||||
|
||||
it('can support the retrieval of transactions for an address (via 3PBP)', function (done) {
|
||||
const keyPair = bitcoin.ECPair.makeRandom()
|
||||
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey })
|
||||
|
||||
dhttp({
|
||||
method: 'GET',
|
||||
url: 'https://blockchain.info/rawaddr/' + address
|
||||
}, function (err, result) {
|
||||
if (err) return done(err)
|
||||
|
||||
// random private keys [probably!] have no transactions
|
||||
assert.strictEqual(result.n_tx, 0)
|
||||
assert.strictEqual(result.total_received, 0)
|
||||
assert.strictEqual(result.total_sent, 0)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
// other networks
|
||||
// examples using other network information
|
||||
it('can generate a Testnet address', function () {
|
||||
const testnet = bitcoin.networks.testnet
|
||||
const keyPair = bitcoin.ECPair.makeRandom({ network: testnet, rng: rng })
|
||||
const wif = keyPair.toWIF()
|
||||
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey, network: testnet })
|
||||
const keyPair = bitcoin.ECPair.makeRandom({ network: TESTNET })
|
||||
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey, network: TESTNET })
|
||||
|
||||
assert.strictEqual(address, 'mubSzQNtZfDj1YdNP6pNDuZy6zs6GDn61L')
|
||||
assert.strictEqual(wif, 'cRgnQe9MUu1JznntrLaoQpB476M8PURvXVQB5R2eqms5tXnzNsrr')
|
||||
// bitcoin testnet P2PKH addresses start with a 'm' or 'n'
|
||||
assert.strictEqual(address.startsWith('m') || address.startsWith('n'), true)
|
||||
})
|
||||
|
||||
it('can generate a Litecoin address', function () {
|
||||
const keyPair = bitcoin.ECPair.makeRandom({ network: LITECOIN, rng: rng })
|
||||
const wif = keyPair.toWIF()
|
||||
// WARNING: although possible, bitcoinjs is NOT necessarily compatible with Litecoin
|
||||
const LITECOIN = {
|
||||
messagePrefix: '\x19Litecoin Signed Message:\n',
|
||||
bip32: {
|
||||
public: 0x019da462,
|
||||
private: 0x019d9cfe
|
||||
},
|
||||
pubKeyHash: 0x30,
|
||||
scriptHash: 0x32,
|
||||
wif: 0xb0
|
||||
}
|
||||
|
||||
const keyPair = bitcoin.ECPair.makeRandom({ network: LITECOIN })
|
||||
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey, network: LITECOIN })
|
||||
|
||||
assert.strictEqual(address, 'LZJSxZbjqJ2XVEquqfqHg1RQTDdfST5PTn')
|
||||
assert.strictEqual(wif, 'T7A4PUSgTDHecBxW1ZiYFrDNRih2o7M8Gf9xpoCgudPF9gDiNvuS')
|
||||
assert.strictEqual(address.startsWith('L'), true)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -64,7 +64,7 @@ describe('bitcoinjs-lib (transactions)', function () {
|
|||
txb.addInput(unspent1.txId, unspent1.vout) // alice2 unspent
|
||||
txb.addOutput('mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf', 8e4) // the actual "spend"
|
||||
txb.addOutput(aliceCpkh.address, 1e4) // Alice's change
|
||||
// (in)(4e4 + 2e4) - (out)(1e4 + 3e4) = (fee)2e4 = 20000, this is the miner fee
|
||||
// (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)
|
||||
|
@ -258,7 +258,7 @@ describe('bitcoinjs-lib (transactions)', function () {
|
|||
})
|
||||
})
|
||||
|
||||
it('can verify Transaction signatures', function () {
|
||||
it('can verify Transaction (P2PKH) signatures', function () {
|
||||
const txHex = '010000000321c5f7e7bc98b3feda84aad36a5c99a02bcb8823a2f3eccbcd5da209698b5c20000000006b48304502210099e021772830207cf7c55b69948d3b16b4dcbf1f55a9cd80ebf8221a169735f9022064d33f11d62cd28240b3862afc0b901adc9f231c7124dd19bdb30367b61964c50121032b4c06c06c3ec0b7fa29519dfa5aae193ee2cc35ca127f29f14ec605d62fb63dffffffff8a75ce85441ddb3f342708ee33cc8ed418b07d9ba9e0e7c4e1cccfe9f52d8a88000000006946304302207916c23dae212c95a920423902fa44e939fb3d542f4478a7b46e9cde53705800021f0d74e9504146e404c1b8f9cba4dff2d4782e3075491c9ed07ce4a7d1c4461a01210216c92abe433106491bdeb4a261226f20f5a4ac86220cc6e37655aac6bf3c1f2affffffffdfef93f69fe32e944fad79fa8f882b3a155d80383252348caba1a77a5abbf7ef000000006b483045022100faa6e9ca289b46c64764a624c59ac30d9abcf1d4a04c4de9089e67cbe0d300a502206930afa683f6807502de5c2431bf9a1fd333c8a2910a76304df0f3d23d83443f0121039e05da8b8ea4f9868ecebb25998c7701542986233f4401799551fbecf316b18fffffffff01ff4b0000000000001976a9146c86476d1d85cd60116cd122a274e6a570a5a35c88acc96d0700'
|
||||
const keyPairs = [
|
||||
'032b4c06c06c3ec0b7fa29519dfa5aae193ee2cc35ca127f29f14ec605d62fb63d',
|
||||
|
@ -281,4 +281,34 @@ describe('bitcoinjs-lib (transactions)', function () {
|
|||
assert.strictEqual(keyPair.verify(hash, ss.signature), true)
|
||||
})
|
||||
})
|
||||
|
||||
it('can verify Transaction (P2SH(P2WPKH)) signatures', function () {
|
||||
const utxos = {
|
||||
'f72d1d83ac40fcedd01415751556a905844ab5f44bbb7728565ebb91b1590109:0': {
|
||||
value: 50000
|
||||
}
|
||||
}
|
||||
|
||||
const txHex = '02000000000101090159b191bb5e562877bb4bf4b54a8405a95615751514d0edfc40ac831d2df7000000001716001435a179e5516947a39ae9c8a25e9fe62c0fc598edffffffff01204e0000000000001976a91431d43308d3c886d53e9ae8a45728370571ff456988ac0247304402206ec41f685b997a51f325b07ee852e82a535f6b52ef54485cc133e05168aa052a022070bafa86108acb51c77b2b259ae8fb7fd1efa10fef804fcfe9b13c2db719acf5012103fb03e9d0a9af86cbed94225dbb8bb70f6b82109bce0a61ddcf41dab6cbb4871100000000'
|
||||
const tx = bitcoin.Transaction.fromHex(txHex)
|
||||
|
||||
tx.ins.forEach(function (input, i) {
|
||||
const txId = Buffer.from(input.hash).reverse().toString('hex')
|
||||
const utxo = utxos[`${txId}:${i}`]
|
||||
if (!utxo) throw new Error('Missing utxo')
|
||||
|
||||
const p2sh = bitcoin.payments.p2sh({
|
||||
input: input.script,
|
||||
witness: input.witness
|
||||
})
|
||||
const p2wpkh = bitcoin.payments.p2wpkh(p2sh.redeem)
|
||||
const p2pkh = bitcoin.payments.p2pkh({ pubkey: p2wpkh.pubkey }) // because P2WPKH is annoying
|
||||
|
||||
const ss = bitcoin.script.signature.decode(p2wpkh.signature)
|
||||
const hash = tx.hashForWitnessV0(i, p2pkh.output, utxo.value, ss.hashType)
|
||||
const keyPair = bitcoin.ECPair.fromPublicKey(p2wpkh.pubkey) // aka, cQ3EtF4mApRcogNGSeyPTKbmfxxn3Yfb1wecfKSws9a8bnYuxoAk
|
||||
|
||||
assert.strictEqual(keyPair.verify(hash, ss.signature), true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue