From 97eda5e27fd66201f1d4d2a08a57419d4a787e22 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 15 Jul 2024 22:32:49 -0400 Subject: [PATCH 1/3] Style. --- src/chain/transaction.cpp | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/chain/transaction.cpp b/src/chain/transaction.cpp index 43844a0560..6b935d4106 100644 --- a/src/chain/transaction.cpp +++ b/src/chain/transaction.cpp @@ -98,21 +98,12 @@ transaction::transaction(const transaction& other) NOEXCEPT other.valid_) { // Optimized for faster optional, not for copy. - if (other.nominal_hash_) nominal_hash_ = to_unique(*other.nominal_hash_); - else - nominal_hash_.reset(); - if (other.witness_hash_) witness_hash_ = to_unique(*other.witness_hash_); - else - witness_hash_.reset(); - if (other.sighash_cache_) sighash_cache_ = to_unique(*other.sighash_cache_); - else - sighash_cache_.reset(); } transaction::transaction(uint32_t version, chain::inputs&& inputs, @@ -211,22 +202,17 @@ transaction& transaction::operator=(const transaction& other) NOEXCEPT valid_ = other.valid_; size_ = other.size_; - // Optimized for faster optional, not for copy. + nominal_hash_.reset(); + witness_hash_.reset(); + sighash_cache_.reset(); + // Optimized for faster optional, not for copy. if (other.nominal_hash_) nominal_hash_ = to_unique(*other.nominal_hash_); - else - nominal_hash_.reset(); - if (other.witness_hash_) witness_hash_ = to_unique(*other.witness_hash_); - else - witness_hash_.reset(); - if (other.sighash_cache_) sighash_cache_ = to_unique(*other.sighash_cache_); - else - sighash_cache_.reset(); return *this; } From a36071e490e1824ddeb93840ed107e7e55c1c76a Mon Sep 17 00:00:00 2001 From: evoskuil Date: Tue, 16 Jul 2024 01:16:28 -0400 Subject: [PATCH 2/3] Comments. --- src/chain/operation.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/chain/operation.cpp b/src/chain/operation.cpp index 220f038820..d499dfde53 100644 --- a/src/chain/operation.cpp +++ b/src/chain/operation.cpp @@ -39,14 +39,14 @@ BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT) // Gotta set something when invalid minimal result, test is_valid. static constexpr auto any_invalid = opcode::op_xor; -// static +// static/private const data_chunk& operation::no_data() NOEXCEPT { static const data_chunk empty_data{}; return empty_data; } -// static +// static/private const chunk_cptr& operation::no_data_cptr() NOEXCEPT { BC_PUSH_WARNING(NO_NEW_OR_DELETE) @@ -58,7 +58,7 @@ const chunk_cptr& operation::no_data_cptr() NOEXCEPT return empty; } -// static +// static/private // Push data is not possible with an invalid code, combination is invalid. const chunk_cptr& operation::any_data_cptr() NOEXCEPT { From 95a49e2ac8459b8349cdf005bb4f09570c7dc101 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Tue, 16 Jul 2024 01:17:25 -0400 Subject: [PATCH 3/3] Avoid unnecessary witness initializations. --- include/bitcoin/system/chain/input.hpp | 15 +++- src/chain/input.cpp | 95 +++++++++++++++++--------- 2 files changed, 76 insertions(+), 34 deletions(-) diff --git a/include/bitcoin/system/chain/input.hpp b/include/bitcoin/system/chain/input.hpp index cac2a6e2ac..24b9cae1dd 100644 --- a/include/bitcoin/system/chain/input.hpp +++ b/include/bitcoin/system/chain/input.hpp @@ -130,12 +130,25 @@ class BC_API input size_t witnessed_size() const NOEXCEPT; void set_witness(reader& source) NOEXCEPT; + inline const chain::witness& get_witness() const NOEXCEPT + { + return witness_ ? *witness_ : no_witness(); + } + + inline const chain::witness::cptr& get_witness_cptr() const NOEXCEPT + { + return witness_ ? witness_ : no_witness_cptr(); + } + typedef struct { size_t nominal; size_t witnessed; } sizes; - void assign_data(reader& source) NOEXCEPT; + ////void assign_data(reader& source) NOEXCEPT; ////static input from_data(reader& source) NOEXCEPT; + static sizes serialized_size(const chain::script& script) NOEXCEPT; static sizes serialized_size(const chain::script& script, const chain::witness& witness) NOEXCEPT; + static const chain::witness& no_witness() NOEXCEPT; + static const chain::witness::cptr& no_witness_cptr() NOEXCEPT; bool extract_sigop_script(chain::script& out, const chain::script& prevout_script) const NOEXCEPT; diff --git a/src/chain/input.cpp b/src/chain/input.cpp index 38d389c9fc..d49f6992e2 100644 --- a/src/chain/input.cpp +++ b/src/chain/input.cpp @@ -42,6 +42,25 @@ static_assert(max_script_size < max_size_t / multisig_default_sigops / heavy_sigops_factor, "input sigop overflow guard"); +// static/private +const witness& input::no_witness() NOEXCEPT +{ + static const chain::witness empty_witness{}; + return empty_witness; +} + +// static/private +const witness::cptr& input::no_witness_cptr() NOEXCEPT +{ + BC_PUSH_WARNING(NO_NEW_OR_DELETE) + static const std::shared_ptr empty + { + new const chain::witness{} + }; + BC_POP_WARNING() + return empty; +} + // Constructors. // ---------------------------------------------------------------------------- @@ -151,12 +170,10 @@ input::input(reader& source) NOEXCEPT script_( source.get_allocator().new_object(source, true), source.get_allocator().deleter(source.get_arena())), - witness_( - source.get_allocator().new_object(/*empty*/), - source.get_allocator().deleter(source.get_arena())), + witness_(nullptr), sequence_(source.read_4_bytes_little_endian()), valid_(source), - size_(serialized_size(*script_, *witness_)) + size_(serialized_size(*script_)) { ////assign_data(source); } @@ -181,7 +198,7 @@ bool input::operator==(const input& other) const NOEXCEPT return (sequence_ == other.sequence_) && (point_ == other.point_ || *point_ == *other.point_) && (script_ == other.script_ || *script_ == *other.script_) - && (witness_ == other.witness_ || *witness_ == *other.witness_); + && (witness_ == other.witness_ || get_witness() == other.get_witness()); } bool input::operator!=(const input& other) const NOEXCEPT @@ -206,28 +223,26 @@ bool input::operator!=(const input& other) const NOEXCEPT //// }; ////} -// private -void input::assign_data(reader&) NOEXCEPT -{ - ////auto& allocator = source.get_allocator(); - //// - ////allocator.construct(&point_, - //// allocator.new_object(source), - //// allocator.deleter(source.get_arena())); - //// - ////allocator.construct(&script_, - //// allocator.new_object(source, true), - //// allocator.deleter(source.get_arena())); - //// - ////// Witness is deserialized and assigned by transaction. - ////allocator.construct(&witness_, - //// allocator.new_object(/*empty*/), - //// allocator.deleter(source.get_arena())); - //// - ////sequence_ = source.read_4_bytes_little_endian(); - ////size_ = serialized_size(*script_, *witness_); - ////valid_ = source; -} +////// private +////void input::assign_data(reader& source) NOEXCEPT +////{ +//// auto& allocator = source.get_allocator(); +//// +//// allocator.construct(&point_, +//// allocator.new_object(source), +//// allocator.deleter(source.get_arena())); +//// +//// allocator.construct(&script_, +//// allocator.new_object(source, true), +//// allocator.deleter(source.get_arena())); +//// +//// // Witness is deserialized and assigned by transaction. +//// allocator.construct(&witness_, nullptr); +//// +//// sequence_ = source.read_4_bytes_little_endian(); +//// size_ = serialized_size(*script_); +//// valid_ = source; +////} // Serialization. // ---------------------------------------------------------------------------- @@ -254,6 +269,20 @@ void input::to_data(writer& sink) const NOEXCEPT sink.write_4_bytes_little_endian(sequence_); } +// static/private +input::sizes input::serialized_size(const chain::script& script) NOEXCEPT +{ + constexpr auto const_size = ceilinged_add( + point::serialized_size(), + sizeof(sequence_)); + + const auto nominal_size = ceilinged_add( + const_size, + script.serialized_size(true)); + + return { nominal_size, zero }; +} + // static/private input::sizes input::serialized_size(const chain::script& script, const chain::witness& witness) NOEXCEPT @@ -334,7 +363,7 @@ const chain::script& input::script() const NOEXCEPT const chain::witness& input::witness() const NOEXCEPT { - return *witness_; + return get_witness(); } const point::cptr& input::point_ptr() const NOEXCEPT @@ -349,7 +378,7 @@ const chain::script::cptr& input::script_ptr() const NOEXCEPT const chain::witness::cptr& input::witness_ptr() const NOEXCEPT { - return witness_; + return get_witness_cptr(); } uint32_t input::sequence() const NOEXCEPT @@ -405,10 +434,10 @@ bool input::is_locked(size_t height, uint32_t median_time_past) const NOEXCEPT bool input::reserved_hash(hash_digest& out) const NOEXCEPT { - if (!witness::is_reserved_pattern(witness_->stack())) + if (!witness::is_reserved_pattern(get_witness().stack())) return false; - std::copy_n(witness_->stack().front()->begin(), hash_size, out.begin()); + std::copy_n(get_witness().stack().front()->begin(), hash_size, out.begin()); return true; } @@ -452,7 +481,7 @@ size_t input::signature_operations(bool bip16, bool bip141) const NOEXCEPT // Embedded/witness scripts are deserialized here and again on scipt eval. chain::script witness; - if (bip141 && witness_->extract_sigop_script(witness, prevout->script())) + if (bip141 && get_witness().extract_sigop_script(witness, prevout->script())) { // Add sigops in the witness script (bip141). return ceilinged_add(sigops, witness.signature_operations(true)); @@ -461,7 +490,7 @@ size_t input::signature_operations(bool bip16, bool bip141) const NOEXCEPT chain::script embedded; if (bip16 && extract_sigop_script(embedded, prevout->script())) { - if (bip141 && witness_->extract_sigop_script(witness, embedded)) + if (bip141 && get_witness().extract_sigop_script(witness, embedded)) { // Add sigops in the embedded witness script (bip141). return ceilinged_add(sigops, witness.signature_operations(true));