diff --git a/src/common.h b/src/common.h index 497f7de..8d61ad9 100644 --- a/src/common.h +++ b/src/common.h @@ -251,6 +251,13 @@ struct ChainMain hash id; }; +enum class NetworkType { + Invalid, + Mainnet, + Testnet, + Stagenet, +}; + } // namespace p2pool #include "util.h" diff --git a/src/json_parsers.h b/src/json_parsers.h index ad5243b..1274fe9 100644 --- a/src/json_parsers.h +++ b/src/json_parsers.h @@ -54,6 +54,7 @@ JSON_VALUE_PARSER(String, const char*) JSON_VALUE_PARSER(String, std::string) JSON_VALUE_PARSER(Uint, uint8_t) JSON_VALUE_PARSER(Uint64, uint64_t) +JSON_VALUE_PARSER(Bool, bool) #undef JSON_VALUE_PARSER diff --git a/src/log.h b/src/log.h index 4cc194d..60c9e87 100644 --- a/src/log.h +++ b/src/log.h @@ -359,6 +359,19 @@ template<> struct log::Stream::Entry } }; +template<> struct log::Stream::Entry +{ + static NOINLINE void put(const NetworkType& value, Stream* wrapper) + { + switch (value) { + case NetworkType::Invalid: *wrapper << "invalid"; break; + case NetworkType::Mainnet: *wrapper << "mainnet"; break; + case NetworkType::Testnet: *wrapper << "testnet"; break; + case NetworkType::Stagenet: *wrapper << "stagenet"; break; + } + } +}; + namespace { template void apply_severity(log::Stream&); diff --git a/src/p2pool.cpp b/src/p2pool.cpp index 74fe141..796890d 100644 --- a/src/p2pool.cpp +++ b/src/p2pool.cpp @@ -51,12 +51,12 @@ p2pool::p2pool(int argc, char* argv[]) panic(); } - const Wallet::Type type = m_params->m_wallet.type(); + const NetworkType type = m_params->m_wallet.type(); - if (type == Wallet::Type::Testnet) { + if (type == NetworkType::Testnet) { LOGWARN(1, "Mining to a testnet wallet address"); } - else if (type == Wallet::Type::Stagenet) { + else if (type == NetworkType::Stagenet) { LOGWARN(1, "Mining to a stagenet wallet address"); } @@ -86,7 +86,7 @@ p2pool::p2pool(int argc, char* argv[]) MinerData d; - m_sideChain = new SideChain(this); + m_sideChain = new SideChain(this, type); m_hasher = new RandomX_Hasher(this); m_blockTemplate = new BlockTemplate(this); m_mempool = new Mempool(); @@ -530,6 +530,63 @@ void p2pool::stratum_on_block() #endif } +void p2pool::get_info() +{ + JSONRPCRequest::call(m_params->m_host, m_params->m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_info\"}", + [this](const char* data, size_t size) + { + parse_get_info_rpc(data, size); + }); +} + +void p2pool::parse_get_info_rpc(const char* data, size_t size) +{ + rapidjson::Document doc; + doc.Parse(data, size); + + if (!doc.IsObject() || !doc.HasMember("result")) { + LOGWARN(1, "get_info RPC response is invalid (\"result\" not found), trying again in 1 second"); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + get_info(); + return; + } + + const auto& result = doc["result"]; + + struct { + bool busy_syncing, mainnet, testnet, stagenet; + } info; + + if (!PARSE(result, info, busy_syncing) || !PARSE(result, info, mainnet) || !PARSE(result, info, testnet) || !PARSE(result, info, stagenet)) { + LOGWARN(1, "get_info RPC response is invalid, trying again in 1 second"); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + get_info(); + return; + } + + if (info.busy_syncing) { + LOGINFO(1, "monerod is busy syncing, trying again in 1 second"); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + get_info(); + return; + } + + NetworkType monero_network = NetworkType::Invalid; + + if (info.mainnet) monero_network = NetworkType::Mainnet; + if (info.testnet) monero_network = NetworkType::Testnet; + if (info.stagenet) monero_network = NetworkType::Stagenet; + + const NetworkType sidechain_network = m_sideChain->network_type(); + + if (monero_network != sidechain_network) { + LOGERR(1, "monerod is on " << monero_network << ", but you're mining to a " << sidechain_network << " sidechain"); + panic(); + } + + get_miner_data(); +} + void p2pool::get_miner_data() { JSONRPCRequest::call(m_params->m_host, m_params->m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_miner_data\"}", @@ -761,7 +818,7 @@ int p2pool::run() { ZMQReader z(m_params->m_host, m_params->m_rpcPort, m_params->m_zmqPort, this); - get_miner_data(); + get_info(); const int rc = uv_run(uv_default_loop_checked(), UV_RUN_DEFAULT); LOGINFO(1, "uv_run exited, result = " << rc); } diff --git a/src/p2pool.h b/src/p2pool.h index a4ab765..71dc4bc 100644 --- a/src/p2pool.h +++ b/src/p2pool.h @@ -102,6 +102,9 @@ private: void stratum_on_block(); + void get_info(); + void parse_get_info_rpc(const char* data, size_t size); + void get_miner_data(); void parse_get_miner_data_rpc(const char* data, size_t size); diff --git a/src/side_chain.cpp b/src/side_chain.cpp index e2ac573..46ec91f 100644 --- a/src/side_chain.cpp +++ b/src/side_chain.cpp @@ -51,8 +51,9 @@ static_assert(1 <= UNCLE_BLOCK_DEPTH && UNCLE_BLOCK_DEPTH <= 10, "Invalid UNCLE_ namespace p2pool { -SideChain::SideChain(p2pool* pool) +SideChain::SideChain(p2pool* pool, NetworkType type) : m_pool(pool) + , m_networkType(type) , m_chainTip(nullptr) , m_poolName("default") , m_targetBlockTime(1) @@ -61,6 +62,8 @@ SideChain::SideChain(p2pool* pool) , m_unclePenalty(20) , m_curDifficulty(m_minDifficulty) { + LOGINFO(1, log::LightCyan() << "network type = " << m_networkType); + if (!load_config(m_pool->params().m_config)) { panic(); } @@ -90,12 +93,13 @@ SideChain::SideChain(p2pool* pool) char consensus_str[log::Stream::BUF_SIZE + 1]; log::Stream s(consensus_str); - s << m_poolName << '\0' - << m_poolPassword << '\0' - << m_targetBlockTime << '\0' - << m_minDifficulty << '\0' - << m_chainWindowSize << '\0' - << m_unclePenalty << '\0'; + s << m_networkType << '\0' + << m_poolName << '\0' + << m_poolPassword << '\0' + << m_targetBlockTime << '\0' + << m_minDifficulty << '\0' + << m_chainWindowSize << '\0' + << m_unclePenalty << '\0'; randomx_init_cache(cache, consensus_str, s.m_pos); } diff --git a/src/side_chain.h b/src/side_chain.h index d27d5ea..5453a41 100644 --- a/src/side_chain.h +++ b/src/side_chain.h @@ -41,7 +41,7 @@ struct MinerShare class SideChain { public: - explicit SideChain(p2pool* pool); + SideChain(p2pool* pool, NetworkType type); ~SideChain(); void fill_sidechain_data(PoolBlock& block, Wallet* w, const hash& txkeySec, std::vector& shares); @@ -62,11 +62,13 @@ public: // Consensus ID can therefore be used as a password to create private P2Pools const std::vector& consensus_id() const { return m_consensusId; } uint64_t chain_window_size() const { return m_chainWindowSize; } + NetworkType network_type() const { return m_networkType; } static bool split_reward(uint64_t reward, const std::vector& shares, std::vector& rewards); private: p2pool* m_pool; + NetworkType m_networkType; private: bool get_shares(PoolBlock* tip, std::vector& shares) const; diff --git a/src/wallet.cpp b/src/wallet.cpp index 3998a90..41b61d3 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -123,7 +123,7 @@ Wallet& Wallet::operator=(const Wallet& w) bool Wallet::decode(const char* address) { - m_type = Type::Invalid; + m_type = NetworkType::Invalid; if (!address || (strlen(address) != ADDRESS_LENGTH)) { return false; @@ -167,11 +167,11 @@ bool Wallet::decode(const char* address) m_prefix = data[0]; - if (m_prefix == valid_prefixes[0]) m_type = Type::Mainnet; - if (m_prefix == valid_prefixes[1]) m_type = Type::Testnet; - if (m_prefix == valid_prefixes[2]) m_type = Type::Stagenet; + if (m_prefix == valid_prefixes[0]) m_type = NetworkType::Mainnet; + if (m_prefix == valid_prefixes[1]) m_type = NetworkType::Testnet; + if (m_prefix == valid_prefixes[2]) m_type = NetworkType::Stagenet; - if (m_type == Type::Invalid) { + if (m_type == NetworkType::Invalid) { return false; } @@ -183,7 +183,7 @@ bool Wallet::decode(const char* address) keccak(data, sizeof(data) - sizeof(m_checksum), md); if (memcmp(&m_checksum, md, sizeof(m_checksum)) != 0) { - m_type = Type::Invalid; + m_type = NetworkType::Invalid; } return valid(); @@ -198,7 +198,7 @@ void Wallet::assign(const hash& spend_pub_key, const hash& view_pub_key) m_viewPublicKey = view_pub_key; m_checksum = 0; - m_type = Type::Mainnet; + m_type = NetworkType::Mainnet; m_txkeySec = {}; m_outputIndex = std::numeric_limits::max(); diff --git a/src/wallet.h b/src/wallet.h index 9e9c1ad..18ad3af 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -24,21 +24,14 @@ namespace p2pool { class Wallet { public: - enum class Type { - Invalid, - Mainnet, - Testnet, - Stagenet, - }; - explicit Wallet(const char* address); ~Wallet(); Wallet(const Wallet& w); Wallet& operator=(const Wallet& w); - FORCEINLINE bool valid() const { return m_type != Type::Invalid; } - FORCEINLINE Type type() const { return m_type; } + FORCEINLINE bool valid() const { return m_type != NetworkType::Invalid; } + FORCEINLINE NetworkType type() const { return m_type; } bool decode(const char* address); void assign(const hash& spend_pub_key, const hash& view_pub_key); @@ -56,7 +49,7 @@ private: hash m_spendPublicKey; hash m_viewPublicKey; uint32_t m_checksum; - Type m_type; + NetworkType m_type; mutable uv_mutex_t m_lock; hash m_txkeySec;