feat: refactor client (#17)

* seperate client and node

* encapsule rpc inside client

* pass proper port into rpc

* track chain head in seperate thread

* client new takes config instead of arc

* refactor main

* add start method to client
This commit is contained in:
Noah Citron 2022-09-10 00:01:23 -04:00 committed by GitHub
parent b8d21abe44
commit cf6c211516
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 322 additions and 186 deletions

View File

@ -1,19 +1,24 @@
use std::{sync::Arc, time::Duration};
use clap::Parser; use clap::Parser;
use common::utils::hex_str_to_bytes; use common::utils::hex_str_to_bytes;
use dirs::home_dir; use dirs::home_dir;
use env_logger::Env; use env_logger::Env;
use eyre::Result; use eyre::Result;
use tokio::{sync::Mutex, time::sleep};
use client::{rpc::Rpc, Client}; use client::Client;
use config::{networks, Config}; use config::{networks, Config};
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init(); env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
let config = get_config()?;
let mut client = Client::new(config).await?;
client.start().await?;
std::future::pending().await
}
fn get_config() -> Result<Config> {
let cli = Cli::parse(); let cli = Cli::parse();
let mut config = match cli.network.as_str() { let mut config = match cli.network.as_str() {
"goerli" => networks::goerli(), "goerli" => networks::goerli(),
@ -28,26 +33,19 @@ async fn main() -> Result<()> {
config.general.checkpoint = hex_str_to_bytes(&checkpoint)?; config.general.checkpoint = hex_str_to_bytes(&checkpoint)?;
} }
let mut client = Client::new(Arc::new(config)).await?; if let Some(port) = cli.port {
client.sync().await?; config.general.rpc_port = Some(port);
let client = Arc::new(Mutex::new(client));
let mut rpc = Rpc::new(client.clone(), cli.port);
rpc.start().await?;
loop {
sleep(Duration::from_secs(10)).await;
client.lock().await.advance().await?
} }
Ok(config)
} }
#[derive(Parser)] #[derive(Parser)]
struct Cli { struct Cli {
#[clap(short, long, default_value = "goerli")] #[clap(short, long, default_value = "goerli")]
network: String, network: String,
#[clap(short, long, default_value = "8545")] #[clap(short, long)]
port: u16, port: Option<u16>,
#[clap(short, long)] #[clap(short, long)]
checkpoint: Option<String>, checkpoint: Option<String>,
} }

View File

@ -1,198 +1,132 @@
use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration;
use ethers::prelude::{Address, U256}; use ethers::prelude::{Address, U256};
use ethers::types::{Transaction, TransactionReceipt, H256}; use ethers::types::{Transaction, TransactionReceipt, H256};
use eyre::Result; use eyre::Result;
use config::Config; use config::Config;
use consensus::rpc::nimbus_rpc::NimbusRpc; use consensus::types::Header;
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};
use execution::ExecutionClient; use log::warn;
use tokio::spawn;
use tokio::sync::Mutex;
use tokio::time::sleep;
use crate::node::Node;
use crate::rpc::Rpc;
pub struct Client { pub struct Client {
consensus: ConsensusClient<NimbusRpc>, node: Arc<Mutex<Node>>,
execution: ExecutionClient<HttpRpc>, rpc: Option<Rpc>,
config: Arc<Config>,
payloads: HashMap<u64, ExecutionPayload>,
block_hashes: HashMap<Vec<u8>, u64>,
block_head: u64,
} }
impl Client { impl Client {
pub async fn new(config: Arc<Config>) -> Result<Self> { pub async fn new(config: Config) -> Result<Self> {
let consensus_rpc = &config.general.consensus_rpc; let config = Arc::new(config);
let checkpoint_hash = &config.general.checkpoint; let node = Node::new(config.clone()).await?;
let execution_rpc = &config.general.execution_rpc; let node = Arc::new(Mutex::new(node));
let consensus = let rpc = if let Some(port) = config.general.rpc_port {
ConsensusClient::new(consensus_rpc, checkpoint_hash, config.clone()).await?; Some(Rpc::new(node.clone(), port))
let execution = ExecutionClient::new(execution_rpc)?; } else {
None
};
let payloads = HashMap::new(); Ok(Client { node, rpc })
let block_hashes = HashMap::new();
Ok(Client {
consensus,
execution,
config,
payloads,
block_hashes,
block_head: 0,
})
} }
pub async fn sync(&mut self) -> Result<()> { pub async fn start(&mut self) -> Result<()> {
self.consensus.sync().await?; self.rpc.as_mut().unwrap().start().await?;
self.node.lock().await.sync().await?;
let head = self.consensus.get_header(); let node = self.node.clone();
let payload = self spawn(async move {
.consensus loop {
.get_execution_payload(&Some(head.slot)) let res = node.lock().await.advance().await;
.await?; if let Err(err) = res {
warn!("{}", err);
}
self.block_head = payload.block_number; sleep(Duration::from_secs(10)).await;
self.block_hashes }
.insert(payload.block_hash.to_vec(), payload.block_number); });
self.payloads.insert(payload.block_number, payload);
Ok(()) Ok(())
} }
pub async fn advance(&mut self) -> Result<()> { pub async fn call(&self, opts: &CallOpts, block: &Option<u64>) -> Result<Vec<u8>> {
self.consensus.advance().await?; self.node.lock().await.call(opts, block)
let head = self.consensus.get_header();
let payload = self
.consensus
.get_execution_payload(&Some(head.slot))
.await?;
self.block_head = payload.block_number;
self.block_hashes
.insert(payload.block_hash.to_vec(), payload.block_number);
self.payloads.insert(payload.block_number, payload);
Ok(())
} }
pub fn call(&self, opts: &CallOpts, block: &Option<u64>) -> Result<Vec<u8>> { pub async fn estimate_gas(&self, opts: &CallOpts) -> Result<u64> {
let payload = self.get_payload(block)?; self.node.lock().await.estimate_gas(opts)
let mut evm = Evm::new(self.execution.clone(), payload, self.chain_id());
evm.call(opts)
}
pub fn estimate_gas(&self, opts: &CallOpts) -> Result<u64> {
let payload = self.get_payload(&None)?;
let mut evm = Evm::new(self.execution.clone(), payload, self.chain_id());
evm.estimate_gas(opts)
} }
pub async fn get_balance(&self, address: &Address, block: &Option<u64>) -> Result<U256> { pub async fn get_balance(&self, address: &Address, block: &Option<u64>) -> Result<U256> {
let payload = self.get_payload(block)?; self.node.lock().await.get_balance(address, block).await
let account = self.execution.get_account(&address, None, &payload).await?;
Ok(account.balance)
} }
pub async fn get_nonce(&self, address: &Address, block: &Option<u64>) -> Result<u64> { pub async fn get_nonce(&self, address: &Address, block: &Option<u64>) -> Result<u64> {
let payload = self.get_payload(block)?; self.node.lock().await.get_nonce(address, block).await
let account = self.execution.get_account(&address, None, &payload).await?;
Ok(account.nonce)
} }
pub async fn get_code(&self, address: &Address, block: &Option<u64>) -> Result<Vec<u8>> { pub async fn get_code(&self, address: &Address, block: &Option<u64>) -> Result<Vec<u8>> {
let payload = self.get_payload(block)?; self.node.lock().await.get_code(address, block).await
self.execution.get_code(&address, &payload).await
} }
pub async fn get_storage_at(&self, address: &Address, slot: H256) -> Result<U256> { pub async fn get_storage_at(&self, address: &Address, slot: H256) -> Result<U256> {
let payload = self.get_payload(&None)?; self.node.lock().await.get_storage_at(address, slot).await
let account = self
.execution
.get_account(address, Some(&[slot]), &payload)
.await?;
let value = account.slots.get(&slot);
match value {
Some(value) => Ok(*value),
None => Err(eyre::eyre!("Slot Not Found")),
}
} }
pub async fn send_raw_transaction(&self, bytes: &Vec<u8>) -> Result<H256> { pub async fn send_raw_transaction(&self, bytes: &Vec<u8>) -> Result<H256> {
self.execution.send_raw_transaction(bytes).await self.node.lock().await.send_raw_transaction(bytes).await
} }
pub async fn get_transaction_receipt( pub async fn get_transaction_receipt(
&self, &self,
tx_hash: &H256, tx_hash: &H256,
) -> Result<Option<TransactionReceipt>> { ) -> Result<Option<TransactionReceipt>> {
self.execution self.node
.get_transaction_receipt(tx_hash, &self.payloads) .lock()
.await
.get_transaction_receipt(tx_hash)
.await .await
} }
pub async fn get_transaction_by_hash(&self, tx_hash: &H256) -> Result<Option<Transaction>> { pub async fn get_transaction_by_hash(&self, tx_hash: &H256) -> Result<Option<Transaction>> {
self.execution self.node
.get_transaction(tx_hash, &self.payloads) .lock()
.await
.get_transaction_by_hash(tx_hash)
.await .await
} }
pub fn get_gas_price(&self) -> Result<U256> { pub async fn get_gas_price(&self) -> Result<U256> {
let payload = self.get_payload(&None)?; self.node.lock().await.get_gas_price()
let base_fee = U256::from_little_endian(&payload.base_fee_per_gas.to_bytes_le());
let tip = U256::from(10_u64.pow(9));
Ok(base_fee + tip)
} }
pub fn get_priority_fee(&self) -> Result<U256> { pub async fn get_priority_fee(&self) -> Result<U256> {
let tip = U256::from(10_u64.pow(9)); self.node.lock().await.get_priority_fee()
Ok(tip)
} }
pub fn get_block_number(&self) -> Result<u64> { pub async fn get_block_number(&self) -> Result<u64> {
let payload = self.get_payload(&None)?; self.node.lock().await.get_block_number()
Ok(payload.block_number)
} }
pub fn get_block_by_number(&self, block: &Option<u64>) -> Result<ExecutionBlock> { pub async fn get_block_by_number(&self, block: &Option<u64>) -> Result<ExecutionBlock> {
let payload = self.get_payload(block)?; self.node.lock().await.get_block_by_number(block)
self.execution.get_block(&payload)
} }
pub fn get_block_by_hash(&self, hash: &Vec<u8>) -> Result<ExecutionBlock> { pub async fn get_block_by_hash(&self, hash: &Vec<u8>) -> Result<ExecutionBlock> {
let block = self.block_hashes.get(hash); self.node.lock().await.get_block_by_hash(hash)
let payload = self.get_payload(&block.cloned())?;
self.execution.get_block(&payload)
} }
pub fn chain_id(&self) -> u64 { pub async fn chain_id(&self) -> u64 {
self.config.general.chain_id self.node.lock().await.chain_id()
} }
pub fn get_header(&self) -> &Header { pub async fn get_header(&self) -> Header {
self.consensus.get_header() self.node.lock().await.get_header().clone()
}
fn get_payload(&self, block: &Option<u64>) -> Result<ExecutionPayload> {
match block {
Some(block) => {
let payload = self.payloads.get(block);
match payload {
Some(payload) => Ok(payload.clone()),
None => Err(eyre::eyre!("Block Not Found")),
}
}
None => {
let payload = self.payloads.get(&self.block_head);
match payload {
Some(payload) => Ok(payload.clone()),
None => Err(eyre::eyre!("Block Not Found")),
}
}
}
} }
} }

View File

@ -2,3 +2,5 @@ mod client;
pub use crate::client::*; pub use crate::client::*;
pub mod rpc; pub mod rpc;
mod node;

198
client/src/node.rs Normal file
View File

@ -0,0 +1,198 @@
use std::collections::HashMap;
use std::sync::Arc;
use ethers::prelude::{Address, U256};
use ethers::types::{Transaction, TransactionReceipt, H256};
use eyre::Result;
use config::Config;
use consensus::rpc::nimbus_rpc::NimbusRpc;
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::ExecutionClient;
pub struct Node {
consensus: ConsensusClient<NimbusRpc>,
execution: ExecutionClient<HttpRpc>,
config: Arc<Config>,
payloads: HashMap<u64, ExecutionPayload>,
block_hashes: HashMap<Vec<u8>, u64>,
block_head: u64,
}
impl Node {
pub async fn new(config: Arc<Config>) -> Result<Self> {
let consensus_rpc = &config.general.consensus_rpc;
let checkpoint_hash = &config.general.checkpoint;
let execution_rpc = &config.general.execution_rpc;
let consensus =
ConsensusClient::new(consensus_rpc, checkpoint_hash, config.clone()).await?;
let execution = ExecutionClient::new(execution_rpc)?;
let payloads = HashMap::new();
let block_hashes = HashMap::new();
Ok(Node {
consensus,
execution,
config,
payloads,
block_hashes,
block_head: 0,
})
}
pub async fn sync(&mut self) -> Result<()> {
self.consensus.sync().await?;
let head = self.consensus.get_header();
let payload = self
.consensus
.get_execution_payload(&Some(head.slot))
.await?;
self.block_head = payload.block_number;
self.block_hashes
.insert(payload.block_hash.to_vec(), payload.block_number);
self.payloads.insert(payload.block_number, payload);
Ok(())
}
pub async fn advance(&mut self) -> Result<()> {
self.consensus.advance().await?;
let head = self.consensus.get_header();
let payload = self
.consensus
.get_execution_payload(&Some(head.slot))
.await?;
self.block_head = payload.block_number;
self.block_hashes
.insert(payload.block_hash.to_vec(), payload.block_number);
self.payloads.insert(payload.block_number, payload);
Ok(())
}
pub fn call(&self, opts: &CallOpts, block: &Option<u64>) -> Result<Vec<u8>> {
let payload = self.get_payload(block)?;
let mut evm = Evm::new(self.execution.clone(), payload, self.chain_id());
evm.call(opts)
}
pub fn estimate_gas(&self, opts: &CallOpts) -> Result<u64> {
let payload = self.get_payload(&None)?;
let mut evm = Evm::new(self.execution.clone(), payload, self.chain_id());
evm.estimate_gas(opts)
}
pub async fn get_balance(&self, address: &Address, block: &Option<u64>) -> Result<U256> {
let payload = self.get_payload(block)?;
let account = self.execution.get_account(&address, None, &payload).await?;
Ok(account.balance)
}
pub async fn get_nonce(&self, address: &Address, block: &Option<u64>) -> Result<u64> {
let payload = self.get_payload(block)?;
let account = self.execution.get_account(&address, None, &payload).await?;
Ok(account.nonce)
}
pub async fn get_code(&self, address: &Address, block: &Option<u64>) -> Result<Vec<u8>> {
let payload = self.get_payload(block)?;
self.execution.get_code(&address, &payload).await
}
pub async fn get_storage_at(&self, address: &Address, slot: H256) -> Result<U256> {
let payload = self.get_payload(&None)?;
let account = self
.execution
.get_account(address, Some(&[slot]), &payload)
.await?;
let value = account.slots.get(&slot);
match value {
Some(value) => Ok(*value),
None => Err(eyre::eyre!("Slot Not Found")),
}
}
pub async fn send_raw_transaction(&self, bytes: &Vec<u8>) -> Result<H256> {
self.execution.send_raw_transaction(bytes).await
}
pub async fn get_transaction_receipt(
&self,
tx_hash: &H256,
) -> Result<Option<TransactionReceipt>> {
self.execution
.get_transaction_receipt(tx_hash, &self.payloads)
.await
}
pub async fn get_transaction_by_hash(&self, tx_hash: &H256) -> Result<Option<Transaction>> {
self.execution
.get_transaction(tx_hash, &self.payloads)
.await
}
pub fn get_gas_price(&self) -> Result<U256> {
let payload = self.get_payload(&None)?;
let base_fee = U256::from_little_endian(&payload.base_fee_per_gas.to_bytes_le());
let tip = U256::from(10_u64.pow(9));
Ok(base_fee + tip)
}
pub fn get_priority_fee(&self) -> Result<U256> {
let tip = U256::from(10_u64.pow(9));
Ok(tip)
}
pub fn get_block_number(&self) -> Result<u64> {
let payload = self.get_payload(&None)?;
Ok(payload.block_number)
}
pub fn get_block_by_number(&self, block: &Option<u64>) -> Result<ExecutionBlock> {
let payload = self.get_payload(block)?;
self.execution.get_block(&payload)
}
pub fn get_block_by_hash(&self, hash: &Vec<u8>) -> Result<ExecutionBlock> {
let block = self.block_hashes.get(hash);
let payload = self.get_payload(&block.cloned())?;
self.execution.get_block(&payload)
}
pub fn chain_id(&self) -> u64 {
self.config.general.chain_id
}
pub fn get_header(&self) -> &Header {
self.consensus.get_header()
}
fn get_payload(&self, block: &Option<u64>) -> Result<ExecutionPayload> {
match block {
Some(block) => {
let payload = self.payloads.get(block);
match payload {
Some(payload) => Ok(payload.clone()),
None => Err(eyre::eyre!("Block Not Found")),
}
}
None => {
let payload = self.payloads.get(&self.block_head);
match payload {
Some(payload) => Ok(payload.clone()),
None => Err(eyre::eyre!("Block Not Found")),
}
}
}
}
}

View File

@ -3,7 +3,7 @@ use ethers::{
types::{Address, Transaction, TransactionReceipt, H256}, types::{Address, Transaction, TransactionReceipt, H256},
}; };
use eyre::Result; use eyre::Result;
use log::{error, info}; use log::{info, warn};
use std::{fmt::Display, net::SocketAddr, str::FromStr, sync::Arc}; use std::{fmt::Display, net::SocketAddr, str::FromStr, sync::Arc};
use tokio::sync::Mutex; use tokio::sync::Mutex;
@ -13,20 +13,21 @@ use jsonrpsee::{
proc_macros::rpc, proc_macros::rpc,
}; };
use super::Client; use crate::node::Node;
use common::utils::{hex_str_to_bytes, u64_to_hex_string}; use common::utils::{hex_str_to_bytes, u64_to_hex_string};
use execution::types::{CallOpts, ExecutionBlock}; use execution::types::{CallOpts, ExecutionBlock};
pub struct Rpc { pub struct Rpc {
client: Arc<Mutex<Client>>, node: Arc<Mutex<Node>>,
handle: Option<HttpServerHandle>, handle: Option<HttpServerHandle>,
port: u16, port: u16,
} }
impl Rpc { impl Rpc {
pub fn new(client: Arc<Mutex<Client>>, port: u16) -> Self { pub fn new(node: Arc<Mutex<Node>>, port: u16) -> Self {
Rpc { Rpc {
client, node,
handle: None, handle: None,
port, port,
} }
@ -34,7 +35,7 @@ impl Rpc {
pub async fn start(&mut self) -> Result<SocketAddr> { pub async fn start(&mut self) -> Result<SocketAddr> {
let rpc_inner = RpcInner { let rpc_inner = RpcInner {
client: self.client.clone(), node: self.node.clone(),
port: self.port, port: self.port,
}; };
let (handle, addr) = start(rpc_inner).await?; let (handle, addr) = start(rpc_inner).await?;
@ -86,7 +87,7 @@ trait NetRpc {
#[derive(Clone)] #[derive(Clone)]
struct RpcInner { struct RpcInner {
client: Arc<Mutex<Client>>, node: Arc<Mutex<Node>>,
port: u16, port: u16,
} }
@ -95,8 +96,8 @@ impl EthRpcServer for RpcInner {
async fn get_balance(&self, address: &str, block: &str) -> Result<String, Error> { async fn get_balance(&self, address: &str, block: &str) -> Result<String, Error> {
let block = convert_err(decode_block(block))?; let block = convert_err(decode_block(block))?;
let address = convert_err(Address::from_str(address))?; let address = convert_err(Address::from_str(address))?;
let client = self.client.lock().await; let node = self.node.lock().await;
let balance = convert_err(client.get_balance(&address, &block).await)?; let balance = convert_err(node.get_balance(&address, &block).await)?;
Ok(balance.encode_hex()) Ok(balance.encode_hex())
} }
@ -104,8 +105,8 @@ impl EthRpcServer for RpcInner {
async fn get_transaction_count(&self, address: &str, block: &str) -> Result<String, Error> { async fn get_transaction_count(&self, address: &str, block: &str) -> Result<String, Error> {
let block = convert_err(decode_block(block))?; let block = convert_err(decode_block(block))?;
let address = convert_err(Address::from_str(address))?; let address = convert_err(Address::from_str(address))?;
let client = self.client.lock().await; let node = self.node.lock().await;
let nonce = convert_err(client.get_nonce(&address, &block).await)?; let nonce = convert_err(node.get_nonce(&address, &block).await)?;
Ok(nonce.encode_hex()) Ok(nonce.encode_hex())
} }
@ -113,48 +114,48 @@ impl EthRpcServer for RpcInner {
async fn get_code(&self, address: &str, block: &str) -> Result<String, Error> { async fn get_code(&self, address: &str, block: &str) -> Result<String, Error> {
let block = convert_err(decode_block(block))?; let block = convert_err(decode_block(block))?;
let address = convert_err(Address::from_str(address))?; let address = convert_err(Address::from_str(address))?;
let client = self.client.lock().await; let node = self.node.lock().await;
let code = convert_err(client.get_code(&address, &block).await)?; let code = convert_err(node.get_code(&address, &block).await)?;
Ok(hex::encode(code)) Ok(hex::encode(code))
} }
async fn call(&self, opts: CallOpts, block: &str) -> Result<String, Error> { async fn call(&self, opts: CallOpts, block: &str) -> Result<String, Error> {
let block = convert_err(decode_block(block))?; let block = convert_err(decode_block(block))?;
let client = self.client.lock().await; let node = self.node.lock().await;
let res = convert_err(client.call(&opts, &block))?; let res = convert_err(node.call(&opts, &block))?;
Ok(format!("0x{}", hex::encode(res))) Ok(format!("0x{}", hex::encode(res)))
} }
async fn estimate_gas(&self, opts: CallOpts) -> Result<String, Error> { async fn estimate_gas(&self, opts: CallOpts) -> Result<String, Error> {
let client = self.client.lock().await; let node = self.node.lock().await;
let gas = convert_err(client.estimate_gas(&opts))?; let gas = convert_err(node.estimate_gas(&opts))?;
Ok(u64_to_hex_string(gas)) Ok(u64_to_hex_string(gas))
} }
async fn chain_id(&self) -> Result<String, Error> { async fn chain_id(&self) -> Result<String, Error> {
let client = self.client.lock().await; let node = self.node.lock().await;
let id = client.chain_id(); let id = node.chain_id();
Ok(u64_to_hex_string(id)) Ok(u64_to_hex_string(id))
} }
async fn gas_price(&self) -> Result<String, Error> { async fn gas_price(&self) -> Result<String, Error> {
let client = self.client.lock().await; let node = self.node.lock().await;
let gas_price = convert_err(client.get_gas_price())?; let gas_price = convert_err(node.get_gas_price())?;
Ok(gas_price.encode_hex()) Ok(gas_price.encode_hex())
} }
async fn max_priority_fee_per_gas(&self) -> Result<String, Error> { async fn max_priority_fee_per_gas(&self) -> Result<String, Error> {
let client = self.client.lock().await; let node = self.node.lock().await;
let tip = convert_err(client.get_priority_fee())?; let tip = convert_err(node.get_priority_fee())?;
Ok(tip.encode_hex()) Ok(tip.encode_hex())
} }
async fn block_number(&self) -> Result<String, Error> { async fn block_number(&self) -> Result<String, Error> {
let client = self.client.lock().await; let node = self.node.lock().await;
let num = convert_err(client.get_block_number())?; let num = convert_err(node.get_block_number())?;
Ok(u64_to_hex_string(num)) Ok(u64_to_hex_string(num))
} }
@ -164,31 +165,31 @@ impl EthRpcServer for RpcInner {
_full_tx: bool, _full_tx: bool,
) -> Result<ExecutionBlock, Error> { ) -> Result<ExecutionBlock, Error> {
let block = convert_err(decode_block(block))?; let block = convert_err(decode_block(block))?;
let client = self.client.lock().await; let node = self.node.lock().await;
let block = convert_err(client.get_block_by_number(&block))?; let block = convert_err(node.get_block_by_number(&block))?;
Ok(block) Ok(block)
} }
async fn get_block_by_hash(&self, hash: &str, _full_tx: bool) -> Result<ExecutionBlock, Error> { async fn get_block_by_hash(&self, hash: &str, _full_tx: bool) -> Result<ExecutionBlock, Error> {
let hash = convert_err(hex_str_to_bytes(hash))?; let hash = convert_err(hex_str_to_bytes(hash))?;
let client = self.client.lock().await; let node = self.node.lock().await;
let block = convert_err(client.get_block_by_hash(&hash))?; let block = convert_err(node.get_block_by_hash(&hash))?;
Ok(block) Ok(block)
} }
async fn send_raw_transaction(&self, bytes: &str) -> Result<String, Error> { async fn send_raw_transaction(&self, bytes: &str) -> Result<String, Error> {
let client = self.client.lock().await; let node = self.node.lock().await;
let bytes = convert_err(hex_str_to_bytes(bytes))?; let bytes = convert_err(hex_str_to_bytes(bytes))?;
let tx_hash = convert_err(client.send_raw_transaction(&bytes).await)?; let tx_hash = convert_err(node.send_raw_transaction(&bytes).await)?;
Ok(hex::encode(tx_hash)) Ok(hex::encode(tx_hash))
} }
async fn get_transaction_receipt(&self, hash: &str) -> Result<TransactionReceipt, Error> { async fn get_transaction_receipt(&self, hash: &str) -> Result<TransactionReceipt, Error> {
let client = self.client.lock().await; let node = self.node.lock().await;
let hash = H256::from_slice(&convert_err(hex_str_to_bytes(hash))?); let hash = H256::from_slice(&convert_err(hex_str_to_bytes(hash))?);
let receipt = convert_err(client.get_transaction_receipt(&hash).await)?; let receipt = convert_err(node.get_transaction_receipt(&hash).await)?;
match receipt { match receipt {
Some(receipt) => Ok(receipt), Some(receipt) => Ok(receipt),
@ -197,9 +198,9 @@ impl EthRpcServer for RpcInner {
} }
async fn get_transaction_by_hash(&self, hash: &str) -> Result<Transaction, Error> { async fn get_transaction_by_hash(&self, hash: &str) -> Result<Transaction, Error> {
let client = self.client.lock().await; let node = self.node.lock().await;
let hash = H256::from_slice(&convert_err(hex_str_to_bytes(hash))?); let hash = H256::from_slice(&convert_err(hex_str_to_bytes(hash))?);
let tx = convert_err(client.get_transaction_by_hash(&hash).await)?; let tx = convert_err(node.get_transaction_by_hash(&hash).await)?;
match tx { match tx {
Some(tx) => Ok(tx), Some(tx) => Ok(tx),
@ -211,8 +212,8 @@ impl EthRpcServer for RpcInner {
#[async_trait] #[async_trait]
impl NetRpcServer for RpcInner { impl NetRpcServer for RpcInner {
async fn version(&self) -> Result<String, Error> { async fn version(&self) -> Result<String, Error> {
let client = self.client.lock().await; let node = self.node.lock().await;
Ok(client.chain_id().to_string()) Ok(node.chain_id().to_string())
} }
} }
@ -236,7 +237,7 @@ async fn start(rpc: RpcInner) -> Result<(HttpServerHandle, SocketAddr)> {
fn convert_err<T, E: Display>(res: Result<T, E>) -> Result<T, Error> { fn convert_err<T, E: Display>(res: Result<T, E>) -> Result<T, Error> {
res.map_err(|err| { res.map_err(|err| {
error!("{}", err); warn!("{}", err);
Error::Custom(err.to_string()) Error::Custom(err.to_string())
}) })
} }

View File

@ -5,6 +5,7 @@ genesis_root = "0x043db0d9a83813551ee2f33450d23797757d430911a9320530ad8a0eabc43e
checkpoint = "0x172128eadf1da46467f4d6a822206698e2d3f957af117dd650954780d680dc99" checkpoint = "0x172128eadf1da46467f4d6a822206698e2d3f957af117dd650954780d680dc99"
consensus_rpc = "http://testing.prater.beacon-api.nimbus.team" consensus_rpc = "http://testing.prater.beacon-api.nimbus.team"
execution_rpc = "https://eth-goerli.g.alchemy.com:443/v2/o_8Qa9kgwDPf9G8sroyQ-uQtyhyWa3ao" execution_rpc = "https://eth-goerli.g.alchemy.com:443/v2/o_8Qa9kgwDPf9G8sroyQ-uQtyhyWa3ao"
rpc_port = 8545
[forks] [forks]

View File

@ -23,6 +23,7 @@ pub struct General {
pub checkpoint: Vec<u8>, pub checkpoint: Vec<u8>,
pub consensus_rpc: String, pub consensus_rpc: String,
pub execution_rpc: String, pub execution_rpc: String,
pub rpc_port: Option<u16>,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]

View File

@ -19,6 +19,7 @@ pub fn goerli() -> Config {
execution_rpc: execution_rpc:
"https://eth-goerli.g.alchemy.com:443/v2/o_8Qa9kgwDPf9G8sroyQ-uQtyhyWa3ao" "https://eth-goerli.g.alchemy.com:443/v2/o_8Qa9kgwDPf9G8sroyQ-uQtyhyWa3ao"
.to_string(), .to_string(),
rpc_port: Some(8545),
}, },
forks: Forks { forks: Forks {
genesis: Fork { genesis: Fork {