From 155fbdb8575a8b1f6444b2b77afef549cf798053 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Thu, 22 Aug 2024 16:10:27 -0400 Subject: [PATCH 1/3] Move hash parsing optimizations to system. --- include/bitcoin/network/messages/block.hpp | 4 -- .../bitcoin/network/messages/transaction.hpp | 3 -- src/messages/block.cpp | 41 +------------------ src/messages/transaction.cpp | 25 +---------- 4 files changed, 3 insertions(+), 70 deletions(-) diff --git a/include/bitcoin/network/messages/block.hpp b/include/bitcoin/network/messages/block.hpp index 23c3e7a3b..84d94b817 100644 --- a/include/bitcoin/network/messages/block.hpp +++ b/include/bitcoin/network/messages/block.hpp @@ -39,10 +39,6 @@ struct BCT_API block static const uint32_t version_minimum; static const uint32_t version_maximum; - /// Populate header and tx hashes onto the block. - static void set_hashes(const system::chain::block& block, - const system::data_chunk& data) NOEXCEPT; - static cptr deserialize(arena& arena, uint32_t version, const system::data_chunk& data, bool witness=true) NOEXCEPT; static cptr deserialize(uint32_t version, const system::data_chunk& data, diff --git a/include/bitcoin/network/messages/transaction.hpp b/include/bitcoin/network/messages/transaction.hpp index a19f52d5b..4d93f5ad8 100644 --- a/include/bitcoin/network/messages/transaction.hpp +++ b/include/bitcoin/network/messages/transaction.hpp @@ -38,9 +38,6 @@ struct BCT_API transaction static const uint32_t version_minimum; static const uint32_t version_maximum; - static system::hash_digest desegregated_hash(size_t witnessed, - size_t unwitnessed, const uint8_t* data) NOEXCEPT; - static cptr deserialize(uint32_t version, const system::data_chunk& data, bool witness=true) NOEXCEPT; static transaction deserialize(uint32_t version, system::reader& source, diff --git a/src/messages/block.cpp b/src/messages/block.cpp index 24f31ec22..faa881405 100644 --- a/src/messages/block.cpp +++ b/src/messages/block.cpp @@ -44,48 +44,9 @@ const identifier block::id = identifier::block; const uint32_t block::version_minimum = level::minimum_protocol; const uint32_t block::version_maximum = level::maximum_protocol; -// static -void block::set_hashes(const chain::block& block, const data_chunk& data) NOEXCEPT -{ - constexpr auto header_size = chain::header::serialized_size(); - - // Cache header hash. - block.header().set_hash(bitcoin_hash(header_size, data.data())); - - // Skip transaction count, guarded by preceding successful block construct. - auto start = std::next(data.data(), header_size); - std::advance(start, size_variable(*start)); - - // Cache transaction hashes. - auto coinbase = true; - for (const auto& tx: *block.transactions_ptr()) - { - const auto witness_size = tx->serialized_size(true); - - // If !witness then wire txs cannot have been segregated. - if (tx->is_segregated()) - { - const auto nominal_size = tx->serialized_size(false); - - tx->set_nominal_hash(transaction::desegregated_hash( - witness_size, nominal_size, start)); - - if (!coinbase) - tx->set_witness_hash(bitcoin_hash(witness_size, start)); - } - else - { - tx->set_nominal_hash(bitcoin_hash(witness_size, start)); - } - - coinbase = false; - std::advance(start, witness_size); - } -} - // static typename block::cptr block::deserialize(uint32_t version, - const system::data_chunk& data, bool witness) NOEXCEPT + const data_chunk& data, bool witness) NOEXCEPT { static default_memory memory{}; return deserialize(*memory.get_arena(), version, data, witness); diff --git a/src/messages/transaction.cpp b/src/messages/transaction.cpp index 9185fd045..5005b8ad3 100644 --- a/src/messages/transaction.cpp +++ b/src/messages/transaction.cpp @@ -35,27 +35,6 @@ const identifier transaction::id = identifier::transaction; const uint32_t transaction::version_minimum = level::minimum_protocol; const uint32_t transaction::version_maximum = level::maximum_protocol; -// Optimized non-witness hash derivation using witness-serialized tx. -hash_digest transaction::desegregated_hash(size_t witnessed, - size_t unwitnessed, const uint8_t* data) NOEXCEPT -{ - BC_ASSERT_MSG(!is_null(data), "nullptr"); - - using namespace system; - constexpr auto preamble = sizeof(uint32_t) + two * sizeof(uint8_t); - const auto puts = floored_subtract(unwitnessed, two * sizeof(uint32_t)); - const auto locktime = floored_subtract(witnessed, sizeof(uint32_t)); - - hash_digest digest{}; - stream::out::fast stream{ digest }; - hash::sha256x2::fast sink{ stream }; - sink.write_bytes(data, sizeof(uint32_t)); - sink.write_bytes(std::next(data, preamble), puts); - sink.write_bytes(std::next(data, locktime), sizeof(uint32_t)); - sink.flush(); - return digest; -} - // static typename transaction::cptr transaction::deserialize(uint32_t version, const data_chunk& data, bool witness) NOEXCEPT @@ -75,8 +54,8 @@ typename transaction::cptr transaction::deserialize(uint32_t version, const auto true_size = tx.serialized_size(true); const auto false_size = tx.serialized_size(false); tx.set_witness_hash(bitcoin_hash(true_size, data.data())); - tx.set_nominal_hash(desegregated_hash(true_size, false_size, - data.data())); + tx.set_nominal_hash(chain::transaction::desegregated_hash( + true_size, false_size, data.data())); } else { From 177f352c352d2e26195c20a8e80636978503c4d6 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Thu, 22 Aug 2024 16:12:21 -0400 Subject: [PATCH 2/3] block::deserialize delete memory if fails. --- src/messages/block.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/messages/block.cpp b/src/messages/block.cpp index faa881405..45a4cc5db 100644 --- a/src/messages/block.cpp +++ b/src/messages/block.cpp @@ -66,10 +66,20 @@ typename block::cptr block::deserialize(arena& arena, uint32_t version, byte_reader reader{ source, &arena }; auto& allocator = reader.get_allocator(); const auto block = allocator.new_object(reader, witness); - if (is_null(block) || !reader) + + // Destruct block if created but failed to deserialize. + if (!reader && !is_null(block)) + byte_allocator::deleter(&arena); + + // Release memory if block construction or deserialization failed. + if (!reader || is_null(block)) + { + arena.release(memory); return nullptr; + } - set_hashes(*block, data); + // Cache hashes as extracted from serialized block. + block->set_hashes(data); // Set size of block allocation owned by memory (zero if non-detachable). block->set_allocation(arena.detach()); From 3dea38f42a270e280a5b8154afc96fe65cd2a860 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Thu, 22 Aug 2024 17:06:24 -0400 Subject: [PATCH 3/3] Comment. --- src/messages/block.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/messages/block.cpp b/src/messages/block.cpp index 45a4cc5db..a22ceac25 100644 --- a/src/messages/block.cpp +++ b/src/messages/block.cpp @@ -92,7 +92,6 @@ typename block::cptr block::deserialize(arena& arena, uint32_t version, byte_allocator::deleter(&arena); // Deallocate detached memory (nop if not detachable). - // Follows destructor just in case a destructor traverses memory. arena.release(memory); })); }