Wallet: added checks for FCMP++ compatibility

This commit is contained in:
SChernykh
2025-10-23 11:40:59 +02:00
parent 0451aebb8a
commit 25a5361777
13 changed files with 1100 additions and 74 deletions
+30 -4
View File
@@ -73,12 +73,22 @@ Params::Params(int argc, char* const argv[])
}
if ((strcmp(argv[i], "--wallet") == 0) && (i + 1 < argc)) {
m_mainWallet.decode(argv[++i]);
const char* s = argv[++i];
if (!m_mainWallet.decode(s)) {
LOGERR(1, "Wallet " << s << " failed to decode");
}
ok = true;
}
if ((strcmp(argv[i], "--subaddress") == 0) && (i + 1 < argc)) {
m_subaddress.decode(argv[++i]);
const char* s = argv[++i];
if (!m_subaddress.decode(s)) {
LOGERR(1, "Subaddress " << s << " failed to decode");
}
ok = true;
}
@@ -333,8 +343,14 @@ Params::Params(int argc, char* const argv[])
char display_wallet_buf[Wallet::ADDRESS_LENGTH] = {};
if (m_mainWallet.valid() && m_subaddress.valid()) {
m_miningWallet.assign(m_subaddress.spend_public_key(), m_mainWallet.view_public_key(), m_mainWallet.type(), false);
m_subaddress.encode(display_wallet_buf);
if (!m_miningWallet.assign(m_subaddress.spend_public_key(), m_mainWallet.view_public_key(), m_mainWallet.type(), false)) {
LOGERR(1, "Failed to configure the mining wallet, falling back to " << m_mainWallet);
m_miningWallet = m_mainWallet;
m_mainWallet.encode(display_wallet_buf);
}
else {
m_subaddress.encode(display_wallet_buf);
}
}
else if (m_mainWallet.valid()) {
m_miningWallet = m_mainWallet;
@@ -367,6 +383,16 @@ bool Params::valid() const
}
}
if (!m_mainWallet.torsion_check()) {
LOGERR(1, m_mainWallet << " didn't pass the torsion check. It will be incompatible with FCMP++.");
return false;
}
if (m_subaddress.valid() && !m_subaddress.torsion_check()) {
LOGERR(1, m_subaddress << " didn't pass the torsion check. It will be incompatible with FCMP++.");
return false;
}
if (m_mergeMiningHosts.size() > 10) {
LOGERR(1, "Too many merge mining blockchains.");
return false;
+3 -1
View File
@@ -2486,7 +2486,9 @@ void SideChain::precalc_worker()
for (const std::pair<size_t, const Wallet*>& w : wallets) {
hash eph_public_key;
uint8_t view_tag;
w.second->get_eph_public_key(job->m_txkeySec, w.first, eph_public_key, view_tag);
if (!w.second->get_eph_public_key(job->m_txkeySec, w.first, eph_public_key, view_tag)) {
LOGWARN(6, "get_eph_public_key failed in precalc_worker");
}
}
} while (true);
}
+31 -1
View File
@@ -27,6 +27,10 @@ extern "C" {
#include "crypto-ops.h"
}
#include "fcmp_pp_crypto.h"
LOG_CATEGORY(Wallet)
namespace {
// Allow only regular addresses (no integrated addresses, no subaddresses)
@@ -81,7 +85,9 @@ namespace p2pool {
Wallet::Wallet(const char* address) : m_prefix(0), m_checksum(0), m_type(NetworkType::Invalid), m_subaddress(false)
{
decode(address);
if (!decode(address) && address) {
LOGWARN(1, address << " failed to decode");
}
}
Wallet::Wallet(const Wallet& w)
@@ -179,6 +185,11 @@ bool Wallet::decode(const char* address)
m_type = NetworkType::Invalid;
}
if (!torsion_check()) {
LOGWARN(1, "Torsion check failed for wallet " << *this << "! It will not be compatible with FCMP++.");
// TODO: add "m_type = NetworkType::Invalid;" and return false in a later release, closer to FCMP++ hardfork
}
return valid();
}
@@ -213,6 +224,11 @@ bool Wallet::assign(const hash& spend_pub_key, const hash& view_pub_key, Network
m_type = type;
m_subaddress = subaddress;
if (!torsion_check()) {
LOGWARN(1, "Torsion check failed for wallet " << *this << "! It will not be compatible with FCMP++.");
// TODO: add "m_type = NetworkType::Invalid;" and return false in a later release, closer to FCMP++ hardfork
}
return true;
}
@@ -256,4 +272,18 @@ bool Wallet::get_eph_public_key(const hash& txkey_sec, size_t output_index, hash
return true;
}
bool Wallet::torsion_check() const
{
ge_p3 p1, p2;
if ((ge_frombytes_vartime(&p1, m_spendPublicKey.h) != 0) || (ge_frombytes_vartime(&p2, m_viewPublicKey.h) != 0)) {
return false;
}
return
!fcmp_pp::mul8_is_identity(p1) &&
!fcmp_pp::mul8_is_identity(p2) &&
fcmp_pp::torsion_check_vartime(p1) &&
fcmp_pp::torsion_check_vartime(p2);
}
} // namespace p2pool
+12 -11
View File
@@ -34,31 +34,32 @@ public:
Wallet(const Wallet& w);
Wallet& operator=(const Wallet& w);
FORCEINLINE bool valid() const { return m_type != NetworkType::Invalid; }
[[nodiscard]] FORCEINLINE bool valid() const { return m_type != NetworkType::Invalid; }
bool decode(const char* address);
bool assign(const hash& spend_pub_key, const hash& view_pub_key, NetworkType type, bool subaddress);
[[nodiscard]] bool decode(const char* address);
[[nodiscard]] bool assign(const hash& spend_pub_key, const hash& view_pub_key, NetworkType type, bool subaddress);
void encode(char (&buf)[ADDRESS_LENGTH]) const;
FORCEINLINE std::string encode() const
[[nodiscard]] FORCEINLINE std::string encode() const
{
char buf[ADDRESS_LENGTH];
encode(buf);
return std::string(buf, buf + ADDRESS_LENGTH);
}
bool get_eph_public_key(const hash& txkey_sec, size_t output_index, hash& eph_public_key, uint8_t& view_tag, const uint8_t* expected_view_tag = nullptr) const;
[[nodiscard]] bool get_eph_public_key(const hash& txkey_sec, size_t output_index, hash& eph_public_key, uint8_t& view_tag, const uint8_t* expected_view_tag = nullptr) const;
FORCEINLINE bool operator<(const Wallet& w) const { return (m_spendPublicKey < w.m_spendPublicKey) || ((m_spendPublicKey == w.m_spendPublicKey) && (m_viewPublicKey < w.m_viewPublicKey)); }
FORCEINLINE bool operator==(const Wallet& w) const { return (m_spendPublicKey == w.m_spendPublicKey) && (m_viewPublicKey == w.m_viewPublicKey); }
FORCEINLINE uint64_t prefix() const { return m_prefix; }
FORCEINLINE const hash& spend_public_key() const { return m_spendPublicKey; }
FORCEINLINE const hash& view_public_key() const { return m_viewPublicKey; }
FORCEINLINE uint32_t checksum() const { return m_checksum; }
FORCEINLINE NetworkType type() const { return m_type; }
FORCEINLINE bool is_subaddress() const { return m_subaddress; }
[[nodiscard]] FORCEINLINE uint64_t prefix() const { return m_prefix; }
[[nodiscard]] FORCEINLINE const hash& spend_public_key() const { return m_spendPublicKey; }
[[nodiscard]] FORCEINLINE const hash& view_public_key() const { return m_viewPublicKey; }
[[nodiscard]] FORCEINLINE uint32_t checksum() const { return m_checksum; }
[[nodiscard]] FORCEINLINE NetworkType type() const { return m_type; }
[[nodiscard]] FORCEINLINE bool is_subaddress() const { return m_subaddress; }
[[nodiscard]] bool torsion_check() const;
private:
uint64_t m_prefix;