Skip to content

Commit

Permalink
Merge 7ac3bdb into 872a26a
Browse files Browse the repository at this point in the history
  • Loading branch information
evoskuil committed Apr 28, 2024
2 parents 872a26a + 7ac3bdb commit 04cb8e6
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 58 deletions.
67 changes: 62 additions & 5 deletions include/bitcoin/database/impl/query/archive.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,45 @@ typename CLASS::transactions_ptr CLASS::get_transactions(
return transactions;
}

TEMPLATE
size_t CLASS::get_candidate_size() const NOEXCEPT
{
return get_candidate_size(get_top_candidate());
}

TEMPLATE
size_t CLASS::get_candidate_size(size_t top) const NOEXCEPT
{
size_t wire{};
for (auto height = zero; height <= top; ++height)
wire += get_block_size(to_candidate(height));

return wire;
}

TEMPLATE
size_t CLASS::get_confirmed_size() const NOEXCEPT
{
return get_confirmed_size(get_top_confirmed());
}

TEMPLATE
size_t CLASS::get_confirmed_size(size_t top) const NOEXCEPT
{
size_t wire{};
for (auto height = zero; height <= top; ++height)
wire += get_block_size(to_confirmed(height));

return wire;
}

TEMPLATE
size_t CLASS::get_block_size(const header_link& link) const NOEXCEPT
{
table::txs::get_block_size txs{};
return store_.txs.get(to_txs_link(link), txs) ? txs.wire : zero;
}

TEMPLATE
typename CLASS::header::cptr CLASS::get_header(
const header_link& link) const NOEXCEPT
Expand Down Expand Up @@ -754,6 +793,20 @@ tx_link CLASS::set_link(const transaction& tx) NOEXCEPT
return {};
}

////// Commit addresses to search.
////auto out_fk = puts.out_fks.begin();
////for (const auto& out: outs)
////{
//// if (!store_.address.put(address_hash(*out), table::address::record
//// {
//// {},
//// *out_fk++
//// }))
//// {
//// return {};
//// }
////}

// Commit tx to search.
return store_.tx.commit_link(tx_fk, key);
// ========================================================================
Expand Down Expand Up @@ -821,7 +874,8 @@ header_link CLASS::set_link(const block& block, const context& ctx) NOEXCEPT
const auto header_fk = set_link(block.header(), ctx);

// Returns txs::link so translate to header::link.
if (set_link(*block.transactions_ptr(), header_fk).is_terminal())
if (set_link(*block.transactions_ptr(), header_fk,
block.serialized_size(true)).is_terminal())
return {};

return header_fk;
Expand All @@ -836,15 +890,16 @@ header_link CLASS::set_link(const block& block) NOEXCEPT
return {};

// Returns txs::link so translate to header::link.
if (set_link(*block.transactions_ptr(), header_fk).is_terminal())
if (set_link(*block.transactions_ptr(), header_fk,
block.serialized_size(true)).is_terminal())
return {};

return header_fk;
}

TEMPLATE
txs_link CLASS::set_link(const transactions& txs,
const header_link& link) NOEXCEPT
const header_link& link, size_t size) NOEXCEPT
{
if (link.is_terminal())
return{};
Expand All @@ -863,12 +918,14 @@ txs_link CLASS::set_link(const transactions& txs,
if (!push_link_value(links, set_link(*tx)))
return {};

using bytes = linkage<schema::size>::integer;
const auto wire = system::possible_narrow_cast<bytes>(size);
const auto malleable = block::is_malleable64(txs);

// ========================================================================
const auto scope = store_.get_transactor();

return store_.txs.put_link(link, table::txs::slab{ {}, malleable, links });
return store_.txs.put_link(link, table::txs::slab{ {}, malleable, wire, links });
// ========================================================================
}

Expand All @@ -883,7 +940,7 @@ bool CLASS::dissasociate(const header_link& link) NOEXCEPT
// ========================================================================
const auto scope = store_.get_transactor();

return store_.txs.put_link(link, table::txs::slab{ {}, malleable, {} });
return store_.txs.put_link(link, table::txs::slab{ {}, malleable, {}, {} });
// ========================================================================
}

Expand Down
9 changes: 7 additions & 2 deletions include/bitcoin/database/query.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,11 @@ class query
outputs_ptr get_outputs(const tx_link& link) const NOEXCEPT;
transactions_ptr get_transactions(const header_link& link) const NOEXCEPT;

size_t get_candidate_size() const NOEXCEPT;
size_t get_candidate_size(size_t top) const NOEXCEPT;
size_t get_confirmed_size() const NOEXCEPT;
size_t get_confirmed_size(size_t top) const NOEXCEPT;
size_t get_block_size(const header_link& link) const NOEXCEPT;
header::cptr get_header(const header_link& link) const NOEXCEPT;
block::cptr get_block(const header_link& link) const NOEXCEPT;
transaction::cptr get_transaction(const tx_link& link) const NOEXCEPT;
Expand All @@ -281,7 +286,8 @@ class query
header_link set_link(const block& block, const chain_context& ctx) NOEXCEPT;
header_link set_link(const block& block, const context& ctx) NOEXCEPT;
header_link set_link(const block& block) NOEXCEPT;
txs_link set_link(const transactions& txs, const header_link& link) NOEXCEPT;
txs_link set_link(const transactions& txs, const header_link& link,
size_t size) NOEXCEPT;
tx_link set_link(const transaction& tx) NOEXCEPT;
bool dissasociate(const header_link& link) NOEXCEPT;

Expand Down Expand Up @@ -474,7 +480,6 @@ class query
const header_link& link, size_t height) const NOEXCEPT;

private:
// for to_blocks
using block_tx = table::strong_tx::record;
using block_txs = std::vector<block_tx>;
static inline header_links strong_only(const block_txs& strongs) NOEXCEPT;
Expand Down
24 changes: 21 additions & 3 deletions include/bitcoin/database/tables/archives/txs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct txs
{
using tx = linkage<schema::tx>;
using keys = std_vector<tx::integer>;
using bytes = linkage<schema::size>;
using hash_map<schema::txs>::hashmap;

struct slab
Expand All @@ -44,13 +45,14 @@ struct txs
link count() const NOEXCEPT
{
return system::possible_narrow_cast<link::integer>(pk + sk +
schema::bit + schema::count_ + tx::size * tx_fks.size());
schema::count_ + schema::bit + bytes::size +tx::size * tx_fks.size());
}

inline bool from_data(reader& source) NOEXCEPT
{
tx_fks.resize(source.read_little_endian<tx::integer, schema::count_>());
malleable = to_bool(source.read_byte());
wire = source.read_little_endian<bytes::integer, bytes::size>();
std::for_each(tx_fks.begin(), tx_fks.end(), [&](auto& fk) NOEXCEPT
{
fk = source.read_little_endian<tx::integer, tx::size>();
Expand All @@ -67,6 +69,7 @@ struct txs

sink.write_little_endian<tx::integer, schema::count_>(fks);
sink.write_byte(to_int<uint8_t>(malleable));
sink.write_little_endian<bytes::integer, bytes::size>(wire);
std::for_each(tx_fks.begin(), tx_fks.end(), [&](const auto& fk) NOEXCEPT
{
sink.write_little_endian<tx::integer, tx::size>(fk);
Expand All @@ -82,6 +85,7 @@ struct txs
}

bool malleable{ false };
bytes::integer wire{}; // block.serialized_size(true)
keys tx_fks{};
};

Expand All @@ -91,7 +95,7 @@ struct txs
inline bool from_data(reader& source) NOEXCEPT
{
const auto count = source.read_little_endian<tx::integer, schema::count_>();
source.skip_byte();
source.skip_bytes(schema::bit + bytes::size);
for (position = zero; position < count; ++position)
if (source.read_little_endian<tx::integer, tx::size>() == link)
return source;
Expand All @@ -110,7 +114,7 @@ struct txs
inline bool from_data(reader& source) NOEXCEPT
{
const auto count = source.read_little_endian<tx::integer, schema::count_>();
source.skip_byte();
source.skip_bytes(schema::bit + bytes::size);
if (!is_zero(count))
{
coinbase_fk = source.read_little_endian<tx::integer, tx::size>();
Expand All @@ -131,12 +135,26 @@ struct txs
{
source.skip_bytes(schema::count_);
malleable = to_bool(source.read_byte());
source.skip_bytes(bytes::size);
return source;
}

bool malleable{};
};

struct get_block_size
: public schema::txs
{
inline bool from_data(reader& source) NOEXCEPT
{
source.skip_bytes(schema::count_ + schema::bit);
wire = source.read_little_endian<bytes::integer, bytes::size>();
return source;
}

bytes::integer wire{};
};

struct get_associated
: public schema::txs
{
Expand Down
9 changes: 5 additions & 4 deletions include/bitcoin/database/tables/schema.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ namespace schema
constexpr size_t puts_ = 5; // ->puts record.
constexpr size_t spend_ = 4; // ->spend record.
constexpr size_t point_ = 4; // ->point record.
constexpr size_t txs_ = 4; // ->txs slab.
constexpr size_t txs_ = 5; // ->txs slab.
constexpr size_t tx = 4; // ->tx record.
constexpr size_t block = 3; // ->header record.
constexpr size_t bk_slab = 3; // ->validated_bk record.
Expand Down Expand Up @@ -252,12 +252,13 @@ namespace schema
static constexpr size_t sk = schema::header::pk;
static constexpr size_t minsize =
count_ + // txs
bit + // mutable
bit + // malleable (could compress with size)
schema::size + // block.serialized_size(true) (could be variable)
transaction::pk; // coinbase
static constexpr size_t minrow = pk + sk + minsize;
static constexpr size_t size = max_size_t;
static_assert(minsize == 8u);
static_assert(minrow == 15u);
static_assert(minsize == 11u);
static_assert(minrow == 19u);
};

/// Index tables.
Expand Down
95 changes: 61 additions & 34 deletions test/query/archive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,22 +536,24 @@ BOOST_AUTO_TEST_CASE(query_archive__set_block__get_block__expected)
"4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73" // script
"00"); // witness
const auto genesis_txs_head = system::base16_chunk(
"0f000000" // slabs size
"00000000" // pk->
"ffffffff"
"ffffffff"
"ffffffff"
"ffffffff"
"ffffffff"
"ffffffff"
"ffffffff"
"ffffffff"
"ffffffff");
"1300000000" // slabs size
"0000000000" // pk->
"ffffffffff"
"ffffffffff"
"ffffffffff"
"ffffffffff"
"ffffffffff"
"ffffffffff"
"ffffffffff"
"ffffffffff"
"ffffffffff");
const auto genesis_txs_body = system::base16_chunk(
"ffffffff" // next->
"000000" // header_fk
"01000000" // txs count (1)
"00000000"); // transaction[0]
"ffffffffff" // next->
"000000" // header_fk
"010000" // txs count (1)
"00" // txs malleable (false)
"1d0100" // txs wire (285)
"00000000"); // transaction[0]

settings settings{};
settings.header_buckets = 5;
Expand Down Expand Up @@ -644,7 +646,7 @@ BOOST_AUTO_TEST_CASE(query_archive__set_block_txs__get_block__expected)
"01000000" // version
"010000" // ins_count
"010000" // outs_count
"0000000000"); // puts_fk->
"0000000000"); // puts_fk->
const auto genesis_puts_head = system::base16_chunk("0900000000");
const auto genesis_puts_body = system::base16_chunk(
"00000000" // spend0_fk->
Expand Down Expand Up @@ -684,22 +686,24 @@ BOOST_AUTO_TEST_CASE(query_archive__set_block_txs__get_block__expected)
"4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73" // script
"00"); // witness
const auto genesis_txs_head = system::base16_chunk(
"0f000000" // slabs size
"00000000" // pk->
"ffffffff"
"ffffffff"
"ffffffff"
"ffffffff"
"ffffffff"
"ffffffff"
"ffffffff"
"ffffffff"
"ffffffff");
"1300000000" // slabs size
"0000000000" // pk->
"ffffffffff"
"ffffffffff"
"ffffffffff"
"ffffffffff"
"ffffffffff"
"ffffffffff"
"ffffffffff"
"ffffffffff"
"ffffffffff");
const auto genesis_txs_body = system::base16_chunk(
"ffffffff" // next->
"000000" // header_fk
"01000000" // txs count (1)
"00000000"); // transaction[0]
"ffffffffff" // next->
"000000" // header_fk
"010000" // txs count (1)
"00" // txs malleable (false)
"1d0100" // txs wire (285)
"00000000"); // transaction[0]

settings settings{};
settings.header_buckets = 5;
Expand Down Expand Up @@ -999,9 +1003,9 @@ BOOST_AUTO_TEST_CASE(query_archive__is_malleable__malleable__true)
BOOST_REQUIRE(query.is_malleated(block3));

// Reassociate the same transaction sets (first(n), disassociated (0), second(n))
BOOST_REQUIRE(!query.set_link(*block1.transactions_ptr(), 1).is_terminal());
BOOST_REQUIRE(!query.set_link(*block2.transactions_ptr(), 2).is_terminal());
BOOST_REQUIRE(!query.set_link(*block3.transactions_ptr(), 3).is_terminal());
BOOST_REQUIRE(!query.set_link(*block1.transactions_ptr(), 1, block1.serialized_size(true)).is_terminal());
BOOST_REQUIRE(!query.set_link(*block2.transactions_ptr(), 2, block2.serialized_size(false)).is_terminal());
BOOST_REQUIRE(!query.set_link(*block3.transactions_ptr(), 3, block3.serialized_size(true)).is_terminal());

// Verify all 3 are reassociated.
BOOST_REQUIRE(query.is_associated(1));
Expand All @@ -1017,6 +1021,29 @@ BOOST_AUTO_TEST_CASE(query_archive__is_malleable__malleable__true)
BOOST_REQUIRE(query.is_malleated(block1));
BOOST_REQUIRE(query.is_malleated(block2));
BOOST_REQUIRE(query.is_malleated(block3));

// Verify stored block sizes.
BOOST_REQUIRE_EQUAL(query.get_block_size(0), test::genesis.serialized_size(true));
BOOST_REQUIRE_EQUAL(query.get_block_size(1), block1.serialized_size(true));
BOOST_REQUIRE_EQUAL(query.get_block_size(2), block2.serialized_size(false));
BOOST_REQUIRE_EQUAL(query.get_block_size(3), block3.serialized_size(true));

// Verify confirmed wire size.
BOOST_REQUIRE_EQUAL(query.get_confirmed_size(), test::genesis.serialized_size(true));
BOOST_REQUIRE_EQUAL(query.get_confirmed_size(0), test::genesis.serialized_size(true));
BOOST_REQUIRE_EQUAL(query.get_confirmed_size(1), test::genesis.serialized_size(true));
BOOST_REQUIRE_EQUAL(query.get_confirmed_size(42), test::genesis.serialized_size(true));

const auto candidate_size = test::genesis.serialized_size(true) + block1.serialized_size(true) + block2.serialized_size(false) + block3.serialized_size(true);

// Verify candidate wire size.
BOOST_REQUIRE(query.push_candidate(query.to_header(block1.hash())));
BOOST_REQUIRE(query.push_candidate(query.to_header(block2.hash())));
BOOST_REQUIRE(query.push_candidate(query.to_header(block3.hash())));
BOOST_REQUIRE_EQUAL(query.get_candidate_size(), candidate_size);
BOOST_REQUIRE_EQUAL(query.get_candidate_size(0), test::genesis.serialized_size(true));
BOOST_REQUIRE_EQUAL(query.get_candidate_size(1), test::genesis.serialized_size(true) + block1.serialized_size(true));
BOOST_REQUIRE_EQUAL(query.get_candidate_size(42), candidate_size);
}

BOOST_AUTO_TEST_CASE(query_archive__get_header__invalid_parent__expected)
Expand Down

0 comments on commit 04cb8e6

Please sign in to comment.