Pubkey的序列化是borsh-js和borsh-rs的区别

The serialize of Pubkey are difference between borsh-js and borsh-rs

我在js中序列化了一个pubkey(solana account publickey),用borsh rust,但是在js中输出的长度是4个字节,而在js客户端中的pubkey是一个长度为44字节的字符串,但是是rust程序中一个32字节的公钥,没有前面的4字节长度,如何序列化为一样?

在 JS 中:

class MintAccount extends Assignable { }
 console.log(MintAccount);
 const SCHEMA = new Map([
 [
   MintAccount,
   {
     kind: 'struct',
     fields: [
       ['tag', 'u8'],
       ['authority','string'],
       ['supply', 'u64']
     ],
   },
 ]
]);
console.log(feePayer.publicKey.toString());
let mintAccount = new MintAccount({tag:1,7xiHVn7EeQwbsPrAtaY3aokHekYTrURsgzReFxd1JeVR,supply:0})
let accountDataBuffer = borsh.serialize(SCHEMA, mintAccount);
console.log(accountDataBuffer);

在 RUST 中: 在 states.rs

#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq)]
pub enum AccountTag {
    Uninitialized,
    Mint,
    TokenAccount,
}

#[derive(BorshSerialize, BorshDeserialize, Debug, Clone)]
pub struct Mint {
    pub tag: AccountTag,
    pub authority: Pubkey,
    pub supply: u64,
}

impl Mint {
    pub fn load_unchecked(ai: &AccountInfo) -> Result<Self, ProgramError> {
        msg!("ai:, {:?}, {:?}",ai,ai.data.borrow());
        Ok(Self::try_from_slice(&ai.data.borrow())?)
    }

    fn validate(&self) -> ProgramResult {
        if self.tag != AccountTag::Mint {
            return Err(ProgramError::InvalidAccountData);
        }
        Ok(())
    }

    pub fn load(ai: &AccountInfo) -> Result<Self, ProgramError> {
        let mint = Self::try_from_slice(&ai.data.borrow())?;
        mint.validate()?;
        Ok(mint)
    }

    pub fn save(&self, ai: &AccountInfo) -> ProgramResult {
        Ok(self.serialize(&mut *ai.data.borrow_mut())?)
    }
}

在processor.rs

impl Processor {
    pub fn process_instruction(
        _program_id: &Pubkey,
        accounts: &[AccountInfo],
        instruction_data: &[u8],
    ) -> ProgramResult {
        let instruction = TokenInstruction::try_from_slice(instruction_data)
            .map_err(|_| ProgramError::InvalidInstructionData)?;
        let accounts_iter = &mut accounts.iter();
        match instruction {
            TokenInstruction::InitializeMint => {
                msg!("Instruction:  ,{:?}",instruction);
                let mint_ai = next_account_info(accounts_iter)?;
                msg!("mint_ai:  ,{:?}",mint_ai);
                let mint_authority = next_account_info(accounts_iter)?;
                msg!("mint_authority:  ,{:?},{:?}",mint_authority,*mint_authority.key);
                let mut mint = Mint::load_unchecked(mint_ai)?;
                msg!("mint:  ,{:?}",mint);
                assert_with_msg(
                    mint_authority.is_signer,
                    ProgramError::MissingRequiredSignature,
                    "Mint Authority must sign",
                )?;
                // TODO
                mint.tag = AccountTag::Mint;
                mint.authority = *mint_authority.key;
                mint.supply = 0;
                 
                msg!("NewMint:  ,{:?},{:?},{:?}",mint,mint_ai.data,&mut &mut mint_ai.data.borrow_mut()[..]);
                // mint.serialize(&mut &mut mint_ai.data.borrow_mut()[..])?;
                mint.save(mint_ai)?;  `

相同的参数,输出结果不同: JS:

 <Buffer 01 2c 00 00 00 37 78 69 48 56 6e 37 45 65 51 77 62 73 50 72 41 74 61 59 33 61 6f 6b 48 65 6b 59 54 72 55 52 73 67 7a 52 65 46 78 64 31 4a 65 56 52 00 ... 7 more bytes>

回复:

 <Buffer 01 67 6b bf 1a 5c ad e2 3f a0 69 13 09 5e e8 6a 50 91 87 1c 3e 16 5d a4 43 84 d0 d6 f4 0e 9a 4f 8c 00 00 00 00 00 00 00 00>

在前端,确保将 public 键定义为 32 字节,而不是字符串:

const SCHEMA = new Map([
 [
   MintAccount,
   {
     kind: 'struct',
     fields: [
       ['tag', 'u8'],
       ['authority', [32]],
       ['supply', 'u64']
     ],
   },
 ]
]);

您可能需要更新序列化的完成方式,因此您的类型可以不是 PublicKey,而是使用 [=14= 的 BufferUint8Array ] 或 authority.toBytes()