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

feat: implement get_filter_changes #221

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
6 changes: 5 additions & 1 deletion client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use eyre::{eyre, Result};
use common::types::BlockTag;
use config::{CheckpointFallback, Config};
use consensus::{types::Header, ConsensusClient};
use execution::types::{CallOpts, ExecutionBlock};
use execution::types::{CallOpts, ExecutionBlock, FilterChangesReturnType};
use log::{error, info, warn};
use tokio::sync::RwLock;

Expand Down Expand Up @@ -567,4 +567,8 @@ impl<DB: Database> Client<DB> {
pub async fn get_coinbase(&self) -> Result<Address> {
self.node.read().await.get_coinbase()
}

pub async fn get_filter_changes(&self, filter_id: U256) -> Result<FilterChangesReturnType> {
self.node.read().await.get_filter_changes(filter_id).await
}
}
7 changes: 6 additions & 1 deletion client/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use consensus::types::{ExecutionPayload, Header};
use consensus::ConsensusClient;
use execution::evm::Evm;
use execution::rpc::http_rpc::HttpRpc;
use execution::types::{CallOpts, ExecutionBlock};
use execution::types::{CallOpts, ExecutionBlock, FilterChangesReturnType};
use execution::ExecutionClient;

use crate::errors::NodeError;
Expand Down Expand Up @@ -264,6 +264,11 @@ impl Node {
self.execution.get_logs(filter, &self.payloads).await
}


pub async fn get_filter_changes(&self, filter_id: U256) -> Result<FilterChangesReturnType> {
self.execution.get_filter_changes(filter_id, &self.payloads).await
}

// assumes tip of 1 gwei to prevent having to prove out every tx in the block
pub fn get_gas_price(&self) -> Result<U256> {
self.check_head_age()?;
Expand Down
9 changes: 8 additions & 1 deletion client/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use common::{
types::BlockTag,
utils::{hex_str_to_bytes, u64_to_hex_string},
};
use execution::types::{CallOpts, ExecutionBlock};
use execution::types::{CallOpts, ExecutionBlock, FilterChangesReturnType};

pub struct Rpc {
node: Arc<RwLock<Node>>,
Expand Down Expand Up @@ -116,6 +116,8 @@ trait EthRpc {
async fn get_coinbase(&self) -> Result<Address, Error>;
#[method(name = "syncing")]
async fn syncing(&self) -> Result<SyncingStatus, Error>;
#[method(name = "getFilterChanges")]
async fn get_filter_changes(&self, filter_id: U256) -> Result<FilterChangesReturnType, Error>;
}

#[rpc(client, server, namespace = "net")]
Expand Down Expand Up @@ -302,6 +304,11 @@ impl EthRpcServer for RpcInner {

Ok(format_hex(&storage))
}

async fn get_filter_changes(&self, filter_id: U256) -> Result<FilterChangesReturnType, Error> {
let node = self.node.read().await;
convert_err(node.get_filter_changes(filter_id).await)
}
}

#[async_trait]
Expand Down
2 changes: 1 addition & 1 deletion config/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ pub struct Fork {
serialize_with = "bytes_serialize"
)]
pub fork_version: Vec<u8>,
}
}
60 changes: 59 additions & 1 deletion execution/src/execution.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::collections::{BTreeMap, HashMap};
use std::fmt::Debug;
use std::str::FromStr;

use ethers::abi::AbiEncode;
Expand All @@ -12,10 +13,12 @@ use common::utils::hex_str_to_bytes;
use consensus::types::ExecutionPayload;
use futures::future::join_all;
use revm::KECCAK_EMPTY;
use serde::Serialize;
use serde::de::DeserializeOwned;
use triehash_ethereum::ordered_trie_root;

use crate::errors::ExecutionError;
use crate::types::Transactions;
use crate::types::{Transactions, FilterChangesReturnType};

use super::proof::{encode_account, verify_proof};
use super::rpc::ExecutionRpc;
Expand Down Expand Up @@ -346,6 +349,61 @@ impl<R: ExecutionRpc> ExecutionClient<R> {
Ok(logs)
}

pub async fn get_filter_changes(
&self,
filter_id: U256,
payloads: &BTreeMap<u64, ExecutionPayload>,
) -> Result<FilterChangesReturnType>{
let filter_id = filter_id.clone();

let filter_return = self.rpc.get_filter_changes(filter_id).await?;

match filter_return {
FilterChangesReturnType::Log(logs) => {
if logs.len() > MAX_SUPPORTED_LOGS_NUMBER {
return Err(
ExecutionError::TooManyLogsToProve(logs.len(), MAX_SUPPORTED_LOGS_NUMBER).into(),
);
}

for (_pos, log) in logs.iter().enumerate() {
// For every log
// Get the hash of the tx that generated it
let tx_hash = log
.transaction_hash
.ok_or(eyre::eyre!("tx hash not found in log"))?;
// Get its proven receipt
let receipt = self
.get_transaction_receipt(&tx_hash, payloads)
.await?
.ok_or(ExecutionError::NoReceiptForTransaction(tx_hash.to_string()))?;

// Check if the receipt contains the desired log
// Encoding logs for comparison
let receipt_logs_encoded = receipt
.logs
.iter()
.map(|log| log.rlp_bytes())
.collect::<Vec<_>>();

let log_encoded = log.rlp_bytes();

if !receipt_logs_encoded.contains(&log_encoded) {
return Err(ExecutionError::MissingLog(
tx_hash.to_string(),
log.log_index.unwrap(),
)
.into());
}
}
Ok(FilterChangesReturnType::Log(logs))
},
FilterChangesReturnType::H256(h256s) => {
Ok(FilterChangesReturnType::H256(h256s))
}
}
}

pub async fn get_fee_history(
&self,
block_count: u64,
Expand Down
32 changes: 30 additions & 2 deletions execution/src/rpc/http_rpc.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::any::{Any, TypeId};
use std::str::FromStr;

use async_trait::async_trait;
Expand All @@ -11,7 +12,7 @@ use ethers::types::{
};
use eyre::Result;

use crate::types::CallOpts;
use crate::types::{CallOpts, FilterChangesReturnType};
use common::errors::RpcError;

use super::ExecutionRpc;
Expand All @@ -27,6 +28,20 @@ impl Clone for HttpRpc {
}
}


// test function, will remove before commiting it for production
fn convert_to_enum(value: &dyn std::any::Any) -> Option<FilterChangesReturnType> {
if let Some(logs) = value.downcast_ref::<Vec<Log>>() {
Some(FilterChangesReturnType::Log(logs.clone()))
} else if let Some(hashes) = value.downcast_ref::<Vec<H256>>() {
Some(FilterChangesReturnType::H256(hashes.clone()))
} else {
None
}

}


#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
impl ExecutionRpc for HttpRpc {
Expand Down Expand Up @@ -154,4 +169,17 @@ impl ExecutionRpc for HttpRpc {
.await
.map_err(|e| RpcError::new("fee_history", e))?)
}
}

async fn get_filter_changes(&self, filter_id: U256) -> Result<FilterChangesReturnType> {
let x = self
.provider.get_filter_changes(filter_id)
.await
.map_err(|e| RpcError::new("get_filter_changes", e)).unwrap();

// let y: FilterChangesReturnType = convert_to_enum(&x).unwrap();

// how to determine between log and h256??

Ok(FilterChangesReturnType::Log(x))
}
}
12 changes: 9 additions & 3 deletions execution/src/rpc/mock_rpc.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use std::{fs::read_to_string, path::PathBuf};
use std::{fs::read_to_string, path::PathBuf, fmt::Debug};

use async_trait::async_trait;
use common::utils::hex_str_to_bytes;
use ethers::types::{
transaction::eip2930::AccessList, Address, EIP1186ProofResponse, FeeHistory, Filter, Log,
Transaction, TransactionReceipt, H256,
Transaction, TransactionReceipt, H256, U256,
};
use eyre::{eyre, Result};
use serde::{de::DeserializeOwned, Serialize};

use crate::types::CallOpts;
use crate::types::{CallOpts, FilterChangesReturnType};

use super::ExecutionRpc;

Expand Down Expand Up @@ -76,4 +77,9 @@ impl ExecutionRpc for MockRpc {
let fee_history = read_to_string(self.path.join("fee_history.json"))?;
Ok(serde_json::from_str(&fee_history)?)
}

async fn get_filter_changes(&self, filter_id: U256) -> Result<FilterChangesReturnType> {
let logs = read_to_string(self.path.join("logs.json"))?;
Ok(serde_json::from_str(&logs)?)
}
}
8 changes: 6 additions & 2 deletions execution/src/rpc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::fmt::Debug;

use async_trait::async_trait;
use ethers::types::{
transaction::eip2930::AccessList, Address, EIP1186ProofResponse, FeeHistory, Filter, Log,
Transaction, TransactionReceipt, H256,
Transaction, TransactionReceipt, H256, U256,
};
use eyre::Result;
use serde::{de::DeserializeOwned, Serialize};

use crate::types::CallOpts;
use crate::types::{CallOpts, FilterChangesReturnType};

pub mod http_rpc;
pub mod mock_rpc;
Expand Down Expand Up @@ -37,4 +40,5 @@ pub trait ExecutionRpc: Send + Clone + Sync + 'static {
last_block: u64,
reward_percentiles: &[f64],
) -> Result<FeeHistory>;
async fn get_filter_changes(&self, filter_id: U256) -> Result<FilterChangesReturnType>;
}
8 changes: 7 additions & 1 deletion execution/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{collections::HashMap, fmt};

use ethers::{
prelude::{Address, H256, U256},
types::Transaction,
types::{Transaction, Log},
};
use eyre::Result;
use serde::{ser::SerializeSeq, Deserialize, Serialize};
Expand All @@ -19,6 +19,12 @@ pub struct Account {
pub slots: HashMap<H256, U256>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum FilterChangesReturnType {
Log(Vec<Log>),
H256(Vec<H256>)
}

#[derive(Deserialize, Serialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct ExecutionBlock {
Expand Down