1
dev/bloom
TomZ edited this page 2024-02-27 16:10:40 +01:00

The bloom filter is used by the Wallet in order to request updates from full nodes over the p2p network.

It is therefore important to always have a correct and up-to-date filter registered with each peer we are connected to. At the same time we don't want to send a new filter every single time something changes. Between this being a waste of bandwidth, it also is pretty bad for our privacy.

So we need to be a bit fuzzy when it comes to the number of addresses we need to register.

Approach;

rebuildBloom() adds

  • all unspent transaction-outputs
  • all change addresses that have money on them.
  • 80 change addresses that are in line to receive money.
    • add 50 to that number of the wallet has cash fusions.
  • All 'main' addresses we've received on.
  • An extra 200 main addresses we haven't used yet.
  • in case of a non-hd wallet; all non-empty addresses and 40 extra addresses.

The take-away here is that the 'gap' for a HD wallet is at minimum 50, or could be 130.

When transactions come in that use those addresses, two things can happen:

  1. The 'gap' between what we sent in a bloom filter and what already is used by transactions we received gets smaller and we might have to send a new bloom filter with new addresses to avoid missing matching transactions.
  2. The wallet may run out of private keys pre-generated and we might need to create more in order to find all the funds in the transactions we have.

Both are the implicit effect of us not updating the bloom filter every change.

The question is, can we deal with that properly and only upload the filter only when needed.

When we we need to upload?

First, the obvious, when a transaction is found that deposits money into one of our matching addresses. We need the server to know that in order to detect that UTXO being spent. Good news, then! This is part of the bloom filter concept and the server will update the filter automatically inserting those UTXOs into the server side filter.

Downside here is that if we receive too many false-positives (transactions that don't actually match our private keys) we should consider force-sending a new bloom filter to remove for the server all those UTXOs that are not actually for us. [m_bloomFilterMisses]

Second, when the incoming transactions deposit money on private keys for the first time, this makes the number of unused, or gap, keys lower in the filter that is known at the server. The maybeRebuildBloom() method checks those gaps after every successful insertion of a transaction. If the gaps are too low, we create the new bloom.

The last reason is a bit more complex.
Downloads happen in the p2plib that Flowee Pay uses and the p2p download happens from more than one peer. When one peer downloaded and then we switch to another peer that starts downloading, we need to make sure that the new peer has an up-to-date filter. Now, when no matching transactions were actually received from the first peer that means that the filter uploaded earlier to the new peer is still completely valid. The event of switching to a new peer is seen on the Wallet as a call to the virtual method rebuildFilter(), part of the DataListenerInterface. This