State
Learn about the state within the context of TimestampVM.
Blockchains can be defined as follows:
A linked-list where each list element consists of a block
Implementations of blockchains, while adhering to the functionality above from a white-box perspective, are defined much more like databases than regular linked lists themselves. In fact, this is what TimestampVM utilizes! By utilizing a general database, TimestampVM is able to store blocks (and thus, store its blockchain) while also being able to store additional data such as pending blocks.
State Definition
Below is the definition of the State struct which is used to maintain the state of the TimestampVM:
State in this context acts like the database of TimestampVM. Within State, we are managing two different data structures:
db: a byte-based mapping which maps bytes to bytes. This is where finalized (that is, accepted blocks are stored)verified_blocks: a hashmap which maps block numbers to their respective blocks. This is where all verified, but pending blocks are stored
While one could have guessed the functionalities of db and verified_blocks from their respective types subnet::rpc::database::Database + Send + Sync and HashMap<ids::Id, Block>, it is not immediately clear why we are wrapping these fields with Read/Write locks and Arc pointers. However, as we'll see soon when we examine the Block data structure, blocks need access to the VM state so they can add themselves to state. This is due to the SetPrefernce function of SnowmanVM interface, which states:
Set Preference
The VM implements the function SetPreference(blkID ids.ID) to allow the consensus engine to notify the VM which block is currently preferred to be accepted. The VM should use this information to set the head of its blockchain. Most importantly, when the consensus engine calls BuildBlock, the VM should be sure to build on top of the block that is the most recently set preference.
Note: SetPreference will always be called with a block that has no verified children.
Therefore, when building a Rust-based VM (or a VM in any supported language), the VM itself is only responsible for tracking the ID of the most recent finalized block; blocks bear the responsibility of storing themselves in VM state. As a result, we will need to wrap the db and verified_blocks fields with the following:
- An
Arcpointer so that whenever we clone theStatestructure, the cloned versions ofdbandverified_blocksare still pointing to the same data structures in memory. This allows for multiple Blocks to share the samedbandverified_blocks - A read/write lock (that is,
RwLock) so that we safely utilize concurrency in our VM
State Functions
Below are the functions associated with the State struct:
The functions above are called will be called by both blocks and the VM itself.
Is this guide helpful?