From 780cfa4ee8faf4c2662f3c739e8a5c9f1c8a1826 Mon Sep 17 00:00:00 2001 From: Determinant Date: Wed, 18 Jul 2018 14:34:43 -0400 Subject: move parent selection to PaceMaker --- include/hotstuff/consensus.h | 13 +++++++------ include/hotstuff/hotstuff.h | 15 ++++++--------- include/hotstuff/liveness.h | 43 +++++++++++++++++++++++++++++++++++++------ 3 files changed, 50 insertions(+), 21 deletions(-) (limited to 'include') 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 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 &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 &cmds, + const std::vector &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 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 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; -/** 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 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 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 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); -- cgit v1.2.3