[WIP] feat: Assume-Valid SwiftSync with accumulator building#1115
[WIP] feat: Assume-Valid SwiftSync with accumulator building#1115JoseSK999 wants to merge 5 commits into
Conversation
| let inv = block_hashes | ||
| .iter() | ||
| .map(|block| Inventory::Block(*block)) | ||
| .map(|block| match witnessless { |
There was a problem hiding this comment.
I think when I wrote this it was more concise this way
| self.send_to_peer( | ||
| peer, | ||
| NodeRequest::GetBlock(vec![header.block_hash()]), | ||
| NodeRequest::GetBlock(vec![header.block_hash()], false), |
There was a problem hiding this comment.
These callsites can become confusing to read without having further context about NodeRequest. I think this is an example of C-CUSTOM-TYPE whereby we should define a new enum (something like WitnessData::Include/Exclude) so the intent is clear from the callsite
| codegen-units = 1 # compile a single codegen unit | ||
|
|
||
| [patch.crates-io] | ||
| rustreexo = { git = "https://github.com/Davidson-Souza/rustreexo.git", branch = "swift-sync" } |
There was a problem hiding this comment.
Not a review comment but this is a cool feature I did not know about
|
The I think we need to harden how we redo inflight requests for this case, need to take a deeper look. |
|
It doesn't recover the swift sync progress after clean shutdown. Also couldn't use the node handle when syncing. |
| /// Pending additions, deletions, and proof for a single accumulator update. | ||
| pub struct StumpUpdate { | ||
| pub adds: Vec<BitcoinNodeHash>, | ||
| pub deletes: Vec<BitcoinNodeHash>, | ||
| pub proof: Proof, | ||
| } |
There was a problem hiding this comment.
You intend to use this with SyncNode as well?
With Swift Sync you can simplify this and send the UTXOs being added + the hints for this block. So you only inflate the zero hashes when processing that block. This should reduce the memory footprint by a lot.
There was a problem hiding this comment.
For sync node we could perhaps make a proof verifier as well, so the pipeline goes:
Proof verifier -> block checker (all but utreexo stuff) -> stump updater.
To feed the proof verifier out of order we can use the get utreexo roots message and fetch roots from peers.
There was a problem hiding this comment.
Yes I made it generic over all the update data needed for Utreexo, because this may be useful outside of SS.
Skipping the zero hashes in the cache is a very good idea! Probably it will eliminate most of the cache data.
There was a problem hiding this comment.
Proof verifier -> block checker (all but utreexo stuff) -> stump updater.
Makes sense because then the stump updater can just apply an infallible operation no? (add UTXOs, remove proved ones)
There was a problem hiding this comment.
Yes I made it generic over all the update data needed for Utreexo, because this may be useful outside of SS.
Maybe you can make an enum to distinguish between Swift Sync and non-swift sync
Probably it will eliminate most of the cache data.
Very likely, the overwhelming majority of TXOs are already spent, so no need to have them there.
There was a problem hiding this comment.
Makes sense because then the stump updater can just apply an infallible operation no?
I'm pretty sure it is.
Edit: And we can have more than one proof checker worker. This is the second most CPU-intensive task for no-assumevalid blocks, after script validation.
There was a problem hiding this comment.
Before checking the proof you need the block anyway no? I was thinking about verifying the proof and block in the same “validation” worker.
It shouldn’t matter if the parallel workers do 2x work, because we will have all workers busy.
Yeah we don't save the agg progress, we would need to save a bitmap for the heights that we have processed and persist the agg. Edit: oh and we need to persist the |
|
~2h on my VPS to sync 🚀🚀🚀 |
|
Sometimes I lose all my peers and just get stuck. |
Do you see logs like “received a block we didn’t request” or similar? Or they simply disconnect? It may be that we over-request to peers. Capping the number of inflight requests per peer may solve it. |
They got banned. But FYI I've increased the max requests to test something. |
Description and Notes
This is a more complete version of #837, as we have Utreexo accumulator building during SwiftSync.
This means your node will perform SwiftSync and build the Utreexo accumulator at the same time, which is cheap thanks to "implicit deletion". After SwiftSync we can finally continue with the usual Utreexo operation, as the UTXO set represented by the accumulator has been verified.
Implicit deletion (implemented in mit-dci/rustreexo#81)
We only need Utreexo proofs (Merkle inclusion proofs) when we need to verify an UTXO exists, and then remove it from the set. Nonetheless, in this case we have SwiftSync hints for spent-ness, so we can delete the hinted-as-spent TXOs at addition time. The later Merkle proof step is skipped entirely, which is a huge bandwidth cut (and avoids hashing to verify the proof).
How to run
You need the hints for the network you intend to run, named
{network}.hints(for example,bitcoin.hintsorsignet.hints), located in the samedatadiras your node uses. Default directory is.florestain the root for mainnet (and.floresta/signet, etc.). Hintsfiles for different networks can be downloaded from the 2140-dev server.For both mainnet and signet you need to run
florestadwith assume-utreexo disabled:florestadfalls back to a fullSyncNodesync (i.e., the full Merkle-proof-heavy and sequential Utreexo sync).StumpUpdater
To keep SwiftSync block processing fully parallel while still producing a
Stump(the accumulator type), we decouple block processing from accumulator updates. The accumulator updates happen in a separate worker, theStumpUpdaterfromstump_updater.rs.StumpUpdaterreceives the UTXO hashes to add, linked to the height they should be applied on. It keeps a cache of pending updates, and enforces the order of updates is sequential.Once we reach the SwiftSync
stop_height(and verify the hints were correct), this worker returns the final computed accumulator, and we continue with the Utreexo-proof mode.