mirror of
https://github.com/EvernodeXRPL/hpcore.git
synced 2026-04-29 15:37:59 +00:00
Apply patch file changes only after consensus verification. (#222)
This commit is contained in:
committed by
GitHub
parent
73f5eea451
commit
146bb1d46c
@@ -25,9 +25,11 @@ namespace consensus
|
||||
constexpr float STAGE_THRESHOLDS[] = {0.5, 0.65, 0.8}; // Voting thresholds for stage 1,2,3
|
||||
constexpr float MAJORITY_THRESHOLD = 0.8;
|
||||
constexpr size_t ROUND_NONCE_SIZE = 64;
|
||||
constexpr const char *HPFS_SESSION_NAME = "ro_patch_file_to_hp";
|
||||
|
||||
consensus_context ctx;
|
||||
bool init_success = false;
|
||||
std::atomic<bool> is_patch_update_pending = false; // Keep track whether the patch file is changed by the SC and is not yet applied to runtime.
|
||||
|
||||
int init()
|
||||
{
|
||||
@@ -141,7 +143,7 @@ namespace consensus
|
||||
broadcast_proposal(p);
|
||||
|
||||
// Upon successful consensus at stage 3, update the ledger and execute the contract using the consensus proposal.
|
||||
if (ctx.stage == 3 && update_ledger_and_execute_contract(p, lcl, state_hash) == -1)
|
||||
if (ctx.stage == 3 && update_ledger_and_execute_contract(p, lcl, state_hash, patch_hash) == -1)
|
||||
LOG_ERROR << "Error occured in Stage 3 consensus execution.";
|
||||
}
|
||||
|
||||
@@ -192,6 +194,11 @@ namespace consensus
|
||||
check_patch_votes(is_patch_desync, majority_patch_hash, votes);
|
||||
check_state_votes(is_state_desync, majority_state_hash, votes);
|
||||
|
||||
// Stop any patch file updates triggered from the sc. The sync is triggered because the changes
|
||||
// done by the contract is not meeting consensus.
|
||||
if (is_patch_desync)
|
||||
is_patch_update_pending = false;
|
||||
|
||||
// Start hpfs sync if we are out-of-sync with majority hpfs state.
|
||||
if (is_state_desync || is_patch_desync)
|
||||
{
|
||||
@@ -784,8 +791,10 @@ namespace consensus
|
||||
/**
|
||||
* Update the ledger and execute the contract after consensus.
|
||||
* @param cons_prop The proposal that reached consensus.
|
||||
* @param new_state_hash The state hash.
|
||||
* @param patch_hash The patch hash.
|
||||
*/
|
||||
int update_ledger_and_execute_contract(const p2p::proposal &cons_prop, std::string &new_lcl, util::h32 &new_state_hash)
|
||||
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)
|
||||
{
|
||||
// Map to temporarily store the raw inputs along with the hash.
|
||||
std::unordered_map<std::string, usr::raw_user_input> raw_inputs;
|
||||
@@ -819,6 +828,10 @@ namespace consensus
|
||||
|
||||
LOG_INFO << "****Ledger created**** (lcl:" << new_lcl.substr(0, 15) << " state:" << cons_prop.state_hash << " patch:" << cons_prop.patch_hash << ")";
|
||||
|
||||
// Apply consensed patch file changes to the hpcore runtime and hp.cfg.
|
||||
if (apply_consensed_patch_file_changes(cons_prop.patch_hash, patch_hash) == -1)
|
||||
return -1;
|
||||
|
||||
// After the current ledger seq no is updated, we remove any newly expired inputs from candidate set.
|
||||
{
|
||||
auto itr = ctx.candidate_user_inputs.begin();
|
||||
@@ -1019,4 +1032,37 @@ namespace consensus
|
||||
counter.try_emplace(candidate, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply patch file changes after verification from consensus.
|
||||
* @param prop_patch_hash Hash of patch file which reached consensus.
|
||||
* @param current_patch_hash Hash of the current patch file.
|
||||
* @return 0 on success. -1 on failure.
|
||||
*/
|
||||
int apply_consensed_patch_file_changes(const util::h32 &prop_patch_hash, const util::h32 ¤t_patch_hash)
|
||||
{
|
||||
// Check whether is there any patch changes to be applied which reached consensus.
|
||||
if (is_patch_update_pending && current_patch_hash == prop_patch_hash)
|
||||
{
|
||||
if (hpfs::start_ro_session(HPFS_SESSION_NAME, false) != -1)
|
||||
{
|
||||
// Appling new patch file changes to hpcore runtime.
|
||||
if (conf::apply_patch_config(HPFS_SESSION_NAME) == -1)
|
||||
{
|
||||
LOG_ERROR << "Appling patch file changes after consensus failed.";
|
||||
hpfs::stop_ro_session(HPFS_SESSION_NAME);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
unl::update_unl_changes_from_patch();
|
||||
is_patch_update_pending = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (hpfs::stop_ro_session(HPFS_SESSION_NAME) == -1)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace consensus
|
||||
|
||||
@@ -95,6 +95,7 @@ namespace consensus
|
||||
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();
|
||||
|
||||
@@ -129,7 +130,7 @@ namespace consensus
|
||||
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);
|
||||
@@ -138,7 +139,7 @@ namespace consensus
|
||||
|
||||
uint64_t get_stage_time_resolution(const uint64_t time);
|
||||
|
||||
int update_ledger_and_execute_contract(const p2p::proposal &proposal, std::string &new_lcl, util::h32 &new_state_hash);
|
||||
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);
|
||||
|
||||
@@ -153,6 +154,8 @@ namespace consensus
|
||||
|
||||
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);
|
||||
|
||||
} // namespace consensus
|
||||
|
||||
#endif
|
||||
|
||||
16
src/sc.cpp
16
src/sc.cpp
@@ -180,6 +180,7 @@ namespace sc
|
||||
|
||||
util::h32 patch_hash;
|
||||
const int patch_hash_result = hpfs::get_hash(patch_hash, ctx.args.hpfs_session_name, hpfs::PATCH_FILE_PATH);
|
||||
|
||||
if (patch_hash_result == -1)
|
||||
{
|
||||
hpfs::release_rw_session();
|
||||
@@ -187,17 +188,10 @@ namespace sc
|
||||
}
|
||||
else if (patch_hash_result == 1 && patch_hash != hpfs::ctx.get_hash(hpfs::HPFS_PARENT_COMPONENTS::PATCH))
|
||||
{
|
||||
// Appling new patch file changes to hpcore runtime.
|
||||
if (conf::apply_patch_config(ctx.args.hpfs_session_name) == -1)
|
||||
{
|
||||
LOG_ERROR << "Appling patch file after contract execution failed";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update global hash tracker with the new patch file hash.
|
||||
hpfs::ctx.set_hash(hpfs::HPFS_PARENT_COMPONENTS::PATCH, patch_hash);
|
||||
unl::update_unl_changes_from_patch();
|
||||
}
|
||||
// Update global hash tracker with the new patch file hash.
|
||||
hpfs::ctx.set_hash(hpfs::HPFS_PARENT_COMPONENTS::PATCH, patch_hash);
|
||||
// Denote that the patch file was updated by the SC.
|
||||
consensus::is_patch_update_pending = true;
|
||||
}
|
||||
|
||||
return hpfs::release_rw_session();
|
||||
|
||||
Reference in New Issue
Block a user