LogoAnchor 中文文档

账户空间

Rust 类型计算账户数据大小(字节)要求的参考指南

本参考指南告诉你应该为账户分配多少空间。

这仅适用于不使用 zero-copy 的账户。zero-copy 使用 repr(C) 并带有指针转换,因此 C 布局适用。

除了账户数据的空间外,你还需要在 space 约束中为 Anchor 的内部标识符(discriminator)添加 8(见示例)。

类型图表

类型空间(字节)详情/示例
bool1只需要 1 位,但仍然使用 1 字节
u8/i81
u16/i162
u32/i324
u64/i648
u128/i12816
[T;数量]space(T) * 数量例如 space([u16;32]) = 2 * 32 = 64
Pubkey32
Vec<T>4 + (space(T) * 数量)账户大小是固定的,因此账户应该从一开始就分配足够的空间
String4 + 字符串的字节长度账户大小是固定的,因此账户应该从一开始就分配足够的空间
Option<T>1 + (space(T))
Enum1 + 最大变体的大小例如 Enum { A, B { val: u8 }, C { val: u16 } } -> 1 + space(u16) = 3
f324NaN 会导致序列化失败
f648NaN 会导致序列化失败

示例

#[account]
pub struct MyData {
    pub val: u16,
    pub state: GameState,
    pub players: Vec<Pubkey> // 我们想要支持最多 10 个玩家
}
 
 
impl MyData {

    pub const MAX_SIZE: usize = 2 + (1 + 32) + (4 + 10 * 32);
}
 
#[derive(AnchorSerialize, AnchorDeserialize, Clone, PartialEq, Eq)]
pub enum GameState {
    Active,
    Tie,
    Won { winner: Pubkey },
}
 
#[derive(Accounts)]
pub struct InitializeMyData<'info> {
    // 注意我们需要为 Anchor 的内部标识符添加 8

    #[account(init, payer = signer, space = 8 + MyData::MAX_SIZE)]
    pub acc: Account<'info, MyData>,
    pub signer: Signer<'info>,
    pub system_program: Program<'info, System>
}

InitSpace 宏

有时计算账户的初始空间可能比较困难。此宏将为结构体添加一个 INIT_SPACE 常量。结构体不需要包含 #[account] 宏来生成该常量。以下是一个示例:

#[account]


#[derive(InitSpace)]
pub struct ExampleAccount {
    pub data: u64,
    #[max_len(50)]
    pub string_one: String,
    #[max_len(10, 5)]
    pub nested: Vec<Vec<u8>>,
}
 
#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(mut)]
    pub payer: Signer<'info>,
    pub system_program: Program<'info, System>,


    #[account(init, payer = payer, space = 8 + ExampleAccount::INIT_SPACE)]
    pub data: Account<'info, ExampleAccount>,
}

需要了解的几个重要事项:

  • 定义 space 时不要忘记标识符
  • max_len 长度表示结构的长度,不是总长度。(例如:Vec<u32> 的 max_len 将是 max_len * 4)

On this page

在GitHub上编辑