From 66cfecf17d0bab92d00e0084408d82fb6efa4243 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Fri, 5 Jun 2026 15:39:53 -0400 Subject: [PATCH 1/2] Implment multisig writer. --- .../database/impl/query/signatures.ipp | 17 +++---- include/bitcoin/database/query.hpp | 6 ++- .../bitcoin/database/tables/caches/ecdsa.hpp | 2 +- .../database/tables/caches/multisig.hpp | 51 ++++++++++++++++++- .../database/tables/caches/schnorr.hpp | 2 +- include/bitcoin/database/tables/schema.hpp | 6 +-- 6 files changed, 66 insertions(+), 18 deletions(-) diff --git a/include/bitcoin/database/impl/query/signatures.ipp b/include/bitcoin/database/impl/query/signatures.ipp index 56b6a4d18..078182261 100644 --- a/include/bitcoin/database/impl/query/signatures.ipp +++ b/include/bitcoin/database/impl/query/signatures.ipp @@ -64,24 +64,21 @@ bool CLASS::set_signature(const hash_digest& digest, const ec_compressed& point, } TEMPLATE -bool CLASS::set_signatures(const hash_digest& , - const multisig_views& , uint16_t , const header_link& ) NOEXCEPT +bool CLASS::set_signatures(const hash_digest& , const ec_compresseds& , + const ec_signatures& , uint16_t , const header_link& ) NOEXCEPT { // ======================================================================== const auto scope = store_.get_transactor(); - // TODO: allocate and then iterate. - // Clean single allocation failure (e.g. disk full). - ////return store_.multisig.put(table::multisig::record + ////return store_.multisig.put(table::multisig::put_ref ////{ //// {}, //// digest, - //// point, - //// signature, - //// pair, - //// link, - //// set + //// keys, + //// sigs, + //// set, + //// link ////}); // ======================================================================== diff --git a/include/bitcoin/database/query.hpp b/include/bitcoin/database/query.hpp index 8e420d475..2be3a92a0 100644 --- a/include/bitcoin/database/query.hpp +++ b/include/bitcoin/database/query.hpp @@ -53,7 +53,9 @@ class query using chain_state = system::chain::chain_state; using chain_state_cptr = system::chain::chain_state::cptr; using chain_context = system::chain::context; + using ec_compresseds = system::ec_compresseds; using ec_compressed = system::ec_compressed; + using ec_signatures = system::ec_signatures; using ec_signature = system::ec_signature; using ec_xonly = system::ec_xonly; @@ -575,8 +577,8 @@ class query const ec_signature& signature, const header_link& link) NOEXCEPT; bool set_signature(const hash_digest& digest, const ec_compressed& point, const ec_signature& signature, const header_link& link) NOEXCEPT; - bool set_signatures(const hash_digest& digest, const multisig_views& pairs, - uint16_t set, const header_link& link) NOEXCEPT; + bool set_signatures(const hash_digest& digest, const ec_compresseds& keys, + const ec_signatures& sigs, uint16_t set, const header_link& link) NOEXCEPT; /// Confirmation. /// ----------------------------------------------------------------------- diff --git a/include/bitcoin/database/tables/caches/ecdsa.hpp b/include/bitcoin/database/tables/caches/ecdsa.hpp index f0c3ab450..d06014bc2 100644 --- a/include/bitcoin/database/tables/caches/ecdsa.hpp +++ b/include/bitcoin/database/tables/caches/ecdsa.hpp @@ -72,7 +72,7 @@ struct ecdsa }; }; -static_assert(sizeof(system::ecdsa::triple) == schema::ecdsa::minrow); +static_assert(sizeof(system::ecdsa::signatures) == schema::ecdsa::minrow); } // namespace table } // namespace database diff --git a/include/bitcoin/database/tables/caches/multisig.hpp b/include/bitcoin/database/tables/caches/multisig.hpp index 2fe2c5455..70bb8534f 100644 --- a/include/bitcoin/database/tables/caches/multisig.hpp +++ b/include/bitcoin/database/tables/caches/multisig.hpp @@ -78,9 +78,58 @@ struct multisig uint16_t set{}; header::integer header_fk{}; }; + + struct put_ref + : public schema::multisig + { + inline link count() const NOEXCEPT + { + using namespace system; + const auto m = sigs.size(); + const auto n = keys.size(); + + BC_ASSERT(!is_subtract_overflow(n, m)); + BC_ASSERT(!is_add_overflow(n - m, one)); + BC_ASSERT(!is_multiply_overflow(m, add1(n - m))); + return possible_narrow_cast(m * add1(n - m)); + } + + inline bool to_data(flipper& sink) const NOEXCEPT + { + using namespace system; + const auto m = sigs.size(); + const auto n = keys.size(); + constexpr auto max = power2(to_half(byte_bits)); + if (is_zero(m) || is_zero(n) || n > max || m > n) + return false; + + for (size_t sig{}; sig < m; ++sig) + { + for (auto key = sig; key <= n - (m - sig); ++key) + { + sink.write_bytes(digest); + sink.write_bytes(keys.at(key)); + sink.write_bytes(sigs.at(sig)); + sink.write_byte(pack_word(m, n)); + sink.write_little_endian(set); + sink.write_little_endian( + header_fk); + } + } + + BC_ASSERT(!sink || sink.get_write_position() == count() * minrow); + return sink; + } + + const hash_digest& digest; + const system::ec_compresseds& keys; + const system::ec_signatures& sigs; + const uint16_t set{}; + const header::integer header_fk{}; + }; }; -static_assert(sizeof(system::multisig::triple) == schema::multisig::minrow); +static_assert(sizeof(system::multisig::signatures) == schema::multisig::minrow); } // namespace table } // namespace database diff --git a/include/bitcoin/database/tables/caches/schnorr.hpp b/include/bitcoin/database/tables/caches/schnorr.hpp index 3ec478bd5..4c53d3cd1 100644 --- a/include/bitcoin/database/tables/caches/schnorr.hpp +++ b/include/bitcoin/database/tables/caches/schnorr.hpp @@ -72,7 +72,7 @@ struct schnorr }; }; -static_assert(sizeof(system::schnorr::triple) == schema::schnorr::minrow); +static_assert(sizeof(system::schnorr::signatures) == schema::schnorr::minrow); } // namespace table } // namespace database diff --git a/include/bitcoin/database/tables/schema.hpp b/include/bitcoin/database/tables/schema.hpp index 95d62da96..b4ddfe54b 100644 --- a/include/bitcoin/database/tables/schema.hpp +++ b/include/bitcoin/database/tables/schema.hpp @@ -304,9 +304,9 @@ struct multisig system::hash_size + system::ec_compressed_size + system::ec_signature_size + - schema::header::pk + - count_ + // input (within block) correlation counter. - one; // [m|n] pairing merged to one byte (max 16). + one + // [m|n] pairing merged to one byte (max 16). + count_ + // input (within block) correlation counter. + schema::header::pk; static constexpr size_t minrow = minsize; static constexpr size_t size = minsize; static constexpr link count() NOEXCEPT { return 1; } From 745675e2fec3e747f0fde4d8a36e88faedfdf154 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Fri, 5 Jun 2026 16:16:13 -0400 Subject: [PATCH 2/2] Adapt to system name change. --- include/bitcoin/database/tables/caches/ecdsa.hpp | 2 +- include/bitcoin/database/tables/caches/multisig.hpp | 2 +- include/bitcoin/database/tables/caches/schnorr.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/bitcoin/database/tables/caches/ecdsa.hpp b/include/bitcoin/database/tables/caches/ecdsa.hpp index d06014bc2..4cd230e8a 100644 --- a/include/bitcoin/database/tables/caches/ecdsa.hpp +++ b/include/bitcoin/database/tables/caches/ecdsa.hpp @@ -72,7 +72,7 @@ struct ecdsa }; }; -static_assert(sizeof(system::ecdsa::signatures) == schema::ecdsa::minrow); +static_assert(sizeof(system::ecdsa::batch) == schema::ecdsa::minrow); } // namespace table } // namespace database diff --git a/include/bitcoin/database/tables/caches/multisig.hpp b/include/bitcoin/database/tables/caches/multisig.hpp index 70bb8534f..687751220 100644 --- a/include/bitcoin/database/tables/caches/multisig.hpp +++ b/include/bitcoin/database/tables/caches/multisig.hpp @@ -129,7 +129,7 @@ struct multisig }; }; -static_assert(sizeof(system::multisig::signatures) == schema::multisig::minrow); +static_assert(sizeof(system::multisig::batch) == schema::multisig::minrow); } // namespace table } // namespace database diff --git a/include/bitcoin/database/tables/caches/schnorr.hpp b/include/bitcoin/database/tables/caches/schnorr.hpp index 4c53d3cd1..2e35a0785 100644 --- a/include/bitcoin/database/tables/caches/schnorr.hpp +++ b/include/bitcoin/database/tables/caches/schnorr.hpp @@ -72,7 +72,7 @@ struct schnorr }; }; -static_assert(sizeof(system::schnorr::signatures) == schema::schnorr::minrow); +static_assert(sizeof(system::schnorr::batch) == schema::schnorr::minrow); } // namespace table } // namespace database