diff --git a/Cargo.lock b/Cargo.lock index e22a4c3a..b7f8f8e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -610,7 +610,7 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "beacon-api-client" version = "0.1.0" -source = "git+https://github.com/ralexstokes/ethereum-consensus?rev=766aca6c5d10ee8dac015fbe705667f60097149d#766aca6c5d10ee8dac015fbe705667f60097149d" +source = "git+https://github.com/ralexstokes/ethereum-consensus?rev=c84f44ee7ec04613adf5f2be845df35e05de1efc#c84f44ee7ec04613adf5f2be845df35e05de1efc" dependencies = [ "clap", "ethereum-consensus", @@ -2271,7 +2271,7 @@ dependencies = [ [[package]] name = "ethereum-consensus" version = "0.1.1" -source = "git+https://github.com/ralexstokes/ethereum-consensus?rev=766aca6c5d10ee8dac015fbe705667f60097149d#766aca6c5d10ee8dac015fbe705667f60097149d" +source = "git+https://github.com/ralexstokes/ethereum-consensus?rev=c84f44ee7ec04613adf5f2be845df35e05de1efc#c84f44ee7ec04613adf5f2be845df35e05de1efc" dependencies = [ "async-stream", "blst", @@ -4189,7 +4189,7 @@ dependencies = [ "reth-primitives", "serde", "tokio", - "toml 0.5.11", + "toml 0.8.2", "tracing", "tracing-subscriber", ] @@ -7359,7 +7359,7 @@ checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" [[package]] name = "ssz_rs" version = "0.9.0" -source = "git+https://github.com/ralexstokes/ssz-rs?rev=20829edcaa48e5f5f39939a69928debc477be4e2#20829edcaa48e5f5f39939a69928debc477be4e2" +source = "git+https://github.com/ralexstokes/ssz-rs?rev=6755022b7727e3392bfbc2b9c683cb7bf9caa4ce#6755022b7727e3392bfbc2b9c683cb7bf9caa4ce" dependencies = [ "bitvec", "hex", @@ -7372,7 +7372,7 @@ dependencies = [ [[package]] name = "ssz_rs_derive" version = "0.9.0" -source = "git+https://github.com/ralexstokes/ssz-rs?rev=20829edcaa48e5f5f39939a69928debc477be4e2#20829edcaa48e5f5f39939a69928debc477be4e2" +source = "git+https://github.com/ralexstokes/ssz-rs?rev=6755022b7727e3392bfbc2b9c683cb7bf9caa4ce#6755022b7727e3392bfbc2b9c683cb7bf9caa4ce" dependencies = [ "proc-macro2", "quote", @@ -7829,7 +7829,19 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.20.2", ] [[package]] @@ -7854,6 +7866,19 @@ dependencies = [ "winnow", ] +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.0.2", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tower" version = "0.4.13" diff --git a/Cargo.toml b/Cargo.toml index eebd6bcf..053b5b6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,8 +7,8 @@ default-members = ["bin/mev"] version = "0.3.0" [workspace.dependencies] -ethereum-consensus = { git = "https://github.com/ralexstokes/ethereum-consensus", rev = "766aca6c5d10ee8dac015fbe705667f60097149d" } -beacon-api-client = { git = "https://github.com/ralexstokes/ethereum-consensus", rev = "766aca6c5d10ee8dac015fbe705667f60097149d" } +ethereum-consensus = { git = "https://github.com/ralexstokes/ethereum-consensus", rev = "c84f44ee7ec04613adf5f2be845df35e05de1efc" } +beacon-api-client = { git = "https://github.com/ralexstokes/ethereum-consensus", rev = "c84f44ee7ec04613adf5f2be845df35e05de1efc" } reth-payload-builder = { git = "https://github.com/paradigmxyz/reth", rev = "1b16d804ef01f4ec3c25e7986381c22739c105b9" } reth-primitives = { git = "https://github.com/paradigmxyz/reth", rev = "1b16d804ef01f4ec3c25e7986381c22739c105b9" } diff --git a/bin/mev/Cargo.toml b/bin/mev/Cargo.toml index 9a8543eb..ab356024 100644 --- a/bin/mev/Cargo.toml +++ b/bin/mev/Cargo.toml @@ -17,7 +17,7 @@ mev-build-rs = { path = "../../mev-build-rs" } mev-rs = { path = "../../mev-rs" } serde = { version = "1.0", features = ["derive"] } -toml = "0.5.9" +toml = "0.8.2" clap = { version = "4.1.4", features = ["derive", "env"] } anyhow = "1.0.57" diff --git a/bin/mev/src/cmd/boost.rs b/bin/mev/src/cmd/boost.rs index 290306ee..c3e5b7b8 100644 --- a/bin/mev/src/cmd/boost.rs +++ b/bin/mev/src/cmd/boost.rs @@ -1,8 +1,8 @@ use crate::cmd::config::Config; use anyhow::{anyhow, Result}; use clap::Args; -use ethereum_consensus::networks::Network; use mev_boost_rs::Service; +use tracing::info; #[derive(Debug, Args)] #[clap(about = "🚀 connecting proposers to the external builder network")] @@ -12,14 +12,16 @@ pub struct Command { } impl Command { - pub async fn execute(&self, network: Network) -> Result<()> { + pub async fn execute(self) -> Result<()> { let config_file = &self.config_file; let config = Config::from_toml_file(config_file)?; - if let Some(mut config) = config.boost { - config.network = network; - Ok(Service::from(config).spawn(None)?.await?) + let network = config.network; + info!("configured for {network}"); + + if let Some(config) = config.boost { + Ok(Service::from(network, config).spawn()?.await?) } else { Err(anyhow!("missing boost config from file provided")) } diff --git a/bin/mev/src/cmd/build/mod.rs b/bin/mev/src/cmd/build/mod.rs index e4c62548..43518faf 100644 --- a/bin/mev/src/cmd/build/mod.rs +++ b/bin/mev/src/cmd/build/mod.rs @@ -2,7 +2,6 @@ mod reth_ext; use anyhow::Result; use clap::Args; -use ethereum_consensus::networks::Network; use reth_ext::{launch_reth_with, RethNodeExt}; #[derive(Debug, Args)] @@ -13,8 +12,9 @@ pub struct Command { } impl Command { - pub async fn execute(&self, network: Network) -> Result<()> { - let ext = RethNodeExt { config_file: self.config_file.clone(), network, config: None }; + pub async fn execute(self) -> Result<()> { + let ext = + RethNodeExt { config_file: self.config_file.clone(), network: None, config: None }; launch_reth_with(ext).await; Ok(()) } diff --git a/bin/mev/src/cmd/build/reth_ext.rs b/bin/mev/src/cmd/build/reth_ext.rs index 1a47721d..6ec6caa9 100644 --- a/bin/mev/src/cmd/build/reth_ext.rs +++ b/bin/mev/src/cmd/build/reth_ext.rs @@ -13,6 +13,7 @@ use reth::{ }; use reth_payload_builder::PayloadBuilderService; use std::{sync::Arc, time::Duration}; +use tracing::warn; struct RethExt; @@ -25,7 +26,7 @@ pub struct RethNodeExt { #[clap(skip)] pub config_file: String, #[clap(skip)] - pub network: Network, + pub network: Option, #[clap(skip)] pub config: Option, } @@ -34,6 +35,7 @@ impl RethNodeExt { pub fn get_build_config(&mut self) -> BuildConfig { self.config.take().unwrap_or_else(|| { let config = Config::from_toml_file(&self.config_file).unwrap(); + self.network = Some(config.network); let config = config.build.unwrap(); self.config = Some(config.clone()); config @@ -61,7 +63,7 @@ impl RethNodeCommandConfig for RethNodeExt { Tasks: reth::tasks::TaskSpawner + Clone + Unpin + 'static, { let build_config = self.get_build_config(); - let network = &self.network; + let network = self.network.as_ref().unwrap(); let context = Arc::new(Context::try_from(network)?); let clock = context.clock().unwrap_or_else(|| { let genesis_time = networks::typical_genesis_time(&context); @@ -110,7 +112,8 @@ pub(crate) async fn launch_reth_with(mut ext: RethNodeExt) { let config = ext.get_build_config(); - let network_name = format!("{0}", ext.network); + let network = ext.network.as_ref().unwrap(); + let network_name = format!("{network}"); let mut params = vec!["".into(), "--chain".into(), network_name.to_string(), "--http".into()]; if let Some(path) = config.jwt_secret_path { @@ -122,6 +125,6 @@ pub(crate) async fn launch_reth_with(mut ext: RethNodeExt) { // NOTE: shim to pass in config node.ext = ext; if let Err(err) = node.execute(ctx).await { - tracing::warn!("{err:?}"); + warn!("{err:?}"); } } diff --git a/bin/mev/src/cmd/config.rs b/bin/mev/src/cmd/config.rs index 3d702065..3a5fd88d 100644 --- a/bin/mev/src/cmd/config.rs +++ b/bin/mev/src/cmd/config.rs @@ -6,9 +6,11 @@ use mev_build_rs::reth_builder::Config as BuildConfig; use mev_relay_rs::Config as RelayConfig; use serde::Deserialize; use std::{fmt, path::Path}; +use tracing::info; #[derive(Debug, Deserialize)] pub struct Config { + pub network: Network, pub boost: Option, #[serde(rename = "builder")] pub build: Option, @@ -19,10 +21,10 @@ impl Config { pub fn from_toml_file + fmt::Display + Clone>(path: P) -> Result { tracing::info!("loading config from `{path}`..."); - let config_data = std::fs::read(path.as_ref()) + let config_data = std::fs::read_to_string(path.as_ref()) .with_context(|| format!("could not read config from `{path}`"))?; - toml::from_slice(&config_data).context("could not parse TOML") + toml::from_str(&config_data).context("could not parse TOML") } } @@ -34,12 +36,11 @@ pub struct Command { } impl Command { - pub async fn execute(&self, network: Network) -> Result<()> { - let config_file = &self.config_file; + pub async fn execute(self) -> Result<()> { + let config_file = self.config_file; let config = Config::from_toml_file(config_file)?; - - tracing::info!("configured for network `{}` with configuration {:#?}", network, config); + info!("{config:#?}"); Ok(()) } diff --git a/bin/mev/src/cmd/relay.rs b/bin/mev/src/cmd/relay.rs index 818a6ca5..dce222b4 100644 --- a/bin/mev/src/cmd/relay.rs +++ b/bin/mev/src/cmd/relay.rs @@ -1,8 +1,8 @@ use crate::cmd::config::Config; use anyhow::{anyhow, Result}; use clap::{Args, Subcommand}; -use ethereum_consensus::networks::Network; use mev_relay_rs::Service; +use tracing::info; #[derive(Debug, Args)] #[clap(about = "🏗 connecting builders to proposers", subcommand_negates_reqs = true)] @@ -20,7 +20,7 @@ pub enum Commands { } impl Command { - pub async fn execute(&self, network: Network) -> Result<()> { + pub async fn execute(self) -> Result<()> { let (config_file, _mock) = if let Some(subcommand) = self.command.as_ref() { match subcommand { Commands::Mock { config_file } => (config_file, true), @@ -31,9 +31,11 @@ impl Command { let config = Config::from_toml_file(config_file)?; - if let Some(mut config) = config.relay { - config.network = network; - let service = Service::from(config).spawn(None).await?; + let network = config.network; + info!("configured for {network}"); + + if let Some(config) = config.relay { + let service = Service::from(network, config).spawn().await?; Ok(service.await?) } else { Err(anyhow!("missing relay config from file provided")) diff --git a/bin/mev/src/main.rs b/bin/mev/src/main.rs index 72ae02e3..80b70c13 100644 --- a/bin/mev/src/main.rs +++ b/bin/mev/src/main.rs @@ -1,42 +1,14 @@ mod cmd; use anyhow::Result; -use clap::{ArgGroup, Parser, Subcommand}; -use ethereum_consensus::networks::Network; +use clap::{Parser, Subcommand}; use std::future::Future; use tokio::signal; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; -#[derive(Default, Debug, Clone, clap::ValueEnum)] -pub enum NetworkArg { - #[default] - Mainnet, - Sepolia, - Goerli, - Holesky, -} - -// NOTE: define this mapping so only this crate needs the `clap` dependency while still being able -// to use the `clap::ValueEnum` machinery -impl From for Network { - fn from(arg: NetworkArg) -> Self { - match arg { - NetworkArg::Mainnet => Self::Mainnet, - NetworkArg::Sepolia => Self::Sepolia, - NetworkArg::Goerli => Self::Goerli, - NetworkArg::Holesky => Self::Holesky, - } - } -} - #[derive(Debug, Parser)] #[clap(author, version, about = "utilities for block space", long_about = None)] -#[clap(group(ArgGroup::new("network-config").args(&["network", "network_config"])))] struct Cli { - #[clap(long, value_enum, value_name = "NETWORK")] - network: Option, - #[clap(long, value_name = "FILE")] - network_config: Option, #[clap(subcommand)] command: Commands, } @@ -72,25 +44,12 @@ async fn run_task_until_signal(task: impl Future>) -> Result async fn main() -> Result<()> { let cli = Cli::parse(); - let network = if let Some(network) = cli.network { - network.into() - } else if let Some(network_config) = cli.network_config { - // use custom config if provided - Network::Custom(network_config) - } else { - // default to `mainnet` if no network configuration is provided - let network = NetworkArg::Mainnet; - network.into() - }; - setup_logging(); - tracing::info!("configured for {network}"); - match cli.command { - Commands::Boost(cmd) => run_task_until_signal(cmd.execute(network)).await, - Commands::Build(cmd) => run_task_until_signal(cmd.execute(network)).await, - Commands::Relay(cmd) => run_task_until_signal(cmd.execute(network)).await, - Commands::Config(cmd) => run_task_until_signal(cmd.execute(network)).await, + Commands::Boost(cmd) => run_task_until_signal(cmd.execute()).await, + Commands::Build(cmd) => run_task_until_signal(cmd.execute()).await, + Commands::Relay(cmd) => run_task_until_signal(cmd.execute()).await, + Commands::Config(cmd) => run_task_until_signal(cmd.execute()).await, } } diff --git a/example.config.toml b/example.config.toml index d1e26f86..39a58b9f 100644 --- a/example.config.toml +++ b/example.config.toml @@ -1,3 +1,5 @@ +network = "holesky" + [boost] host = "0.0.0.0" port = 18550 diff --git a/mev-boost-rs/src/service.rs b/mev-boost-rs/src/service.rs index e8947dfa..7cfe5f0d 100644 --- a/mev-boost-rs/src/service.rs +++ b/mev-boost-rs/src/service.rs @@ -20,18 +20,11 @@ pub struct Config { pub host: Ipv4Addr, pub port: u16, pub relays: Vec, - #[serde(default)] - pub network: Network, } impl Default for Config { fn default() -> Self { - Self { - host: Ipv4Addr::UNSPECIFIED, - port: 18550, - relays: vec![], - network: Network::default(), - } + Self { host: Ipv4Addr::UNSPECIFIED, port: 18550, relays: vec![] } } } @@ -58,14 +51,14 @@ pub struct Service { } impl Service { - pub fn from(config: Config) -> Self { + pub fn from(network: Network, config: Config) -> Self { let relays = parse_relay_endpoints(&config.relays); - Self { host: config.host, port: config.port, relays, network: config.network } + Self { host: config.host, port: config.port, relays, network } } /// Spawns a new [`RelayMux`] and [`BlindedBlockProviderServer`] task - pub fn spawn(self, context: Option) -> Result { + pub fn spawn(self) -> Result { let Self { host, port, relays, network } = self; if relays.is_empty() { @@ -78,8 +71,7 @@ impl Service { } } - let context = - if let Some(context) = context { context } else { Context::try_from(&network)? }; + let context = Context::try_from(&network)?; let relays = relays.into_iter().map(Relay::from); let clock = context.clock().unwrap_or_else(|| { let genesis_time = networks::typical_genesis_time(&context); diff --git a/mev-boost-rs/tests/integration.rs b/mev-boost-rs/tests/integration.rs index 30eaf76b..bd7fc67f 100644 --- a/mev-boost-rs/tests/integration.rs +++ b/mev-boost-rs/tests/integration.rs @@ -6,6 +6,7 @@ use ethereum_consensus::{ builder::{SignedValidatorRegistration, ValidatorRegistration}, capella::mainnet as capella, crypto::SecretKey, + networks::Network, phase0::mainnet::{compute_domain, Validator}, primitives::{DomainType, ExecutionAddress, Hash32, Root}, signing::sign_with_domain, @@ -74,10 +75,8 @@ async fn test_end_to_end() { let genesis_validators_root = Root::try_from([23u8; 32].as_ref()).unwrap(); - let mut context = Context::for_mainnet(); - // mock epoch values to transition across forks - context.bellatrix_fork_epoch = 12; - context.capella_fork_epoch = 22; + let network = Network::Sepolia; + let context = Context::try_from(&network).unwrap(); // NOTE: non-default secret key required. otherwise public key is point at infinity and // signature verification will fail. @@ -93,11 +92,11 @@ async fn test_end_to_end() { // start mux server let mut config = Config::default(); - config.relays.push(format!("http://{relay_public_key}@127.0.0.1:{port}")); + config.relays.push(format!("http://{relay_public_key:?}@127.0.0.1:{port}")); let mux_port = config.port; - let service = Service::from(config); - service.spawn(Some(context.clone())).unwrap(); + let service = Service::from(network, config); + service.spawn().unwrap(); let beacon_node = RelayClient::new(ApiClient::new( Url::parse(&format!("http://127.0.0.1:{mux_port}")).unwrap(), @@ -140,8 +139,8 @@ async fn propose_block( ) { let fork = if shuffling_index == 0 { Fork::Bellatrix } else { Fork::Capella }; let current_slot = match fork { - Fork::Bellatrix => 32 + context.bellatrix_fork_epoch * context.slots_per_epoch, - Fork::Capella => 32 + context.capella_fork_epoch * context.slots_per_epoch, + Fork::Bellatrix => 30 + context.bellatrix_fork_epoch * context.slots_per_epoch, + Fork::Capella => 30 + context.capella_fork_epoch * context.slots_per_epoch, _ => unimplemented!(), }; let parent_hash = Hash32::try_from([shuffling_index as u8; 32].as_ref()).unwrap(); diff --git a/mev-relay-rs/src/service.rs b/mev-relay-rs/src/service.rs index b4ad6bf3..0b7ce73b 100644 --- a/mev-relay-rs/src/service.rs +++ b/mev-relay-rs/src/service.rs @@ -17,8 +17,6 @@ pub struct Config { pub host: Ipv4Addr, pub port: u16, pub beacon_node_url: String, - #[serde(default)] - pub network: Network, pub secret_key: SecretKey, } @@ -28,7 +26,6 @@ impl Default for Config { host: Ipv4Addr::LOCALHOST, port: 28545, beacon_node_url: "http://127.0.0.1:5052".into(), - network: Default::default(), secret_key: Default::default(), } } @@ -43,25 +40,24 @@ pub struct Service { } impl Service { - pub fn from(config: Config) -> Self { + pub fn from(network: Network, config: Config) -> Self { let endpoint: Url = config.beacon_node_url.parse().unwrap(); let beacon_node = Client::new(endpoint); Self { host: config.host, port: config.port, beacon_node, - network: config.network, + network, secret_key: config.secret_key, } } /// Configures the [`Relay`] and the [`BlindedBlockProviderServer`] and spawns both to /// individual tasks - pub async fn spawn(self, context: Option) -> Result { + pub async fn spawn(self) -> Result { let Self { host, port, beacon_node, network, secret_key } = self; - let context = - if let Some(context) = context { context } else { Context::try_from(&network)? }; + let context = Context::try_from(&network)?; let clock = context.clock().unwrap_or_else(|| { let genesis_time = networks::typical_genesis_time(&context); context.clock_at(genesis_time) diff --git a/mev-rs/src/blinded_block_provider/api/client.rs b/mev-rs/src/blinded_block_provider/api/client.rs index 8ae9179c..f33a345e 100644 --- a/mev-rs/src/blinded_block_provider/api/client.rs +++ b/mev-rs/src/blinded_block_provider/api/client.rs @@ -43,7 +43,7 @@ impl Client { bid_request: &BidRequest, ) -> Result { let target = format!( - "/eth/v1/builder/header/{}/{}/{}", + "/eth/v1/builder/header/{}/{:?}/{:?}", bid_request.slot, bid_request.parent_hash, bid_request.public_key ); let response = self.api.http_get(&target).await?; diff --git a/mev-rs/src/relay.rs b/mev-rs/src/relay.rs index 8cf90d4f..495cf697 100644 --- a/mev-rs/src/relay.rs +++ b/mev-rs/src/relay.rs @@ -103,7 +103,8 @@ mod tests { let public_key = sk.public_key(); let mut url = Url::parse(URL).unwrap(); - url.set_username(&public_key.to_string()).unwrap(); + let public_key_str = format!("{public_key:?}"); + url.set_username(&public_key_str).unwrap(); let endpoint = RelayEndpoint::try_from(url.clone()).unwrap(); assert_eq!(endpoint.url, url); diff --git a/mev-rs/src/serde.rs b/mev-rs/src/serde.rs index 20830e92..4c4ca5e7 100644 --- a/mev-rs/src/serde.rs +++ b/mev-rs/src/serde.rs @@ -1 +1 @@ -pub(crate) use ethereum_consensus::serde::as_string; +pub(crate) use ethereum_consensus::serde::as_str; diff --git a/mev-rs/src/types/bid_request.rs b/mev-rs/src/types/bid_request.rs index 8fd706fe..3ffff95c 100644 --- a/mev-rs/src/types/bid_request.rs +++ b/mev-rs/src/types/bid_request.rs @@ -3,7 +3,7 @@ use ethereum_consensus::primitives::{BlsPublicKey, Hash32, Slot}; #[derive(Debug, Default, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct BidRequest { - #[serde(with = "crate::serde::as_string")] + #[serde(with = "crate::serde::as_str")] pub slot: Slot, pub parent_hash: Hash32, pub public_key: BlsPublicKey, diff --git a/mev-rs/src/types/block_submission.rs b/mev-rs/src/types/block_submission.rs index 2977b5df..7645f8da 100644 --- a/mev-rs/src/types/block_submission.rs +++ b/mev-rs/src/types/block_submission.rs @@ -7,7 +7,7 @@ use ethereum_consensus::{ #[derive(Debug, Default, Clone, SimpleSerialize)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct BidTrace { - #[serde(with = "crate::serde::as_string")] + #[serde(with = "crate::serde::as_str")] pub slot: Slot, pub parent_hash: Hash32, pub block_hash: Hash32, @@ -16,9 +16,9 @@ pub struct BidTrace { #[serde(rename = "proposer_pubkey")] pub proposer_public_key: BlsPublicKey, pub proposer_fee_recipient: ExecutionAddress, - #[serde(with = "crate::serde::as_string")] + #[serde(with = "crate::serde::as_str")] pub gas_limit: u64, - #[serde(with = "crate::serde::as_string")] + #[serde(with = "crate::serde::as_str")] pub gas_used: u64, pub value: U256, } diff --git a/mev-rs/src/types/proposer_schedule.rs b/mev-rs/src/types/proposer_schedule.rs index 82e5b5e5..c0e34cf5 100644 --- a/mev-rs/src/types/proposer_schedule.rs +++ b/mev-rs/src/types/proposer_schedule.rs @@ -4,9 +4,9 @@ use ethereum_consensus::primitives::{Slot, ValidatorIndex}; #[derive(Debug, Default, Clone)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ProposerSchedule { - #[serde(with = "crate::serde::as_string")] + #[serde(with = "crate::serde::as_str")] pub slot: Slot, - #[serde(with = "crate::serde::as_string")] + #[serde(with = "crate::serde::as_str")] pub validator_index: ValidatorIndex, pub entry: SignedValidatorRegistration, }