-
Notifications
You must be signed in to change notification settings - Fork 33
Shared State Hash Protocol
This document describes the cross-module communication using the interfaces in ../shared/modules to compute a new state hash. See module specific documentation & implementation details inside each module respectively.
NOTE: The diagrams below use some Hotstuff specific terminology as described in the HotPOKT Consensus Specification but can be adapted to other BFT protocols as well.
The Utility and Persistence modules maintain a context (i.e. an ephemeral states) driven by the Consensus module that can be released & reverted (i.e. the block is invalid / no Validator Consensus reached) or can be committed & persisted to disk (i.e. the block is finalized).
On every round of every height:
- The
Consensusmodule handles aNEWROUNDmessage - A new
UtilityUnitOfWorkis initialized at the current height - A new
PersistenceRWContextis initialized at the current height - The Block Application flow commences
sequenceDiagram
title Steps 1-4
participant B as Bus
participant C as Consensus
participant U as Utility
participant P as Persistence
%% Handle New Message
B-->>C: HandleMessage(NEWROUND)
%% NEWROUND
activate C
%% Create Contexts
C->>+U: NewContext(height)
U->>+P: NewRWContext(height)
P->>-U: PersistenceContext
U->>U: store context<br>locally
activate U
deactivate U
U->>-C: UtilityUnitOfWork
C->>C: store context<br>locally
deactivate C
%% Apply Block
Note over C, P: 'Block Application'
The Proposer drives the Validators to agreement via the Consensus Lifecycle (i.e. HotPOKT)
- The
Consensusmodule handles theDECIDEmessage - The
commitQCis propagated to theUtilityUnitOfWork&PersistenceContextonCommit - The persistence module's internal implementation for 'Store Block' must execute.
- Both the
UtilityUnitOfWorkandPersistenceContextare released
sequenceDiagram
title Steps 5-8
participant B as Bus
participant C as Consensus
participant U as Utility
participant P as Persistence
%% Handle New Message
B-->>C: HandleMessage(DECIDE)
activate C
%% Commit Context
C->>+U: Context.Commit(proposer, quorumCert)
U->>+P: Context.Commit(proposer, quorumCert)
P->>P: Internal Implementation
Note over P: Store Block
P->>-U: err_code
U->>C: err_code
deactivate U
%% Release Context
C->>+U: Context.Release()
U->>+P: Context.Release()
P->>-U: err_code
U->>-C: err_code
deactivate C
When applying the block during the NEWROUND message shown above, the majority of the flow is similar between the leader and the replica with one of the major differences being a call to the Utility module as seen below.
-
ApplyBlock- Uses the existing set of transactions to validate & propose -
CreateProposalBlock- Reaps the mempool for a new set of transaction to validate and propose
graph TD
B[Should I prepare a new block?] --> |Wait for 2/3+ NEWROUND messages| C
C[Am I the leader?] --> |Yes| D
C[Am I the leader?] --> |No| Z
D[Did I get any prepareQCs?] --> |Find highest valid prepareQC| E
D[Did I get any prepareQCs?] --> |No| Z
E[Am I ahead of highPrepareQC?] --> |Yes| G
E[Am I ahead of highPrepareQC?] --> |No| Z
G[Do I have a lockedQC] --> |No| H
G[Do I have a lockedQC] --> |Yes| I
I[Is prepareQC.view > lockedQC.view] --> |"No<br>(lockedQC.block)"| Z
I[Is prepareQC.view > lockedQC.view] --> |"Yes<br>(prepareQC.block)"| Z
H[CreateProposalBlock]
Z[ApplyBlock]
As either the leader or replica, the following steps are followed to apply the proposal transactions in the block.
- Update the
UtilityUnitOfWorkwith the proposed block - Call either
ApplyBlockorCreateProposalBlockbased on the flow above
sequenceDiagram
title Steps 1-2
participant C as Consensus
participant U as Utility
%% Update the proposal in the utility unit of work
C->>+U: SetProposalBlock(hash, proposer, txs)
U->>-C: err_code
%% Apply the block to the local proposal state
C->>+U: ApplyBlock / CreateProposalBlock
U->>-C: err_code
- Loop over all transactions proposed
- Check if the transaction has already been applied to the local state
- Perform the CRUD operation(s) corresponding to each transaction
- The persistence module's internal implementation for 'Compute State Hash' must be triggered
- Validate that the local state hash computed is the same as that proposed
sequenceDiagram
title Steps 3-7
participant C as Consensus
participant U as Utility
participant P as Persistence
loop for each tx in txs
U->>+P: TransactionExists(txHash)
P->>-U: false (does not exist)
loop for each operation in tx
U->>+P: Get*/Set*/Update*/Insert*
P->>-U: err_code
U->>U: Validation logic
activate U
deactivate U
end
end
%% TODO: Consolidate AppHash and StateHash
U->>+P: ComputeStateHash()
P->>P: Internal Implementation
Note over P: Compute State Hash
P->>-U: stateHash
U->>C: stateHash
%% Validate the computed hash
C->>C: Compare local hash<br>against proposed hash
Contents
- Home
- Persistence
- Changelog
-
Persistence
- Indexer
- Rpc
- Runtime
- State_Machine
-
Guides
- Roadmap
-
Guides
- Learning
- Guides
-
Guides
- Contributing
- Devlog
-
Guides
- Dependencies
-
Guides
- Releases
- Guides
- P2P
-
Shared
- Crypto
- Shared
-
Shared
- Modules
-
Build
- Config
- Consensus
-
Guides
- Telemetry
- Utility
- Logger