parse_block_accounts_and_messages.rs
Overview
This file provides functionality to extract and organize data related to account activities and internal messages from a blockchain block structure (AckiNackiBlock). It primarily focuses on gathering information needed for post-processing updates after a block has been processed optimistically. The main method implemented extends the AckiNackiBlock struct with the ability to compute:
Consumed internal messages by accounts.
Produced internal messages routed to specific accounts or other threads.
Accounts that have changed their decentralized application (dApp) identifiers during the block.
This processing is essential for maintaining the optimistic state consistency and for routing messages correctly within the system.
Key Structures and Types
AckiNackiBlock
Represents a processed block of the blockchain with additional metadata (extra). Extended here with post-processing data extraction logic.OptimisticStateImpl
Represents the mutable optimistic state of the blockchain shard, which is used to verify and update state changes caused by block processing.ShardStateUnsplit
Represents the shard state snapshot after block execution, used to query accounts and their current state.MessageIdentifier
A unique identifier for internal messages, used for tracking message consumption and production.WrappedMessage
Wraps a raw internal message with additional metadata for processing convenience.AccountAddress
Represents the unique address of an account on the blockchain.AccountRouting
Combines a dApp identifier and an account address, used to route messages and identify accounts with respect to their dApp context.WrappedAccount
Wraps an account instance together with its address, to be used when returning updated account information.DAppIdentifier
Represents the identifier of a decentralized application associated with an account.
Detailed Explanation of get_data_for_postprocessing
Signature
pub fn get_data_for_postprocessing(
&self,
initial_optimistic_state: &mut OptimisticStateImpl,
updated_shard_state: Arc<ShardStateUnsplit>,
) -> anyhow::Result<(
HashMap<AccountAddress, HashSet<MessageIdentifier>>,
HashMap<AccountAddress, Vec<(MessageIdentifier, Arc<WrappedMessage>)>>,
HashMap<AccountRouting, Option<WrappedAccount>>,
HashMap<AccountRouting, Vec<(MessageIdentifier, Arc<WrappedMessage>)>>,
)>
Parameters
&self
Reference to the currentAckiNackiBlockinstance.initial_optimistic_state: &mut OptimisticStateImpl
Mutable reference to the optimistic state before applying this block. Used to determine message routing ownership.updated_shard_state: Arc<ShardStateUnsplit>
Thread-safe shared reference to the shard state after block execution, providing access to the current state of accounts.
Return Value
Returns a Result containing a tuple of four collections upon success:
Consumed Internal Messages:
HashMap<AccountAddress, HashSet<MessageIdentifier>>
Maps each account address to a set of identifiers of internal messages it has consumed during block processing.Produced Internal Messages to Current Thread:
HashMap<AccountAddress, Vec<(MessageIdentifier, Arc<WrappedMessage>)>>
Maps each account address to a list of tuples, each containing an internal message identifier and the wrapped message, representing produced internal messages routed within the current optimistic state thread.Accounts That Changed dApp ID:
HashMap<AccountRouting, Option<WrappedAccount>>
Maps each account routing (dApp ID + account address) to an optional wrapped account if the account changed its dApp identifier during block processing. If the account is missing, the value isNone.Produced Internal Messages to Other Threads:
HashMap<AccountRouting, Vec<(MessageIdentifier, Arc<WrappedMessage>)>>
Maps each account routing to a list of produced internal messages that belong to other optimistic state threads, i.e., messages that do not belong to the current optimistic state.
Processing Steps and Implementation Details
Initialize Data Structures:
Four HashMaps to store consumed messages, accounts with changed dApp IDs, produced messages to current thread, and produced messages to other threads are created.Read Block Extra Metadata:
The method reads the extra data from the underlying block to access message descriptors:Out Message Descriptor: Iterates over all outgoing messages in the block, extracting those with internal destination accounts. For each message:
Extract internal header and destination account ID.
Construct an
AccountRoutingfrom dApp ID (or fallback to default) and destination account.Wrap the message and create a
MessageIdentifier.Append the message to the
produced_internal_messagesmap keyed byAccountRouting.
In Message Descriptor: Iterates over all incoming messages, extracting internal headers and destination account addresses. Each message is identified and inserted into the
consumed_internal_messagesset for the destination account.
Parse Account Blocks for dApp ID Changes:
Iterates over account blocks within the main block extra data to detect accounts that changed their dApp IDs. For each account block:If the dApp ID changed, the method retrieves the account from the updated shard state.
Constructs an
AccountRoutingbased on the new dApp ID (or defaults).Inserts the routing and either a wrapped account or
Noneif missing in theaccounts_that_changed_their_dapp_idmap.
Split Produced Internal Messages Based on Routing Ownership:
Divides the collected produced internal messages into two groups based on whether the routing belongs to the current optimistic state thread:Messages belonging to the current thread are keyed in the
produced_internal_messages_to_the_current_threadmap using only the account address.Messages belonging to other threads are stored in
produced_internal_messages_to_other_threadskeyed by the fullAccountRouting.
Return Collected Data:
Returns all four data structures wrapped inOk.
Error Handling
Uses
anyhow::Resultfor error propagation.Each read operation on block extras, message descriptors, and account blocks maps errors to formatted error messages.
Message reading failures are propagated as errors.
Iteration over message descriptors and account blocks returns early on errors.
Usage Example
let mut optimistic_state = ...; // Obtained from optimistic state management
let updated_shard_state = Arc::new(...); // Snapshot after block execution
let block: AckiNackiBlock = ...; // The block to post-process
let result = block.get_data_for_postprocessing(&mut optimistic_state, updated_shard_state)?;
let (
consumed_messages,
produced_messages_current_thread,
accounts_with_dapp_changes,
produced_messages_other_threads,
) = result;
// Further processing with these collections...
Interaction With Other System Components
OptimisticStateImpl
Used to verify ownership of message routings to determine if produced messages belong to the current optimistic thread.ShardStateUnsplit
Provides account data needed to confirm dApp ID changes after block processing.WrappedMessageandMessageIdentifier
Used for representing and uniquely identifying internal messages for consumption and production tracking.AccountRoutingandDAppIdentifier
Used to route messages and track accounts within the context of their associated dApp IDs.Block-related Traits (
tvm_block::ShardStateUnsplitand related)
Used to read block extra data, incoming/outgoing message descriptors, and account blocks.
This file serves as a crucial bridge between raw block data and the optimistic state management system, enabling accurate message routing and account state tracking after block execution.
Mermaid Diagram
flowchart TD
A[AckiNackiBlock] -->|get_data_for_postprocessing| B[Read Block Extra]
B --> C[Read Out Message Descriptor]
B --> D[Read In Message Descriptor]
B --> E[Read Account Blocks]
C --> F[Extract Produced Internal Messages]
D --> G[Extract Consumed Internal Messages]
E --> H[Detect Accounts with dApp ID Changes]
F --> I{Routing Ownership Check}
I -->|Belongs Current Thread| J[Produced Messages To Current Thread]
I -->|Belongs Other Threads| K[Produced Messages To Other Threads]
subgraph Outputs
G[Consumed Internal Messages]
J[Produced Internal Messages To Current Thread]
H[Accounts That Changed dApp ID]
K[Produced Internal Messages To Other Threads]
end
get_data_for_postprocessing-->|Returns|Outputs