Skip to content
Permalink
Browse files

SQUASH

  • Loading branch information...
moneromooo-monero committed Jul 8, 2019
1 parent 12f6c35 commit 36d291fd5a5cfc213e8ae4db72a0c0d7fc098a25
@@ -76,14 +76,15 @@ class LoggingPerformanceTimer: public PerformanceTimer

void set_performance_timer_log_level(el::Level level);

#define PERF_TIMER_UNIT(name, unit) tools::LoggingPerformanceTimer pt_##name(#name, "perf." MONERO_DEFAULT_LOG_CATEGORY, unit, tools::performance_timer_log_level)
#define PERF_TIMER_UNIT_L(name, unit, l) tools::LoggingPerformanceTimer pt_##name(#name, "perf." MONERO_DEFAULT_LOG_CATEGORY, unit, l)
#define PERF_TIMER_NAME(name) pt_##name
#define PERF_TIMER_UNIT(name, unit) tools::LoggingPerformanceTimer PERF_TIMER_NAME(name)(#name, "perf." MONERO_DEFAULT_LOG_CATEGORY, unit, tools::performance_timer_log_level)
#define PERF_TIMER_UNIT_L(name, unit, l) tools::LoggingPerformanceTimer PERF_TIMER_NAME(name)t_##name(#name, "perf." MONERO_DEFAULT_LOG_CATEGORY, unit, l)
#define PERF_TIMER(name) PERF_TIMER_UNIT(name, 1000000)
#define PERF_TIMER_L(name, l) PERF_TIMER_UNIT_L(name, 1000000, l)
#define PERF_TIMER_START_UNIT(name, unit) std::unique_ptr<tools::LoggingPerformanceTimer> pt_##name(new tools::LoggingPerformanceTimer(#name, "perf." MONERO_DEFAULT_LOG_CATEGORY, unit, el::Level::Info))
#define PERF_TIMER_START_UNIT(name, unit) std::unique_ptr<tools::LoggingPerformanceTimer> PERF_TIMER_NAME(name)(new tools::LoggingPerformanceTimer(#name, "perf." MONERO_DEFAULT_LOG_CATEGORY, unit, el::Level::Info))
#define PERF_TIMER_START(name) PERF_TIMER_START_UNIT(name, 1000000)
#define PERF_TIMER_STOP(name) do { pt_##name.reset(NULL); } while(0)
#define PERF_TIMER_PAUSE(name) pt_##name->pause()
#define PERF_TIMER_RESUME(name) pt_##name->resume()
#define PERF_TIMER_STOP(name) do { PERF_TIMER_NAME(name).reset(NULL); } while(0)
#define PERF_TIMER_PAUSE(name) PERF_TIMER_NAME(name)->pause()
#define PERF_TIMER_RESUME(name) PERF_TIMER_NAME(name)->resume()

}
@@ -2278,7 +2278,7 @@ bool t_rpc_command_executor::rpc_payments()
}
}

const uint64_t now = (boost::posix_time::microsec_clock::universal_time() - cryptonote::rpc_payment_epoch).total_seconds();
const uint64_t now = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
uint64_t balance = 0;
tools::msg_writer() << boost::format("%64s %16u %16u %8u %8u %8u %8u %s")
% "Client ID" % "Balance" % "Total mined" % "Good" % "Stale" % "Bad" % "Dupes" % "Last update";
@@ -69,37 +69,44 @@ using namespace epee;

#define RPC_TRACKER(rpc) \
PERF_TIMER(rpc); \
RPCTracker tracker(#rpc)
RPCTracker tracker(#rpc, PERF_TIMER_NAME(rpc))

namespace
{
class RPCTracker
{
public:
RPCTracker(const char *rpc): rpc(rpc), timer(rpc, MONERO_DEFAULT_LOG_CATEGORY, 1000000, tools::performance_timer_log_level) {
struct entry_t
{
uint64_t count;
uint64_t time;
uint64_t credits;
};

RPCTracker(const char *rpc, tools::LoggingPerformanceTimer &timer): rpc(rpc), timer(timer) {
}
~RPCTracker() {
boost::unique_lock<boost::mutex> lock(mutex);
auto &e = tracker[rpc];
std::get<0>(e)++;
std::get<1>(e) = timer.value();
++e.count;
e.time += timer.value();
}
void pay(uint64_t amount) {
boost::unique_lock<boost::mutex> lock(mutex);
auto &e = tracker[rpc];
std::get<2>(e) += amount;
e.credits += amount;
}
const std::string &rpc_name() const { return rpc; }
static void clear() { boost::unique_lock<boost::mutex> lock(mutex); tracker.clear(); }
static std::unordered_map<std::string, std::tuple<uint64_t, uint64_t, uint64_t>> data() { boost::unique_lock<boost::mutex> lock(mutex); return tracker; }
static std::unordered_map<std::string, entry_t> data() { boost::unique_lock<boost::mutex> lock(mutex); return tracker; }
private:
std::string rpc;
tools::LoggingPerformanceTimer timer;
tools::LoggingPerformanceTimer &timer;
static boost::mutex mutex;
static std::unordered_map<std::string, std::tuple<uint64_t, uint64_t, uint64_t>> tracker;
static std::unordered_map<std::string, entry_t> tracker;
};
boost::mutex RPCTracker::mutex;
std::unordered_map<std::string, std::tuple<uint64_t, uint64_t, uint64_t>> RPCTracker::tracker;
std::unordered_map<std::string, RPCTracker::entry_t> RPCTracker::tracker;

void add_reason(std::string &reasons, const char *reason)
{
@@ -124,10 +131,6 @@ namespace
namespace cryptonote
{

std::string core_rpc_server::get_client_id_signature() const
{
return cryptonote::make_rpc_payment_signature(m_local_client);
}
//-----------------------------------------------------------------------------------
void core_rpc_server::init_options(boost::program_options::options_description& desc)
{
@@ -172,6 +175,12 @@ namespace cryptonote
std::string address = command_line::get_arg(vm, arg_rpc_payment_address);
if (!address.empty())
{
if (!m_restricted && nettype() != FAKECHAIN)

{
MERROR("RPC payment enabled, but server is not restricted, anyone can adjust their balance to bypass payment");
return false;
}
cryptonote::address_parse_info info;
if (!get_account_address_from_str(info, nettype(), address))
{
@@ -203,8 +212,6 @@ namespace cryptonote
MWARNING("The RPC server is accessible from the outside, but no RPC payment was setup. RPC access will be free for all.");
}

m_local_client = rct::rct2sk(rct::skGen());

m_bootstrap_daemon_address = command_line::get_arg(vm, arg_bootstrap_daemon_address);
if (!m_bootstrap_daemon_address.empty())
{
@@ -270,12 +277,6 @@ namespace cryptonote
return false;
}
crypto::public_key local_client;
crypto::secret_key_to_public_key(m_local_client, local_client);
if (client == local_client)
{
credits = 0;
return true;
}
if (!m_rpc_payment->pay(client, ts, payment, rpc, same_ts, credits))
{
message = CORE_RPC_STATUS_PAYMENT_REQUIRED;
@@ -2669,7 +2670,8 @@ namespace cryptonote
}

crypto::public_key client;
if (!epee::string_tools::hex_to_pod(req.client.substr(0, 2 * sizeof(client)), client))
uint64_t ts;
if (!cryptonote::verify_rpc_payment_signature(req.client, client, ts))
{
res.credits = 0;
res.status = "Invalid client ID";
@@ -2780,7 +2782,7 @@ namespace cryptonote
return false;
}

RPCTracker ext_tracker(("external:" + req.paying_for).c_str());
RPCTracker ext_tracker(("external:" + req.paying_for).c_str(), PERF_TIMER_NAME(rpc_access_pay));
if (!check_payment(req.client, req.payment, req.paying_for, false, res.status, res.credits, res.top_hash))
return true;
ext_tracker.pay(req.payment);
@@ -2805,9 +2807,9 @@ namespace cryptonote
{
res.data.resize(res.data.size() + 1);
res.data.back().rpc = d.first;
res.data.back().count = std::get<0>(d.second);
res.data.back().time = std::get<1>(d.second);
res.data.back().credits = std::get<2>(d.second);
res.data.back().count = d.second.count;
res.data.back().time = d.second.time;
res.data.back().credits = d.second.credits;
}

res.status = CORE_RPC_STATUS_OK;
@@ -89,8 +89,6 @@ namespace cryptonote
);
network_type nettype() const { return m_core.get_nettype(); }

std::string get_client_id_signature() const;

CHAIN_HTTP_TO_MAP2(connection_context); //forward http requests to uri map

BEGIN_URI_MAP2()
@@ -275,7 +273,6 @@ namespace cryptonote
bool m_was_bootstrap_ever_used;
bool m_restricted;
std::unique_ptr<rpc_payment> m_rpc_payment;
crypto::secret_key m_local_client;
};
}

@@ -52,6 +52,9 @@
#define PENALTY_FOR_DUPLICATE 20

#define DEFAULT_FLUSH_AGE (3600 * 24 * 180) // half a year
#define DEFAULT_ZERO_FLUSH_AGE (60 * 2) // 2 minutes

#define RPC_PAYMENT_NONCE_TAIL 0x58

namespace
{
@@ -145,7 +148,12 @@ namespace cryptonote
return false;
if(!remove_field_from_tx_extra(new_block.miner_tx.extra, typeid(cryptonote::tx_extra_nonce)))
return false;
extra_nonce = cryptonote::blobdata((const char*)&client, 4);
char data[33];
memcpy(data, &client, 32);
data[32] = RPC_PAYMENT_NONCE_TAIL;
crypto::hash hash;
cn_fast_hash(data, sizeof(data), hash);
extra_nonce = cryptonote::blobdata((const char*)&hash, 4);
if(!add_extra_nonce_to_tx_extra(new_block.miner_tx.extra, extra_nonce))
return false;
info.previous_block = std::move(info.block);
@@ -185,7 +193,7 @@ namespace cryptonote
const bool is_current = cookie == info.cookie;
MINFO("client " << client << " sends nonce: " << nonce << ", " << (is_current ? "current" : "stale"));
std::unordered_set<uint64_t> &payments = is_current ? info.payments : info.previous_payments;
if (payments.find(nonce) != payments.end())
if (!payments.insert(nonce).second)
{
MWARNING("Duplicate nonce " << nonce << " from " << (is_current ? "current" : "previous"));
++m_nonces_dupe;
@@ -195,7 +203,6 @@ namespace cryptonote
error_message = "Duplicate payment";
return false;
}
payments.insert(nonce);

const uint64_t now = time(NULL);
if (!is_current)
@@ -262,10 +269,10 @@ namespace cryptonote
return true;
}

bool rpc_payment::load(const std::string &directory)
bool rpc_payment::load(std::string directory)
{
TRY_ENTRY();
m_directory = directory;
m_directory = std::move(directory);
std::string state_file_path = directory + "/" + RPC_PAYMENTS_DATA_FILENAME;
MINFO("loading rpc payments data from " << state_file_path);
std::ifstream data;
@@ -302,18 +309,18 @@ namespace cryptonote
MWARNING("Failed to create data directory: " << directory);
return false;
}
std::string state_file_path = (boost::filesystem::path(directory) / RPC_PAYMENTS_DATA_FILENAME).string();
if (epee::file_io_utils::is_file_exist(state_file_path))
const boost::filesystem::path state_file_path = (boost::filesystem::path(directory) / RPC_PAYMENTS_DATA_FILENAME);
if (boost::filesystem::exists(state_file_path))
{
std::string state_file_path_old = state_file_path + ".old";
std::string state_file_path_old = state_file_path.string() + ".old";
boost::system::error_code ec;
boost::filesystem::remove(state_file_path_old, ec);
std::error_code e = tools::replace_file(state_file_path, state_file_path_old);
std::error_code e = tools::replace_file(state_file_path.string(), state_file_path_old);
if (e)
MWARNING("Failed to rename " << state_file_path << " to " << state_file_path_old << ": " << e);
}
std::ofstream data;
data.open(state_file_path, std::ios_base::binary | std::ios_base::out | std::ios::trunc);
data.open(state_file_path.string(), std::ios_base::binary | std::ios_base::out | std::ios::trunc);
if (data.fail())
{
MWARNING("Failed to save RPC payments to file " << state_file_path);
@@ -330,20 +337,20 @@ namespace cryptonote
{
unsigned int count = 0;
const time_t now = time(NULL);
time_t seconds0 = seconds;
if (seconds == 0)
{
seconds = DEFAULT_FLUSH_AGE;
const time_t t0 = seconds > now ? 0 : now - seconds;
seconds0 = DEFAULT_ZERO_FLUSH_AGE;
}
const time_t threshold = seconds > now ? 0 : now - seconds;
const time_t threshold0 = seconds0 > now ? 0 : now - seconds0;
for (std::unordered_map<crypto::public_key, client_info>::iterator i = m_client_info.begin(); i != m_client_info.end(); )
{
std::unordered_map<crypto::public_key, client_info>::iterator j = i++;
const time_t t = std::max(j->second.last_request_timestamp, j->second.update_time);
if (j->second.credits == 0)
{
MINFO("Erasing " << j->first << " with " << j->second.credits << " credits");
m_client_info.erase(j);
++count;
}
else if (t < t0)
const bool erase = t < ((j->second.credits == 0) ? threshold0 : threshold);
if (erase)
{
MINFO("Erasing " << j->first << " with " << j->second.credits << " credits, inactive for " << (now-t)/86400 << " days");
m_client_info.erase(j);
@@ -355,12 +362,11 @@ namespace cryptonote

uint64_t rpc_payment::get_hashes(unsigned int seconds) const
{
const time_t now = time(NULL);
const uint64_t now = time(NULL);
uint64_t hashes = 0;
for (std::map<uint32_t, uint64_t>::const_reverse_iterator i = m_hashrate.crbegin(); i != m_hashrate.crend(); ++i)
for (std::map<uint64_t, uint64_t>::const_reverse_iterator i = m_hashrate.crbegin(); i != m_hashrate.crend(); ++i)
{
unsigned age = now - i->first;
if (age > seconds)
if (now > i->first + seconds)
break;
hashes += i->second;
}
@@ -369,12 +375,11 @@ namespace cryptonote

void rpc_payment::prune_hashrate(unsigned int seconds)
{
const time_t now = time(NULL);
std::map<uint32_t, uint64_t>::iterator i;
const uint64_t now = time(NULL);
std::map<uint64_t, uint64_t>::iterator i;
for (i = m_hashrate.begin(); i != m_hashrate.end(); ++i)
{
unsigned age = now - i->first;
if (age <= seconds)
if (now <= i->first + seconds)
break;
}
m_hashrate.erase(m_hashrate.begin(), i);
@@ -115,7 +115,7 @@ namespace cryptonote
a & m_nonces_dupe;
}

bool load(const std::string &directory);
bool load(std::string directory);
bool store(const std::string &directory = std::string());

private:
@@ -124,7 +124,7 @@ namespace cryptonote
uint64_t m_credits_per_hash_found;
std::unordered_map<crypto::public_key, client_info> m_client_info;
std::string m_directory;
std::map<uint32_t, uint64_t> m_hashrate;
std::map<uint64_t, uint64_t> m_hashrate;
uint64_t m_credits_total;
uint64_t m_credits_used;
uint64_t m_nonces_good;
@@ -28,6 +28,7 @@

#include <inttypes.h>
#include <stdlib.h>
#include <chrono>
#include "include_base_utils.h"
#include "string_tools.h"
#include "rpc_payment_signature.h"
@@ -39,17 +40,16 @@

namespace cryptonote
{
const boost::posix_time::ptime rpc_payment_epoch(boost::gregorian::date(1970, 1, 1));

std::string make_rpc_payment_signature(const crypto::secret_key &skey)
{
std::string s;
crypto::public_key pkey;
crypto::secret_key_to_public_key(skey, pkey);
crypto::signature sig;
const uint64_t now = (boost::posix_time::microsec_clock::universal_time() - rpc_payment_epoch).total_microseconds();
const uint64_t now = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
char ts[17];
snprintf(ts, sizeof(ts), "%16.16" PRIx64, now);
int ret = snprintf(ts, sizeof(ts), "%16.16" PRIx64, now);
CHECK_AND_ASSERT_MES(ret == 16, "", "snprintf failed");
ts[16] = 0;
CHECK_AND_ASSERT_MES(strlen(ts) == 16, "", "Invalid time conversion");
crypto::hash hash;
@@ -96,7 +96,7 @@ namespace cryptonote
return false;
}
ts = ull;
const uint64_t now = (boost::posix_time::microsec_clock::universal_time() - rpc_payment_epoch).total_microseconds();
const uint64_t now = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
if (ts > now + TIMESTAMP_LEEWAY)
{
MDEBUG("Timestamp is in the future");
@@ -34,7 +34,6 @@

namespace cryptonote
{
extern const boost::posix_time::ptime rpc_payment_epoch;
std::string make_rpc_payment_signature(const crypto::secret_key &skey);
bool verify_rpc_payment_signature(const std::string &message, crypto::public_key &pkey, uint64_t &ts);
}

0 comments on commit 36d291f

Please sign in to comment.
You can’t perform that action at this time.