mirror of
https://github.com/SChernykh/p2pool.git
synced 2024-12-22 19:39:22 +00:00
Added path
bitmap to get_merkle_proof
This commit is contained in:
parent
e986e5dc2e
commit
f67009f133
13 changed files with 53 additions and 16 deletions
|
@ -1303,14 +1303,14 @@ std::vector<AuxChainData> BlockTemplate::get_aux_chains(const uint32_t template_
|
||||||
return m_poolBlockTemplate->m_auxChains;
|
return m_poolBlockTemplate->m_auxChains;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlockTemplate::get_aux_proof(const uint32_t template_id, uint32_t extra_nonce, const hash& h, std::vector<hash>& proof) const
|
bool BlockTemplate::get_aux_proof(const uint32_t template_id, uint32_t extra_nonce, const hash& h, std::vector<hash>& proof, uint32_t& path) const
|
||||||
{
|
{
|
||||||
ReadLock lock(m_lock);
|
ReadLock lock(m_lock);
|
||||||
|
|
||||||
if (template_id != m_templateId) {
|
if (template_id != m_templateId) {
|
||||||
const BlockTemplate* old = m_oldTemplates[template_id % array_size(&BlockTemplate::m_oldTemplates)];
|
const BlockTemplate* old = m_oldTemplates[template_id % array_size(&BlockTemplate::m_oldTemplates)];
|
||||||
if (old && (template_id == old->m_templateId)) {
|
if (old && (template_id == old->m_templateId)) {
|
||||||
return old->get_aux_proof(template_id, extra_nonce, h, proof);
|
return old->get_aux_proof(template_id, extra_nonce, h, proof, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -1346,7 +1346,7 @@ bool BlockTemplate::get_aux_proof(const uint32_t template_id, uint32_t extra_non
|
||||||
std::vector<std::vector<hash>> tree;
|
std::vector<std::vector<hash>> tree;
|
||||||
merkle_hash_full_tree(hashes, tree);
|
merkle_hash_full_tree(hashes, tree);
|
||||||
|
|
||||||
return get_merkle_proof(tree, h, proof);
|
return get_merkle_proof(tree, h, proof, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> BlockTemplate::get_block_template_blob(uint32_t template_id, uint32_t sidechain_extra_nonce, size_t& nonce_offset, size_t& extra_nonce_offset, size_t& merkle_root_offset, hash& merge_mining_root, const BlockTemplate** pThis) const
|
std::vector<uint8_t> BlockTemplate::get_block_template_blob(uint32_t template_id, uint32_t sidechain_extra_nonce, size_t& nonce_offset, size_t& extra_nonce_offset, size_t& merkle_root_offset, hash& merge_mining_root, const BlockTemplate** pThis) const
|
||||||
|
@ -1489,7 +1489,7 @@ void BlockTemplate::init_merge_mining_merkle_proof()
|
||||||
std::vector<std::vector<hash>> tree;
|
std::vector<std::vector<hash>> tree;
|
||||||
merkle_hash_full_tree(hashes, tree);
|
merkle_hash_full_tree(hashes, tree);
|
||||||
|
|
||||||
get_merkle_proof(tree, m_poolBlockTemplate->m_sidechainId, m_poolBlockTemplate->m_merkleProof);
|
get_merkle_proof(tree, m_poolBlockTemplate->m_sidechainId, m_poolBlockTemplate->m_merkleProof, m_poolBlockTemplate->m_merkleProofPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace p2pool
|
} // namespace p2pool
|
||||||
|
|
|
@ -49,7 +49,7 @@ public:
|
||||||
uint32_t get_hashing_blobs(uint32_t extra_nonce_start, uint32_t count, std::vector<uint8_t>& blobs, uint64_t& height, difficulty_type& difficulty, difficulty_type& aux_diff, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset, uint32_t& template_id) const;
|
uint32_t get_hashing_blobs(uint32_t extra_nonce_start, uint32_t count, std::vector<uint8_t>& blobs, uint64_t& height, difficulty_type& difficulty, difficulty_type& aux_diff, difficulty_type& sidechain_difficulty, hash& seed_hash, size_t& nonce_offset, uint32_t& template_id) const;
|
||||||
|
|
||||||
std::vector<AuxChainData> get_aux_chains(const uint32_t template_id) const;
|
std::vector<AuxChainData> get_aux_chains(const uint32_t template_id) const;
|
||||||
bool get_aux_proof(const uint32_t template_id, uint32_t extra_nonce, const hash& h, std::vector<hash>& proof) const;
|
bool get_aux_proof(const uint32_t template_id, uint32_t extra_nonce, const hash& h, std::vector<hash>& proof, uint32_t& path) const;
|
||||||
|
|
||||||
std::vector<uint8_t> get_block_template_blob(uint32_t template_id, uint32_t sidechain_extra_nonce, size_t& nonce_offset, size_t& extra_nonce_offset, size_t& merkle_root_offset, hash& merge_mining_root, const BlockTemplate** pThis) const;
|
std::vector<uint8_t> get_block_template_blob(uint32_t template_id, uint32_t sidechain_extra_nonce, size_t& nonce_offset, size_t& extra_nonce_offset, size_t& merkle_root_offset, hash& merge_mining_root, const BlockTemplate** pThis) const;
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
virtual ~IMergeMiningClient() {}
|
virtual ~IMergeMiningClient() {}
|
||||||
|
|
||||||
[[nodiscard]] virtual bool get_params(ChainParameters& out_params) const = 0;
|
[[nodiscard]] virtual bool get_params(ChainParameters& out_params) const = 0;
|
||||||
virtual void submit_solution(const BlockTemplate* block_tpl, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof) = 0;
|
virtual void submit_solution(const BlockTemplate* block_tpl, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace p2pool
|
} // namespace p2pool
|
||||||
|
|
|
@ -283,7 +283,7 @@ bool MergeMiningClientJSON_RPC::parse_merge_mining_get_job(const char* data, siz
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MergeMiningClientJSON_RPC::submit_solution(const BlockTemplate* /*block_tpl*/, const uint8_t (&/*hashing_blob*/)[128], size_t /*nonce_offset*/, const hash& /*seed_hash*/, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof)
|
void MergeMiningClientJSON_RPC::submit_solution(const BlockTemplate* /*block_tpl*/, const uint8_t (&/*hashing_blob*/)[128], size_t /*nonce_offset*/, const hash& /*seed_hash*/, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t /*merkle_proof_path*/)
|
||||||
{
|
{
|
||||||
ReadLock lock(m_lock);
|
ReadLock lock(m_lock);
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ public:
|
||||||
~MergeMiningClientJSON_RPC() override;
|
~MergeMiningClientJSON_RPC() override;
|
||||||
|
|
||||||
bool get_params(ChainParameters& out_params) const override;
|
bool get_params(ChainParameters& out_params) const override;
|
||||||
void submit_solution(const BlockTemplate* block_tpl, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof) override;
|
void submit_solution(const BlockTemplate* block_tpl, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void loop(void* data);
|
static void loop(void* data);
|
||||||
|
|
|
@ -125,7 +125,7 @@ bool MergeMiningClientTari::get_params(ChainParameters& out_params) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MergeMiningClientTari::submit_solution(const BlockTemplate* block_tpl, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& /*merkle_proof*/)
|
void MergeMiningClientTari::submit_solution(const BlockTemplate* block_tpl, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& /*merkle_proof*/, uint32_t /*merkle_proof_path*/)
|
||||||
{
|
{
|
||||||
Block block;
|
Block block;
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,7 +31,7 @@ public:
|
||||||
~MergeMiningClientTari() override;
|
~MergeMiningClientTari() override;
|
||||||
|
|
||||||
bool get_params(ChainParameters& out_params) const override;
|
bool get_params(ChainParameters& out_params) const override;
|
||||||
void submit_solution(const BlockTemplate* block_tpl, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof) override;
|
void submit_solution(const BlockTemplate* block_tpl, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path) override;
|
||||||
|
|
||||||
static constexpr char TARI_PREFIX[] = "tari://";
|
static constexpr char TARI_PREFIX[] = "tari://";
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@ void merkle_hash_full_tree(const std::vector<hash>& hashes, std::vector<std::vec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get_merkle_proof(const std::vector<std::vector<hash>>& tree, const hash& h, std::vector<hash>& proof)
|
bool get_merkle_proof(const std::vector<std::vector<hash>>& tree, const hash& h, std::vector<hash>& proof, uint32_t& path)
|
||||||
{
|
{
|
||||||
if (tree.empty()) {
|
if (tree.empty()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -137,12 +137,14 @@ bool get_merkle_proof(const std::vector<std::vector<hash>>& tree, const hash& h,
|
||||||
}
|
}
|
||||||
|
|
||||||
proof.clear();
|
proof.clear();
|
||||||
|
path = 0;
|
||||||
|
|
||||||
if (count == 1) {
|
if (count == 1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (count == 2) {
|
else if (count == 2) {
|
||||||
proof.emplace_back(hashes[index ^ 1]);
|
proof.emplace_back(hashes[index ^ 1]);
|
||||||
|
path = index & 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
size_t cnt = 1;
|
size_t cnt = 1;
|
||||||
|
@ -158,6 +160,7 @@ bool get_merkle_proof(const std::vector<std::vector<hash>>& tree, const hash& h,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
proof.emplace_back(hashes[j]);
|
proof.emplace_back(hashes[j]);
|
||||||
|
path = index & 1;
|
||||||
index = (index >> 1) + k;
|
index = (index >> 1) + k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,6 +172,7 @@ bool get_merkle_proof(const std::vector<std::vector<hash>>& tree, const hash& h,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
proof.emplace_back(tree[i][j]);
|
proof.emplace_back(tree[i][j]);
|
||||||
|
path = (static_cast<uint64_t>(path) << 1) | (index & 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,6 +264,26 @@ bool verify_merkle_proof(hash h, const std::vector<hash>& proof, size_t index, s
|
||||||
return get_root_from_proof(h, proof, index, count) == root;
|
return get_root_from_proof(h, proof, index, count) == root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool verify_merkle_proof(hash h, const std::vector<hash>& proof, uint32_t path, const root_hash& root)
|
||||||
|
{
|
||||||
|
for (size_t d = 0, depth = proof.size(); d < depth; ++d) {
|
||||||
|
hash tmp[2];
|
||||||
|
|
||||||
|
if ((path >> (depth - d - 1)) & 1) {
|
||||||
|
tmp[0] = proof[d];
|
||||||
|
tmp[1] = h;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tmp[0] = h;
|
||||||
|
tmp[1] = proof[d];
|
||||||
|
}
|
||||||
|
|
||||||
|
keccak(tmp[0].h, HASH_SIZE * 2, h.h);
|
||||||
|
}
|
||||||
|
|
||||||
|
return h == root;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t get_aux_slot(const hash &id, uint32_t nonce, uint32_t n_aux_chains)
|
uint32_t get_aux_slot(const hash &id, uint32_t nonce, uint32_t n_aux_chains)
|
||||||
{
|
{
|
||||||
if (n_aux_chains <= 1) {
|
if (n_aux_chains <= 1) {
|
||||||
|
|
|
@ -22,10 +22,12 @@ namespace p2pool {
|
||||||
void merkle_hash(const std::vector<hash>& hashes, root_hash& root);
|
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);
|
void merkle_hash_full_tree(const std::vector<hash>& hashes, std::vector<std::vector<hash>>& tree);
|
||||||
|
|
||||||
bool get_merkle_proof(const std::vector<std::vector<hash>>& tree, const hash& h, std::vector<hash>& proof);
|
bool get_merkle_proof(const std::vector<std::vector<hash>>& tree, const hash& h, std::vector<hash>& proof, uint32_t& path);
|
||||||
|
|
||||||
root_hash get_root_from_proof(hash h, const std::vector<hash>& proof, size_t index, size_t count);
|
root_hash get_root_from_proof(hash h, const std::vector<hash>& proof, size_t index, size_t count);
|
||||||
|
|
||||||
bool verify_merkle_proof(hash h, const std::vector<hash>& proof, size_t index, size_t count, const root_hash& root);
|
bool verify_merkle_proof(hash h, const std::vector<hash>& proof, size_t index, size_t count, const root_hash& root);
|
||||||
|
bool verify_merkle_proof(hash h, const std::vector<hash>& proof, uint32_t path, const root_hash& root);
|
||||||
|
|
||||||
uint32_t get_aux_slot(const hash &id, uint32_t nonce, uint32_t n_aux_chains);
|
uint32_t get_aux_slot(const hash &id, uint32_t nonce, uint32_t n_aux_chains);
|
||||||
bool find_aux_nonce(const std::vector<hash>& aux_id, uint32_t& nonce, uint32_t max_nonce = 0xFFFF);
|
bool find_aux_nonce(const std::vector<hash>& aux_id, uint32_t& nonce, uint32_t max_nonce = 0xFFFF);
|
||||||
|
|
|
@ -667,19 +667,23 @@ void p2pool::submit_aux_block(const hash& chain_id, uint32_t template_id, uint32
|
||||||
|
|
||||||
if (chain_id == params.aux_id) {
|
if (chain_id == params.aux_id) {
|
||||||
std::vector<hash> proof;
|
std::vector<hash> proof;
|
||||||
|
uint32_t path;
|
||||||
|
|
||||||
if (m_blockTemplate->get_aux_proof(template_id, extra_nonce, params.aux_hash, proof)) {
|
if (m_blockTemplate->get_aux_proof(template_id, extra_nonce, params.aux_hash, proof, path)) {
|
||||||
if (pool_block_debug()) {
|
if (pool_block_debug()) {
|
||||||
const MinerData data = miner_data();
|
const MinerData data = miner_data();
|
||||||
const uint32_t n_aux_chains = static_cast<uint32_t>(data.aux_chains.size() + 1);
|
const uint32_t n_aux_chains = static_cast<uint32_t>(data.aux_chains.size() + 1);
|
||||||
const uint32_t index = get_aux_slot(params.aux_id, data.aux_nonce, n_aux_chains);
|
const uint32_t index = get_aux_slot(params.aux_id, data.aux_nonce, n_aux_chains);
|
||||||
|
|
||||||
if (!verify_merkle_proof(params.aux_hash, proof, index, n_aux_chains, merge_mining_root)) {
|
if (!verify_merkle_proof(params.aux_hash, proof, index, n_aux_chains, merge_mining_root)) {
|
||||||
LOGERR(0, "submit_aux_block: verify_merkle_proof failed for chain_id " << chain_id);
|
LOGERR(0, "submit_aux_block: verify_merkle_proof (1) failed for chain_id " << chain_id);
|
||||||
|
}
|
||||||
|
if (!verify_merkle_proof(params.aux_hash, proof, path, merge_mining_root)) {
|
||||||
|
LOGERR(0, "submit_aux_block: verify_merkle_proof (2) failed for chain_id " << chain_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c->submit_solution(block_tpl, hashing_blob, nonce_offset, seed_hash, blob, proof);
|
c->submit_solution(block_tpl, hashing_blob, nonce_offset, seed_hash, blob, proof, path);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOGWARN(3, "submit_aux_block: failed to get merkle proof for chain_id " << chain_id);
|
LOGWARN(3, "submit_aux_block: failed to get merkle proof for chain_id " << chain_id);
|
||||||
|
|
|
@ -48,6 +48,8 @@ PoolBlock::PoolBlock()
|
||||||
, m_sidechainHeight(0)
|
, m_sidechainHeight(0)
|
||||||
, m_difficulty{}
|
, m_difficulty{}
|
||||||
, m_cumulativeDifficulty{}
|
, m_cumulativeDifficulty{}
|
||||||
|
, m_merkleProof{}
|
||||||
|
, m_merkleProofPath(0)
|
||||||
, m_sidechainExtraBuf{}
|
, m_sidechainExtraBuf{}
|
||||||
, m_sidechainId{}
|
, m_sidechainId{}
|
||||||
, m_depth(0)
|
, m_depth(0)
|
||||||
|
@ -102,6 +104,7 @@ PoolBlock& PoolBlock::operator=(const PoolBlock& b)
|
||||||
m_difficulty = b.m_difficulty;
|
m_difficulty = b.m_difficulty;
|
||||||
m_cumulativeDifficulty = b.m_cumulativeDifficulty;
|
m_cumulativeDifficulty = b.m_cumulativeDifficulty;
|
||||||
m_merkleProof = b.m_merkleProof;
|
m_merkleProof = b.m_merkleProof;
|
||||||
|
m_merkleProofPath = b.m_merkleProofPath;
|
||||||
memcpy(m_sidechainExtraBuf, b.m_sidechainExtraBuf, sizeof(m_sidechainExtraBuf));
|
memcpy(m_sidechainExtraBuf, b.m_sidechainExtraBuf, sizeof(m_sidechainExtraBuf));
|
||||||
m_sidechainId = b.m_sidechainId;
|
m_sidechainId = b.m_sidechainId;
|
||||||
m_depth = b.m_depth;
|
m_depth = b.m_depth;
|
||||||
|
|
|
@ -134,6 +134,7 @@ struct PoolBlock
|
||||||
|
|
||||||
// Merkle proof for merge mining
|
// Merkle proof for merge mining
|
||||||
std::vector<hash> m_merkleProof;
|
std::vector<hash> m_merkleProof;
|
||||||
|
uint32_t m_merkleProofPath;
|
||||||
|
|
||||||
// Arbitrary extra data
|
// Arbitrary extra data
|
||||||
uint32_t m_sidechainExtraBuf[4];
|
uint32_t m_sidechainExtraBuf[4];
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "keccak.h"
|
#include "keccak.h"
|
||||||
#include "merkle.h"
|
#include "merkle.h"
|
||||||
#include "pool_block.h"
|
#include "pool_block.h"
|
||||||
|
#include "keccak.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
namespace p2pool {
|
namespace p2pool {
|
||||||
|
@ -74,9 +75,11 @@ TEST(merkle, tree)
|
||||||
for (size_t i = 0, n = hashes.size(); i < n; ++i) {
|
for (size_t i = 0, n = hashes.size(); i < n; ++i) {
|
||||||
const hash& h = hashes[i];
|
const hash& h = hashes[i];
|
||||||
std::vector<hash> proof;
|
std::vector<hash> proof;
|
||||||
|
uint32_t path;
|
||||||
|
|
||||||
ASSERT_TRUE(get_merkle_proof(tree, h, proof));
|
ASSERT_TRUE(get_merkle_proof(tree, h, proof, path));
|
||||||
ASSERT_TRUE(verify_merkle_proof(h, proof, i, n, root));
|
ASSERT_TRUE(verify_merkle_proof(h, proof, i, n, root));
|
||||||
|
ASSERT_TRUE(verify_merkle_proof(h, proof, path, root));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue