From 4651b2e01bfbc3e2cf930b32335902a19da5774c Mon Sep 17 00:00:00 2001 From: pierre-l Date: Wed, 31 Jan 2024 12:07:18 +0100 Subject: [PATCH] docs: Document the synchronization process Include a mermaid sequence diagram using aquamarine --- Cargo.lock | 34 ++++++++++++++++++++++++++++ crates/core/Cargo.toml | 5 +++++ crates/core/src/client.rs | 47 ++++++++++++++++++++++++++++++--------- 3 files changed, 75 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ceaa6cac..c19d1ad6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -174,6 +174,20 @@ version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +[[package]] +name = "aquamarine" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21cc1548309245035eb18aa7f0967da6bc65587005170c56e6ef2788a4cf3f4e" +dependencies = [ + "include_dir", + "itertools 0.10.5", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "ark-ff" version = "0.4.2" @@ -387,6 +401,7 @@ dependencies = [ name = "beerus-core" version = "0.3.0" dependencies = [ + "aquamarine", "async-trait", "bitvec 1.0.1", "ethabi", @@ -2425,6 +2440,25 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "include_dir" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e" +dependencies = [ + "include_dir_macros", +] + +[[package]] +name = "include_dir_macros" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "indenter" version = "0.3.3" diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index c12235b0..db3e97ac 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -4,8 +4,13 @@ edition = "2021" name = "beerus-core" version = "0.3.0" +[package.metadata.cargo-udeps] +# Aquamarine generates Mermaid diagrams and causes a udeps false positive. +ignore = [["aquamarine"]] + [dependencies] tokio = { workspace = true } +aquamarine = "0.5" async-trait = "0.1.58" bitvec = "1.0.1" ethabi = "18.0.0" diff --git a/crates/core/src/client.rs b/crates/core/src/client.rs index 5a0b8ce3..14ab87f5 100644 --- a/crates/core/src/client.rs +++ b/crates/core/src/client.rs @@ -159,11 +159,31 @@ impl BeerusClient { }) } + #[cfg_attr(doc, aquamarine::aquamarine)] /// Start a async thread to query the last updated state of Starknet /// via the Core Contracts on L1(updated via the `updateState` call). /// /// The loop run in this thread will query these values at /// `config.poll_secs` seconds + /// + /// Synchronization process sequence (currently untrusted because + /// unproven, see #550): + /// ```mermaid + /// sequenceDiagram + /// Beerus->>+L1: get_starknet_state_root + /// L1-->>-Beerus: starknet state root + /// Note over Beerus,L1: State root: hash of the state Merkle tree + /// Beerus->>+L1: get_startknet_block_number + /// L1-->>-Beerus: starknet block number synched in L1 + /// alt local L1 block number >= L1 block number + /// Beerus->>Beerus: return None + /// Note over Beerus,L1: Local state is at least as up-to-date as the remote node + /// else + /// Beerus->>+L2: get_block_with_tx_hashes(latest) + /// L2-->>-Beerus: latest L2 block + /// Beerus->>Beerus: Update local state to the new, unproven state + /// end + /// ``` pub async fn start(&mut self) -> Result<()> { let l1_client = self.helios_client.clone(); let l2_client = self.config.to_starknet_client(); @@ -173,7 +193,7 @@ impl BeerusClient { let state_loop = async move { loop { - match pull_block( + match sync( &l1_client, &l2_client, core_contract_addr, @@ -307,7 +327,7 @@ impl BeerusClient { } } -async fn pull_block( +async fn sync( l1_client: &Client, l2_client: &JsonRpcClient, core_contract_addr: H160, @@ -315,30 +335,35 @@ async fn pull_block( ) -> Result> { let starknet_state_root = get_starknet_state_root(l1_client, core_contract_addr).await?; - let starknet_block_number = + let l1_starknet_block_number = get_starknet_state_block_number(l1_client, core_contract_addr).await?; let local_block_number = node.read().await.l1_block_number; - debug!("starknet block number: {starknet_block_number}, local block number: {local_block_number}"); - if local_block_number >= starknet_block_number { + debug!("starknet block number: {l1_starknet_block_number}, local block number: {local_block_number}"); + // The local state is up to date with the remote node. Nothing more to do. + if local_block_number >= l1_starknet_block_number { return Ok(None); } + // The local state is out of date, retrieve the latest block from L2. // TODO: Issue #550 - feat: sync from proven root match l2_client .get_block_with_tx_hashes(BlockId::Tag(StarknetBlockTag::Latest)) .await { - Ok(MaybePendingBlockWithTxHashes::Block(block)) => { - let blocks_behind = block.block_number - starknet_block_number; + Ok(MaybePendingBlockWithTxHashes::Block(l2_latest_block)) => { + let blocks_behind = + l2_latest_block.block_number - l1_starknet_block_number; info!( - "L1 block: {}, L2 block: {} ({} blocks behind)", - starknet_block_number, block.block_number, blocks_behind + "L1 block: {}, L2 block: {} (L1 is {} blocks behind)", + l1_starknet_block_number, + l2_latest_block.block_number, + blocks_behind ); let mut guard = node.write().await; - guard.update(starknet_block_number, starknet_state_root); - Ok(Some(block.block_number)) + guard.update(l1_starknet_block_number, starknet_state_root); + Ok(Some(l2_latest_block.block_number)) } Ok(MaybePendingBlockWithTxHashes::PendingBlock(_)) => { Err(eyre!("expecting latest got pending"))