Propose an implementation that supports fork-aware protocol state. Specifically, we want to track different protocol variables that can be updated through consensus mechanism. At start we will focus on identity table but will want to keep the design general so that additional data can be added and maintained by the Protocol State in future.
We will need to extend the block payload to include the protocol state’s root hash:
// Payload is the actual content of each block.
type Payload struct {
// Guarantees are ordered in execution order. May be empty, in which case
// only the system chunk is executed for this block.
Guarantees []*CollectionGuarantee
// Seals holds block seals for ancestor blocks.
// The oldest seal must connect to the latest seal in the fork extended by this block.
// Seals must be internally connected, containing no seals with duplicate block IDs or heights.
// Seals may be empty. It presents a set, i.e. there is no protocol-defined ordering.
Seals []*Seal
Receipts ExecutionReceiptMetaList
Results ExecutionResultList
// Root hash of protocol state. Per convention, this is the resulting state after applying all
// identity-chaning operations potentially contained in the block. The block payload itself is
// validated wrt. to the protocol state committed to by its parent. Thereby, we are only
// accepting protocol states that have been certified by a valid QC.
ProtocolStateID Identifier
}
The new field ProtocolStateID
is the root hash of protocol state AFTER applying block to block storage. Replicas must ensure their local protocol state has the same root hash as ProtocolStateID
. (see Identity-Changing Operations for more details)
Splitting identity into immutable and mutable parts as suggested here: https://github.com/dapperlabs/flow-go/issues/6232 introduces more structure into code and allows us to build safer APIs.