0

I would like to test that a public key that doesn't own a PDA can't alter its data. I'm doing as follows:

  1. Generate a new keypair for user2 (user1 is the pubkey of the local wallet on Anchor's workspace) with:
// This works as expected
const user2 = anchor.web3.Keypair.generate();

const [user2Pda] = anchor.web3.PublicKey.findProgramAddressSync(
  [user2.publicKey.toBuffer()],
  program.programId
);
  1. Then, I try to initialize the second user account just like I did to the first one, which worked correctly:
// This fails
const _tx = await program.methods
    .initializeUser(user2Data.name, user2Data.imgPath)
    .accounts({
      user: user2Pda,
      signer: user2.publicKey
     })
     .rpc();

But it fails with error:

Error: Signature verification failed.
Missing signature for public key [<the key>].

My guess is that the pubkey that should be the signer of the transaction (user2's) is not the one doing the transaction, which I think is the local wallet's pubkey (user1's). So how can I achieve this, to be able to use another wallet within Anchor tests?

Because if I simply don't initialize the second user account on chain and try to change the data on an account that it doesn't own as follows:

const _tx = await program.methods
      .updateUser("new name", "new name")
      .accounts({
        user: user1Pda,
        signer: user2.publicKey
      })
      .rpc();

I get the message Error: Signature verification failed, which doesn't seem to be the correct error to receive (I expected some constraint violation, an Error that is an instance of AnchorError).

Also, if any of my thoughts are wrong, please correct me, I'll be happy to know :)

EDIT: after adding the new wallet as signer (see below) you need to airdrop some lamports to the second user keypair, so that it can pay for the transaction!!!

1 Answer 1

2

TLDR: you need to provide signature of the user2 to the call. Before calling .rpc() use method .signers([user2]).

The error Error: Signature verification failed comes not from the on-chain program as you expect but it's a verification held on the client side (@solana/web3.js library) before the transaction is sent to blockchain.

The process is like following: the Anchor on chain program declares what account has to sign the transaction (with pub signer: Signer<'info> or similar), an IDL json file is generated, based on this IDL the Anchor TypeScript client is capable to understand what accounts are required to call the particular transactions (i.e., here the user and signer is provided). With all of this information the Anchor library generates transaction data (in form of JSON https://medium.com/@asmiller1989/solana-transactions-in-depth-1f7f7fe06ac2#f4cb) that the web3.js methods utilize to understand if all required signatures were provided. As the Anchor program requires the signer public key to sign the transaction it is needed to get provided the keypair of the pubkey (user2.publicKey) to get signed.

0

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.