Merge pull request #1114 from bitcoinjs/loose
payments: dont always require output data
This commit is contained in:
commit
60ec5fe938
10 changed files with 101 additions and 114 deletions
|
@ -20,7 +20,8 @@ function stacksEqual (a, b) {
|
|||
function p2ms (a, opts) {
|
||||
if (
|
||||
!a.output &&
|
||||
!(a.pubkeys && a.m !== undefined)
|
||||
!(a.pubkeys && a.m !== undefined) &&
|
||||
!a.signatures
|
||||
) throw new TypeError('Not enough data')
|
||||
opts = opts || { validate: true }
|
||||
|
||||
|
|
|
@ -11,7 +11,9 @@ let BITCOIN_NETWORK = require('../networks').bitcoin
|
|||
function p2pk (a, opts) {
|
||||
if (
|
||||
!a.output &&
|
||||
!a.pubkey
|
||||
!a.pubkey &&
|
||||
!a.input &&
|
||||
!a.signature
|
||||
) throw new TypeError('Not enough data')
|
||||
opts = opts || { validate: true }
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ function p2sh (a, opts) {
|
|||
|
||||
redeem: typef.maybe({
|
||||
network: typef.maybe(typef.Object),
|
||||
output: typef.Buffer,
|
||||
output: typef.maybe(typef.Buffer),
|
||||
input: typef.maybe(typef.Buffer),
|
||||
witness: typef.maybe(typef.arrayOf(typef.Buffer))
|
||||
}),
|
||||
|
@ -86,7 +86,7 @@ function p2sh (a, opts) {
|
|||
return _redeem()
|
||||
})
|
||||
lazy.prop(o, 'input', function () {
|
||||
if (!a.redeem || !a.redeem.input) return
|
||||
if (!a.redeem || !a.redeem.input || !a.redeem.output) return
|
||||
return bscript.compile([].concat(
|
||||
bscript.decompile(a.redeem.input),
|
||||
a.redeem.output
|
||||
|
@ -124,13 +124,15 @@ function p2sh (a, opts) {
|
|||
// inlined to prevent 'no-inner-declarations' failing
|
||||
const checkRedeem = function (redeem) {
|
||||
// is the redeem output empty/invalid?
|
||||
const decompile = bscript.decompile(redeem.output)
|
||||
if (!decompile || decompile.length < 1) throw new TypeError('Redeem.output too short')
|
||||
if (redeem.output) {
|
||||
const decompile = bscript.decompile(redeem.output)
|
||||
if (!decompile || decompile.length < 1) throw new TypeError('Redeem.output too short')
|
||||
|
||||
// match hash against other sources
|
||||
const hash2 = bcrypto.hash160(redeem.output)
|
||||
if (hash && !hash.equals(hash2)) throw new TypeError('Hash mismatch')
|
||||
else hash = hash2
|
||||
// match hash against other sources
|
||||
const hash2 = bcrypto.hash160(redeem.output)
|
||||
if (hash && !hash.equals(hash2)) throw new TypeError('Hash mismatch')
|
||||
else hash = hash2
|
||||
}
|
||||
|
||||
if (redeem.input) {
|
||||
const hasInput = redeem.input.length > 0
|
||||
|
|
|
@ -40,7 +40,7 @@ function p2wsh (a, opts) {
|
|||
redeem: typef.maybe({
|
||||
input: typef.maybe(typef.Buffer),
|
||||
network: typef.maybe(typef.Object),
|
||||
output: typef.Buffer,
|
||||
output: typef.maybe(typef.Buffer),
|
||||
witness: typef.maybe(typef.arrayOf(typef.Buffer))
|
||||
}),
|
||||
input: typef.maybe(typef.BufferN(0)),
|
||||
|
@ -83,8 +83,14 @@ function p2wsh (a, opts) {
|
|||
})
|
||||
lazy.prop(o, 'witness', function () {
|
||||
// transform redeem input to witness stack?
|
||||
if (a.redeem && a.redeem.input && a.redeem.input.length > 0) {
|
||||
let stack = bscript.toStack(_rchunks())
|
||||
if (
|
||||
a.redeem &&
|
||||
a.redeem.input &&
|
||||
a.redeem.input.length > 0 &&
|
||||
a.redeem.output &&
|
||||
a.redeem.output.length > 0
|
||||
) {
|
||||
const stack = bscript.toStack(_rchunks())
|
||||
|
||||
// assign, and blank the existing input
|
||||
o.redeem = Object.assign({ witness: stack }, a.redeem)
|
||||
|
@ -93,6 +99,7 @@ function p2wsh (a, opts) {
|
|||
}
|
||||
|
||||
if (!a.redeem) return
|
||||
if (!a.redeem.output) return
|
||||
if (!a.redeem.witness) return
|
||||
return [].concat(a.redeem.witness, a.redeem.output)
|
||||
})
|
||||
|
@ -117,7 +124,7 @@ function p2wsh (a, opts) {
|
|||
a.output.length !== 34 ||
|
||||
a.output[0] !== OPS.OP_0 ||
|
||||
a.output[1] !== 0x20) throw new TypeError('Output is invalid')
|
||||
let hash2 = a.output.slice(2)
|
||||
const hash2 = a.output.slice(2)
|
||||
if (hash && !hash.equals(hash2)) throw new TypeError('Hash mismatch')
|
||||
else hash = hash2
|
||||
}
|
||||
|
@ -129,22 +136,26 @@ function p2wsh (a, opts) {
|
|||
if (
|
||||
a.redeem.input &&
|
||||
a.redeem.input.length > 0 &&
|
||||
a.redeem.witness) throw new TypeError('Ambiguous witness source')
|
||||
a.redeem.witness &&
|
||||
a.redeem.witness.length > 0
|
||||
) throw new TypeError('Ambiguous witness source')
|
||||
|
||||
// is the redeem output non-empty?
|
||||
if (bscript.decompile(a.redeem.output).length === 0) throw new TypeError('Redeem.output is invalid')
|
||||
if (a.redeem.output) {
|
||||
if (bscript.decompile(a.redeem.output).length === 0) throw new TypeError('Redeem.output is invalid')
|
||||
|
||||
// match hash against other sources
|
||||
let hash2 = bcrypto.sha256(a.redeem.output)
|
||||
if (hash && !hash.equals(hash2)) throw new TypeError('Hash mismatch')
|
||||
else hash = hash2
|
||||
// match hash against other sources
|
||||
let hash2 = bcrypto.sha256(a.redeem.output)
|
||||
if (hash && !hash.equals(hash2)) throw new TypeError('Hash mismatch')
|
||||
else hash = hash2
|
||||
}
|
||||
|
||||
if (a.redeem.input && !bscript.isPushOnly(_rchunks())) throw new TypeError('Non push-only scriptSig')
|
||||
if (a.witness && a.redeem.witness && !stacksEqual(a.witness, a.redeem.witness)) throw new TypeError('Witness and redeem.witness mismatch')
|
||||
}
|
||||
|
||||
if (a.witness) {
|
||||
if (a.redeem && !a.redeem.output.equals(a.witness[a.witness.length - 1])) throw new TypeError('Witness and redeem.output mismatch')
|
||||
if (a.redeem && a.redeem.output && !a.redeem.output.equals(a.witness[a.witness.length - 1])) throw new TypeError('Witness and redeem.output mismatch')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -67,12 +67,8 @@ function verify (txo, callback) {
|
|||
})
|
||||
}
|
||||
|
||||
// TODO: remove
|
||||
const baddress = bitcoin.address
|
||||
const bcrypto = bitcoin.crypto
|
||||
function getAddress (node, network) {
|
||||
network = network || bitcoin.networks.bitcoin
|
||||
return baddress.toBase58Check(bcrypto.hash160(node.publicKey), network.pubKeyHash)
|
||||
return bitcoin.payments.p2pkh({ pubkey: node.publicKey, network }).address
|
||||
}
|
||||
|
||||
function randomAddress () {
|
||||
|
|
|
@ -18,18 +18,10 @@ const LITECOIN = {
|
|||
// deterministic RNG for testing only
|
||||
function rng () { return Buffer.from('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz') }
|
||||
|
||||
// TODO: remove
|
||||
const baddress = bitcoin.address
|
||||
const bcrypto = bitcoin.crypto
|
||||
function getAddress (node, network) {
|
||||
network = network || bitcoin.networks.bitcoin
|
||||
return baddress.toBase58Check(bcrypto.hash160(node.publicKey), network.pubKeyHash)
|
||||
}
|
||||
|
||||
describe('bitcoinjs-lib (addresses)', function () {
|
||||
it('can generate a random address', function () {
|
||||
const keyPair = bitcoin.ECPair.makeRandom({ rng: rng })
|
||||
const address = getAddress(keyPair)
|
||||
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey })
|
||||
|
||||
assert.strictEqual(address, '1F5VhMHukdnUES9kfXqzPzMeF1GPHKiF64')
|
||||
})
|
||||
|
@ -38,7 +30,7 @@ describe('bitcoinjs-lib (addresses)', function () {
|
|||
const hash = bitcoin.crypto.sha256(Buffer.from('correct horse battery staple'))
|
||||
|
||||
const keyPair = bitcoin.ECPair.fromPrivateKey(hash)
|
||||
const address = getAddress(keyPair)
|
||||
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey })
|
||||
|
||||
// Generating addresses from SHA256 hashes is not secure if the input to the hash function is predictable
|
||||
// Do not use with predictable inputs
|
||||
|
@ -47,76 +39,71 @@ describe('bitcoinjs-lib (addresses)', function () {
|
|||
|
||||
it('can import an address via WIF', function () {
|
||||
const keyPair = bitcoin.ECPair.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct')
|
||||
const address = getAddress(keyPair)
|
||||
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey })
|
||||
|
||||
assert.strictEqual(address, '19AAjaTUbRjQCMuVczepkoPswiZRhjtg31')
|
||||
})
|
||||
|
||||
it('can generate a 2-of-3 multisig P2SH address', function () {
|
||||
const pubKeys = [
|
||||
it('can generate a P2SH, pay-to-multisig (2-of-3) address', function () {
|
||||
const pubkeys = [
|
||||
'026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01',
|
||||
'02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9',
|
||||
'03c6103b3b83e4a24a0e33a4df246ef11772f9992663db0c35759a5e2ebf68d8e9'
|
||||
].map(function (hex) { return Buffer.from(hex, 'hex') })
|
||||
|
||||
const redeemScript = bitcoin.script.multisig.output.encode(2, pubKeys) // 2 of 3
|
||||
const scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
|
||||
const address = bitcoin.address.fromOutputScript(scriptPubKey)
|
||||
].map((hex) => Buffer.from(hex, 'hex'))
|
||||
const { address } = bitcoin.payments.p2sh({
|
||||
redeem: bitcoin.payments.p2ms({ m: 2, pubkeys })
|
||||
})
|
||||
|
||||
assert.strictEqual(address, '36NUkt6FWUi3LAWBqWRdDmdTWbt91Yvfu7')
|
||||
})
|
||||
|
||||
it('can generate a SegWit address', function () {
|
||||
const keyPair = bitcoin.ECPair.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct')
|
||||
|
||||
const scriptPubKey = bitcoin.script.witnessPubKeyHash.output.encode(bitcoin.crypto.hash160(keyPair.publicKey))
|
||||
const address = bitcoin.address.fromOutputScript(scriptPubKey)
|
||||
const { address } = bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey })
|
||||
|
||||
assert.strictEqual(address, 'bc1qt97wqg464zrhnx23upykca5annqvwkwujjglky')
|
||||
})
|
||||
|
||||
it('can generate a SegWit address (via P2SH)', function () {
|
||||
const keyPair = bitcoin.ECPair.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct')
|
||||
|
||||
const redeemScript = bitcoin.script.witnessPubKeyHash.output.encode(bitcoin.crypto.hash160(keyPair.publicKey))
|
||||
const scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
|
||||
const address = bitcoin.address.fromOutputScript(scriptPubKey)
|
||||
const { address } = bitcoin.payments.p2sh({
|
||||
redeem: bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey })
|
||||
})
|
||||
|
||||
assert.strictEqual(address, '34AgLJhwXrvmkZS1o5TrcdeevMt22Nar53')
|
||||
})
|
||||
|
||||
it('can generate a SegWit 3-of-4 multisig address', function () {
|
||||
const pubKeys = [
|
||||
it('can generate a P2WSH (SegWit), pay-to-multisig (3-of-4) address', function () {
|
||||
const pubkeys = [
|
||||
'026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01',
|
||||
'02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9',
|
||||
'023e4740d0ba639e28963f3476157b7cf2fb7c6fdf4254f97099cf8670b505ea59',
|
||||
'03c6103b3b83e4a24a0e33a4df246ef11772f9992663db0c35759a5e2ebf68d8e9'
|
||||
].map(function (hex) { return Buffer.from(hex, 'hex') })
|
||||
|
||||
const witnessScript = bitcoin.script.multisig.output.encode(3, pubKeys) // 3 of 4
|
||||
const scriptPubKey = bitcoin.script.witnessScriptHash.output.encode(bitcoin.crypto.sha256(witnessScript))
|
||||
const address = bitcoin.address.fromOutputScript(scriptPubKey)
|
||||
].map((hex) => Buffer.from(hex, 'hex'))
|
||||
const { address } = bitcoin.payments.p2wsh({
|
||||
redeem: bitcoin.payments.p2ms({ m: 3, pubkeys })
|
||||
})
|
||||
|
||||
assert.strictEqual(address, 'bc1q75f6dv4q8ug7zhujrsp5t0hzf33lllnr3fe7e2pra3v24mzl8rrqtp3qul')
|
||||
})
|
||||
|
||||
it('can generate a SegWit 2-of-2 multisig address (via P2SH)', function () {
|
||||
const pubKeys = [
|
||||
it('can generate a P2SH(P2WSH(...)), pay-to-multisig (2-of-2) address', function () {
|
||||
const pubkeys = [
|
||||
'026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01',
|
||||
'02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9'
|
||||
].map(function (hex) { return Buffer.from(hex, 'hex') })
|
||||
|
||||
const witnessScript = bitcoin.script.multisig.output.encode(2, pubKeys) // 2 of 2
|
||||
const redeemScript = bitcoin.script.witnessScriptHash.output.encode(bitcoin.crypto.sha256(witnessScript))
|
||||
const scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
|
||||
const address = bitcoin.address.fromOutputScript(scriptPubKey)
|
||||
].map((hex) => Buffer.from(hex, 'hex'))
|
||||
const { address } = bitcoin.payments.p2sh({
|
||||
redeem: bitcoin.payments.p2wsh({
|
||||
redeem: bitcoin.payments.p2ms({ m: 2, pubkeys })
|
||||
})
|
||||
})
|
||||
|
||||
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 = getAddress(keyPair)
|
||||
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey })
|
||||
|
||||
dhttp({
|
||||
method: 'GET',
|
||||
|
@ -137,7 +124,7 @@ describe('bitcoinjs-lib (addresses)', function () {
|
|||
const testnet = bitcoin.networks.testnet
|
||||
const keyPair = bitcoin.ECPair.makeRandom({ network: testnet, rng: rng })
|
||||
const wif = keyPair.toWIF()
|
||||
const address = getAddress(keyPair, testnet)
|
||||
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey, network: testnet })
|
||||
|
||||
assert.strictEqual(address, 'mubSzQNtZfDj1YdNP6pNDuZy6zs6GDn61L')
|
||||
assert.strictEqual(wif, 'cRgnQe9MUu1JznntrLaoQpB476M8PURvXVQB5R2eqms5tXnzNsrr')
|
||||
|
@ -146,7 +133,7 @@ describe('bitcoinjs-lib (addresses)', function () {
|
|||
it('can generate a Litecoin address', function () {
|
||||
const keyPair = bitcoin.ECPair.makeRandom({ network: LITECOIN, rng: rng })
|
||||
const wif = keyPair.toWIF()
|
||||
const address = getAddress(keyPair, LITECOIN)
|
||||
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey, network: LITECOIN })
|
||||
|
||||
assert.strictEqual(address, 'LZJSxZbjqJ2XVEquqfqHg1RQTDdfST5PTn')
|
||||
assert.strictEqual(wif, 'T7A4PUSgTDHecBxW1ZiYFrDNRih2o7M8Gf9xpoCgudPF9gDiNvuS')
|
||||
|
|
|
@ -5,12 +5,8 @@ const bip32 = require('bip32')
|
|||
const bip39 = require('bip39')
|
||||
const bitcoin = require('../../')
|
||||
|
||||
// TODO: remove
|
||||
const baddress = bitcoin.address
|
||||
const bcrypto = bitcoin.crypto
|
||||
function getAddress (node, network) {
|
||||
network = network || bitcoin.networks.bitcoin
|
||||
return baddress.toBase58Check(bcrypto.hash160(node.publicKey), network.pubKeyHash)
|
||||
return bitcoin.payments.p2pkh({ pubkey: node.publicKey, network }).address
|
||||
}
|
||||
|
||||
describe('bitcoinjs-lib (BIP32)', function () {
|
||||
|
|
|
@ -12,6 +12,7 @@ const bob = bitcoin.ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZs
|
|||
describe('bitcoinjs-lib (transactions w/ CLTV)', function () {
|
||||
// force update MTP
|
||||
before(function (done) {
|
||||
this.timeout(30000)
|
||||
regtestUtils.mine(11, done)
|
||||
})
|
||||
|
||||
|
|
|
@ -4,11 +4,8 @@ const assert = require('assert')
|
|||
const bitcoin = require('../../')
|
||||
const ecc = require('tiny-secp256k1')
|
||||
|
||||
// TODO: remove
|
||||
const baddress = bitcoin.address
|
||||
const bcrypto = bitcoin.crypto
|
||||
function getAddress (node) {
|
||||
return baddress.toBase58Check(bcrypto.hash160(node.publicKey), bitcoin.networks.bitcoin.pubKeyHash)
|
||||
function getAddress (node, network) {
|
||||
return bitcoin.payments.p2pkh({ pubkey: node.publicKey, network }).address
|
||||
}
|
||||
|
||||
// vG = (dG \+ sha256(e * dG)G)
|
||||
|
|
|
@ -5,14 +5,6 @@ const bitcoin = require('../../')
|
|||
const regtestUtils = require('./_regtest')
|
||||
const regtest = regtestUtils.network
|
||||
|
||||
// TODO: remove
|
||||
const baddress = bitcoin.address
|
||||
const bcrypto = bitcoin.crypto
|
||||
function getAddress (node, network) {
|
||||
network = network || bitcoin.networks.bitcoin
|
||||
return baddress.toBase58Check(bcrypto.hash160(node.publicKey), network.pubKeyHash)
|
||||
}
|
||||
|
||||
function rng () {
|
||||
return Buffer.from('YT8dAtK4d16A3P1z+TpwB2jJ4aFH3g9M1EioIBkLEV4=', 'base64')
|
||||
}
|
||||
|
@ -59,18 +51,22 @@ describe('bitcoinjs-lib (transactions)', function () {
|
|||
const alice2 = bitcoin.ECPair.makeRandom({ network: regtest })
|
||||
const aliceChange = bitcoin.ECPair.makeRandom({ network: regtest, rng: rng })
|
||||
|
||||
const alice1pkh = bitcoin.payments.p2pkh({ pubkey: alice1.publicKey, network: regtest })
|
||||
const alice2pkh = bitcoin.payments.p2pkh({ pubkey: alice2.publicKey, network: regtest })
|
||||
const aliceCpkh = bitcoin.payments.p2pkh({ pubkey: aliceChange.publicKey, network: regtest })
|
||||
|
||||
// give Alice 2 unspent outputs
|
||||
regtestUtils.faucet(getAddress(alice1, regtest), 5e4, function (err, unspent0) {
|
||||
regtestUtils.faucet(alice1pkh.address, 5e4, function (err, unspent0) {
|
||||
if (err) return done(err)
|
||||
|
||||
regtestUtils.faucet(getAddress(alice2, regtest), 7e4, function (err, unspent1) {
|
||||
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(getAddress(aliceChange, regtest), 1e4) // Alice's change
|
||||
txb.addOutput(aliceCpkh.address, 1e4) // Alice's change
|
||||
// (in)(4e4 + 2e4) - (out)(1e4 + 3e4) = (fee)2e4 = 20000, this is the miner fee
|
||||
|
||||
// Alice signs each input with the respective private keys
|
||||
|
@ -88,8 +84,9 @@ describe('bitcoinjs-lib (transactions)', function () {
|
|||
this.timeout(30000)
|
||||
|
||||
const keyPair = bitcoin.ECPair.makeRandom({ network: regtest })
|
||||
const p2pkh = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey, network: regtest })
|
||||
|
||||
regtestUtils.faucet(getAddress(keyPair, regtest), 2e5, function (err, unspent) {
|
||||
regtestUtils.faucet(p2pkh.address, 2e5, function (err, unspent) {
|
||||
if (err) return done(err)
|
||||
|
||||
const txb = new bitcoin.TransactionBuilder(regtest)
|
||||
|
@ -150,20 +147,16 @@ describe('bitcoinjs-lib (transactions)', function () {
|
|||
this.timeout(30000)
|
||||
|
||||
const keyPair = bitcoin.ECPair.makeRandom({ network: regtest })
|
||||
const pubKeyHash = bitcoin.crypto.hash160(keyPair.publicKey)
|
||||
const p2wpkh = bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey, network: regtest })
|
||||
const p2sh = bitcoin.payments.p2sh({ redeem: p2wpkh, network: regtest })
|
||||
|
||||
const redeemScript = bitcoin.script.witnessPubKeyHash.output.encode(pubKeyHash)
|
||||
const redeemScriptHash = bitcoin.crypto.hash160(redeemScript)
|
||||
const scriptPubKey = bitcoin.script.scriptHash.output.encode(redeemScriptHash)
|
||||
const address = bitcoin.address.fromOutputScript(scriptPubKey, regtest)
|
||||
|
||||
regtestUtils.faucet(address, 5e4, function (err, unspent) {
|
||||
regtestUtils.faucet(p2sh.address, 5e4, function (err, unspent) {
|
||||
if (err) return done(err)
|
||||
|
||||
const txb = new bitcoin.TransactionBuilder(regtest)
|
||||
txb.addInput(unspent.txId, unspent.vout)
|
||||
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4)
|
||||
txb.sign(0, keyPair, redeemScript, null, unspent.value)
|
||||
txb.sign(0, keyPair, p2sh.redeem.output, null, unspent.value)
|
||||
|
||||
const tx = txb.build()
|
||||
|
||||
|
@ -190,22 +183,21 @@ describe('bitcoinjs-lib (transactions)', function () {
|
|||
bitcoin.ECPair.makeRandom({ network: regtest }),
|
||||
bitcoin.ECPair.makeRandom({ network: regtest })
|
||||
]
|
||||
const pubKeys = keyPairs.map(function (x) { return x.publicKey })
|
||||
const pubkeys = keyPairs.map(x => x.publicKey)
|
||||
|
||||
const witnessScript = bitcoin.script.multisig.output.encode(3, pubKeys)
|
||||
const redeemScript = bitcoin.script.witnessScriptHash.output.encode(bitcoin.crypto.sha256(witnessScript))
|
||||
const scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
|
||||
const address = bitcoin.address.fromOutputScript(scriptPubKey, regtest)
|
||||
const p2ms = bitcoin.payments.p2ms({ m: 3, pubkeys, network: regtest })
|
||||
const p2wsh = bitcoin.payments.p2wsh({ redeem: p2ms, network: regtest })
|
||||
const p2sh = bitcoin.payments.p2sh({ redeem: p2wsh, network: regtest })
|
||||
|
||||
regtestUtils.faucet(address, 6e4, function (err, unspent) {
|
||||
regtestUtils.faucet(p2sh.address, 6e4, function (err, unspent) {
|
||||
if (err) return done(err)
|
||||
|
||||
const txb = new bitcoin.TransactionBuilder(regtest)
|
||||
txb.addInput(unspent.txId, unspent.vout)
|
||||
txb.addInput(unspent.txId, unspent.vout, null, p2sh.output)
|
||||
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 3e4)
|
||||
txb.sign(0, keyPairs[0], redeemScript, null, unspent.value, witnessScript)
|
||||
txb.sign(0, keyPairs[2], redeemScript, null, unspent.value, witnessScript)
|
||||
txb.sign(0, keyPairs[3], redeemScript, null, unspent.value, witnessScript)
|
||||
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()
|
||||
|
||||
|
@ -235,12 +227,14 @@ describe('bitcoinjs-lib (transactions)', function () {
|
|||
|
||||
tx.ins.forEach(function (input, i) {
|
||||
const keyPair = keyPairs[i]
|
||||
const prevOutScript = bitcoin.address.toOutputScript(getAddress(keyPair))
|
||||
const scriptSig = bitcoin.script.pubKeyHash.input.decode(input.script)
|
||||
const ss = bitcoin.script.signature.decode(scriptSig.signature)
|
||||
const hash = tx.hashForSignature(i, prevOutScript, ss.hashType)
|
||||
const p2pkh = bitcoin.payments.p2pkh({
|
||||
pubkey: keyPair.publicKey,
|
||||
input: input.script
|
||||
})
|
||||
|
||||
const ss = bitcoin.script.signature.decode(p2pkh.signature)
|
||||
const hash = tx.hashForSignature(i, p2pkh.output, ss.hashType)
|
||||
|
||||
assert.strictEqual(scriptSig.pubKey.toString('hex'), keyPair.publicKey.toString('hex'))
|
||||
assert.strictEqual(keyPair.verify(hash, ss.signature), true)
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Add table
Reference in a new issue