Accounts are structures that can be accessed through pre-defined offsets. They were designed in such a way that they do not require serialization through tools like Borsh or Anchor. In earlier versions, each parameter was placed at a pre-determined offset. Currently, this approach is being revised to allow mapping of the data buffer directly to the structure type on a Little Endian architecture.

All accounts are described in files located in the src/accounts folder and end with _account.

AccountHeader

Every account (except for circular log buffers) has an AccountHeader used for data verification.

#[repr(C)]
pub struct AccountHeader {
    pub tag: u32,
    pub version: u32,
    pub root: Pubkey,
}
  • tag indicates the “type” of account (e.g., an account serving pools or a specific type of log account).
  • version indicates which version of the structure should be mapped to this account.
  • root stores the public key of the root account to verify that this account is part of the account tree of this branch of the smart contract. The exception is the root-account, which stores the platform administrator’s public key in this field.

Data Fields

Each account file contains descriptions of fields with their absolute offsets relative to the data buffer extracted from the blockchain. This can be useful if you need to read not the entire account, but only a specific field or a nested structure: in this case, you can make an RPC request to get a data slice with the required field.

pub const WORKER_ACCOUNT_TAG_OFFSET: usize = 0;
pub const WORKER_ACCOUNT_VERSION_OFFSET: usize = 4;
pub const WORKER_ACCOUNT_ROOT_ADDRESS_OFFSET: usize = 8;
pub const WORKER_ACCOUNT_ID_OFFSET: usize = 40;
pub const WORKER_ACCOUNT_STATE_OFFSET: usize = 44;
// ......

However, in most cases, it is more convenient to work directly with the structures:

#[repr(C)]
#[derive(Clone, Copy)]
pub struct WorkerAccount {
    pub header: AccountHeader,
    //  40 bytes
    pub id: u32,
    //  4 bytes, WORKER_ACCOUNT_ID_OFFSET
    pub state: WorkerState,
    //  4 bytes, WORKER_ACCOUNT_STATE_OFFSET
    pub task_id: u32,
    //  4 bytes, WORKER_ACCOUNT_TASK_ID_OFFSET
    pub instr_id: u32,
    //  4 bytes, WORKER_ACCOUNT_INSTR_ID_OFFSET
    // ......
}

Because the original approach did not anticipate data mapping to structures, many fields ended up being misaligned. We are working on correcting this situation; however, some fields may still be misaligned, so getters are suggested for these fields (these data fields are intentionally declared private):

pub struct WorkerAccount {
    // ......
    pub duration: u32,
    //  4 bytes, WORKER_ACCOUNT_DURATION_OFFSET
    init_px: [u8; 8],
    //  8 bytes, WORKER_ACCOUNT_INIT_PX_OFFSET
    pub own_ps: u32,
    //  4 bytes, WORKER_ACCOUNT_OWN_PS_OFFSET
// ......
    impl WorkerAccount {
    #[inline(always)]
    pub fn get_init_px( & self ) -> i64 { i64::from_ne_bytes( self.init_px)
}
// ......