aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2019-04-07 16:10:23 -0400
committerDeterminant <ted.sybil@gmail.com>2019-04-07 16:10:23 -0400
commit2757995cb91dd02ebd6ede693cc6c02c4e359afe (patch)
treed5d3acfe2bae5907c2d949358acfc9659604495b /src
parent49225da30a16a81f5e07c499af88c95da68b45b1 (diff)
clean up consensus code
Diffstat (limited to 'src')
-rw-r--r--src/consensus.cpp75
-rw-r--r--src/hotstuff.cpp13
2 files changed, 46 insertions, 42 deletions
diff --git a/src/consensus.cpp b/src/consensus.cpp
index 8b6e977..b57e258 100644
--- a/src/consensus.cpp
+++ b/src/consensus.cpp
@@ -33,16 +33,14 @@ namespace hotstuff {
HotStuffCore::HotStuffCore(ReplicaID id,
privkey_bt &&priv_key):
b0(new Block(true, 1)),
- bqc(b0),
bexec(b0),
vheight(0),
priv_key(std::move(priv_key)),
- tails{bqc},
+ tails{b0},
neg_vote(false),
id(id),
storage(new EntityStorage()) {
storage->add_blk(b0);
- b0->qc_ref = b0;
}
void HotStuffCore::sanity_check_delivered(const block_t &blk) {
@@ -84,8 +82,20 @@ bool HotStuffCore::on_deliver_blk(const block_t &blk) {
return true;
}
-void HotStuffCore::check_commit(const block_t &_blk) {
- const block_t &blk = _blk->qc_ref;
+void HotStuffCore::update_hqc(const block_t &_hqc, const quorum_cert_bt &qc) {
+ if (_hqc->height > hqc.first->height)
+ {
+ hqc = std::make_pair(_hqc, qc->clone());
+ on_hqc_update();
+ }
+}
+
+void HotStuffCore::update(const block_t &nblk) {
+ const block_t &blk = nblk->qc_ref;
+ if (blk == nullptr)
+ throw std::runtime_error("empty qc_ref");
+ update_hqc(blk, nblk->qc);
+ /* check for commit */
if (blk->qc_ref == nullptr) return;
/* decided blk could possible be incomplete due to pruning */
if (blk->decision) return;
@@ -117,18 +127,6 @@ void HotStuffCore::check_commit(const block_t &_blk) {
bexec = p;
}
-bool HotStuffCore::update(const uint256_t &bqc_hash) {
- block_t _bqc = get_delivered_blk(bqc_hash);
- if (_bqc->qc_ref == nullptr) return false;
- check_commit(_bqc);
- if (_bqc->qc_ref->height > bqc->qc_ref->height)
- {
- bqc = _bqc;
- on_bqc_update();
- }
- return true;
-}
-
void HotStuffCore::on_propose(const std::vector<uint256_t> &cmds,
const std::vector<block_t> &parents,
bytearray_t &&extra) {
@@ -139,7 +137,7 @@ void HotStuffCore::on_propose(const std::vector<uint256_t> &cmds,
quorum_cert_bt qc = nullptr;
block_t qc_ref = nullptr;
/* a block can optionally carray a QC */
- if (p != b0 && p->voted.size() >= config.nmajority)
+ if (p->voted.size() >= config.nmajority)
{
qc = p->self_qc->clone();
qc_ref = p;
@@ -155,15 +153,15 @@ void HotStuffCore::on_propose(const std::vector<uint256_t> &cmds,
const uint256_t bnew_hash = bnew->get_hash();
bnew->self_qc = create_quorum_cert(bnew_hash);
on_deliver_blk(bnew);
- update(bnew_hash);
- Proposal prop(id, bqc->get_hash(), bnew, nullptr);
+ update(bnew);
+ Proposal prop(id, bnew, nullptr);
LOG_PROTO("propose %s", std::string(*bnew).c_str());
/* self-vote */
if (bnew->height <= vheight)
throw std::runtime_error("new block should be higher than vheight");
vheight = bnew->height;
on_receive_vote(
- Vote(id, bqc->get_hash(), bnew_hash,
+ Vote(id, bnew_hash,
create_part_cert(*priv_key, bnew_hash), this));
on_propose_(prop);
/* boradcast to other replicas */
@@ -171,14 +169,14 @@ void HotStuffCore::on_propose(const std::vector<uint256_t> &cmds,
}
void HotStuffCore::on_receive_proposal(const Proposal &prop) {
- if (!update(prop.bqc_hash)) return;
LOG_PROTO("got %s", std::string(prop).c_str());
block_t bnew = prop.blk;
sanity_check_delivered(bnew);
+ update(bnew);
bool opinion = false;
if (bnew->height > vheight)
{
- block_t pref = bqc->qc_ref;
+ block_t pref = hqc.first;
block_t b;
for (b = bnew;
b->height > pref->height;
@@ -195,14 +193,11 @@ void HotStuffCore::on_receive_proposal(const Proposal &prop) {
on_receive_proposal_(prop);
if (opinion && !neg_vote)
do_vote(prop.proposer,
- Vote(id,
- bqc->get_hash(),
- bnew->get_hash(),
+ Vote(id, bnew->get_hash(),
create_part_cert(*priv_key, bnew->get_hash()), this));
}
void HotStuffCore::on_receive_vote(const Vote &vote) {
- if (!update(vote.bqc_hash)) return;
LOG_PROTO("got %s", std::string(vote).c_str());
LOG_PROTO("now state: %s", std::string(*this).c_str());
block_t blk = get_delivered_blk(vote.blk_hash);
@@ -225,10 +220,18 @@ void HotStuffCore::on_receive_vote(const Vote &vote) {
{
qc->compute();
on_qc_finish(blk);
+ update_hqc(blk, qc);
}
}
/*** end HotStuff protocol logic ***/
-void HotStuffCore::on_init(uint32_t nfaulty) { config.nmajority = 2 * nfaulty + 1; }
+void HotStuffCore::on_init(uint32_t nfaulty) {
+ config.nmajority = 2 * nfaulty + 1;
+ b0->qc = create_quorum_cert(b0->get_hash());
+ b0->qc->compute();
+ b0->self_qc = b0->qc->clone();
+ b0->qc_ref = b0;
+ hqc = std::make_pair(b0, b0->qc->clone());
+}
void HotStuffCore::prune(uint32_t staleness) {
block_t start;
@@ -292,9 +295,9 @@ promise_t HotStuffCore::async_wait_receive_proposal() {
});
}
-promise_t HotStuffCore::async_bqc_update() {
- return bqc_update_waiting.then([this]() {
- return bqc;
+promise_t HotStuffCore::async_hqc_update() {
+ return hqc_update_waiting.then([this]() {
+ return hqc.first;
});
}
@@ -310,17 +313,17 @@ void HotStuffCore::on_receive_proposal_(const Proposal &prop) {
t.resolve(prop);
}
-void HotStuffCore::on_bqc_update() {
- auto t = std::move(bqc_update_waiting);
- bqc_update_waiting = promise_t();
+void HotStuffCore::on_hqc_update() {
+ auto t = std::move(hqc_update_waiting);
+ hqc_update_waiting = promise_t();
t.resolve();
}
HotStuffCore::operator std::string () const {
DataStream s;
s << "<hotstuff "
- << "bqc=" << get_hex10(bqc->get_hash()) << " "
- << "bqc.rheight=" << std::to_string(bqc->qc_ref->height) << " "
+ << "hqc=" << get_hex10(hqc.first->get_hash()) << " "
+ << "hqc.height=" << std::to_string(hqc.first->height) << " "
<< "bexec=" << get_hex10(bexec->get_hash()) << " "
<< "vheight=" << std::to_string(vheight) << " "
<< "tails=" << std::to_string(tails.size()) << ">";
diff --git a/src/hotstuff.cpp b/src/hotstuff.cpp
index 4a84927..9b36fa2 100644
--- a/src/hotstuff.cpp
+++ b/src/hotstuff.cpp
@@ -223,7 +223,8 @@ promise_t HotStuffBase::async_deliver_blk(const uint256_t &blk_hash,
/* the parents should be delivered */
for (const auto &phash: blk->get_parent_hashes())
pms.push_back(async_deliver_blk(phash, replica_id));
- pms.push_back(blk->verify(get_config(), vpool));
+ if (blk != get_genesis())
+ pms.push_back(blk->verify(get_config(), vpool));
promise::all(pms).then([this, blk]() {
on_deliver_blk(blk);
});
@@ -238,8 +239,7 @@ void HotStuffBase::propose_handler(MsgPropose &&msg, const Net::conn_t &conn) {
block_t blk = prop.blk;
if (!blk) return;
promise::all(std::vector<promise_t>{
- async_deliver_blk(prop.bqc_hash, peer),
- async_deliver_blk(blk->get_hash(), peer),
+ async_deliver_blk(blk->get_hash(), peer)
}).then([this, prop = std::move(prop)]() {
on_receive_proposal(prop);
});
@@ -251,11 +251,10 @@ void HotStuffBase::vote_handler(MsgVote &&msg, const Net::conn_t &conn) {
//auto &vote = msg.vote;
RcObj<Vote> v(new Vote(std::move(msg.vote)));
promise::all(std::vector<promise_t>{
- async_deliver_blk(v->bqc_hash, peer),
async_deliver_blk(v->blk_hash, peer),
v->verify(vpool),
}).then([this, v=std::move(v)](const promise::values_t values) {
- if (!promise::any_cast<bool>(values[2]))
+ if (!promise::any_cast<bool>(values[1]))
LOG_WARN("invalid vote from %d", v->voter);
else
on_receive_vote(*v);
@@ -415,7 +414,9 @@ void HotStuffBase::do_decide(Finality &&fin) {
HotStuffBase::~HotStuffBase() {}
-void HotStuffBase::start(std::vector<std::pair<NetAddr, pubkey_bt>> &&replicas, bool ec_loop) {
+void HotStuffBase::start(
+ std::vector<std::pair<NetAddr, pubkey_bt>> &&replicas,
+ bool ec_loop) {
for (size_t i = 0; i < replicas.size(); i++)
{
auto &addr = replicas[i].first;