mirror of
https://github.com/EvernodeXRPL/hpcore.git
synced 2026-04-29 15:37:59 +00:00
168 lines
5.2 KiB
C++
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
|