LedgerJS - How to P2SH sign multiple transactions from multiple wallets in 1 function call?

0

First some explanation

I have made 2 raw transactions via Electrum using my Nano S Ledger as seed and exported them to .txn files.

let rawTx1 = "02000000000101bf00f7aca2e0d393ad0a762224ad4cd5a10d9950804fbc5a22fe970918301179000000001716001400ce8131595e014b45ec6ca49495d547ab8bd872fdffffff02a08601000000000017a91457fd0d41e459a4227b8932327786cf512d99399987bc72ca...";
let rawTx2 = "02000000000101bf00f7aca2e0d393ad0a762224ad4cd5a10d9950804fbc5a22fe970918301179000000001716001400ce8131595e014b45ec6ca49495d547ab8bd872fdffffff02a08601000000000017a914a66dff1bf27dd1a5944b5bc9ff2b0f410efb64cd87bc72ca...";

Then I turned them into UTXO objects using the splitTransaction() function:

const UTXO1 = await btc.splitTransaction(rawTx1, true);
const UTXO2 = await btc.splitTransaction(rawTx2, true);

Next, I get the Wallet public keys I used for these transactions:

const wallet_1 = await btc.getWalletPublicKey("m/49'/1'/1'", false, true);
const wallet_2 = await btc.getWalletPublicKey("m/49'/1'/2'", false, true);

So transaction 1 was made with wallet 1 and transaction 2 with wallet 2. According to LedgerJS, I have to respect that order when calling the signP2SH() function:

btc.signP2SHTransaction([[UTXO1, 1, wallet_1.publicKey], [UTXO2, 1, wallet_2.publicKey]],
    ["m/49'/1'/1'", "m/49'/1'/2'"],
    btc.serializeTransactionOutputs(???).toString('hex')
);

Here,

[UTXO1, 1, wallet_1.publicKey]

are the Transaction object, output index, and redeem script in that order. And

["m/49'/1'/1'", "m/49'/1'/2'"]

are the derivation paths of both of my wallets.

My question is about the third line:

btc.serializeTransactionOutputs(???).toString('hex')

I know for a single transaction from a single wallet, I just toss in the UTXO1 in there:

btc.serializeTransactionOutputs(UTXO1).toString('hex')

But now that I have multiple UTXO's, I don't know what to fill in there anymore. Any ideas?

EDIT

Thanks to @Pierre Pollastri's answer I figured out the hashed script form.

So this code

const outputScript1 = btc.serializeTransactionOutputs(UTXO1).toString('hex')
const outputScript2 = btc.serializeTransactionOutputs(UTXO2).toString('hex')

produces the Output script for both UTXO's. Since we are processing two transactions we need to merge these output scripts. These scripts look as follows:

outputScript1 = 02404b4c000000000017a914c436f95c2ab5062dbc884a7c76ac805b58c00fe5879eaa7f000000000017a914429b7a8975c97dad6f90604faf732d9c7045279a87
outputScript2 = 02404b4c000000000017a914c436f95c2ab5062dbc884a7c76ac805b58c00fe587ee337e000000000017a914284c4c58d659cd485a283b48b4dc79da7571043587

They both start with 02, which indicates that each script handles 2 transactions. So what I did was simply change 02 into 04, remove the 02 from the 2nd script and then concatenate the 2nd script after the 1st script:

finalScript = 04404b4c000000000017a914c436f95c2ab5062dbc884a7c76ac805b58c00fe5879eaa7f000000000017a914429b7a8975c97dad6f90604faf732d9c7045279a87404b4c000000000017a914c436f95c2ab5062dbc884a7c76ac805b58c00fe587ee337e000000000017a914284c4c58d659cd485a283b48b4dc79da7571043587

Then call the function as stated above:

btc.signP2SHTransaction([[UTXO1, 1, wallet_1.publicKey], [UTXO2, 1, wallet_2.publicKey]],
    ["m/49'/1'/1'", "m/49'/1'/2'"],
    finalScript
);

It worked and I was able to sign the transaction :)

CoderApprentice

Posted 2019-03-24T12:18:23.290

Reputation: 27

Answers

1

The third parameter is just your outputs script (actually it's the whole outputs part of a transaction) so depending on which address you want to send the funds it will change.

It's using the same format as in bitcoin transactions. The data are serialized like this

TYPE | Description VARINT | Number of outputs to create 8 byte | Amount to send to the first output VARINT | Size of the output script x bytes | The actual output script

In most case you can consider that VARINT is only 1 byte (special cases if you data is bigger than 255 bytes but if that's the case you probably have an issue somewhere :P)

Regarding the output script depending on which address you want to send you have different type of scripts to use.

btc.serializeTransactionOutputs(???).toString('hex') is just serializing the outputs part of the transaction from a split transaction. If you use it on an existing transaction you're basically sending to the same addresses (the same amounts to the same addresses).

Pierre Pollastri

Posted 2019-03-24T12:18:23.290

Reputation: 26