Skip to content

Commit

Permalink
Merge pull request #151 from HerodotusDev/rust-hints
Browse files Browse the repository at this point in the history
Rust hints
  • Loading branch information
Okm165 authored Feb 10, 2025
2 parents eea0ec6 + 129414a commit 0dc24e5
Show file tree
Hide file tree
Showing 23 changed files with 376 additions and 133 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/rust-vm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,9 @@ jobs:
- name: Run Nextest Tests
env:
RPC_URL_ETHEREUM: ${{ secrets.RPC_URL_ETHEREUM_SEPOLIA }}
RPC_URL_FEEDER_GATEWAY: ${{ secrets.RPC_URL_FEEDER_GATEWAY }}
RPC_URL_HERODOTUS_INDEXER: ${{ secrets.RPC_URL_HERODOTUS_INDEXER }}
RPC_URL_HERODOTUS_INDEXER_GROWER: ${{ secrets.RPC_URL_HERODOTUS_INDEXER_GROWER }}
RPC_URL_HERODOTUS_INDEXER_STAGING: ${{ secrets.RPC_URL_HERODOTUS_INDEXER_STAGING }}
RPC_URL_STARKNET: ${{ secrets.RPC_URL_STARKNET_SEPOLIA }}
HERODOTUS_STAGING_INDEXER: ${{ secrets.HERODOTUS_STAGING_INDEXER }}
run: cargo nextest run

5 changes: 4 additions & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion crates/dry_hint_processor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ cairo-lang-casm.workspace = true
cairo-lang-starknet-classes.workspace = true
cairo-vm.workspace = true
hints.workspace = true
reqwest.workspace = true
indexer.workspace = true
serde.workspace = true
starknet-types-core.workspace = true
starknet.workspace = true
Expand Down
53 changes: 13 additions & 40 deletions crates/dry_hint_processor/src/syscall_handler/starknet/header.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
use std::env;

use cairo_vm::{types::relocatable::Relocatable, vm::vm_core::VirtualMachine, Felt252};
use reqwest::Url;
use indexer::{models::blocks, Indexer};
use syscall_handler::{traits::CallHandler, SyscallExecutionError, SyscallResult};
use types::{
cairo::{
starknet::header::{Block, FunctionId, StarknetBlock},
starknet::header::{FunctionId, StarknetBlock},
structs::CairoFelt,
traits::CairoType,
},
keys::starknet::header::{CairoKey, Key},
RPC_URL_FEEDER_GATEWAY, STARKNET_MAINNET_CHAIN_ID, STARKNET_TESTNET_CHAIN_ID,
};

#[derive(Debug, Default)]
Expand Down Expand Up @@ -41,43 +38,19 @@ impl CallHandler for HeaderCallHandler {
}

async fn handle(&mut self, key: Self::Key, function_id: Self::Id, _vm: &VirtualMachine) -> SyscallResult<Self::CallHandlerResult> {
let base_url = Url::parse(&env::var(RPC_URL_FEEDER_GATEWAY).unwrap()).unwrap();

// Feeder Gateway rejects the requests if this header is not set
let host_header = match key.chain_id {
STARKNET_MAINNET_CHAIN_ID => "alpha-mainnet.starknet.io",
STARKNET_TESTNET_CHAIN_ID => "alpha-sepolia.starknet.io",
_ => {
return Err(SyscallExecutionError::InternalError(
format!("Unknown chain id: {}", key.chain_id).into(),
))
}
};

let request = reqwest::Client::new()
.get(format!("{}get_block", base_url))
.header("Host", host_header)
.query(&[("blockNumber", key.block_number.to_string())]);

let response = request
.send()
let provider = Indexer::default();

// Fetch proof response
let response = provider
.get_blocks(blocks::IndexerQuery::new(
key.chain_id,
key.block_number.into(),
key.block_number.into(),
))
.await
.map_err(|e| SyscallExecutionError::InternalError(format!("Network request failed: {}", e).into()))?;

let block_data: Block = match response.status().is_success() {
true => response.json().await,
false => {
let status = response.status();
let error_body = response.text().await.unwrap_or_default();
return Err(SyscallExecutionError::InternalError(
format!("Request failed ({}): {}", status, error_body).into(),
));
}
}
.map_err(|e| SyscallExecutionError::InternalError(format!("Failed to parse block data: {}", e).into()))?;

let sn_block: StarknetBlock = block_data.into();

Ok(sn_block.handle(function_id))
// Create block and handle function
Ok(StarknetBlock::from_hash_fields(response.fields).handle(function_id))
}
}
36 changes: 17 additions & 19 deletions crates/fetcher/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@ use eth_trie_proofs::{tx_receipt_trie::TxReceiptsMptHandler, tx_trie::TxsMptHand
use futures::StreamExt;
use indexer::models::IndexerError;
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
use proof_keys::{
evm::{FlattenedKey, ProofKeys as EvmProofKeys},
starknet::ProofKeys as StarknetProofKeys,
ProofKeys,
};
use proof_keys::{evm::ProofKeys as EvmProofKeys, starknet::ProofKeys as StarknetProofKeys, FlattenedKey, ProofKeys};
use reqwest::Url;
use starknet_types_core::felt::FromStrError;
use syscall_handler::SyscallHandler;
Expand Down Expand Up @@ -300,15 +296,13 @@ impl<'a> Fetcher<'a> {
})
}

pub async fn collect_starknet_proofs(&self) -> Result<StarknetProofs, FetcherError> {
async fn collect_starknet_headers_proofs(
&self,
flattened_keys: &HashSet<FlattenedKey>,
) -> Result<HashMap<MmrMeta, Vec<StarknetHeader>>, FetcherError> {
let mut headers_with_mmr = HashMap::default();
let mut storages: HashSet<StarknetStorage> = HashSet::default();

// Collect header proofs
let mut header_fut = futures::stream::iter(
self.proof_keys
.starknet
.header_keys
flattened_keys
.iter()
.map(|key| StarknetProofKeys::fetch_header_proof(key.chain_id, key.block_number)),
)
Expand All @@ -326,6 +320,16 @@ impl<'a> Fetcher<'a> {
self.progress_bars.starknet_header.safe_inc();
}

Ok(headers_with_mmr)
}

pub async fn collect_starknet_proofs(&self) -> Result<StarknetProofs, FetcherError> {
let mut storages: HashSet<StarknetStorage> = HashSet::default();

let flattened_keys = self.proof_keys.starknet.to_flattened_keys();

let headers_with_mmr = self.collect_starknet_headers_proofs(&flattened_keys).await?;

#[cfg(feature = "progress_bars")]
self.progress_bars
.starknet_header
Expand All @@ -343,13 +347,7 @@ impl<'a> Fetcher<'a> {
.boxed();

while let Some(result) = storage_fut.next().await {
let (header_with_mmr, storage) = result?;
headers_with_mmr
.entry(header_with_mmr.mmr_meta)
.and_modify(|headers: &mut Vec<StarknetHeader>| headers.extend(header_with_mmr.headers.clone()))
.or_insert(header_with_mmr.headers);
storages.insert(storage);

storages.insert(result?);
#[cfg(feature = "progress_bars")]
self.progress_bars.starknet_storage.safe_inc();
}
Expand Down
7 changes: 1 addition & 6 deletions crates/fetcher/src/proof_keys/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use types::{
RPC_URL_ETHEREUM,
};

use super::FlattenedKey;
use crate::FetcherError;

#[derive(Debug, Default)]
Expand All @@ -31,12 +32,6 @@ pub struct ProofKeys {
pub transaction_keys: HashSet<keys::evm::transaction::Key>,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FlattenedKey {
pub chain_id: u128,
pub block_number: u64,
}

impl ProofKeys {
fn normalize_hex(input: &str) -> String {
let hex_str = input.trim_start_matches("0x");
Expand Down
15 changes: 9 additions & 6 deletions crates/fetcher/src/proof_keys/mod.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
use alloy::{hex::FromHexError, primitives::Bytes};
use indexer::{
models::{IndexerQuery, MMRProof},
Indexer,
};
use indexer::{models::accumulators, Indexer};
use types::proofs::mmr::MmrMeta;

use crate::FetcherError;

pub mod evm;
pub mod starknet;

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FlattenedKey {
pub chain_id: u128,
pub block_number: u64,
}

#[derive(Debug, Default)]
pub struct ProofKeys {
pub evm: evm::ProofKeys,
Expand All @@ -22,12 +25,12 @@ impl ProofKeys {
format!("{:0>width$}", hex_str, width = (hex_str.len() + 1) / 2 * 2)
}

pub async fn fetch_mmr_proof(chain_id: u128, block_number: u64) -> Result<(MMRProof, MmrMeta), FetcherError> {
pub async fn fetch_mmr_proof(chain_id: u128, block_number: u64) -> Result<(accumulators::MMRProof, MmrMeta), FetcherError> {
let provider = Indexer::default();

// Fetch proof response
let response = provider
.get_headers_proof(IndexerQuery::new(chain_id, block_number, block_number))
.get_headers_proof(accumulators::IndexerQuery::new(chain_id, block_number, block_number))
.await?;

// Extract MMR metadata
Expand Down
25 changes: 23 additions & 2 deletions crates/fetcher/src/proof_keys/starknet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use types::{
RPC_URL_STARKNET,
};

use super::FlattenedKey;
use crate::FetcherError;

#[derive(Debug, Default)]
Expand Down Expand Up @@ -53,7 +54,7 @@ impl ProofKeys {
}
}

pub async fn fetch_storage_proof(key: &keys::starknet::storage::Key) -> Result<(HeaderMmrMeta<Header>, Storage), FetcherError> {
pub async fn fetch_storage_proof(key: &keys::starknet::storage::Key) -> Result<Storage, FetcherError> {
let response = reqwest::Client::new()
.post(Url::parse(&env::var(RPC_URL_STARKNET).unwrap()).unwrap())
.json(&serde_json::json!({
Expand Down Expand Up @@ -81,6 +82,26 @@ impl ProofKeys {

let storage = Storage::new(key.block_number, key.address, vec![key.storage_slot], proof);

Ok((ProofKeys::fetch_header_proof(key.chain_id, key.block_number).await?, storage))
Ok(storage)
}

pub fn to_flattened_keys(&self) -> HashSet<FlattenedKey> {
let mut flattened = HashSet::new();

for key in &self.header_keys {
flattened.insert(FlattenedKey {
chain_id: key.chain_id,
block_number: key.block_number,
});
}

for key in &self.storage_keys {
flattened.insert(FlattenedKey {
chain_id: key.chain_id,
block_number: key.block_number,
});
}

flattened
}
}
1 change: 1 addition & 0 deletions crates/indexer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ edition = "2021"

[dependencies]
alloy.workspace = true
cairo-vm.workspace = true
reqwest.workspace = true
serde_json.workspace = true
serde_with.workspace = true
Expand Down
Loading

0 comments on commit 0dc24e5

Please sign in to comment.