diff --git a/src/block_template.cpp b/src/block_template.cpp index edc6251..670171e 100644 --- a/src/block_template.cpp +++ b/src/block_template.cpp @@ -910,7 +910,7 @@ hash BlockTemplate::calc_miner_tx_hash(uint32_t extra_nonce) const // Calculate miner transaction hash hash result; - keccak(hashes, sizeof(hashes), result.h, HASH_SIZE); + keccak(hashes, sizeof(hashes), result.h); return result; } @@ -929,7 +929,7 @@ void BlockTemplate::calc_merkle_tree_main_branch() } else if (count == 2) { m_merkleTreeMainBranch.insert(m_merkleTreeMainBranch.end(), h + HASH_SIZE, h + HASH_SIZE * 2); - keccak(h, HASH_SIZE * 2, root_hash.h, HASH_SIZE); + keccak(h, HASH_SIZE * 2, root_hash.h); } else { size_t i, j, cnt; @@ -941,11 +941,14 @@ void BlockTemplate::calc_merkle_tree_main_branch() std::vector ints(cnt * HASH_SIZE); memcpy(ints.data(), h, (cnt * 2 - count) * HASH_SIZE); + hash tmp; + for (i = cnt * 2 - count, j = cnt * 2 - count; j < cnt; i += 2, ++j) { if (i == 0) { m_merkleTreeMainBranch.insert(m_merkleTreeMainBranch.end(), h + HASH_SIZE, h + HASH_SIZE * 2); } - keccak(h + i * HASH_SIZE, HASH_SIZE * 2, ints.data() + j * HASH_SIZE, HASH_SIZE); + keccak(h + i * HASH_SIZE, HASH_SIZE * 2, tmp.h); + memcpy(ints.data() + j * HASH_SIZE, tmp.h, HASH_SIZE); } while (cnt > 2) { @@ -954,12 +957,13 @@ void BlockTemplate::calc_merkle_tree_main_branch() if (i == 0) { m_merkleTreeMainBranch.insert(m_merkleTreeMainBranch.end(), ints.data() + HASH_SIZE, ints.data() + HASH_SIZE * 2); } - keccak(ints.data() + i * HASH_SIZE, HASH_SIZE * 2, ints.data() + j * HASH_SIZE, HASH_SIZE); + keccak(ints.data() + i * HASH_SIZE, HASH_SIZE * 2, tmp.h); + memcpy(ints.data() + j * HASH_SIZE, tmp.h, HASH_SIZE); } } m_merkleTreeMainBranch.insert(m_merkleTreeMainBranch.end(), ints.data() + HASH_SIZE, ints.data() + HASH_SIZE * 2); - keccak(ints.data(), HASH_SIZE * 2, root_hash.h, HASH_SIZE); + keccak(ints.data(), HASH_SIZE * 2, root_hash.h); } } @@ -1039,7 +1043,7 @@ uint32_t BlockTemplate::get_hashing_blob_nolock(uint32_t extra_nonce, uint8_t* b memcpy(h, root_hash.h, HASH_SIZE); memcpy(h + HASH_SIZE, m_merkleTreeMainBranch.data() + i, HASH_SIZE); - keccak(h, HASH_SIZE * 2, root_hash.h, HASH_SIZE); + keccak(h, HASH_SIZE * 2, root_hash.h); } memcpy(p, root_hash.h, HASH_SIZE); diff --git a/src/crypto.cpp b/src/crypto.cpp index 252201e..d7be7f2 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -134,7 +134,7 @@ bool check_keys(const hash& pub, const hash& sec) static FORCEINLINE void hash_to_scalar(const uint8_t* data, int length, uint8_t (&res)[HASH_SIZE]) { - keccak(data, length, res, HASH_SIZE); + keccak(data, length, res); sc_reduce32(res); } @@ -416,7 +416,7 @@ void derive_view_tag(const hash& derivation, size_t output_index, uint8_t& view_ writeVarint(output_index, [&p](uint8_t b) { *(p++) = b; }); hash view_tag_full; - keccak(buf, static_cast(p - buf), view_tag_full.h, HASH_SIZE); + keccak(buf, static_cast(p - buf), view_tag_full.h); view_tag = view_tag_full.h[0]; } diff --git a/src/keccak.cpp b/src/keccak.cpp index 2d8bcda..9c756cf 100644 --- a/src/keccak.cpp +++ b/src/keccak.cpp @@ -115,14 +115,10 @@ NOINLINE void keccakf(uint64_t* st) } } -NOINLINE void keccak(const uint8_t* in, int inlen, uint8_t* md, int mdlen) +NOINLINE void keccak_step(const uint8_t* &in, int &inlen, uint64_t (&st)[25]) { - uint64_t st[25]; - - const int rsiz = sizeof(st) == mdlen ? KeccakParams::HASH_DATA_AREA : 200 - 2 * mdlen; - const int rsizw = rsiz / 8; - - memset(st, 0, sizeof(st)); + constexpr int rsiz = KeccakParams::HASH_DATA_AREA; + constexpr int rsizw = rsiz / 8; for (; inlen >= rsiz; inlen -= rsiz, in += rsiz) { for (int i = 0; i < rsizw; i++) { @@ -130,6 +126,14 @@ NOINLINE void keccak(const uint8_t* in, int inlen, uint8_t* md, int mdlen) } keccakf(st); } +} + +NOINLINE void keccak_finish(const uint8_t* in, int inlen, uint64_t (&st)[25]) +{ + constexpr int rsiz = KeccakParams::HASH_DATA_AREA; + constexpr int rsizw = rsiz / 8; + + keccak_step(in, inlen, st); // last block and padding alignas(8) uint8_t temp[144]; @@ -144,13 +148,22 @@ NOINLINE void keccak(const uint8_t* in, int inlen, uint8_t* md, int mdlen) } keccakf(st); - - memcpy(md, st, mdlen); } -void keccak(const uint8_t *in, int inlen, uint8_t (&md)[200]) +NOINLINE void keccak(const uint8_t* in, int inlen, uint8_t (&md)[32]) { - keccak(in, inlen, md, 200); + uint64_t st[25] = {}; + keccak_step(in, inlen, st); + keccak_finish(in, inlen, st); + memcpy(md, st, 32); +} + +NOINLINE void keccak(const uint8_t* in, int inlen, uint8_t(&md)[200]) +{ + uint64_t st[25] = {}; + keccak_step(in, inlen, st); + keccak_finish(in, inlen, st); + memcpy(md, st, sizeof(md)); } } // namespace p2pool diff --git a/src/keccak.h b/src/keccak.h index e43f07d..b3a2d33 100644 --- a/src/keccak.h +++ b/src/keccak.h @@ -25,8 +25,11 @@ enum KeccakParams { }; void keccakf(uint64_t* st); -void keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen); -void keccak(const uint8_t* in, int inlen, uint8_t (&md)[200]); +void keccak(const uint8_t *in, int inlen, uint8_t (&md)[32]); +void keccak(const uint8_t *in, int inlen, uint8_t (&md)[200]); + +void keccak_step(const uint8_t* &in, int &inlen, uint64_t (&st)[25]); +void keccak_finish(const uint8_t* in, int inlen, uint64_t (&st)[25]); template FORCEINLINE void keccak_custom(T&& in, int inlen, uint8_t* md, int mdlen) diff --git a/src/p2pool.cpp b/src/p2pool.cpp index 5e56212..7de8264 100644 --- a/src/p2pool.cpp +++ b/src/p2pool.cpp @@ -1032,7 +1032,7 @@ void p2pool::parse_get_miner_data_rpc(const char* data, size_t size) } hash h; - keccak(reinterpret_cast(data), static_cast(size), h.h, HASH_SIZE); + keccak(reinterpret_cast(data), static_cast(size), h.h); if (h == m_getMinerDataHash) { LOGWARN(4, "Received a duplicate get_miner_data RPC response, ignoring it"); return; diff --git a/src/pool_block.cpp b/src/pool_block.cpp index 8da936b..218c712 100644 --- a/src/pool_block.cpp +++ b/src/pool_block.cpp @@ -310,18 +310,22 @@ bool PoolBlock::get_pow_hash(RandomX_Hasher_Base* hasher, uint64_t height, const memcpy(blob, mainchain_data.data(), blob_size); const uint8_t* miner_tx = mainchain_data.data() + header_size; - keccak(miner_tx, static_cast(miner_tx_size) - 1, reinterpret_cast(hashes), HASH_SIZE); + hash tmp; + keccak(miner_tx, static_cast(miner_tx_size) - 1, tmp.h); + memcpy(hashes, tmp.h, HASH_SIZE); count = m_transactions.size(); uint8_t* h = reinterpret_cast(m_transactions.data()); - keccak(reinterpret_cast(hashes), HASH_SIZE * 3, h, HASH_SIZE); + keccak(reinterpret_cast(hashes), HASH_SIZE * 3, tmp.h); + memcpy(h, tmp.h, HASH_SIZE); if (count == 1) { memcpy(blob + blob_size, h, HASH_SIZE); } else if (count == 2) { - keccak(h, HASH_SIZE * 2, blob + blob_size, HASH_SIZE); + keccak(h, HASH_SIZE * 2, tmp.h); + memcpy(blob + blob_size, tmp.h, HASH_SIZE); } else { size_t i, j, cnt; @@ -334,17 +338,20 @@ bool PoolBlock::get_pow_hash(RandomX_Hasher_Base* hasher, uint64_t height, const memcpy(tmp_ints.data(), h, (cnt * 2 - count) * HASH_SIZE); for (i = cnt * 2 - count, j = cnt * 2 - count; j < cnt; i += 2, ++j) { - keccak(h + i * HASH_SIZE, HASH_SIZE * 2, tmp_ints.data() + j * HASH_SIZE, HASH_SIZE); + keccak(h + i * HASH_SIZE, HASH_SIZE * 2, tmp.h); + memcpy(tmp_ints.data() + j * HASH_SIZE, tmp.h, HASH_SIZE); } while (cnt > 2) { cnt >>= 1; for (i = 0, j = 0; j < cnt; i += 2, ++j) { - keccak(tmp_ints.data() + i * HASH_SIZE, HASH_SIZE * 2, tmp_ints.data() + j * HASH_SIZE, HASH_SIZE); + keccak(tmp_ints.data() + i * HASH_SIZE, HASH_SIZE * 2, tmp.h); + memcpy(tmp_ints.data() + j * HASH_SIZE, tmp.h, HASH_SIZE); } } - keccak(tmp_ints.data(), HASH_SIZE * 2, blob + blob_size, HASH_SIZE); + keccak(tmp_ints.data(), HASH_SIZE * 2, tmp.h); + memcpy(blob + blob_size, tmp.h, HASH_SIZE); } } blob_size += HASH_SIZE; diff --git a/src/side_chain.cpp b/src/side_chain.cpp index 8ed4d38..35c3368 100644 --- a/src/side_chain.cpp +++ b/src/side_chain.cpp @@ -141,7 +141,7 @@ SideChain::SideChain(p2pool* pool, NetworkType type, const char* pool_name) } hash id; - keccak(reinterpret_cast(scratchpad), static_cast(scratchpad_size * sizeof(rx_vec_i128)), id.h, HASH_SIZE); + keccak(reinterpret_cast(scratchpad), static_cast(scratchpad_size * sizeof(rx_vec_i128)), id.h); randomx_release_cache(cache); m_consensusId.assign(id.h, id.h + HASH_SIZE); #else diff --git a/tests/src/block_template_tests.cpp b/tests/src/block_template_tests.cpp index 2111e99..0d92e4a 100644 --- a/tests/src/block_template_tests.cpp +++ b/tests/src/block_template_tests.cpp @@ -77,7 +77,7 @@ TEST(block_template, update) ASSERT_EQ(template_id, 1); hash blobs_hash; - keccak(blobs.data(), static_cast(blobs.size()), blobs_hash.h, HASH_SIZE); + keccak(blobs.data(), static_cast(blobs.size()), blobs_hash.h); ASSERT_EQ(blobs_hash, H("e9154971a27c412175562d23ab458b0d3cf780a8bcecf62ff3f667fed9d3bc1d")); // Test 2: mempool with high fee and low fee transactions, it must choose high fee transactions diff --git a/tests/src/keccak_tests.cpp b/tests/src/keccak_tests.cpp index 36e4071..15c8a2a 100644 --- a/tests/src/keccak_tests.cpp +++ b/tests/src/keccak_tests.cpp @@ -27,7 +27,7 @@ TEST(keccak, hashing) hash output; const uint8_t* data = reinterpret_cast(input); const int len = static_cast(size); - keccak(data, len, output.h, HASH_SIZE); + keccak(data, len, output.h); char buf[log::Stream::BUF_SIZE + 1]; log::Stream s(buf);