Files
hpcore/src/cons/cons.hpp
2019-11-09 07:38:26 +05:30

133 lines
3.9 KiB
C++

#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<p2p::proposal> 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<std::string> 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<std::string, candidate_user_input> 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<std::string, candidate_user_output> 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<uint8_t, int32_t> stage;
std::map<uint64_t, int32_t> time;
std::map<std::string, int32_t> lcl;
std::map<std::string, int32_t> users;
std::map<std::string, int32_t> inputs;
std::map<std::string, int32_t> 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 <typename T>
void increment(std::map<T, int32_t> &counter, const T &candidate);
} // namespace cons
#endif