Skip to content

Commit

Permalink
feat(papyrus_base_layer): start implementing eth events api
Browse files Browse the repository at this point in the history
- Currently only implementing the simplest event to parse, the rest are
  coming up.
- removed two unused error variants: `FeltParseError`, `Serde`
  • Loading branch information
Gilad Chase committed Dec 20, 2024
1 parent 5d52e5e commit 0f34dd6
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 11 deletions.
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.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ alloy-dyn-abi = "0.8.3"
alloy-json-rpc = "0.3.5"
alloy-primitives = "0.8.3"
alloy-provider = "0.3.5"
alloy-rpc-types-eth = "0.3.5"
alloy-sol-types = "0.8.3"
alloy-transport = "0.3.5"
alloy-transport-http = "0.3.5"
Expand Down
1 change: 1 addition & 0 deletions crates/papyrus_base_layer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ alloy-dyn-abi.workspace = true
alloy-json-rpc.workspace = true
alloy-primitives.workspace = true
alloy-provider.workspace = true
alloy-rpc-types-eth.workspace = true
alloy-sol-types = { workspace = true, features = ["json"] }
alloy-transport.workspace = true
alloy-transport-http.workspace = true
Expand Down
87 changes: 87 additions & 0 deletions crates/papyrus_base_layer/src/eth_events.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use std::sync::Arc;

use alloy_primitives::{Address as EthereumContractAddress, U256};
use alloy_rpc_types_eth::Log;
use alloy_sol_types::SolEvent;
use starknet_api::core::{EntryPointSelector, Nonce};
use starknet_api::transaction::fields::Calldata;
use starknet_types_core::felt::Felt;

use crate::ethereum_base_layer_contract::{
EthereumBaseLayerError,
EthereumBaseLayerResult,
Starknet,
};
use crate::{MessageData, StarknetEvent};

impl TryFrom<Log> for StarknetEvent {
type Error = EthereumBaseLayerError;

fn try_from(log: Log) -> EthereumBaseLayerResult<Self> {
let event_signature =
*log.topic0().ok_or_else(|| Self::Error::UnhandledL1Event(log.inner.clone()))?;
let validate = true;
let log = log.inner;

Ok(match event_signature {
sig if sig == Starknet::LogMessageToL2::SIGNATURE_HASH => {
todo!()
}
sig if sig == Starknet::MessageToL2CancellationStarted::SIGNATURE_HASH => {
let decoded = Starknet::MessageToL2CancellationStarted::decode_log(&log, validate)?;
StarknetEvent::MessageToL2CancellationStarted(decoded.try_into()?)
}
sig if sig == Starknet::MessageToL2Canceled::SIGNATURE_HASH => {
todo!()
}
sig if sig == Starknet::ConsumedMessageToL1::SIGNATURE_HASH => {
todo!()
}
_ => return Err(EthereumBaseLayerError::UnhandledL1Event(log)),
})
}
}

impl TryFrom<alloy_primitives::Log<Starknet::MessageToL2CancellationStarted>> for MessageData {
type Error = EthereumBaseLayerError;

fn try_from(
decoded: alloy_primitives::Log<Starknet::MessageToL2CancellationStarted>,
) -> EthereumBaseLayerResult<Self> {
create_l1_message_data(
decoded.fromAddress,
decoded.toAddress,
decoded.selector,
&decoded.payload,
decoded.nonce,
)
}
}

pub fn create_l1_message_data(
from_address: EthereumContractAddress,
to_address: U256,
selector: U256,
payload: &[U256],
nonce: U256,
) -> EthereumBaseLayerResult<MessageData> {
Ok(MessageData {
from_address: felt_from_eth_address(from_address)
.try_into()
.map_err(EthereumBaseLayerError::StarknetApiParsingError)?,
to_address: felt_from_u256(to_address)
.try_into()
.map_err(EthereumBaseLayerError::StarknetApiParsingError)?,
entry_point_selector: EntryPointSelector(felt_from_u256(selector)),
payload: Calldata(Arc::new(payload.iter().map(|&x| felt_from_u256(x)).collect())),
nonce: Nonce(felt_from_u256(nonce)),
})
}

pub fn felt_from_eth_address(address: EthereumContractAddress) -> Felt {
Felt::from_bytes_be_slice(address.0.as_slice())
}

pub fn felt_from_u256(num: U256) -> Felt {
Felt::from_bytes_be(&num.to_be_bytes())
}
35 changes: 24 additions & 11 deletions crates/papyrus_base_layer/src/ethereum_base_layer_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ use std::future::IntoFuture;

use alloy_dyn_abi::SolType;
use alloy_json_rpc::RpcError;
pub(crate) use alloy_primitives::Address as EthereumContractAddress;
use alloy_primitives::Address as EthereumContractAddress;
use alloy_provider::network::Ethereum;
use alloy_provider::{Provider, ProviderBuilder, RootProvider};
use alloy_rpc_types_eth::{BlockNumberOrTag, Filter as EthEventFilter};
use alloy_sol_types::{sol, sol_data};
use alloy_transport::TransportErrorKind;
use alloy_transport_http::{Client, Http};
Expand All @@ -15,12 +16,12 @@ use papyrus_config::{ParamPath, ParamPrivacyInput, SerializationType, Serialized
use serde::{Deserialize, Serialize};
use starknet_api::block::{BlockHash, BlockHashAndNumber, BlockNumber};
use starknet_api::hash::StarkHash;
use starknet_types_core::felt;
use starknet_api::StarknetApiError;
use url::Url;

use crate::{BaseLayerContract, StarknetEvent};

type EthereumBaseLayerResult<T> = Result<T, EthereumBaseLayerError>;
pub type EthereumBaseLayerResult<T> = Result<T, EthereumBaseLayerError>;

// Wraps the Starknet contract with a type that implements its interface, and is aware of its
// events.
Expand Down Expand Up @@ -81,11 +82,23 @@ impl BaseLayerContract for EthereumBaseLayerContract {

async fn events(
&self,
_from_block: u64,
_until_block: u64,
_event_identifiers: Vec<&str>,
from_block: u64,
until_block: u64,
events: Vec<&str>,
) -> EthereumBaseLayerResult<Vec<StarknetEvent>> {
todo!("Implmeneted in a subsequent commit")
let filter = EthEventFilter::new()
.from_block(BlockNumberOrTag::Number(from_block))
.events(events)
.to_block(until_block);

// Get all logs from the latest block that match the filter.
self.contract
.provider()
.get_logs(&filter)
.await?
.into_iter()
.map(TryInto::try_into)
.collect()
}

async fn latest_l1_block_number(&self, finality: u64) -> EthereumBaseLayerResult<Option<u64>> {
Expand All @@ -98,13 +111,13 @@ pub enum EthereumBaseLayerError {
#[error(transparent)]
Contract(#[from] alloy_contract::Error),
#[error(transparent)]
FeltParseError(#[from] felt::FromStrError),
#[error(transparent)]
RpcError(#[from] RpcError<TransportErrorKind>),
#[error(transparent)]
Serde(#[from] serde_json::Error),
#[error(transparent)]
TypeError(#[from] alloy_sol_types::Error),
#[error("{0}")]
StarknetApiParsingError(StarknetApiError),
#[error("{0:?}")]
UnhandledL1Event(alloy_primitives::Log),
}

#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
Expand Down
2 changes: 2 additions & 0 deletions crates/papyrus_base_layer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use starknet_api::transaction::L1HandlerTransaction;

pub mod ethereum_base_layer_contract;

pub(crate) mod eth_events;

#[cfg(any(feature = "testing", test))]
pub mod test_utils;

Expand Down

0 comments on commit 0f34dd6

Please sign in to comment.