Nodes and substates
In Radix, everything in the kernel is a node. This includes blueprints, packages, components, and anything related to blockchain state.
Each node can have their own state. This state is generally stored in substate structures.
Nodes can be stored in two different types of devices: the store and the heap.
Substate devices
The heap device is used during transactions, and there is an invariant that ensures that there are no live references to nodes on the heap when the transaction ends. It has the following structure,
where NodeId
is just a wrapped [u8; 30]
, while the NodeSubstates
structure is a BTreeMap
that maps partitions to substates:
Each substate is keyed by a SubstateKey
(which is either a u8
, a Vec<u8>
, or a ([u8; 2], Vec<u8>)
depending on the type of key being used) and stored as an IndexedScryptoValue
:
This implies that substates can hold references to other nodes, which is important because, as previously mentioned, there is an invariant that ensures that there are no live references to other nodes when the transaction ends.
Therefore, it is important that at the end of a transaction, there are no substates on the heap with nodes in their owned_nodes
or references
vectors, while those nodes themselves are also on the heap, as that would mean that there is a live reference to this node.
The store device is where permanent substates live. This includes globalized component and blueprint states as well as globalized nodes themselves. The store device keeps track of nodes that are created in the current transaction as well as transient substates (that is, substates that are only intended to be alive for the duration of a transaction).
The substate_db
field refers to a SubstateDatabase
, which is a database structure that stores globalized and otherwise permanent blockchain states. During a transaction, this database is used as a starting point, while at the end of the transaction, the database is updated with any newly created globalized nodes as well as any permanent changes to the blockchain state.
Substate structures
The actual data structures that are used to store specific types of blockchain data are what we will refer to as substate structures. For example, the substate structure to track the validator rewards looks like this:
Where the proposer_rewards
map tracks the actual reward amounts per validator and the rewards_vault
is the vault that contains the rewards themselves.
These substates are generally part of a globalized component, or a blueprint. In this case, the ValidatorRewardsSubstate
is part of the global consensus-manager component, which handles consensus for the Radix blockchain. The globalized component or blueprint in this instance is referred to as a node in the Radix engine's kernel.
Substates are not directly stored as part of the node, however. Instead, nodes can have modules. In the above example, the ValidatorRewardsSubstate
would be part of the consensus-manager component's SELF module. The module itself contains fields, which is where substates are stored.
As an example, the substate above is accessed as follows:
The node that ends up storing the substate is in turn converted to an IndexedScryptoValue
, which will then track any other nodes that this node references or owns.