From 86e2e1211c36d98915e27f48c124e14fbe99d228 Mon Sep 17 00:00:00 2001 From: Ravin Perera <33562092+ravinsp@users.noreply.github.com> Date: Mon, 23 Nov 2020 23:00:13 +0530 Subject: [PATCH] Introduced consensus round nonce and reintroduced stage 0. (#160) * Reintroduced stage 0. * Introduced round nonce for reduced lcl predictability. --- README.md | 4 +- dev-setup.sh | 3 + src/consensus.cpp | 90 ++++++++++++++----------- src/consensus.hpp | 5 +- src/crypto.cpp | 9 +++ src/crypto.hpp | 2 + src/msg/fbuf/p2pmsg_content.fbs | 1 + src/msg/fbuf/p2pmsg_content_generated.h | 48 +++++++++++-- src/msg/fbuf/p2pmsg_helpers.cpp | 2 + src/p2p/p2p.hpp | 8 +-- 10 files changed, 120 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 0c33fc00..6fd6ede1 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,7 @@ Run the setup script located at the repo root (tested on Ubuntu 18.04). 1. Refer to the Wiki for instructions on running Hot Pocket. ## FlatBuffers message definitions -If you update flatbuffers message definitions, you need to run the flatbuffers code generator to update the stubs. You need to have flatbuffers cli tool installed for this. - -`sudo snap install flatbuffers --edge` +If you update flatbuffers message definitions, you need to run the flatbuffers code generator to update the stubs. Example: When you make a change to `p2pmsg_content.fbc` defnition file, you need to run this: diff --git a/dev-setup.sh b/dev-setup.sh index bb157c78..f0a50386 100755 --- a/dev-setup.sh +++ b/dev-setup.sh @@ -57,6 +57,9 @@ pushd flatbuffers-1.12.0 > /dev/null 2>&1 cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release make sudo cp -r include/flatbuffers /usr/local/include/ +# Copy the flatbuffers compiler +sudo cp flatc /usr/local/bin/flatc +sudo chmod +x /usr/local/bin/flatc popd > /dev/null 2>&1 rm v1.12.0.tar.gz && rm -r flatbuffers-1.12.0 diff --git a/src/consensus.cpp b/src/consensus.cpp index 57369130..3e439855 100644 --- a/src/consensus.cpp +++ b/src/consensus.cpp @@ -29,15 +29,15 @@ namespace consensus constexpr float STAGE2_THRESHOLD = 0.65; constexpr float STAGE3_THRESHOLD = 0.8; constexpr float MAJORITY_THRESHOLD = 0.8; + constexpr size_t ROUND_NONCE_SIZE = 64; consensus_context ctx; bool init_success = false; int init() { - // We allocate 2/7 of roundtime for stage 1 and 2. The rest (4/7) is allocated to stage 3. - // This is because stage 3 needs some time to execute the contract in addition to broadcasting the proposal. - ctx.stage_time = (conf::cfg.roundtime * 2) / 7; + // We allocate 1/4 of roundtime for each stage (0, 1, 2, 3). + ctx.stage_time = conf::cfg.roundtime / 4; ctx.stage_reset_wait_threshold = conf::cfg.roundtime / 10; // Starting consensus processing thread. @@ -98,8 +98,7 @@ namespace consensus int consensus() { - // A consensus round consists of 3 stages (1,2,3). - // Stage 3 is the last stage AND it also provides entry point for next round stage 1. + // A consensus round consists of 4 stages (0,1,2,3). // For a given stage, this function may get visited multiple times due to time-wait conditions. uint64_t stage_start = 0; @@ -121,12 +120,22 @@ namespace consensus hpfs::h32 state = state_common::ctx.get_state(); vote_counter votes; - if (ctx.stage == 1) + if (ctx.stage == 0) + { + // Prepare the consensus candidate user inputs that we have acumulated so far. (We receive them periodically via NUPs) + // The candidate inputs will be included in the stage 0 proposal. + if (verify_and_populate_candidate_user_inputs(lcl_seq_no) == -1) + return -1; + + const p2p::proposal new_round_prop = create_stage0_proposal(lcl, state); + broadcast_proposal(new_round_prop); + } + else if (ctx.stage == 1) { if (is_in_sync(lcl, votes)) { // If we are in sync, vote and broadcast the winning votes to next stage. - const p2p::proposal p = create_stage_proposal(STAGE1_THRESHOLD, votes, lcl, state); + const p2p::proposal p = create_stage123_proposal(STAGE1_THRESHOLD, votes, lcl, state); broadcast_proposal(p); } } @@ -135,12 +144,13 @@ namespace consensus if (is_in_sync(lcl, votes)) { // If we are in sync, vote and broadcast the winning votes to next stage. - const p2p::proposal p = create_stage_proposal(STAGE2_THRESHOLD, votes, lcl, state); + const p2p::proposal p = create_stage123_proposal(STAGE2_THRESHOLD, votes, lcl, state); broadcast_proposal(p); } - // In stage 2, broadcast non-unl proposal (NUP) containing inputs from locally connected users. - // This will be captured and verified at the end of stage 3. + // During stage 2, broadcast non-unl proposal (NUP) containing inputs from locally connected users. + // This will be captured and verified during every round stage 0. + // (We broadcast this at stage 2 instead of 3 to give it enough time to reach others before next round stage 0) broadcast_nonunl_proposal(); } else if (ctx.stage == 3) @@ -149,28 +159,16 @@ namespace consensus { // If we are in sync, vote and get the final winning votes. // This is the consensus proposal which makes it into the ledger and contract execution - const p2p::proposal p = create_stage_proposal(STAGE3_THRESHOLD, votes, lcl, state); + const p2p::proposal p = create_stage123_proposal(STAGE3_THRESHOLD, votes, lcl, state); // Update the ledger and execute the contract using the consensus proposal. if (update_ledger_and_execute_contract(p, lcl, state) == -1) LOG_ERROR << "Error occured in Stage 3 consensus execution."; } - - // Prepare for next round by sending NEW-ROUND PROPOSAL. - // At the end of stage 3, we broadcast the "new round" proposal which is subjected - // to voting in next round stage 1. - - // Prepare the consensus candidate user inputs that we have acumulated so far. (We receive them periodically via NUPs) - // The candidate inputs will be included in the new round proposal. - if (verify_and_populate_candidate_user_inputs(lcl_seq_no) == -1) - return -1; - - const p2p::proposal new_round_prop = create_new_round_proposal(lcl, state); - broadcast_proposal(new_round_prop); } - // We have finished a consensus stage. Transition to next stage. (if at stage 3 go to next round stage 1) - ctx.stage = (ctx.stage < 3) ? (ctx.stage + 1) : 1; + // We have finished a consensus stage. Transition to next stage. (if at stage 3 go to next round stage 0) + ctx.stage = (ctx.stage + 1) % 4; return 0; } @@ -283,23 +281,23 @@ namespace consensus const uint64_t now = util::get_epoch_milliseconds(); // Rrounds are discreet windows of roundtime. - // This gets the start time of current round window. Stage 1 must start in the next round window. + // This gets the start time of current round window. Stage 0 must start in the next round window. const uint64_t current_round_start = (((uint64_t)(now / conf::cfg.roundtime)) * conf::cfg.roundtime); - if (ctx.stage == 1) + if (ctx.stage == 0) { - // Stage 1 must start in the next round window. - // (This makes sure stage 3 gets whichever the remaining time in the round after stage 1 and 2) + // Stage 0 must start in the next round window. + // (This makes sure stage 3 gets whichever the remaining time in the round after stages 0,1,2) stage_start = current_round_start + conf::cfg.roundtime; const uint64_t to_wait = stage_start - now; - LOG_DEBUG << "Waiting " << std::to_string(to_wait) << "ms for next round stage 1"; + LOG_DEBUG << "Waiting " << to_wait << "ms for next round stage 0"; util::sleep(to_wait); return true; } else { - stage_start = current_round_start + ((ctx.stage - 1) * ctx.stage_time); + stage_start = current_round_start + (ctx.stage * ctx.stage_time); // Compute stage time wait. // Node wait between stages to collect enough proposals from previous stages from other nodes. @@ -309,7 +307,7 @@ namespace consensus // it will join in next round. Otherwise it will continue particapating in this round. if (to_wait < ctx.stage_reset_wait_threshold) //todo: self claculating/adjusting network delay { - LOG_DEBUG << "Missed stage " << std::to_string(ctx.stage) << " window. Resetting to stage 1"; + LOG_DEBUG << "Missed stage " << std::to_string(ctx.stage) << " window. Resetting to stage 0"; ctx.stage = 1; return false; } @@ -495,15 +493,16 @@ namespace consensus return 0; } - p2p::proposal create_new_round_proposal(std::string_view lcl, hpfs::h32 state) + p2p::proposal create_stage0_proposal(std::string_view lcl, hpfs::h32 state) { - // The proposal we are going to emit at the end of stage 3 after ledger update. - // This is the proposal that stage 1 votes on. + // This is the proposal that stage 0 votes on. + // We report our own values in stage 0. p2p::proposal stg_prop; stg_prop.time = ctx.time_now; stg_prop.stage = 0; stg_prop.lcl = lcl; stg_prop.state = state; + crypto::random_bytes(stg_prop.nonce, ROUND_NONCE_SIZE); // Populate the proposal with set of candidate user pubkeys. stg_prop.users.swap(ctx.candidate_users); @@ -516,12 +515,10 @@ namespace consensus for (const auto &[hash, cand_output] : ctx.candidate_user_outputs) stg_prop.hash_outputs.emplace(hash); - // todo: generate stg_prop hash and check with ctx.novel_proposal, we are sending same proposal again. - return stg_prop; } - p2p::proposal create_stage_proposal(const float_t vote_threshold, vote_counter &votes, std::string_view lcl, hpfs::h32 state) + p2p::proposal create_stage123_proposal(const float_t vote_threshold, vote_counter &votes, std::string_view lcl, hpfs::h32 state) { // The proposal to be emited at the end of this stage. p2p::proposal stg_prop; @@ -541,6 +538,9 @@ namespace consensus if (ctx.time_now > cp.time && (ctx.time_now - cp.time) <= conf::cfg.roundtime) increment(votes.time, cp.time); + // Vote for round nonce. + increment(votes.nonce, cp.nonce); + // Vote for user pubkeys. for (const std::string &pubkey : cp.users) increment(votes.users, pubkey); @@ -592,6 +592,20 @@ namespace consensus } } + // Round nonce is voted on a simple sorted (highest to lowest) and majority basis, since there will always be disagreement. + uint32_t highest_nonce_vote = 0; + for (auto itr = votes.nonce.rbegin(); itr != votes.nonce.rend(); ++itr) + { + const std::string &nonce = itr->first; + const uint32_t numvotes = itr->second; + + if (numvotes > highest_nonce_vote) + { + highest_time_vote = numvotes; + stg_prop.nonce = nonce; + } + } + return stg_prop; } diff --git a/src/consensus.hpp b/src/consensus.hpp index c3eb3ff9..72bbf479 100644 --- a/src/consensus.hpp +++ b/src/consensus.hpp @@ -79,6 +79,7 @@ namespace consensus struct vote_counter { std::map time; + std::map nonce; std::map lcl; std::map users; std::map inputs; @@ -108,9 +109,9 @@ namespace consensus int verify_and_populate_candidate_user_inputs(const uint64_t lcl_seq_no); - p2p::proposal create_new_round_proposal(std::string_view lcl, hpfs::h32 state); + p2p::proposal create_stage0_proposal(std::string_view lcl, hpfs::h32 state); - p2p::proposal create_stage_proposal(const float_t vote_threshold, vote_counter &votes, std::string_view lcl, hpfs::h32 state); + p2p::proposal create_stage123_proposal(const float_t vote_threshold, vote_counter &votes, std::string_view lcl, hpfs::h32 state); void broadcast_proposal(const p2p::proposal &p); diff --git a/src/crypto.cpp b/src/crypto.cpp index 94600e77..fe5082d2 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -131,6 +131,15 @@ namespace crypto decoded_pubkey + 1); // +1 to skip prefix byte. } + /** + * Generate random bytes of specified length. + */ + void random_bytes(std::string &result, const size_t len) + { + result.resize(len); + randombytes_buf(result.data(), len); + } + /** * Generate blake3 hash for a given message. * @param data String to hash. diff --git a/src/crypto.hpp b/src/crypto.hpp index 31b68e0d..87d9afa1 100644 --- a/src/crypto.hpp +++ b/src/crypto.hpp @@ -29,6 +29,8 @@ namespace crypto int verify_hex(std::string_view msg, std::string_view sighex, std::string_view pubkeyhex); + void random_bytes(std::string &result, const size_t len); + std::string get_hash(std::string_view data); std::string get_hash(const unsigned char *data, size_t data_length); diff --git a/src/msg/fbuf/p2pmsg_content.fbs b/src/msg/fbuf/p2pmsg_content.fbs index a883ae73..90d2b9d4 100644 --- a/src/msg/fbuf/p2pmsg_content.fbs +++ b/src/msg/fbuf/p2pmsg_content.fbs @@ -51,6 +51,7 @@ table NonUnl_Proposal_Message { table Proposal_Message { //Proposal type message schema stage:uint8; time:uint64; + nonce: [ubyte]; users:[ByteArray]; hash_inputs:[ByteArray]; hash_outputs:[ByteArray]; diff --git a/src/msg/fbuf/p2pmsg_content_generated.h b/src/msg/fbuf/p2pmsg_content_generated.h index ccfd4767..7ee5ea33 100644 --- a/src/msg/fbuf/p2pmsg_content_generated.h +++ b/src/msg/fbuf/p2pmsg_content_generated.h @@ -324,6 +324,7 @@ struct Peer_Challenge_MessageBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + Peer_Challenge_MessageBuilder &operator=(const Peer_Challenge_MessageBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -390,6 +391,7 @@ struct Peer_Challenge_Response_MessageBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + Peer_Challenge_Response_MessageBuilder &operator=(const Peer_Challenge_Response_MessageBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -472,6 +474,7 @@ struct UserInputBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + UserInputBuilder &operator=(const UserInputBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -548,6 +551,7 @@ struct UserInputGroupBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + UserInputGroupBuilder &operator=(const UserInputGroupBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -707,6 +711,7 @@ struct ContentBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + ContentBuilder &operator=(const ContentBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -755,6 +760,7 @@ struct NonUnl_Proposal_MessageBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + NonUnl_Proposal_MessageBuilder &operator=(const NonUnl_Proposal_MessageBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -784,10 +790,11 @@ struct Proposal_Message FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_STAGE = 4, VT_TIME = 6, - VT_USERS = 8, - VT_HASH_INPUTS = 10, - VT_HASH_OUTPUTS = 12, - VT_STATE = 14 + VT_NONCE = 8, + VT_USERS = 10, + VT_HASH_INPUTS = 12, + VT_HASH_OUTPUTS = 14, + VT_STATE = 16 }; uint8_t stage() const { return GetField(VT_STAGE, 0); @@ -801,6 +808,12 @@ struct Proposal_Message FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { bool mutate_time(uint64_t _time) { return SetField(VT_TIME, _time, 0); } + const flatbuffers::Vector *nonce() const { + return GetPointer *>(VT_NONCE); + } + flatbuffers::Vector *mutable_nonce() { + return GetPointer *>(VT_NONCE); + } const flatbuffers::Vector> *users() const { return GetPointer> *>(VT_USERS); } @@ -829,6 +842,8 @@ struct Proposal_Message FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { return VerifyTableStart(verifier) && VerifyField(verifier, VT_STAGE) && VerifyField(verifier, VT_TIME) && + VerifyOffset(verifier, VT_NONCE) && + verifier.VerifyVector(nonce()) && VerifyOffset(verifier, VT_USERS) && verifier.VerifyVector(users()) && verifier.VerifyVectorOfTables(users()) && @@ -854,6 +869,9 @@ struct Proposal_MessageBuilder { void add_time(uint64_t time) { fbb_.AddElement(Proposal_Message::VT_TIME, time, 0); } + void add_nonce(flatbuffers::Offset> nonce) { + fbb_.AddOffset(Proposal_Message::VT_NONCE, nonce); + } void add_users(flatbuffers::Offset>> users) { fbb_.AddOffset(Proposal_Message::VT_USERS, users); } @@ -870,6 +888,7 @@ struct Proposal_MessageBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + Proposal_MessageBuilder &operator=(const Proposal_MessageBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -881,6 +900,7 @@ inline flatbuffers::Offset CreateProposal_Message( flatbuffers::FlatBufferBuilder &_fbb, uint8_t stage = 0, uint64_t time = 0, + flatbuffers::Offset> nonce = 0, flatbuffers::Offset>> users = 0, flatbuffers::Offset>> hash_inputs = 0, flatbuffers::Offset>> hash_outputs = 0, @@ -891,6 +911,7 @@ inline flatbuffers::Offset CreateProposal_Message( builder_.add_hash_outputs(hash_outputs); builder_.add_hash_inputs(hash_inputs); builder_.add_users(users); + builder_.add_nonce(nonce); builder_.add_stage(stage); return builder_.Finish(); } @@ -899,10 +920,12 @@ inline flatbuffers::Offset CreateProposal_MessageDirect( flatbuffers::FlatBufferBuilder &_fbb, uint8_t stage = 0, uint64_t time = 0, + const std::vector *nonce = nullptr, const std::vector> *users = nullptr, const std::vector> *hash_inputs = nullptr, const std::vector> *hash_outputs = nullptr, const std::vector *state = nullptr) { + auto nonce__ = nonce ? _fbb.CreateVector(*nonce) : 0; auto users__ = users ? _fbb.CreateVector>(*users) : 0; auto hash_inputs__ = hash_inputs ? _fbb.CreateVector>(*hash_inputs) : 0; auto hash_outputs__ = hash_outputs ? _fbb.CreateVector>(*hash_outputs) : 0; @@ -911,6 +934,7 @@ inline flatbuffers::Offset CreateProposal_MessageDirect( _fbb, stage, time, + nonce__, users__, hash_inputs__, hash_outputs__, @@ -947,6 +971,7 @@ struct Npl_MessageBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + Npl_MessageBuilder &operator=(const Npl_MessageBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -1013,6 +1038,7 @@ struct History_Request_MessageBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + History_Request_MessageBuilder &operator=(const History_Request_MessageBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -1096,6 +1122,7 @@ struct History_Response_MessageBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + History_Response_MessageBuilder &operator=(const History_Response_MessageBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -1170,6 +1197,7 @@ struct HistoryLedgerBlockPairBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + HistoryLedgerBlockPairBuilder &operator=(const HistoryLedgerBlockPairBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -1229,6 +1257,7 @@ struct HistoryLedgerBlockBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + HistoryLedgerBlockBuilder &operator=(const HistoryLedgerBlockBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -1322,6 +1351,7 @@ struct State_Request_MessageBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + State_Request_MessageBuilder &operator=(const State_Request_MessageBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -1443,6 +1473,7 @@ struct State_Response_MessageBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + State_Response_MessageBuilder &operator=(const State_Response_MessageBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -1511,6 +1542,7 @@ struct Fs_Entry_ResponseBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + Fs_Entry_ResponseBuilder &operator=(const Fs_Entry_ResponseBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -1576,6 +1608,7 @@ struct File_HashMap_ResponseBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + File_HashMap_ResponseBuilder &operator=(const File_HashMap_ResponseBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -1645,6 +1678,7 @@ struct Block_ResponseBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + Block_ResponseBuilder &operator=(const Block_ResponseBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -1726,6 +1760,7 @@ struct State_FS_Hash_EntryBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + State_FS_Hash_EntryBuilder &operator=(const State_FS_Hash_EntryBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -1788,6 +1823,7 @@ struct Peer_Requirement_Announcement_MessageBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + Peer_Requirement_Announcement_MessageBuilder &operator=(const Peer_Requirement_Announcement_MessageBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -1843,6 +1879,7 @@ struct Available_Capacity_Announcement_MessageBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + Available_Capacity_Announcement_MessageBuilder &operator=(const Available_Capacity_Announcement_MessageBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -1876,6 +1913,7 @@ struct Peer_List_Request_MessageBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + Peer_List_Request_MessageBuilder &operator=(const Peer_List_Request_MessageBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -1920,6 +1958,7 @@ struct Peer_List_Response_MessageBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + Peer_List_Response_MessageBuilder &operator=(const Peer_List_Response_MessageBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); @@ -2007,6 +2046,7 @@ struct Peer_PropertiesBuilder { : fbb_(_fbb) { start_ = fbb_.StartTable(); } + Peer_PropertiesBuilder &operator=(const Peer_PropertiesBuilder &); flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); auto o = flatbuffers::Offset(end); diff --git a/src/msg/fbuf/p2pmsg_helpers.cpp b/src/msg/fbuf/p2pmsg_helpers.cpp index 5fdb0e85..14392c4b 100644 --- a/src/msg/fbuf/p2pmsg_helpers.cpp +++ b/src/msg/fbuf/p2pmsg_helpers.cpp @@ -224,6 +224,7 @@ namespace msg::fbuf::p2pmsg p.pubkey = flatbuff_bytes_to_sv(pubkey); p.sent_timestamp = timestamp; p.time = msg.time(); + p.nonce = flatbuff_bytes_to_sv(msg.nonce()); p.stage = msg.stage(); p.lcl = flatbuff_bytes_to_sv(lcl); p.state = flatbuff_bytes_to_sv(msg.state()); @@ -368,6 +369,7 @@ namespace msg::fbuf::p2pmsg builder, p.stage, p.time, + sv_to_flatbuff_bytes(builder, p.nonce), stringlist_to_flatbuf_bytearrayvector(builder, p.users), stringlist_to_flatbuf_bytearrayvector(builder, p.hash_inputs), stringlist_to_flatbuf_bytearrayvector(builder, p.hash_outputs), diff --git a/src/p2p/p2p.hpp b/src/p2p/p2p.hpp index cc570f36..77e4dadd 100644 --- a/src/p2p/p2p.hpp +++ b/src/p2p/p2p.hpp @@ -16,12 +16,10 @@ namespace p2p { std::string pubkey; - // The timestamp of the sender when this proposal was sent. - uint64_t sent_timestamp = 0; - - // The time value that is voted on. - uint64_t time = 0; + uint64_t sent_timestamp = 0; // The timestamp of the sender when this proposal was sent. + uint64_t time = 0; // The time value that is voted on. uint8_t stage = 0; + std::string nonce; // Random nonce that is used to reduce lcl predictability. std::string lcl; hpfs::h32 state; std::set users;