2

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.

1 Answer 1

1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.