Subject UNL changeset to consensus. (#183)

This commit is contained in:
Chalith Desaman
2020-12-07 13:06:58 +05:30
committed by GitHub
parent da0eb08512
commit a87e8a0c7e
17 changed files with 309 additions and 49 deletions

View File

@@ -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();

View File

@@ -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<std::string, candidate_user_output> 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<std::string, uint32_t> inputs;
std::map<std::string, uint32_t> outputs;
std::map<hpfs::h32, uint32_t> state;
std::map<std::string, uint32_t> unl_additions;
std::map<std::string, uint32_t> unl_removals;
};
int init();

View File

@@ -16,7 +16,7 @@ namespace msg::controlmsg
return jctlmsg::extract_type(extracted_type, jdoc);
}
int controlmsg_parser::extract_unl_changeset(std::vector<std::string> &additions, std::vector<std::string> &removals)
int controlmsg_parser::extract_unl_changeset(std::set<std::string> &additions, std::set<std::string> &removals)
{
return jctlmsg::extract_unl_changeset(additions, removals, jdoc);
}

View File

@@ -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<std::string> &additions, std::vector<std::string> &removals);
int extract_unl_changeset(std::set<std::string> &additions, std::set<std::string> &removals);
};
} // namespace msg::controlmsg

View File

@@ -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> 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::LedgerBlock> 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.
}

View File

@@ -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;

View File

@@ -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<uint64_t>(VT_SEQ_NO, 0);
@@ -68,6 +72,12 @@ struct LedgerBlock FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *mutable_outputs() {
return GetPointer<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *>(VT_OUTPUTS);
}
const msg::fbuf::ledger::Unl_Changeset *unl_changeset() const {
return GetPointer<const msg::fbuf::ledger::Unl_Changeset *>(VT_UNL_CHANGESET);
}
msg::fbuf::ledger::Unl_Changeset *mutable_unl_changeset() {
return GetPointer<msg::fbuf::ledger::Unl_Changeset *>(VT_UNL_CHANGESET);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<uint64_t>(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<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>>> outputs) {
fbb_.AddOffset(LedgerBlock::VT_OUTPUTS, outputs);
}
void add_unl_changeset(flatbuffers::Offset<msg::fbuf::ledger::Unl_Changeset> 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<LedgerBlock> CreateLedgerBlock(
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> state = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>>> users = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>>> inputs = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>>> outputs = 0) {
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>>> outputs = 0,
flatbuffers::Offset<msg::fbuf::ledger::Unl_Changeset> 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<LedgerBlock> CreateLedgerBlockDirect(
const std::vector<uint8_t> *state = nullptr,
const std::vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *users = nullptr,
const std::vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *inputs = nullptr,
const std::vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *outputs = nullptr) {
const std::vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *outputs = nullptr,
flatbuffers::Offset<msg::fbuf::ledger::Unl_Changeset> unl_changeset = 0) {
auto lcl__ = lcl ? _fbb.CreateVector<uint8_t>(*lcl) : 0;
auto state__ = state ? _fbb.CreateVector<uint8_t>(*state) : 0;
auto users__ = users ? _fbb.CreateVector<flatbuffers::Offset<msg::fbuf::ByteArray>>(*users) : 0;
@@ -167,7 +185,81 @@ inline flatbuffers::Offset<LedgerBlock> 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<flatbuffers::Offset<msg::fbuf::ByteArray>> *additions() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *>(VT_ADDITIONS);
}
flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *mutable_additions() {
return GetPointer<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *>(VT_ADDITIONS);
}
const flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *removals() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *>(VT_REMOVALS);
}
flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *mutable_removals() {
return GetPointer<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *>(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<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>>> additions) {
fbb_.AddOffset(Unl_Changeset::VT_ADDITIONS, additions);
}
void add_removals(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>>> removals) {
fbb_.AddOffset(Unl_Changeset::VT_REMOVALS, removals);
}
explicit Unl_ChangesetBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
flatbuffers::Offset<Unl_Changeset> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Unl_Changeset>(end);
return o;
}
};
inline flatbuffers::Offset<Unl_Changeset> CreateUnl_Changeset(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>>> additions = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>>> removals = 0) {
Unl_ChangesetBuilder builder_(_fbb);
builder_.add_removals(removals);
builder_.add_additions(additions);
return builder_.Finish();
}
inline flatbuffers::Offset<Unl_Changeset> CreateUnl_ChangesetDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const std::vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *additions = nullptr,
const std::vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *removals = nullptr) {
auto additions__ = additions ? _fbb.CreateVector<flatbuffers::Offset<msg::fbuf::ByteArray>>(*additions) : 0;
auto removals__ = removals ? _fbb.CreateVector<flatbuffers::Offset<msg::fbuf::ByteArray>>(*removals) : 0;
return msg::fbuf::ledger::CreateUnl_Changeset(
_fbb,
additions__,
removals__);
}
inline const msg::fbuf::ledger::LedgerBlock *GetLedgerBlock(const void *buf) {

View File

@@ -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

View File

@@ -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<Peer_Challenge_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Peer_Challenge_Message>(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<Peer_Challenge_Response_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Peer_Challenge_Response_Message>(end);
@@ -491,7 +492,6 @@ struct UserInputBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
UserInputBuilder &operator=(const UserInputBuilder &);
flatbuffers::Offset<UserInput> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<UserInput>(end);
@@ -568,7 +568,6 @@ struct UserInputGroupBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
UserInputGroupBuilder &operator=(const UserInputGroupBuilder &);
flatbuffers::Offset<UserInputGroup> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<UserInputGroup>(end);
@@ -728,7 +727,6 @@ struct ContentBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
ContentBuilder &operator=(const ContentBuilder &);
flatbuffers::Offset<Content> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Content>(end);
@@ -777,7 +775,6 @@ struct NonUnl_Proposal_MessageBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
NonUnl_Proposal_MessageBuilder &operator=(const NonUnl_Proposal_MessageBuilder &);
flatbuffers::Offset<NonUnl_Proposal_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<NonUnl_Proposal_Message>(end);
@@ -802,6 +799,79 @@ inline flatbuffers::Offset<NonUnl_Proposal_Message> 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<flatbuffers::Offset<msg::fbuf::ByteArray>> *additions() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *>(VT_ADDITIONS);
}
flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *mutable_additions() {
return GetPointer<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *>(VT_ADDITIONS);
}
const flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *removals() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *>(VT_REMOVALS);
}
flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *mutable_removals() {
return GetPointer<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *>(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<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>>> additions) {
fbb_.AddOffset(Unl_Changeset::VT_ADDITIONS, additions);
}
void add_removals(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>>> removals) {
fbb_.AddOffset(Unl_Changeset::VT_REMOVALS, removals);
}
explicit Unl_ChangesetBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
flatbuffers::Offset<Unl_Changeset> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Unl_Changeset>(end);
return o;
}
};
inline flatbuffers::Offset<Unl_Changeset> CreateUnl_Changeset(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>>> additions = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>>> removals = 0) {
Unl_ChangesetBuilder builder_(_fbb);
builder_.add_removals(removals);
builder_.add_additions(additions);
return builder_.Finish();
}
inline flatbuffers::Offset<Unl_Changeset> CreateUnl_ChangesetDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const std::vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *additions = nullptr,
const std::vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *removals = nullptr) {
auto additions__ = additions ? _fbb.CreateVector<flatbuffers::Offset<msg::fbuf::ByteArray>>(*additions) : 0;
auto removals__ = removals ? _fbb.CreateVector<flatbuffers::Offset<msg::fbuf::ByteArray>>(*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<uint8_t>(VT_STAGE, 0);
@@ -855,6 +926,12 @@ struct Proposal_Message FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
flatbuffers::Vector<uint8_t> *mutable_state() {
return GetPointer<flatbuffers::Vector<uint8_t> *>(VT_STATE);
}
const msg::fbuf::p2pmsg::Unl_Changeset *unl_changeset() const {
return GetPointer<const msg::fbuf::p2pmsg::Unl_Changeset *>(VT_UNL_CHANGESET);
}
msg::fbuf::p2pmsg::Unl_Changeset *mutable_unl_changeset() {
return GetPointer<msg::fbuf::p2pmsg::Unl_Changeset *>(VT_UNL_CHANGESET);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<uint8_t>(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<flatbuffers::Vector<uint8_t>> state) {
fbb_.AddOffset(Proposal_Message::VT_STATE, state);
}
void add_unl_changeset(flatbuffers::Offset<msg::fbuf::p2pmsg::Unl_Changeset> 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<Proposal_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Proposal_Message>(end);
@@ -921,9 +1002,11 @@ inline flatbuffers::Offset<Proposal_Message> CreateProposal_Message(
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>>> users = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>>> hash_inputs = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::ByteArray>>> hash_outputs = 0,
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> state = 0) {
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> state = 0,
flatbuffers::Offset<msg::fbuf::p2pmsg::Unl_Changeset> 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<Proposal_Message> CreateProposal_MessageDirect(
const std::vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *users = nullptr,
const std::vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *hash_inputs = nullptr,
const std::vector<flatbuffers::Offset<msg::fbuf::ByteArray>> *hash_outputs = nullptr,
const std::vector<uint8_t> *state = nullptr) {
const std::vector<uint8_t> *state = nullptr,
flatbuffers::Offset<msg::fbuf::p2pmsg::Unl_Changeset> unl_changeset = 0) {
auto nonce__ = nonce ? _fbb.CreateVector<uint8_t>(*nonce) : 0;
auto users__ = users ? _fbb.CreateVector<flatbuffers::Offset<msg::fbuf::ByteArray>>(*users) : 0;
auto hash_inputs__ = hash_inputs ? _fbb.CreateVector<flatbuffers::Offset<msg::fbuf::ByteArray>>(*hash_inputs) : 0;
@@ -955,7 +1039,8 @@ inline flatbuffers::Offset<Proposal_Message> 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<Npl_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Npl_Message>(end);
@@ -1043,7 +1127,6 @@ struct History_Request_MessageBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
History_Request_MessageBuilder &operator=(const History_Request_MessageBuilder &);
flatbuffers::Offset<History_Request_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<History_Request_Message>(end);
@@ -1122,7 +1205,6 @@ struct History_Response_MessageBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
History_Response_MessageBuilder &operator=(const History_Response_MessageBuilder &);
flatbuffers::Offset<History_Response_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<History_Response_Message>(end);
@@ -1197,7 +1279,6 @@ struct HistoryLedgerBlockPairBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
HistoryLedgerBlockPairBuilder &operator=(const HistoryLedgerBlockPairBuilder &);
flatbuffers::Offset<HistoryLedgerBlockPair> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<HistoryLedgerBlockPair>(end);
@@ -1257,7 +1338,6 @@ struct HistoryLedgerBlockBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
HistoryLedgerBlockBuilder &operator=(const HistoryLedgerBlockBuilder &);
flatbuffers::Offset<HistoryLedgerBlock> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<HistoryLedgerBlock>(end);
@@ -1351,7 +1431,6 @@ struct State_Request_MessageBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
State_Request_MessageBuilder &operator=(const State_Request_MessageBuilder &);
flatbuffers::Offset<State_Request_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<State_Request_Message>(end);
@@ -1473,7 +1552,6 @@ struct State_Response_MessageBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
State_Response_MessageBuilder &operator=(const State_Response_MessageBuilder &);
flatbuffers::Offset<State_Response_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<State_Response_Message>(end);
@@ -1542,7 +1620,6 @@ struct Fs_Entry_ResponseBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
Fs_Entry_ResponseBuilder &operator=(const Fs_Entry_ResponseBuilder &);
flatbuffers::Offset<Fs_Entry_Response> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Fs_Entry_Response>(end);
@@ -1608,7 +1685,6 @@ struct File_HashMap_ResponseBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
File_HashMap_ResponseBuilder &operator=(const File_HashMap_ResponseBuilder &);
flatbuffers::Offset<File_HashMap_Response> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<File_HashMap_Response>(end);
@@ -1678,7 +1754,6 @@ struct Block_ResponseBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
Block_ResponseBuilder &operator=(const Block_ResponseBuilder &);
flatbuffers::Offset<Block_Response> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Block_Response>(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<State_FS_Hash_Entry> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<State_FS_Hash_Entry>(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<Peer_Requirement_Announcement_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Peer_Requirement_Announcement_Message>(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<Available_Capacity_Announcement_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Available_Capacity_Announcement_Message>(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<Peer_List_Request_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Peer_List_Request_Message>(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<Peer_List_Response_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Peer_List_Response_Message>(end);
@@ -2046,7 +2116,6 @@ struct Peer_PropertiesBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
Peer_PropertiesBuilder &operator=(const Peer_PropertiesBuilder &);
flatbuffers::Offset<Peer_Properties> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Peer_Properties>(end);

View File

@@ -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> 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_Message> 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<Content> message = CreateContent(builder, Message_Proposal_Message, proposal.Union());
builder.Finish(message); // Finished building message content to get serialised content.

View File

@@ -66,14 +66,14 @@ namespace msg::controlmsg::json
* "remove": ["pk1","pk2",...]
* }
*/
int extract_unl_changeset(std::vector<std::string> &additions, std::vector<std::string> &removals, const jsoncons::json &d)
int extract_unl_changeset(std::set<std::string> &additions, std::set<std::string> &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<std::string> &vec, const jsoncons::json &d, const char *field_name)
void extract_string_set(std::set<std::string> &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);
}
}
}

View File

@@ -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<std::string> &additions, std::vector<std::string> &removals, const jsoncons::json &d);
int extract_unl_changeset(std::set<std::string> &additions, std::set<std::string> &removals, const jsoncons::json &d);
void extract_string_array(std::vector<std::string> &vec, const jsoncons::json &d, const char *field_name);
void extract_string_set(std::set<std::string> &vec, const jsoncons::json &d, const char *field_name);
} // namespace msg::controlmsg::json

View File

@@ -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<std::string> additions; // Pubkeys of the peers that need to be added to the unl.
std::set<std::string> 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<std::string> 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<std::string> users;
std::set<std::string> hash_inputs;
std::set<std::string> hash_outputs;
contract_unl_changeset unl_changeset; // Additions and removals of the unl.
};
struct nonunl_proposal

View File

@@ -823,9 +823,10 @@ namespace sc
}
else if (type == msg::controlmsg::MSGTYPE_UNL_CHANGESET && !ctx.args.readonly)
{
std::vector<std::string> 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();
}
}

View File

@@ -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),

View File

@@ -59,7 +59,7 @@ namespace unl
/**
* Called by contract to update unl at runtime.
*/
void update(const std::vector<std::string> &additions, const std::vector<std::string> &removals)
void update(const std::set<std::string> &additions, const std::set<std::string> &removals)
{
if (additions.empty() && removals.empty())
return;

View File

@@ -13,7 +13,7 @@ namespace unl
std::string get_json();
bool exists(const std::string &bin_pubkey);
void init(const std::set<std::string> &init_list);
void update(const std::vector<std::string> &additions, const std::vector<std::string> &removals);
void update(const std::set<std::string> &additions, const std::set<std::string> &removals);
void update_json_list();
} // namespace unl