aboutsummaryrefslogtreecommitdiff
path: root/include/hotstuff
diff options
context:
space:
mode:
Diffstat (limited to 'include/hotstuff')
-rw-r--r--include/hotstuff/client.h46
-rw-r--r--include/hotstuff/consensus.h3
-rw-r--r--include/hotstuff/entity.h27
-rw-r--r--include/hotstuff/hotstuff.h28
-rw-r--r--include/hotstuff/liveness.h46
5 files changed, 79 insertions, 71 deletions
diff --git a/include/hotstuff/client.h b/include/hotstuff/client.h
index 00ec77d..2127595 100644
--- a/include/hotstuff/client.h
+++ b/include/hotstuff/client.h
@@ -4,6 +4,7 @@
#include "salticidae/msg.h"
#include "hotstuff/type.h"
#include "hotstuff/entity.h"
+#include "hotstuff/consensus.h"
namespace hotstuff {
@@ -13,6 +14,39 @@ enum {
CHK_CMD = 0x6
};
+struct Finality: public Serializable {
+ ReplicaID rid;
+ int8_t decision;
+ uint256_t blk_hash;
+
+ public:
+ Finality() = default;
+ Finality(ReplicaID rid, int8_t decision, uint256_t blk_hash):
+ rid(rid), decision(decision), blk_hash(blk_hash) {}
+
+ void serialize(DataStream &s) const override {
+ s << rid << decision;
+ if (decision == 1) s << blk_hash;
+ }
+
+ void unserialize(DataStream &s) override {
+ s >> rid >> decision;
+ if (decision == 1) s >> blk_hash;
+ }
+};
+
+struct MsgClient: public salticidae::MsgBase<> {
+ using MsgBase::MsgBase;
+ void gen_reqcmd(const Command &cmd);
+ void parse_reqcmd(command_t &cmd, HotStuffCore *hsc) const;
+
+ void gen_respcmd(const uint256_t &cmd_hash, const Finality &fin);
+ void parse_respcmd(uint256_t &cmd_hash, Finality &fin) const;
+
+ void gen_chkcmd(const uint256_t &cmd_hash);
+ void parse_chkcmd(uint256_t &cmd_hash) const;
+};
+
class CommandDummy: public Command {
static uint64_t cnt;
uint64_t n;
@@ -49,18 +83,6 @@ class CommandDummy: public Command {
}
};
-struct MsgClient: public salticidae::MsgBase<> {
- using MsgBase::MsgBase;
- void gen_reqcmd(const Command &cmd);
- void parse_reqcmd(CommandDummy &cmd) const;
-
- void gen_respcmd(const uint256_t &cmd_hash, const Finality &fin);
- void parse_respcmd(uint256_t &cmd_hash, Finality &fin) const;
-
- void gen_chkcmd(const uint256_t &cmd_hash);
- void parse_chkcmd(uint256_t &cmd_hash) const;
-};
-
}
#endif
diff --git a/include/hotstuff/consensus.h b/include/hotstuff/consensus.h
index 18e891e..cb18db5 100644
--- a/include/hotstuff/consensus.h
+++ b/include/hotstuff/consensus.h
@@ -1,6 +1,7 @@
#ifndef _HOTSTUFF_CONSENSUS_H
#define _HOTSTUFF_CONSENSUS_H
+#include <cassert>
#include <set>
#include <unordered_map>
@@ -125,7 +126,7 @@ class HotStuffCore {
block_t get_genesis() { return b0; }
const ReplicaConfig &get_config() { return config; }
int8_t get_cmd_decision(const uint256_t &cmd_hash);
- ReplicaID get_id() { return id; }
+ ReplicaID get_id() const { return id; }
operator std::string () const;
};
diff --git a/include/hotstuff/entity.h b/include/hotstuff/entity.h
index 00c64a6..03aff06 100644
--- a/include/hotstuff/entity.h
+++ b/include/hotstuff/entity.h
@@ -73,26 +73,6 @@ class HotStuffCore;
using block_t = salticidae::RcObj<Block>;
using block_weak_t = salticidae::WeakObj<Block>;
-struct Finality: public Serializable {
- int8_t decision;
- uint256_t blk_hash;
-
- public:
- Finality(): decision(0) {}
- Finality(int8_t decision, uint256_t blk_hash):
- decision(decision), blk_hash(blk_hash) {}
-
- void serialize(DataStream &s) const override {
- s << decision;
- if (decision == 1) s << blk_hash;
- }
-
- void unserialize(DataStream &s) override {
- s >> decision;
- if (decision == 1) s >> blk_hash;
- }
-};
-
class Command: public Serializable {
friend HotStuffCore;
block_weak_t container;
@@ -101,7 +81,6 @@ class Command: public Serializable {
virtual const uint256_t &get_hash() const = 0;
virtual bool verify() const = 0;
inline int8_t get_decision() const;
- inline Finality get_finality() const;
block_t get_container() const {
return container;
}
@@ -220,12 +199,6 @@ int8_t Command::get_decision() const {
return cptr ? cptr->get_decision() : 0;
}
-Finality Command::get_finality() const {
- block_t blk = get_container();
- return Finality(get_decision(),
- blk ? blk->get_hash() : uint256_t());
-}
-
class EntityStorage {
std::unordered_map<const uint256_t, block_t> blk_cache;
std::unordered_map<const uint256_t, command_t> cmd_cache;
diff --git a/include/hotstuff/hotstuff.h b/include/hotstuff/hotstuff.h
index 9546216..9d1a8a8 100644
--- a/include/hotstuff/hotstuff.h
+++ b/include/hotstuff/hotstuff.h
@@ -153,6 +153,7 @@ class HotStuffBase: public HotStuffCore {
void do_broadcast_proposal(const Proposal &) override;
void do_vote(ReplicaID, const Vote &) override;
void do_decide(const command_t &) override;
+ void do_forward(const uint256_t &cmd_hash, ReplicaID rid);
public:
HotStuffBase(uint32_t blk_size,
@@ -160,30 +161,15 @@ class HotStuffBase: public HotStuffCore {
ReplicaID rid,
privkey_bt &&priv_key,
NetAddr listen_addr,
- EventContext eb = EventContext(),
- pacemaker_bt pmaker = nullptr);
+ EventContext eb,
+ pacemaker_bt pmaker);
~HotStuffBase();
/* the API for HotStuffBase */
/* Submit the command to be decided. */
- void add_command(command_t cmd) {
- cmd_pending.push(storage->add_cmd(cmd));
- if (cmd_pending.size() >= blk_size)
- {
- std::vector<command_t> cmds;
- for (uint32_t i = 0; i < blk_size; i++)
- {
- cmds.push_back(cmd_pending.front());
- cmd_pending.pop();
- }
- pmaker->beat().then([this, cmds = std::move(cmds)]() {
- on_propose(cmds);
- });
- }
- }
-
+ ReplicaID add_command(command_t cmd);
void add_replica(ReplicaID idx, const NetAddr &addr, pubkey_bt &&pub_key);
void start(bool eb_loop = false);
@@ -238,13 +224,15 @@ class HotStuff: public HotStuffBase {
ReplicaID rid,
const bytearray_t &raw_privkey,
NetAddr listen_addr,
- EventContext eb = nullptr):
+ EventContext eb = EventContext(),
+ pacemaker_bt pmaker = new PaceMakerDummy()):
HotStuffBase(blk_size,
parent_limit,
rid,
new PrivKeyType(raw_privkey),
listen_addr,
- eb) {}
+ eb,
+ std::move(pmaker)) {}
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 f8d3c50..b23d4c2 100644
--- a/include/hotstuff/liveness.h
+++ b/include/hotstuff/liveness.h
@@ -7,13 +7,16 @@ namespace hotstuff {
/** Abstraction for liveness gadget (oracle). */
class PaceMaker {
+ protected:
+ HotStuffCore *hsc;
public:
virtual ~PaceMaker() = default;
+ virtual void init(HotStuffCore *_hsc) { hsc = _hsc; }
/** Get a promise resolved when the pace maker thinks it is a *good* time
- * to issue new commands. When promise is resolved with the ID of itself,
- * the replica should propose the command, otherwise it will forward the
- * command to the proposer indicated by the ID. */
+ * to issue new commands. When promise is resolved, the replica should
+ * propose the command. */
virtual promise_t beat() = 0;
+ virtual ReplicaID get_proposer() = 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
* */
@@ -24,7 +27,6 @@ using pacemaker_bt = BoxObj<PaceMaker>;
/** A pace maker that waits for the qc of the last proposed block. */
class PaceMakerDummy: public PaceMaker {
- HotStuffCore *hsc;
std::queue<promise_t> pending_beats;
block_t last_proposed;
bool locked;
@@ -34,9 +36,8 @@ class PaceMakerDummy: public PaceMaker {
{
auto pm = pending_beats.front();
pending_beats.pop();
- hsc->async_qc_finish(last_proposed).then(
- [id = hsc->get_id(), pm]() {
- pm.resolve(id);
+ hsc->async_qc_finish(last_proposed).then([this, pm]() {
+ pm.resolve(get_proposer());
});
locked = true;
}
@@ -52,13 +53,19 @@ class PaceMakerDummy: public PaceMaker {
}
public:
- PaceMakerDummy(HotStuffCore *hsc):
- hsc(hsc),
- last_proposed(hsc->get_genesis()),
- locked(false) {
+ PaceMakerDummy() = default;
+
+ void init(HotStuffCore *hsc) override {
+ PaceMaker::init(hsc);
+ last_proposed = hsc->get_genesis();
+ locked = false;
update_last_proposed();
}
+ ReplicaID get_proposer() override {
+ return hsc->get_id();
+ }
+
promise_t beat() override {
promise_t pm;
pending_beats.push(pm);
@@ -73,6 +80,23 @@ class PaceMakerDummy: public PaceMaker {
}
};
+class PaceMakerDummyFixed: public PaceMakerDummy {
+ ReplicaID proposer;
+
+ public:
+ 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);
+ });
+ }
+};
+
}
#endif