mirror of
https://github.com/EvernodeXRPL/hpcore.git
synced 2026-04-29 15:37:59 +00:00
166 lines
6.1 KiB
C++
166 lines
6.1 KiB
C++
#ifndef _HP_CONS_
|
|
#define _HP_CONS_
|
|
|
|
#include "pchheader.hpp"
|
|
#include "util/util.hpp"
|
|
#include "util/buffer_store.hpp"
|
|
#include "util/merkle_hash_tree.hpp"
|
|
#include "./sc/sc.hpp"
|
|
#include "p2p/p2p.hpp"
|
|
#include "usr/user_input.hpp"
|
|
#include "util/h32.hpp"
|
|
|
|
namespace consensus
|
|
{
|
|
/**
|
|
* Represents a contract input that takes part in consensus.
|
|
*/
|
|
struct candidate_user_input
|
|
{
|
|
const std::string userpubkey;
|
|
const uint64_t maxledgerseqno = 0;
|
|
const util::buffer_view input;
|
|
|
|
candidate_user_input(const std::string userpubkey, const util::buffer_view input, const uint64_t maxledgerseqno)
|
|
: userpubkey(std::move(userpubkey)), input(input), maxledgerseqno(maxledgerseqno)
|
|
{
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Represents a contract-generated user output that takes part in consensus.
|
|
*/
|
|
struct generated_user_output
|
|
{
|
|
const std::string userpubkey;
|
|
std::list<sc::contract_output> outputs;
|
|
|
|
generated_user_output(const std::string userpubkey, const std::list<sc::contract_output> outputs)
|
|
: userpubkey(std::move(userpubkey)), outputs(std::move(outputs))
|
|
{
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 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;
|
|
|
|
// Set of user pubkeys that is said to be connected to the cluster. This will be cleared in each round.
|
|
std::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::map<std::string, candidate_user_input> candidate_user_inputs;
|
|
|
|
// Map of outputs generated by the contract with output hash as 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::map<std::string, generated_user_output> generated_user_outputs;
|
|
util::merkle_hash_tree user_outputs_hashtree;
|
|
std::string user_outputs_our_sig;
|
|
std::vector<std::pair<std::string, std::string>> user_outputs_unl_sig;
|
|
|
|
uint8_t stage = 1;
|
|
uint64_t round_start_time = 0;
|
|
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.
|
|
uint64_t round_boundry_offset = 0; // Time window boundry offset based on contract id.
|
|
uint16_t unreliable_votes_attempts = 0; // No. of times we failed to get reliable votes continously.
|
|
|
|
std::optional<sc::execution_context> contract_ctx;
|
|
std::mutex contract_ctx_mutex;
|
|
bool is_shutting_down = false;
|
|
|
|
std::thread consensus_thread;
|
|
|
|
consensus_context() : user_outputs_hashtree(16)
|
|
{
|
|
}
|
|
};
|
|
|
|
struct vote_counter
|
|
{
|
|
std::map<uint64_t, uint32_t> time;
|
|
std::map<std::string, uint32_t> nonce;
|
|
std::map<std::string, uint32_t> lcl;
|
|
std::map<std::string, uint32_t> users;
|
|
std::map<std::string, uint32_t> inputs;
|
|
std::map<std::string, uint32_t> output_hash;
|
|
std::map<util::h32, uint32_t> state_hash;
|
|
std::map<util::h32, uint32_t> patch_hash;
|
|
};
|
|
|
|
extern std::atomic<bool> is_patch_update_pending; // Keep track whether the patch file is changed by the SC and is not yet applied to runtime.
|
|
|
|
int init();
|
|
|
|
void deinit();
|
|
|
|
void wait();
|
|
|
|
void run_consensus();
|
|
|
|
int consensus();
|
|
|
|
int check_sync_status(std::string_view lcl, const size_t unl_count, vote_counter &votes);
|
|
|
|
void check_sync_completion();
|
|
|
|
void revise_candidate_proposals();
|
|
|
|
bool wait_and_proceed_stage();
|
|
|
|
void broadcast_nonunl_proposal();
|
|
|
|
bool push_npl_message(p2p::npl_message &npl_message);
|
|
|
|
int verify_and_populate_candidate_user_inputs(const uint64_t lcl_seq_no);
|
|
|
|
p2p::proposal create_stage0_proposal(std::string_view lcl, util::h32 state_hash, util::h32 patch_hash);
|
|
|
|
p2p::proposal create_stage123_proposal(vote_counter &votes, std::string_view lcl, const size_t unl_count, const util::h32 state_hash, const util::h32 patch_hash);
|
|
|
|
void broadcast_proposal(const p2p::proposal &p);
|
|
|
|
bool check_lcl_votes(bool &is_desync, std::string &majority_lcl, vote_counter &votes, std::string_view lcl, const size_t unl_count);
|
|
|
|
void check_state_votes(bool &is_state_desync, util::h32 &majority_state_hash, vote_counter &votes);
|
|
|
|
void check_patch_votes(bool &is_patch_desync, util::h32 &majority_patch_hash, vote_counter &votes);
|
|
|
|
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 update_ledger_and_execute_contract(const p2p::proposal &cons_prop, std::string &new_lcl, util::h32 &new_state_hash, const util::h32 &patch_hash);
|
|
|
|
int dispatch_user_outputs(const p2p::proposal &cons_prop, const uint64_t lcl_seq_no, std::string_view lcl);
|
|
|
|
int 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);
|
|
|
|
template <typename T>
|
|
void increment(std::map<T, uint32_t> &counter, const T &candidate);
|
|
|
|
int get_initial_state_hash(util::h32 &hash);
|
|
|
|
bool push_control_message(const std::string &control_msg);
|
|
|
|
int apply_consensed_patch_file_changes(const util::h32 &prop_patch_hash, const util::h32 ¤t_patch_hash);
|
|
|
|
void refresh_roundtime(const bool perform_detection);
|
|
|
|
} // namespace consensus
|
|
|
|
#endif
|