mirror of
https://github.com/SChernykh/p2pool.git
synced 2024-11-17 00:07:47 +00:00
Initialize tx key from previous blocks
This commit is contained in:
parent
1bd04c2840
commit
ae6747c82d
5 changed files with 73 additions and 23 deletions
|
@ -268,19 +268,10 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, Wallet
|
||||||
|
|
||||||
const int sidechain_version = m_poolBlockTemplate->get_sidechain_version();
|
const int sidechain_version = m_poolBlockTemplate->get_sidechain_version();
|
||||||
|
|
||||||
if (sidechain_version > 1) {
|
if (sidechain_version <= 1) {
|
||||||
static_assert(decltype(m_rng)::word_size == 64, "m_rng must be 64-bit");
|
m_poolBlockTemplate->m_txkeySecSeed = miner_wallet->spend_public_key();
|
||||||
|
|
||||||
uint64_t* p = reinterpret_cast<uint64_t*>(m_poolBlockTemplate->m_txkeySecSeed.h);
|
|
||||||
for (size_t i = 0; i < HASH_SIZE / sizeof(uint64_t); ++i) {
|
|
||||||
p[i] = m_rng();
|
|
||||||
}
|
|
||||||
|
|
||||||
get_tx_keys(m_poolBlockTemplate->m_txkeyPub, m_poolBlockTemplate->m_txkeySec, m_poolBlockTemplate->m_txkeySecSeed, data.prev_id);
|
get_tx_keys(m_poolBlockTemplate->m_txkeyPub, m_poolBlockTemplate->m_txkeySec, m_poolBlockTemplate->m_txkeySecSeed, data.prev_id);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
get_tx_keys(m_poolBlockTemplate->m_txkeyPub, m_poolBlockTemplate->m_txkeySec, miner_wallet->spend_public_key(), data.prev_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_poolBlockTemplate->m_minerWallet = *miner_wallet;
|
m_poolBlockTemplate->m_minerWallet = *miner_wallet;
|
||||||
|
|
||||||
|
|
|
@ -122,13 +122,13 @@ PoolBlock::~PoolBlock()
|
||||||
uv_mutex_destroy(&m_lock);
|
uv_mutex_destroy(&m_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> PoolBlock::serialize_mainchain_data(size_t* header_size, size_t* miner_tx_size, int* outputs_offset, int* outputs_blob_size) const
|
std::vector<uint8_t> PoolBlock::serialize_mainchain_data(size_t* header_size, size_t* miner_tx_size, int* outputs_offset, int* outputs_blob_size, const uint32_t* nonce, const uint32_t* extra_nonce) const
|
||||||
{
|
{
|
||||||
MutexLock lock(m_lock);
|
MutexLock lock(m_lock);
|
||||||
return serialize_mainchain_data_nolock(header_size, miner_tx_size, outputs_offset, outputs_blob_size);
|
return serialize_mainchain_data_nolock(header_size, miner_tx_size, outputs_offset, outputs_blob_size, nonce, extra_nonce);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> PoolBlock::serialize_mainchain_data_nolock(size_t* header_size, size_t* miner_tx_size, int* outputs_offset, int* outputs_blob_size) const
|
std::vector<uint8_t> PoolBlock::serialize_mainchain_data_nolock(size_t* header_size, size_t* miner_tx_size, int* outputs_offset, int* outputs_blob_size, const uint32_t* nonce, const uint32_t* extra_nonce) const
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
data.reserve(128 + m_outputs.size() * 39 + m_transactions.size() * HASH_SIZE);
|
data.reserve(128 + m_outputs.size() * 39 + m_transactions.size() * HASH_SIZE);
|
||||||
|
@ -138,7 +138,11 @@ std::vector<uint8_t> PoolBlock::serialize_mainchain_data_nolock(size_t* header_s
|
||||||
data.push_back(m_minorVersion);
|
data.push_back(m_minorVersion);
|
||||||
writeVarint(m_timestamp, data);
|
writeVarint(m_timestamp, data);
|
||||||
data.insert(data.end(), m_prevId.h, m_prevId.h + HASH_SIZE);
|
data.insert(data.end(), m_prevId.h, m_prevId.h + HASH_SIZE);
|
||||||
data.insert(data.end(), reinterpret_cast<const uint8_t*>(&m_nonce), reinterpret_cast<const uint8_t*>(&m_nonce) + NONCE_SIZE);
|
|
||||||
|
if (!nonce) {
|
||||||
|
nonce = &m_nonce;
|
||||||
|
}
|
||||||
|
data.insert(data.end(), reinterpret_cast<const uint8_t*>(nonce), reinterpret_cast<const uint8_t*>(nonce) + NONCE_SIZE);
|
||||||
|
|
||||||
const size_t header_size0 = data.size();
|
const size_t header_size0 = data.size();
|
||||||
if (header_size) {
|
if (header_size) {
|
||||||
|
@ -191,7 +195,10 @@ std::vector<uint8_t> PoolBlock::serialize_mainchain_data_nolock(size_t* header_s
|
||||||
*(p++) = TX_EXTRA_NONCE;
|
*(p++) = TX_EXTRA_NONCE;
|
||||||
*(p++) = static_cast<uint8_t>(extra_nonce_size);
|
*(p++) = static_cast<uint8_t>(extra_nonce_size);
|
||||||
|
|
||||||
memcpy(p, &m_extraNonce, EXTRA_NONCE_SIZE);
|
if (!extra_nonce) {
|
||||||
|
extra_nonce = &m_extraNonce;
|
||||||
|
}
|
||||||
|
memcpy(p, extra_nonce, EXTRA_NONCE_SIZE);
|
||||||
p += EXTRA_NONCE_SIZE;
|
p += EXTRA_NONCE_SIZE;
|
||||||
if (extra_nonce_size > EXTRA_NONCE_SIZE) {
|
if (extra_nonce_size > EXTRA_NONCE_SIZE) {
|
||||||
memset(p, 0, extra_nonce_size - EXTRA_NONCE_SIZE);
|
memset(p, 0, extra_nonce_size - EXTRA_NONCE_SIZE);
|
||||||
|
@ -232,7 +239,7 @@ std::vector<uint8_t> PoolBlock::serialize_sidechain_data() const
|
||||||
|
|
||||||
MutexLock lock(m_lock);
|
MutexLock lock(m_lock);
|
||||||
|
|
||||||
data.reserve((m_uncles.size() + 4) * HASH_SIZE + 20);
|
data.reserve((m_uncles.size() + 4) * HASH_SIZE + 36);
|
||||||
|
|
||||||
const hash& spend = m_minerWallet.spend_public_key();
|
const hash& spend = m_minerWallet.spend_public_key();
|
||||||
const hash& view = m_minerWallet.view_public_key();
|
const hash& view = m_minerWallet.view_public_key();
|
||||||
|
@ -317,7 +324,7 @@ bool PoolBlock::get_pow_hash(RandomX_Hasher_Base* hasher, uint64_t height, const
|
||||||
MutexLock lock(m_lock);
|
MutexLock lock(m_lock);
|
||||||
|
|
||||||
size_t header_size, miner_tx_size;
|
size_t header_size, miner_tx_size;
|
||||||
const std::vector<uint8_t> mainchain_data = serialize_mainchain_data_nolock(&header_size, &miner_tx_size, nullptr, nullptr);
|
const std::vector<uint8_t> mainchain_data = serialize_mainchain_data_nolock(&header_size, &miner_tx_size, nullptr, nullptr, nullptr, nullptr);
|
||||||
|
|
||||||
if (!header_size || !miner_tx_size || (mainchain_data.size() < header_size + miner_tx_size)) {
|
if (!header_size || !miner_tx_size || (mainchain_data.size() < header_size + miner_tx_size)) {
|
||||||
LOGERR(1, "tried to calculate PoW of uninitialized block");
|
LOGERR(1, "tried to calculate PoW of uninitialized block");
|
||||||
|
@ -405,4 +412,28 @@ uint64_t PoolBlock::get_payout(const Wallet& w) const
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hash PoolBlock::calculate_tx_key_seed() const
|
||||||
|
{
|
||||||
|
const char domain[] = "tx_key_seed";
|
||||||
|
const uint32_t zero = 0;
|
||||||
|
|
||||||
|
const std::vector<uint8_t> mainchain_data = serialize_mainchain_data(nullptr, nullptr, nullptr, nullptr, &zero, &zero);
|
||||||
|
const std::vector<uint8_t> sidechain_data = serialize_sidechain_data();
|
||||||
|
|
||||||
|
hash result;
|
||||||
|
keccak_custom([&domain, &mainchain_data, &sidechain_data](int offset) -> uint8_t {
|
||||||
|
size_t k = offset;
|
||||||
|
|
||||||
|
if (k < sizeof(domain)) return domain[k];
|
||||||
|
k -= sizeof(domain);
|
||||||
|
|
||||||
|
if (k < mainchain_data.size()) return mainchain_data[k];
|
||||||
|
k -= mainchain_data.size();
|
||||||
|
|
||||||
|
return sidechain_data[k];
|
||||||
|
}, static_cast<int>(sizeof(domain) + mainchain_data.size() + sidechain_data.size()), result.h, HASH_SIZE);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace p2pool
|
} // namespace p2pool
|
||||||
|
|
|
@ -137,8 +137,8 @@ struct PoolBlock
|
||||||
|
|
||||||
uint64_t m_localTimestamp;
|
uint64_t m_localTimestamp;
|
||||||
|
|
||||||
std::vector<uint8_t> serialize_mainchain_data(size_t* header_size = nullptr, size_t* miner_tx_size = nullptr, int* outputs_offset = nullptr, int* outputs_blob_size = nullptr) const;
|
std::vector<uint8_t> serialize_mainchain_data(size_t* header_size = nullptr, size_t* miner_tx_size = nullptr, int* outputs_offset = nullptr, int* outputs_blob_size = nullptr, const uint32_t* nonce = nullptr, const uint32_t* extra_nonce = nullptr) const;
|
||||||
std::vector<uint8_t> serialize_mainchain_data_nolock(size_t* header_size, size_t* miner_tx_size, int* outputs_offset, int* outputs_blob_size) const;
|
std::vector<uint8_t> serialize_mainchain_data_nolock(size_t* header_size, size_t* miner_tx_size, int* outputs_offset, int* outputs_blob_size, const uint32_t* nonce, const uint32_t* extra_nonce) const;
|
||||||
std::vector<uint8_t> serialize_sidechain_data() const;
|
std::vector<uint8_t> serialize_sidechain_data() const;
|
||||||
|
|
||||||
int deserialize(const uint8_t* data, size_t size, const SideChain& sidechain, uv_loop_t* loop, bool compact);
|
int deserialize(const uint8_t* data, size_t size, const SideChain& sidechain, uv_loop_t* loop, bool compact);
|
||||||
|
@ -171,6 +171,8 @@ struct PoolBlock
|
||||||
memcpy(p + HASH_SIZE + NONCE_SIZE, &m_extraNonce, EXTRA_NONCE_SIZE);
|
memcpy(p + HASH_SIZE + NONCE_SIZE, &m_extraNonce, EXTRA_NONCE_SIZE);
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hash calculate_tx_key_seed() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace p2pool
|
} // namespace p2pool
|
||||||
|
|
|
@ -203,6 +203,7 @@ SideChain::~SideChain()
|
||||||
|
|
||||||
void SideChain::fill_sidechain_data(PoolBlock& block, std::vector<MinerShare>& shares) const
|
void SideChain::fill_sidechain_data(PoolBlock& block, std::vector<MinerShare>& shares) const
|
||||||
{
|
{
|
||||||
|
const int sidechain_version = block.get_sidechain_version();
|
||||||
block.m_uncles.clear();
|
block.m_uncles.clear();
|
||||||
|
|
||||||
ReadLock lock(m_sidechainLock);
|
ReadLock lock(m_sidechainLock);
|
||||||
|
@ -215,10 +216,20 @@ void SideChain::fill_sidechain_data(PoolBlock& block, std::vector<MinerShare>& s
|
||||||
block.m_difficulty = m_minDifficulty;
|
block.m_difficulty = m_minDifficulty;
|
||||||
block.m_cumulativeDifficulty = m_minDifficulty;
|
block.m_cumulativeDifficulty = m_minDifficulty;
|
||||||
|
|
||||||
|
if (sidechain_version > 1) {
|
||||||
|
block.m_txkeySecSeed = {};
|
||||||
|
get_tx_keys(block.m_txkeyPub, block.m_txkeySec, block.m_txkeySecSeed, block.m_prevId);
|
||||||
|
}
|
||||||
|
|
||||||
get_shares(&block, shares);
|
get_shares(&block, shares);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sidechain_version > 1) {
|
||||||
|
block.m_txkeySecSeed = (block.m_prevId == tip->m_prevId) ? tip->m_txkeySecSeed : tip->calculate_tx_key_seed();
|
||||||
|
get_tx_keys(block.m_txkeyPub, block.m_txkeySec, block.m_txkeySecSeed, block.m_prevId);
|
||||||
|
}
|
||||||
|
|
||||||
block.m_parent = tip->m_sidechainId;
|
block.m_parent = tip->m_sidechainId;
|
||||||
block.m_sidechainHeight = tip->m_sidechainHeight + 1;
|
block.m_sidechainHeight = tip->m_sidechainHeight + 1;
|
||||||
|
|
||||||
|
@ -1331,12 +1342,15 @@ void SideChain::verify_loop(PoolBlock* block)
|
||||||
|
|
||||||
void SideChain::verify(PoolBlock* block)
|
void SideChain::verify(PoolBlock* block)
|
||||||
{
|
{
|
||||||
|
const int sidechain_version = block->get_sidechain_version();
|
||||||
|
|
||||||
// Genesis block
|
// Genesis block
|
||||||
if (block->m_sidechainHeight == 0) {
|
if (block->m_sidechainHeight == 0) {
|
||||||
if (!block->m_parent.empty() ||
|
if (!block->m_parent.empty() ||
|
||||||
!block->m_uncles.empty() ||
|
!block->m_uncles.empty() ||
|
||||||
(block->m_difficulty != m_minDifficulty) ||
|
(block->m_difficulty != m_minDifficulty) ||
|
||||||
(block->m_cumulativeDifficulty != m_minDifficulty))
|
(block->m_cumulativeDifficulty != m_minDifficulty) ||
|
||||||
|
((sidechain_version > 1) && !block->m_txkeySecSeed.empty()))
|
||||||
{
|
{
|
||||||
block->m_invalid = true;
|
block->m_invalid = true;
|
||||||
}
|
}
|
||||||
|
@ -1382,12 +1396,24 @@ void SideChain::verify(PoolBlock* block)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sidechain_version > 1) {
|
||||||
|
// Check m_txkeySecSeed
|
||||||
|
const hash h = (block->m_prevId == parent->m_prevId) ? parent->m_txkeySecSeed : parent->calculate_tx_key_seed();
|
||||||
|
if (block->m_txkeySecSeed != h) {
|
||||||
|
LOGWARN(3, "block " << block->m_sidechainId << " has invalid tx key seed: expected " << h << ", got " << block->m_txkeySecSeed);
|
||||||
|
block->m_verified = true;
|
||||||
|
block->m_invalid = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const uint64_t expectedHeight = parent->m_sidechainHeight + 1;
|
const uint64_t expectedHeight = parent->m_sidechainHeight + 1;
|
||||||
if (block->m_sidechainHeight != expectedHeight) {
|
if (block->m_sidechainHeight != expectedHeight) {
|
||||||
LOGWARN(3, "block at height = " << block->m_sidechainHeight <<
|
LOGWARN(3, "block at height = " << block->m_sidechainHeight <<
|
||||||
", id = " << block->m_sidechainId <<
|
", id = " << block->m_sidechainId <<
|
||||||
", mainchain height = " << block->m_txinGenHeight <<
|
", mainchain height = " << block->m_txinGenHeight <<
|
||||||
" has wrong height: expected " << expectedHeight);
|
" has wrong height: expected " << expectedHeight);
|
||||||
|
block->m_verified = true;
|
||||||
block->m_invalid = true;
|
block->m_invalid = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ TEST(block_template, update)
|
||||||
tpl.update(data, mempool, &wallet);
|
tpl.update(data, mempool, &wallet);
|
||||||
|
|
||||||
const PoolBlock* b = tpl.pool_block_template();
|
const PoolBlock* b = tpl.pool_block_template();
|
||||||
ASSERT_EQ(b->m_sidechainId, H("e6fa454c10374439dcc9eee3198f6ba17a7a3764510569c3b963b31510b74780"));
|
ASSERT_EQ(b->m_sidechainId, H("3085dc0425d94fb2752e21e5d5a4fbad42105a189f9678cadabb69cf55a321ee"));
|
||||||
|
|
||||||
std::vector<uint8_t> blobs;
|
std::vector<uint8_t> blobs;
|
||||||
uint64_t height;
|
uint64_t height;
|
||||||
|
@ -79,7 +79,7 @@ TEST(block_template, update)
|
||||||
|
|
||||||
hash blobs_hash;
|
hash blobs_hash;
|
||||||
keccak(blobs.data(), static_cast<int>(blobs.size()), blobs_hash.h);
|
keccak(blobs.data(), static_cast<int>(blobs.size()), blobs_hash.h);
|
||||||
ASSERT_EQ(blobs_hash, H("fd0079d39d1739ded6e710192228276cbaa55eaabde7a26c38f8986709a030e4"));
|
ASSERT_EQ(blobs_hash, H("c1211e083d27ddb81eddb125af4f10b6df16efd418cf684f6d0e8e49a5ffaf3f"));
|
||||||
|
|
||||||
// Test 2: mempool with high fee and low fee transactions, it must choose high fee transactions
|
// Test 2: mempool with high fee and low fee transactions, it must choose high fee transactions
|
||||||
for (uint64_t i = 0; i < 512; ++i) {
|
for (uint64_t i = 0; i < 512; ++i) {
|
||||||
|
|
Loading…
Reference in a new issue