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
Arc
pointer so that whenever we clone theState
structure, the cloned versions ofdb
andverified_blocks
are still pointing to the same data structures in memory. This allows for multiple Blocks to share the samedb
andverified_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.