mirror of
https://github.com/SChernykh/p2pool.git
synced 2025-01-03 17:29:24 +00:00
api: store difficulty and totalHashes for each block
This commit is contained in:
parent
2d8530798d
commit
661d596107
9 changed files with 122 additions and 18 deletions
|
@ -52,6 +52,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <signal.h>
|
#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); }
|
||||||
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); }
|
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
|
// Finds a 64-bit target for mining (target = 2^64 / difficulty) and rounds up the result of division
|
||||||
|
|
|
@ -29,6 +29,8 @@ namespace log {
|
||||||
|
|
||||||
int GLOBAL_LOG_LEVEL = 4;
|
int GLOBAL_LOG_LEVEL = 4;
|
||||||
|
|
||||||
|
#ifndef P2POOL_LOG_DISABLE
|
||||||
|
|
||||||
static volatile bool stopped = false;
|
static volatile bool stopped = false;
|
||||||
static volatile bool worker_started = false;
|
static volatile bool worker_started = false;
|
||||||
|
|
||||||
|
@ -234,9 +236,9 @@ private:
|
||||||
std::ofstream m_logFile;
|
std::ofstream m_logFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef P2POOL_LOG_DISABLE
|
|
||||||
static Worker worker;
|
static Worker worker;
|
||||||
#endif
|
|
||||||
|
#endif // P2POOL_LOG_DISABLE
|
||||||
|
|
||||||
NOINLINE Writer::Writer(Severity severity) : Stream(m_stackBuf)
|
NOINLINE Writer::Writer(Severity severity) : Stream(m_stackBuf)
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,7 +34,8 @@ struct Stream
|
||||||
{
|
{
|
||||||
enum params : int { BUF_SIZE = 1024 - 1 };
|
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>
|
template<typename T>
|
||||||
struct Entry
|
struct Entry
|
||||||
|
@ -88,8 +89,8 @@ struct Stream
|
||||||
FORCEINLINE void writeBuf(const char* buf, size_t n0)
|
FORCEINLINE void writeBuf(const char* buf, size_t n0)
|
||||||
{
|
{
|
||||||
const int n = static_cast<int>(n0);
|
const int n = static_cast<int>(n0);
|
||||||
int pos = m_pos;
|
const int pos = m_pos;
|
||||||
if (pos > BUF_SIZE - n) {
|
if (pos + n > m_bufSize) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memcpy(m_buf + pos, buf, n);
|
memcpy(m_buf + pos, buf, n);
|
||||||
|
@ -104,6 +105,7 @@ struct Stream
|
||||||
int m_pos;
|
int m_pos;
|
||||||
int m_numberWidth;
|
int m_numberWidth;
|
||||||
char* m_buf;
|
char* m_buf;
|
||||||
|
int m_bufSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Writer : public Stream
|
struct Writer : public Stream
|
||||||
|
|
|
@ -583,8 +583,16 @@ void p2pool::get_info()
|
||||||
|
|
||||||
uint64_t height;
|
uint64_t height;
|
||||||
f >> 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);
|
api_update_block_found(nullptr);
|
||||||
}
|
}
|
||||||
|
@ -821,8 +829,8 @@ void p2pool::api_update_pool_stats()
|
||||||
MutexLock lock(m_foundBlocksLock);
|
MutexLock lock(m_foundBlocksLock);
|
||||||
if (!m_foundBlocks.empty()) {
|
if (!m_foundBlocks.empty()) {
|
||||||
total_blocks_found = m_foundBlocks.size();
|
total_blocks_found = m_foundBlocks.size();
|
||||||
last_block_found_time = m_foundBlocks.back().first;
|
last_block_found_time = m_foundBlocks.back().timestamp;
|
||||||
last_block_found_height = m_foundBlocks.back().second;
|
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 time_t cur_time = time(nullptr);
|
||||||
|
const difficulty_type total_hashes = m_sideChain->total_hashes();
|
||||||
|
difficulty_type diff;
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
|
{
|
||||||
|
ReadLock lock(m_mainchainLock);
|
||||||
|
diff.lo = m_mainchainByHeight[data->height].difficulty;
|
||||||
|
}
|
||||||
|
|
||||||
std::ofstream f(FOUND_BLOCKS_FILE, std::ios::app);
|
std::ofstream f(FOUND_BLOCKS_FILE, std::ios::app);
|
||||||
if (f.is_open()) {
|
if (f.is_open()) {
|
||||||
f << cur_time << ' ' << data->height << '\n';
|
f << cur_time << ' ' << data->height << ' ' << diff << ' ' << total_hashes << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<FoundBlock> found_blocks;
|
||||||
std::vector<std::pair<time_t, uint64_t>> found_blocks;
|
|
||||||
{
|
{
|
||||||
MutexLock lock(m_foundBlocksLock);
|
MutexLock lock(m_foundBlocksLock);
|
||||||
if (data) {
|
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",
|
m_api->set(p2pool_api::Category::POOL, "blocks",
|
||||||
|
@ -873,8 +887,10 @@ void p2pool::api_update_block_found(const ChainMain* data)
|
||||||
if (!first) {
|
if (!first) {
|
||||||
s << ',';
|
s << ',';
|
||||||
}
|
}
|
||||||
s << "{\"height\":" << i->second << ',';
|
s << "{\"height\":" << i->height << ','
|
||||||
s << "\"ts\":" << i->first << '}';
|
<< "\"difficulty\":" << i->block_diff << ','
|
||||||
|
<< "\"totalHashes\":" << i->total_hashes << ','
|
||||||
|
<< "\"ts\":" << i->timestamp << '}';
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
s << ']';
|
s << ']';
|
||||||
|
|
17
src/p2pool.h
17
src/p2pool.h
|
@ -117,8 +117,23 @@ private:
|
||||||
void api_update_pool_stats();
|
void api_update_pool_stats();
|
||||||
void api_update_block_found(const ChainMain* data);
|
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;
|
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 };
|
std::atomic<uint32_t> m_serversStarted{ 0 };
|
||||||
StratumServer* m_stratumServer = nullptr;
|
StratumServer* m_stratumServer = nullptr;
|
||||||
|
|
|
@ -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)
|
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);
|
std::vector<char> buf(16384);
|
||||||
log::Stream s(buf.data());
|
log::Stream s(buf.data(), buf.size());
|
||||||
callback(s);
|
callback(s);
|
||||||
buf.resize(s.m_pos);
|
buf.resize(s.m_pos);
|
||||||
|
|
||||||
|
|
|
@ -667,6 +667,7 @@ void SideChain::print_status()
|
||||||
|
|
||||||
difficulty_type SideChain::total_hashes() const
|
difficulty_type SideChain::total_hashes() const
|
||||||
{
|
{
|
||||||
|
MutexLock lock(m_sidechainLock);
|
||||||
return m_chainTip ? m_chainTip->m_cumulativeDifficulty : difficulty_type();
|
return m_chainTip ? m_chainTip->m_cumulativeDifficulty : difficulty_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
38
src/util.cpp
38
src/util.cpp
|
@ -117,6 +117,44 @@ difficulty_type operator+(const difficulty_type& a, const difficulty_type& b)
|
||||||
return result;
|
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)
|
void uv_mutex_init_checked(uv_mutex_t* mutex)
|
||||||
{
|
{
|
||||||
const int result = uv_mutex_init(mutex);
|
const int result = uv_mutex_init(mutex);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include <random>
|
#include <random>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace p2pool {
|
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)
|
TEST(difficulty_type, check_pow)
|
||||||
{
|
{
|
||||||
hash h;
|
hash h;
|
||||||
|
|
Loading…
Reference in a new issue