Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 29 additions & 40 deletions include/bitcoin/database/impl/query/signatures.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -74,92 +74,81 @@ bool CLASS::purge_schnorr_signatures() NOEXCEPT

TEMPLATE
bool CLASS::set_signature(const hash_digest& digest, const ec_compressed& point,
const ec_signature& signature, const header_link& link) NOEXCEPT
const ec_signature& signature, uint16_t id, const header_link& link) NOEXCEPT
{
// ========================================================================
const auto scope = store_.get_transactor();

// Clean single allocation failure (e.g. disk full).
return store_.ecdsa.put(table::ecdsa::record
return store_.ecdsa.put(table::ecdsa::put_single_ref
{
{},
digest,
point,
signature,
id,
link
});
// ========================================================================

return true;
}

TEMPLATE
bool CLASS::set_signature(const hash_digest& digest, const ec_xonly& point,
const ec_signature& signature, const header_link& link) NOEXCEPT
const ec_signature& signature, uint16_t id, const header_link& link) NOEXCEPT
{
// ========================================================================
const auto scope = store_.get_transactor();

// Clean single allocation failure (e.g. disk full).
return store_.schnorr.put(table::schnorr::record
return store_.schnorr.put(table::schnorr::put_single_ref
{
{},
digest,
point,
signature,
id,
link
});
// ========================================================================

return true;
}

TEMPLATE
bool CLASS::set_signatures(const hash_digest&, const ec_compresseds&,
const ec_signatures&, size_t, const header_link&) NOEXCEPT
bool CLASS::set_signatures(const hash_digest& digest,
const ec_compresseds& keys, const ec_signatures& sigs, uint16_t id,
const header_link& link) NOEXCEPT
{
// ========================================================================
const auto scope = store_.get_transactor();

// TODO: flatten via store_.ecdsa.put();

////// Clean single allocation failure (e.g. disk full).
////return store_.multisig.put(table::multisig::put_ref
////{
//// {},
//// digest,
//// keys,
//// sigs,
//// group,
//// link
////});
// Clean single allocation failure (e.g. disk full).
return store_.ecdsa.put(table::ecdsa::put_multiple_ref
{
{},
digest,
keys,
sigs,
id,
link
});
// ========================================================================

return true;
}

TEMPLATE
bool CLASS::set_signatures(const threshold& , size_t ,
const header_link& ) NOEXCEPT
bool CLASS::set_signatures(const threshold& batch, uint16_t id,
const header_link& link) NOEXCEPT
{
// ========================================================================
const auto scope = store_.get_transactor();

// TODO: flatten via store_.schnorr.put();

////// Clean single allocation failure (e.g. disk full).
////return store_.multisig.put(table::multisig::put_ref
////{
//// {},
//// digest,
//// keys,
//// sigs,
//// group,
//// link
////});
// Clean single allocation failure (e.g. disk full).
return store_.schnorr.put(table::schnorr::put_multiple_ref
{
{},
batch,
id,
link
});
// ========================================================================

return true;
}

} // namespace database
Expand Down
11 changes: 7 additions & 4 deletions include/bitcoin/database/query.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -574,12 +574,15 @@ class query

/// Set signature (ecdsa/schnorr/multisig) table entry.
bool set_signature(const hash_digest& digest, const ec_compressed& point,
const ec_signature& signature, const header_link& link) NOEXCEPT;
const ec_signature& signature, uint16_t id,
const header_link& link) NOEXCEPT;
bool set_signature(const hash_digest& digest, const ec_xonly& point,
const ec_signature& signature, const header_link& link) NOEXCEPT;
const ec_signature& signature, uint16_t id,
const header_link& link) NOEXCEPT;
bool set_signatures(const hash_digest& digest, const ec_compresseds& keys,
const ec_signatures& sigs, size_t set, const header_link& link) NOEXCEPT;
bool set_signatures(const threshold& group, size_t set,
const ec_signatures& sigs, uint16_t id,
const header_link& link) NOEXCEPT;
bool set_signatures(const threshold& batch, uint16_t id,
const header_link& link) NOEXCEPT;

/// Signature verification.
Expand Down
102 changes: 99 additions & 3 deletions include/bitcoin/database/tables/caches/ecdsa.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
namespace libbitcoin {
namespace database {
namespace table {

/// ecdsa is an array of ecdsa signature validation records.
struct ecdsa
: public no_map<schema::ecdsa>
Expand All @@ -37,11 +37,18 @@ struct ecdsa
struct record
: public schema::ecdsa
{
inline link count() const NOEXCEPT
{
return 1;
}

inline bool from_data(reader& source) NOEXCEPT
{
digest = source.read_hash();
point = source.read_forward<system::ec_compressed_size>();
signature = source.read_forward<system::ec_signature_size>();
pair = source.read_byte();
group = source.read_little_endian<uint16_t>();
header_fk = source.read_little_endian<header::integer, header::size>();
BC_ASSERT(!source || source.get_read_position() == minrow);
return source;
Expand All @@ -52,6 +59,8 @@ struct ecdsa
sink.write_bytes(digest);
sink.write_bytes(point);
sink.write_bytes(signature);
sink.write_byte(pair);
sink.write_little_endian<uint16_t>(group);
sink.write_little_endian<header::integer, header::size>(header_fk);
BC_ASSERT(!sink || sink.get_write_position() == minrow);
return sink;
Expand All @@ -62,17 +71,104 @@ struct ecdsa
return digest == other.digest
&& point == other.point
&& signature == other.signature
&& pair == other.pair
&& group == other.group
&& header_fk == other.header_fk;
}

/// pair: m (row 0, for all), n (row 1, for n > 1).
system::hash_digest digest{};
system::ec_compressed point{};
system::ec_signature signature{};
uint8_t pair{};
uint16_t group{};
header::integer header_fk{};
};
};

static_assert(sizeof(system::ecdsa::batch) == schema::ecdsa::minrow);
struct put_single_ref
: public schema::ecdsa
{
inline link count() const NOEXCEPT
{
return 1;
}

/// Writer used for single-sig row, should always write pair = 1.
inline bool to_data(flipper& sink) const NOEXCEPT
{
sink.write_bytes(digest);
sink.write_bytes(point);
sink.write_bytes(signature);
sink.write_byte(0);
sink.write_little_endian<uint16_t>(group);
sink.write_little_endian<header::integer, header::size>(header_fk);
BC_ASSERT(!sink || sink.get_write_position() == minrow);
return sink;
}

/// pair: m (row 0, for all), n (row 1, for n > 1).
const system::hash_digest& digest;
const system::ec_compressed& point;
const system::ec_signature& signature;
uint16_t group{};
header::integer header_fk{};
};

/// Writer for one row multisig, writes as if a single sig.
/// Writer for multisig groups (denormalized m|n in first two rows).
struct put_multiple_ref
: public schema::ecdsa
{
inline link count() const NOEXCEPT
{
using namespace system;
const auto m = sigs.size();
const auto n = keys.size();
const auto gap = n - m;
if (is_subtract_overflow(n, m) || 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<link::integer>(m * sum);
}

inline bool to_data(flipper& sink) const NOEXCEPT
{
using namespace system;
constexpr auto max = power2(to_half(byte_bits));
const auto m = sigs.size();
const auto n = keys.size();
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<uint8_t>(sig, key));
sink.write_little_endian<uint16_t>(group);
sink.write_little_endian<header::integer, header::size>(
header_fk);
}
}

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
Expand Down
2 changes: 0 additions & 2 deletions include/bitcoin/database/tables/caches/multisig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,6 @@ struct multisig
};
};

static_assert(sizeof(system::multisig::batch) == schema::multisig::minrow);

} // namespace table
} // namespace database
} // namespace libbitcoin
Expand Down
Loading
Loading