feat: wasm support (#182)
* basic consensus setup * basic execution setup * patch for wasm * basic wasm client * proxy cors for testing * migrate to webpack * use typescript * track chain head * rename to helios-ts * better build instructions * add getCode * builds everywhere * add wasm-pack to dependencies * compile for both wasm and non-wasm * fix deps * fix deps * remove ds store * add blocktags * add getNonce * use BTreeMap to store payloads * add getTransaction * switch to proper ethers provider * post merge fixes * compile client to wasm * fix tests * fmt * use milagro for bls * handle node advance in rust * faster bls deserialization * clippy * add ConfigDB * remove ts bindings * fix gitignore * remove ts workspace member * remove unused mut * uncomment old deletions * bump to 0.2.0
This commit is contained in:
parent
604b325983
commit
72267b4563
|
@ -1,3 +1,3 @@
|
||||||
/target
|
.DS_Store
|
||||||
|
target
|
||||||
*.env
|
*.env
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "helios"
|
name = "helios"
|
||||||
version = "0.1.3"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
autobenches = false
|
autobenches = false
|
||||||
|
|
||||||
|
@ -21,11 +21,11 @@ common = { path = "./common" }
|
||||||
consensus = { path = "./consensus" }
|
consensus = { path = "./consensus" }
|
||||||
execution = { path = "./execution" }
|
execution = { path = "./execution" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
eyre = "0.6.8"
|
eyre = "0.6.8"
|
||||||
home = "0.5.4"
|
home = "0.5.4"
|
||||||
ethers = "1.0.2"
|
ethers = "1.0.0"
|
||||||
env_logger = "0.9.0"
|
env_logger = "0.9.0"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
tracing-test = "0.2.3"
|
tracing-test = "0.2.3"
|
||||||
|
@ -34,6 +34,9 @@ plotters = "0.3.3"
|
||||||
tempfile = "3.3.0"
|
tempfile = "3.3.0"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
ethers = { git = "https://github.com/gakonst/ethers-rs", rev = "c17c0c3c956f12d205a5ede3176599d8a30ca739" }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
strip = true
|
strip = true
|
||||||
opt-level = "z"
|
opt-level = "z"
|
||||||
|
|
|
@ -2,7 +2,7 @@ cargo-features = ["different-binary-name"]
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "cli"
|
name = "cli"
|
||||||
version = "0.1.3"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use std::{
|
use std::{
|
||||||
fs,
|
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
process::exit,
|
process::exit,
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
|
@ -104,10 +103,10 @@ struct Cli {
|
||||||
|
|
||||||
impl Cli {
|
impl Cli {
|
||||||
fn as_cli_config(&self) -> CliConfig {
|
fn as_cli_config(&self) -> CliConfig {
|
||||||
let checkpoint = match &self.checkpoint {
|
let checkpoint = self
|
||||||
Some(checkpoint) => Some(hex_str_to_bytes(checkpoint).expect("invalid checkpoint")),
|
.checkpoint
|
||||||
None => self.get_cached_checkpoint(),
|
.as_ref()
|
||||||
};
|
.map(|c| hex_str_to_bytes(c).expect("invalid checkpoint"));
|
||||||
|
|
||||||
CliConfig {
|
CliConfig {
|
||||||
checkpoint,
|
checkpoint,
|
||||||
|
@ -121,21 +120,6 @@ impl Cli {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_cached_checkpoint(&self) -> Option<Vec<u8>> {
|
|
||||||
let data_dir = self.get_data_dir();
|
|
||||||
let checkpoint_file = data_dir.join("checkpoint");
|
|
||||||
|
|
||||||
if checkpoint_file.exists() {
|
|
||||||
let checkpoint_res = fs::read(checkpoint_file);
|
|
||||||
match checkpoint_res {
|
|
||||||
Ok(checkpoint) => Some(checkpoint),
|
|
||||||
Err(_) => None,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_data_dir(&self) -> PathBuf {
|
fn get_data_dir(&self) -> PathBuf {
|
||||||
if let Some(dir) = &self.data_dir {
|
if let Some(dir) = &self.data_dir {
|
||||||
PathBuf::from_str(dir).expect("cannot find data dir")
|
PathBuf::from_str(dir).expect("cannot find data dir")
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
[package]
|
[package]
|
||||||
name = "client"
|
name = "client"
|
||||||
version = "0.1.3"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = { version = "1", features = ["full"] }
|
|
||||||
eyre = "0.6.8"
|
eyre = "0.6.8"
|
||||||
serde = { version = "1.0.143", features = ["derive"] }
|
serde = { version = "1.0.143", features = ["derive"] }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "cb08f18ca919cc1b685b861d0fa9e2daabe89737" }
|
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "d09f55b4f8554491e3431e01af1c32347a8781cd" }
|
||||||
ethers = "1.0.2"
|
ethers = "1.0.0"
|
||||||
jsonrpsee = { version = "0.15.1", features = ["full"] }
|
|
||||||
futures = "0.3.23"
|
futures = "0.3.23"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
thiserror = "1.0.37"
|
thiserror = "1.0.37"
|
||||||
|
@ -19,3 +17,13 @@ common = { path = "../common" }
|
||||||
consensus = { path = "../consensus" }
|
consensus = { path = "../consensus" }
|
||||||
execution = { path = "../execution" }
|
execution = { path = "../execution" }
|
||||||
config = { path = "../config" }
|
config = { path = "../config" }
|
||||||
|
|
||||||
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
|
jsonrpsee = { version = "0.15.1", features = ["full"] }
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
|
||||||
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
|
gloo-timers = "0.2.6"
|
||||||
|
wasm-bindgen-futures = "0.4.33"
|
||||||
|
tokio = { version = "1", features = ["sync"] }
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use config::networks::Network;
|
use config::networks::Network;
|
||||||
|
@ -12,13 +11,25 @@ use config::{CheckpointFallback, Config};
|
||||||
use consensus::{types::Header, ConsensusClient};
|
use consensus::{types::Header, ConsensusClient};
|
||||||
use execution::types::{CallOpts, ExecutionBlock};
|
use execution::types::{CallOpts, ExecutionBlock};
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use tokio::spawn;
|
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
use std::path::PathBuf;
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
use tokio::spawn;
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
|
|
||||||
use crate::database::{Database, FileDB};
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
use gloo_timers::callback::Interval;
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
use wasm_bindgen_futures::spawn_local;
|
||||||
|
|
||||||
|
use crate::database::Database;
|
||||||
use crate::errors::NodeError;
|
use crate::errors::NodeError;
|
||||||
use crate::node::Node;
|
use crate::node::Node;
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use crate::rpc::Rpc;
|
use crate::rpc::Rpc;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -27,7 +38,9 @@ pub struct ClientBuilder {
|
||||||
consensus_rpc: Option<String>,
|
consensus_rpc: Option<String>,
|
||||||
execution_rpc: Option<String>,
|
execution_rpc: Option<String>,
|
||||||
checkpoint: Option<Vec<u8>>,
|
checkpoint: Option<Vec<u8>>,
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
rpc_port: Option<u16>,
|
rpc_port: Option<u16>,
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
data_dir: Option<PathBuf>,
|
data_dir: Option<PathBuf>,
|
||||||
config: Option<Config>,
|
config: Option<Config>,
|
||||||
fallback: Option<String>,
|
fallback: Option<String>,
|
||||||
|
@ -62,11 +75,13 @@ impl ClientBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub fn rpc_port(mut self, port: u16) -> Self {
|
pub fn rpc_port(mut self, port: u16) -> Self {
|
||||||
self.rpc_port = Some(port);
|
self.rpc_port = Some(port);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub fn data_dir(mut self, data_dir: PathBuf) -> Self {
|
pub fn data_dir(mut self, data_dir: PathBuf) -> Self {
|
||||||
self.data_dir = Some(data_dir);
|
self.data_dir = Some(data_dir);
|
||||||
self
|
self
|
||||||
|
@ -92,7 +107,7 @@ impl ClientBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(self) -> Result<Client<FileDB>> {
|
pub fn build<DB: Database>(self) -> Result<Client<DB>> {
|
||||||
let base_config = if let Some(network) = self.network {
|
let base_config = if let Some(network) = self.network {
|
||||||
network.to_base_config()
|
network.to_base_config()
|
||||||
} else {
|
} else {
|
||||||
|
@ -127,6 +142,7 @@ impl ClientBuilder {
|
||||||
base_config.checkpoint
|
base_config.checkpoint
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
let rpc_port = if self.rpc_port.is_some() {
|
let rpc_port = if self.rpc_port.is_some() {
|
||||||
self.rpc_port
|
self.rpc_port
|
||||||
} else if let Some(config) = &self.config {
|
} else if let Some(config) = &self.config {
|
||||||
|
@ -135,6 +151,7 @@ impl ClientBuilder {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
let data_dir = if self.data_dir.is_some() {
|
let data_dir = if self.data_dir.is_some() {
|
||||||
self.data_dir
|
self.data_dir
|
||||||
} else if let Some(config) = &self.config {
|
} else if let Some(config) = &self.config {
|
||||||
|
@ -167,8 +184,14 @@ impl ClientBuilder {
|
||||||
consensus_rpc,
|
consensus_rpc,
|
||||||
execution_rpc,
|
execution_rpc,
|
||||||
checkpoint,
|
checkpoint,
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
rpc_port,
|
rpc_port,
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
rpc_port: None,
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
data_dir,
|
data_dir,
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
data_dir: None,
|
||||||
chain: base_config.chain,
|
chain: base_config.chain,
|
||||||
forks: base_config.forks,
|
forks: base_config.forks,
|
||||||
max_checkpoint_age: base_config.max_checkpoint_age,
|
max_checkpoint_age: base_config.max_checkpoint_age,
|
||||||
|
@ -183,35 +206,38 @@ impl ClientBuilder {
|
||||||
|
|
||||||
pub struct Client<DB: Database> {
|
pub struct Client<DB: Database> {
|
||||||
node: Arc<RwLock<Node>>,
|
node: Arc<RwLock<Node>>,
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
rpc: Option<Rpc>,
|
rpc: Option<Rpc>,
|
||||||
db: Option<DB>,
|
db: DB,
|
||||||
fallback: Option<String>,
|
fallback: Option<String>,
|
||||||
load_external_fallback: bool,
|
load_external_fallback: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client<FileDB> {
|
impl<DB: Database> Client<DB> {
|
||||||
fn new(config: Config) -> Result<Self> {
|
fn new(mut config: Config) -> Result<Self> {
|
||||||
|
let db = DB::new(&config)?;
|
||||||
|
let checkpoint = db.load_checkpoint()?;
|
||||||
|
config.checkpoint = checkpoint;
|
||||||
|
|
||||||
let config = Arc::new(config);
|
let config = Arc::new(config);
|
||||||
let node = Node::new(config.clone())?;
|
let node = Node::new(config.clone())?;
|
||||||
let node = Arc::new(RwLock::new(node));
|
let node = Arc::new(RwLock::new(node));
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
let rpc = config.rpc_port.map(|port| Rpc::new(node.clone(), port));
|
let rpc = config.rpc_port.map(|port| Rpc::new(node.clone(), port));
|
||||||
|
|
||||||
let data_dir = config.data_dir.clone();
|
|
||||||
let db = data_dir.map(FileDB::new);
|
|
||||||
|
|
||||||
Ok(Client {
|
Ok(Client {
|
||||||
node,
|
node,
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
rpc,
|
rpc,
|
||||||
db,
|
db,
|
||||||
fallback: config.fallback.clone(),
|
fallback: config.fallback.clone(),
|
||||||
load_external_fallback: config.load_external_fallback,
|
load_external_fallback: config.load_external_fallback,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<DB: Database> Client<DB> {
|
|
||||||
pub async fn start(&mut self) -> Result<()> {
|
pub async fn start(&mut self) -> Result<()> {
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
if let Some(rpc) = &mut self.rpc {
|
if let Some(rpc) = &mut self.rpc {
|
||||||
rpc.start().await?;
|
rpc.start().await?;
|
||||||
}
|
}
|
||||||
|
@ -241,6 +267,13 @@ impl<DB: Database> Client<DB> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.start_advance_thread();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
fn start_advance_thread(&self) {
|
||||||
let node = self.node.clone();
|
let node = self.node.clone();
|
||||||
spawn(async move {
|
spawn(async move {
|
||||||
loop {
|
loop {
|
||||||
|
@ -250,11 +283,25 @@ impl<DB: Database> Client<DB> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let next_update = node.read().await.duration_until_next_update();
|
let next_update = node.read().await.duration_until_next_update();
|
||||||
|
|
||||||
sleep(next_update).await;
|
sleep(next_update).await;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
fn start_advance_thread(&self) {
|
||||||
|
let node = self.node.clone();
|
||||||
|
Interval::new(12000, move || {
|
||||||
|
let node = node.clone();
|
||||||
|
spawn_local(async move {
|
||||||
|
let res = node.write().await.advance().await;
|
||||||
|
if let Err(err) = res {
|
||||||
|
warn!("consensus error: {}", err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn boot_from_fallback(&self) -> eyre::Result<()> {
|
async fn boot_from_fallback(&self) -> eyre::Result<()> {
|
||||||
|
@ -335,8 +382,8 @@ impl<DB: Database> Client<DB> {
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("saving last checkpoint hash");
|
info!("saving last checkpoint hash");
|
||||||
let res = self.db.as_ref().map(|db| db.save_checkpoint(checkpoint));
|
let res = self.db.save_checkpoint(checkpoint);
|
||||||
if res.is_some() && res.unwrap().is_err() {
|
if res.is_err() {
|
||||||
warn!("checkpoint save failed");
|
warn!("checkpoint save failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,40 @@
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use std::{
|
use std::{
|
||||||
fs,
|
fs,
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use config::Config;
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
|
|
||||||
pub trait Database {
|
pub trait Database {
|
||||||
|
fn new(config: &Config) -> Result<Self>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
fn save_checkpoint(&self, checkpoint: Vec<u8>) -> Result<()>;
|
fn save_checkpoint(&self, checkpoint: Vec<u8>) -> Result<()>;
|
||||||
fn load_checkpoint(&self) -> Result<Vec<u8>>;
|
fn load_checkpoint(&self) -> Result<Vec<u8>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub struct FileDB {
|
pub struct FileDB {
|
||||||
data_dir: PathBuf,
|
data_dir: PathBuf,
|
||||||
|
default_checkpoint: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileDB {
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub fn new(data_dir: PathBuf) -> Self {
|
|
||||||
FileDB { data_dir }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Database for FileDB {
|
impl Database for FileDB {
|
||||||
|
fn new(config: &Config) -> Result<Self> {
|
||||||
|
if let Some(data_dir) = &config.data_dir {
|
||||||
|
return Ok(FileDB {
|
||||||
|
data_dir: data_dir.to_path_buf(),
|
||||||
|
default_checkpoint: config.checkpoint.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
eyre::bail!("data dir not in config")
|
||||||
|
}
|
||||||
|
|
||||||
fn save_checkpoint(&self, checkpoint: Vec<u8>) -> Result<()> {
|
fn save_checkpoint(&self, checkpoint: Vec<u8>) -> Result<()> {
|
||||||
fs::create_dir_all(&self.data_dir)?;
|
fs::create_dir_all(&self.data_dir)?;
|
||||||
|
|
||||||
|
@ -44,6 +57,30 @@ impl Database for FileDB {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
f.read_to_end(&mut buf)?;
|
f.read_to_end(&mut buf)?;
|
||||||
|
|
||||||
Ok(buf)
|
if buf.len() == 32 {
|
||||||
|
Ok(buf)
|
||||||
|
} else {
|
||||||
|
Ok(self.default_checkpoint.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ConfigDB {
|
||||||
|
checkpoint: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Database for ConfigDB {
|
||||||
|
fn new(config: &Config) -> Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
checkpoint: config.checkpoint.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_checkpoint(&self) -> Result<Vec<u8>> {
|
||||||
|
Ok(self.checkpoint.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_checkpoint(&self, _checkpoint: Vec<u8>) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ pub enum NodeError {
|
||||||
BlockNotFoundError(#[from] BlockNotFoundError),
|
BlockNotFoundError(#[from] BlockNotFoundError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
impl NodeError {
|
impl NodeError {
|
||||||
pub fn to_json_rpsee_error(self) -> jsonrpsee::core::Error {
|
pub fn to_json_rpsee_error(self) -> jsonrpsee::core::Error {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -3,6 +3,8 @@ pub use crate::client::*;
|
||||||
|
|
||||||
pub mod database;
|
pub mod database;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub mod rpc;
|
pub mod rpc;
|
||||||
|
|
||||||
mod node;
|
pub mod node;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
[package]
|
[package]
|
||||||
name = "common"
|
name = "common"
|
||||||
version = "0.1.3"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
eyre = "0.6.8"
|
eyre = "0.6.8"
|
||||||
serde = { version = "1.0.143", features = ["derive"] }
|
serde = { version = "1.0.143", features = ["derive"] }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "cb08f18ca919cc1b685b861d0fa9e2daabe89737" }
|
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "d09f55b4f8554491e3431e01af1c32347a8781cd" }
|
||||||
ethers = "1.0.2"
|
ethers = "1.0.0"
|
||||||
thiserror = "1.0.37"
|
thiserror = "1.0.37"
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "config"
|
name = "config"
|
||||||
version = "0.1.3"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = { version = "1", features = ["full"] }
|
|
||||||
eyre = "0.6.8"
|
eyre = "0.6.8"
|
||||||
serde = { version = "1.0.143", features = ["derive"] }
|
serde = { version = "1.0.143", features = ["derive"] }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "cb08f18ca919cc1b685b861d0fa9e2daabe89737" }
|
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "d09f55b4f8554491e3431e01af1c32347a8781cd" }
|
||||||
ethers = "1.0.2"
|
ethers = "1.0.0"
|
||||||
figment = { version = "0.10.7", features = ["toml", "env"] }
|
figment = { version = "0.10.7", features = ["toml", "env"] }
|
||||||
thiserror = "1.0.37"
|
thiserror = "1.0.37"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
|
|
||||||
common = { path = "../common" }
|
|
||||||
reqwest = "0.11.13"
|
reqwest = "0.11.13"
|
||||||
serde_yaml = "0.9.14"
|
serde_yaml = "0.9.14"
|
||||||
strum = "0.24.1"
|
strum = "0.24.1"
|
||||||
futures = "0.3.25"
|
futures = "0.3.25"
|
||||||
|
|
||||||
|
common = { path = "../common" }
|
||||||
|
|
||||||
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
|
|
@ -136,26 +136,25 @@ impl CheckpointFallback {
|
||||||
// Iterate over all mainnet checkpoint sync services and get the latest checkpoint slot for each.
|
// Iterate over all mainnet checkpoint sync services and get the latest checkpoint slot for each.
|
||||||
let tasks: Vec<_> = services
|
let tasks: Vec<_> = services
|
||||||
.iter()
|
.iter()
|
||||||
.map(|service| {
|
.map(|service| async move {
|
||||||
let service = service.clone();
|
let service = service.clone();
|
||||||
tokio::spawn(async move {
|
match Self::query_service(&service.endpoint).await {
|
||||||
match Self::query_service(&service.endpoint).await {
|
Some(raw) => {
|
||||||
Some(raw) => {
|
if raw.data.slots.is_empty() {
|
||||||
if raw.data.slots.is_empty() {
|
return Err(eyre::eyre!("no slots"));
|
||||||
return Err(eyre::eyre!("no slots"));
|
|
||||||
}
|
|
||||||
Ok(raw.data.slots[0].clone())
|
|
||||||
}
|
}
|
||||||
None => Err(eyre::eyre!("failed to query service")),
|
Ok(raw.data.slots[0].clone())
|
||||||
}
|
}
|
||||||
})
|
None => Err(eyre::eyre!("failed to query service")),
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let slots = futures::future::join_all(tasks)
|
let slots = futures::future::join_all(tasks)
|
||||||
.await
|
.await
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|slot| match &slot {
|
.filter_map(|slot| match &slot {
|
||||||
Ok(Ok(s)) => Some(s.clone()),
|
Ok(s) => Some(s.clone()),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
|
@ -36,7 +36,7 @@ impl Network {
|
||||||
pub fn mainnet() -> BaseConfig {
|
pub fn mainnet() -> BaseConfig {
|
||||||
BaseConfig {
|
BaseConfig {
|
||||||
checkpoint: hex_str_to_bytes(
|
checkpoint: hex_str_to_bytes(
|
||||||
"0x428ce0b5f5bbed1fc2b3feb5d4152ae0fe98a80b1bfa8de36681868e81e9222a",
|
"0x766647f3c4e1fc91c0db9a9374032ae038778411fbff222974e11f2e3ce7dadf",
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
rpc_port: 8545,
|
rpc_port: 8545,
|
||||||
|
|
|
@ -1,27 +1,31 @@
|
||||||
[package]
|
[package]
|
||||||
name = "consensus"
|
name = "consensus"
|
||||||
version = "0.1.3"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = { version = "1", features = ["full"] }
|
|
||||||
eyre = "0.6.8"
|
eyre = "0.6.8"
|
||||||
serde = { version = "1.0.143", features = ["derive"] }
|
serde = { version = "1.0.143", features = ["derive"] }
|
||||||
serde_json = "1.0.85"
|
serde_json = "1.0.85"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "cb08f18ca919cc1b685b861d0fa9e2daabe89737" }
|
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "d09f55b4f8554491e3431e01af1c32347a8781cd" }
|
||||||
blst = "0.3.10"
|
milagro_bls = { git = "https://github.com/Snowfork/milagro_bls" }
|
||||||
ethers = "1.0.2"
|
ethers = "1.0.0"
|
||||||
bytes = "1.2.1"
|
bytes = "1.2.1"
|
||||||
toml = "0.5.9"
|
toml = "0.5.9"
|
||||||
async-trait = "0.1.57"
|
async-trait = "0.1.57"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
chrono = "0.4.22"
|
chrono = "0.4.22"
|
||||||
thiserror = "1.0.37"
|
thiserror = "1.0.37"
|
||||||
openssl = { version = "0.10", features = ["vendored"] }
|
reqwest = { version = "0.11.13", features = ["json"] }
|
||||||
reqwest = { version = "0.11.12", features = ["json"] }
|
|
||||||
reqwest-middleware = "0.1.6"
|
|
||||||
reqwest-retry = "0.1.5"
|
|
||||||
|
|
||||||
common = { path = "../common" }
|
common = { path = "../common" }
|
||||||
config = { path = "../config" }
|
config = { path = "../config" }
|
||||||
|
|
||||||
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
|
openssl = { version = "0.10", features = ["vendored"] }
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
|
||||||
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
|
wasm-timer = "0.2.5"
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::UNIX_EPOCH;
|
|
||||||
|
|
||||||
use blst::min_pk::PublicKey;
|
|
||||||
use chrono::Duration;
|
use chrono::Duration;
|
||||||
use eyre::eyre;
|
use eyre::eyre;
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
|
use milagro_bls::PublicKey;
|
||||||
use ssz_rs::prelude::*;
|
use ssz_rs::prelude::*;
|
||||||
|
|
||||||
use common::types::*;
|
use common::types::*;
|
||||||
|
@ -21,9 +20,20 @@ use super::rpc::ConsensusRpc;
|
||||||
use super::types::*;
|
use super::types::*;
|
||||||
use super::utils::*;
|
use super::utils::*;
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
use std::time::SystemTime;
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
use std::time::UNIX_EPOCH;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
use wasm_timer::SystemTime;
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
use wasm_timer::UNIX_EPOCH;
|
||||||
|
|
||||||
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md
|
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md
|
||||||
// does not implement force updates
|
// does not implement force updates
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct ConsensusClient<R: ConsensusRpc> {
|
pub struct ConsensusClient<R: ConsensusRpc> {
|
||||||
rpc: R,
|
rpc: R,
|
||||||
store: LightClientStore,
|
store: LightClientStore,
|
||||||
|
@ -480,18 +490,13 @@ impl<R: ConsensusRpc> ConsensusClient<R> {
|
||||||
|
|
||||||
fn age(&self, slot: u64) -> Duration {
|
fn age(&self, slot: u64) -> Duration {
|
||||||
let expected_time = self.slot_timestamp(slot);
|
let expected_time = self.slot_timestamp(slot);
|
||||||
let now = std::time::SystemTime::now()
|
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
|
||||||
.duration_since(UNIX_EPOCH)
|
|
||||||
.unwrap();
|
|
||||||
let delay = now - std::time::Duration::from_secs(expected_time);
|
let delay = now - std::time::Duration::from_secs(expected_time);
|
||||||
chrono::Duration::from_std(delay).unwrap()
|
chrono::Duration::from_std(delay).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expected_current_slot(&self) -> u64 {
|
pub fn expected_current_slot(&self) -> u64 {
|
||||||
let now = std::time::SystemTime::now()
|
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
|
||||||
.duration_since(UNIX_EPOCH)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let genesis_time = self.config.chain.genesis_time;
|
let genesis_time = self.config.chain.genesis_time;
|
||||||
let since_genesis = now - std::time::Duration::from_secs(genesis_time);
|
let since_genesis = now - std::time::Duration::from_secs(genesis_time);
|
||||||
|
|
||||||
|
@ -509,7 +514,7 @@ impl<R: ConsensusRpc> ConsensusClient<R> {
|
||||||
let next_slot = current_slot + 1;
|
let next_slot = current_slot + 1;
|
||||||
let next_slot_timestamp = self.slot_timestamp(next_slot);
|
let next_slot_timestamp = self.slot_timestamp(next_slot);
|
||||||
|
|
||||||
let now = std::time::SystemTime::now()
|
let now = SystemTime::now()
|
||||||
.duration_since(UNIX_EPOCH)
|
.duration_since(UNIX_EPOCH)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_secs();
|
.as_secs();
|
||||||
|
@ -540,7 +545,7 @@ fn get_participating_keys(
|
||||||
bitfield.iter().enumerate().for_each(|(i, bit)| {
|
bitfield.iter().enumerate().for_each(|(i, bit)| {
|
||||||
if bit == true {
|
if bit == true {
|
||||||
let pk = &committee.pubkeys[i];
|
let pk = &committee.pubkeys[i];
|
||||||
let pk = PublicKey::from_bytes(pk).unwrap();
|
let pk = PublicKey::from_bytes_unchecked(pk).unwrap();
|
||||||
pks.push(pk);
|
pks.push(pk);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,8 @@ pub struct MockRpc {
|
||||||
testdata: PathBuf,
|
testdata: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||||
impl ConsensusRpc for MockRpc {
|
impl ConsensusRpc for MockRpc {
|
||||||
fn new(path: &str) -> Self {
|
fn new(path: &str) -> Self {
|
||||||
MockRpc {
|
MockRpc {
|
||||||
|
|
|
@ -7,7 +7,8 @@ use eyre::Result;
|
||||||
use crate::types::{BeaconBlock, Bootstrap, FinalityUpdate, OptimisticUpdate, Update};
|
use crate::types::{BeaconBlock, Bootstrap, FinalityUpdate, OptimisticUpdate, Update};
|
||||||
|
|
||||||
// implements https://github.com/ethereum/beacon-APIs/tree/master/apis/beacon/light_client
|
// implements https://github.com/ethereum/beacon-APIs/tree/master/apis/beacon/light_client
|
||||||
#[async_trait]
|
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||||
pub trait ConsensusRpc {
|
pub trait ConsensusRpc {
|
||||||
fn new(path: &str) -> Self;
|
fn new(path: &str) -> Self;
|
||||||
async fn get_bootstrap(&self, block_root: &'_ [u8]) -> Result<Bootstrap>;
|
async fn get_bootstrap(&self, block_root: &'_ [u8]) -> Result<Bootstrap>;
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
|
|
||||||
use reqwest_retry::{policies::ExponentialBackoff, RetryTransientMiddleware};
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
|
||||||
use super::ConsensusRpc;
|
use super::ConsensusRpc;
|
||||||
|
@ -9,25 +7,17 @@ use crate::constants::MAX_REQUEST_LIGHT_CLIENT_UPDATES;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
use common::errors::RpcError;
|
use common::errors::RpcError;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct NimbusRpc {
|
pub struct NimbusRpc {
|
||||||
rpc: String,
|
rpc: String,
|
||||||
client: ClientWithMiddleware,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||||
impl ConsensusRpc for NimbusRpc {
|
impl ConsensusRpc for NimbusRpc {
|
||||||
fn new(rpc: &str) -> Self {
|
fn new(rpc: &str) -> Self {
|
||||||
let retry_policy = ExponentialBackoff::builder()
|
|
||||||
.backoff_exponent(1)
|
|
||||||
.build_with_max_retries(3);
|
|
||||||
|
|
||||||
let client = ClientBuilder::new(reqwest::Client::new())
|
|
||||||
.with(RetryTransientMiddleware::new_with_policy(retry_policy))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
NimbusRpc {
|
NimbusRpc {
|
||||||
rpc: rpc.to_string(),
|
rpc: rpc.to_string(),
|
||||||
client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,8 +28,8 @@ impl ConsensusRpc for NimbusRpc {
|
||||||
self.rpc, root_hex
|
self.rpc, root_hex
|
||||||
);
|
);
|
||||||
|
|
||||||
let res = self
|
let client = reqwest::Client::new();
|
||||||
.client
|
let res = client
|
||||||
.get(req)
|
.get(req)
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
|
@ -58,8 +48,8 @@ impl ConsensusRpc for NimbusRpc {
|
||||||
self.rpc, period, count
|
self.rpc, period, count
|
||||||
);
|
);
|
||||||
|
|
||||||
let res = self
|
let client = reqwest::Client::new();
|
||||||
.client
|
let res = client
|
||||||
.get(req)
|
.get(req)
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
|
@ -73,10 +63,7 @@ impl ConsensusRpc for NimbusRpc {
|
||||||
|
|
||||||
async fn get_finality_update(&self) -> Result<FinalityUpdate> {
|
async fn get_finality_update(&self) -> Result<FinalityUpdate> {
|
||||||
let req = format!("{}/eth/v1/beacon/light_client/finality_update", self.rpc);
|
let req = format!("{}/eth/v1/beacon/light_client/finality_update", self.rpc);
|
||||||
let res = self
|
let res = reqwest::get(req)
|
||||||
.client
|
|
||||||
.get(req)
|
|
||||||
.send()
|
|
||||||
.await
|
.await
|
||||||
.map_err(|e| RpcError::new("finality_update", e))?
|
.map_err(|e| RpcError::new("finality_update", e))?
|
||||||
.json::<FinalityUpdateResponse>()
|
.json::<FinalityUpdateResponse>()
|
||||||
|
@ -88,10 +75,7 @@ impl ConsensusRpc for NimbusRpc {
|
||||||
|
|
||||||
async fn get_optimistic_update(&self) -> Result<OptimisticUpdate> {
|
async fn get_optimistic_update(&self) -> Result<OptimisticUpdate> {
|
||||||
let req = format!("{}/eth/v1/beacon/light_client/optimistic_update", self.rpc);
|
let req = format!("{}/eth/v1/beacon/light_client/optimistic_update", self.rpc);
|
||||||
let res = self
|
let res = reqwest::get(req)
|
||||||
.client
|
|
||||||
.get(req)
|
|
||||||
.send()
|
|
||||||
.await
|
.await
|
||||||
.map_err(|e| RpcError::new("optimistic_update", e))?
|
.map_err(|e| RpcError::new("optimistic_update", e))?
|
||||||
.json::<OptimisticUpdateResponse>()
|
.json::<OptimisticUpdateResponse>()
|
||||||
|
@ -103,10 +87,7 @@ impl ConsensusRpc for NimbusRpc {
|
||||||
|
|
||||||
async fn get_block(&self, slot: u64) -> Result<BeaconBlock> {
|
async fn get_block(&self, slot: u64) -> Result<BeaconBlock> {
|
||||||
let req = format!("{}/eth/v2/beacon/blocks/{}", self.rpc, slot);
|
let req = format!("{}/eth/v2/beacon/blocks/{}", self.rpc, slot);
|
||||||
let res = self
|
let res = reqwest::get(req)
|
||||||
.client
|
|
||||||
.get(req)
|
|
||||||
.send()
|
|
||||||
.await
|
.await
|
||||||
.map_err(|e| RpcError::new("blocks", e))?
|
.map_err(|e| RpcError::new("blocks", e))?
|
||||||
.json::<BeaconBlockResponse>()
|
.json::<BeaconBlockResponse>()
|
||||||
|
@ -118,10 +99,7 @@ impl ConsensusRpc for NimbusRpc {
|
||||||
|
|
||||||
async fn chain_id(&self) -> Result<u64> {
|
async fn chain_id(&self) -> Result<u64> {
|
||||||
let req = format!("{}/eth/v1/config/spec", self.rpc);
|
let req = format!("{}/eth/v1/config/spec", self.rpc);
|
||||||
let res = self
|
let res = reqwest::get(req)
|
||||||
.client
|
|
||||||
.get(req)
|
|
||||||
.send()
|
|
||||||
.await
|
.await
|
||||||
.map_err(|e| RpcError::new("spec", e))?
|
.map_err(|e| RpcError::new("spec", e))?
|
||||||
.json::<SpecResponse>()
|
.json::<SpecResponse>()
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
use blst::{
|
|
||||||
min_pk::{PublicKey, Signature},
|
|
||||||
BLST_ERROR,
|
|
||||||
};
|
|
||||||
use common::{types::Bytes32, utils::bytes32_to_node};
|
use common::{types::Bytes32, utils::bytes32_to_node};
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
|
use milagro_bls::{AggregateSignature, PublicKey};
|
||||||
use ssz_rs::prelude::*;
|
use ssz_rs::prelude::*;
|
||||||
|
|
||||||
use crate::types::{Header, SignatureBytes};
|
use crate::types::{Header, SignatureBytes};
|
||||||
|
@ -14,10 +11,9 @@ pub fn calc_sync_period(slot: u64) -> u64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_aggregate_valid(sig_bytes: &SignatureBytes, msg: &[u8], pks: &[&PublicKey]) -> bool {
|
pub fn is_aggregate_valid(sig_bytes: &SignatureBytes, msg: &[u8], pks: &[&PublicKey]) -> bool {
|
||||||
let dst: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
|
let sig_res = AggregateSignature::from_bytes(sig_bytes);
|
||||||
let sig_res = Signature::from_bytes(sig_bytes);
|
|
||||||
match sig_res {
|
match sig_res {
|
||||||
Ok(sig) => sig.fast_aggregate_verify(true, msg, dst, pks) == BLST_ERROR::BLST_SUCCESS,
|
Ok(sig) => sig.fast_aggregate_verify(msg, pks),
|
||||||
Err(_) => false,
|
Err(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::str::FromStr;
|
||||||
use env_logger::Env;
|
use env_logger::Env;
|
||||||
use ethers::{types::Address, utils};
|
use ethers::{types::Address, utils};
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
use helios::{client::ClientBuilder, config::networks::Network, types::BlockTag};
|
use helios::{config::networks::Network, prelude::*};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
|
@ -15,12 +15,13 @@ async fn main() -> Result<()> {
|
||||||
let consensus_rpc = "https://www.lightclientdata.org";
|
let consensus_rpc = "https://www.lightclientdata.org";
|
||||||
log::info!("Using consensus RPC URL: {}", consensus_rpc);
|
log::info!("Using consensus RPC URL: {}", consensus_rpc);
|
||||||
|
|
||||||
let mut client = ClientBuilder::new()
|
let mut client: Client<FileDB> = ClientBuilder::new()
|
||||||
.network(Network::MAINNET)
|
.network(Network::MAINNET)
|
||||||
.consensus_rpc(consensus_rpc)
|
.consensus_rpc(consensus_rpc)
|
||||||
.execution_rpc(untrusted_rpc_url)
|
.execution_rpc(untrusted_rpc_url)
|
||||||
.load_external_fallback()
|
.load_external_fallback()
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
log::info!(
|
log::info!(
|
||||||
"Built client on network \"{}\" with external checkpoint fallbacks",
|
"Built client on network \"{}\" with external checkpoint fallbacks",
|
||||||
Network::MAINNET
|
Network::MAINNET
|
||||||
|
|
|
@ -35,7 +35,7 @@ async fn main() -> Result<()> {
|
||||||
builder = builder.load_external_fallback();
|
builder = builder.load_external_fallback();
|
||||||
|
|
||||||
// Build the client
|
// Build the client
|
||||||
let _client = builder.build().unwrap();
|
let _client: Client<FileDB> = builder.build().unwrap();
|
||||||
println!("Constructed client!");
|
println!("Constructed client!");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
[package]
|
[package]
|
||||||
name = "execution"
|
name = "execution"
|
||||||
version = "0.1.3"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
reqwest = { version = "0.11", features = ["json"] }
|
reqwest = { version = "0.11", features = ["json"] }
|
||||||
tokio = { version = "1", features = ["full"] }
|
|
||||||
eyre = "0.6.8"
|
eyre = "0.6.8"
|
||||||
serde = { version = "1.0.143", features = ["derive"] }
|
serde = { version = "1.0.143", features = ["derive"] }
|
||||||
serde_json = "1.0.85"
|
serde_json = "1.0.85"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "cb08f18ca919cc1b685b861d0fa9e2daabe89737" }
|
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "d09f55b4f8554491e3431e01af1c32347a8781cd" }
|
||||||
ethers = "1.0.2"
|
revm = { version = "2.3", default-features = false, features = ["std", "k256", "with-serde"] }
|
||||||
revm = "2.1.0"
|
ethers = "1.0.0"
|
||||||
bytes = "1.2.1"
|
bytes = "1.2.1"
|
||||||
futures = "0.3.23"
|
futures = "0.3.23"
|
||||||
toml = "0.5.9"
|
toml = "0.5.9"
|
||||||
|
@ -20,7 +19,10 @@ triehash-ethereum = { git = "https://github.com/openethereum/parity-ethereum", r
|
||||||
async-trait = "0.1.57"
|
async-trait = "0.1.57"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
thiserror = "1.0.37"
|
thiserror = "1.0.37"
|
||||||
openssl = { version = "0.10", features = ["vendored"] }
|
|
||||||
|
|
||||||
common = { path = "../common" }
|
common = { path = "../common" }
|
||||||
consensus = { path = "../consensus" }
|
consensus = { path = "../consensus" }
|
||||||
|
|
||||||
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
|
openssl = { version = "0.10", features = ["vendored"] }
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
|
|
@ -9,14 +9,13 @@ use bytes::Bytes;
|
||||||
use common::{errors::BlockNotFoundError, types::BlockTag};
|
use common::{errors::BlockNotFoundError, types::BlockTag};
|
||||||
use ethers::{
|
use ethers::{
|
||||||
abi::ethereum_types::BigEndianHash,
|
abi::ethereum_types::BigEndianHash,
|
||||||
prelude::{Address, H160, H256, U256},
|
|
||||||
types::transaction::eip2930::AccessListItem,
|
types::transaction::eip2930::AccessListItem,
|
||||||
|
types::{Address, H160, H256, U256},
|
||||||
};
|
};
|
||||||
use eyre::{Report, Result};
|
use eyre::{Report, Result};
|
||||||
use futures::future::join_all;
|
use futures::{executor::block_on, future::join_all};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use revm::{AccountInfo, Bytecode, Database, Env, TransactOut, TransactTo, EVM};
|
use revm::{AccountInfo, Bytecode, Database, Env, TransactOut, TransactTo, EVM};
|
||||||
use tokio::runtime::Runtime;
|
|
||||||
|
|
||||||
use consensus::types::ExecutionPayload;
|
use consensus::types::ExecutionPayload;
|
||||||
|
|
||||||
|
@ -225,8 +224,9 @@ impl<'a, R: ExecutionRpc> ProofDB<'a, R> {
|
||||||
|
|
||||||
let handle = thread::spawn(move || {
|
let handle = thread::spawn(move || {
|
||||||
let account_fut = execution.get_account(&address, Some(&slots), &payload);
|
let account_fut = execution.get_account(&address, Some(&slots), &payload);
|
||||||
let runtime = Runtime::new()?;
|
// let runtime = Runtime::new()?;
|
||||||
runtime.block_on(account_fut)
|
// runtime.block_on(account_fut)
|
||||||
|
block_on(account_fut)
|
||||||
});
|
});
|
||||||
|
|
||||||
handle.join().unwrap()
|
handle.join().unwrap()
|
||||||
|
|
|
@ -27,13 +27,16 @@ impl Clone for HttpRpc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||||
impl ExecutionRpc for HttpRpc {
|
impl ExecutionRpc for HttpRpc {
|
||||||
fn new(rpc: &str) -> Result<Self> {
|
fn new(rpc: &str) -> Result<Self> {
|
||||||
let http = Http::from_str(rpc)?;
|
let http = Http::from_str(rpc)?;
|
||||||
let mut client = RetryClient::new(http, Box::new(HttpRateLimitRetryPolicy), 100, 50);
|
let mut client = RetryClient::new(http, Box::new(HttpRateLimitRetryPolicy), 100, 50);
|
||||||
client.set_compute_units(300);
|
client.set_compute_units(300);
|
||||||
|
|
||||||
let provider = Provider::new(client);
|
let provider = Provider::new(client);
|
||||||
|
|
||||||
Ok(HttpRpc {
|
Ok(HttpRpc {
|
||||||
url: rpc.to_string(),
|
url: rpc.to_string(),
|
||||||
provider,
|
provider,
|
||||||
|
|
|
@ -17,7 +17,8 @@ pub struct MockRpc {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||||
impl ExecutionRpc for MockRpc {
|
impl ExecutionRpc for MockRpc {
|
||||||
fn new(rpc: &str) -> Result<Self> {
|
fn new(rpc: &str) -> Result<Self> {
|
||||||
let path = PathBuf::from(rpc);
|
let path = PathBuf::from(rpc);
|
||||||
|
|
|
@ -10,7 +10,8 @@ use crate::types::CallOpts;
|
||||||
pub mod http_rpc;
|
pub mod http_rpc;
|
||||||
pub mod mock_rpc;
|
pub mod mock_rpc;
|
||||||
|
|
||||||
#[async_trait]
|
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||||
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||||
pub trait ExecutionRpc: Send + Clone + Sync + 'static {
|
pub trait ExecutionRpc: Send + Clone + Sync + 'static {
|
||||||
fn new(rpc: &str) -> Result<Self>
|
fn new(rpc: &str) -> Result<Self>
|
||||||
where
|
where
|
||||||
|
|
Loading…
Reference in New Issue