Files
hpcore/src/cons/cons.hpp

168 lines
5.2 KiB
C++

#ifndef _HP_CONS_
#define _HP_CONS_
#include "../pchheader.hpp"
#include "../util.hpp"
#include "../sc.hpp"
#include "../p2p/p2p.hpp"
#include "../usr/user_input.hpp"
#include "../hpfs/h32.hpp"
#include "../sc.hpp"
#include "ledger_handler.hpp"
namespace cons
{
/**
* 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 map of proposals that are being collected as consensus stages are progressing.
// peer public key is the key.
// todo: having a queue of proposals against peer pubkey.
std::unordered_map<std::string, const p2p::proposal> candidate_proposals;
// The set of npl messages that are being collected as consensus stages are progressing.
std::list<p2p::npl_message> candidate_npl_messages;
// 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 = 0;
uint64_t time_now = 0;
std::string lcl;
uint64_t led_seq_no = 0;
hpfs::h32 state = hpfs::h32_empty;
//Map of closed ledgers(only lrdgername[sequnece_number-hash], state hash) with sequence number as map key.
//contains closed ledgers from latest to latest - MAX_LEDGER_SEQUENCE.
//this is loaded when node started and updated throughout consensus - delete ledgers that falls behind MAX_LEDGER_SEQUENCE range.
//We will use this to track lcls related logic.- track state, lcl request, response.
std::map<uint64_t, ledger_cache_entry> ledger_cache;
std::string last_requested_lcl;
//ledger close time of previous hash
uint16_t stage_time = 0; // Time allocated to a consensus stage.
uint16_t stage_reset_wait_threshold = 0; // Minimum stage wait time to reset the stage.
std::mutex state_sync_lock;
sc::execution_context contract_ctx;
bool is_shutting_down = false;
consensus_context()
: recent_userinput_hashes(200)
{
}
};
struct vote_counter
{
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;
std::map<hpfs::h32, int32_t> state;
};
extern consensus_context ctx;
int init();
void deinit();
int run_consensus();
int consensus();
void purify_candidate_proposals();
bool wait_and_proceed_stage(uint64_t &stage_start);
void broadcast_nonunl_proposal();
void verify_and_populate_candidate_user_inputs();
bool verify_appbill_check(std::string_view pubkey, const size_t input_len);
p2p::proposal create_stage0_proposal();
p2p::proposal create_stage123_proposal(vote_counter &votes);
void broadcast_proposal(const p2p::proposal &p);
void check_lcl_votes(bool &is_desync, bool &should_request_history, std::string &majority_lcl, vote_counter &votes);
void check_state_votes(bool &is_desync, hpfs::h32 &majority_state, vote_counter &votes);
float_t get_stage_threshold(const uint8_t stage);
void timewait_stage(const bool reset, const uint64_t time);
uint64_t get_ledger_time_resolution(const uint64_t time);
uint64_t get_stage_time_resolution(const uint64_t time);
int apply_ledger(const p2p::proposal &proposal);
void dispatch_user_outputs(const p2p::proposal &cons_prop);
void feed_user_inputs_to_contract_bufmap(sc::contract_bufmap_t &bufmap, const p2p::proposal &cons_prop);
void extract_user_outputs_from_contract_bufmap(sc::contract_bufmap_t &bufmap);
void broadcast_npl_output(std::string &output);
template <typename T>
void increment(std::map<T, int32_t> &counter, const T &candidate);
int get_initial_state_hash(hpfs::h32 &hash);
void on_state_sync_completion(const hpfs::h32 new_state);
} // namespace cons
#endif