Skip to content

Instantly share code, notes, and snippets.

@arhag
Created August 31, 2023 23:16
Show Gist options
  • Save arhag/3071922a6cecf563ad6cca183b8a76d0 to your computer and use it in GitHub Desktop.
Save arhag/3071922a6cecf563ad6cca183b8a76d0 to your computer and use it in GitHub Desktop.
HotStuff types
// WIP
namespace eosio::hotstuff {
using sha256 = fc::sha256;
using block_id_type = eosio::chain::block_id_type;
using bitset = boost::dynamic_bitset<uint32_t>;
using bls_public_key = fc::crypto::blslib::bls_public_key;
using bls_signature = fc::crypto::blslib::bls_signature;
struct proposal {
sha256 parent_proposal; //< ID of the proposal that is justified by the valid QC that normally must be
//< available prior to creating this proposal.
//< This could be the empty hash to indicate that this proposal has no parent,
//< which is allowed in exceptional situations such as when the transition to
//< HotStuff consensus first occurs or if the network needs to unsafely
//< recover liveness from some catastrophic failure.
block_id_type head_block; //< ID of the head of the blockchain proposed by this proposal.
//< If the parent_proposal is not the empty hash, then head_block must reference a
//< block that is or extends the block referenced by the head_block of the proposal
//< referenced by parent_proposal.
block_id_type final_on_qc; //< ID of the latest block that is in the branch defined by head_block that will
//< be considered final once a valid QC is available for this proposal.
//< If parent_proposal is the empty hash, there would not be a long enough QC
//< chain to advance finality of the blockchain, but final_on_qc should reference
//< the last known final block in the branch defined by head_block.
uint64_t view; //< View number for this proposal.
//< Assume time_bound is the number of milliseconds (rounded up) since UNIX epoch for
//< the block timestamp captured in the block referenced by head_block.
//< Assuming p is a proposal where p.proposal_id() == parent_proposal:
//< Then, view must be greater than p.view but less than time_bound.
//< If possible, view should ideally be equal to p.view + 1.
//< If that is not possible, then the next best value for the view (assuming allowed
//< by the constraints) is the number of milliseconds (rounded up) since UNIX epoch
//< for the block timestamp captured in the block one previous to the block referenced
//< by head_block.
//< If such a p does not exist since parent_proposal is the empty hash,
//< then view must be equal to time_bound.
uint64_t active_generation; //< Generation number for the finalizer set that is active at the start of
//< this proposal.
//< That active finalizer set must be used as the QC signature on this
//< proposal's proposal_id().
//< Assuming p is a proposal where p.proposal_id() == parent_proposal:
//< Then, active_generation must be equal to p.next_active_generation.
//< If such a p does not exist since parent_proposal is the empty hash,
//< then active_generation must be equal to the highest generation number of
//< the proposed finalizer sets available in the block header extensions for
//< the blockchain accessible from the block referenced by final_on_qc.
uint64_t next_active_generation; //< Generation number for the finalizer set to be considered active for
//< the next proposal that references this proposal assuming a valid QC is
//< available for this proposal.
//< Assuming p is a proposal where p.proposal_id() == parent_proposal:
//< Then, next_active_generation must be greater than or equal to
//< p.next_active_generation.
//< It must be set to the highest generation number of the proposed
//< finalizer sets available in the block header extensions for the
//< blockchain accessible from the block referenced by final_on_qc.
//< If such a p does not exist since parent_proposal is the empty hash,
//< then next_active_generation must be equal to active_generation.
sha256 proposal_id() const; // Computes SHA256 digest of a serialization of the variables above within this struct.
}
struct quorum_certificate_signature {
bitset present_finalizers;
bls_signature aggregate_signature;
};
struct quorum_certificate {
sha256 proposal_id;
quorum_certificate_signature qc_sig; //< QC signature on proposal_id.
//< qc_sig.present_finalizers bitset references the finalizer set with
//< generation number equal to p.active_generation where p is a proposal
//< such that p.proposal_id() == proposal_id.
};
} // namespace eosio::hotstuff
namespace eosio::chain {
namespace hs = eosio::hotstuff;
struct hs_proposal_message {
hs::proposal proposal;
hs::quorum_certificate_signature qc_sig; //< QC signature on proposal.parent_proposal.
//< qc_sig.present_finalizers bitset references the finalizer set with
//< generation number equal to p.active_generation where p is a
//< proposal such that p.proposal_id() == proposal.parent_proposal.
};
struct hs_vote_message {
fc::sha256 proposal_id;
hs::bls_public_key pub_key;
hs::bls_signature sig; // Signature sig must be on proposal_id validated with public key pub_key.
};
struct hs_new_view_message {
hs::quorum_certificate high_qc;
};
} // namespace eosio::chain
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment