diff --git a/Makefile.am b/Makefile.am
index 8919ab88..08b846fc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -137,7 +137,6 @@ test_libbitcoin_database_test_SOURCES = \
test/tables/archives/txs.cpp \
test/tables/caches/duplicate.cpp \
test/tables/caches/ecdsa.cpp \
- test/tables/caches/multisig.cpp \
test/tables/caches/prevout.cpp \
test/tables/caches/schnorr.cpp \
test/tables/caches/validated_bk.cpp \
@@ -331,7 +330,6 @@ include_bitcoin_database_tables_cachesdir = ${includedir}/bitcoin/database/table
include_bitcoin_database_tables_caches_HEADERS = \
include/bitcoin/database/tables/caches/duplicate.hpp \
include/bitcoin/database/tables/caches/ecdsa.hpp \
- include/bitcoin/database/tables/caches/multisig.hpp \
include/bitcoin/database/tables/caches/prevout.hpp \
include/bitcoin/database/tables/caches/schnorr.hpp \
include/bitcoin/database/tables/caches/validated_bk.hpp \
diff --git a/builds/msvc/vs2022/libbitcoin-database-test/libbitcoin-database-test.vcxproj b/builds/msvc/vs2022/libbitcoin-database-test/libbitcoin-database-test.vcxproj
index 2bf28919..a2f8dcbe 100644
--- a/builds/msvc/vs2022/libbitcoin-database-test/libbitcoin-database-test.vcxproj
+++ b/builds/msvc/vs2022/libbitcoin-database-test/libbitcoin-database-test.vcxproj
@@ -194,7 +194,6 @@
-
diff --git a/builds/msvc/vs2022/libbitcoin-database-test/libbitcoin-database-test.vcxproj.filters b/builds/msvc/vs2022/libbitcoin-database-test/libbitcoin-database-test.vcxproj.filters
index fa19d2bc..659bc9bc 100644
--- a/builds/msvc/vs2022/libbitcoin-database-test/libbitcoin-database-test.vcxproj.filters
+++ b/builds/msvc/vs2022/libbitcoin-database-test/libbitcoin-database-test.vcxproj.filters
@@ -270,9 +270,6 @@
src\tables\caches
-
- src\tables\caches
-
src\tables\caches
diff --git a/builds/msvc/vs2022/libbitcoin-database/libbitcoin-database.vcxproj b/builds/msvc/vs2022/libbitcoin-database/libbitcoin-database.vcxproj
index 45db2b54..2f587bb8 100644
--- a/builds/msvc/vs2022/libbitcoin-database/libbitcoin-database.vcxproj
+++ b/builds/msvc/vs2022/libbitcoin-database/libbitcoin-database.vcxproj
@@ -184,7 +184,6 @@
-
diff --git a/builds/msvc/vs2022/libbitcoin-database/libbitcoin-database.vcxproj.filters b/builds/msvc/vs2022/libbitcoin-database/libbitcoin-database.vcxproj.filters
index f6ff8ec2..77f13be8 100644
--- a/builds/msvc/vs2022/libbitcoin-database/libbitcoin-database.vcxproj.filters
+++ b/builds/msvc/vs2022/libbitcoin-database/libbitcoin-database.vcxproj.filters
@@ -269,9 +269,6 @@
include\bitcoin\database\tables\caches
-
- include\bitcoin\database\tables\caches
-
include\bitcoin\database\tables\caches
diff --git a/builds/msvc/vs2026/libbitcoin-database-test/libbitcoin-database-test.vcxproj b/builds/msvc/vs2026/libbitcoin-database-test/libbitcoin-database-test.vcxproj
index 63efd201..88e6e91a 100644
--- a/builds/msvc/vs2026/libbitcoin-database-test/libbitcoin-database-test.vcxproj
+++ b/builds/msvc/vs2026/libbitcoin-database-test/libbitcoin-database-test.vcxproj
@@ -194,7 +194,6 @@
-
diff --git a/builds/msvc/vs2026/libbitcoin-database-test/libbitcoin-database-test.vcxproj.filters b/builds/msvc/vs2026/libbitcoin-database-test/libbitcoin-database-test.vcxproj.filters
index fa19d2bc..659bc9bc 100644
--- a/builds/msvc/vs2026/libbitcoin-database-test/libbitcoin-database-test.vcxproj.filters
+++ b/builds/msvc/vs2026/libbitcoin-database-test/libbitcoin-database-test.vcxproj.filters
@@ -270,9 +270,6 @@
src\tables\caches
-
- src\tables\caches
-
src\tables\caches
diff --git a/builds/msvc/vs2026/libbitcoin-database/libbitcoin-database.vcxproj b/builds/msvc/vs2026/libbitcoin-database/libbitcoin-database.vcxproj
index 6f098d2d..552d67c6 100644
--- a/builds/msvc/vs2026/libbitcoin-database/libbitcoin-database.vcxproj
+++ b/builds/msvc/vs2026/libbitcoin-database/libbitcoin-database.vcxproj
@@ -184,7 +184,6 @@
-
diff --git a/builds/msvc/vs2026/libbitcoin-database/libbitcoin-database.vcxproj.filters b/builds/msvc/vs2026/libbitcoin-database/libbitcoin-database.vcxproj.filters
index f6ff8ec2..77f13be8 100644
--- a/builds/msvc/vs2026/libbitcoin-database/libbitcoin-database.vcxproj.filters
+++ b/builds/msvc/vs2026/libbitcoin-database/libbitcoin-database.vcxproj.filters
@@ -269,9 +269,6 @@
include\bitcoin\database\tables\caches
-
- include\bitcoin\database\tables\caches
-
include\bitcoin\database\tables\caches
diff --git a/include/bitcoin/database.hpp b/include/bitcoin/database.hpp
index 9e5a896b..adc01c08 100644
--- a/include/bitcoin/database.hpp
+++ b/include/bitcoin/database.hpp
@@ -64,7 +64,6 @@
#include
#include
#include
-#include
#include
#include
#include
diff --git a/include/bitcoin/database/query.hpp b/include/bitcoin/database/query.hpp
index 9ba8bbe7..3df9ddae 100644
--- a/include/bitcoin/database/query.hpp
+++ b/include/bitcoin/database/query.hpp
@@ -572,24 +572,35 @@ class query
bool set_tx_connected(const tx_link& link, const context& ctx,
uint64_t fee, size_t sigops) NOEXCEPT;
- /// Set signature (ecdsa/schnorr/multisig) table entry.
+ /// Signature Batching.
+ /// -----------------------------------------------------------------------
+
+ /// Set single ecdsa signature row.
bool set_signature(const hash_digest& digest, const ec_compressed& point,
const ec_signature& signature, uint16_t id,
const header_link& link) NOEXCEPT;
+
+ /// Set single schnorr signature row.
bool set_signature(const hash_digest& digest, const ec_xonly& point,
const ec_signature& signature, uint16_t id,
const header_link& link) NOEXCEPT;
+
+ /// Set ecdsa multisig rows.
bool set_signatures(const hash_digest& digest, const ec_compresseds& keys,
const ec_signatures& sigs, uint16_t id,
const header_link& link) NOEXCEPT;
+
+ /// Set schnorr threshold signature rows.
bool set_signatures(const threshold& batch, uint16_t id,
const header_link& link) NOEXCEPT;
- /// Signature verification.
+ /// Verify all signatures in table.
+ bool verify_ecdsa_signatures(const stopper& cancel, header_links&) NOEXCEPT;
+ bool verify_schnorr_signatures(const stopper& cancel, header_links&) NOEXCEPT;
+
+ /// Purge all signatures in table.
bool purge_ecdsa_signatures() NOEXCEPT;
bool purge_schnorr_signatures() NOEXCEPT;
- bool verify_ecdsa_signatures(const stopper& cancel,header_links&) NOEXCEPT;
- bool verify_schnorr_signatures(const stopper& cancel, header_links&) NOEXCEPT;
/// Confirmation.
/// -----------------------------------------------------------------------
diff --git a/include/bitcoin/database/tables/caches/multisig.hpp b/include/bitcoin/database/tables/caches/multisig.hpp
deleted file mode 100644
index 97c9c57a..00000000
--- a/include/bitcoin/database/tables/caches/multisig.hpp
+++ /dev/null
@@ -1,144 +0,0 @@
-/**
- * Copyright (c) 2011-2026 libbitcoin developers (see AUTHORS)
- *
- * This file is part of libbitcoin.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-#ifndef LIBBITCOIN_DATABASE_TABLES_CACHES_MULTISIG_HPP
-#define LIBBITCOIN_DATABASE_TABLES_CACHES_MULTISIG_HPP
-
-#include
-#include
-#include
-
-namespace libbitcoin {
-namespace database {
-namespace table {
-
-/// multisig is an array of multisig signature validation records.
-struct multisig
- : public no_map
-{
- using header = schema::header::link;
- using no_map::nomap;
-
- struct record
- : public schema::multisig
- {
- inline bool from_data(reader& source) NOEXCEPT
- {
- digest = source.read_hash();
- point = source.read_forward();
- signature = source.read_forward();
- pair = source.read_byte();
- group = source.read_2_bytes_little_endian();
- header_fk = source.read_little_endian();
- BC_ASSERT(!source || source.get_read_position() == minrow);
- return source;
- }
-
- inline bool to_data(flipper& sink) const NOEXCEPT
- {
- sink.write_bytes(digest);
- sink.write_bytes(point);
- sink.write_bytes(signature);
- sink.write_byte(pair);
- sink.write_little_endian(group);
- sink.write_little_endian(header_fk);
- BC_ASSERT(!sink || sink.get_write_position() == minrow);
- return sink;
- }
-
- inline bool operator==(const record& other) const NOEXCEPT
- {
- return digest == other.digest
- && point == other.point
- && signature == other.signature
- && pair == other.pair
- && group == other.group
- && header_fk == other.header_fk;
- }
-
- system::hash_digest digest{};
- system::ec_compressed point{};
- system::ec_signature signature{};
- uint8_t pair{};
- uint16_t group{};
- 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();
- if (is_subtract_overflow(n, m))
- return {};
-
- const auto gap = n - m;
- if (is_add_overflow(gap, one))
- return {};
-
- const auto sum = add1(gap);
- if (is_multiply_overflow(m, sum))
- return {};
-
- // Terminal count fails the write attempt, so to_data() is guarded.
- return possible_narrow_cast(m * sum);
- }
-
- 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(group);
- 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 group{};
- const header::integer header_fk{};
- };
-};
-
-} // namespace table
-} // namespace database
-} // namespace libbitcoin
-
-#endif
diff --git a/include/bitcoin/database/tables/schema.hpp b/include/bitcoin/database/tables/schema.hpp
index 33975d32..0d18c6fb 100644
--- a/include/bitcoin/database/tables/schema.hpp
+++ b/include/bitcoin/database/tables/schema.hpp
@@ -268,7 +268,7 @@ struct ecdsa
system::hash_size +
system::ec_compressed_size +
system::ec_signature_size +
- one + // [m|n] in one byte (m in first row, n in second).
+ one + // [m|n] packed 16x16 in one byte in first row.
count_ + // input (within block) correlation counter.
schema::header::pk;
static constexpr size_t minrow = minsize;
@@ -288,7 +288,7 @@ struct schnorr
system::hash_size +
system::ec_xonly_size +
system::ec_signature_size +
- one + // category (see system::chain::signatures::category).
+ one + // to_value(system::chain::signatures::category).
two + // [min|max] in two bytes (min in first row, max in second).
count_ + // input (within block) correlation counter.
schema::header::pk;
@@ -300,26 +300,6 @@ struct schnorr
static_assert(link::size == 4u);
};
-// array
-struct multisig
-{
- static constexpr size_t pk = schema::outs::pk;
- using link = schema::outs::link;
- static constexpr size_t minsize =
- system::hash_size +
- system::ec_compressed_size +
- system::ec_signature_size +
- 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; }
- static_assert(minsize == 135u);
- static_assert(minrow == 135u);
- static_assert(link::size == 4u);
-};
-
// record hashmap
struct duplicate
{
diff --git a/test/tables/caches/multisig.cpp b/test/tables/caches/multisig.cpp
deleted file mode 100644
index 6ea77262..00000000
--- a/test/tables/caches/multisig.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/**
- * Copyright (c) 2011-2026 libbitcoin developers (see AUTHORS)
- *
- * This file is part of libbitcoin.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-#include "../../test.hpp"
-#include "../../mocks/chunk_storage.hpp"
-
-BOOST_AUTO_TEST_SUITE(multisig_tests)
-
-using namespace system;
-
-const table::multisig::record record1
-{
- {},
- base16_hash("1111111111111111111111111111111111111111111111111111111111111111"),
- base16_array("222222222222222222222222222222222222222222222222222222222222222222"),
- base16_array("33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333"),
- 0xcd_u8,
- 0xbbaa_u16,
- 0x00345678_u32
-};
-
-const table::multisig::record record2
-{
- {},
- base16_hash("4444444444444444444444444444444444444444444444444444444444444444"),
- base16_array("555555555555555555555555555555555555555555555555555555555555555555"),
- base16_array("66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666"),
- 0x89_u8,
- 0x3412_u16,
- 0x00cdef12_u32
-};
-
-const auto expected_head = base16_chunk("00000000");
-const auto closed_head = base16_chunk("02000000");
-const auto expected_body = base16_chunk
-(
- // record 1
- "1111111111111111111111111111111111111111111111111111111111111111"
- "222222222222222222222222222222222222222222222222222222222222222222"
- "33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333"
- "cdaabb785634"
-
- // record 2
- "4444444444444444444444444444444444444444444444444444444444444444"
- "555555555555555555555555555555555555555555555555555555555555555555"
- "66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666"
- "89123412efcd"
-);
-
-BOOST_AUTO_TEST_CASE(multisig__put__two__expected)
-{
- test::chunk_storage head_store{};
- test::chunk_storage body_store{};
- table::multisig instance{ head_store, body_store };
- BOOST_REQUIRE(instance.create());
-
- table::multisig::link link1{};
- BOOST_REQUIRE(instance.put_link(link1, record1));
- BOOST_REQUIRE_EQUAL(link1, 0u);
-
- table::multisig::link link2{};
- BOOST_REQUIRE(instance.put_link(link2, record2));
- BOOST_REQUIRE_EQUAL(link2, 1u);
-
- BOOST_REQUIRE_EQUAL(head_store.buffer(), expected_head);
- BOOST_REQUIRE_EQUAL(body_store.buffer(), expected_body);
- BOOST_REQUIRE(instance.close());
- BOOST_REQUIRE_EQUAL(head_store.buffer(), closed_head);
-}
-
-BOOST_AUTO_TEST_CASE(multisig__get__two__expected)
-{
- auto head = expected_head;
- auto body = expected_body;
- test::chunk_storage head_store{ head };
- test::chunk_storage body_store{ body };
- table::multisig instance{ head_store, body_store };
- BOOST_REQUIRE_EQUAL(head_store.buffer(), expected_head);
- BOOST_REQUIRE_EQUAL(body_store.buffer(), expected_body);
-
- table::multisig::record out{};
- BOOST_REQUIRE(instance.get(0u, out));
- BOOST_REQUIRE(out == record1);
- BOOST_REQUIRE(instance.get(1u, out));
- BOOST_REQUIRE(out == record2);
-}
-
-BOOST_AUTO_TEST_SUITE_END()