Skip to content

add silent payments prevouts_summarys table#804

Open
josibake wants to merge 4 commits into
libbitcoin:masterfrom
josibake:add-silent-payments-prevout-summaries-table
Open

add silent payments prevouts_summarys table#804
josibake wants to merge 4 commits into
libbitcoin:masterfrom
josibake:add-silent-payments-prevout-summaries-table

Conversation

@josibake
Copy link
Copy Markdown
Contributor

@josibake josibake commented Jun 1, 2026

This adds a table for silent payments prevout summary objects. I'm using the terminology from the libsecp module as I feel its the best description for what this data is.

I mostly copied the design from the compact filters table as they seemed conceptually similar. I've tried to add good tests where reasonable, but might add more/move some to other layers if it makes sense.

Depends on:

Comment thread include/bitcoin/database/impl/query/consensus/consensus_forks.ipp Outdated
Comment thread include/bitcoin/database/impl/query/consensus/consensus_forks.ipp Outdated
Comment thread include/bitcoin/database/impl/query/consensus/consensus_strong.ipp Outdated
Comment thread include/bitcoin/database/tables/optionals/sp_prevout_summaries.hpp Outdated
Comment thread include/bitcoin/database/impl/query/sp_prevout_summaries.ipp Outdated
Comment thread Makefile.am
Comment thread test/query/sp_prevout_summaries.cpp Outdated
Comment thread test/query/sp_prevout_summaries.cpp Outdated
Comment thread test/query/sp_prevout_summaries.cpp Outdated
Comment thread test/query/sp_prevout_summaries.cpp Outdated
josibake added 4 commits June 3, 2026 12:14
add the optional silent table for indexing and storing the prevout summaries
needed for scanning.

the confirmed block writer aggregates these by block, but the
construction is at the transaction level. this allows us to use this for
unconfirmed transactions later, once its decided how they should be stored.
add settings, store lifecycle plumbing, extent reporting, and
start-height configuration for the silent payment index.

start height defaults to taproot activation, but is configurable for the
personal server usecase: if the server is supporting a single wallet
where the client knows the wallet birthdate, they should build the index
starting from the wallet birthdate, not taproot activation.
build and read per-block silent payment scan records from populated prevouts.
require configured optional indexes, including silent payment scan data,
before validated candidates are returned for confirmation.
@josibake josibake force-pushed the add-silent-payments-prevout-summaries-table branch from fcd10ab to 629b78a Compare June 3, 2026 10:22
@josibake
Copy link
Copy Markdown
Contributor Author

josibake commented Jun 3, 2026

Feedback addressed (unless I missed something) and updated to use the new libbitcoin-system refactor. Thanks for the review, I am much happier with how this looks, though I will pour one out for the 11% speedup.

@josibake josibake changed the title add silent payments prevout summaries table add silent payments prevouts_summarys table Jun 3, 2026
while (is_block_validated(ec, link, height, top_checkpoint) &&
(!filter || is_filtered_body(link)))
(!filter || is_filtered_body(link)) &&
(!silent || height < silent_start || is_silent_indexed(link)))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that both filter and silent index states should not be checked here. The filter check may be an impl artifact. See chaser_validate:

    // Valid must be set after set_prevouts and set_filter_body.
    if (!bypass && !query.set_block_valid(link))
        return error::validate8;

The block cannot be in a validated state without the filter having been set. If for some reason these are set and validation did not get set, then these would just get set again - but logically I don't believe that's possible due to node design without a hard fault/stop. Please remove both of these and verify behavior.

// silent
// ----------------------------------------------------------------------------

namespace payment = system::wallet::silent_payment;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid global (in this case database::) namespace pollution. These are insidious, so just be cognizant that an IPP is a header.

}

TEMPLATE
bool CLASS::set_silent(silent& out, const tx_link& link,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set_silent() is a misnomer in database, as it does not write to a table. This is actually an accumulating get.


namespace payment = system::wallet::silent_payment;

static inline bool to_silent_record(silent_record& out,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a query/store method misnomer. All of the to_ methods should be simple link translations. This is actually a get.


namespace payment = system::wallet::silent_payment;

static inline bool to_silent_record(silent_record& out,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid global (database::) namespace pollution. This should be a member of query.

Comment thread src/settings.cpp
silent_buckets{ 128 },
silent_size{ 1 },
silent_rate{ 50 },
silent_start_height{ 0 }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of these things looks not like the others. We should find a better way.

Comment thread test/query/silent.cpp
BOOST_REQUIRE_EQUAL(actual.records.size(), 1u);
BOOST_REQUIRE(actual.records.front().tx == tx);
BOOST_REQUIRE_EQUAL(actual.records.front().prevouts_summary,
expected_prevouts_summary);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style, no wrap

Comment thread test/query/silent.cpp
BOOST_REQUIRE_EQUAL(actual.records.size(), 1u);
BOOST_REQUIRE(actual.records.front().tx == txs[1]);
BOOST_REQUIRE_EQUAL(actual.records.front().prevouts_summary,
expected_block_prevouts_summary);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style, could use shorter name, or just leave it.

Comment thread test/query/silent.cpp
BOOST_REQUIRE_EQUAL(actual.records.size(), 1u);
BOOST_REQUIRE(actual.records.front().tx == txs[1]);
BOOST_REQUIRE_EQUAL(actual.records.front().prevouts_summary,
expected_block_prevouts_summary);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style.

Comment thread test/query/silent.cpp
const auto link = query.to_header(spend.hash());
const auto txs = query.to_transactions(link);
BOOST_REQUIRE_EQUAL(txs.size(), 2u);
const auto& spend_tx = *spend.transactions_ptr()->at(1);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style (macro sammich).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants