1

I have a transaction that uses 2 signers(the user and the Keypair from the backend). It signs from the Backend and returns a serialized transaction for the user to sign. However, I am getting this Error

`Error: failed to send transaction: Transaction signature verification failure

at Connection.sendEncodedTransaction(node_modules/@solana/web3.js/src/connection.ts:5054:13)

at processTicksAndRejections(node:internal/process/task_queues:96:5) 

at Connection.sendRawTransaction(node_modules/@solana/web3.js/src/connection.ts:5013:20)`.

This is my code snippet

  const tx = await program.methods.create(new anchor.BN(3))
  .accounts({
    payer: provider.wallet.publicKey,
    backend: backend.publicKey,
    systemProgram: SystemProgram.programId
  }).transaction();

  tx.recentBlockhash = (
    await program.provider.connection.getLatestBlockhash()
  ).blockhash;

  tx.sign(backend);
  const serializedTx = tx.serialize({ requireAllSignatures: false });

  // Deserialize it and then sign with provider wallet
  let recoveredTransaction: Transaction | undefined = Transaction.from(Buffer.from(serializedTx));
  
  recoveredTransaction = await provider.wallet.signTransaction(recoveredTransaction);
  recoveredTransaction.feePayer = provider.wallet.publicKey;

  const final_tx =
      (await provider.connection.sendRawTransaction(
          recoveredTransaction.serialize({ verifySignatures: false, requireAllSignatures: false }),
      ));

  await provider.connection.confirmTransaction(final_tx, "confirmed");
2
  • try using tx.partialSign(backend) that should help
    – Pratik.js
    Commented Nov 23, 2022 at 14:53
  • using tx.partialSign produces the same output, I have posted my findings to the root cause of the problem below Commented Nov 24, 2022 at 14:17

2 Answers 2

2

You cannot modify the transaction at all after signing it. Adding the instructions, setting the feepayer, and setting the blockhash need to be done prior to any signatures.

Signing the transaction should be the last step before sending it to RPC.

1
  • Is it possible to have an arbitrary number of signers for a given transaction? Or, by contrary, only the required signers can/must sign? Commented Feb 9 at 23:33
2

The root cause of this Error seems to be that when the backend signs the transaction, If a feePayer was not specified, the transaction automatically sets the feePayer to the backend publickey. Hence when the feePayer is later modified to the user publickey and the user signs the transaction after deserializing the transaction data, It seems the transaction data is also changed and does not produce the same Initial serialized transaction which consequently causes the Error: failed to send transaction: Transaction signature verification failure error.

The Error is easily fixed by specifying the feePayer before Signing the transaction.

  tx.recentBlockhash = (
    await program.provider.connection.getLatestBlockhash()
  ).blockhash;
  tx.feePayer = provider.wallet.publicKey // specify the feepayer before signing

  tx.sign(backend);
  const serializedTx = tx.serialize({ requireAllSignatures: false });

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.