2

I want to check the payment paid by the user in the chain and add it to database.

Frontend:

  const transactionString =
      "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEDyIchCFWi8XOQK9v26xdqOA6+Nh0PxppQs5xbNaKQd7/0i+hG2L1v22b2JWcGVBnJMaqEN3yadwu9twp/uzdQZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4VWxeJUJXETqt/CGxFeYTUs45eWde5bOPqThLZxVqEcBAgIAAQwCAAAAAOH1BQAAAAA=";

    const tx = Transaction.from(Buffer.from(transactionString, "base64"));
    tx.feePayer = anchorWallet.publicKey;

    await anchorWallet.signTransaction(tx);
    const signedData = tx.serialize().toString("base64");

    console.log(signedData);
    // AT9nK/UKWz+T/vhsli/hYVANRlVctUEPjJp+myjfeLNJqM5h982cyrQqbGlRnn/x3WwpJjOR3rI3JaxWfzuq+AUBAAEDyIchCFWi8XOQK9v26xdqOA6+Nh0PxppQs5xbNaKQd7/0i+hG2L1v22b2JWcGVBnJMaqEN3yadwu9twp/uzdQZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4VWxeJUJXETqt/CGxFeYTUs45eWde5bOPqThLZxVqEcBAgIAAQwCAAAAAOH1BQAAAAA=

i send the signedData to the backend

app.post("/:publicKey/pay", async (c) => {
  const publicKey = new PublicKey(c.req.param("publicKey"));
  const tx = Transaction.from(Buffer.from(await c.req.text(), "base64"));

  const {
    value: { blockhash },
  } = await connection.getLatestBlockhashAndContext();

  tx.recentBlockhash = blockhash;

  const signature = await connection.sendRawTransaction(tx.serialize());
})

and I get the error "Trace: Signature verification failed". How can I solve this problem? Don't you already have the necessary signatures in the Transaction?

1 Answer 1

3

You need to do it in this order:

  1. Attach recent blockhash
  2. Sign transaction

You're doing it backwards, which will fail signature verification. This is because the recent blockhash is part of the message data being signed.

I'm not 100% sure, but it seems like the anchorWallet.signTransaction call in your frontend is already fetching the recent blockhash for you. So I think you can simply remove the assignment of the recent blockhash that you have in your backend, and you should be good.

2
  • Thank you, it worked. So one more question, so that I can't use this signed transaction over and over again (because it's a vulnerability), how does the blockchain solve it?
    – tolgaandx
    Commented Oct 20, 2022 at 9:10
  • I don't know the exact details of the mechanism, but I do know that the Transaction Processing Unit (TPU) performs transaction deduplication. I imagine it's doable simply by caching recent transaction signatures in a hash-set, and comparing all inbound transactions to that set. For an inquisitive mind such as yours, I'd highly recommend taking a peak at the Solana source code!
    – HelmetFace
    Commented Oct 20, 2022 at 16:43

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.