api: store difficulty and totalHashes for each block

This commit is contained in:
SChernykh 2021-09-03 18:04:54 +02:00
parent 2d8530798d
commit 661d596107
9 changed files with 122 additions and 18 deletions

View file

@ -52,6 +52,7 @@
#include <algorithm>
#include <atomic>
#include <chrono>
#include <iostream>
#include <signal.h>
@ -187,6 +188,9 @@ struct difficulty_type
FORCEINLINE bool operator==(const difficulty_type& other) const { return (lo == other.lo) && (hi == other.hi); }
FORCEINLINE bool operator!=(const difficulty_type& other) const { return (lo != other.lo) || (hi != other.hi); }
friend std::ostream& operator<<(std::ostream& s, const difficulty_type& d);
friend std::istream& operator>>(std::istream& s, difficulty_type& d);
FORCEINLINE double to_double() const { return static_cast<double>(hi) * 18446744073709551616.0 + static_cast<double>(lo); }
// Finds a 64-bit target for mining (target = 2^64 / difficulty) and rounds up the result of division

View file

@ -29,6 +29,8 @@ namespace log {
int GLOBAL_LOG_LEVEL = 4;
#ifndef P2POOL_LOG_DISABLE
static volatile bool stopped = false;
static volatile bool worker_started = false;
@ -234,9 +236,9 @@ private:
std::ofstream m_logFile;
};
#ifndef P2POOL_LOG_DISABLE
static Worker worker;
#endif
#endif // P2POOL_LOG_DISABLE
NOINLINE Writer::Writer(Severity severity) : Stream(m_stackBuf)
{

View file

@ -34,7 +34,8 @@ struct Stream
{
enum params : int { BUF_SIZE = 1024 - 1 };
explicit FORCEINLINE Stream(char* buf) : m_pos(0), m_numberWidth(1), m_buf(buf) {}
explicit FORCEINLINE Stream(char* buf) : m_pos(0), m_numberWidth(1), m_buf(buf), m_bufSize(BUF_SIZE) {}
FORCEINLINE Stream(char* buf, size_t size) : m_pos(0), m_numberWidth(1), m_buf(buf), m_bufSize(static_cast<int>(size)) {}
template<typename T>
struct Entry
@ -88,8 +89,8 @@ struct Stream
FORCEINLINE void writeBuf(const char* buf, size_t n0)
{
const int n = static_cast<int>(n0);
int pos = m_pos;
if (pos > BUF_SIZE - n) {
const int pos = m_pos;
if (pos + n > m_bufSize) {
return;
}
memcpy(m_buf + pos, buf, n);
@ -104,6 +105,7 @@ struct Stream
int m_pos;
int m_numberWidth;
char* m_buf;
int m_bufSize;
};
struct Writer : public Stream

View file

@ -583,8 +583,16 @@ void p2pool::get_info()
uint64_t height;
f >> height;
if (f.eof()) break;
m_foundBlocks.emplace_back(std::make_pair(timestamp, height));
difficulty_type block_difficulty;
f >> block_difficulty;
if (f.eof()) break;
difficulty_type cumulative_difficulty;
f >> cumulative_difficulty;
m_foundBlocks.emplace_back(timestamp, height, block_difficulty, cumulative_difficulty);
}
api_update_block_found(nullptr);
}
@ -821,8 +829,8 @@ void p2pool::api_update_pool_stats()
MutexLock lock(m_foundBlocksLock);
if (!m_foundBlocks.empty()) {
total_blocks_found = m_foundBlocks.size();
last_block_found_time = m_foundBlocks.back().first;
last_block_found_height = m_foundBlocks.back().second;
last_block_found_time = m_foundBlocks.back().timestamp;
last_block_found_height = m_foundBlocks.back().height;
}
}
@ -846,22 +854,28 @@ void p2pool::api_update_block_found(const ChainMain* data)
}
const time_t cur_time = time(nullptr);
const difficulty_type total_hashes = m_sideChain->total_hashes();
difficulty_type diff;
if (data) {
{
ReadLock lock(m_mainchainLock);
diff.lo = m_mainchainByHeight[data->height].difficulty;
}
std::ofstream f(FOUND_BLOCKS_FILE, std::ios::app);
if (f.is_open()) {
f << cur_time << ' ' << data->height << '\n';
f << cur_time << ' ' << data->height << ' ' << diff << ' ' << total_hashes << '\n';
}
}
std::vector<std::pair<time_t, uint64_t>> found_blocks;
std::vector<FoundBlock> found_blocks;
{
MutexLock lock(m_foundBlocksLock);
if (data) {
m_foundBlocks.emplace_back(std::make_pair(cur_time, data->height));
m_foundBlocks.emplace_back(cur_time, data->height, diff, total_hashes);
}
found_blocks.assign(m_foundBlocks.end() - std::min<size_t>(m_foundBlocks.size(), 25), m_foundBlocks.end());
found_blocks.assign(m_foundBlocks.end() - std::min<size_t>(m_foundBlocks.size(), 100), m_foundBlocks.end());
}
m_api->set(p2pool_api::Category::POOL, "blocks",
@ -873,8 +887,10 @@ void p2pool::api_update_block_found(const ChainMain* data)
if (!first) {
s << ',';
}
s << "{\"height\":" << i->second << ',';
s << "\"ts\":" << i->first << '}';
s << "{\"height\":" << i->height << ','
<< "\"difficulty\":" << i->block_diff << ','
<< "\"totalHashes\":" << i->total_hashes << ','
<< "\"ts\":" << i->timestamp << '}';
first = false;
}
s << ']';

View file

@ -117,8 +117,23 @@ private:
void api_update_pool_stats();
void api_update_block_found(const ChainMain* data);
struct FoundBlock
{
FORCEINLINE FoundBlock(time_t _t, uint64_t _h, const difficulty_type& _block_diff, const difficulty_type& _total_hashes)
: timestamp(_t)
, height(_h)
, block_diff(_block_diff)
, total_hashes(_total_hashes)
{}
time_t timestamp;
uint64_t height;
difficulty_type block_diff;
difficulty_type total_hashes;
};
uv_mutex_t m_foundBlocksLock;
std::vector<std::pair<time_t, uint64_t>> m_foundBlocks;
std::vector<FoundBlock> m_foundBlocks;
std::atomic<uint32_t> m_serversStarted{ 0 };
StratumServer* m_stratumServer = nullptr;

View file

@ -94,8 +94,8 @@ void p2pool_api::on_stop()
void p2pool_api::dump_to_file_async_internal(const Category& category, const char* filename, DumpFileCallbackBase&& callback)
{
std::vector<char> buf(log::Stream::BUF_SIZE + 1);
log::Stream s(buf.data());
std::vector<char> buf(16384);
log::Stream s(buf.data(), buf.size());
callback(s);
buf.resize(s.m_pos);

View file

@ -667,6 +667,7 @@ void SideChain::print_status()
difficulty_type SideChain::total_hashes() const
{
MutexLock lock(m_sidechainLock);
return m_chainTip ? m_chainTip->m_cumulativeDifficulty : difficulty_type();
}

View file

@ -117,6 +117,44 @@ difficulty_type operator+(const difficulty_type& a, const difficulty_type& b)
return result;
}
std::ostream& operator<<(std::ostream& s, const difficulty_type& d)
{
char buf[log::Stream::BUF_SIZE + 1];
log::Stream s1(buf);
s1 << d << '\0';
s << buf;
return s;
}
std::istream& operator>>(std::istream& s, difficulty_type& diff)
{
diff.lo = 0;
diff.hi = 0;
bool found_number = false;
char c;
while (s.good() && !s.eof()) {
s.read(&c, 1);
if (!s.good() || s.eof()) {
break;
}
if ('0' <= c && c <= '9') {
found_number = true;
const uint32_t digit = static_cast<uint32_t>(c - '0');
uint64_t hi;
diff.lo = umul128(diff.lo, 10, &hi) + digit;
if (diff.lo < digit) {
++hi;
}
diff.hi = diff.hi * 10 + hi;
}
else if (found_number) {
return s;
}
}
return s;
}
void uv_mutex_init_checked(uv_mutex_t* mutex)
{
const int result = uv_mutex_init(mutex);

View file

@ -18,6 +18,7 @@
#include "common.h"
#include "gtest/gtest.h"
#include <random>
#include <sstream>
namespace p2pool {
@ -103,6 +104,31 @@ TEST(difficulty_type, compare)
}
}
TEST(difficulty_type, input_output)
{
auto test_value = [](uint64_t lo, uint64_t hi, const char* s) {
difficulty_type diff{ lo, hi };
std::stringstream ss;
ss << diff;
ASSERT_EQ(ss.str(), s);
difficulty_type diff2;
ss >> diff2;
ASSERT_EQ(diff2, diff);
};
test_value(0, 0, "0");
test_value(1, 0, "1");
test_value(340599339356ull, 0, "340599339356");
test_value(std::numeric_limits<uint64_t>::max(), 0, "18446744073709551615");
test_value(0, 1, "18446744073709551616");
test_value(1, 1, "18446744073709551617");
test_value(7766279631452241919ull, 5, "99999999999999999999");
test_value(7766279631452241920ull, 5, "100000000000000000000");
test_value(7766279631452241921ull, 5, "100000000000000000001");
test_value(14083847773837265618ull, 6692605942ull, "123456789012345678901234567890");
test_value(std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max(), "340282366920938463463374607431768211455");
}
TEST(difficulty_type, check_pow)
{
hash h;