Port P2Pool to Salvium
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(p2pool)
|
||||
project(p2pool-salvium)
|
||||
|
||||
include(cmake/standard.cmake)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// Fixed difficulty for miners that connect to your node must be set in their config.json
|
||||
//
|
||||
{
|
||||
"name": "default",
|
||||
"name": "salvium_main",
|
||||
"password": "",
|
||||
"block_time": 10,
|
||||
"min_diff": 100000,
|
||||
|
||||
+16
-3
@@ -166,8 +166,18 @@ BlockTemplate& BlockTemplate::operator=(const BlockTemplate& b)
|
||||
|
||||
static FORCEINLINE uint64_t get_base_reward(uint64_t already_generated_coins)
|
||||
{
|
||||
const uint64_t result = ~already_generated_coins >> 19;
|
||||
return (result < BASE_BLOCK_REWARD) ? BASE_BLOCK_REWARD : result;
|
||||
// Salvium emission formula
|
||||
if (already_generated_coins == 0) {
|
||||
return PREMINE_AMOUNT;
|
||||
}
|
||||
|
||||
uint64_t base_reward = (MONEY_SUPPLY - already_generated_coins) >> EMISSION_SPEED_FACTOR;
|
||||
|
||||
if (base_reward < BASE_BLOCK_REWARD) {
|
||||
base_reward = BASE_BLOCK_REWARD;
|
||||
}
|
||||
|
||||
return base_reward;
|
||||
}
|
||||
|
||||
static FORCEINLINE uint64_t get_block_reward(uint64_t base_reward, uint64_t median_weight, uint64_t fees, uint64_t weight)
|
||||
@@ -332,7 +342,10 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const
|
||||
|
||||
select_mempool_transactions(mempool);
|
||||
|
||||
const uint64_t base_reward = get_base_reward(data.already_generated_coins);
|
||||
uint64_t base_reward = get_base_reward(data.already_generated_coins);
|
||||
|
||||
// Salvium: 20% goes to staking, miners get 80%
|
||||
base_reward = (base_reward * 4) / 5; // 80% of total reward
|
||||
|
||||
uint64_t total_tx_fees = 0;
|
||||
uint64_t total_tx_weight = 0;
|
||||
|
||||
@@ -125,6 +125,7 @@ constexpr uint8_t EXTRA_NONCE_MAX_SIZE = EXTRA_NONCE_SIZE + 10;
|
||||
constexpr uint8_t TX_VERSION = 2;
|
||||
constexpr uint8_t TXIN_GEN = 0xFF;
|
||||
constexpr uint8_t TXOUT_TO_TAGGED_KEY = 3;
|
||||
constexpr uint8_t TXOUT_TO_CARROT_V1 = 4;
|
||||
constexpr uint8_t TX_EXTRA_TAG_PUBKEY = 1;
|
||||
constexpr uint8_t TX_EXTRA_NONCE = 2;
|
||||
constexpr uint8_t TX_EXTRA_MERGE_MINING_TAG = 3;
|
||||
|
||||
@@ -400,15 +400,15 @@ template<> struct log::Stream::Entry<XMRAmount>
|
||||
{
|
||||
static NOINLINE void put(XMRAmount value, Stream* wrapper)
|
||||
{
|
||||
constexpr uint64_t denomination = 1000000000000ULL;
|
||||
constexpr uint64_t denomination = 100000000ULL;
|
||||
|
||||
const int w = wrapper->getNumberWidth();
|
||||
|
||||
wrapper->setNumberWidth(1);
|
||||
*wrapper << value.m_data / denomination << '.';
|
||||
|
||||
wrapper->setNumberWidth(12);
|
||||
*wrapper << value.m_data % denomination << " XMR";
|
||||
wrapper->setNumberWidth(8);
|
||||
*wrapper << value.m_data % denomination << " SAL";
|
||||
|
||||
wrapper->setNumberWidth(w);
|
||||
}
|
||||
|
||||
+11
-11
@@ -58,13 +58,13 @@
|
||||
|
||||
void p2pool_usage()
|
||||
{
|
||||
printf("P2Pool %s\n"
|
||||
printf("P2Pool-Salvium %s\n"
|
||||
"\nUsage:\n\n" \
|
||||
"--wallet Main wallet address (the one that starts with 4...). To mine to a subaddress of this wallet, use it together with --subaddress\n"
|
||||
"--wallet Main wallet address (the one that starts with SC1...). To mine to a subaddress of this wallet, use it together with --subaddress\n"
|
||||
"--subaddress Subaddress to mine to. It must belong to the same wallet that was specified with --wallet parameter\n"
|
||||
"--host IP address of your Monero node, default is 127.0.0.1\n"
|
||||
"--rpc-port monerod RPC API port number, default is 18081\n"
|
||||
"--zmq-port monerod ZMQ pub port number, default is 18083 (same port as in monerod's \"--zmq-pub\" command line parameter)\n"
|
||||
"--host IP address of your Salvium node, default is 127.0.0.1\n"
|
||||
"--rpc-port salviumd RPC API port number, default is 19081\n"
|
||||
"--zmq-port salviumd ZMQ pub port number, default is 19083 (same port as in salviumd's \"--zmq-pub\" command line parameter)\n"
|
||||
"--stratum Comma-separated list of IP:port for stratum server to listen on\n"
|
||||
"--p2p Comma-separated list of IP:port for p2p server to listen on\n"
|
||||
"--addpeers Comma-separated list of IP:port of other p2pool nodes to connect to\n"
|
||||
@@ -79,7 +79,7 @@ void p2pool_usage()
|
||||
"--no-cache Disable p2pool.cache\n"
|
||||
"--no-color Disable colors in console output\n"
|
||||
#ifdef WITH_RANDOMX
|
||||
"--no-randomx Disable internal RandomX hasher: p2pool will use RPC calls to monerod to check PoW hashes\n"
|
||||
"--no-randomx Disable internal RandomX hasher: p2pool will use RPC calls to salviumd to check PoW hashes\n"
|
||||
#endif
|
||||
"--out-peers N Maximum number of outgoing connections for p2p server (any value between 10 and 450)\n"
|
||||
"--in-peers N Maximum number of incoming connections for p2p server (any value between 10 and 450)\n"
|
||||
@@ -87,7 +87,7 @@ void p2pool_usage()
|
||||
"--mini Connect to p2pool-mini sidechain. Note that it will also change default p2p port from %d to %d\n"
|
||||
"--nano Connect to p2pool-nano sidechain. Note that it will also change default p2p port from %d to %d\n"
|
||||
"--no-autodiff Disable automatic difficulty adjustment for miners connected to stratum (WARNING: incompatible with Nicehash and MRR)\n"
|
||||
"--rpc-login Specify username[:password] required for Monero RPC server\n"
|
||||
"--rpc-login Specify username[:password] required for Salvium RPC server\n"
|
||||
"--socks5 Specify IP:port of a SOCKS5 proxy to use for outgoing connections\n"
|
||||
"--no-dns Disable DNS queries, use only IP addresses to connect to peers (seed node DNS will be unavailable too)\n"
|
||||
"--p2p-external-port Port number that your router uses for mapping to your local p2p port. Use it if you are behind a NAT and still want to accept incoming connections\n"
|
||||
@@ -96,13 +96,13 @@ void p2pool_usage()
|
||||
"--no-igd An alias for --no-upnp\n"
|
||||
"--upnp-stratum Port forward Stratum port (it's not forwarded by default)\n"
|
||||
#endif
|
||||
"--merge-mine IP:port and wallet address for another blockchain to merge mine with\n"
|
||||
// "--merge-mine IP:port and wallet address for another blockchain to merge mine with\n"
|
||||
"--version Print p2pool's version and build details\n"
|
||||
#ifdef WITH_TLS
|
||||
"--tls-cert file Load TLS certificate chain from \"file\" in the PEM format\n"
|
||||
"--tls-cert-key file Load TLS certificate private key from \"file\" in the PEM format\n"
|
||||
"--rpc-ssl Enable SSL on RPC connections to the Monero node\n"
|
||||
"--rpc-ssl-fingerprint base64-encoded fingerprint of the Monero node's certificate (optional, use it for certificate pinning)\n"
|
||||
"--rpc-ssl Enable SSL on RPC connections to the Salvium node\n"
|
||||
"--rpc-ssl-fingerprint base64-encoded fingerprint of the Salvium node's certificate (optional, use it for certificate pinning)\n"
|
||||
#endif
|
||||
"--no-stratum-http Disable HTTP on Stratum ports\n"
|
||||
"--full-validation Enables full share validation / increases CPU usage\n"
|
||||
@@ -110,7 +110,7 @@ void p2pool_usage()
|
||||
"--no-clearnet-p2p Forces P2P server to listen on 127.0.0.1 and to not connect to clearnet IPs\n"
|
||||
"--help Show this help message\n\n"
|
||||
"Example command line:\n\n"
|
||||
"%s --host 127.0.0.1 --rpc-port 18081 --zmq-port 18083 --wallet YOUR_WALLET_ADDRESS --stratum 0.0.0.0:%d --p2p 0.0.0.0:%d\n\n",
|
||||
"%s-salvium --host 127.0.0.1 --rpc-port 19081 --zmq-port 19083 --wallet YOUR_WALLET_ADDRESS --stratum 0.0.0.0:%d --p2p 0.0.0.0:%d\n\n",
|
||||
p2pool::VERSION,
|
||||
static_cast<uint32_t>(p2pool::DEFAULT_STRATUM_BAN_TIME),
|
||||
p2pool::log::MAX_GLOBAL_LOG_LEVEL,
|
||||
|
||||
+7
-7
@@ -48,9 +48,9 @@ LOG_CATEGORY(P2PServer)
|
||||
|
||||
static constexpr char saved_peer_list_file_name[] = "p2pool_peers.txt";
|
||||
static constexpr char saved_onion_peer_list_file_name[] = "p2pool_onion_peers.txt";
|
||||
static const char* seed_nodes[] = { "seeds.p2pool.io", "main.p2poolpeers.net", "main.gupax.io", "" };
|
||||
static const char* seed_nodes_mini[] = { "seeds-mini.p2pool.io", "mini.p2poolpeers.net", "mini.gupax.io", "" };
|
||||
static const char* seed_nodes_nano[] = { "seeds-nano.p2pool.io", "nano.p2poolpeers.net", "nano.gupax.io", ""};
|
||||
static const char* seed_nodes[] = { "" };
|
||||
static const char* seed_nodes_mini[] = { "" };
|
||||
static const char* seed_nodes_nano[] = { "" };
|
||||
|
||||
static constexpr int DEFAULT_BACKLOG = 16;
|
||||
static constexpr uint64_t DEFAULT_BAN_TIME = 600;
|
||||
@@ -416,7 +416,7 @@ void P2PServer::update_peer_connections()
|
||||
m_seenGoodPeers = true;
|
||||
}
|
||||
else if (!m_peerListMonero.empty()) {
|
||||
LOGINFO(3, "Scanning monerod peers, " << m_peerListMonero.size() << " left");
|
||||
LOGINFO(3, "Scanning salviumd peers, " << m_peerListMonero.size() << " left");
|
||||
for (uint32_t i = 0; (i < 25) && !m_peerListMonero.empty(); ++i) {
|
||||
peer_list.push_back(m_peerListMonero.back());
|
||||
m_peerListMonero.pop_back();
|
||||
@@ -473,7 +473,7 @@ void P2PServer::update_peer_connections()
|
||||
}
|
||||
|
||||
if (!has_good_peers && ((m_timerCounter % 10) == 0) && (SideChain::network_type() == NetworkType::Mainnet)) {
|
||||
LOGERR(1, "no connections to other p2pool nodes, check your monerod/p2pool/network/firewall setup!!!");
|
||||
LOGERR(1, "no connections to other p2pool nodes, check your salviumd/p2pool/network/firewall setup!!!");
|
||||
load_peer_list();
|
||||
if (m_peerListMonero.empty()) {
|
||||
load_monerod_peer_list();
|
||||
@@ -866,7 +866,7 @@ void P2PServer::load_monerod_peer_list()
|
||||
// Put recently active peers last in the list (it will be scanned backwards)
|
||||
std::sort(m_peerListMonero.begin(), m_peerListMonero.end(), [](const Peer& a, const Peer& b) { return a.m_lastSeen < b.m_lastSeen; });
|
||||
|
||||
LOGINFO(4, "monerod peer list loaded (" << m_peerListMonero.size() << " peers)");
|
||||
LOGINFO(4, "salviumd peer list loaded (" << m_peerListMonero.size() << " peers)");
|
||||
},
|
||||
[](const char* data, size_t size, double)
|
||||
{
|
||||
@@ -1504,7 +1504,7 @@ void P2PServer::check_for_updates(bool forced) const
|
||||
|
||||
if ((forced || s.precalcFinished()) && m_newP2PoolVersionDetected && s.p2pool_update_available()) {
|
||||
LOGINFO(0, log::LightCyan() << "********************************************************************************");
|
||||
LOGINFO(0, log::LightCyan() << "* An updated P2Pool version is available, visit p2pool.io for more information *");
|
||||
LOGINFO(0, log::LightCyan() << "* An updated P2Pool-salvium version is available, visit whiskymine.io for more information *");
|
||||
LOGINFO(0, log::LightCyan() << "********************************************************************************");
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -32,11 +32,11 @@ static constexpr uint64_t P2P_BUF_SIZE = MAX_BLOCK_SIZE + (1 + sizeof(uint32_t))
|
||||
static_assert((P2P_BUF_SIZE & (P2P_BUF_SIZE - 1)) == 0, "P2P_BUF_SIZE is not a power of 2, fix MAX_BLOCK_SIZE");
|
||||
|
||||
static constexpr size_t PEER_LIST_RESPONSE_MAX_PEERS = 16;
|
||||
static constexpr int DEFAULT_P2P_PORT = 37889;
|
||||
static constexpr int DEFAULT_P2P_PORT_MINI = 37888;
|
||||
static constexpr int DEFAULT_P2P_PORT_NANO = 37890;
|
||||
static constexpr int DEFAULT_P2P_PORT = 38889;
|
||||
static constexpr int DEFAULT_P2P_PORT_MINI = 38888;
|
||||
static constexpr int DEFAULT_P2P_PORT_NANO = 38890;
|
||||
|
||||
static constexpr int DEFAULT_P2P_PORT_ONION = 28722;
|
||||
static constexpr int DEFAULT_P2P_PORT_ONION = 29722;
|
||||
|
||||
static constexpr uint32_t PROTOCOL_VERSION_1_0 = 0x00010000UL;
|
||||
static constexpr uint32_t PROTOCOL_VERSION_1_1 = 0x00010001UL;
|
||||
|
||||
@@ -243,12 +243,15 @@ Params::Params(int argc, char* const argv[])
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
if ((strcmp(argv[i], "--merge-mine") == 0) && (i + 2 < argc)) {
|
||||
m_mergeMiningHosts.emplace_back(argv[i + 1], argv[i + 2]);
|
||||
i += 2;
|
||||
ok = true;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
#ifdef WITH_TLS
|
||||
if ((strcmp(argv[i], "--tls-cert") == 0) && (i + 1 < argc)) {
|
||||
m_tlsCert = argv[++i];
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ struct Params
|
||||
|
||||
struct Host
|
||||
{
|
||||
Host() : m_address("127.0.0.1"), m_rpcPort(18081), m_zmqPort(18083), m_rpcSSL(false) {}
|
||||
Host() : m_address("127.0.0.1"), m_rpcPort(19081), m_zmqPort(19083), m_rpcSSL(false) {}
|
||||
|
||||
Host(const char* address, int32_t rpcPort, int32_t zmqPort, const char* rpcLogin)
|
||||
: m_address(address)
|
||||
|
||||
+9
-2
@@ -53,8 +53,15 @@ struct MinerShare;
|
||||
// 128 KB minus BLOCK_RESPONSE P2P protocol header (5 bytes)
|
||||
static constexpr uint64_t MAX_BLOCK_SIZE = 128 * 1024 - 5;
|
||||
|
||||
// 0.6 XMR
|
||||
static constexpr uint64_t BASE_BLOCK_REWARD = 600000000000ULL;
|
||||
// Salvium emission constants (from cryptonote_config.h)
|
||||
static constexpr uint64_t MONEY_SUPPLY = 18440000000000000ULL; // 184.4M * 10^8
|
||||
static constexpr uint64_t FINAL_SUBSIDY_PER_MINUTE = 30000000ULL; // 0.3 SAL
|
||||
static constexpr uint64_t PREMINE_AMOUNT = 2210000000000000ULL;
|
||||
static constexpr int EMISSION_SPEED_FACTOR_PER_MINUTE = 21;
|
||||
static constexpr int DIFFICULTY_TARGET_V2 = 120; // 2 minutes
|
||||
static constexpr int TARGET_MINUTES = DIFFICULTY_TARGET_V2 / 60; // 2
|
||||
static constexpr int EMISSION_SPEED_FACTOR = EMISSION_SPEED_FACTOR_PER_MINUTE - (TARGET_MINUTES - 1); // 20
|
||||
static constexpr uint64_t BASE_BLOCK_REWARD = FINAL_SUBSIDY_PER_MINUTE * TARGET_MINUTES; // Tail emission
|
||||
|
||||
// 1000 years at 1 TH/s. It should be enough for any normal use.
|
||||
static constexpr difficulty_type MAX_CUMULATIVE_DIFFICULTY{ 13019633956666736640ULL, 1710ULL };
|
||||
|
||||
+54
-17
@@ -22,6 +22,7 @@
|
||||
#include "wallet.h"
|
||||
#include "keccak.h"
|
||||
#include "crypto.h"
|
||||
#include <ios>
|
||||
|
||||
extern "C" {
|
||||
#include "crypto-ops.h"
|
||||
@@ -35,9 +36,9 @@ namespace {
|
||||
|
||||
// Allow only regular addresses (no integrated addresses, no subaddresses)
|
||||
// Values taken from cryptonote_config.h (CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX)
|
||||
constexpr uint64_t valid_prefixes[] = { 18, 53, 24 };
|
||||
|
||||
constexpr uint64_t valid_prefixes_subaddress[] = { 42, 63, 36 };
|
||||
constexpr uint64_t valid_prefixes[] = { 0x180c96, 0x254c96, 0x24cc96 }; // SC1, SC1T, SC1S (mainnet, testnet, stagenet)
|
||||
constexpr uint64_t valid_prefixes_subaddress[] = { 0x314c96, 0x3c54c96, 0x384cc96 }; // SC1s, SC1Ts, SC1Ss
|
||||
|
||||
constexpr std::array<int, 9> block_sizes{ 0, 2, 3, 5, 6, 7, 9, 10, 11 };
|
||||
constexpr int num_full_blocks = p2pool::Wallet::ADDRESS_LENGTH / block_sizes.back();
|
||||
@@ -115,23 +116,35 @@ bool Wallet::decode(const char* address)
|
||||
{
|
||||
m_type = NetworkType::Invalid;
|
||||
|
||||
if (!address || (strlen(address) != ADDRESS_LENGTH)) {
|
||||
if (!address) {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr int last_block_size_index = block_sizes_lookup[last_block_size];
|
||||
const size_t addr_len = strlen(address);
|
||||
if (addr_len < 97 || addr_len > 98) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static_assert(last_block_size_index >= 0, "Check ADDRESS_LENGTH");
|
||||
// Calculate based on actual address length
|
||||
const int actual_num_full_blocks = addr_len / block_sizes.back();
|
||||
const int actual_last_block_size = addr_len % block_sizes.back();
|
||||
const int actual_last_block_size_index = block_sizes_lookup[actual_last_block_size];
|
||||
|
||||
uint8_t data[static_cast<size_t>(num_full_blocks) * sizeof(uint64_t) + last_block_size_index] = {};
|
||||
if (actual_last_block_size_index < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t data[73] = {};
|
||||
int data_index = 0;
|
||||
|
||||
for (int i = 0; i <= num_full_blocks; ++i) {
|
||||
const char* addr_ptr = address; // Use separate pointer for iteration
|
||||
|
||||
for (int i = 0; i <= actual_num_full_blocks; ++i) {
|
||||
uint64_t num = 0;
|
||||
uint64_t order = 1;
|
||||
|
||||
for (int j = ((i < num_full_blocks) ? block_sizes.back() : last_block_size) - 1; j >= 0; --j) {
|
||||
const int8_t digit = rev_alphabet.data[static_cast<uint8_t>(address[j])];
|
||||
for (int j = ((i < actual_num_full_blocks) ? block_sizes.back() : actual_last_block_size) - 1; j >= 0; --j) {
|
||||
const int8_t digit = rev_alphabet.data[static_cast<uint8_t>(addr_ptr[j])];
|
||||
if (digit < 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -146,14 +159,28 @@ bool Wallet::decode(const char* address)
|
||||
order *= alphabet_size;
|
||||
}
|
||||
|
||||
address += block_sizes.back();
|
||||
addr_ptr += (i < actual_num_full_blocks) ? block_sizes.back() : actual_last_block_size; // Advance by actual size
|
||||
|
||||
for (int j = static_cast<int>((i < num_full_blocks) ? sizeof(num) : last_block_size_index) - 1; j >= 0; --j) {
|
||||
for (int j = static_cast<int>((i < actual_num_full_blocks) ? sizeof(num) : actual_last_block_size_index) - 1; j >= 0; --j) {
|
||||
data[data_index++] = static_cast<uint8_t>(num >> (j * 8));
|
||||
}
|
||||
}
|
||||
|
||||
m_prefix = data[0];
|
||||
// Decode varint tag from start of data
|
||||
uint64_t tag = 0;
|
||||
int varint_len = 0;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
tag |= static_cast<uint64_t>(data[i] & 0x7F) << (i * 7);
|
||||
++varint_len;
|
||||
if ((data[i] & 0x80) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char hex_buf[32];
|
||||
snprintf(hex_buf, sizeof(hex_buf), "0x%lx", tag);
|
||||
|
||||
m_prefix = tag;
|
||||
|
||||
switch (m_prefix)
|
||||
{
|
||||
@@ -169,14 +196,25 @@ bool Wallet::decode(const char* address)
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(m_spendPublicKey.h, data + 1, HASH_SIZE);
|
||||
memcpy(m_viewPublicKey.h, data + 1 + HASH_SIZE, HASH_SIZE);
|
||||
memcpy(&m_checksum, data + 1 + HASH_SIZE * 2, sizeof(m_checksum));
|
||||
memcpy(m_spendPublicKey.h, data + varint_len, HASH_SIZE);
|
||||
memcpy(m_viewPublicKey.h, data + varint_len + HASH_SIZE, HASH_SIZE);
|
||||
|
||||
// Load checksum from correct position (at end of decoded data)
|
||||
memcpy(&m_checksum, data + data_index - sizeof(m_checksum), sizeof(m_checksum));
|
||||
|
||||
uint8_t md[200];
|
||||
keccak(data, sizeof(data) - sizeof(m_checksum), md);
|
||||
keccak(data, data_index - sizeof(m_checksum), md);
|
||||
|
||||
uint32_t calculated_checksum;
|
||||
memcpy(&calculated_checksum, md, sizeof(calculated_checksum));
|
||||
|
||||
if (m_checksum != calculated_checksum) {
|
||||
LOGINFO(1, "Checksum FAILED");
|
||||
m_type = NetworkType::Invalid;
|
||||
}
|
||||
|
||||
if (memcmp(&m_checksum, md, sizeof(m_checksum)) != 0) {
|
||||
LOGINFO(1, "Checksum FAILED");
|
||||
m_type = NetworkType::Invalid;
|
||||
}
|
||||
|
||||
@@ -187,7 +225,6 @@ bool Wallet::decode(const char* address)
|
||||
|
||||
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();
|
||||
|
||||
+1
-4
@@ -24,10 +24,7 @@ namespace p2pool {
|
||||
class Wallet
|
||||
{
|
||||
public:
|
||||
// public keys: 64 bytes -> 88 characters in base58
|
||||
// prefix (1 byte) + checksum (4 bytes) -> 7 characters in base58
|
||||
// 95 characters in total
|
||||
static constexpr int ADDRESS_LENGTH = 95;
|
||||
static constexpr int ADDRESS_LENGTH = 97;
|
||||
|
||||
explicit Wallet(const char* address);
|
||||
|
||||
|
||||
+52
-16
@@ -348,47 +348,83 @@ static std::vector<uint8_t> construct_monero_block_blob(rapidjson::Value* value,
|
||||
writeVarint(arr.Size(), blob);
|
||||
|
||||
for (auto* i = arr.begin(); i != arr.end(); ++i) {
|
||||
|
||||
auto amount = i->FindMember("amount");
|
||||
if ((amount == i->MemberEnd()) || !amount->value.IsUint64()) {
|
||||
LOGWARN(3, "construct_monero_block_blob: amount not found or is not UInt64");
|
||||
return empty_blob;
|
||||
}
|
||||
|
||||
auto to_tagged_key = i->FindMember("to_tagged_key");
|
||||
if ((to_tagged_key == i->MemberEnd()) || !to_tagged_key->value.IsObject()) {
|
||||
LOGWARN(3, "construct_monero_block_blob: to_tagged_key not found or is not an object");
|
||||
// Salvium uses target.carrot_v1 instead of to_tagged_key
|
||||
auto target = i->FindMember("target");
|
||||
if ((target == i->MemberEnd()) || !target->value.IsObject()) {
|
||||
// LOGWARN(3, "construct_salvium_block_blob: target not found or is not an object");
|
||||
continue;
|
||||
}
|
||||
|
||||
auto carrot_v1 = target->value.FindMember("carrot_v1");
|
||||
if ((carrot_v1 == target->value.MemberEnd()) || !carrot_v1->value.IsObject()) {
|
||||
LOGWARN(3, "construct_salvium_block_blob: carrot_v1 not found or is not an object");
|
||||
return empty_blob;
|
||||
}
|
||||
|
||||
auto key = to_tagged_key->value.FindMember("key");
|
||||
if ((key == to_tagged_key->value.MemberEnd()) || !key->value.IsString()) {
|
||||
LOGWARN(3, "construct_monero_block_blob: key not found or is not a string");
|
||||
auto key = carrot_v1->value.FindMember("key");
|
||||
if ((key == carrot_v1->value.MemberEnd()) || !key->value.IsString()) {
|
||||
LOGWARN(3, "construct_salvium_block_blob: key not found or is not a string");
|
||||
return empty_blob;
|
||||
}
|
||||
|
||||
auto view_tag = to_tagged_key->value.FindMember("view_tag");
|
||||
if ((view_tag == to_tagged_key->value.MemberEnd()) || !view_tag->value.IsString()) {
|
||||
LOGWARN(3, "construct_monero_block_blob: view_tag not found or is not a string");
|
||||
auto asset_type = carrot_v1->value.FindMember("asset_type");
|
||||
if ((asset_type == carrot_v1->value.MemberEnd()) || !asset_type->value.IsString()) {
|
||||
LOGWARN(3, "construct_salvium_block_blob: asset_type not found or is not a string");
|
||||
return empty_blob;
|
||||
}
|
||||
|
||||
auto view_tag = carrot_v1->value.FindMember("view_tag");
|
||||
if ((view_tag == carrot_v1->value.MemberEnd()) || !view_tag->value.IsString()) {
|
||||
LOGWARN(3, "construct_salvium_block_blob: view_tag not found or is not a string");
|
||||
return empty_blob;
|
||||
}
|
||||
|
||||
auto encrypted_janus_anchor = carrot_v1->value.FindMember("encrypted_janus_anchor");
|
||||
if ((encrypted_janus_anchor == carrot_v1->value.MemberEnd()) || !encrypted_janus_anchor->value.IsString()) {
|
||||
LOGWARN(3, "construct_salvium_block_blob: encrypted_janus_anchor not found or is not a string");
|
||||
return empty_blob;
|
||||
}
|
||||
|
||||
// Serialize: amount + type + key + asset_type + view_tag + encrypted_janus_anchor
|
||||
writeVarint(amount->value.GetUint64(), blob);
|
||||
blob.push_back(TXOUT_TO_TAGGED_KEY);
|
||||
blob.push_back(TXOUT_TO_CARROT_V1);
|
||||
|
||||
// Key (32 bytes)
|
||||
if (!from_hex(key->value.GetString(), key->value.GetStringLength(), h)) {
|
||||
LOGWARN(3, "construct_monero_block_blob: invalid key " << key->value.GetString());
|
||||
LOGWARN(3, "construct_salvium_block_blob: invalid key " << key->value.GetString());
|
||||
return empty_blob;
|
||||
}
|
||||
|
||||
blob.insert(blob.end(), h.h, h.h + HASH_SIZE);
|
||||
|
||||
std::vector<uint8_t> t;
|
||||
if (!from_hex(view_tag->value.GetString(), view_tag->value.GetStringLength(), t) || (t.size() != 1)) {
|
||||
LOGWARN(3, "construct_monero_block_blob: invalid view_tag " << view_tag->value.GetString());
|
||||
// Asset type (string with length prefix)
|
||||
const char* asset_str = asset_type->value.GetString();
|
||||
const size_t asset_len = asset_type->value.GetStringLength();
|
||||
writeVarint(asset_len, blob);
|
||||
blob.insert(blob.end(), asset_str, asset_str + asset_len);
|
||||
|
||||
// View tag (3 bytes)
|
||||
std::vector<uint8_t> vt;
|
||||
if (!from_hex(view_tag->value.GetString(), view_tag->value.GetStringLength(), vt) || (vt.size() != 3)) {
|
||||
LOGWARN(3, "construct_salvium_block_blob: invalid view_tag " << view_tag->value.GetString());
|
||||
return empty_blob;
|
||||
}
|
||||
blob.insert(blob.end(), vt.begin(), vt.end());
|
||||
|
||||
// Encrypted janus anchor (16 bytes)
|
||||
std::vector<uint8_t> eja;
|
||||
if (!from_hex(encrypted_janus_anchor->value.GetString(), encrypted_janus_anchor->value.GetStringLength(), eja) || (eja.size() != 16)) {
|
||||
LOGWARN(3, "construct_salvium_block_blob: invalid encrypted_janus_anchor " << encrypted_janus_anchor->value.GetString());
|
||||
return empty_blob;
|
||||
}
|
||||
blob.insert(blob.end(), eja.begin(), eja.end());
|
||||
|
||||
blob.push_back(t[0]);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> t;
|
||||
|
||||
Reference in New Issue
Block a user