Refactored keccak interface

- Allow calculating keccak hash in steps
- Only allow 32 and 200 byte final hashes
This commit is contained in:
SChernykh 2023-01-08 12:56:26 +01:00
parent 4f34c4466a
commit 632f3faac5
9 changed files with 58 additions and 31 deletions

View file

@ -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<uint8_t> 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);

View file

@ -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<int>(p - buf), view_tag_full.h, HASH_SIZE);
keccak(buf, static_cast<int>(p - buf), view_tag_full.h);
view_tag = view_tag_full.h[0];
}

View file

@ -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

View file

@ -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<typename T>
FORCEINLINE void keccak_custom(T&& in, int inlen, uint8_t* md, int mdlen)

View file

@ -1032,7 +1032,7 @@ void p2pool::parse_get_miner_data_rpc(const char* data, size_t size)
}
hash h;
keccak(reinterpret_cast<const uint8_t*>(data), static_cast<int>(size), h.h, HASH_SIZE);
keccak(reinterpret_cast<const uint8_t*>(data), static_cast<int>(size), h.h);
if (h == m_getMinerDataHash) {
LOGWARN(4, "Received a duplicate get_miner_data RPC response, ignoring it");
return;

View file

@ -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<int>(miner_tx_size) - 1, reinterpret_cast<uint8_t*>(hashes), HASH_SIZE);
hash tmp;
keccak(miner_tx, static_cast<int>(miner_tx_size) - 1, tmp.h);
memcpy(hashes, tmp.h, HASH_SIZE);
count = m_transactions.size();
uint8_t* h = reinterpret_cast<uint8_t*>(m_transactions.data());
keccak(reinterpret_cast<uint8_t*>(hashes), HASH_SIZE * 3, h, HASH_SIZE);
keccak(reinterpret_cast<uint8_t*>(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;

View file

@ -141,7 +141,7 @@ SideChain::SideChain(p2pool* pool, NetworkType type, const char* pool_name)
}
hash id;
keccak(reinterpret_cast<uint8_t*>(scratchpad), static_cast<int>(scratchpad_size * sizeof(rx_vec_i128)), id.h, HASH_SIZE);
keccak(reinterpret_cast<uint8_t*>(scratchpad), static_cast<int>(scratchpad_size * sizeof(rx_vec_i128)), id.h);
randomx_release_cache(cache);
m_consensusId.assign(id.h, id.h + HASH_SIZE);
#else

View file

@ -77,7 +77,7 @@ TEST(block_template, update)
ASSERT_EQ(template_id, 1);
hash blobs_hash;
keccak(blobs.data(), static_cast<int>(blobs.size()), blobs_hash.h, HASH_SIZE);
keccak(blobs.data(), static_cast<int>(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

View file

@ -27,7 +27,7 @@ TEST(keccak, hashing)
hash output;
const uint8_t* data = reinterpret_cast<const uint8_t*>(input);
const int len = static_cast<int>(size);
keccak(data, len, output.h, HASH_SIZE);
keccak(data, len, output.h);
char buf[log::Stream::BUF_SIZE + 1];
log::Stream s(buf);