diff options
Diffstat (limited to 'include/hotstuff')
-rw-r--r-- | include/hotstuff/consensus.h | 13 | ||||
-rw-r--r-- | include/hotstuff/hotstuff.h | 15 | ||||
-rw-r--r-- | include/hotstuff/liveness.h | 43 |
3 files changed, 50 insertions, 21 deletions
diff --git a/include/hotstuff/consensus.h b/include/hotstuff/consensus.h index cb18db5..73d47ef 100644 --- a/include/hotstuff/consensus.h +++ b/include/hotstuff/consensus.h @@ -40,14 +40,11 @@ class HotStuffCore { protected: ReplicaID id; /**< identity of the replica itself */ - const int32_t parent_limit; /**< maximum number of parents */ public: BoxObj<EntityStorage> storage; - HotStuffCore(ReplicaID id, - privkey_bt &&priv_key, - int32_t parent_limit); + HotStuffCore(ReplicaID id, privkey_bt &&priv_key); virtual ~HotStuffCore() = default; /* Inputs of the state machine triggered by external events, should called @@ -73,8 +70,11 @@ class HotStuffCore { * The block mentioned in the message should be already delivered. */ void on_receive_vote(const Vote &vote); - /** Call to submit new commands to be decided (executed). */ - void on_propose(const std::vector<command_t> &cmds); + /** Call to submit new commands to be decided (executed). "Parents" must + * contain at least one block, and the first block is the actual parent, + * while the others are uncles/aunts */ + void on_propose(const std::vector<command_t> &cmds, + const std::vector<block_t> &parents); /* Functions required to construct concrete instances for abstract classes. * */ @@ -127,6 +127,7 @@ class HotStuffCore { const ReplicaConfig &get_config() { return config; } int8_t get_cmd_decision(const uint256_t &cmd_hash); ReplicaID get_id() const { return id; } + const std::set<block_t, BlockHeightCmp> get_tails() const { return tails; } operator std::string () const; }; diff --git a/include/hotstuff/hotstuff.h b/include/hotstuff/hotstuff.h index 9d1a8a8..0aa83de 100644 --- a/include/hotstuff/hotstuff.h +++ b/include/hotstuff/hotstuff.h @@ -157,12 +157,11 @@ class HotStuffBase: public HotStuffCore { public: HotStuffBase(uint32_t blk_size, - int32_t parent_limit, ReplicaID rid, privkey_bt &&priv_key, NetAddr listen_addr, - EventContext eb, - pacemaker_bt pmaker); + pacemaker_bt pmaker, + EventContext eb); ~HotStuffBase(); @@ -220,19 +219,17 @@ class HotStuff: public HotStuffBase { public: HotStuff(uint32_t blk_size, - int32_t parent_limit, ReplicaID rid, const bytearray_t &raw_privkey, NetAddr listen_addr, - EventContext eb = EventContext(), - pacemaker_bt pmaker = new PaceMakerDummy()): + pacemaker_bt pmaker, + EventContext eb = EventContext()): HotStuffBase(blk_size, - parent_limit, rid, new PrivKeyType(raw_privkey), listen_addr, - eb, - std::move(pmaker)) {} + std::move(pmaker), + eb) {} void add_replica(ReplicaID idx, const NetAddr &addr, const bytearray_t &pubkey_raw) { DataStream s(pubkey_raw); diff --git a/include/hotstuff/liveness.h b/include/hotstuff/liveness.h index b23d4c2..a51c032 100644 --- a/include/hotstuff/liveness.h +++ b/include/hotstuff/liveness.h @@ -17,6 +17,7 @@ class PaceMaker { * propose the command. */ virtual promise_t beat() = 0; virtual ReplicaID get_proposer() = 0; + virtual std::vector<block_t> get_parents() = 0; /** Get a promise resolved when the pace maker thinks it is a *good* time * to vote for a block. The promise is resolved with the next proposer's ID * */ @@ -25,8 +26,31 @@ class PaceMaker { using pacemaker_bt = BoxObj<PaceMaker>; -/** A pace maker that waits for the qc of the last proposed block. */ -class PaceMakerDummy: public PaceMaker { +class PMAllParents: public virtual PaceMaker { + const int32_t parent_limit; /**< maximum number of parents */ + public: + PMAllParents(int32_t parent_limit): parent_limit(parent_limit) {} + std::vector<block_t> get_parents() override { + auto tails = hsc->get_tails(); + size_t nparents = tails.size(); + if (parent_limit > 0) + nparents = std::min(nparents, (size_t)parent_limit); + assert(nparents > 0); + block_t p = *tails.rbegin(); + std::vector<block_t> parents{p}; + nparents--; + /* add the rest of tails as "uncles/aunts" */ + while (nparents--) + { + auto it = tails.begin(); + parents.push_back(*it); + tails.erase(it); + } + return std::move(parents); + } +}; + +class PMWaitQC: public virtual PaceMaker { std::queue<promise_t> pending_beats; block_t last_proposed; bool locked; @@ -53,8 +77,6 @@ class PaceMakerDummy: public PaceMaker { } public: - PaceMakerDummy() = default; - void init(HotStuffCore *hsc) override { PaceMaker::init(hsc); last_proposed = hsc->get_genesis(); @@ -80,16 +102,25 @@ class PaceMakerDummy: public PaceMaker { } }; +/** A pace maker that waits for the qc of the last proposed block. */ +struct PaceMakerDummy: public PMAllParents, public PMWaitQC { + PaceMakerDummy(int32_t parent_limit): + PMAllParents(parent_limit), PMWaitQC() {} +}; + class PaceMakerDummyFixed: public PaceMakerDummy { ReplicaID proposer; public: + PaceMakerDummyFixed(ReplicaID proposer, + int32_t parent_limit): + PaceMakerDummy(parent_limit), + proposer(proposer) {} + ReplicaID get_proposer() override { return proposer; } - PaceMakerDummyFixed(ReplicaID proposer): proposer(proposer) {} - promise_t next_proposer(ReplicaID) override { return promise_t([this](promise_t &pm) { pm.resolve(proposer); |