pepper_sync/lib.rs
1#![warn(missing_docs)]
2//! Pepper Sync
3//!
4//! Pepper-sync is a crate providing a sync engine for the zcash network providing the following features:
5//! - Non-linear scanning, allowing chain tip and targetted scanning
6//! - Spend-before-sync, combines the shard roots with high priority chain tip scanning to enable spending of notes as
7//! they are scanned
8//! - Speed, trial decryption and tree building are computed in parallel and a multi-task architecture help maximumise
9//! throughput for fetching and scanning
10//! - Scan by shards, uses subtree metadata to create scan ranges that contain all note commitments to each shard to
11//! enable faster spending of decrypted outputs.
12//! - Fixed memory batching, each scan worker receives a batch with a fixed number of outputs for stable memory usage.
13//! - Pause and resume, the sync engine can be paused to allow the wallet to perform time-critical tasks that would
14//! require the acquisition of the wallet lock multiple times in quick succession.
15//!
16//! Terminology:
17//! - Chain height - highest block height of best chain from the server.
18//! - Wallet height - highest block height of blockchain known to the wallet.
19//! - Fully scanned height - block height in which the wallet has completed scanning all blocks equal to and below this height.
20//! - Shard range - the range of blocks that contain all note commitments to a fully completed shard in the blockchain.
21//!
22//! Initialisation:
23//! 1. For first time sync, creates a single scan range from birthday to chain height.
24//! 2. If synced previously, merge all previously scanned ranges together and create a new scan range from wallet
25//! height to chain height (the part of the chain that has been mined since last sync).
26//! 3. Use locators from transparent address discovery and targetted scanning to set "found note" priority ranges.
27//! 4. Finds the upper range bound of the latest orchard and sapling shard ranges and splits the scan range at the lowest
28//! height of the two, setting the upper scan range to priority "chain tip". This ensures that both the sapling and orchard
29//! note commitments are scanned in the latest incomplete shard at the chain tip.
30//! 5. Set the first 10 blocks after the highest previously scanned blocks to "verify" priority to check for re-org.
31//!
32//! Scanning:
33//! 1. Take the highest priority scan range and split off an orchard shard range off the lower end. setting to "ignored"
34//! (a.k.a scanning) priority and sending this to the "batcher" task.
35//! 2. The batcher takes this scan range (containing all note commitments to an orchard shard) and fetches the compact
36//! blocks, splitting the blocks into multiple batches with a fixed number of outputs.
37//! 3. Each batch is sent to an idle "scan worker" which scans a batch and returns scan results to the main sync process.
38//! 4. When the scan results have been processed the scan range containing the batch of scanned blocks is set to "scanned"
39//! priority.
40//! 5. When a worker is scanning the final batch in a scan range (shard range), the batcher will go idle and the main task
41//! will send it a new scan range of highest priority. it will then send the first batch of this new scan range to an idle
42//! scan worker and the scan process continues until all ranges are scanned.
43//! 6. When scan results are being processed, it checks newly derived nullifiers of decrypted outputs against the nullifier
44//! map (a map of all nullifiers in the transactions inputs/spends on chain). If a spend is found it sets the surrounding
45//! shard range (sapling shard if sapling note is spent and orchard shard if orchard note is spent) to "found note" priority.
46//!
47
48pub(crate) mod client;
49pub mod error;
50pub mod keys;
51pub(crate) mod scan;
52pub mod sync;
53pub mod wallet;
54pub(crate) mod witness;
55
56pub use sync::add_scan_targets;
57pub use sync::scan_pending_transaction;
58pub use sync::sync;
59pub use sync::sync_status;
60
61use zcash_protocol::ShieldedProtocol;
62
63pub(crate) const MAX_BATCH_OUTPUTS: usize = 2usize.pow(12);
64
65pub(crate) trait SyncDomain {
66 const SHIELDED_PROTOCOL: ShieldedProtocol;
67}
68
69pub(crate) struct Sapling;
70
71impl SyncDomain for Sapling {
72 const SHIELDED_PROTOCOL: ShieldedProtocol = ShieldedProtocol::Sapling;
73}
74
75pub(crate) struct Orchard;
76
77impl SyncDomain for Orchard {
78 const SHIELDED_PROTOCOL: ShieldedProtocol = ShieldedProtocol::Orchard;
79}