Skip to content

Commit 4cf6e73

Browse files
committed
bip352: index highest output amount
This enables dust filtering. It has very little overhead.
1 parent 71792e7 commit 4cf6e73

File tree

3 files changed

+30
-17
lines changed

3 files changed

+30
-17
lines changed

src/index/bip352.cpp

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,17 @@ class BIP352Index::DB : public BaseIndex::DB
3737
public:
3838
explicit DB(fs::path file_name, size_t n_cache_size, bool f_memory = false, bool f_wipe = false);
3939

40-
bool WriteSilentPayments(const std::pair<uint256, std::vector<CPubKey>>& tweaks);
40+
bool WriteSilentPayments(const std::pair<uint256, tweak_index_entry>& kv);
4141
};
4242

4343
BIP352Index::DB::DB(fs::path file_name, size_t n_cache_size, bool f_memory, bool f_wipe) :
4444
BaseIndex::DB(gArgs.GetDataDirNet() / "indexes" / file_name, n_cache_size, f_memory, f_wipe)
4545
{}
4646

47-
bool BIP352Index::DB::WriteSilentPayments(const std::pair<uint256, std::vector<CPubKey>>& tweaks)
47+
bool BIP352Index::DB::WriteSilentPayments(const std::pair<uint256, tweak_index_entry>& kv)
4848
{
4949
CDBBatch batch(*this);
50-
batch.Write(std::make_pair(DB_SILENT_PAYMENT_INDEX, tweaks.first), tweaks.second);
50+
batch.Write(std::make_pair(DB_SILENT_PAYMENT_INDEX, kv.first), kv.second);
5151
return WriteBatch(batch);
5252
}
5353

@@ -59,7 +59,7 @@ BIP352Index::BIP352Index(bool cut_through, std::unique_ptr<interfaces::Chain> ch
5959

6060
BIP352Index::~BIP352Index() = default;
6161

62-
bool BIP352Index::GetSilentPaymentKeys(const std::vector<CTransactionRef>& txs, const CBlockUndo& block_undo, std::vector<CPubKey>& tweaked_pub_key_sums) const
62+
bool BIP352Index::GetSilentPaymentKeys(const std::vector<CTransactionRef>& txs, const CBlockUndo& block_undo, tweak_index_entry& index_entry) const
6363
{
6464
assert(txs.size() - 1 == block_undo.vtxundo.size());
6565

@@ -78,6 +78,15 @@ bool BIP352Index::GetSilentPaymentKeys(const std::vector<CTransactionRef>& txs,
7878

7979
std::optional<CPubKey> tweaked_pk = bip352::GetSerializedSilentPaymentsPublicData(tx->vin, coins);
8080
if (tweaked_pk) {
81+
// Used to filter dust. To keep the index small we use only one byte
82+
// and measure in hexasats.
83+
uint8_t max_output_hsat = 0;
84+
for (const CTxOut& txout : tx->vout) {
85+
if (!txout.scriptPubKey.IsPayToTaproot()) continue;
86+
uint8_t output_hsat = txout.nValue > max_dust_threshold ? UINT8_MAX : txout.nValue >> dust_shift;
87+
max_output_hsat = std::max(output_hsat, max_output_hsat);
88+
}
89+
8190
if (m_cut_through) {
8291
// Skip entry if all outputs have been spent.
8392
// This is only effective when the index is generated while
@@ -98,7 +107,7 @@ bool BIP352Index::GetSilentPaymentKeys(const std::vector<CTransactionRef>& txs,
98107
}
99108
if (spent == tx->vout.size()) continue;
100109
}
101-
tweaked_pub_key_sums.emplace_back(tweaked_pk.value());
110+
index_entry.emplace_back(std::make_pair(tweaked_pk.value(), max_output_hsat));
102111
}
103112
}
104113

@@ -129,17 +138,17 @@ bool BIP352Index::CustomAppend(const interfaces::BlockInfo& block)
129138
// Should be impossible on an unpruned node
130139
LogError("Failed to read undo file for %s", GetName());
131140
return false;
132-
}
141+
};
133142

134-
std::vector<CPubKey> tweaked_pub_key_sums;
135-
GetSilentPaymentKeys(block.data->vtx, block_undo, tweaked_pub_key_sums);
143+
tweak_index_entry index_entry;
144+
GetSilentPaymentKeys(block.data->vtx, block_undo, index_entry);
136145

137-
return m_db->WriteSilentPayments(make_pair(block.hash, tweaked_pub_key_sums));
146+
return m_db->WriteSilentPayments(make_pair(block.hash, index_entry));
138147
}
139148

140-
bool BIP352Index::FindSilentPayment(const uint256& block_hash, std::vector<CPubKey>& tweaked_pub_key_sums) const
149+
bool BIP352Index::FindSilentPayment(const uint256& block_hash, tweak_index_entry& index_entry) const
141150
{
142-
return m_db->Read(std::make_pair(DB_SILENT_PAYMENT_INDEX, block_hash), tweaked_pub_key_sums);
151+
return m_db->Read(std::make_pair(DB_SILENT_PAYMENT_INDEX, block_hash), index_entry);
143152
}
144153

145154
BaseIndex::DB& BIP352Index::GetDB() const { return *m_db; }

src/index/bip352.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,13 @@ class BIP352Index final : public BaseIndex
2929
* For each block hash we store and array of transactions. For each
3030
* transaction we store:
3131
* - the tweaked pubkey sum
32+
* - the highest output amount (for dust filtering)
3233
*/
33-
using tweak_index_entry = std::vector<CPubKey>;
34+
using tweak_index_entry = std::vector<std::pair<CPubKey, uint8_t>>;
35+
static constexpr uint8_t dust_shift{4}; // Hexasat
36+
/* Maximum dust threshold that we can filter */
37+
static constexpr CAmount max_dust_threshold{CAmount(UINT8_MAX - 1) << dust_shift};
3438

35-
protected:
3639
class DB;
3740

3841
private:
@@ -46,12 +49,13 @@ class BIP352Index final : public BaseIndex
4649
/**
4750
* Derive the silent payment tweaked public key for every block transaction.
4851
*
52+
*
4953
* @param[in] txs all block transactions
5054
* @param[in] block_undo block undo data
51-
* @param[out] tweaked_pub_key_sums the tweaked public keys, only for transactions that have one
55+
* @param[out] index_entry the tweaked public keys, only for transactions that have one
5256
* @return false if something went wrong
5357
*/
54-
bool GetSilentPaymentKeys(const std::vector<CTransactionRef>& txs, const CBlockUndo& block_undo, std::vector<CPubKey>& tweaked_pub_key_sums) const;
58+
bool GetSilentPaymentKeys(const std::vector<CTransactionRef>& txs, const CBlockUndo& block_undo, tweak_index_entry& index_entry) const;
5559

5660
protected:
5761
bool CustomAppend(const interfaces::BlockInfo& block) override;
@@ -64,7 +68,7 @@ class BIP352Index final : public BaseIndex
6468
// Destructor is declared because this class contains a unique_ptr to an incomplete type.
6569
virtual ~BIP352Index() override;
6670

67-
bool FindSilentPayment(const uint256& block_hash, std::vector<CPubKey>& tweaked_pub_key_sums) const;
71+
bool FindSilentPayment(const uint256& block_hash, tweak_index_entry& index_entry) const;
6872
};
6973

7074
/// The global BIP325 index. May be null.

src/rpc/blockchain.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,7 @@ static RPCHelpMan getsilentpaymentblockdata()
771771
UniValue tweaks_res(UniValue::VARR);
772772

773773
for (const auto& entry : tweak_index_entry) {
774-
tweaks_res.push_back(HexStr(entry));
774+
tweaks_res.push_back(HexStr(entry.first));
775775
}
776776

777777
ret.pushKV("bip352_tweaks", tweaks_res);

0 commit comments

Comments
 (0)