Skip to content

Commit

Permalink
Merge pull request #7 from jbcaron/testnet
Browse files Browse the repository at this point in the history
Testnet
  • Loading branch information
antiyro committed Mar 6, 2024
2 parents 7d938f5 + b79401e commit cd75088
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 82 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ git # Deoxys Changelog

## Next release

- feat: Removal of the hardcoded mainnet configuration
- refactor: pass new CI
- fix(workflows): Fix deoxys CI
- feat(rpc): add_invoke_tx, add_deploy_account_tx, add_declare_tx
Expand Down
26 changes: 20 additions & 6 deletions crates/client/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ use mc_genesis_data_provider::GenesisProvider;
pub use mc_rpc_core::utils::*;
pub use mc_rpc_core::{Felt, StarknetReadRpcApiServer, StarknetTraceRpcApiServer, StarknetWriteRpcApiServer};
use mc_storage::OverrideHandle;
use mc_sync::l2::get_config;
use mc_sync::utility::get_highest_block_hash_and_number;
use mc_sync::l2::get_highest_block_hash_and_number;
use mc_sync::utility::get_config;
use mp_block::BlockStatus;
use mp_contract::class::ContractClassWrapper;
use mp_felt::{Felt252Wrapper, Felt252WrapperError};
Expand Down Expand Up @@ -291,7 +291,10 @@ where
&self,
declare_transaction: BroadcastedDeclareTransaction,
) -> RpcResult<DeclareTransactionResult> {
let config = get_config();
let config = get_config().map_err(|e| {
error!("Failed to get config: {e}");
StarknetRpcApiError::InternalServerError
})?;
let sequencer = SequencerGatewayProvider::new(config.feeder_gateway, config.gateway, config.chain_id);

let sequencer_response = match sequencer.add_declare_transaction(declare_transaction).await {
Expand Down Expand Up @@ -321,7 +324,10 @@ where
&self,
invoke_transaction: BroadcastedInvokeTransaction,
) -> RpcResult<InvokeTransactionResult> {
let config = get_config();
let config = get_config().map_err(|e| {
error!("Failed to get config: {e}");
StarknetRpcApiError::InternalServerError
})?;
let sequencer = SequencerGatewayProvider::new(config.feeder_gateway, config.gateway, config.chain_id);

let sequencer_response = match sequencer.add_invoke_transaction(invoke_transaction).await {
Expand Down Expand Up @@ -352,7 +358,10 @@ where
&self,
deploy_account_transaction: BroadcastedDeployAccountTransaction,
) -> RpcResult<DeployAccountTransactionResult> {
let config = get_config();
let config = get_config().map_err(|e| {
error!("Failed to get config: {e}");
StarknetRpcApiError::InternalServerError
})?;
let sequencer = SequencerGatewayProvider::new(config.feeder_gateway, config.gateway, config.chain_id);

let sequencer_response = match sequencer.add_deploy_account_transaction(deploy_account_transaction).await {
Expand Down Expand Up @@ -959,7 +968,12 @@ where
/// defined by the Starknet protocol, indicating the particular network.
fn chain_id(&self) -> RpcResult<Felt> {
let best_block_hash = self.client.info().best_hash;
let chain_id = get_config().chain_id;
let chain_id = get_config()
.map_err(|e| {
error!("Failed to get config: {e}");
StarknetRpcApiError::InternalServerError
})?
.chain_id;

Ok(Felt(chain_id))
}
Expand Down
4 changes: 2 additions & 2 deletions crates/client/sync/src/commitments/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ pub fn event_commitment<B: BlockT>(events: &[Event], bonsai_db: &Arc<BonsaiDb<B>
}

let id = id_builder.new_id();
bonsai_storage.commit(id).map_err(|_| format!("Failed to commit to bonsai storage"))?;
bonsai_storage.commit(id).map_err(|_| "Failed to commit to bonsai storage")?;

// restores the Bonsai Trie to it's previous state
let root_hash = bonsai_storage.root_hash().map_err(|_| format!("Failed to get root hash"))?;
let root_hash = bonsai_storage.root_hash().map_err(|_| "Failed to get root hash")?;
bonsai_storage.revert_to(zero).unwrap();

Ok(Felt252Wrapper::from(root_hash))
Expand Down
16 changes: 7 additions & 9 deletions crates/client/sync/src/l1.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! Contains the necessaries to perform an L1 verification of the state

use std::str::FromStr;
use std::sync::{Arc, Mutex};

use anyhow::Result;
Expand All @@ -19,8 +18,8 @@ use serde_json::Value;
use starknet_api::hash::StarkHash;

use crate::l2::STARKNET_STATE_UPDATE;
use crate::utility::{event_to_l1_state_update, get_state_update_at};
use crate::utils::constant::{starknet_core_address, LOG_STATE_UPDTATE_TOPIC};
use crate::utility::{event_to_l1_state_update, get_config, get_state_update_at};
use crate::utils::constant::LOG_STATE_UPDTATE_TOPIC;

lazy_static! {
/// Shared latest L2 state update verified on L1
Expand Down Expand Up @@ -83,8 +82,7 @@ impl EthereumClient {
/// Get the block number of the last occurrence of a given event.
pub async fn get_last_event_block_number(&self) -> Result<u64, Box<dyn std::error::Error>> {
let topic = H256::from_slice(&hex::decode(&LOG_STATE_UPDTATE_TOPIC[2..])?);
let address =
Address::from_str(starknet_core_address::MAINNET).map_err(|e| format!("Failed to parse address: {}", e))?;
let address = get_config()?.l1_core_address;
let latest_block = self.get_latest_block_number().await.expect("Failed to retrieve latest block number");

// Assuming an avg Block time of 15sec we check for a LogStateUpdate occurence in the last ~24h
Expand All @@ -107,7 +105,7 @@ impl EthereumClient {
/// Get the last Starknet block number verified on L1
pub async fn get_last_block_number(&self) -> Result<u64> {
let data = decode("35befa5d")?;
let to: Address = starknet_core_address::MAINNET.parse()?;
let to: Address = get_config().expect("Failed to get config").l1_core_address;
let tx_request = TransactionRequest::new().to(to).data(data);
let tx = TypedTransaction::Legacy(tx_request);
let result = self.provider.call(&tx, None).await.expect("Failed to get last block number");
Expand All @@ -121,7 +119,7 @@ impl EthereumClient {
/// Get the last Starknet state root verified on L1
pub async fn get_last_state_root(&self) -> Result<StarkHash> {
let data = decode("9588eca2")?;
let to: Address = starknet_core_address::MAINNET.parse()?;
let to: Address = get_config().expect("Failed to get config").l1_core_address;
let tx_request = TransactionRequest::new().to(to).data(data);
let tx = TypedTransaction::Legacy(tx_request);
let result = self.provider.call(&tx, None).await.expect("Failed to get last state root");
Expand All @@ -131,7 +129,7 @@ impl EthereumClient {
/// Get the last Starknet block hash verified on L1
pub async fn get_last_block_hash(&self) -> Result<StarkHash> {
let data = decode("0x382d83e3")?;
let to: Address = starknet_core_address::MAINNET.parse()?;
let to: Address = get_config().expect("Failed to get config").l1_core_address;
let tx_request = TransactionRequest::new().to(to).data(data);
let tx = TypedTransaction::Legacy(tx_request);
let result = self.provider.call(&tx, None).await.expect("Failed to get last block hash");
Expand All @@ -157,7 +155,7 @@ impl EthereumClient {
/// verified state
pub async fn listen_and_update_state(&self, start_block: u64) -> Result<(), Box<dyn std::error::Error>> {
let client = self.provider.clone();
let address: Address = starknet_core_address::MAINNET.parse().expect("Failed to parse Starknet core address");
let address: Address = get_config().expect("Failed to get config").l1_core_address;
abigen!(
StarknetCore,
"crates/client/sync/src/utils/abis/starknet_core.json",
Expand Down
62 changes: 25 additions & 37 deletions crates/client/sync/src/l2.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
//! Contains the code required to fetch data from the feeder efficiently.
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use std::sync::{Arc, Mutex, RwLock};
use std::time::Duration;

use itertools::Itertools;
use lazy_static::lazy_static;
use mc_db::BonsaiDbs;
use mc_storage::OverrideHandle;
use mp_block::state_update::StateUpdateWrapper;
Expand All @@ -12,7 +13,7 @@ use mp_felt::Felt252Wrapper;
use mp_storage::StarknetStorageSchemaVersion;
use reqwest::Url;
use serde::Deserialize;
use sp_core::H256;
use sp_core::{H160, H256};
use sp_runtime::generic::{Block, Header};
use sp_runtime::traits::{BlakeTwo256, Block as BlockT};
use sp_runtime::OpaqueExtrinsic;
Expand All @@ -27,7 +28,7 @@ use tokio::sync::mpsc::Sender;
use tokio::task::JoinSet;

use crate::commitments::lib::{build_commitment_state_diff, update_state_root};
use crate::utility::{get_block_hash_by_number, update_highest_block_hash_and_number};
use crate::utility::get_block_hash_by_number;
use crate::CommandSink;

/// Contains the Starknet verified state on L2
Expand All @@ -47,17 +48,9 @@ lazy_static! {
});
}

use lazy_static::lazy_static;

// TODO: find a better place to store this
lazy_static! {
/// Store the configuration globally
static ref CONFIG: Arc<Mutex<FetchConfig>> = Arc::new(Mutex::new(FetchConfig::default()));
}

lazy_static! {
/// Shared latest block number and hash of chain
pub static ref STARKNET_HIGHEST_BLOCK_HASH_AND_NUMBER: Arc<Mutex<(FieldElement, u64)>> = Arc::new(Mutex::new((FieldElement::default(), 0)));
/// Shared latest block number and hash of chain, using a RwLock to allow for concurrent reads and exclusive writes
static ref STARKNET_HIGHEST_BLOCK_HASH_AND_NUMBER: RwLock<(FieldElement, u64)> = RwLock::new((FieldElement::default(), 0));
}

/// The configuration of the worker responsible for fetching new blocks and state updates from the
Expand All @@ -74,19 +67,8 @@ pub struct FetchConfig {
pub workers: u32,
/// Whether to play a sound when a new block is fetched.
pub sound: bool,
}

impl Default for FetchConfig {
fn default() -> Self {
FetchConfig {
// Provide default values for each field of FetchConfig
gateway: Url::parse("http://default-gateway-url.com").unwrap(),
feeder_gateway: Url::parse("http://default-feeder-gateway-url.com").unwrap(),
chain_id: starknet_ff::FieldElement::default(), // Adjust as necessary
workers: 4,
sound: false,
}
}
/// The L1 contract core address
pub l1_core_address: H160,
}

/// The configuration of the senders responsible for sending blocks and state
Expand Down Expand Up @@ -141,7 +123,6 @@ pub async fn sync<B: BlockT>(
rpc_port: u16,
backend: Arc<mc_db::Backend<B>>,
) {
update_config(&config);
let SenderConfig { block_sender, state_update_sender, class_sender, command_sink, overrides } = &mut sender_config;
let client = SequencerGatewayProvider::new(config.gateway.clone(), config.feeder_gateway.clone(), config.chain_id);
let bonsai_dbs = BonsaiDbs {
Expand Down Expand Up @@ -436,7 +417,8 @@ async fn create_block(cmds: &mut CommandSink, parent_hash: &mut Option<H256>) ->
/// Update the L2 state with the latest data
pub fn update_l2(state_update: L2StateUpdate) {
{
let mut last_state_update = STARKNET_STATE_UPDATE.lock().expect("failed to lock STARKNET_STATE_UPDATE");
let mut last_state_update =
STARKNET_STATE_UPDATE.lock().expect("Failed to acquire lock on STARKNET_STATE_UPDATE");
*last_state_update = state_update.clone();
}
}
Expand Down Expand Up @@ -466,16 +448,22 @@ pub async fn verify_l2<B: BlockT>(
Ok(())
}

pub fn get_highest_block_hash_and_number() -> (FieldElement, u64) {
*STARKNET_HIGHEST_BLOCK_HASH_AND_NUMBER.lock().expect("failed to lock STARKNET_HIGHEST_BLOCK_HASH_AND_NUMBER")
}
async fn update_highest_block_hash_and_number(client: &SequencerGatewayProvider) -> Result<(), String> {
let block = client.get_block(BlockId::Latest).await.map_err(|e| format!("failed to get block: {e}"))?;

fn update_config(config: &FetchConfig) {
let last_config = CONFIG.clone();
let mut new_config = last_config.lock().unwrap();
*new_config = config.clone();
let hash = block.block_hash.ok_or("block hash not found")?;
let number = block.block_number.ok_or("block number not found")?;

let mut highest_block_hash_and_number = STARKNET_HIGHEST_BLOCK_HASH_AND_NUMBER
.write()
.expect("Failed to acquire write lock on STARKNET_HIGHEST_BLOCK_HASH_AND_NUMBER");
*highest_block_hash_and_number = (hash, number);

Ok(())
}

pub fn get_config() -> FetchConfig {
CONFIG.lock().unwrap().clone()
pub fn get_highest_block_hash_and_number() -> (FieldElement, u64) {
*STARKNET_HIGHEST_BLOCK_HASH_AND_NUMBER
.read()
.expect("Failed to acquire read lock on STARKNET_HIGHEST_BLOCK_HASH_AND_NUMBER")
}
9 changes: 8 additions & 1 deletion crates/client/sync/src/utils/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use starknet_ff::FieldElement;
use starknet_providers::sequencer::models as p;

use crate::commitments::lib::calculate_commitments;
use crate::utility::get_config;

pub async fn block(block: p::Block) -> mp_block::Block {
// converts starknet_provider transactions and events to mp_transactions and starknet_api events
Expand Down Expand Up @@ -207,7 +208,13 @@ async fn commitments(
}

fn chain_id() -> mp_felt::Felt252Wrapper {
starknet_ff::FieldElement::from_byte_slice_be(b"SN_MAIN").unwrap().into()
match get_config() {
Ok(config) => config.chain_id.into(),
Err(e) => {
log::error!("Failed to get chain id: {}", e);
FieldElement::from_byte_slice_be(b"").unwrap().into()
}
}
}

fn felt(field_element: starknet_ff::FieldElement) -> starknet_api::hash::StarkFelt {
Expand Down
44 changes: 23 additions & 21 deletions crates/client/sync/src/utils/utility.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,40 @@
//! Utility functions for Deoxys.

use std::error::Error;
use std::sync::RwLock;
use std::thread::sleep;
use std::time::Duration;

use ethers::types::I256;
use lazy_static::lazy_static;
use rand::seq::SliceRandom;
use rand::thread_rng;
use reqwest::header;
use serde_json::{json, Value};
use starknet_api::hash::StarkFelt;
use starknet_ff::FieldElement;
use starknet_providers::sequencer::models::BlockId;
use starknet_providers::SequencerGatewayProvider;

use crate::l1::{L1StateUpdate, LogStateUpdate};
use crate::l2::{L2StateUpdate, STARKNET_HIGHEST_BLOCK_HASH_AND_NUMBER};
use crate::l2::{FetchConfig, L2StateUpdate};

// TODO: find a better place to store this
lazy_static! {
/// Store the configuration globally, using a RwLock to allow for concurrent reads and exclusive writes
static ref CONFIG: RwLock<Option<FetchConfig>> = RwLock::new(None);
}

/// this function needs to be called only once at the start of the program
pub fn update_config(config: &FetchConfig) {
let mut new_config = CONFIG.write().expect("Failed to acquire write lock on CONFIG");
*new_config = Some(config.clone());
}

pub fn get_config() -> Result<FetchConfig, &'static str> {
let config_guard = CONFIG.read().expect("Failed to acquire read lock on CONFIG");
match &*config_guard {
Some(config) => Ok(config.clone()),
None => Err("Configuration not set yet"),
}
}

// TODO: secure the auto calls here

Expand Down Expand Up @@ -132,23 +151,6 @@ pub async fn get_state_update_at(rpc_port: u16, block_number: u64) -> Result<L2S
Err(Box::new(std::io::Error::new(std::io::ErrorKind::Other, "Maximum retries exceeded")))
}

pub async fn update_highest_block_hash_and_number(client: &SequencerGatewayProvider) -> Result<(), String> {
let block = client.get_block(BlockId::Latest).await.map_err(|e| format!("failed to get block: {e}"))?;

let hash = block.block_hash.ok_or("block hash not found")?;
let number = block.block_number.ok_or("block number not found")?;

let last_highest_block_hash_and_number = STARKNET_HIGHEST_BLOCK_HASH_AND_NUMBER.clone();
let mut new_highest_block_hash_and_number = last_highest_block_hash_and_number.lock().unwrap();
*new_highest_block_hash_and_number = (hash, number);

Ok(())
}

pub fn get_highest_block_hash_and_number() -> (FieldElement, u64) {
*STARKNET_HIGHEST_BLOCK_HASH_AND_NUMBER.lock().expect("failed to lock STARKNET_HIGHEST_BLOCK_HASH_AND_NUMBER")
}

/// Returns a random Pokémon name.
pub async fn get_random_pokemon_name() -> Result<String, Box<dyn std::error::Error>> {
let res = reqwest::get("https://pokeapi.co/api/v2/pokemon/?limit=1000").await?;
Expand Down
Loading

0 comments on commit cd75088

Please sign in to comment.