Compare commits

..

24 Commits

Author SHA1 Message Date
SChernykh 06463e3e68 p2pool v4.8.1 2025-06-25 08:03:43 +02:00
SChernykh 52d3454b0f CI: added pruned and compact block blobs test 2025-06-24 23:13:58 +02:00
SChernykh 927258396e Merge pull request #365 from Low-power/update-stratum-hashrate-data-without-connected-workers
Hash rate values in `local/stratum` API file stuck after all workers disconnected
2025-06-24 13:41:15 +02:00
SChernykh b9face492d CI: always save coverage data 2025-06-24 10:36:39 +02:00
WHR d289526f45 Stratum: update hash rate data on new block template, even when no workers connected 2025-06-24 16:32:16 +08:00
SChernykh 1b05f1e750 Block parser: stricter checks 2025-06-24 00:57:13 +02:00
SChernykh 10d583adb6 Added more checks to readVarint 2025-06-23 13:06:01 +02:00
SChernykh 1b863109f9 CI: more tests 2025-06-22 23:18:36 +02:00
SChernykh e5d487aa50 CI: added more tests 2025-06-22 21:58:57 +02:00
SChernykh e69f5722df CI: use clang-20 for code coverage 2025-06-22 17:22:35 +02:00
SChernykh b3678bfbe9 CI: added submit_sidechain_block test 2025-06-22 13:40:00 +02:00
SChernykh 7a82b0fe43 Deploy code coverage report 2025-06-22 11:11:06 +02:00
SChernykh 5aea5768a7 CI: more tests 2025-06-21 16:20:24 +02:00
SChernykh 3f54025384 CI: added more block template tests 2025-06-21 13:16:56 +02:00
SChernykh c421324b73 SideChain: fixed a synchronization blocker bug 2025-06-21 01:06:36 +02:00
SChernykh 0535ca2892 CI: added more tests 2025-06-20 23:30:10 +02:00
SChernykh e68a31f72a CI: added more crypto tests 2025-06-20 22:06:52 +02:00
SChernykh 02533848d2 Updated cppzmq 2025-06-20 19:52:54 +02:00
SChernykh 6cd79b3a48 CI: added more tests to improve code coverage 2025-06-20 19:49:30 +02:00
SChernykh 3d1ef0d049 CI: added code coverage workflow 2025-06-20 18:23:26 +02:00
SChernykh 547b3430c2 CI: added nano sidechain dump to tests 2025-06-20 11:24:49 +02:00
SChernykh 88df27a359 CI: block verify - more tests 2025-06-20 08:33:21 +02:00
SChernykh 7eaef5faca CI: use the latest cppcheck code again 2025-06-18 18:40:32 +02:00
SChernykh 9cb9545ce6 CI: use native runner for Ubuntu ARM64 builds 2025-06-16 17:00:55 +02:00
29 changed files with 585 additions and 97 deletions
+10 -10
View File
@@ -259,13 +259,13 @@ jobs:
strategy:
matrix:
config:
- {os: ubuntu-22.04, flags: "-fuse-linker-plugin -ffunction-sections -mfix-cortex-a53-835769 -mfix-cortex-a53-843419"}
- {os: ubuntu-22.04-arm, flags: "-fuse-linker-plugin -ffunction-sections -mfix-cortex-a53-835769 -mfix-cortex-a53-843419"}
steps:
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y git build-essential cmake gcc-aarch64-linux-gnu g++-aarch64-linux-gnu binutils-aarch64-linux-gnu qemu-user
sudo apt install -y git build-essential cmake
- name: Checkout repository
uses: actions/checkout@v4
@@ -275,7 +275,7 @@ jobs:
- name: Build libcurl
run: |
cd external/src/curl
cmake . -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../../../cmake/aarch64_toolchain.cmake -DCMAKE_C_FLAGS="-Os -flto=auto ${{ matrix.config.flags }}" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_DISABLE_INSTALL=ON -DCURL_ENABLE_EXPORT_TARGET=OFF -DCURL_DISABLE_HEADERS_API=ON -DCURL_DISABLE_BINDLOCAL=ON -DBUILD_LIBCURL_DOCS=OFF -DBUILD_MISC_DOCS=OFF -DENABLE_CURL_MANUAL=OFF -DCURL_ZLIB=OFF -DCURL_BROTLI=OFF -DCURL_ZSTD=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DCURL_DISABLE_WEBSOCKETS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF -DCURL_DISABLE_TESTS=ON -DUSE_NGHTTP2=OFF -DBUILD_EXAMPLES=OFF -DP2POOL_BORINGSSL=ON -DCURL_DISABLE_SRP=ON -DOPENSSL_INCLUDE_DIR=../grpc/third_party/boringssl-with-bazel/src/include
cmake . -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="-Os -flto=auto ${{ matrix.config.flags }}" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_DISABLE_INSTALL=ON -DCURL_ENABLE_EXPORT_TARGET=OFF -DCURL_DISABLE_HEADERS_API=ON -DCURL_DISABLE_BINDLOCAL=ON -DBUILD_LIBCURL_DOCS=OFF -DBUILD_MISC_DOCS=OFF -DENABLE_CURL_MANUAL=OFF -DCURL_ZLIB=OFF -DCURL_BROTLI=OFF -DCURL_ZSTD=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DCURL_DISABLE_WEBSOCKETS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF -DCURL_DISABLE_TESTS=ON -DUSE_NGHTTP2=OFF -DBUILD_EXAMPLES=OFF -DP2POOL_BORINGSSL=ON -DCURL_DISABLE_SRP=ON -DOPENSSL_INCLUDE_DIR=../grpc/third_party/boringssl-with-bazel/src/include
make -j$(nproc)
cd lib && mkdir .libs && cp libcurl.a .libs
@@ -284,7 +284,7 @@ jobs:
cd external/src/libuv
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../../../cmake/aarch64_toolchain.cmake -DCMAKE_C_FLAGS='-Os -flto=auto ${{ matrix.config.flags }}' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS='-Os -flto=auto ${{ matrix.config.flags }}' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
make -j$(nproc)
- name: Build libzmq
@@ -292,36 +292,36 @@ jobs:
cd external/src/libzmq
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../../../cmake/aarch64_toolchain.cmake -DCMAKE_C_FLAGS='-Os -flto=auto ${{ matrix.config.flags }}' -DCMAKE_CXX_FLAGS='-Os -flto=auto ${{ matrix.config.flags }}' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF -DCMAKE_POLICY_VERSION_MINIMUM="3.5"
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS='-Os -flto=auto ${{ matrix.config.flags }}' -DCMAKE_CXX_FLAGS='-Os -flto=auto ${{ matrix.config.flags }}' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF -DCMAKE_POLICY_VERSION_MINIMUM="3.5"
make -j$(nproc)
- name: Build p2pool
run: |
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../cmake/aarch64_toolchain.cmake -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON -DARCH_ID=aarch64 -DCMAKE_POLICY_VERSION_MINIMUM="3.5"
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON -DARCH_ID=aarch64 -DCMAKE_POLICY_VERSION_MINIMUM="3.5"
make -j$(nproc) p2pool
- name: Run RandomX tests
run: |
cd build
qemu-aarch64 -L /usr/aarch64-linux-gnu p2pool --test
./p2pool --test
make -j$(nproc) randomx-tests
qemu-aarch64 -L /usr/aarch64-linux-gnu external/src/RandomX/randomx-tests
external/src/RandomX/randomx-tests
- name: Build tests
run: |
cd tests
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_STRIP=/usr/bin/aarch64-linux-gnu-strip -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON -DARCH_ID=aarch64 -DCMAKE_POLICY_VERSION_MINIMUM="3.5"
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON -DARCH_ID=aarch64 -DCMAKE_POLICY_VERSION_MINIMUM="3.5"
make -j$(nproc) p2pool_tests
- name: Run tests
run: |
cd tests/build
gunzip *.gz
qemu-aarch64 -L /usr/aarch64-linux-gnu ./p2pool_tests
./p2pool_tests
- name: Archive binary
uses: actions/upload-artifact@v4
+91
View File
@@ -0,0 +1,91 @@
name: Code coverage
on:
push:
branches: ["master"]
paths-ignore:
- 'docker-compose/**'
- 'docs/**'
- 'README.md'
pull_request:
jobs:
coverage:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y cmake libuv1-dev libzmq3-dev libgss-dev libcurl4-openssl-dev libidn2-0-dev lcov
- name: Install clang
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 20 all
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build tests
run: |
cd tests
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DDEV_DEBUG=ON -DWITH_COVERAGE=ON -DCMAKE_C_COMPILER=clang-20 -DCMAKE_CXX_COMPILER=clang++-20 -DCMAKE_POLICY_VERSION_MINIMUM="3.5"
make -j$(nproc) p2pool_tests
- name: Run tests
run: |
cd tests/build
gunzip *.gz
LLVM_PROFILE_FILE="p2pool_tests.profraw" ./p2pool_tests
- name: Merge profile data
run: |
cd tests/build
llvm-profdata-20 merge -sparse ./p2pool_tests.profraw -o ./p2pool_tests.profdata
- name: Export profile data
run: |
cd tests/build
llvm-cov-20 export ./p2pool_tests -format=lcov -instr-profile=./p2pool_tests.profdata > coverage.info
- name: Run genhtml
run: |
cd tests/build
genhtml --demangle-cpp -o coverage coverage.info
- name: Checkout GitHub Pages repository
uses: actions/checkout@v4
with:
repository: SChernykh/SChernykh.github.io
token: ${{ secrets.PAGES_DEPLOY_TOKEN }}
path: gh-pages
- name: Copy coverage report to GitHub Pages repo
run: |
rm -rf gh-pages/p2pool-coverage
cp -r tests/build/coverage gh-pages/p2pool-coverage
- name: Commit and push coverage report
run: |
cd gh-pages
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add p2pool-coverage
git commit -m "Update p2pool coverage report"
git push
- name: Archive coverage data
if: '!cancelled()'
uses: actions/upload-artifact@v4
with:
name: p2pool-coverage
path: tests/build/coverage
+4 -4
View File
@@ -28,8 +28,8 @@ jobs:
- name: Checkout cppcheck
run: |
git clone https://github.com/danmar/cppcheck cppcheck-main
cd cppcheck-main
git checkout 6d7dc76052ad36128fae93f994d6a2bf57e93103
git clone https://github.com/danmar/simplecpp simplecpp
cp -rf simplecpp cppcheck-main/externals
- name: Build cppcheck
run: |
@@ -76,8 +76,8 @@ jobs:
- name: Checkout cppcheck
run: |
git clone https://github.com/danmar/cppcheck cppcheck-main
cd cppcheck-main
git checkout 6d7dc76052ad36128fae93f994d6a2bf57e93103
git clone https://github.com/danmar/simplecpp simplecpp
Copy-Item -Path "simplecpp" -Destination "cppcheck-main/externals" -Recurse -Force
- name: Build cppcheck
run: |
-8
View File
@@ -1,8 +0,0 @@
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_CROSSCOMPILING TRUE)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++)
set(CMAKE_STRIP /usr/bin/aarch64-linux-gnu-strip)
+1 -1
View File
@@ -741,7 +741,7 @@ void BlockTemplate::fill_optimal_knapsack(const MinerData& data, uint64_t base_r
constexpr uint64_t FEE_COEFF = 1000;
const uint64_t n = m_mempoolTxs.size();
const uint64_t max_weight = data.median_weight + (data.median_weight / 32) - miner_tx_weight;
const uint64_t max_weight = data.median_weight + (data.median_weight / 8) - miner_tx_weight;
m_knapsack.resize((n + 1) * max_weight);
memset(m_knapsack.data(), 0, max_weight * sizeof(uint32_t));
+6
View File
@@ -50,6 +50,12 @@ public:
}
}
void clear()
{
WriteLock lock(m_lock);
m_transactions.clear();
}
private:
mutable uv_rwlock_t m_lock;
unordered_map<hash, TxMempoolData> m_transactions;
+16 -5
View File
@@ -26,6 +26,12 @@ namespace p2pool {
void merkle_hash(const std::vector<hash>& hashes, root_hash& root)
{
const size_t count = hashes.size();
if (count == 0) {
root.clear();
return;
}
const uint8_t* h = hashes[0].h;
if (count == 1) {
@@ -62,10 +68,15 @@ void merkle_hash(const std::vector<hash>& hashes, root_hash& root)
void merkle_hash_full_tree(const std::vector<hash>& hashes, std::vector<std::vector<hash>>& tree)
{
const size_t count = hashes.size();
const uint8_t* h = hashes[0].h;
tree.clear();
if (count == 0) {
return;
}
const uint8_t* h = hashes[0].h;
if (count == 1) {
tree.push_back(hashes);
}
@@ -181,14 +192,14 @@ bool get_merkle_proof(const std::vector<std::vector<hash>>& tree, const hash& h,
root_hash get_root_from_proof(hash h, const std::vector<hash>& proof, size_t index, size_t count)
{
if (count == 1) {
return root_hash(h);
}
if (index >= count) {
return root_hash();
}
if (count == 1) {
return root_hash(h);
}
hash tmp[2];
if (count == 2) {
+26 -21
View File
@@ -806,29 +806,12 @@ void P2PServer::Peer::normalize()
}
}
void P2PServer::broadcast(const PoolBlock& block, const PoolBlock* parent)
P2PServer::Broadcast::Broadcast(const PoolBlock& block, const PoolBlock* parent)
{
// Don't broadcast blocks when shutting down
if (m_finished.load()) {
return;
}
Broadcast* data = this;
MinerData miner_data = m_pool->miner_data();
if (block.m_txinGenHeight + 2 < miner_data.height) {
LOGWARN(3, "Trying to broadcast a stale block " << block.m_sidechainId << " (mainchain height " << block.m_txinGenHeight << ", current height is " << miner_data.height << ')');
return;
}
if (block.m_txinGenHeight > miner_data.height + 2) {
LOGWARN(3, "Trying to broadcast a block " << block.m_sidechainId << " ahead on mainchain (mainchain height " << block.m_txinGenHeight << ", current height is " << miner_data.height << ')');
return;
}
Broadcast* data = new Broadcast{};
data->id = block.m_sidechainId;
data->received_timestamp = block.m_receivedTimestamp;
id = block.m_sidechainId;
received_timestamp = block.m_receivedTimestamp;
int outputs_offset, outputs_blob_size;
const std::vector<uint8_t> mainchain_data = block.serialize_mainchain_data(nullptr, nullptr, &outputs_offset, &outputs_blob_size);
@@ -895,6 +878,28 @@ void P2PServer::broadcast(const PoolBlock& block, const PoolBlock* parent)
data->ancestor_hashes.reserve(block.m_uncles.size() + 1);
data->ancestor_hashes = block.m_uncles;
data->ancestor_hashes.push_back(block.m_parent);
}
void P2PServer::broadcast(const PoolBlock& block, const PoolBlock* parent)
{
// Don't broadcast blocks when shutting down
if (m_finished.load()) {
return;
}
MinerData miner_data = m_pool->miner_data();
if (block.m_txinGenHeight + 2 < miner_data.height) {
LOGWARN(3, "Trying to broadcast a stale block " << block.m_sidechainId << " (mainchain height " << block.m_txinGenHeight << ", current height is " << miner_data.height << ')');
return;
}
if (block.m_txinGenHeight > miner_data.height + 2) {
LOGWARN(3, "Trying to broadcast a block " << block.m_sidechainId << " ahead on mainchain (mainchain height " << block.m_txinGenHeight << ", current height is " << miner_data.height << ')');
return;
}
Broadcast* data = new Broadcast(block, parent);
LOGINFO(5, "Broadcasting block " << block.m_sidechainId << " (height " << block.m_sidechainHeight << "): " << data->compact_blob.size() << '/' << data->pruned_blob.size() << '/' << data->blob.size() << " bytes (compact/pruned/full)");
+13 -11
View File
@@ -168,6 +168,19 @@ public:
};
};
struct Broadcast
{
Broadcast(const PoolBlock& block, const PoolBlock* parent);
hash id;
uint64_t received_timestamp;
std::vector<uint8_t> blob;
std::vector<uint8_t> pruned_blob;
std::vector<uint8_t> compact_blob;
std::vector<hash> ancestor_hashes;
};
void broadcast(const PoolBlock& block, const PoolBlock* parent);
[[nodiscard]] uint64_t get_random64();
[[nodiscard]] uint64_t get_peerId() const { return m_peerId; }
@@ -262,17 +275,6 @@ private:
std::vector<Peer> m_peerListMonero;
std::atomic<uint64_t> m_peerListLastSaved;
struct Broadcast
{
hash id;
uint64_t received_timestamp;
std::vector<uint8_t> blob;
std::vector<uint8_t> pruned_blob;
std::vector<uint8_t> compact_blob;
std::vector<hash> ancestor_hashes;
};
uv_mutex_t m_broadcastLock;
uv_async_t m_broadcastAsync;
std::vector<Broadcast*> m_broadcastQueue;
+1 -1
View File
@@ -390,7 +390,7 @@ void p2pool::handle_tx(TxMempoolData& tx)
void p2pool::handle_miner_data(MinerData& data)
{
#if TEST_MEMPOOL_PICKING_ALGORITHM
if (m_mempool->m_transactions.size() < data.tx_backlog.size()) {
if (m_mempool->size() < data.tx_backlog.size()) {
m_mempool->swap(data.tx_backlog);
}
#else
+1 -1
View File
@@ -389,8 +389,8 @@ bool PoolBlock::get_pow_hash(RandomX_Hasher_Base* hasher, uint64_t height, const
root_hash tmp_root;
merkle_hash(m_transactions, tmp_root);
memcpy(blob + blob_size, tmp_root.h, HASH_SIZE);
blob_size += HASH_SIZE;
}
blob_size += HASH_SIZE;
writeVarint(count, [&blob, &blob_size](uint8_t b) { blob[blob_size++] = b; });
+6
View File
@@ -115,6 +115,12 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, const SideChain& si
uint64_t reward;
READ_VARINT(reward);
// TxOutput max value check
if (reward >= (1ULL << 56)) {
return __LINE__;
}
t.m_reward = reward;
total_reward += reward;
+18 -3
View File
@@ -1444,9 +1444,24 @@ void SideChain::verify_loop(PoolBlock* block)
continue;
}
const std::vector<PoolBlock*>& next_blocks = it->second;
if (!next_blocks.empty()) {
blocks_to_verify.insert(blocks_to_verify.end(), next_blocks.begin(), next_blocks.end());
for (PoolBlock* b : it->second) {
if ((i == 1) && (b->m_parent == block->m_sidechainId)) {
// Update depth if needed
if (b->m_depth + 1 < block->m_depth) {
b->m_depth = block->m_depth - 1;
}
blocks_to_verify.push_back(b);
}
else for (const hash& h : b->m_uncles) {
if (h == block->m_sidechainId) {
// Update depth if needed
if (b->m_depth + i < block->m_depth) {
b->m_depth = block->m_depth - i;
}
blocks_to_verify.push_back(b);
break;
}
}
}
}
}
-1
View File
@@ -29,7 +29,6 @@ class P2PServer;
struct MinerShare
{
FORCEINLINE MinerShare() : m_weight(), m_wallet(nullptr) {}
FORCEINLINE MinerShare(const difficulty_type& w, const Wallet* x) : m_weight(w), m_wallet(x) {}
FORCEINLINE bool operator==(const MinerShare& s) const { return *m_wallet == *s.m_wallet; }
+2
View File
@@ -113,6 +113,7 @@ void StratumServer::on_block(const BlockTemplate& block)
const uint32_t num_connections = m_numConnections;
if (num_connections == 0) {
LOGINFO(4, "no clients connected");
update_hashrate_data(0, seconds_since_epoch());
api_update_local_stats(seconds_since_epoch());
return;
}
@@ -186,6 +187,7 @@ void StratumServer::on_block(const BlockTemplate& block)
}
}
update_hashrate_data(0, seconds_since_epoch());
api_update_local_stats(seconds_since_epoch());
}
+8 -1
View File
@@ -36,7 +36,7 @@ namespace p2pool {
#define P2POOL_VERSION_MAJOR 4
#define P2POOL_VERSION_MINOR 8
#define P2POOL_VERSION_PATCH 0
#define P2POOL_VERSION_PATCH 1
constexpr uint32_t P2POOL_VERSION = (P2POOL_VERSION_MAJOR << 16) | (P2POOL_VERSION_MINOR << 8) | P2POOL_VERSION_PATCH;
@@ -175,6 +175,8 @@ template<> FORCEINLINE bool out_of_range<uint64_t>(uint64_t) { return false; }
template<typename T>
const uint8_t* readVarint(const uint8_t* data, const uint8_t* data_end, T& b)
{
static_assert(std::is_unsigned_v<T>, "readVarint works only with unsigned types");
uint64_t result = 0;
int k = 0;
@@ -184,6 +186,11 @@ const uint8_t* readVarint(const uint8_t* data, const uint8_t* data_end, T& b)
}
const uint64_t cur_byte = *(data++);
if (k && (cur_byte == 0)) {
return nullptr;
}
result |= (cur_byte & 0x7F) << k;
if ((k > 0) && (shiftleft128(cur_byte & 0x7F, 0, k) != 0)) {
+7
View File
@@ -5,6 +5,12 @@ include(cmake/standard.cmake)
option(STATIC_LIBS "Use locally built libuv and libzmq static libs" OFF)
option(WITH_LTO "Use link-time compiler optimization (if linking fails for you, run cmake with -DWITH_LTO=OFF)" ON)
option(WITH_COVERAGE "Generate code coverage data" OFF)
option(DEV_DEBUG "[Developer only] Compile a debug build" OFF)
if (DEV_DEBUG)
add_definitions(-DDEV_DEBUG)
endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
@@ -213,3 +219,4 @@ add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMA
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/src/block.dat" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/src/sidechain_dump.dat.gz" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/src/sidechain_dump_mini.dat.gz" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/src/sidechain_dump_nano.dat.gz" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
+22 -6
View File
@@ -1,10 +1,17 @@
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
set(GENERAL_FLAGS "-pthread")
set(WARNING_FLAGS "-Wall -Wextra")
set(OPTIMIZATION_FLAGS "-O3 -ffast-math -s")
if (WITH_LTO)
set(OPTIMIZATION_FLAGS "${OPTIMIZATION_FLAGS} -flto=auto -fuse-linker-plugin")
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(OPTIMIZATION_FLAGS "-O0 -g3")
if (WITH_COVERAGE)
set(OPTIMIZATION_FLAGS "${OPTIMIZATION_FLAGS} --coverage")
endif()
else()
set(OPTIMIZATION_FLAGS "-O3 -ffast-math -s")
if (WITH_LTO)
set(OPTIMIZATION_FLAGS "${OPTIMIZATION_FLAGS} -flto=auto -fuse-linker-plugin")
endif()
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GENERAL_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
@@ -45,10 +52,19 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
endif()
set(WARNING_FLAGS "-Wall -Wextra -Wno-undefined-internal")
set(OPTIMIZATION_FLAGS "-O3 -ffast-math -funroll-loops -fmerge-all-constants")
if (WITH_LTO)
set(OPTIMIZATION_FLAGS "${OPTIMIZATION_FLAGS} -flto")
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(OPTIMIZATION_FLAGS "-O0 -g3")
else()
set(OPTIMIZATION_FLAGS "-O3 -ffast-math -funroll-loops -fmerge-all-constants")
if (WITH_LTO)
set(OPTIMIZATION_FLAGS "${OPTIMIZATION_FLAGS} -flto")
endif()
endif()
if (WITH_COVERAGE)
set(OPTIMIZATION_FLAGS "${OPTIMIZATION_FLAGS} -fprofile-instr-generate -fcoverage-mapping")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GENERAL_FLAGS} ${WARNING_FLAGS} ${OPTIMIZATION_FLAGS}")
+154 -13
View File
@@ -26,6 +26,13 @@
namespace p2pool {
static hash H(const char* s)
{
hash result;
from_hex(s, strlen(s), result);
return result;
};
TEST(block_template, update)
{
init_crypto_cache();
@@ -34,15 +41,6 @@ TEST(block_template, update)
BlockTemplate tpl(&sidechain, nullptr);
tpl.rng().seed(123);
auto H = [](const char* s)
{
std::stringstream ss;
ss << s;
hash result;
ss >> result;
return result;
};
MinerData data;
data.major_version = 16;
data.height = 2762973;
@@ -58,6 +56,7 @@ TEST(block_template, update)
// Test 1: empty template
tpl.update(data, mempool, &wallet);
ASSERT_EQ(tpl.get_reward(), 600000000000ULL);
const PoolBlock* b = tpl.pool_block_template();
ASSERT_EQ(b->m_sidechainId, H("2c90c1926a75c81afd49bf4a4b63e9de7b4c153866411c47e7af864b547c23ec"));
@@ -68,7 +67,7 @@ TEST(block_template, update)
hash seed_hash;
size_t nonce_offset;
uint32_t template_id;
tpl.get_hashing_blobs(0, 10000, blobs, height, diff, aux_diff, sidechain_diff, seed_hash, nonce_offset, template_id);
tpl.get_hashing_blobs(0, 1000, blobs, height, diff, aux_diff, sidechain_diff, seed_hash, nonce_offset, template_id);
ASSERT_EQ(height, 2762973);
ASSERT_EQ(diff, 300346053753ULL);
@@ -79,7 +78,7 @@ TEST(block_template, update)
hash blobs_hash;
keccak(blobs.data(), static_cast<int>(blobs.size()), blobs_hash.h);
ASSERT_EQ(blobs_hash, H("c043b754d043b4f6fe3f70273a937c77ff75a5afba9a6ca92776e79da28a1165"));
ASSERT_EQ(blobs_hash, H("da11e1ee86779a559df63a55e0b238ce5a67b977e0f68a0b347a39d37096a4bc"));
// Test 2: mempool with high fee and low fee transactions, it must choose high fee transactions
for (uint64_t i = 0; i < 512; ++i) {
@@ -89,8 +88,10 @@ TEST(block_template, update)
tx.weight = 1500;
mempool.add(tx);
}
ASSERT_EQ(mempool.size(), 512);
tpl.update(data, mempool, &wallet);
ASSERT_EQ(tpl.get_reward(), 612054770773ULL);
ASSERT_EQ(b->m_sidechainId, H("c9df4853003ab436416b9fc9a5a072d16b4dede849e697a8be2ebb9c88c8ec72"));
ASSERT_EQ(b->m_transactions.size(), 203);
@@ -99,7 +100,7 @@ TEST(block_template, update)
ASSERT_GE(*reinterpret_cast<const uint64_t*>(b->m_transactions[i].h), 256);
}
tpl.get_hashing_blobs(0, 10000, blobs, height, diff, aux_diff, sidechain_diff, seed_hash, nonce_offset, template_id);
tpl.get_hashing_blobs(0, 1000, blobs, height, diff, aux_diff, sidechain_diff, seed_hash, nonce_offset, template_id);
ASSERT_EQ(height, 2762973);
ASSERT_EQ(diff, 300346053753ULL);
@@ -109,7 +110,147 @@ TEST(block_template, update)
ASSERT_EQ(template_id, 2U);
keccak(blobs.data(), static_cast<int>(blobs.size()), blobs_hash.h);
ASSERT_EQ(blobs_hash, H("f00e196216d160a4fcbf468f748205039d276d62edfa6c6fd4c81dbd1f62d9b7"));
ASSERT_EQ(blobs_hash, H("20aa6a98ca92bc4564bcdc367c078425d4b44b156c2bc7bb703ef055e4fd2c1b"));
// Test 3: small but not empty mempool, and aux chains
std::vector<TxMempoolData> transactions;
for (uint64_t i = 0; i < 10; ++i) {
TxMempoolData tx;
*reinterpret_cast<uint64_t*>(tx.id.h) = i;
tx.fee = 30000000;
tx.weight = 1500;
transactions.push_back(tx);
}
mempool.swap(transactions);
ASSERT_EQ(mempool.size(), 10);
data.aux_chains.emplace_back(H("01f0cf665bd4cd31cbb2b2470236389c483522b350335e10a4a5dca34cb85990"), H("d9de1cfba7cdbd47f12f77addcb39b24c1ae7a16c35372bf28d6aee5d7579ee6"), difficulty_type(1000000));
tpl.update(data, mempool, &wallet);
ASSERT_EQ(tpl.get_reward(), 600300000000ULL);
ASSERT_EQ(b->m_sidechainId, H("c32abac2cad40e263a94f5f43f90e0a7d7d4b151305b79951dbc8c88c3180613"));
ASSERT_EQ(b->m_transactions.size(), 11);
tpl.get_hashing_blobs(0, 1000, blobs, height, diff, aux_diff, sidechain_diff, seed_hash, nonce_offset, template_id);
ASSERT_EQ(height, 2762973);
ASSERT_EQ(diff, 300346053753ULL);
ASSERT_EQ(sidechain_diff, sidechain.difficulty());
ASSERT_EQ(seed_hash, data.seed_hash);
ASSERT_EQ(nonce_offset, 39U);
ASSERT_EQ(template_id, 3U);
keccak(blobs.data(), static_cast<int>(blobs.size()), blobs_hash.h);
ASSERT_EQ(blobs_hash, H("536c0ee8013718b174b63613939379939cee2267e803f77cdabb05fcb47e846f"));
// Test 4: mempool with a lot of transactions with various fees, all parts of transaction picking algorithm should be tested
mempool.clear();
std::mt19937_64 rng;
for (uint64_t i = 0; i < 10000; ++i) {
TxMempoolData tx;
*reinterpret_cast<uint64_t*>(tx.id.h) = i;
tx.weight = 1500 + (rng() % 10007);
tx.fee = 30000000 + (rng() % 100000007);
mempool.add(tx);
}
ASSERT_EQ(mempool.size(), 10000);
tpl.update(data, mempool, &wallet);
ASSERT_EQ(tpl.get_reward(), 619742028747ULL);
ASSERT_EQ(b->m_sidechainId, H("69e7dd43dd99ac6be3f57ca333cc0d814189e83aee1773c99a341aca085c0d46"));
ASSERT_EQ(b->m_transactions.size(), 174);
tpl.get_hashing_blobs(0, 1000, blobs, height, diff, aux_diff, sidechain_diff, seed_hash, nonce_offset, template_id);
ASSERT_EQ(height, 2762973);
ASSERT_EQ(diff, 300346053753ULL);
ASSERT_EQ(sidechain_diff, sidechain.difficulty());
ASSERT_EQ(seed_hash, data.seed_hash);
ASSERT_EQ(nonce_offset, 39U);
ASSERT_EQ(template_id, 4U);
keccak(blobs.data(), static_cast<int>(blobs.size()), blobs_hash.h);
ASSERT_EQ(blobs_hash, H("4f62562aa84400eb085f58447d8daa45257369f1ec046b2150212329c9e86ae4"));
destroy_crypto_cache();
}
TEST(block_template, submit_sidechain_block)
{
init_crypto_cache();
SideChain sidechain(nullptr, NetworkType::Mainnet, "unit_test");
ASSERT_EQ(sidechain.consensus_hash(), H("81d45b62c10afa4fdda7cebb02dd5ad82c43b577eb3fb0857824427c55fd8a8d"));
BlockTemplate tpl(&sidechain, nullptr);
tpl.rng().seed(123);
BlockTemplate tpl2(&sidechain, nullptr);
tpl2.rng().seed(456);
BlockTemplate tpl3(&sidechain, nullptr);
tpl3.rng().seed(789);
MinerData data;
data.major_version = 16;
data.height = 2762973;
data.prev_id = H("81a0260b29d5224e88d04b11faff321fbdc11c4570779386b2a1817a86dc622c");
data.seed_hash = H("33d0fb381466f04d6a1919ced3b698f54a28add3da5a6479b096c67df7a4974c");
data.difficulty = { 300346053753ULL, 0 };
data.median_weight = 300000;
data.already_generated_coins = 18204981557254756780ULL;
data.median_timestamp = (1ULL << 35) - (sidechain.chain_window_size() * 2 + 10) * sidechain.block_time() - 3600;
Mempool mempool;
Wallet wallet("44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg");
std::mt19937_64 rng(101112);
for (uint64_t i = 0, i2 = 0, i3 = 0; i < sidechain.chain_window_size() * 3; ++i) {
tpl.update(data, mempool, &wallet);
if ((rng() % 31) == 0) {
tpl2.update(data, mempool, &wallet);
if ((rng() % 11) == 0) {
tpl3.update(data, mempool, &wallet);
++i3;
ASSERT_TRUE(tpl3.submit_sidechain_block(i3, 0, 0));
}
++i2;
ASSERT_TRUE(tpl2.submit_sidechain_block(i2, 0, 0));
}
ASSERT_TRUE(tpl.submit_sidechain_block(i + 1, 0, 0));
data.median_timestamp += sidechain.block_time();
}
ASSERT_EQ(sidechain.difficulty(), 219467);
ASSERT_EQ(sidechain.blocksById().size(), 4487);
ASSERT_TRUE(sidechain.precalcFinished());
const PoolBlock* tip = sidechain.chainTip();
ASSERT_TRUE(tip != nullptr);
ASSERT_TRUE(tip->m_verified);
ASSERT_FALSE(tip->m_invalid);
ASSERT_EQ(tip->m_txinGenHeight, data.height);
ASSERT_EQ(tip->m_sidechainHeight, sidechain.chain_window_size() * 3 - 1);
ASSERT_EQ(tip->m_sidechainId, H("12d57571a28d62d2b6dca3a647500d23ac22864138b22a133f237b459a0862da"));
destroy_crypto_cache();
}
+20 -2
View File
@@ -27,8 +27,22 @@ TEST(crypto, derivation)
{
init_crypto_cache();
// Run the tests twice to check how crypto cache works
for (int i = 0; i < 2; ++i) {
hash pub, sec;
generate_keys(pub, sec);
ASSERT_TRUE(check_keys(pub, sec));
sec.h[HASH_SIZE - 1] = 0xff;
ASSERT_FALSE(check_keys(pub, sec));
// Run the tests several times to check how crypto cache works
for (int i = 0; i < 4; ++i) {
if (i == 2) {
clear_crypto_cache(seconds_since_epoch() - 1);
}
else if (i == 3) {
clear_crypto_cache(seconds_since_epoch() + 1);
}
std::ifstream f("crypto_tests.txt");
ASSERT_EQ(f.good() && f.is_open(), true);
do {
@@ -44,6 +58,9 @@ TEST(crypto, derivation)
}
uint8_t view_tag;
ASSERT_EQ(p2pool::generate_key_derivation(key1, key2, 0, derivation, view_tag), result);
ASSERT_EQ(p2pool::generate_key_derivation(key1, key2, 1, derivation, view_tag), result);
ASSERT_EQ(p2pool::generate_key_derivation(key1, key2, 2, derivation, view_tag), result);
ASSERT_EQ(p2pool::generate_key_derivation(key1, key2, 3, derivation, view_tag), result);
if (result) {
ASSERT_EQ(derivation, expected_derivation);
}
@@ -89,6 +106,7 @@ TEST(crypto, derivation)
} while (!f.eof());
}
clear_crypto_cache(0);
destroy_crypto_cache();
}
+18 -3
View File
@@ -416,12 +416,18 @@ TEST(difficulty_type, div128)
TEST(difficulty_type, compare)
{
const difficulty_type diff[4] = { { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } };
const difficulty_type diff[9] = {
{ 0, 0 }, { 1, 0 }, { 2, 0 },
{ 0, 1 }, { 1, 1 }, { 2, 1 },
{ 0, 2 }, { 1, 2 }, { 2, 2 },
};
for (int i = 0; i <= 3; ++i) {
for (int j = 0; j <= 3; ++j) {
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
ASSERT_EQ(diff[i] > diff[j], i > j);
ASSERT_EQ(diff[i] < diff[j], i < j);
ASSERT_EQ(diff[i] >= diff[j], i >= j);
ASSERT_EQ(diff[i] <= diff[j], i <= j);
ASSERT_EQ(diff[i] == diff[j], i == j);
ASSERT_EQ(diff[i] != diff[j], i != j);
}
@@ -451,6 +457,15 @@ TEST(difficulty_type, input_output)
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");
std::stringstream ss;
difficulty_type diff;
ss << "340599339356 test";
ss >> diff;
ASSERT_EQ(diff.lo, 340599339356ull);
ASSERT_EQ(diff.hi, 0ull);
}
TEST(difficulty_type, json_parser)
+17
View File
@@ -70,9 +70,19 @@ TEST(hash, input_output)
std::stringstream ss;
ss << h;
ASSERT_EQ(ss.str(), s);
hash h2;
ss >> h2;
ASSERT_EQ(h2, h);
hash h3;
ASSERT_TRUE(from_hex(s, strlen(s), h3));
ASSERT_EQ(h3, h);
std::vector<uint8_t> v;
ASSERT_TRUE(from_hex(s, strlen(s), v));
ASSERT_EQ(v.size(), HASH_SIZE);
ASSERT_EQ(memcmp(v.data(), h.h, HASH_SIZE), 0);
};
hash h;
@@ -90,6 +100,13 @@ TEST(hash, input_output)
h.h[i] = 0xff - i;
}
check(h, "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0");
ASSERT_FALSE(from_hex("123", 3, h));
ASSERT_FALSE(from_hex("000000000000000000000000000000000000000000000000000000000000000z", HASH_SIZE * 2, h));
std::vector<uint8_t> v;
ASSERT_FALSE(from_hex("123", 3, v));
ASSERT_FALSE(from_hex("000000000000000000000000000000000000000000000000000000000000000z", HASH_SIZE * 2, v));
}
TEST(hash, json_parser)
+1
View File
@@ -28,6 +28,7 @@ using namespace p2pool;
int main(int argc, char** argv)
{
set_main_thread();
p2pool_usage();
PoolBlock::s_precalculatedSharesLock = new ReadWriteLock();
+35
View File
@@ -93,6 +93,15 @@ TEST(merkle, tree)
auto check_full_tree = [&hashes, &root]() {
std::vector<std::vector<hash>> tree;
{
hash h;
std::vector<hash> proof;
uint32_t path;
ASSERT_FALSE(get_merkle_proof(tree, h, proof, path));
}
merkle_hash_full_tree(hashes, tree);
ASSERT_GE(tree.size(), 1);
@@ -127,12 +136,15 @@ TEST(merkle, tree)
}
}
const hash empty_hash;
for (size_t i = 0, n = hashes.size(); i < n; ++i) {
const hash& h = hashes[i];
std::vector<hash> proof;
uint32_t path;
ASSERT_TRUE(get_merkle_proof(tree, h, proof, path));
ASSERT_FALSE(get_merkle_proof(tree, empty_hash, proof, path));
uint32_t path_monero;
ASSERT_TRUE(tree_path(n, i, &path_monero));
@@ -140,10 +152,33 @@ TEST(merkle, tree)
ASSERT_TRUE(verify_merkle_proof(h, proof, i, n, root));
ASSERT_TRUE(verify_merkle_proof(h, proof, path, root));
ASSERT_FALSE(verify_merkle_proof(h, proof, n, n, root));
ASSERT_FALSE(verify_merkle_proof(empty_hash, proof, i, n, root));
ASSERT_FALSE(verify_merkle_proof(empty_hash, proof, path, root));
while (!proof.empty()) {
proof.pop_back();
ASSERT_FALSE(verify_merkle_proof(h, proof, i, n, root));
ASSERT_FALSE(verify_merkle_proof(h, proof, path, root));
}
ASSERT_EQ(get_position_from_path(n, path), i);
}
};
// 0 leaves
uint32_t path_monero;
ASSERT_FALSE(tree_path(0, 0, &path_monero));
merkle_hash(std::vector<hash>(), root);
ASSERT_TRUE(root.empty());
std::vector<std::vector<hash>> tree;
merkle_hash_full_tree(std::vector<hash>(), tree);
ASSERT_TRUE(tree.empty());
// 1 leaf
merkle_hash(hashes, root);
ASSERT_EQ(root, input[0]);
+80 -5
View File
@@ -20,6 +20,7 @@
#include "pool_block.h"
#include "pow_hash.h"
#include "side_chain.h"
#include "p2p_server.h"
#include "gtest/gtest.h"
#include <fstream>
@@ -53,9 +54,23 @@ TEST(pool_block, deserialize)
ASSERT_EQ(b.deserialize(buf.data(), buf.size(), sidechain, nullptr, false), 0);
{
const PoolBlock::full_id id = b.get_full_id();
ASSERT_EQ(memcmp(id.data(), b.m_sidechainId.h, HASH_SIZE), 0);
ASSERT_EQ(memcmp(id.data() + HASH_SIZE, &b.m_nonce, NONCE_SIZE), 0);
ASSERT_EQ(memcmp(id.data() + HASH_SIZE + NONCE_SIZE, &b.m_extraNonce, EXTRA_NONCE_SIZE), 0);
}
ASSERT_EQ(b.get_payout(Wallet("4B4aCvEcZr6GcusVJfEds2LXixCeJ2dQBaDUCguWmzi5L7PW5tVXfAnE4cn1mQdiNzH6zWcEPMQTiYTsNcX44ryxCJWZKZH")), 17411468548U);
ASSERT_EQ(b.get_payout(Wallet("43VbH7CQCJqhH1d327TBenCs9hFN3zvcgX5YZdGyJfEE5rabasAtKhyPsKmbYSU9AmMReACZrz9j5U2Ba6WXWoQpVi38AJn")), 1404738424U);
ASSERT_EQ(b.get_payout(Wallet("46r3PD45TYH9jVf8sEejW9JdK1EgNe6BeYLdGyJTU1MRctoevAHXpzSjBMJhdkLirGXwiWdZejSRZ8MZP72artSD17LprKY")), 1419699645U);
ASSERT_EQ(b.get_payout(Wallet("44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg")), 0U);
size_t header_size, miner_tx_size;
int outputs_offset, outputs_blob_size;
const std::vector<uint8_t> mainchain_data = b.serialize_mainchain_data(&header_size, &miner_tx_size, &outputs_offset, &outputs_blob_size);
const std::vector<uint8_t> sidechain_data = b.serialize_sidechain_data();
ASSERT_EQ(mainchain_data.size(), 1829U);
ASSERT_EQ(header_size, 43U);
@@ -103,6 +118,12 @@ TEST(pool_block, deserialize)
ASSERT_EQ(b.m_difficulty.check_pow(pow_hash), true);
// Test self-assignment
b = b;
ASSERT_EQ(b.serialize_mainchain_data(), mainchain_data);
ASSERT_EQ(b.serialize_sidechain_data(), sidechain_data);
destroy_crypto_cache();
}
@@ -116,18 +137,29 @@ TEST(pool_block, verify)
const char* m_fileName;
uint64_t m_txinGenHeight;
uint64_t m_sidechainHeight;
uint32_t m_expectedSharesNextBlock;
bool m_shuffle;
} tests[2] = {
{ "default", "sidechain_dump.dat", 3258121, 9443762, true },
{ "mini", "sidechain_dump_mini.dat", 3258121, 8912067, false },
} tests[6] = {
{ "default", "sidechain_dump.dat", 3258121, 9443762, 30, false },
{ "default", "sidechain_dump.dat", 3258121, 9443762, 30, true },
{ "mini", "sidechain_dump_mini.dat", 3258121, 8912067, 593, false },
{ "mini", "sidechain_dump_mini.dat", 3258121, 8912067, 593, true },
{ "nano", "sidechain_dump_nano.dat", 3438036, 116651, 131, false },
{ "nano", "sidechain_dump_nano.dat", 3438036, 116651, 131, true },
};
for (const STest& t : tests)
{
SideChain sidechain(nullptr, NetworkType::Mainnet, t.m_poolName);
// Difficulty of block 3256320
sidechain.m_testMainChainDiff = difficulty_type(374140388237ULL, 0ULL);
if (strcmp(t.m_poolName, "nano") == 0) {
// Difficulty of block 3436544
sidechain.m_testMainChainDiff = difficulty_type(568969201978ULL, 0ULL);
}
else {
// Difficulty of block 3256320
sidechain.m_testMainChainDiff = difficulty_type(374140388237ULL, 0ULL);
}
std::ifstream f(t.m_fileName, std::ios::binary | std::ios::ate);
ASSERT_EQ(f.good() && f.is_open(), true);
@@ -180,6 +212,49 @@ TEST(pool_block, verify)
ASSERT_EQ(tip->m_txinGenHeight, t.m_txinGenHeight);
ASSERT_EQ(tip->m_sidechainHeight, t.m_sidechainHeight);
PoolBlock block;
block.m_minerWallet.decode("44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg");
std::vector<MinerShare> shares;
sidechain.fill_sidechain_data(block, shares);
ASSERT_EQ(block.m_sidechainHeight, t.m_sidechainHeight + 1);
ASSERT_EQ(shares.size(), t.m_expectedSharesNextBlock);
const PoolBlock* parent = sidechain.find_block(tip->m_parent);
ASSERT_TRUE(parent != nullptr);
// Check pruned and compact broadcast blobs
auto tip_full_blob = tip->serialize_mainchain_data();
auto v2 = tip->serialize_sidechain_data();
tip_full_blob.insert(tip_full_blob.end(), v2.begin(), v2.end());
P2PServer::Broadcast broadcast(*tip, parent);
{
PoolBlock block2;
ASSERT_EQ(block2.deserialize(broadcast.pruned_blob.data(), broadcast.pruned_blob.size(), sidechain, nullptr, false), 0);
auto v1 = block2.serialize_mainchain_data();
v2 = block2.serialize_sidechain_data();
v1.insert(v1.end(), v2.begin(), v2.end());
ASSERT_EQ(v1, tip_full_blob);
}
if (!broadcast.compact_blob.empty()) {
PoolBlock block3;
ASSERT_EQ(block3.deserialize(broadcast.compact_blob.data(), broadcast.compact_blob.size(), sidechain, nullptr, true), 0);
auto v1 = block3.serialize_mainchain_data();
v2 = block3.serialize_sidechain_data();
v1.insert(v1.end(), v2.begin(), v2.end());
ASSERT_EQ(v1, tip_full_blob);
}
}
destroy_crypto_cache();
Binary file not shown.
+18
View File
@@ -80,6 +80,24 @@ TEST(util, varint)
// Invalid value 2
uint8_t buf2[1] = { 0x80 };
ASSERT_EQ(readVarint(buf2, buf2 + 1, check), nullptr);
// Invalid value 3
uint8_t buf3[16];
memset(buf3, 128, sizeof(buf3));
ASSERT_EQ(readVarint(buf3, buf3 + sizeof(buf3), check), nullptr);
// Invalid value 4
uint32_t check2;
uint8_t buf4[] = {255, 255, 255, 255, 127};
ASSERT_EQ(readVarint(buf4, buf4 + sizeof(buf4), check2), nullptr);
// Invalid value 5
uint8_t buf5[] = {128, 0};
ASSERT_EQ(readVarint(buf5, buf5 + sizeof(buf5), check), nullptr);
// Invalid value 6 (2^64)
uint8_t buf6[] = {128, 128, 128, 128, 128, 128, 128, 128, 128, 2};
ASSERT_EQ(readVarint(buf6, buf6 + sizeof(buf6), check), nullptr);
}
TEST(util, bsr)
+9
View File
@@ -77,6 +77,15 @@ TEST(wallet, input_output)
s << w.view_public_key();
ASSERT_EQ(memcmp(buf, viewkey, HASH_SIZE * 2), 0);
// Test Wallet copy
Wallet w1(w);
ASSERT_EQ(w1.prefix(), w.prefix());
ASSERT_EQ(w1.spend_public_key(), w.spend_public_key());
ASSERT_EQ(w1.view_public_key(), w.view_public_key());
ASSERT_EQ(w1.checksum(), w.checksum());
ASSERT_EQ(w1.type(), w.type());
// Test Wallet::assign()
Wallet w2(nullptr);
w2.assign(w.spend_public_key(), w.view_public_key(), w.type());