mirror of
https://github.com/EvernodeXRPL/hpcore.git
synced 2026-04-29 15:37:59 +00:00
Observer mode fix (#78)
* Fixed observer mode consensus issues. * Added startup_mode to fix mode change check.
This commit is contained in:
46
src/conf.cpp
46
src/conf.cpp
@@ -14,8 +14,8 @@ contract_ctx ctx;
|
||||
// Global configuration struct exposed to the application.
|
||||
contract_config cfg;
|
||||
|
||||
const static char *MODE_OBSERVING = "observing";
|
||||
const static char *MODE_PROPOSING = "proposing";
|
||||
const static char *MODE_OBSERVER = "observer";
|
||||
const static char *MODE_PROPOSER = "proposer";
|
||||
|
||||
/**
|
||||
* Loads and initializes the contract config for execution. Must be called once during application startup.
|
||||
@@ -31,16 +31,13 @@ int init()
|
||||
if (validate_contract_dir_paths() != 0 || load_config() != 0 || validate_config() != 0)
|
||||
return -1;
|
||||
|
||||
if (cfg.mode == OPERATING_MODE::PROPOSING)
|
||||
{
|
||||
// Append self peer to peer list.
|
||||
const std::string portstr = std::to_string(cfg.peerport);
|
||||
const std::string peerid = "0.0.0.0:" + portstr;
|
||||
cfg.peers.emplace(std::move(peerid), std::make_pair("0.0.0.0", portstr));
|
||||
// Append self peer to peer list.
|
||||
const std::string portstr = std::to_string(cfg.peerport);
|
||||
const std::string peerid = "0.0.0.0:" + portstr;
|
||||
cfg.peers.emplace(std::move(peerid), std::make_pair("0.0.0.0", portstr));
|
||||
|
||||
// Append self pubkey to unl list.
|
||||
cfg.unl.emplace(cfg.pubkey);
|
||||
}
|
||||
// Append self pubkey to unl list.
|
||||
cfg.unl.emplace(cfg.pubkey);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -91,7 +88,7 @@ int create_contract()
|
||||
crypto::generate_signing_keys(cfg.pubkey, cfg.seckey);
|
||||
binpair_to_hex();
|
||||
|
||||
cfg.mode = OPERATING_MODE::PROPOSING;
|
||||
cfg.startup_mode = OPERATING_MODE::PROPOSER;
|
||||
cfg.listenip = "0.0.0.0";
|
||||
cfg.peerport = 22860;
|
||||
cfg.roundtime = 1000;
|
||||
@@ -202,15 +199,16 @@ int load_config()
|
||||
|
||||
// Load up the values into the struct.
|
||||
|
||||
if (d["mode"] == MODE_OBSERVING)
|
||||
cfg.mode = OPERATING_MODE::OBSERVING;
|
||||
else if (d["mode"] == MODE_PROPOSING)
|
||||
cfg.mode = OPERATING_MODE::PROPOSING;
|
||||
if (d["mode"] == MODE_OBSERVER)
|
||||
cfg.startup_mode = OPERATING_MODE::OBSERVER;
|
||||
else if (d["mode"] == MODE_PROPOSER)
|
||||
cfg.startup_mode = OPERATING_MODE::PROPOSER;
|
||||
else
|
||||
{
|
||||
std::cout << "Invalid mode. 'observing' or 'proposing' expected.\n";
|
||||
std::cout << "Invalid mode. 'observer' or 'proposer' expected.\n";
|
||||
return -1;
|
||||
}
|
||||
cfg.current_mode = cfg.startup_mode;
|
||||
|
||||
cfg.pubkeyhex = d["pubkeyhex"].GetString();
|
||||
cfg.seckeyhex = d["seckeyhex"].GetString();
|
||||
@@ -221,18 +219,16 @@ int load_config()
|
||||
cfg.appbill = d["appbill"].GetString();
|
||||
cfg.appbillargs = d["appbillargs"].GetString();
|
||||
|
||||
|
||||
// Populate runtime contract execution args.
|
||||
if (!cfg.binargs.empty())
|
||||
boost::split(cfg.runtime_binexec_args, cfg.binargs, boost::is_any_of(" "));
|
||||
cfg.runtime_binexec_args.insert(cfg.runtime_binexec_args.begin(), ( cfg.binary[0] == '/' ? cfg.binary : util::realpath( ctx.contract_dir + "/bin/" + cfg.binary ) ) );
|
||||
cfg.runtime_binexec_args.insert(cfg.runtime_binexec_args.begin(), (cfg.binary[0] == '/' ? cfg.binary : util::realpath(ctx.contract_dir + "/bin/" + cfg.binary)));
|
||||
|
||||
|
||||
// Populate runtime app bill args.
|
||||
if (!cfg.appbillargs.empty())
|
||||
boost::split(cfg.runtime_appbill_args, cfg.appbillargs, boost::is_any_of(" "));
|
||||
|
||||
cfg.runtime_appbill_args.insert(cfg.runtime_appbill_args.begin(), ( cfg.appbill[0] == '/' ? cfg.appbill : util::realpath( ctx.contract_dir + "/bin/" + cfg.appbill ) ) );
|
||||
cfg.runtime_appbill_args.insert(cfg.runtime_appbill_args.begin(), (cfg.appbill[0] == '/' ? cfg.appbill : util::realpath(ctx.contract_dir + "/bin/" + cfg.appbill)));
|
||||
|
||||
// Uncomment for docker-based execution.
|
||||
// std::string volumearg;
|
||||
@@ -314,7 +310,7 @@ int save_config()
|
||||
d.SetObject();
|
||||
rapidjson::Document::AllocatorType &allocator = d.GetAllocator();
|
||||
d.AddMember("version", rapidjson::StringRef(util::HP_VERSION), allocator);
|
||||
d.AddMember("mode", rapidjson::StringRef(cfg.mode == OPERATING_MODE::OBSERVING ? MODE_OBSERVING : MODE_PROPOSING),
|
||||
d.AddMember("mode", rapidjson::StringRef(cfg.startup_mode == OPERATING_MODE::OBSERVER ? MODE_OBSERVER : MODE_PROPOSER),
|
||||
allocator);
|
||||
|
||||
d.AddMember("pubkeyhex", rapidjson::StringRef(cfg.pubkeyhex.data()), allocator);
|
||||
@@ -611,7 +607,11 @@ int is_schema_valid(const rapidjson::Document &d)
|
||||
|
||||
void change_operating_mode(const OPERATING_MODE mode)
|
||||
{
|
||||
cfg.mode = mode;
|
||||
// Do not allow to change the mode if the node was started as an observer.
|
||||
if (cfg.startup_mode == OPERATING_MODE::OBSERVER)
|
||||
return;
|
||||
|
||||
cfg.current_mode = mode;
|
||||
}
|
||||
|
||||
} // namespace conf
|
||||
|
||||
@@ -16,8 +16,8 @@ typedef std::pair<std::string, std::string> ip_port_pair;
|
||||
// The operating mode of the contract node.
|
||||
enum OPERATING_MODE
|
||||
{
|
||||
OBSERVING = 0, // Observer mode. Only emits NUPs. Does not participate in voting.
|
||||
PROPOSING = 1 // Consensus participant mode.
|
||||
OBSERVER = 0, // Observer mode. Only emits NUPs. Does not participate in voting.
|
||||
PROPOSER = 1 // Consensus participant mode.
|
||||
};
|
||||
|
||||
// Holds contextual information about the currently loaded contract.
|
||||
@@ -47,11 +47,11 @@ struct contract_config
|
||||
std::string seckey; // Contract secret key bytes
|
||||
std::vector<std::string> runtime_binexec_args; // Contract binary execution args used during runtime.
|
||||
std::vector<std::string> runtime_appbill_args; // Appbill execution args used during runtime.
|
||||
|
||||
OPERATING_MODE current_mode; // Current operating mode of the contract (Observer/Proposer)
|
||||
|
||||
// Config elements which are loaded from the config file.
|
||||
|
||||
OPERATING_MODE mode; // Operating mode of the contract (Observing/Proposing).
|
||||
OPERATING_MODE startup_mode; // Configured startup operating mode of the contract (Observer/Proposer).
|
||||
std::string pubkeyhex; // Contract hex public key
|
||||
std::string seckeyhex; // Contract hex secret key
|
||||
std::string binary; // Full path to the contract binary
|
||||
|
||||
@@ -132,6 +132,7 @@ void consensus()
|
||||
|
||||
// In stage 0 we create a novel proposal and broadcast it.
|
||||
const p2p::proposal stg_prop = create_stage0_proposal();
|
||||
|
||||
broadcast_proposal(stg_prop);
|
||||
}
|
||||
else // Stage 1, 2, 3
|
||||
@@ -205,8 +206,8 @@ void consensus()
|
||||
}
|
||||
else
|
||||
{
|
||||
//Node is in sync with current lcl ->switch to proposing mode.
|
||||
conf::change_operating_mode(conf::OPERATING_MODE::PROPOSING);
|
||||
//Node is in sync with current lcl ->switch to proposer mode.
|
||||
conf::change_operating_mode(conf::OPERATING_MODE::PROPOSER);
|
||||
}
|
||||
|
||||
if (ctx.stage == 1 || (ctx.stage == 3 && ctx.is_state_syncing))
|
||||
@@ -216,6 +217,7 @@ void consensus()
|
||||
{
|
||||
// In stage 1, 2, 3 we vote for incoming proposals and promote winning votes based on thresholds.
|
||||
const p2p::proposal stg_prop = create_stage123_proposal(votes);
|
||||
|
||||
broadcast_proposal(stg_prop);
|
||||
|
||||
if (ctx.stage == 3)
|
||||
@@ -586,8 +588,8 @@ p2p::proposal create_stage123_proposal(vote_counter &votes)
|
||||
*/
|
||||
void broadcast_proposal(const p2p::proposal &p)
|
||||
{
|
||||
// In observing mode, we do not send out any proposals.
|
||||
if (conf::cfg.mode == conf::OPERATING_MODE::OBSERVING)
|
||||
// In observer mode, we do not send out any proposals.
|
||||
if (conf::cfg.current_mode == conf::OPERATING_MODE::OBSERVER)
|
||||
return;
|
||||
|
||||
p2p::peer_outbound_message msg(std::make_shared<flatbuffers::FlatBufferBuilder>(1024));
|
||||
@@ -658,11 +660,11 @@ void check_lcl_votes(bool &is_desync, bool &should_request_history, std::string
|
||||
|
||||
if (total_lcl_votes < (MAJORITY_THRESHOLD * conf::cfg.unl.size()))
|
||||
{
|
||||
LOG_DBG << "Not enough peers proposing to perform consensus votes:" << std::to_string(total_lcl_votes) << " needed:" << std::to_string(MAJORITY_THRESHOLD * conf::cfg.unl.size());
|
||||
LOG_DBG << "Not enough peers proposer to perform consensus votes:" << std::to_string(total_lcl_votes) << " needed:" << std::to_string(MAJORITY_THRESHOLD * conf::cfg.unl.size());
|
||||
is_desync = true;
|
||||
|
||||
//Not enough nodes are propsing. So Node is switching to Proposing if it's in observing mode.
|
||||
conf::change_operating_mode(conf::OPERATING_MODE::PROPOSING);
|
||||
//Not enough nodes are propsing. So Node is switching to Proposer if it's in observer mode.
|
||||
conf::change_operating_mode(conf::OPERATING_MODE::PROPOSER);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -685,8 +687,8 @@ void check_lcl_votes(bool &is_desync, bool &should_request_history, std::string
|
||||
LOG_DBG << "We are not on the consensus ledger, requesting history from a random peer";
|
||||
is_desync = true;
|
||||
|
||||
//Node is in not sync with current lcl ->switch to observing mode.
|
||||
conf::change_operating_mode(conf::OPERATING_MODE::OBSERVING);
|
||||
//Node is not in sync with current lcl ->switch to observer mode.
|
||||
conf::change_operating_mode(conf::OPERATING_MODE::OBSERVER);
|
||||
|
||||
should_request_history = true;
|
||||
return;
|
||||
@@ -896,8 +898,8 @@ void check_state(vote_counter &votes)
|
||||
{
|
||||
if (ctx.state_sync_lcl != ctx.lcl)
|
||||
{
|
||||
// Change the mode to passive and not sending out proposals till the state is synced
|
||||
conf::change_operating_mode(conf::OPERATING_MODE::OBSERVING);
|
||||
// Switch to observer mode to avoid sending out proposals till the state is synced
|
||||
conf::change_operating_mode(conf::OPERATING_MODE::OBSERVER);
|
||||
|
||||
const hasher::B2H majority_state_hash = *reinterpret_cast<const hasher::B2H *>(majority_state.c_str());
|
||||
LOG_INFO << "Starting state sync. Curr state:" << *reinterpret_cast<const hasher::B2H *>(ctx.curr_hash_state.c_str()) << " majority:" << majority_state_hash;
|
||||
@@ -914,7 +916,7 @@ void check_state(vote_counter &votes)
|
||||
|
||||
ctx.is_state_syncing = false;
|
||||
ctx.state_sync_lcl.clear();
|
||||
conf::change_operating_mode(conf::OPERATING_MODE::PROPOSING);
|
||||
conf::change_operating_mode(conf::OPERATING_MODE::PROPOSER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ int main(int argc, char **argv)
|
||||
hplog::init();
|
||||
|
||||
LOG_INFO << "Operating mode: "
|
||||
<< (conf::cfg.mode == conf::OPERATING_MODE::OBSERVING ? "Observing" : "Proposing");
|
||||
<< (conf::cfg.startup_mode == conf::OPERATING_MODE::OBSERVER ? "Observer" : "Proposer");
|
||||
|
||||
statefs::init(conf::ctx.state_hist_dir);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user