Bitcoinjs-lib: How to spend from a P2SH or P2SH(P2WSH) that uses a custom script ?

Created on 13 Oct 2018  路  7Comments  路  Source: bitcoinjs/bitcoinjs-lib

For educational purposes, i created two address using a custom script

let network = bitcoinjs.networks.testnet
let OP_INT_BASE = bitcoinjs.opcodes.OP_RESERVED
let output = bitcoinjs.script.compile([].concat(
            bitcoinjs.opcodes.OP_ADD,
            OP_INT_BASE + 5,
            bitcoinjs.opcodes.OP_EQUAL))
const p2wsh = bitcoinjs.payments.p2wsh({redeem: {output: output, network: network}, network: network})
const p2wshInP2sh = bitcoinjs.payments.p2sh({redeem: p2wsh, network: network})
console.log(p2wshInP2sh.address) //2MwnRrQxKhCdr8e3vbL7ymhtzQFYPTx9xww
const p2sh = bitcoinjs.payments.p2sh({redeem: {output: output, network: network}, network: network})
console.log(p2sh.address) //2N7WfHK1ftrTdhWej8rnFNR7guhvhfGWwFR

When trying to broadcast a transaction that spends from them, i get a validation error for the inputs am spending

let network = bitcoinjs.networks.testnet
let transactionBuilder = new bitcoinjs.TransactionBuilder(network)
transactionBuilder.addOutput("2MsVQkDHmP6QBZouY6p8SeGjETnyoddt1D9", 1000)
let outputScript = bitcoinjs.script.fromASM("OP_0 OP_2 OP_3")
transactionBuilder.addInput("b5b3efcf397505cfa55a7c0607deb067429d74c73969e917fe48c061101f61d3", 0)
transactionBuilder.addInput("f9ea94ac11d3f2873fbb2dc28267f0387e1aac020aac1247211581bcb21df6a5", 0)
let tx = transactionBuilder.buildIncomplete()
tx.setWitness(0,[outputScript])
tx.setInputScript(1,outputScript)
console.log(tx.toHex())//02000000000102d3611f1061c048fe17e96939c7749d4267b0de07067c5aa5cf057539cfefb3b50000000000ffffffffa5f61db2bc8115214712ac0a02ac1a7e38f06782c22dbb3f87f2d311ac94eaf90000000003005253ffffffff01e80300000000000017a91402aecda401bc6f3f2342b0e92b2eb49d5eee56b38701030052530000000000

I took a look at the transaction tests + fixtures and tried some changes in the inputs, but i don't seems to get it right

Thank you

All 7 comments

you're setting your witness as the witnessScript / redeemScript.

also, segwit requires everything to be Pushdata in the witness, so OP_2 etc. is not valid, you need OP_PUSHDATA(1byte) 0x02 instead. OP_ADD will treat it as 2.

This should work:

const bitcoinjs = require('bitcoinjs-lib')
let network = bitcoinjs.networks.testnet
let OP_INT_BASE = bitcoinjs.opcodes.OP_RESERVED
let output = bitcoinjs.script.compile([].concat(
            bitcoinjs.opcodes.OP_ADD,
            OP_INT_BASE + 5,
            bitcoinjs.opcodes.OP_EQUAL))
const p2wsh = bitcoinjs.payments.p2wsh({redeem: {output: output, network: network}, network: network})
const p2wshInP2sh = bitcoinjs.payments.p2sh({redeem: p2wsh, network: network})
console.log(p2wshInP2sh.address)
const p2sh = bitcoinjs.payments.p2sh({redeem: {output: output, network: network}, network: network})
console.log(p2sh.address)

let transactionBuilder = new bitcoinjs.TransactionBuilder(network)
transactionBuilder.addOutput("2MsVQkDHmP6QBZouY6p8SeGjETnyoddt1D9", 1000)
transactionBuilder.addInput("b5b3efcf397505cfa55a7c0607deb067429d74c73969e917fe48c061101f61d3", 0)
transactionBuilder.addInput("f9ea94ac11d3f2873fbb2dc28267f0387e1aac020aac1247211581bcb21df6a5", 0)
let tx = transactionBuilder.buildIncomplete()

let scriptSigForP2WSHInP2SH = bitcoinjs.script.compile([p2wsh.output])

let scriptSigForSimpleP2SH = bitcoinjs.script.compile([OP_INT_BASE + 2, OP_INT_BASE + 3, p2sh.redeem.output])

let witnessStackForP2WSHInP2SH = [Buffer.from('02','hex'), Buffer.from('03','hex'), p2wsh.redeem.output]

tx.setInputScript(0, scriptSigForP2WSHInP2SH)
tx.setWitness(0, witnessStackForP2WSHInP2SH)

tx.setInputScript(1, scriptSigForSimpleP2SH)

console.log(tx.toHex())

@dabura667 @junderw thank you a lot
The example is perfectly self describing
Cheers

Can someone explain the use of OP_INT_BASE or point me to some resource please?
Why not writing bitcoin.opcodes.OP_5 as it produces the same 0x55 hex value?

It's the same thing.

OPT_INT_BASE is just 0x50

so + 5 is 0x55

or just use OP_5 which is 0x55

or just write 85, which is 0x55 in base10.

there's no special meaning

Ok, thanks a lot!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

silence-may picture silence-may  路  3Comments

zhaozhiming picture zhaozhiming  路  3Comments

Mr-Mondragon picture Mr-Mondragon  路  3Comments

ishwarchandratiwari picture ishwarchandratiwari  路  3Comments

hoshsadiq picture hoshsadiq  路  3Comments