Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: add project documents #815

Merged
merged 7 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,6 @@ wiremock = "0.6.2"

[patch.crates-io]
starknet-core = { git = "https://github.com/kariy/starknet-rs", branch = "dojo-patch" }

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(tarpaulin_include)'] }
5 changes: 5 additions & 0 deletions _typos.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
[default.extend-words]
wrk = "wrk"

[files]
extend-exclude = [
"coverage.html",
]
114 changes: 114 additions & 0 deletions doc/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
Beerus Architecture Overview
============================

## Components

* Beerus client library (`src/client.rs`)
* Beerus RPC server
- Based on `axum` HTTP server
- RPC impl (`src/rpc.rs`)
* JSON-RPC spec (generated code: `src/gen.rs`)
- Starknet spec 0.7.1 (`etc/spec/starknet/0.7.1`)
- Generated by `iamgroot` (Rust DTO codegen tool)
* Ethereum client (`src/eth.rs`)
- Based on `helios` Ethereum light client
* Merkle proof check (`src/proof.rs`)
* Stateless execution (`src/exe/mod.rs`)
- `blockifier`
- `cairo-vm`
- `cairo-lang-*`
* WebAssembly library (`web/beerus-web`)

## Execution

### Get current state

```mermaid
sequenceDiagram
Beerus->>Helios: Start
loop Sync
Helios->>(Beacon Chain): Query Beacon Chain
(Beacon Chain)->>Helios: Beacon Chain data
end
Note right of Helios: Helios is ready
Helios->>Beerus: Synced
Note right of Beerus: Beerus is ready
Beerus->>Helios: Query State
Beerus->>Helios: Get Latest Block
Helios->>(Ethereum RPC): Get Latest Block
(Ethereum RPC)->>Helios: Latest Block Number
Helios->>Beerus: Latest Block Number

Beerus->>Helios: Call stateBlockNumber()
Helios->>(Ethereum RPC): Call Starknet Core Contract
(Ethereum RPC)->>Helios: Get Result
Helios->>Beerus: Get Result

Beerus->>Helios: Call stateBlockHash()
Helios->>(Ethereum RPC): Call Starknet Core Contract
(Ethereum RPC)->>Helios: Get Result
Helios->>Beerus: Get Result

Beerus->>Helios: Call stateRoot()
Helios->>(Ethereum RPC): Call Starknet Core Contract
(Ethereum RPC)->>Helios: Get Result
Helios->>Beerus: Get Result

Beerus->>Beerus: Store Current State
```

### Stateless call (RPC)

```mermaid
sequenceDiagram
(RPC Server)->>Beerus: starknet_call
Beerus->>Beerus: Check current state
Beerus->>Blockifier: Prepare execution context
Blockifier->>Blockifier: Create Starknet client
Blockifier->>Blockifier: Create State reader & write
loop Stateless Execution
Blockifier->>State Reader: State Request
State Reader->>(Starknet RPC): Query State
(Starknet RPC)->>State Reader: State Result
State Reader->>(Starknet RPC): Query State Proof
(Starknet RPC)->>State Reader: State Proof
State Reader->>State Reader: Verify State Proof
State Reader->>Blockifier: State Result
end
Note right of (RPC Server): Other methods are proxied
(RPC Server)->>Beerus: starknet_*
Beerus->>(Starknet RPC): (proxy the request)
(Starknet RPC)->>Beerus: (proxy the response)
Beerus->>(RPC Server): response
```

### Stateless call (WASM)

```mermaid
sequenceDiagram
(Browser)->>(Browser): Check Proxy
(Browser)->>Beerus: Init
Note right of Beerus: Beerus is set up to run in a WebWorker
Beerus->>(Browser): Ready
(Browser)->>Beerus: Call
Beerus->>Client: Inject post() function
Client->>Client: create blocking StateReader
Note right of Client: Blocking StateReader is required by Blockifier
Client->>Client: create async StateReader
Client->>Beerus: Ready
Beerus->>Blockifier: Execute call
loop Stateless Execution
Blockifier->>Client: State Request
Client->>(Starknet RPC): State Request
(Starknet RPC)->>Client: State Result
Client->>(Starknet RPC): Get State Proof
(Starknet RPC)->>Client: State Proof
Client->>Client: Verify State Proof
Client->>Blockifier: State Result
end
Blockifier->>Beerus: Call Result
```

Beerus allows Blockifier to execute calls in a stateless manner by providing implementation of a `StateReader`. The `StateReader` implementation fetches necessary state (the value for the provided key to be exact) directly from Starknet RPC (and then pulls merkle proof for the value and verifies that it is valid). Thus during call execution Beerus has no control over which specific RPC methods are being called and how often - it depends on Blockifier and specific execution context of the call (contract & method that are being executed).

Beerus workload is purely IO bound, as the only computation being performed is the verification of a merkle proof for a received key-value pairs. Thus performance of the stateless call execution depends on latency and frequency of RPC calls performed by Blockifier.
671 changes: 671 additions & 0 deletions doc/coverage.html

Large diffs are not rendered by default.

66 changes: 66 additions & 0 deletions doc/coverage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
How to make a code coverage report

1. Install [tarpaulin](https://github.com/xd009642/tarpaulin)

```
cargo install cargo-tarpaulin
```

1. Run the tests


```
## Exclude ./web from coverage
## WARNING: Commit any changes made to ./web/* first, or they will be lost
rm -rf web/*

export STARKNET_MAINNET_URL: https://starknet-mainnet.g.alchemy.com/starknet/version/rpc/v0_7/${ALCHEMY_KEY}
export STARKNET_SEPOLIA_URL: https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_7/${ALCHEMY_KEY}
BEERUS_TEST_RUN=1 cargo tarpaulin --out html

## Restore content of ./web
git restore web
```

```
2024-10-23T09:38:36.285998Z INFO cargo_tarpaulin::report: Coverage Results:
|| Tested/Total Lines:
|| src/client.rs: 9/63
|| src/config.rs: 21/59
|| src/eth.rs: 0/78
|| src/exe/err.rs: 0/6
|| src/exe/map.rs: 48/50
|| src/exe/mod.rs: 75/127
|| src/proof.rs: 86/157
|| src/rpc.rs: 114/154
|| src/util.rs: 13/14
||
51.69% coverage, 366/708 lines covered
```

1. Check out the report

Open `tarpaulin-report.html` in a browser.

1. Update report (optional)

```
mv tarpaulin-report.html coverage.html
rm doc/coverage.html
mv coverage.html doc/

git add doc/coverage.html
git commit -m 'docs(cov): update coverage report'
```

1. Alternative coverage (optional)

Use [llvm-cov](https://github.com/taiki-e/cargo-llvm-cov):

```
cargo +stable install cargo-llvm-cov --locked

export STARKNET_MAINNET_URL: https://starknet-mainnet.g.alchemy.com/starknet/version/rpc/v0_7/${ALCHEMY_KEY}
export STARKNET_SEPOLIA_URL: https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_7/${ALCHEMY_KEY}
BEERUS_TEST_RUN=1 cargo llvm-cov --html
```
2 changes: 2 additions & 0 deletions src/bin/beerus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use beerus::{
use tokio::sync::RwLock;
use validator::Validate;

#[cfg(not(tarpaulin_include))] // exclude from code-coverage report
#[tokio::main]
async fn main() -> eyre::Result<()> {
tracing_subscriber::fmt::init();
Expand Down Expand Up @@ -56,6 +57,7 @@ async fn main() -> eyre::Result<()> {
Ok(())
}

#[cfg(not(tarpaulin_include))] // exclude from code-coverage report
async fn get_config() -> eyre::Result<ServerConfig> {
let path = std::env::args().nth(1);
let config = if let Some(path) = path {
Expand Down
1 change: 1 addition & 0 deletions src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub use gen::*;
#[allow(clippy::module_inception)]
#[allow(non_snake_case)]
#[allow(clippy::enum_variant_names)]
#[allow(clippy::large_enum_variant)]
pub mod gen {
use serde::{Deserialize, Serialize};
use serde_json::Value;
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ pub mod client;
pub mod config;
pub mod eth;
pub mod exe;

#[cfg(not(tarpaulin_include))] // exclude from code-coverage report
pub mod gen;

pub mod proof;

#[cfg(not(target_arch = "wasm32"))]
Expand Down
Loading