diff --git a/src/block_template.cpp b/src/block_template.cpp index ae90db2..d35cdcd 100644 --- a/src/block_template.cpp +++ b/src/block_template.cpp @@ -266,7 +266,22 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, Wallet m_blockHeaderSize = m_blockHeader.size(); - get_tx_keys(m_poolBlockTemplate->m_txkeyPub, m_poolBlockTemplate->m_txkeySec, miner_wallet->spend_public_key(), data.prev_id); + 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(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); + } + 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_sidechain->fill_sidechain_data(*m_poolBlockTemplate, m_shares); @@ -602,7 +617,7 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, Wallet { memset(m_sidechainHashKeccakState, 0, sizeof(m_sidechainHashKeccakState)); - const size_t extra_nonce_offset = m_sidechainHashBlob.size() - HASH_SIZE - ((m_poolBlockTemplate->get_sidechain_version() > 1) ? EXTRA_NONCE_SIZE : 0); + const size_t extra_nonce_offset = m_sidechainHashBlob.size() - HASH_SIZE - ((sidechain_version > 1) ? EXTRA_NONCE_SIZE : 0); if (extra_nonce_offset >= KeccakParams::HASH_DATA_AREA) { // Sidechain data is big enough to cache keccak state up to extra_nonce m_sidechainHashInputLength = (extra_nonce_offset / KeccakParams::HASH_DATA_AREA) * KeccakParams::HASH_DATA_AREA; diff --git a/src/crypto.cpp b/src/crypto.cpp index d7be7f2..e253b24 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -266,10 +266,10 @@ public: return true; } - void get_tx_keys(hash& pub, hash& sec, const hash& wallet_spend_key, const hash& monero_block_id) + void get_tx_keys(hash& pub, hash& sec, const hash& seed, const hash& monero_block_id) { std::array index; - memcpy(index.data(), wallet_spend_key.h, HASH_SIZE); + memcpy(index.data(), seed.h, HASH_SIZE); memcpy(index.data() + HASH_SIZE, monero_block_id.h, HASH_SIZE); { @@ -287,7 +287,7 @@ public: uint8_t entropy[N + HASH_SIZE * 2]; memcpy(entropy, domain, N); - memcpy(entropy + N, wallet_spend_key.h, HASH_SIZE); + memcpy(entropy + N, seed.h, HASH_SIZE); memcpy(entropy + N + HASH_SIZE, monero_block_id.h, HASH_SIZE); generate_keys_deterministic(pub, sec, entropy, sizeof(entropy)); @@ -399,9 +399,9 @@ bool derive_public_key(const hash& derivation, size_t output_index, const hash& return cache->get_public_key(derivation, output_index, base, derived_key); } -void get_tx_keys(hash& pub, hash& sec, const hash& wallet_spend_key, const hash& monero_block_id) +void get_tx_keys(hash& pub, hash& sec, const hash& seed, const hash& monero_block_id) { - cache->get_tx_keys(pub, sec, wallet_spend_key, monero_block_id); + cache->get_tx_keys(pub, sec, seed, monero_block_id); } void derive_view_tag(const hash& derivation, size_t output_index, uint8_t& view_tag) diff --git a/src/crypto.h b/src/crypto.h index 2ab908c..ab5c6cd 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -21,7 +21,7 @@ namespace p2pool { void generate_keys(hash& pub, hash& sec); void generate_keys_deterministic(hash& pub, hash& sec, const uint8_t* entropy, size_t len); -void get_tx_keys(hash& pub, hash& sec, const hash& wallet_spend_key, const hash& monero_block_id); +void get_tx_keys(hash& pub, hash& sec, const hash& seed, const hash& monero_block_id); bool check_keys(const hash& pub, const hash& sec); bool generate_key_derivation(const hash& key1, const hash& key2, size_t output_index, hash& derivation, uint8_t& view_tag); bool derive_public_key(const hash& derivation, size_t output_index, const hash& base, hash& derived_key); diff --git a/src/pool_block.cpp b/src/pool_block.cpp index 92fe2f4..07bc35e 100644 --- a/src/pool_block.cpp +++ b/src/pool_block.cpp @@ -38,6 +38,7 @@ PoolBlock::PoolBlock() , m_txkeyPub{} , m_extraNonceSize(0) , m_extraNonce(0) + , m_txkeySecSeed{} , m_txkeySec{} , m_parent{} , m_sidechainHeight(0) @@ -91,6 +92,7 @@ PoolBlock& PoolBlock::operator=(const PoolBlock& b) m_extraNonce = b.m_extraNonce; m_transactions = b.m_transactions; m_minerWallet = b.m_minerWallet; + m_txkeySecSeed = b.m_txkeySecSeed; m_txkeySec = b.m_txkeySec; m_parent = b.m_parent; m_uncles = b.m_uncles; @@ -235,9 +237,18 @@ std::vector PoolBlock::serialize_sidechain_data() const const hash& spend = m_minerWallet.spend_public_key(); const hash& view = m_minerWallet.view_public_key(); + const int sidechain_version = get_sidechain_version(); + data.insert(data.end(), spend.h, spend.h + HASH_SIZE); data.insert(data.end(), view.h, view.h + HASH_SIZE); - data.insert(data.end(), m_txkeySec.h, m_txkeySec.h + HASH_SIZE); + + if (sidechain_version > 1) { + data.insert(data.end(), m_txkeySecSeed.h, m_txkeySecSeed.h + HASH_SIZE); + } + else { + data.insert(data.end(), m_txkeySec.h, m_txkeySec.h + HASH_SIZE); + } + data.insert(data.end(), m_parent.h, m_parent.h + HASH_SIZE); writeVarint(m_uncles.size(), data); @@ -254,7 +265,7 @@ std::vector PoolBlock::serialize_sidechain_data() const writeVarint(m_cumulativeDifficulty.lo, data); writeVarint(m_cumulativeDifficulty.hi, data); - if (get_sidechain_version() > 1) { + if (sidechain_version > 1) { const uint8_t* p = reinterpret_cast(m_sidechainExtraBuf); data.insert(data.end(), p, p + sizeof(m_sidechainExtraBuf)); } diff --git a/src/pool_block.h b/src/pool_block.h index f444713..2e2bc4a 100644 --- a/src/pool_block.h +++ b/src/pool_block.h @@ -106,6 +106,7 @@ struct PoolBlock // Transaction secret key // Required to check that pub keys in the miner transaction pay out to correct miner wallet addresses + hash m_txkeySecSeed; hash m_txkeySec; // Side-chain parent and uncle blocks diff --git a/src/pool_block_parser.inl b/src/pool_block_parser.inl index f7cb2c9..79a5c34 100644 --- a/src/pool_block_parser.inl +++ b/src/pool_block_parser.inl @@ -260,20 +260,33 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, const SideChain& si return __LINE__; } - READ_BUF(m_txkeySec.h, HASH_SIZE); + READ_BUF(m_txkeySecSeed.h, HASH_SIZE); - if (!check_keys(m_txkeyPub, m_txkeySec)) { - return __LINE__; - } + const int sidechain_version = get_sidechain_version(); - // Enforce deterministic tx keys starting from v15 - if (m_majorVersion >= HARDFORK_VIEW_TAGS_VERSION) { - hash pub, sec; - get_tx_keys(pub, sec, spend_pub_key, m_prevId); - if ((pub != m_txkeyPub) || (sec != m_txkeySec)) { + if (sidechain_version > 1) { + hash pub; + get_tx_keys(pub, m_txkeySec, m_txkeySecSeed, m_prevId); + if (pub != m_txkeyPub) { return __LINE__; } } + else { + m_txkeySec = m_txkeySecSeed; + + // Enforce deterministic tx keys starting from v15 + if (m_majorVersion >= HARDFORK_VIEW_TAGS_VERSION) { + hash pub, sec; + get_tx_keys(pub, sec, spend_pub_key, m_prevId); + if ((pub != m_txkeyPub) || (sec != m_txkeySec)) { + return __LINE__; + } + } + } + + if (!check_keys(m_txkeyPub, m_txkeySec)) { + return __LINE__; + } READ_BUF(m_parent.h, HASH_SIZE); @@ -317,7 +330,6 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, const SideChain& si READ_VARINT(m_cumulativeDifficulty.lo); READ_VARINT(m_cumulativeDifficulty.hi); - const int sidechain_version = get_sidechain_version(); if (sidechain_version > 1) { READ_BUF(m_sidechainExtraBuf, sizeof(m_sidechainExtraBuf)); } diff --git a/tests/src/block_template_tests.cpp b/tests/src/block_template_tests.cpp index f2aaeef..a42195e 100644 --- a/tests/src/block_template_tests.cpp +++ b/tests/src/block_template_tests.cpp @@ -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("d98c48f1137eac26d31ae1d94cce12625c519fc79d1b153035418a1715f6be61")); + ASSERT_EQ(b->m_sidechainId, H("e6fa454c10374439dcc9eee3198f6ba17a7a3764510569c3b963b31510b74780")); std::vector blobs; uint64_t height; @@ -79,7 +79,7 @@ TEST(block_template, update) hash blobs_hash; keccak(blobs.data(), static_cast(blobs.size()), blobs_hash.h); - ASSERT_EQ(blobs_hash, H("c828b3ef21a28535373aba95ece7429b4abb4c687883722f901eeaf110a9ebaa")); + ASSERT_EQ(blobs_hash, H("fd0079d39d1739ded6e710192228276cbaa55eaabde7a26c38f8986709a030e4")); // Test 2: mempool with high fee and low fee transactions, it must choose high fee transactions for (uint64_t i = 0; i < 512; ++i) {