From 971d5d26b5f05345f321f2f7848aea8534a68757 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 15 Jul 2024 03:02:57 -0400 Subject: [PATCH] Witness. --- include/bitcoin/system/chain/witness.hpp | 4 +- src/chain/witness.cpp | 45 +++--- test/chain/witness.cpp | 181 ++++++++++++++++++++++- 3 files changed, 208 insertions(+), 22 deletions(-) diff --git a/include/bitcoin/system/chain/witness.hpp b/include/bitcoin/system/chain/witness.hpp index 05d7b145b5..47d03ea63a 100644 --- a/include/bitcoin/system/chain/witness.hpp +++ b/include/bitcoin/system/chain/witness.hpp @@ -124,9 +124,11 @@ class BC_API witness witness(const chunk_cptrs& stack, bool valid, size_t size) NOEXCEPT; private: + void assign_data(reader& source, bool prefix) NOEXCEPT; + ////static witness from_data(reader& source, bool prefix) NOEXCEPT; + // TODO: move to config serialization wrapper. static witness from_string(const std::string& mnemonic) NOEXCEPT; - static witness from_data(reader& source, bool prefix) NOEXCEPT; BC_PUSH_WARNING(SMART_PTR_NOT_NEEDED) BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR) diff --git a/src/chain/witness.cpp b/src/chain/witness.cpp index 0b3a0ccafd..08e0cede56 100644 --- a/src/chain/witness.cpp +++ b/src/chain/witness.cpp @@ -98,13 +98,15 @@ witness::witness(std::istream& stream, bool prefix) NOEXCEPT } witness::witness(reader&& source, bool prefix) NOEXCEPT - : witness(from_data(source, prefix)) + : witness(source, prefix/*from_data(source, prefix)*/) { } witness::witness(reader& source, bool prefix) NOEXCEPT - : witness(from_data(source, prefix)) +////: witness(from_data(source, prefix)) + : stack_(source.arena()) { + assign_data(source, prefix); } witness::witness(const std::string& mnemonic) NOEXCEPT @@ -162,36 +164,41 @@ void witness::skip(reader& source, bool prefix) NOEXCEPT } } -static data_chunk read_element(reader& source) NOEXCEPT +// private +void witness::assign_data(reader& source, bool prefix) NOEXCEPT { - // Each witness encoded as variable integer prefixed byte array (bip144). - return source.read_bytes(source.read_size(max_block_weight)); -} - -// static/private -witness witness::from_data(reader& source, bool prefix) NOEXCEPT -{ - size_t size{}; - chunk_cptrs stack{}; + size_ = zero; + const auto& allocator = source.allocator(); + ////allocator.destroy(&stack_); + ////allocator.construct(&stack_); if (prefix) { - const auto capacity = source.read_size(max_block_weight); - stack.reserve(capacity); + const auto count = source.read_size(max_block_weight); + stack_.reserve(count); - for (size_t element = 0; element < capacity; ++element) + for (size_t element = 0; element < count; ++element) { - stack.push_back(to_shared(read_element(source))); - size = element_size(size, stack.back()); + const auto size = source.read_size(max_block_weight); + stack_.emplace_back( + source.read_bytes_raw(size), + allocator.deleter(source.arena())); + size_ = element_size(size_, stack_.back()); } } else { while (!source.is_exhausted()) - stack.push_back(to_shared(read_element(source))); + { + const auto size = source.read_size(max_block_weight); + stack_.emplace_back( + source.read_bytes_raw(size), + allocator.deleter(source.arena())); + size_ = element_size(size_, stack_.back()); + } } - return { stack, source, size }; + valid_ = source; } inline bool is_push_token(const std::string& token) NOEXCEPT diff --git a/test/chain/witness.cpp b/test/chain/witness.cpp index 8b23845df8..f373ac8e35 100644 --- a/test/chain/witness.cpp +++ b/test/chain/witness.cpp @@ -21,10 +21,187 @@ BOOST_AUTO_TEST_SUITE(witness_tests) namespace json = boost::json; +using namespace system::chain; -BOOST_AUTO_TEST_CASE(witness_test) +const block& get_block() NOEXCEPT { - BOOST_REQUIRE(true); + constexpr auto root = base16_hash("1bf6a4281aca254af9dafb696dc1b9ce47d9f0785ebd4622fa0e28104fe3df44"); + constexpr uint32_t block_version{ 0 }; + constexpr hash_digest previous_block_hash{ 1 }; + constexpr hash_digest merkle_root{ root }; + constexpr uint32_t timestamp{ 3 }; + constexpr uint32_t bits{ 4 }; + constexpr uint32_t nonce{ 5 }; + constexpr uint32_t tx_version{ 6 }; + constexpr uint32_t locktime{ 7 }; + constexpr uint32_t sequence{ 8 }; + constexpr uint64_t value{ 9 }; + constexpr hash_digest point_hash{ 9 }; + constexpr uint32_t point_index{ 9 }; + constexpr bool minimal{ true }; + + static const block instance + { + header // ptr
+ { + block_version, + previous_block_hash, + merkle_root, + timestamp, + bits, + nonce + }, + transactions // ptr> + { + // coinbase + transaction // first tx + { + tx_version, + inputs + { + input // exactly one input + { + point // null point + { + null_hash, + point::null_index + }, + script{ operations{ operation{ opcode::nop1 }, operation{ opcode::nop2 } } }, // minumum 2 bytes + sequence + } + }, + outputs + { + output // at least one output + { + value, // no more than reward + script{} + } + }, + locktime + }, + transaction // ptr + { + tx_version, + inputs // ptr>> + { + input // ptr + { + point // ptr + { + point_hash, + point_index + }, + script // ptr