Skip to content

Commit

Permalink
Retries for proofs and starknet (#14)
Browse files Browse the repository at this point in the history
* feat: enhance MMR build options and refactor RPC handling

Add new MMR build options:
- Add --start-block (-s) to start building from specific block
- Add --from-latest (-l) to start from latest MMR block
- Add validation to prevent conflicting options
- Update help text for all CLI options

Refactor RPC URL handling:
- Move RPC URL handling from StarknetAccount to AccumulatorBuilder
- Add starknet_rpc_url field to AccumulatorBuilder struct
- Update AccumulatorBuilder::new signature to accept RPC URL
- Remove RPC URL handling from StarknetAccount

New AccumulatorBuilder methods:
- Add build_from_block for starting from specific block
- Add build_from_latest for starting from latest MMR block
- Add build_from_block_with_batches for batch processing
- Add build_from_latest_with_batches for batch processing

This change improves flexibility in MMR building by:
1. Allowing users to specify custom start points
2. Supporting continuation from latest MMR state
3. Making the RPC URL dependency explicit
4. Simplifying provider creation for latest block queries

* remove unused update_mmr_state from starknet account

* implemented retries for starkent proof verification tx

* fixes for mmr build restart + added min block to starknet store

* scarb fmt

* updated cairo in ci
  • Loading branch information
ametel01 authored Jan 8, 2025
1 parent 194cd1d commit 90dd9ab
Show file tree
Hide file tree
Showing 17 changed files with 406 additions and 116 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/cairo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
submodules: true
- uses: software-mansion/setup-scarb@v1
with:
scarb-version: "2.8.5"
scarb-version: "2.9.1"
- run: cd contracts/starknet && scarb fmt --check
- run: cd contracts/starknet && scarb build
# - run: snforge test
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 55 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,13 +242,68 @@ Required toolchain components:
./scripts/deploy.sh
```

#### Terminal 4: MMR Builder Options

The MMR builder supports several options for controlling how the MMR is built:

```bash
# Build MMR with default settings (from latest finalized block)
cargo run --bin build_mmr --release

# Build from a specific start block
cargo run --bin build_mmr --release -- --start-block <BLOCK_NUMBER>

# Build from the latest onchain MMR block
cargo run --bin build_mmr --release -- --from-latest

# Control batch size
cargo run --bin build_mmr --release -- --batch-size <SIZE>

# Process specific number of batches
cargo run --bin build_mmr --release -- --num-batches <COUNT>

# Skip proof verification
cargo run --bin build_mmr --release -- --skip-proof

# Combine options (examples)
cargo run --bin build_mmr --release -- --from-latest --num-batches 10
cargo run --bin build_mmr --release -- --start-block 1000 --batch-size 512
```

Available options:
- `--start-block, -s`: Start building from this block number
- `--from-latest, -l`: Start building from the latest onchain MMR block
- `--batch-size`: Number of blocks per batch (default: 1024)
- `--num-batches, -n`: Number of batches to process
- `--skip-proof, -p`: Skip proof verification
- `--env-file, -e`: Path to environment file (default: .env)

Note: `--from-latest` and `--start-block` cannot be used together.

#### Terminal 4: Light Client Process

Execute client binary:
```bash
cargo run --bin client --release
```

The client supports the following options:

```bash
# Run with default settings (5 second polling interval)
cargo run --bin client --release

# Run with custom polling interval (in seconds)
cargo run --bin client --release -- --polling-interval 10

# Use a specific environment file
cargo run --bin client --release -- --env-file .env.local
```

Available options:
- `--polling-interval`: Time between polls in seconds (default: 5)
- `--env-file, -e`: Path to environment file (default: .env)

#### Terminal 5: Block Hash Relayer Process

Execute relayer process:
Expand Down
31 changes: 31 additions & 0 deletions config/.env.docker.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
ETH_RPC_URL=http://anvil:8545
FORK_URL=http://209.127.228.66:8545

BONSAI_API_KEY=XXX
BONSAI_API_URL=https://api.bonsai.xyz/

DATABASE_URL=XXX

ETH_ACCOUNT_ADDRESS=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
ACCOUNT_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

SN_MESSAGING=0x0c77a52c35601106993B684E6b20D68FF0a89493
L1_MESSAGE_SENDER=0x77F83238fa5FFD7E031C2D1195AC5d0a8D1B3df5

export FOUNDRY_EVM_VERSION=cancun

ANVIL_CONFIG=config/anvil.messaging.json
STARKNET_RPC_URL=http://katana:5050
STARKNET_PRIVATE_KEY=0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912
STARKNET_ACCOUNT_ADDRESS=0x127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec

L2_MSG_PROXY=0x01c0692f888adfb3dea3d4b4446afbfcd3a2456a64b113084af3549e8d6915e8
FOSSIL_STORE=0x02d4eac88f8e9bbb0fd4ff2c35d385710bf3f8a6e4061266ac4de628dac11dd5

STARKNET_VERIFIER=0x03848e3432559e5804d48e1a60faa59c9ab00f515bcf122e3865193277eb118a
FOSSIL_VERIFIER=0x029d9eba080e8e7a6eed79f432b8d0cbe1e7ffe4187eda3cf2819cde8d700ff2

STARKNET_ACCOUNT=katana-0

DEPLOYMENT_VERSION=local
CHAIN_ID=11155111
27 changes: 0 additions & 27 deletions config/.env.example

This file was deleted.

6 changes: 3 additions & 3 deletions config/anvil.messaging.docker.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"chain": "ethereum",
"rpc_url": "http://localhost:8545",
"contract_address": "0xE37675Bb1cc1c90dB0Deed8033CAb650770e79cE",
"rpc_url": "http://anvil:8545",
"contract_address": "0xe9FfA5399C14206e16D801dA5BD94cbF67bE82a7",
"sender_address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"private_key": "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
"interval": 2,
"from_block": 7422233
"from_block": 7442506
}
35 changes: 30 additions & 5 deletions contracts/starknet/store/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
#[starknet::interface]
pub trait IFossilStore<TContractState> {
fn initialize(ref self: TContractState, verifier_address: starknet::ContractAddress, min_update_interval: u64);
fn initialize(
ref self: TContractState,
verifier_address: starknet::ContractAddress,
min_update_interval: u64,
);
fn store_latest_blockhash_from_l1(ref self: TContractState, block_number: u64, blockhash: u256);
fn update_mmr_state(ref self: TContractState, journal: verifier::Journal);
fn get_latest_blockhash_from_l1(self: @TContractState) -> (u64, u256);
fn get_mmr_state(self: @TContractState, batch_index: u64) -> Store::MMRSnapshot;
fn get_latest_mmr_block(self: @TContractState) -> u64;
fn get_min_mmr_block(self: @TContractState) -> u64;
}

#[starknet::contract]
Expand Down Expand Up @@ -38,6 +43,7 @@ mod Store {
latest_blockhash_from_l1: (u64, u256),
latest_mmr_block: u64,
mmr_batches: Map<u64, MMRBatch>,
min_mmr_block: u64,
min_update_interval: u64,
}

Expand Down Expand Up @@ -65,7 +71,11 @@ mod Store {

#[abi(embed_v0)]
impl FossilStoreImpl of super::IFossilStore<ContractState> {
fn initialize(ref self: ContractState, verifier_address: starknet::ContractAddress, min_update_interval: u64) {
fn initialize(
ref self: ContractState,
verifier_address: starknet::ContractAddress,
min_update_interval: u64,
) {
assert!(!self.initialized.read(), "Contract already initialized");
self.initialized.write(true);
self.verifier_address.write(verifier_address);
Expand Down Expand Up @@ -98,14 +108,25 @@ mod Store {
actual_update_interval >= min_update_interval,
"Update interval: {} must be greater than or equal to the minimum update interval: {}",
actual_update_interval,
min_update_interval
min_update_interval,
);
self.latest_mmr_block.write(journal.latest_mmr_block);
}

let mut curr_state = self.mmr_batches.entry(journal.batch_index);

curr_state.latest_mmr_block.write(journal.latest_mmr_block);

let min_mmr_block = self.min_mmr_block.read();
let lowest_batch_block = journal.latest_mmr_block - journal.leaves_count + 1;
if min_mmr_block != 0 {
if lowest_batch_block < min_mmr_block {
self.min_mmr_block.write(lowest_batch_block);
}
} else {
self.min_mmr_block.write(lowest_batch_block);
}

curr_state.latest_mmr_block_hash.write(journal.latest_mmr_block_hash);
curr_state.leaves_count.write(journal.leaves_count);
curr_state.root_hash.write(journal.root_hash);
Expand All @@ -117,8 +138,8 @@ mod Store {
latest_mmr_block: journal.latest_mmr_block,
latest_mmr_block_hash: journal.latest_mmr_block_hash,
leaves_count: journal.leaves_count,
root_hash: journal.root_hash
}
root_hash: journal.root_hash,
},
);
}

Expand All @@ -136,5 +157,9 @@ mod Store {
fn get_latest_mmr_block(self: @ContractState) -> u64 {
self.latest_mmr_block.read()
}

fn get_min_mmr_block(self: @ContractState) -> u64 {
self.min_mmr_block.read()
}
}
}
8 changes: 6 additions & 2 deletions contracts/starknet/verifier/src/fossil_verifier.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ mod FossilVerifier {

#[external(v0)]
fn verify_mmr_proof(ref self: ContractState, proof: Span<felt252>) -> bool {
let journal = self.bn254_verifier.read().verify_groth16_proof_bn254(proof).expect('Failed to verify proof');
let journal = self
.bn254_verifier
.read()
.verify_groth16_proof_bn254(proof)
.expect('Failed to verify proof');

let journal = decode_journal(journal);

Expand All @@ -59,7 +63,7 @@ mod FossilVerifier {
batch_index: journal.batch_index,
latest_mmr_block: journal.latest_mmr_block,
new_leaves_count: journal.leaves_count,
new_mmr_root: journal.root_hash
new_mmr_root: journal.root_hash,
},
);

Expand Down
8 changes: 4 additions & 4 deletions contracts/starknet/verifier/src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub(crate) fn decode_journal(journal_bytes: Span<u8>) -> Journal {
m += 1;
};

Journal { batch_index, latest_mmr_block, latest_mmr_block_hash, root_hash, leaves_count, }
Journal { batch_index, latest_mmr_block, latest_mmr_block_hash, root_hash, leaves_count }
}

trait BitShift<T> {
Expand Down Expand Up @@ -163,7 +163,7 @@ mod tests {
assert_eq!(journal.latest_mmr_block, 7253851);
assert_eq!(
journal.latest_mmr_block_hash,
0x858768dd79b8c6190fb224ff398345ffe4fcb9c4899c55e0fc0994b7d35177af
0x858768dd79b8c6190fb224ff398345ffe4fcb9c4899c55e0fc0994b7d35177af,
);
assert_eq!(
journal.root_hash, 0x72aa9525dc9b7953631c0699d041fd4f23aa9f98c4a73aab27fbf2f0b9b451f8,
Expand Down Expand Up @@ -340,8 +340,8 @@ mod tests {
0,
0,
0,
0
0,
]
.span()
}
}
}
36 changes: 27 additions & 9 deletions crates/publisher/bin/build_mmr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,20 @@ struct Args {
num_batches: Option<u64>,

/// Skip proof verification
#[arg(short, long, default_value_t = false)]
#[arg(short = 'p', long, default_value_t = false)]
skip_proof: bool,

/// Path to environment file (optional)
#[arg(short = 'e', long, default_value = ".env")]
env_file: String,

/// Start building from this block number. If not specified, starts from the latest finalized block.
#[arg(short = 's', long)]
start_block: Option<u64>,

/// Start building from the latest MMR block
#[arg(short = 'l', long, default_value_t = false)]
from_latest: bool,
}

#[tokio::main]
Expand All @@ -40,14 +48,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let private_key = get_env_var("STARKNET_PRIVATE_KEY")?;
let account_address = get_env_var("STARKNET_ACCOUNT_ADDRESS")?;

// Parse CLI arguments
let args = Args::parse();

let starknet_provider = StarknetProvider::new(&rpc_url)?;
let starknet_account =
StarknetAccount::new(starknet_provider.provider(), &private_key, &account_address)?;

let mut builder = AccumulatorBuilder::new(
&rpc_url,
chain_id,
&verifier_address,
&store_address,
Expand All @@ -61,11 +67,23 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
e
})?;

// Build MMR from finalized block to block #0 or up to the specified number of batches
if let Some(num_batches) = args.num_batches {
builder.build_with_num_batches(num_batches).await?;
} else {
builder.build_from_finalized().await?;
// Build MMR from specified start block or finalized block
match (args.from_latest, args.start_block, args.num_batches) {
(true, Some(_), _) => {
return Err("Cannot specify both --from-latest and --start-block".into());
}
(true, None, Some(num_batches)) => {
builder.build_from_latest_with_batches(num_batches).await?
}
(true, None, None) => builder.build_from_latest().await?,
(false, Some(start_block), Some(num_batches)) => {
builder
.build_from_block_with_batches(start_block, num_batches)
.await?
}
(false, Some(start_block), None) => builder.build_from_block(start_block).await?,
(false, None, Some(num_batches)) => builder.build_with_num_batches(num_batches).await?,
(false, None, None) => builder.build_from_finalized().await?,
}

info!("Host finished");
Expand Down
1 change: 1 addition & 0 deletions crates/publisher/src/api/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub async fn prove_mmr_update(
)?;

let mut builder = AccumulatorBuilder::new(
rpc_url,
chain_id,
verifier_address,
store_address,
Expand Down
Loading

0 comments on commit 90dd9ab

Please sign in to comment.