Light client friendly proofs for events

We are working on a cross-chain bridge connecting to Diem. The current approach is like Central-Claim protocol described in Xclaim paper.

We have embedded a Diem light client that can validate LedgerInfo and TransactionToLedgerInfoProof and it works. However now the deposit is identified by the transaction inclusion proof and its execution status, but it’s hard to handle all the edge cases beyond naive transactions (e.g. when the transfer is caused by some other contracts). So IMO it’s better to identify the deposit by token transfer events.

Internally the events are added to its own accumulators. However it looks like the RPC doesn’t expose a way to produce the verifiable proof. Am I correct? If that’s the case, is there any walk-around, or will it be added in the future?

Another questions. Every event has a counter under its key path. Do the different accounts have their own counter for the transfer receiving logs, or do they share the same counter? We only care about some specific accounts. So if the events for different accounts are counted separately, our relayer can sync much less data.

P.S. Is it good to put the questions here, or better send as a Github issue?

2 Likes

Hey, a cross-chain bridge sounds like a cool project, can’t wait to hear more about it : )

The light client story is a bit rough around the edges currently, though we’re starting to focus more effort on improving it. For context, most of the current Diem blockchain users are big VASPs or Designated Dealers that run their own full nodes, so much of the tooling assumes you have your own full node (and hence doesn’t use the light client APIs).

Just to make sure you’re on the right track, you’re going to want to call the json-rpc method Client::get_state_proof(my_local_trusted_version) -> (LedgerInfoWithSignatures, EpochChangeProof, AccumulatorConsistencyProof), which provides the proofs needed to get you from your current trusted version to the remote node’s current version. Note that there are some tricky details, for instance, the EpochChangeProof might have more: true, meaning there are more epoch changes you need to fetch. You’ll also need to choose an initial trusted Waypoint. If you’re just using testnet, you can just hit https://testnet.diem.com/waypoint.txt for this.

You can use something like the TrustedState verifier to ratchet your trusted Waypoint (this is just a <version>:<ledger info hash> pair). You’ll probably also want to serialize the TrustedState's current verified_state: Waypoint to a file/local storage so you don’t have to re-sync every time.

Onto your other questions: events are not shared between accounts. Each EventKey represents a globally unique event stream.

As far as identifying successful deposits, the Sent/ReceivedEvents should be considered the source-of-truth. If you want to get all of the deposits to an account as a light client, you first call Client::get_account_state_with_proof(AccountAddress) -> AccountStateWithProof, verify the state proof, deserialize the blob into an AccountView, extract the received_events_key: EventKey, then use the event key to pull the received payment events using Client::get_events_with_proof(event_key, start, limit). Though, it looks like the rust sdk doesn’t currently implement get_events_with_proof

You can see how to deserialize the blob: Option<BytesView> into an AccountView or AccountState here, though this doesn’t verify the account state proof. You can use AccountStateWithProof::verify to verify the state proof.

For the future, you’ll probably get quicker help if you post a Github issue and tag someone in it : )

2 Likes