diff --git a/src/common.h b/src/common.h index c7935a8..d6a868b 100644 --- a/src/common.h +++ b/src/common.h @@ -52,6 +52,7 @@ #include #include #include +#include #include @@ -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(hi) * 18446744073709551616.0 + static_cast(lo); } // Finds a 64-bit target for mining (target = 2^64 / difficulty) and rounds up the result of division diff --git a/src/log.cpp b/src/log.cpp index 5987608..c6f3945 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -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) { diff --git a/src/log.h b/src/log.h index dac0860..2a41c5c 100644 --- a/src/log.h +++ b/src/log.h @@ -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(size)) {} template struct Entry @@ -88,8 +89,8 @@ struct Stream FORCEINLINE void writeBuf(const char* buf, size_t n0) { const int n = static_cast(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 diff --git a/src/p2pool.cpp b/src/p2pool.cpp index 88366d1..c75ad9c 100644 --- a/src/p2pool.cpp +++ b/src/p2pool.cpp @@ -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> found_blocks; + std::vector 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(m_foundBlocks.size(), 25), m_foundBlocks.end()); + found_blocks.assign(m_foundBlocks.end() - std::min(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 << ']'; diff --git a/src/p2pool.h b/src/p2pool.h index 3db4702..0d1820c 100644 --- a/src/p2pool.h +++ b/src/p2pool.h @@ -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> m_foundBlocks; + std::vector m_foundBlocks; std::atomic m_serversStarted{ 0 }; StratumServer* m_stratumServer = nullptr; diff --git a/src/p2pool_api.cpp b/src/p2pool_api.cpp index dccf2dc..7b20848 100644 --- a/src/p2pool_api.cpp +++ b/src/p2pool_api.cpp @@ -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 buf(log::Stream::BUF_SIZE + 1); - log::Stream s(buf.data()); + std::vector buf(16384); + log::Stream s(buf.data(), buf.size()); callback(s); buf.resize(s.m_pos); diff --git a/src/side_chain.cpp b/src/side_chain.cpp index 21af2a4..8277000 100644 --- a/src/side_chain.cpp +++ b/src/side_chain.cpp @@ -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(); } diff --git a/src/util.cpp b/src/util.cpp index 714d5d1..46558ab 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -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(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); diff --git a/tests/src/difficulty_type.cpp b/tests/src/difficulty_type.cpp index dbeb6bb..d862f27 100644 --- a/tests/src/difficulty_type.cpp +++ b/tests/src/difficulty_type.cpp @@ -18,6 +18,7 @@ #include "common.h" #include "gtest/gtest.h" #include +#include 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::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::max(), std::numeric_limits::max(), "340282366920938463463374607431768211455"); +} + TEST(difficulty_type, check_pow) { hash h;