Solanaの「Signature verification failed」エラー

Anchorでアカウント作成(init)を2つ同時実施したときのエラー

現象

anchor testすると以下のエラー。

ターミナル

 hello
    1) Creates a vault


  0 passing (156ms)
  1 failing

  1) hello
       Creates a vault:
     Error: Signature verification failed
      at Transaction.serialize (node_modules/@solana/web3.js/src/transaction.ts:736:13)
      at AnchorProvider.sendAndConfirm (node_modules/@project-serum/anchor/src/provider.ts:145:22)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)
      at MethodsBuilder.rpc [as _rpcFn] (node_modules/@project-serum/anchor/src/program/namespace/rpc.ts:29:16)

lib.rs

use anchor_lang::prelude::*;

declare_id!("6KzWJqAvnZhDZDkd69N6oVy7ySVsXDMM2B7UfQynEpf4");

#[program]
pub mod hello {
    use super::*;

    pub fn create(ctx: Context<Create>, authority: Pubkey) -> Result<()> {
        let vault = &mut ctx.accounts.vault;
        vault.authority = authority;
        vault.count = 0;
        Ok(())
    }
}

#[derive(Accounts)]
pub struct Create<'info> {
    #[account(init, payer = user, space = 8 + 40)]
    pub vault: Account<'info, Vault>,
    #[account(mut)]
    pub user: Signer<'info>,
    pub system_program: Program<'info, System>,

    #[account(init, payer = user, space = 8 + 40)]
    pub vault2: Account<'info, Vault2>,
}

#[account]
pub struct Vault {
    pub authority: Pubkey,
    pub count: u64,
}

#[account]
pub struct Vault2 {
    pub authority: Pubkey,
    pub count: u64,
}

tests/hello.ts

import * as anchor from "@project-serum/anchor";
import { Program } from "@project-serum/anchor";
import { Hello } from "../target/types/hello";
import { assert } from 'chai';

describe("hello", () => {
  // Configure the client to use the local cluster.
  anchor.setProvider(anchor.AnchorProvider.env());
  const program = anchor.workspace.Hello as Program<Hello>;
  const provider = anchor.AnchorProvider.local();

  const vault = anchor.web3.Keypair.generate();
  const vault2 = anchor.web3.Keypair.generate();
  console.log(vault.publicKey.toString());
  console.log(vault2.publicKey.toString());


  it("Creates a vault", async () => {
    await program.methods
    .create(
      provider.wallet.publicKey
    )
    .accounts({
      vault: vault.publicKey,
      user: provider.wallet.publicKey,
      systemProgram: anchor.web3.SystemProgram.programId,
      vault2: vault2.publicKey,
    })
    .signers([vault])
    .rpc()

    let vaultAccount = await program.account.vault.fetch(vault.publicKey);

    assert.ok(vaultAccount.authority.equals(provider.wallet.publicKey));
    assert.ok(vaultAccount.count.toNumber() === 0);
  });
});

原因

2つ目のアカウントを作成するためのSignerが足りていないため。

対応

Signersに2つ目のアカウントを作成するためのKeypairを渡す。

tests/hello.ts

  const vault = anchor.web3.Keypair.generate();
  const vault2 = anchor.web3.Keypair.generate();

    〜〜〜省略〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

    .accounts({
      vault: vault.publicKey,
      user: provider.wallet.publicKey,
      systemProgram: anchor.web3.SystemProgram.programId,
      vault2: vault2.publicKey,
    })
    .signers([vault, vault2]) // ← ここに2つ目(vault2)を追加

@solana/spl-tokenのmintToしたときのエラー

@solana/spl-token v0.2.0で、mintToしたときに発生したエラー。

現象

anchor testを実行すると以下のエラーが発生。
(エラー発生箇所は、Anchorとは関係なく、Solanaのjs「spl-token」で発生)

ターミナル:

  escrow
    1) Initialise escrow state


  0 passing (2s)
  1 failing

  1) escrow
       Initialise escrow state:
     Error: Signature verification failed
      at Transaction.serialize (node_modules/@solana/web3.js/src/transaction.ts:736:13)
      at Connection.sendTransaction (node_modules/@solana/web3.js/src/connection.ts:4426:41)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)
      at sendAndConfirmTransaction (node_modules/@solana/web3.js/src/util/send-and-confirm-transaction.ts:31:21)

escrow.ts(抜粋):

  const payer = Keypair.generate();
  const mintAuthority = Keypair.generate();

      const mintA = await createMint(
      connection, // connection
      payer, // payer
      mintAuthority.publicKey, // mintAuthority
      null, // freezeAuthority
      9 // decimals
    );

    const mintATx = await mintTo(
      connection, // connection
      payer, // payer
      mintA, // mint
      initializerTokenAccountA.address, // destination
      mintAuthority.publicKey, // authority
      initializerAmount, // amount
      [] // signer(s)
    );

原因

authorityがpayerと異なる場合は、Keypairの指定が必要っぽい?
もし、 payer = authority だと、publicKeyの指定でも大丈夫だった。

solana-program-library/mintTo.ts のパラメータ

「authority: Signer | PublicKey,」とあるが、テストコードでは

solana-program-library/mint.test.ts のテストコード

「let mintAuthority: Keypair;」となっていて、KeyPairを渡していた。

対応

authorityにKeypairを渡すようにして解決。

escrow.ts(抜粋):

  const payer = Keypair.generate();
  const mintAuthority = Keypair.generate();

      const mintA = await createMint(
      connection, // connection
      payer, // payer
      mintAuthority.publicKey, // mintAuthority
      null, // freezeAuthority
      9 // decimals
    );

    const mintATx = await mintTo(
      connection, // connection
      payer, // payer
      mintA, // mint
      initializerTokenAccountA.address, // destination
      mintAuthority, // authority ← Keypairを渡すようにした
      initializerAmount, // amount
      [] // signer(s)
    );