From a87e8a0c7ec441482dee97105899f52fad16be3a Mon Sep 17 00:00:00 2001 From: Chalith Desaman Date: Mon, 7 Dec 2020 13:06:58 +0530 Subject: [PATCH] Subject UNL changeset to consensus. (#183) --- src/consensus.cpp | 40 +++++++- src/consensus.hpp | 5 + src/msg/controlmsg_parser.cpp | 2 +- src/msg/controlmsg_parser.hpp | 2 +- src/msg/fbuf/ledger_helpers.cpp | 8 +- src/msg/fbuf/ledger_schema.fbs | 6 ++ src/msg/fbuf/ledger_schema_generated.h | 100 ++++++++++++++++++- src/msg/fbuf/p2pmsg_content.fbs | 6 ++ src/msg/fbuf/p2pmsg_content_generated.h | 123 ++++++++++++++++++------ src/msg/fbuf/p2pmsg_helpers.cpp | 13 ++- src/msg/json/controlmsg_json.cpp | 10 +- src/msg/json/controlmsg_json.hpp | 4 +- src/p2p/p2p.hpp | 25 +++++ src/sc.cpp | 7 +- src/sc.hpp | 3 + src/unl.cpp | 2 +- src/unl.hpp | 2 +- 17 files changed, 309 insertions(+), 49 deletions(-) diff --git a/src/consensus.cpp b/src/consensus.cpp index 6478b83c..025fb547 100644 --- a/src/consensus.cpp +++ b/src/consensus.cpp @@ -125,7 +125,7 @@ namespace consensus if (ctx.stage == 0) { - // Prepare the consensus candidate user inputs that we have acumulated so far. (We receive them periodically via NUPs) + // Prepare the consensus candidate user inputs that we have accumulated 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; @@ -164,6 +164,9 @@ namespace consensus // This is the consensus proposal which makes it into the ledger and contract execution const p2p::proposal p = create_stage123_proposal(STAGE3_THRESHOLD, votes, lcl, unl_count, state); + // Update the unl with the unl changeset that subjected to the consensus. + unl::update(p.unl_changeset.additions, p.unl_changeset.removals); + // 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."; @@ -518,6 +521,9 @@ namespace consensus for (const auto &[hash, cand_output] : ctx.candidate_user_outputs) stg_prop.hash_outputs.emplace(hash); + // Populate the proposal wil unl changeset. + stg_prop.unl_changeset = ctx.candidate_unl_changeset; + return stg_prop; } @@ -557,9 +563,19 @@ namespace consensus for (const std::string &hash : cp.hash_outputs) if (ctx.candidate_user_outputs.count(hash) > 0) increment(votes.outputs, hash); + + // Vote for unl additions. Only vote for the unl additions that are in our candidate_unl_changeset. + for (const std::string &pubkey : cp.unl_changeset.additions) + if (ctx.candidate_unl_changeset.additions.count(pubkey) > 0) + increment(votes.unl_additions, pubkey); + + // Vote for unl removals. Only vote for the unl removals that are in our candidate_unl_changeset. + for (const std::string &pubkey : cp.unl_changeset.removals) + if (ctx.candidate_unl_changeset.removals.count(pubkey) > 0) + increment(votes.unl_removals, pubkey); } - const uint32_t required_votes = ceil(vote_threshold * unl_count); + uint32_t required_votes = ceil(vote_threshold * unl_count); // todo: check if inputs being proposed by another node are actually spoofed inputs // from a user locally connected to this node. @@ -581,6 +597,19 @@ namespace consensus if (numvotes >= required_votes) stg_prop.hash_outputs.emplace(hash); + // For the unl changeset reset required votes for majority votes. + required_votes = ceil(MAJORITY_THRESHOLD * unl_count); + + // Add unl additions which have votes over majority threshold to proposal. + for (const auto &[pubkey, numvotes] : votes.unl_additions) + if (numvotes >= required_votes) + stg_prop.unl_changeset.additions.emplace(pubkey); + + // Add unl removals which have votes over majority threshold to proposal. + for (const auto &[pubkey, numvotes] : votes.unl_removals) + if (numvotes >= required_votes) + stg_prop.unl_changeset.removals.emplace(pubkey); + // time is voted on a simple sorted (highest to lowest) and majority basis, since there will always be disagreement. uint32_t highest_time_vote = 0; for (auto itr = votes.time.rbegin(); itr != votes.time.rend(); ++itr) @@ -772,6 +801,9 @@ namespace consensus } } + // Clear candidate unl changset after consensus rounds are completed. + ctx.candidate_unl_changeset.clear(); + // Send any output from the previous consensus round to locally connected users. dispatch_user_outputs(cons_prop, new_lcl_seq_no, new_lcl); @@ -804,6 +836,10 @@ namespace consensus extract_user_outputs_from_contract_bufmap(args.userbufs); + // Prepare the consensus candidate unl changeset that we have accumulated so far. (We receive them as control inputs) + // The candidate unl changeset will be included in the stage 0 proposal. + std::swap(ctx.candidate_unl_changeset, ctx.contract_ctx->args.unl_changeset); + { std::scoped_lock lock(ctx.contract_ctx_mutex); ctx.contract_ctx.reset(); diff --git a/src/consensus.hpp b/src/consensus.hpp index 4de8ae91..fd67d655 100644 --- a/src/consensus.hpp +++ b/src/consensus.hpp @@ -64,6 +64,9 @@ namespace consensus // all users. We will use this map to distribute outputs back to connected users once consensus is achieved. std::unordered_map candidate_user_outputs; + // Collected unl changset to be subjected to the consensus. This will stay here until end of the current consensus round. + p2p::contract_unl_changeset candidate_unl_changeset; + uint8_t stage = 1; uint64_t time_now = 0; uint16_t stage_time = 0; // Time allocated to a consensus stage. @@ -85,6 +88,8 @@ namespace consensus std::map inputs; std::map outputs; std::map state; + std::map unl_additions; + std::map unl_removals; }; int init(); diff --git a/src/msg/controlmsg_parser.cpp b/src/msg/controlmsg_parser.cpp index c1d72827..940fdcea 100644 --- a/src/msg/controlmsg_parser.cpp +++ b/src/msg/controlmsg_parser.cpp @@ -16,7 +16,7 @@ namespace msg::controlmsg return jctlmsg::extract_type(extracted_type, jdoc); } - int controlmsg_parser::extract_unl_changeset(std::vector &additions, std::vector &removals) + int controlmsg_parser::extract_unl_changeset(std::set &additions, std::set &removals) { return jctlmsg::extract_unl_changeset(additions, removals, jdoc); } diff --git a/src/msg/controlmsg_parser.hpp b/src/msg/controlmsg_parser.hpp index 93082d21..a0944b8b 100644 --- a/src/msg/controlmsg_parser.hpp +++ b/src/msg/controlmsg_parser.hpp @@ -12,7 +12,7 @@ namespace msg::controlmsg public: int parse(std::string_view message); int extract_type(std::string &extracted_type) const; - int extract_unl_changeset(std::vector &additions, std::vector &removals); + int extract_unl_changeset(std::set &additions, std::set &removals); }; } // namespace msg::controlmsg diff --git a/src/msg/fbuf/ledger_helpers.cpp b/src/msg/fbuf/ledger_helpers.cpp index 4bf025b9..ce37c34b 100644 --- a/src/msg/fbuf/ledger_helpers.cpp +++ b/src/msg/fbuf/ledger_helpers.cpp @@ -13,6 +13,11 @@ namespace msg::fbuf::ledger */ void create_ledger_block_from_proposal(flatbuffers::FlatBufferBuilder &builder, const p2p::proposal &p, const uint64_t seq_no) { + const flatbuffers::Offset unl_changeset = CreateUnl_Changeset( + builder, + stringlist_to_flatbuf_bytearrayvector(builder, p.unl_changeset.additions), + stringlist_to_flatbuf_bytearrayvector(builder, p.unl_changeset.removals)); + flatbuffers::Offset ledger = ledger::CreateLedgerBlock( builder, @@ -22,7 +27,8 @@ namespace msg::fbuf::ledger hash_to_flatbuff_bytes(builder, p.state), stringlist_to_flatbuf_bytearrayvector(builder, p.users), stringlist_to_flatbuf_bytearrayvector(builder, p.hash_inputs), - stringlist_to_flatbuf_bytearrayvector(builder, p.hash_outputs)); + stringlist_to_flatbuf_bytearrayvector(builder, p.hash_outputs), + unl_changeset); builder.Finish(ledger); // Finished building message content to get serialised content. } diff --git a/src/msg/fbuf/ledger_schema.fbs b/src/msg/fbuf/ledger_schema.fbs index b5ec5cfd..b1100a4e 100644 --- a/src/msg/fbuf/ledger_schema.fbs +++ b/src/msg/fbuf/ledger_schema.fbs @@ -10,6 +10,12 @@ table LedgerBlock { users: [ByteArray]; inputs: [ByteArray]; outputs: [ByteArray]; + unl_changeset: Unl_Changeset; +} + +table Unl_Changeset { + additions:[ByteArray]; + removals:[ByteArray]; } root_type LedgerBlock; \ No newline at end of file diff --git a/src/msg/fbuf/ledger_schema_generated.h b/src/msg/fbuf/ledger_schema_generated.h index 62aa8393..ed5a8076 100644 --- a/src/msg/fbuf/ledger_schema_generated.h +++ b/src/msg/fbuf/ledger_schema_generated.h @@ -15,6 +15,9 @@ namespace ledger { struct LedgerBlock; struct LedgerBlockBuilder; +struct Unl_Changeset; +struct Unl_ChangesetBuilder; + struct LedgerBlock FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { typedef LedgerBlockBuilder Builder; enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { @@ -24,7 +27,8 @@ struct LedgerBlock FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_STATE = 10, VT_USERS = 12, VT_INPUTS = 14, - VT_OUTPUTS = 16 + VT_OUTPUTS = 16, + VT_UNL_CHANGESET = 18 }; uint64_t seq_no() const { return GetField(VT_SEQ_NO, 0); @@ -68,6 +72,12 @@ struct LedgerBlock FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { flatbuffers::Vector> *mutable_outputs() { return GetPointer> *>(VT_OUTPUTS); } + const msg::fbuf::ledger::Unl_Changeset *unl_changeset() const { + return GetPointer(VT_UNL_CHANGESET); + } + msg::fbuf::ledger::Unl_Changeset *mutable_unl_changeset() { + return GetPointer(VT_UNL_CHANGESET); + } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField(verifier, VT_SEQ_NO) && @@ -85,6 +95,8 @@ struct LedgerBlock FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VerifyOffset(verifier, VT_OUTPUTS) && verifier.VerifyVector(outputs()) && verifier.VerifyVectorOfTables(outputs()) && + VerifyOffset(verifier, VT_UNL_CHANGESET) && + verifier.VerifyTable(unl_changeset()) && verifier.EndTable(); } }; @@ -114,6 +126,9 @@ struct LedgerBlockBuilder { void add_outputs(flatbuffers::Offset>> outputs) { fbb_.AddOffset(LedgerBlock::VT_OUTPUTS, outputs); } + void add_unl_changeset(flatbuffers::Offset unl_changeset) { + fbb_.AddOffset(LedgerBlock::VT_UNL_CHANGESET, unl_changeset); + } explicit LedgerBlockBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); @@ -133,10 +148,12 @@ inline flatbuffers::Offset CreateLedgerBlock( flatbuffers::Offset> state = 0, flatbuffers::Offset>> users = 0, flatbuffers::Offset>> inputs = 0, - flatbuffers::Offset>> outputs = 0) { + flatbuffers::Offset>> outputs = 0, + flatbuffers::Offset unl_changeset = 0) { LedgerBlockBuilder builder_(_fbb); builder_.add_time(time); builder_.add_seq_no(seq_no); + builder_.add_unl_changeset(unl_changeset); builder_.add_outputs(outputs); builder_.add_inputs(inputs); builder_.add_users(users); @@ -153,7 +170,8 @@ inline flatbuffers::Offset CreateLedgerBlockDirect( const std::vector *state = nullptr, const std::vector> *users = nullptr, const std::vector> *inputs = nullptr, - const std::vector> *outputs = nullptr) { + const std::vector> *outputs = nullptr, + flatbuffers::Offset unl_changeset = 0) { auto lcl__ = lcl ? _fbb.CreateVector(*lcl) : 0; auto state__ = state ? _fbb.CreateVector(*state) : 0; auto users__ = users ? _fbb.CreateVector>(*users) : 0; @@ -167,7 +185,81 @@ inline flatbuffers::Offset CreateLedgerBlockDirect( state__, users__, inputs__, - outputs__); + outputs__, + unl_changeset); +} + +struct Unl_Changeset FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef Unl_ChangesetBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_ADDITIONS = 4, + VT_REMOVALS = 6 + }; + const flatbuffers::Vector> *additions() const { + return GetPointer> *>(VT_ADDITIONS); + } + flatbuffers::Vector> *mutable_additions() { + return GetPointer> *>(VT_ADDITIONS); + } + const flatbuffers::Vector> *removals() const { + return GetPointer> *>(VT_REMOVALS); + } + flatbuffers::Vector> *mutable_removals() { + return GetPointer> *>(VT_REMOVALS); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_ADDITIONS) && + verifier.VerifyVector(additions()) && + verifier.VerifyVectorOfTables(additions()) && + VerifyOffset(verifier, VT_REMOVALS) && + verifier.VerifyVector(removals()) && + verifier.VerifyVectorOfTables(removals()) && + verifier.EndTable(); + } +}; + +struct Unl_ChangesetBuilder { + typedef Unl_Changeset Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_additions(flatbuffers::Offset>> additions) { + fbb_.AddOffset(Unl_Changeset::VT_ADDITIONS, additions); + } + void add_removals(flatbuffers::Offset>> removals) { + fbb_.AddOffset(Unl_Changeset::VT_REMOVALS, removals); + } + explicit Unl_ChangesetBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateUnl_Changeset( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset>> additions = 0, + flatbuffers::Offset>> removals = 0) { + Unl_ChangesetBuilder builder_(_fbb); + builder_.add_removals(removals); + builder_.add_additions(additions); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateUnl_ChangesetDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector> *additions = nullptr, + const std::vector> *removals = nullptr) { + auto additions__ = additions ? _fbb.CreateVector>(*additions) : 0; + auto removals__ = removals ? _fbb.CreateVector>(*removals) : 0; + return msg::fbuf::ledger::CreateUnl_Changeset( + _fbb, + additions__, + removals__); } inline const msg::fbuf::ledger::LedgerBlock *GetLedgerBlock(const void *buf) { diff --git a/src/msg/fbuf/p2pmsg_content.fbs b/src/msg/fbuf/p2pmsg_content.fbs index 5e5f6e5d..2a43aa8a 100644 --- a/src/msg/fbuf/p2pmsg_content.fbs +++ b/src/msg/fbuf/p2pmsg_content.fbs @@ -49,6 +49,11 @@ table NonUnl_Proposal_Message { user_inputs:[UserInputGroup]; } +table Unl_Changeset { + additions:[ByteArray]; + removals:[ByteArray]; +} + table Proposal_Message { //Proposal type message schema stage:uint8; time:uint64; @@ -57,6 +62,7 @@ table Proposal_Message { //Proposal type message schema hash_inputs:[ByteArray]; hash_outputs:[ByteArray]; state: [ubyte]; + unl_changeset: Unl_Changeset; } table Npl_Message { //NPL type message schema diff --git a/src/msg/fbuf/p2pmsg_content_generated.h b/src/msg/fbuf/p2pmsg_content_generated.h index 8be63158..1a4c9821 100644 --- a/src/msg/fbuf/p2pmsg_content_generated.h +++ b/src/msg/fbuf/p2pmsg_content_generated.h @@ -30,6 +30,9 @@ struct ContentBuilder; struct NonUnl_Proposal_Message; struct NonUnl_Proposal_MessageBuilder; +struct Unl_Changeset; +struct Unl_ChangesetBuilder; + struct Proposal_Message; struct Proposal_MessageBuilder; @@ -336,7 +339,6 @@ 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); @@ -408,7 +410,6 @@ 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); @@ -491,7 +492,6 @@ 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); @@ -568,7 +568,6 @@ 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); @@ -728,7 +727,6 @@ 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); @@ -777,7 +775,6 @@ 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); @@ -802,6 +799,79 @@ inline flatbuffers::Offset CreateNonUnl_Proposal_Messag user_inputs__); } +struct Unl_Changeset FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef Unl_ChangesetBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_ADDITIONS = 4, + VT_REMOVALS = 6 + }; + const flatbuffers::Vector> *additions() const { + return GetPointer> *>(VT_ADDITIONS); + } + flatbuffers::Vector> *mutable_additions() { + return GetPointer> *>(VT_ADDITIONS); + } + const flatbuffers::Vector> *removals() const { + return GetPointer> *>(VT_REMOVALS); + } + flatbuffers::Vector> *mutable_removals() { + return GetPointer> *>(VT_REMOVALS); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_ADDITIONS) && + verifier.VerifyVector(additions()) && + verifier.VerifyVectorOfTables(additions()) && + VerifyOffset(verifier, VT_REMOVALS) && + verifier.VerifyVector(removals()) && + verifier.VerifyVectorOfTables(removals()) && + verifier.EndTable(); + } +}; + +struct Unl_ChangesetBuilder { + typedef Unl_Changeset Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_additions(flatbuffers::Offset>> additions) { + fbb_.AddOffset(Unl_Changeset::VT_ADDITIONS, additions); + } + void add_removals(flatbuffers::Offset>> removals) { + fbb_.AddOffset(Unl_Changeset::VT_REMOVALS, removals); + } + explicit Unl_ChangesetBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateUnl_Changeset( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset>> additions = 0, + flatbuffers::Offset>> removals = 0) { + Unl_ChangesetBuilder builder_(_fbb); + builder_.add_removals(removals); + builder_.add_additions(additions); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateUnl_ChangesetDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector> *additions = nullptr, + const std::vector> *removals = nullptr) { + auto additions__ = additions ? _fbb.CreateVector>(*additions) : 0; + auto removals__ = removals ? _fbb.CreateVector>(*removals) : 0; + return msg::fbuf::p2pmsg::CreateUnl_Changeset( + _fbb, + additions__, + removals__); +} + struct Proposal_Message FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { typedef Proposal_MessageBuilder Builder; enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { @@ -811,7 +881,8 @@ struct Proposal_Message FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_USERS = 10, VT_HASH_INPUTS = 12, VT_HASH_OUTPUTS = 14, - VT_STATE = 16 + VT_STATE = 16, + VT_UNL_CHANGESET = 18 }; uint8_t stage() const { return GetField(VT_STAGE, 0); @@ -855,6 +926,12 @@ struct Proposal_Message FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { flatbuffers::Vector *mutable_state() { return GetPointer *>(VT_STATE); } + const msg::fbuf::p2pmsg::Unl_Changeset *unl_changeset() const { + return GetPointer(VT_UNL_CHANGESET); + } + msg::fbuf::p2pmsg::Unl_Changeset *mutable_unl_changeset() { + return GetPointer(VT_UNL_CHANGESET); + } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField(verifier, VT_STAGE) && @@ -872,6 +949,8 @@ struct Proposal_Message FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { verifier.VerifyVectorOfTables(hash_outputs()) && VerifyOffset(verifier, VT_STATE) && verifier.VerifyVector(state()) && + VerifyOffset(verifier, VT_UNL_CHANGESET) && + verifier.VerifyTable(unl_changeset()) && verifier.EndTable(); } }; @@ -901,11 +980,13 @@ struct Proposal_MessageBuilder { void add_state(flatbuffers::Offset> state) { fbb_.AddOffset(Proposal_Message::VT_STATE, state); } + void add_unl_changeset(flatbuffers::Offset unl_changeset) { + fbb_.AddOffset(Proposal_Message::VT_UNL_CHANGESET, unl_changeset); + } explicit Proposal_MessageBuilder(flatbuffers::FlatBufferBuilder &_fbb) : 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); @@ -921,9 +1002,11 @@ inline flatbuffers::Offset CreateProposal_Message( flatbuffers::Offset>> users = 0, flatbuffers::Offset>> hash_inputs = 0, flatbuffers::Offset>> hash_outputs = 0, - flatbuffers::Offset> state = 0) { + flatbuffers::Offset> state = 0, + flatbuffers::Offset unl_changeset = 0) { Proposal_MessageBuilder builder_(_fbb); builder_.add_time(time); + builder_.add_unl_changeset(unl_changeset); builder_.add_state(state); builder_.add_hash_outputs(hash_outputs); builder_.add_hash_inputs(hash_inputs); @@ -941,7 +1024,8 @@ inline flatbuffers::Offset CreateProposal_MessageDirect( const std::vector> *users = nullptr, const std::vector> *hash_inputs = nullptr, const std::vector> *hash_outputs = nullptr, - const std::vector *state = nullptr) { + const std::vector *state = nullptr, + flatbuffers::Offset unl_changeset = 0) { auto nonce__ = nonce ? _fbb.CreateVector(*nonce) : 0; auto users__ = users ? _fbb.CreateVector>(*users) : 0; auto hash_inputs__ = hash_inputs ? _fbb.CreateVector>(*hash_inputs) : 0; @@ -955,7 +1039,8 @@ inline flatbuffers::Offset CreateProposal_MessageDirect( users__, hash_inputs__, hash_outputs__, - state__); + state__, + unl_changeset); } struct Npl_Message FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { @@ -988,7 +1073,6 @@ 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); @@ -1043,7 +1127,6 @@ 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); @@ -1122,7 +1205,6 @@ 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); @@ -1197,7 +1279,6 @@ 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); @@ -1257,7 +1338,6 @@ 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); @@ -1351,7 +1431,6 @@ 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); @@ -1473,7 +1552,6 @@ 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); @@ -1542,7 +1620,6 @@ 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); @@ -1608,7 +1685,6 @@ 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); @@ -1678,7 +1754,6 @@ 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); @@ -1760,7 +1835,6 @@ 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); @@ -1823,7 +1897,6 @@ 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); @@ -1879,7 +1952,6 @@ 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); @@ -1913,7 +1985,6 @@ 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); @@ -1958,7 +2029,6 @@ 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); @@ -2046,7 +2116,6 @@ 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 1b48247c..1bf738e9 100644 --- a/src/msg/fbuf/p2pmsg_helpers.cpp +++ b/src/msg/fbuf/p2pmsg_helpers.cpp @@ -232,6 +232,10 @@ namespace msg::fbuf::p2pmsg p.lcl = flatbuff_bytes_to_sv(lcl); p.state = flatbuff_bytes_to_sv(msg.state()); + const auto unl_changeset = msg.unl_changeset(); + p.unl_changeset.additions = flatbuf_bytearrayvector_to_stringlist(unl_changeset->additions()); + p.unl_changeset.removals = flatbuf_bytearrayvector_to_stringlist(unl_changeset->removals()); + if (msg.users()) p.users = flatbuf_bytearrayvector_to_stringlist(msg.users()); @@ -368,6 +372,12 @@ namespace msg::fbuf::p2pmsg // todo:get a average propsal message size and allocate content builder based on that. flatbuffers::FlatBufferBuilder builder(1024); + const flatbuffers::Offset unl_changeset = CreateUnl_Changeset( + builder, + stringlist_to_flatbuf_bytearrayvector(builder, p.unl_changeset.additions), + stringlist_to_flatbuf_bytearrayvector(builder, p.unl_changeset.removals) + ); + const flatbuffers::Offset proposal = CreateProposal_Message( builder, @@ -377,7 +387,8 @@ namespace msg::fbuf::p2pmsg stringlist_to_flatbuf_bytearrayvector(builder, p.users), stringlist_to_flatbuf_bytearrayvector(builder, p.hash_inputs), stringlist_to_flatbuf_bytearrayvector(builder, p.hash_outputs), - hash_to_flatbuff_bytes(builder, p.state)); + hash_to_flatbuff_bytes(builder, p.state), + unl_changeset); const flatbuffers::Offset message = CreateContent(builder, Message_Proposal_Message, proposal.Union()); builder.Finish(message); // Finished building message content to get serialised content. diff --git a/src/msg/json/controlmsg_json.cpp b/src/msg/json/controlmsg_json.cpp index 252371f8..768bfc6a 100644 --- a/src/msg/json/controlmsg_json.cpp +++ b/src/msg/json/controlmsg_json.cpp @@ -66,14 +66,14 @@ namespace msg::controlmsg::json * "remove": ["pk1","pk2",...] * } */ - int extract_unl_changeset(std::vector &additions, std::vector &removals, const jsoncons::json &d) + int extract_unl_changeset(std::set &additions, std::set &removals, const jsoncons::json &d) { - extract_string_array(additions, d, FLD_ADD); - extract_string_array(removals, d, FLD_REMOVE); + extract_string_set(additions, d, FLD_ADD); + extract_string_set(removals, d, FLD_REMOVE); return 0; } - void extract_string_array(std::vector &vec, const jsoncons::json &d, const char *field_name) + void extract_string_set(std::set &vec, const jsoncons::json &d, const char *field_name) { if (!d.contains(field_name) || !d[field_name].is_array()) return; @@ -88,7 +88,7 @@ namespace msg::controlmsg::json bin_pubkey.length(), hex_pubkey) != -1) { - vec.push_back(bin_pubkey); + vec.emplace(bin_pubkey); } } } diff --git a/src/msg/json/controlmsg_json.hpp b/src/msg/json/controlmsg_json.hpp index 8ea7c5cf..6b0b57f8 100644 --- a/src/msg/json/controlmsg_json.hpp +++ b/src/msg/json/controlmsg_json.hpp @@ -12,9 +12,9 @@ namespace msg::controlmsg::json int extract_type(std::string &extracted_type, const jsoncons::json &d); - int extract_unl_changeset(std::vector &additions, std::vector &removals, const jsoncons::json &d); + int extract_unl_changeset(std::set &additions, std::set &removals, const jsoncons::json &d); - void extract_string_array(std::vector &vec, const jsoncons::json &d, const char *field_name); + void extract_string_set(std::set &vec, const jsoncons::json &d, const char *field_name); } // namespace msg::controlmsg::json diff --git a/src/p2p/p2p.hpp b/src/p2p/p2p.hpp index 757b234e..0443de8a 100644 --- a/src/p2p/p2p.hpp +++ b/src/p2p/p2p.hpp @@ -18,6 +18,30 @@ namespace p2p constexpr uint16_t STATE_RES_LIST_CAP = 64; // Maximum state response count. constexpr uint16_t PEER_LIST_CAP = 64; // Maximum peer count. + struct contract_unl_changeset + { + std::set additions; // Pubkeys of the peers that need to be added to the unl. + std::set removals; // Pubkeys of the peers that need to be removed from the unl. + + void clear() + { + additions.clear(); + removals.clear(); + } + + // If there are items which are in both additions and removals. Remove them from the both sets. + void purify() + { + std::set intersect; + std::set_intersection(additions.begin(), additions.end(), removals.begin(), removals.end(), std::inserter(intersect, intersect.begin())); + for (const auto &item : intersect) + { + additions.erase(item); + removals.erase(item); + } + } + }; + struct proposal { std::string pubkey; @@ -31,6 +55,7 @@ namespace p2p std::set users; std::set hash_inputs; std::set hash_outputs; + contract_unl_changeset unl_changeset; // Additions and removals of the unl. }; struct nonunl_proposal diff --git a/src/sc.cpp b/src/sc.cpp index fd672790..a21dc5eb 100644 --- a/src/sc.cpp +++ b/src/sc.cpp @@ -823,9 +823,10 @@ namespace sc } else if (type == msg::controlmsg::MSGTYPE_UNL_CHANGESET && !ctx.args.readonly) { - std::vector additions, removals; - parser.extract_unl_changeset(additions, removals); - unl::update(additions, removals); + // Populate the received change set. Changeset will be affected after going through the consensus. + // Since changesets are std::set objects. It'll maintain a sorted set. + parser.extract_unl_changeset(ctx.args.unl_changeset.additions, ctx.args.unl_changeset.removals); + ctx.args.unl_changeset.purify(); } } diff --git a/src/sc.hpp b/src/sc.hpp index 75a633a7..f06c0aec 100644 --- a/src/sc.hpp +++ b/src/sc.hpp @@ -83,6 +83,9 @@ namespace sc // State hash after execution will be copied to this (not applicable to read only mode). hpfs::h32 post_execution_state_hash = hpfs::h32_empty; + // Collected unl addition and removal change sets. Holds the changeset until they are subjected to the consensus. + p2p::contract_unl_changeset unl_changeset; + contract_execution_args(util::buffer_store &user_input_store) : user_input_store(user_input_store), npl_messages(MAX_NPL_MSG_QUEUE_SIZE), diff --git a/src/unl.cpp b/src/unl.cpp index adf69bc0..226fe226 100644 --- a/src/unl.cpp +++ b/src/unl.cpp @@ -59,7 +59,7 @@ namespace unl /** * Called by contract to update unl at runtime. */ - void update(const std::vector &additions, const std::vector &removals) + void update(const std::set &additions, const std::set &removals) { if (additions.empty() && removals.empty()) return; diff --git a/src/unl.hpp b/src/unl.hpp index f06a4b90..edfab66e 100644 --- a/src/unl.hpp +++ b/src/unl.hpp @@ -13,7 +13,7 @@ namespace unl std::string get_json(); bool exists(const std::string &bin_pubkey); void init(const std::set &init_list); - void update(const std::vector &additions, const std::vector &removals); + void update(const std::set &additions, const std::set &removals); void update_json_list(); } // namespace unl