aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorDeterminant <[email protected]>2018-07-18 14:34:43 -0400
committerDeterminant <[email protected]>2018-07-18 14:34:43 -0400
commit780cfa4ee8faf4c2662f3c739e8a5c9f1c8a1826 (patch)
treee54d5ecbb11634e9f2c211dd4cddd8903cda86d9 /include
parente08bf4e6a40cf82822c50b1433a573d0d8800f80 (diff)
move parent selection to PaceMaker
Diffstat (limited to 'include')
-rw-r--r--include/hotstuff/consensus.h13
-rw-r--r--include/hotstuff/hotstuff.h15
-rw-r--r--include/hotstuff/liveness.h43
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);