Cannot sign txn with change address using bitcoinjs-lib psbt

0

I am having a difficult time figuring out how to sign a spend from a change address. I get Error: cannot sign for this input with the key <value>. The initial transaction works fine, where I generate a transaction with multiple inputs to two outputs, one of them being the change address - it is the same as the spender addresses. Here are the steps: 1) I grab all UTXO for our spending address.

const unspentTx = (await listUnspentTxByAddresses([mainAddress])).data.result;

2) I add all inputs and outputs, sign, finalize, and submit.

  const fee = new BigNumber((await getEstimateSmartFee(2)).data.result.feerate)
    .times(100000000)
    .div(3);

  const output = {
    address: destinationAddress,
    value: parseInt(pullAmount.minus(fee).toFixed(0)),
  };

  const senderBalance = sum
    .times(100000000)
    .minus(pullAmount)
    .minus(fee);

  const change = {
    address: sender,
    value: parseInt(senderBalance.toString()),
  };

  // Adding the output
  psbt.addOutput(output);
  psbt.addOutput(change);

  for (let i = 0; i < txids.length; i++) {
    const transactionObject = await getTransaction(txids[i]);

    const input = {
      hash: txids[i],
      index: 0,
      nonWitnessUtxo: Buffer.from(transactionObject.data.result.hex, 'hex'),
    };

    try {
      psbt.addInput(input);
    } catch (e) {
      console.log('Add Input Failed e =>', e);
      return null;
    }
  }

  const key = bitcoin.ECPair.fromWIF(privateKey, testnet);

  for (let i = 0; i < txids.length; i++) {
    psbt.signInput(i, key);
  }

  psbt.finalizeAllInputs();

  const rawTx = psbt.extractTransaction().toHex();

  const withdrawPendingTx = await sendRawTransaction(rawTx);

This works the first time around, but as mentioned, the second time I call await listUnspentTxByAddresses([mainAddress]) and follow the same exact procedure, the js library validation prevents signing with the main address key. It doesn't seem to make sense, so I hope there is an obvious error here. I'm pretty sure it's sent as a default P2PKH with SigHashAll.

GViz

Posted 2019-11-15T02:51:19.657

Reputation: 23

Answers

0

Simple solution! index in input object was hardcoded to 0 instead of taking the vout nonce from UTXO list. I was going to delete, but I'll leave the post up.

GViz

Posted 2019-11-15T02:51:19.657

Reputation: 23