mirror of
https://github.com/SChernykh/p2pool.git
synced 2024-11-16 15:57:39 +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();
|
||||
|
||||
if (sidechain_version > 1) {
|
||||
static_assert(decltype(m_rng)::word_size == 64, "m_rng must be 64-bit");
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
if (sidechain_version <= 1) {
|
||||
m_poolBlockTemplate->m_txkeySecSeed = miner_wallet->spend_public_key();
|
||||
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;
|
||||
|
||||
|
|
|
@ -122,13 +122,13 @@ PoolBlock::~PoolBlock()
|
|||
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);
|
||||
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;
|
||||
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);
|
||||
writeVarint(m_timestamp, data);
|
||||
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();
|
||||
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++) = 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;
|
||||
if (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);
|
||||
|
||||
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& 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);
|
||||
|
||||
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)) {
|
||||
LOGERR(1, "tried to calculate PoW of uninitialized block");
|
||||
|
@ -405,4 +412,28 @@ uint64_t PoolBlock::get_payout(const Wallet& w) const
|
|||
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
|
||||
|
|
|
@ -137,8 +137,8 @@ struct PoolBlock
|
|||
|
||||
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_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(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 uint32_t* nonce, const uint32_t* extra_nonce) 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);
|
||||
|
@ -171,6 +171,8 @@ struct PoolBlock
|
|||
memcpy(p + HASH_SIZE + NONCE_SIZE, &m_extraNonce, EXTRA_NONCE_SIZE);
|
||||
return key;
|
||||
}
|
||||
|
||||
hash calculate_tx_key_seed() const;
|
||||
};
|
||||
|
||||
} // namespace p2pool
|
||||
|
|
|
@ -203,6 +203,7 @@ SideChain::~SideChain()
|
|||
|
||||
void SideChain::fill_sidechain_data(PoolBlock& block, std::vector<MinerShare>& shares) const
|
||||
{
|
||||
const int sidechain_version = block.get_sidechain_version();
|
||||
block.m_uncles.clear();
|
||||
|
||||
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_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);
|
||||
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_sidechainHeight = tip->m_sidechainHeight + 1;
|
||||
|
||||
|
@ -1331,12 +1342,15 @@ void SideChain::verify_loop(PoolBlock* block)
|
|||
|
||||
void SideChain::verify(PoolBlock* block)
|
||||
{
|
||||
const int sidechain_version = block->get_sidechain_version();
|
||||
|
||||
// Genesis block
|
||||
if (block->m_sidechainHeight == 0) {
|
||||
if (!block->m_parent.empty() ||
|
||||
!block->m_uncles.empty() ||
|
||||
(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;
|
||||
}
|
||||
|
@ -1382,12 +1396,24 @@ void SideChain::verify(PoolBlock* block)
|
|||
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;
|
||||
if (block->m_sidechainHeight != expectedHeight) {
|
||||
LOGWARN(3, "block at height = " << block->m_sidechainHeight <<
|
||||
", id = " << block->m_sidechainId <<
|
||||
", mainchain height = " << block->m_txinGenHeight <<
|
||||
" has wrong height: expected " << expectedHeight);
|
||||
block->m_verified = true;
|
||||
block->m_invalid = true;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ TEST(block_template, update)
|
|||
tpl.update(data, mempool, &wallet);
|
||||
|
||||
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;
|
||||
uint64_t height;
|
||||
|
@ -79,7 +79,7 @@ TEST(block_template, update)
|
|||
|
||||
hash blobs_hash;
|
||||
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
|
||||
for (uint64_t i = 0; i < 512; ++i) {
|
||||
|
|
Loading…
Reference in a new issue