Bitcoinjs-lib: Creating unsigned transactions

Created on 26 Feb 2018  路  4Comments  路  Source: bitcoinjs/bitcoinjs-lib

Hello, I'm trying to create an unsigned transaction trying to emulate what is done here: https://coinb.in/#newTransaction.

The code below works almost perfectly:

// Function used to build a new unsigned transaction
function buildTransaction(inputs, outputs){
    var txBuilder = new bitcoin.TransactionBuilder(bitcoin.networks.bitcoin)
    for(var i = 0; i < inputs.length; i++){
        var input = inputs[i]
        txBuilder.addInput(input.txid, input.vout, 0xffffffff, Buffer.from(input.scriptPubKey, 'hex'))
    }

    for(var i = 0; i < outputs.length; i++){
        var output = outputs[i]
        txBuilder.addOutput(output.address, output.amount)
    }
    return txBuilder.buildIncomplete().toHex()
}

When comparing the resulting hex however I get something slightly different. To be specific, the input script is not being serialized.

Here are the details of the transaction I'm trying to build:

Input
1Lix81GCLu1aPQyuJaKc1939xmT34UREuN

Output1
1H1cnxyaLsVpeFygfMa2BwERBX3vBQFArU,0.2

Output2
1648hXsCNRsCBhgh2st5YiBAXh9sK2Td6w,0.01000

Change
1H1cnxyaLsVpeFygfMa2BwERBX3vBQFArU,0.2

And here are the resulted serializations with spaces separating the tx fields. TxBuilder is the name of my code.

Coinb.in
01000000 01 883c77e0dd54fef2c9f6e3dde4155c5128d39b01c5d5b71dffb6afd7001694f0 00000000 19 76a914d85974f276aecaca262aed5c91145186fa32df4988ac ffffffff 03 002d310100000000 19 76a914af9fe3ff6b59997f014228a25c0382016e2ff08f88ac ca046f0300000000 19 76a914af9fe3ff6b59997f014228a25c0382016e2ff08f88ac 40420f0000000000 19 76a91437704dafd4db3195de854127921c0ad05476f74188ac 00000000
TxBuilder
01000000 01 883c77e0dd54fef2c9f6e3dde4155c5128d39b01c5d5b71dffb6afd7001694f0 00000000 00                                                    fffffffd 03 002d310100000000 19 76a914d85974f276aecaca262aed5c91145186fa32df4988ac e803000000000000 19 76a91437704dafd4db3195de854127921c0ad05476f74188ac ca046f0300000000 19 76a914af9fe3ff6b59997f014228a25c0382016e2ff08f88ac 00000000

As you can see, the only thing missing here is the locking script of the previous tx output.

I am currently fixing this by modifying lines 460-465 of the transaction_builder.js file like this:

  return {
    type: scriptType,
    // script: bscript.compile(sig),
    script: input.prevOutScript,
    witness: witness
  }

But this is an ugly hack which is most likely breaking the signed tx serialization. Moreover, since I am not familiar with this library, I'm afraid I might be missing something here; maybe there is a flag somewhere that would allow me to do exactly what I want without having to modify the library's code.

If there is not, I think this situation should be addressed, don't you? I'd suggest checking if the signature is present before calling bscript.compile(sig).

how to / question / docs

All 4 comments

This is because the scriptPubkey is being serialized at signing.

There is no standard for partially signed / unsigned transaction serialization........ but IMO we shouldn't bend over backward to match against a single website.

// Function used to build a new unsigned transaction
function buildTransaction(inputs, outputs){
    var txBuilder = new bitcoin.TransactionBuilder(bitcoin.networks.bitcoin)
    for(var i = 0; i < inputs.length; i++){
        var input = inputs[i]
        txBuilder.addInput(input.txid, input.vout, 0xffffffff, Buffer.from(input.scriptPubKey, 'hex'))
    }

    for(var i = 0; i < outputs.length; i++){
        var output = outputs[i]
        txBuilder.addOutput(output.address, output.amount)
    }
    var tx = txBuilder.buildIncomplete()
    for(var i = 0; i < inputs.length; i++){
        var input = inputs[i]
        tx.ins[i].script = Buffer.from(input.scriptPubKey, 'hex')
    }
    return tx.toHex()
}

This is a workaround that doesn't need to touch bitcoinjs-lib source.

To be specific, the input script is not being serialized.

What input script? You haven't signed anything!
It appears that coinb.in is using the input script to transport the prev output script?
That is non-standard and misleading.

I recommend looking at PBST (BIP174) for an actual proposal of a format that we could use to help resolve this situation (unsigned transaction communication).

What input script? You haven't signed anything!
It appears that coinb.in is using the input script to transport the prev output script?
That is non-standard and misleading.

You're right, they seem to be sending the scriptPubKey of the previous transaction where this transaction's scriptSig should be.

I recommend looking at PBST (BIP174) for an actual proposal of a format that we could use to help resolve this situation (unsigned transaction communication).

It would be indeed good to have a common standard for this, I know electrum does it differently. Or maybe they follow the standard you pointed out, I don't know, haven't checked their serialization format just yet.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tuyennvtb picture tuyennvtb  路  3Comments

Beardcoding picture Beardcoding  路  3Comments

LeonYanghaha picture LeonYanghaha  路  3Comments

namnv04 picture namnv04  路  3Comments

ghost picture ghost  路  3Comments