update.rs
Overview
This file provides an extension implementation for the ZeroState struct, enabling the addition and management of blockchain accounts and internal messages within the zero state. It implements key functions to:
Add new accounts with associated state initialization.
Inject internal messages into the zero state message queue.
Calculate wallet addresses for block keepers based on public keys and state initialization.
Manage block keeper metadata including staking and activity status.
The file primarily manipulates low-level blockchain state abstractions such as StateInit, AccountStorage, and Message, relying on cryptographic identifiers like UInt256 and AccountId. It interacts with thread-specific shard states and message queues, ensuring state consistency and message propagation for optimistic execution contexts.
Detailed Descriptions
Impl Block: ZeroState
The implementation block extends the ZeroState struct with several crucial methods that maintain and manipulate blockchain state and messages.
Method: add_account
pub fn add_account<P: AsRef<Path>>(
&mut self,
path: P,
address: Option<String>,
dapp_id: Option<UInt256>,
balance: Option<CurrencyCollection>,
salt: Option<Cell>,
thread_identifier: &ThreadIdentifier,
) -> anyhow::Result<String>
Purpose
Adds a new blockchain account into the zero state by loading a StateInit from a specified file path, optionally applying a salt to the code cell, and associating the account with a thread-specific shard state.
Parameters
path: Path to a file containing the serializedStateInit.address: Optional string representing the account address in hexadecimal form. IfNone, the address is derived from the state init hash.dapp_id: Optional decentralized application identifier (UInt256) linked to the account.balance: Optional initial balance as aCurrencyCollection.salt: OptionalCellvalue to salt the smart contract's code.thread_identifier: Reference to theThreadIdentifierspecifying the thread context.
Returns
Result<String>: On success, returns the hexadecimal string of the account ID.
Usage Example
let account_id = zero_state.add_account(
"path/to/state_init.boc",
Some("abcdef1234567890...".to_string()),
None,
None,
None,
&thread_id,
)?;
println!("Added account with ID: {}", account_id);
Implementation Details
Loads the
StateInitfrom the specified file.If a salt is provided, applies it to the contract's code cell to ensure uniqueness.
Computes the account ID either from the provided address or the state init hash.
Constructs the
AccountStorageand initialAccountwith current timestamp-based storage info.Updates the account's storage statistics internally.
Sets the initial balance if specified.
Wraps the account in a
ShardAccountwith optionaldapp_id.Inserts the account into the zero state's shard state for the given thread.
Updates the account count if the feature
monitor-accounts-numberis enabled.
Method: add_message_from_zeroes
pub fn add_message_from_zeroes(
&mut self,
dest: String,
value: Option<u128>,
ecc: Option<ExtraCurrencyCollection>,
dapp_id: Option<UInt256>,
thread_identifier: &ThreadIdentifier,
) -> anyhow::Result<()>
Purpose
Creates and adds an internal message originating from the zero account (all zero address) to a specified destination account within the zero state message queue.
Parameters
dest: Destination account address as a string.value: Optional token amount to transfer (in nano tokens, represented asu128).ecc: Optional extra currency collection to attach.dapp_id: Optional dapp identifier linked to the message source.thread_identifier: Reference to the thread context for message insertion.
Returns
Result<()>: Indicates success or failure of message addition.
Usage Example
zero_state.add_message_from_zeroes(
"0123456789abcdef...".to_string(),
Some(1000000),
None,
Some(dapp_id),
&thread_id,
)?;
Implementation Details
Converts destination string to an
AccountId.Constructs a
CurrencyCollectionfrom the provided value and extra currencies.Builds an
InternalMessageHeaderfrom the zero account address to the destination.Sets the source dapp ID on the header if provided.
Constructs a
Messagewith the internal header.Delegates to
add_messageto enqueue the message.
Method: add_message
pub fn add_message(
&mut self,
message: Message,
thread_identifier: &ThreadIdentifier,
) -> anyhow::Result<()>
Purpose
Inserts an internal message into the zero state's message queue for a specified thread, enabling optimistic execution and message tracking.
Parameters
message: TheMessageobject to be added. Must be internal.thread_identifier: Reference to the thread context.
Returns
Result<()>: Success or failure of the operation.
Usage Example
zero_state.add_message(message, &thread_id)?;
Implementation Details
Asserts that the message is internal.
Wraps the message in a
WrappedMessage.Generates a
MessageIdentifieras a unique key.Accesses the mutable optimistic state for the thread.
Builds a new
ThreadMessageQueueStatethat includes the added message under the destination's queue.Uses an in-memory durable storage for messages (
MessageDurableStorage::mem()).Does not currently persist to shard state message queues; commented-out code indicates prior or planned implementations.
Method: calculate_block_keeper_wallet_address
pub fn calculate_block_keeper_wallet_address(
_owner_pubkey: UInt256,
mut data: StateInit,
) -> anyhow::Result<UInt256>
Purpose
Computes the wallet address hash for a block keeper by salting the StateInit code using the owner's public key and then hashing the updated StateInit.
Parameters
_owner_pubkey: Owner's public key asUInt256.data: A mutableStateInitobject representing the initial state.
Returns
Result<UInt256>: The resulting wallet address hash.
Usage Example
let wallet_address = ZeroState::calculate_block_keeper_wallet_address(owner_pubkey, state_init)?;
Implementation Details
Writes the owner's public key into a
BuilderDatacell.Uses
set_code_salt_cellto apply the salt to theStateInitcode.Updates the
StateInitwith the salted code.Returns the hash of the salted
StateInitas the wallet address.
Method: add_block_keeper
#[allow(clippy::too_many_arguments)]
pub fn add_block_keeper(
&mut self,
wallet_address: String,
pubkey: String,
epoch_finish_seq_no: u64,
wait_step: u64,
stake: BigUint,
thread_id: ThreadIdentifier,
signer_index: SignerIndex,
owner_pubkey: String,
)
Purpose
Registers or updates block keeper metadata within the zero state context, associating cryptographic keys, staking information, and operational status.
Parameters
wallet_address: Block keeper wallet address as a hex string.pubkey: Public key for the block keeper as a hex string.epoch_finish_seq_no: Epoch sequence number when the block keeper's period ends.wait_step: Waiting step parameter for block keeper activation or scheduling.stake: Amount staked by the block keeper asBigUint.thread_id: Thread context identifier.signer_index: Index identifying the signer in the set.owner_pubkey: Owner's public key in string format.
Usage Example
zero_state.add_block_keeper(
wallet_addr_str,
pubkey_str,
epoch_end,
wait_step_val,
stake_amount,
thread_id,
signer_idx,
owner_pubkey_str,
);
Implementation Details
Converts string representations to
AccountId,UInt256, andPubKey.Inserts a new
BlockKeeperDataentry into theblock_keeper_setmap keyed bythread_idandsigner_index.Sets initial block keeper status to
Active.Stores staking and ownership metadata for further consensus or validation phases.
Important Implementation Notes
The file leverages several blockchain-specific data structures from dependencies such as
tvm_block,tvm_client, andtvm_types.It uses
anyhow::Resultfor error handling, providing detailed contextual error messages.The zero account address is defined as a constant
ZERO_ACCOUNTconsisting of 64 zero hex characters.The
add_messagemethod currently uses an optimistic state update approach, managing messages in memory withThreadMessageQueueState.Commented-out code in
add_messageshows an older or alternative approach involving out message queue manipulation at the shard state level.The
add_accountmethod uses system time since UNIX epoch for storage statistics timestamps.add_block_keepermanages a map keyed by thread IDs and signer indices, allowing multiple block keepers per thread.
Interaction with Other Components
ZeroState: Core data structure representing the genesis or baseline state for shards and threads.ThreadIdentifier: Used to identify which thread/shard context the account or message belongs to.StateInit: Represents initialization state of a blockchain smart contract/account loaded from BOC files.ShardAccountandAccountStorage: Abstractions for managing account state and storage details.MessageandInternalMessageHeader: Used for representing and constructing internal messages to be processed by the blockchain.ThreadMessageQueueState: Manages the optimistic state of messages at the thread level.BlockKeeperDataandBlockKeeperStatus: Structures used to maintain block keeper information required for consensus and staking.MessageDurableStorage: Provides storage abstraction for messages, currently memory-based in this implementation.tvm_client::boc::set_code_salt_cellis used to apply salting on smart contract code, a critical operation for uniqueness and security.
Visual Diagram: Class Structure of ZeroState Extension
classDiagram
class ZeroState {
+add_account(path, address, dapp_id, balance, salt, thread_identifier) String
+add_message_from_zeroes(dest, value, ecc, dapp_id, thread_identifier) void
+add_message(message, thread_identifier) void
+calculate_block_keeper_wallet_address(owner_pubkey, data) UInt256
+add_block_keeper(wallet_address, pubkey, epoch_finish_seq_no, wait_step, stake, thread_id, signer_index, owner_pubkey) void
}
This diagram summarizes the methods added to ZeroState by this file, focusing on account and message management as well as block keeper registration.
For further details on concepts like StateInit, Message, and AccountStorage, see State Initialization and Account Management and Message Handling in Blockchain Systems. The cryptographic primitives such as UInt256 and AccountId are detailed in Cryptographic Identifiers.