#ifndef _HP_CONS_ #define _HP_CONS_ #include "../pchheader.hpp" #include "../util.hpp" #include "../proc/proc.hpp" #include "../p2p/p2p.hpp" #include "../usr/user_input.hpp" namespace cons { //stage 1 vote threshold static const float STAGE1_THRESHOLD = 0.5; //stage 2 vote threshold static const float STAGE2_THRESHOLD = 0.65; //stage 3 vote threshold static const float STAGE3_THRESHOLD = 0.8; /** * Represents a contract input that takes part in consensus. */ struct candidate_user_input { const std::string userpubkey; const uint64_t maxledgerseqno; std::string input; candidate_user_input(const std::string userpubkey, const std::string input, const uint64_t maxledgerseqno) : userpubkey(std::move(userpubkey)), input(std::move(input)), maxledgerseqno(maxledgerseqno) { } }; /** * Represents a contract output that takes part in consensus. */ struct candidate_user_output { const std::string userpubkey; std::string output; candidate_user_output(const std::string userpubkey, const std::string output) : userpubkey(std::move(userpubkey)), output(std::move(output)) { } }; /** * This is used to store consensus information */ struct consensus_context { // The set of proposals that are being collected as consensus stages are progressing. std::list candidate_proposals; // Set of user pubkeys that is said to be connected to the cluster. This will be cleared in each round. std::unordered_set candidate_users; // Map of candidate user inputs with input hash as map key. Inputs will stay here until they // achieve consensus or expire (due to maxledgerseqno). Input hash is globally unique among inputs // from all users. We will use this map to feed inputs into the contract once consensus is achieved. std::unordered_map candidate_user_inputs; // Map of outputs generated by the contract with output hash is the map key. Outputs will stay // here until the end of the current consensus round. Output hash is globally unique among outputs for // all users. We will use this map to distribute outputs back to connected users once consensus is achieved. std::unordered_map candidate_user_outputs; util::rollover_hashset recent_userinput_hashes; uint8_t stage; uint64_t novel_proposal_time; uint64_t time_now; std::string lcl; uint64_t led_seq_no; consensus_context() : recent_userinput_hashes(200) { } }; struct vote_counter { std::map stage; std::map time; std::map lcl; std::map users; std::map inputs; std::map outputs; }; extern consensus_context ctx; int init(); void consensus(); void broadcast_nonunl_proposal(); void verify_and_populate_candidate_user_inputs(); p2p::proposal create_stage0_proposal(); p2p::proposal create_stage123_proposal(vote_counter &votes); void broadcast_proposal(const p2p::proposal &p); void check_majority_stage(bool &is_desync, bool &should_reset, uint8_t &majority_stage, vote_counter &votes); void check_lcl_votes(bool &is_desync, bool &should_request_history, std::string &majority_lcl, vote_counter &votes); float_t get_stage_threshold(const uint8_t stage); void timewait_stage(const bool reset); void apply_ledger(const p2p::proposal &proposal); void dispatch_user_outputs(const p2p::proposal &cons_prop); void feed_inputs_to_contract_bufmap(proc::contract_bufmap_t &bufmap, const p2p::proposal &cons_prop); void extract_outputs_from_contract_bufmap(proc::contract_bufmap_t &bufmap); void run_contract_binary(const int64_t time_now, proc::contract_bufmap_t &useriobufmap); template void increment(std::map &counter, const T &candidate); } // namespace cons #endif