diff --git a/src/base/crypto/Coin.cpp b/src/base/crypto/Coin.cpp index a70ca0751..2895636ea 100644 --- a/src/base/crypto/Coin.cpp +++ b/src/base/crypto/Coin.cpp @@ -1,13 +1,6 @@ /* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018 Lee Clagett - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,9 +16,10 @@ * along with this program. If not, see . */ - #include "base/crypto/Coin.h" #include "3rdparty/rapidjson/document.h" +#include "base/io/json/Json.h" +#include "base/io/log/Log.h" #include @@ -39,74 +33,66 @@ namespace xmrig { -struct CoinName +struct CoinInfo { + const Algorithm::Id algorithm; + const char *code; const char *name; - const Coin::Id id; + const uint64_t target; + const uint64_t units; + const char *tag; }; -static CoinName const coin_names[] = { - { "monero", Coin::MONERO }, - { "xmr", Coin::MONERO }, - { "arqma", Coin::ARQMA }, - { "arq", Coin::ARQMA }, - { "dero", Coin::DERO }, - { "keva", Coin::KEVA }, - { "ravencoin", Coin::RAVEN }, - { "raven", Coin::RAVEN }, - { "rvn", Coin::RAVEN }, - { "conceal", Coin::CONCEAL }, - { "wownero", Coin::WOWNERO } +static const CoinInfo coinInfo[] = { + { Algorithm::INVALID, nullptr, nullptr, 0, 0, nullptr }, + { Algorithm::RX_0, "XMR", "Monero", 120, 1000000000000, YELLOW_BG_BOLD( WHITE_BOLD_S " monero ") }, + { Algorithm::CN_R, "SUMO", "Sumokoin", 240, 1000000000, BLUE_BG_BOLD( WHITE_BOLD_S " sumo ") }, + { Algorithm::RX_ARQ, "ARQ", "ArQmA", 120, 1000000000, BLUE_BG_BOLD( WHITE_BOLD_S " arqma ") }, + { Algorithm::ASTROBWT_DERO, "DERO", "DERO", 0, 0, BLUE_BG_BOLD( WHITE_BOLD_S " dero ") }, + { Algorithm::RX_KEVA, "KVA", "Kevacoin", 0, 0, MAGENTA_BG_BOLD(WHITE_BOLD_S " keva ") }, + { Algorithm::KAWPOW_RVN, "RVN", "Ravencoin", 0, 0, BLUE_BG_BOLD( WHITE_BOLD_S " raven ") }, + { Algorithm::RX_WOW, "WOW", "Wownero", 300, 100000000000, MAGENTA_BG_BOLD(WHITE_BOLD_S " wownero ") }, }; +static_assert(Coin::MAX == sizeof(coinInfo) / sizeof(coinInfo[0]), "size mismatch"); + + +const char *Coin::kDisabled = "DISABLED_COIN"; +const char *Coin::kField = "coin"; +const char *Coin::kUnknown = "UNKNOWN_COIN"; + + } /* namespace xmrig */ - -xmrig::Algorithm::Id xmrig::Coin::algorithm(uint8_t blobVersion) const +xmrig::Coin::Coin(const rapidjson::Value &value) { - switch (id()) { - case MONERO: - return (blobVersion >= 12) ? Algorithm::RX_0 : Algorithm::CN_R; - - case ARQMA: - return (blobVersion >= 15) ? Algorithm::RX_ARQ : Algorithm::CN_PICO_0; - - case DERO: - return (blobVersion >= 4) ? Algorithm::ASTROBWT_DERO : Algorithm::CN_0; - - case KEVA: - return (blobVersion >= 11) ? Algorithm::RX_KEVA : Algorithm::CN_R; - - case RAVEN: - return Algorithm::KAWPOW_RVN; - - case CONCEAL: - return Algorithm::CN_CCX; - - case WOWNERO: - return Algorithm::RX_WOW; - - case INVALID: - break; + if (value.IsString()) { + m_id = parse(value.GetString()); + } + else if (value.IsObject() && !value.ObjectEmpty()) { + m_id = parse(Json::getString(value, kField)); } - - return Algorithm::INVALID; } +xmrig::Algorithm xmrig::Coin::algorithm(uint8_t) const +{ + return coinInfo[m_id].algorithm; +} + + +const char *xmrig::Coin::code() const +{ + return coinInfo[m_id].code; +} + const char *xmrig::Coin::name() const { - for (const auto &i : coin_names) { - if (i.id == m_id) { - return i.name; - } - } - - return nullptr; + return coinInfo[m_id].name; } @@ -114,7 +100,19 @@ rapidjson::Value xmrig::Coin::toJSON() const { using namespace rapidjson; - return isValid() ? Value(StringRef(name())) : Value(kNullType); + return isValid() ? Value(StringRef(code())) : Value(kNullType); +} + + +uint64_t xmrig::Coin::target(uint8_t) const +{ + return coinInfo[m_id].target; +} + + +uint64_t xmrig::Coin::units() const +{ + return coinInfo[m_id].units; } @@ -124,11 +122,17 @@ xmrig::Coin::Id xmrig::Coin::parse(const char *name) return INVALID; } - for (const auto &i : coin_names) { - if (strcasecmp(name, i.name) == 0) { - return i.id; + for (uint32_t i = 1; i < MAX; ++i) { + if (strcasecmp(name, coinInfo[i].code) == 0 || strcasecmp(name, coinInfo[i].name) == 0) { + return static_cast(i); } } return INVALID; } + + +const char *xmrig::Coin::tag(Id id) +{ + return coinInfo[id].tag; +} diff --git a/src/base/crypto/Coin.h b/src/base/crypto/Coin.h index 985335cb4..ac661b7d1 100644 --- a/src/base/crypto/Coin.h +++ b/src/base/crypto/Coin.h @@ -1,13 +1,6 @@ /* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018 Lee Clagett - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,38 +30,52 @@ namespace xmrig { class Coin { public: - enum Id : int { - INVALID = -1, + enum Id : uint32_t { + INVALID, MONERO, + SUMO, ARQMA, DERO, KEVA, RAVEN, - CONCEAL, - WOWNERO + WOWNERO, + MAX }; + static const char *kDisabled; + static const char *kField; + static const char *kUnknown; Coin() = default; - inline Coin(const char *name) : m_id(parse(name)) {} - inline Coin(Id id) : m_id(id) {} + Coin(const rapidjson::Value &value); + inline Coin(const char *name) : m_id(parse(name)) {} + inline Coin(Id id) : m_id(id) {} + inline Coin(uint32_t id) : m_id(id < MAX ? static_cast(id) : INVALID) {} - inline bool isEqual(const Coin &other) const { return m_id == other.m_id; } - inline bool isValid() const { return m_id != INVALID; } - inline Id id() const { return m_id; } + inline bool isEqual(const Coin &other) const { return m_id == other.m_id; } + inline bool isValid() const { return m_id != INVALID; } + inline Id id() const { return m_id; } + inline const char *tag() const { return tag(m_id); } + inline double decimal(uint64_t amount) const { return static_cast(amount) / units(); } - Algorithm::Id algorithm(uint8_t blobVersion = 255) const; + Algorithm algorithm(uint8_t blobVersion = 255) const; + const char *code() const; const char *name() const; rapidjson::Value toJSON() const; + uint64_t target(uint8_t blobVersion = 255) const; + uint64_t units() const; - inline bool operator!=(Coin::Id id) const { return m_id != id; } - inline bool operator!=(const Coin &other) const { return !isEqual(other); } - inline bool operator==(Coin::Id id) const { return m_id == id; } - inline bool operator==(const Coin &other) const { return isEqual(other); } - inline operator Coin::Id() const { return m_id; } + inline bool operator!=(Id id) const { return m_id != id; } + inline bool operator!=(const Coin &other) const { return !isEqual(other); } + inline bool operator<(Id id) const { return m_id < id; } + inline bool operator<(const Coin &other) const { return m_id < other.m_id; } + inline bool operator==(Id id) const { return m_id == id; } + inline bool operator==(const Coin &other) const { return isEqual(other); } + inline operator Id() const { return m_id; } static Id parse(const char *name); + static const char *tag(Id id); private: Id m_id = INVALID; diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 3a1a3abf1..c9af2801e 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -414,19 +414,19 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) } WalletAddress user_address; - if (!user_address.Decode(m_pool.user())) { + if (!user_address.decode(m_pool.user())) { LOG_ERR("Invalid wallet address."); *code = 10; return false; } - if (memcmp(user_address.public_spend_key, public_spendkey, sizeof(public_spendkey)) != 0) { + if (memcmp(user_address.spendKey(), public_spendkey, sizeof(public_spendkey)) != 0) { LOG_ERR("Wallet address and spend key don't match."); *code = 11; return false; } - if (memcmp(user_address.public_view_key, public_viewkey, sizeof(public_viewkey)) != 0) { + if (memcmp(user_address.viewKey(), public_viewkey, sizeof(public_viewkey)) != 0) { LOG_ERR("Wallet address and view key don't match."); *code = 12; return false; diff --git a/src/base/tools/cryptonote/BlobReader.h b/src/base/tools/cryptonote/BlobReader.h index f10bcd88b..e8be0d65f 100644 --- a/src/base/tools/cryptonote/BlobReader.h +++ b/src/base/tools/cryptonote/BlobReader.h @@ -1,8 +1,8 @@ /* XMRig - * Copyright 2012-2013 The Cryptonote developers - * Copyright 2014-2021 The Monero Project - * Copyright 2018-2021 SChernykh - * Copyright 2016-2021 XMRig , + * Copyright (c) 2012-2013 The Cryptonote developers + * Copyright (c) 2014-2021 The Monero Project + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,58 +23,71 @@ #include +#include namespace xmrig { -class CBlobReader +class BlobReader { public: - inline CBlobReader(const void* data, size_t size) - : m_data(reinterpret_cast(data)) - , m_size(size) - , m_index(0) + inline BlobReader(const uint8_t *data, size_t size) : + m_size(size), + m_data(data) {} - inline bool operator()(uint8_t& data) { return getByte(data); } - inline bool operator()(uint64_t& data) { return getVarint(data); } + inline bool operator()(uint64_t &data) { return getVarint(data); } + inline bool operator()(uint8_t &data) { return getByte(data); } + inline size_t index() const { return m_index; } + inline size_t remaining() const { return m_size - m_index; } + + inline bool skip(size_t n) + { + if (m_index + n > m_size) { + return false; + } + + m_index += n; + + return true; + } template inline bool operator()(uint8_t(&data)[N]) { - for (size_t i = 0; i < N; ++i) { - if (!getByte(data[i])) { - return false; - } + if (m_index + N > m_size) { + return false; } + + memcpy(data, m_data + m_index, N); + m_index += N; + return true; } template - inline void readItems(T& data, size_t count) + inline void readItems(T &data, size_t count) { data.resize(count); - for (size_t i = 0; i < count; ++i) + for (size_t i = 0; i < count; ++i) { operator()(data[i]); + } } - inline size_t index() const { return m_index; } - - inline void skip(size_t N) { m_index += N; } - private: - inline bool getByte(uint8_t& data) + inline bool getByte(uint8_t &data) { if (m_index >= m_size) { return false; } data = m_data[m_index++]; + return true; } - inline bool getVarint(uint64_t& data) + inline bool getVarint(uint64_t &data) { uint64_t result = 0; uint8_t t; @@ -89,12 +102,13 @@ private: } while (t & 0x80); data = result; + return true; } - const uint8_t* m_data; - size_t m_size; - size_t m_index; + const size_t m_size; + const uint8_t *m_data; + size_t m_index = 0; }; diff --git a/src/base/tools/cryptonote/BlockTemplate.cpp b/src/base/tools/cryptonote/BlockTemplate.cpp index 29653441d..ede0b19a8 100644 --- a/src/base/tools/cryptonote/BlockTemplate.cpp +++ b/src/base/tools/cryptonote/BlockTemplate.cpp @@ -1,8 +1,8 @@ /* XMRig - * Copyright 2012-2013 The Cryptonote developers - * Copyright 2014-2021 The Monero Project - * Copyright 2018-2021 SChernykh - * Copyright 2016-2021 XMRig , + * Copyright (c) 2012-2013 The Cryptonote developers + * Copyright (c) 2014-2021 The Monero Project + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,7 +32,7 @@ bool BlockTemplate::Init(const String& blockTemplate, Coin coin) { raw_blob = Cvt::fromHex(blockTemplate); - CBlobReader ar(raw_blob.data(), raw_blob.size()); + BlobReader ar(raw_blob.data(), raw_blob.size()); // Block header ar(major_version); @@ -90,7 +90,7 @@ bool BlockTemplate::Init(const String& blockTemplate, Coin coin) ar.readItems(extra, extra_size); - CBlobReader ar_extra(extra.data(), extra_size); + BlobReader ar_extra(extra.data(), extra_size); tx_extra_nonce_size = 0; tx_extra_nonce_index = 0; diff --git a/src/base/tools/cryptonote/BlockTemplate.h b/src/base/tools/cryptonote/BlockTemplate.h index 4a6ef8051..6effd3feb 100644 --- a/src/base/tools/cryptonote/BlockTemplate.h +++ b/src/base/tools/cryptonote/BlockTemplate.h @@ -1,8 +1,8 @@ /* XMRig - * Copyright 2012-2013 The Cryptonote developers - * Copyright 2014-2021 The Monero Project - * Copyright 2018-2021 SChernykh - * Copyright 2016-2021 XMRig , + * Copyright (c) 2012-2013 The Cryptonote developers + * Copyright (c) 2014-2021 The Monero Project + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/base/tools/cryptonote/WalletAddress.cpp b/src/base/tools/cryptonote/WalletAddress.cpp index 7be1ef9d6..6b7f5343d 100644 --- a/src/base/tools/cryptonote/WalletAddress.cpp +++ b/src/base/tools/cryptonote/WalletAddress.cpp @@ -1,8 +1,8 @@ /* XMRig - * Copyright 2012-2013 The Cryptonote developers - * Copyright 2014-2021 The Monero Project - * Copyright 2018-2021 SChernykh - * Copyright 2016-2021 XMRig , + * Copyright (c) 2012-2013 The Cryptonote developers + * Copyright (c) 2014-2021 The Monero Project + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,24 +18,29 @@ * along with this program. If not, see . */ - -#include "base/crypto/keccak.h" -#include "base/tools/cryptonote/BlobReader.h" #include "base/tools/cryptonote/WalletAddress.h" -#include "base/tools/cryptonote/umul128.h" +#include "3rdparty/rapidjson/document.h" +#include "base/crypto/keccak.h" #include "base/tools/Buffer.h" +#include "base/tools/cryptonote/BlobReader.h" +#include "base/tools/cryptonote/umul128.h" +#include "base/tools/Cvt.h" + + #include +#include -namespace xmrig { - - -bool WalletAddress::Decode(const String& address) +bool xmrig::WalletAddress::decode(const char *address, size_t size) { static constexpr std::array block_sizes{ 0, 2, 3, 5, 6, 7, 9, 10, 11 }; static constexpr char alphabet[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; constexpr size_t alphabet_size = sizeof(alphabet) - 1; + if (size < kMinSize || size > kMaxSize) { + return false; + } + int8_t reverse_alphabet[256]; memset(reverse_alphabet, -1, sizeof(reverse_alphabet)); @@ -43,7 +48,7 @@ bool WalletAddress::Decode(const String& address) reverse_alphabet[static_cast(alphabet[i])] = i; } - const int len = static_cast(address.size()); + const int len = static_cast(size); const int num_full_blocks = len / block_sizes.back(); const int last_block_size = len % block_sizes.back(); @@ -60,10 +65,15 @@ bool WalletAddress::Decode(const String& address) return false; } - Buffer data; - data.reserve(static_cast(num_full_blocks) * sizeof(uint64_t) + last_block_size_index); + const size_t data_size = static_cast(num_full_blocks) * sizeof(uint64_t) + last_block_size_index; + if (data_size < kMinDataSize) { + return false; + } - const char* address_data = address.data(); + Buffer data; + data.reserve(data_size); + + const char *address_data = address; for (int i = 0; i <= num_full_blocks; ++i) { uint64_t num = 0; @@ -87,28 +97,138 @@ bool WalletAddress::Decode(const String& address) address_data += block_sizes.back(); - uint8_t* p = reinterpret_cast(&num); - for (int j = ((i < num_full_blocks) ? sizeof(num) : last_block_size_index) - 1; j >= 0; --j) { + auto p = reinterpret_cast(&num); + for (int j = ((i < num_full_blocks) ? static_cast(sizeof(num)) : last_block_size_index) - 1; j >= 0; --j) { data.emplace_back(p[j]); } } - CBlobReader ar(data.data(), data.size()); + assert(data.size() == data_size); - ar(tag); - ar(public_spend_key); - ar(public_view_key); - ar(checksum); + BlobReader ar(data.data(), data_size); - uint8_t md[200]; - keccak(data.data(), data.size() - sizeof(checksum), md); + if (ar(m_tag) && ar(m_publicSpendKey) && ar(m_publicViewKey) && ar.skip(ar.remaining() - sizeof(m_checksum)) && ar(m_checksum)) { + uint8_t md[200]; + keccak(data.data(), data_size - sizeof(m_checksum), md); - if (memcmp(checksum, md, sizeof(checksum)) != 0) { - return false; + if (memcmp(m_checksum, md, sizeof(m_checksum)) == 0) { + m_data = { address, size }; + + return true; + } } - return true; + m_tag = 0; + + return false; } -} /* namespace xmrig */ +bool xmrig::WalletAddress::decode(const rapidjson::Value &address) +{ + return address.IsString() && decode(address.GetString(), address.GetStringLength()); +} + + +const char *xmrig::WalletAddress::netName() const +{ + static const std::array names = { "mainnet", "testnet", "stagenet" }; + + return names[net()]; +} + + +const char *xmrig::WalletAddress::typeName() const +{ + static const std::array names = { "public", "integrated", "subaddress" }; + + return names[type()]; +} + + +rapidjson::Value xmrig::WalletAddress::toJSON(rapidjson::Document &doc) const +{ + using namespace rapidjson; + + return isValid() ? m_data.toJSON(doc) : Value(kNullType); +} + + +#ifdef XMRIG_FEATURE_API +rapidjson::Value xmrig::WalletAddress::toAPI(rapidjson::Document &doc) const +{ + using namespace rapidjson; + + if (!isValid()) { + return Value(kNullType); + } + + auto &allocator = doc.GetAllocator(); + Value out(kObjectType); + out.AddMember(StringRef(Coin::kField), coin().toJSON(), allocator); + out.AddMember("address", m_data.toJSON(doc), allocator); + out.AddMember("type", StringRef(typeName()), allocator); + out.AddMember("net", StringRef(netName()), allocator); + out.AddMember("rpc_port", rpcPort(), allocator); + out.AddMember("zmq_port", zmqPort(), allocator); + out.AddMember("tag", m_tag, allocator); + out.AddMember("view_key", Cvt::toHex(m_publicViewKey, kKeySize, doc), allocator); + out.AddMember("spend_key", Cvt::toHex(m_publicSpendKey, kKeySize, doc), allocator); + out.AddMember("checksum", Cvt::toHex(m_checksum, sizeof(m_checksum), doc), allocator); + + return out; +} +#endif + + +const xmrig::WalletAddress::TagInfo &xmrig::WalletAddress::tagInfo(uint64_t tag) +{ + static TagInfo dummy = { Coin::INVALID, MAINNET, PUBLIC, 0 }; + static const std::map tags = { + { 18, { Coin::MONERO, MAINNET, PUBLIC, 18081, 18082 } }, + { 19, { Coin::MONERO, MAINNET, INTEGRATED, 18081, 18082 } }, + { 42, { Coin::MONERO, MAINNET, SUBADDRESS, 18081, 18082 } }, + + { 53, { Coin::MONERO, TESTNET, PUBLIC, 28081, 28082 } }, + { 54, { Coin::MONERO, TESTNET, INTEGRATED, 28081, 28082 } }, + { 63, { Coin::MONERO, TESTNET, SUBADDRESS, 28081, 28082 } }, + + { 24, { Coin::MONERO, STAGENET, PUBLIC, 38081, 38082 } }, + { 25, { Coin::MONERO, STAGENET, INTEGRATED, 38081, 38082 } }, + { 36, { Coin::MONERO, STAGENET, SUBADDRESS, 38081, 38082 } }, + + { 0x2bb39a, { Coin::SUMO, MAINNET, PUBLIC, 19734, 19735 } }, + { 0x29339a, { Coin::SUMO, MAINNET, INTEGRATED, 19734, 19735 } }, + { 0x8319a, { Coin::SUMO, MAINNET, SUBADDRESS, 19734, 19735 } }, + + { 0x37751a, { Coin::SUMO, TESTNET, PUBLIC, 29734, 29735 } }, + { 0x34f51a, { Coin::SUMO, TESTNET, INTEGRATED, 29734, 29735 } }, + { 0x1d351a, { Coin::SUMO, TESTNET, SUBADDRESS, 29734, 29735 } }, + + { 0x2cca, { Coin::ARQMA, MAINNET, PUBLIC, 19994, 19995 } }, + { 0x116bc7, { Coin::ARQMA, MAINNET, INTEGRATED, 19994, 19995 } }, + { 0x6847, { Coin::ARQMA, MAINNET, SUBADDRESS, 19994, 19995 } }, + + { 0x53ca, { Coin::ARQMA, TESTNET, PUBLIC, 29994, 29995 } }, + { 0x504a, { Coin::ARQMA, TESTNET, INTEGRATED, 29994, 29995 } }, + { 0x524a, { Coin::ARQMA, TESTNET, SUBADDRESS, 29994, 29995 } }, + + { 0x39ca, { Coin::ARQMA, STAGENET, PUBLIC, 39994, 39995 } }, + { 0x1742ca, { Coin::ARQMA, STAGENET, INTEGRATED, 39994, 39995 } }, + { 0x1d84ca, { Coin::ARQMA, STAGENET, SUBADDRESS, 39994, 39995 } }, + + { 0xc8ed8, { Coin::DERO, MAINNET, PUBLIC, 20206, 0 } }, + { 0xa0ed8, { Coin::DERO, MAINNET, INTEGRATED, 20206, 0 } }, + + { 0x6cf58, { Coin::DERO, TESTNET, PUBLIC, 30306, 0 } }, + { 0x44f58, { Coin::DERO, TESTNET, INTEGRATED, 30306, 0 } }, + + { 4146, { Coin::WOWNERO, MAINNET, PUBLIC, 34568, 34569 } }, + { 6810, { Coin::WOWNERO, MAINNET, INTEGRATED, 34568, 34569 } }, + { 12208, { Coin::WOWNERO, MAINNET, SUBADDRESS, 34568, 34569 } }, + }; + + const auto it = tags.find(tag); + + return it == tags.end() ? dummy : it->second; +} diff --git a/src/base/tools/cryptonote/WalletAddress.h b/src/base/tools/cryptonote/WalletAddress.h index cc3c2ec42..1c82c92bc 100644 --- a/src/base/tools/cryptonote/WalletAddress.h +++ b/src/base/tools/cryptonote/WalletAddress.h @@ -1,8 +1,8 @@ /* XMRig - * Copyright 2012-2013 The Cryptonote developers - * Copyright 2014-2021 The Monero Project - * Copyright 2018-2021 SChernykh - * Copyright 2016-2021 XMRig , + * Copyright (c) 2012-2013 The Cryptonote developers + * Copyright (c) 2014-2021 The Monero Project + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,19 +23,78 @@ #include "base/tools/String.h" +#include "base/crypto/Coin.h" namespace xmrig { -struct WalletAddress +class WalletAddress { - uint64_t tag; - uint8_t public_spend_key[32]; - uint8_t public_view_key[32]; - uint8_t checksum[4]; +public: + enum Net : uint32_t { + MAINNET, + TESTNET, + STAGENET + }; - bool Decode(const String& address); + enum Type : uint32_t { + PUBLIC, + INTEGRATED, + SUBADDRESS + }; + + constexpr static size_t kKeySize = 32; + constexpr static size_t kMaxSize = 256; + constexpr static size_t kMinDataSize = 69; + constexpr static size_t kMinSize = 95; + + WalletAddress() = default; + inline WalletAddress(const char *address, size_t size) { decode(address, size); } + inline WalletAddress(const char *address) { decode(address); } + inline WalletAddress(const rapidjson::Value &address) { decode(address); } + inline WalletAddress(const String &address) { decode(address); } + + inline bool decode(const char *address) { return decode(address, strlen(address)); } + inline bool decode(const String &address) { return decode(address, address.size()); } + inline bool isValid() const { return m_tag > 0 && m_data.size() >= kMinSize; } + inline const char *data() const { return m_data; } + inline const Coin &coin() const { return tagInfo(m_tag).coin; } + inline const uint8_t *spendKey() const { return m_publicSpendKey; } + inline const uint8_t *viewKey() const { return m_publicViewKey; } + inline Net net() const { return tagInfo(m_tag).net; } + inline Type type() const { return tagInfo(m_tag).type; } + inline uint16_t rpcPort() const { return tagInfo(m_tag).rpcPort; } + inline uint16_t zmqPort() const { return tagInfo(m_tag).zmqPort; } + inline uint64_t tag() const { return m_tag; } + + bool decode(const char *address, size_t size); + bool decode(const rapidjson::Value &address); + const char *netName() const; + const char *typeName() const; + rapidjson::Value toJSON(rapidjson::Document &doc) const; + +# ifdef XMRIG_FEATURE_API + rapidjson::Value toAPI(rapidjson::Document &doc) const; +# endif + +private: + struct TagInfo + { + const Coin coin; + const Net net; + const Type type; + const uint16_t rpcPort; + const uint16_t zmqPort; + }; + + static const TagInfo &tagInfo(uint64_t tag); + + String m_data; + uint64_t m_tag = 0; + uint8_t m_checksum[4]{}; + uint8_t m_publicSpendKey[kKeySize]{}; + uint8_t m_publicViewKey[kKeySize]{}; };