EspressoSystems / cape

Configurable Asset Privacy for Ethereum
https://cape.docs.espressosys.com/
GNU General Public License v3.0
93 stars 19 forks source link

Estimate on how long it takes for a wallet to sync based on # contract events #1232

Open philippecamacho opened 1 year ago

philippecamacho commented 1 year ago

Currently a wallet needs to scan linearly all the CAP smart contract events in order to build its state. How much does it take in practice? Can we deduce this from existing on chain data?

philippecamacho commented 1 year ago

@jbearer 's answer: https://espresso.zulipchat.com/#narrow/stream/311688-CAPE/topic/CAPE.20on.20arbitrum.20.28Circle.29/near/308880309

Short answer: too long. I benchmarked ledger scanning a while ago and it was something like 6-8TPS. I believe the bottleneck is in MerkleTree insertion.

Why does it take so long? Why must it scan every transaction when it comes back online? There are 3 reasons:

it needs to discover transactions that it received while offline, and it needs up-to-date Merkle proofs for the records. The way it does this, without leaking privacy by asking the EQS for proofs, is by scanning the ledger in order, building up a partially-sparse Merkle tree as it goes, so that it ends up with an up-to-date tree containing paths to all of the leaves it cares about. Note, though, that this could happen asynchronously. it needs to update its Merkle root in order to build transactions. It currently does this in the same ledger scan, incrementally applying transactions until it arrives at the most up-to-date root. In principle I think it would be possible to add a fast sync mode where, if the backend supports it, we just fetch the latest state from the query service with proof and start building transactions from there. Since the EQS is already trusted in CAPE, the "proof" can just be (). We could keep the same feature when deploying CAP on Espresso with an untrusted EsQS using the consensus catchup mechanism (a chain of QCs authenticating the final state and every stake table change). Implementing this would allow us to resync quickly and scan the ledger for received transactions asynchronously. However... it needs to update its existing Merkle proofs for owned records before it can spend them. For this, it does need to replay transactions. It cannot outsource the work to a service without revealing information about which records it owns. And there is no way to make this non-blocking, since you cannot build transactions until you have up-to-date proofs. Since (1) could be made non-blocking and (2) could be accelerated with a (possibly authenticated) fast sync protocol, (3) is the real bottleneck. I'm not sure how to improve this either. Larger blocks can help some. Possibly there are some potential gains by doing batch insert (i.e. instead of applying blocks one by one, ask the EQS for every single record commitment that has been created since you went offline, and apply them all in a batch). But I remember there are some theoretical limitations about how efficient accumulator batch insert can be.