diff --git a/plonky2x/Cargo.toml b/plonky2x/Cargo.toml index 4a2d2e5e9..b4f405f6c 100644 --- a/plonky2x/Cargo.toml +++ b/plonky2x/Cargo.toml @@ -32,7 +32,7 @@ serde = { version = "1.0.187", features = ["derive"] } serde_json = "1.0.103" tokio = { version = "1", features = ["full"] } anyhow = "1.0.75" -reqwest = { version = "0.11.4", features = ["json"] } +reqwest = { version = "0.11.4", features = ["blocking", "json"] } array-macro = "2.1.5" tracing = "0.1.37" num-bigint = { version = "0.4", features = ["rand"] } diff --git a/plonky2x/src/frontend/eth/beacon/generators/balance.rs b/plonky2x/src/frontend/eth/beacon/generators/balance.rs index 9451b8602..aa3df6ea9 100644 --- a/plonky2x/src/frontend/eth/beacon/generators/balance.rs +++ b/plonky2x/src/frontend/eth/beacon/generators/balance.rs @@ -149,27 +149,22 @@ impl, const D: usize> SimpleGenerator .block_on(async { match &self.input { BeaconBalanceInput::IndexConst(idx) => { - self.client - .get_validator_balance_v2(hex!(block_root), *idx) - .await + self.client.get_validator_balance_v2(hex!(block_root), *idx) } BeaconBalanceInput::IndexVariable(idx) => { let idx = idx.get(witness); self.client .get_validator_balance_v2(hex!(block_root), idx.as_u64()) - .await } BeaconBalanceInput::PubkeyConst(pubkey) => { let pubkey = hex!(pubkey.0); self.client .get_validator_balance_by_pubkey_v2(hex!(block_root), pubkey) - .await } BeaconBalanceInput::PubkeyVariable(pubkey) => { let pubkey = hex!(pubkey.get(witness)); self.client .get_validator_balance_by_pubkey_v2(hex!(block_root), pubkey) - .await } } }) diff --git a/plonky2x/src/frontend/eth/beacon/generators/balances.rs b/plonky2x/src/frontend/eth/beacon/generators/balances.rs index 3d6c0a729..d9ea46023 100644 --- a/plonky2x/src/frontend/eth/beacon/generators/balances.rs +++ b/plonky2x/src/frontend/eth/beacon/generators/balances.rs @@ -68,7 +68,6 @@ impl, const D: usize> SimpleGenerator let result = rt.block_on(async { self.client .get_balances_root(hex!(block_root.as_bytes()).to_string()) - .await .expect("failed to get validators root") }); diff --git a/plonky2x/src/frontend/eth/beacon/generators/historical.rs b/plonky2x/src/frontend/eth/beacon/generators/historical.rs index ebd866149..4a75ddd7b 100644 --- a/plonky2x/src/frontend/eth/beacon/generators/historical.rs +++ b/plonky2x/src/frontend/eth/beacon/generators/historical.rs @@ -74,7 +74,6 @@ impl, const D: usize> SimpleGenerator let result = rt.block_on(async { self.client .get_historical_block(hex!(block_root.as_bytes()).to_string(), offset.as_u64()) - .await .expect("failed to get validators root") }); diff --git a/plonky2x/src/frontend/eth/beacon/generators/mod.rs b/plonky2x/src/frontend/eth/beacon/generators/mod.rs index 92372483c..a37ec5081 100644 --- a/plonky2x/src/frontend/eth/beacon/generators/mod.rs +++ b/plonky2x/src/frontend/eth/beacon/generators/mod.rs @@ -2,6 +2,7 @@ mod balance; mod balances; mod historical; mod validator; +mod validator_witness; mod validators; mod withdrawal; mod withdrawals; diff --git a/plonky2x/src/frontend/eth/beacon/generators/validator.rs b/plonky2x/src/frontend/eth/beacon/generators/validator.rs index b35d86776..b347f1ce6 100644 --- a/plonky2x/src/frontend/eth/beacon/generators/validator.rs +++ b/plonky2x/src/frontend/eth/beacon/generators/validator.rs @@ -127,20 +127,17 @@ impl, const D: usize> SimpleGenerator BeaconValidatorGeneratorInput::IndexConst(idx) => self .client .get_validator(hex!(block_root), *idx) - .await .expect("failed to get validator"), BeaconValidatorGeneratorInput::IndexVariable(idx) => { let idx = idx.get(witness).as_u64(); self.client .get_validator(hex!(block_root), idx) - .await .expect("failed to get validator") } BeaconValidatorGeneratorInput::PubkeyVariable(pubkey) => { let pubkey = hex!(pubkey.get(witness)); self.client .get_validator_by_pubkey(hex!(block_root), pubkey) - .await .expect("failed to get validator") } } diff --git a/plonky2x/src/frontend/eth/beacon/generators/validator_witness.rs b/plonky2x/src/frontend/eth/beacon/generators/validator_witness.rs new file mode 100644 index 000000000..bd8e06a48 --- /dev/null +++ b/plonky2x/src/frontend/eth/beacon/generators/validator_witness.rs @@ -0,0 +1,28 @@ +use std::env; + +use serde::{Deserialize, Serialize}; + +use crate::frontend::eth::beacon::vars::BeaconValidatorVariable; +use crate::frontend::generator::simple::hint::Hint; +use crate::frontend::uint::uint64::U64Variable; +use crate::frontend::vars::ValueStream; +use crate::prelude::{Bytes32Variable, PlonkParameters}; +use crate::utils::eth::beacon::BeaconClient; +use crate::utils::hex; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BeaconValidatorWitnessGenerator {} + +impl, const D: usize> Hint for BeaconValidatorWitnessGenerator { + fn hint(&self, input_stream: &mut ValueStream, output_stream: &mut ValueStream) { + let client = BeaconClient::new(env::var("CONSENSUS_RPC_1").unwrap()); + let header_root = input_stream.read_value::(); + let validator_index = input_stream.read_value::(); + + let response = client + .get_validator_witness(hex!(header_root), validator_index.as_u64()) + .unwrap(); + + output_stream.write_value::(response.validator); + } +} diff --git a/plonky2x/src/frontend/eth/beacon/generators/validators.rs b/plonky2x/src/frontend/eth/beacon/generators/validators.rs index 1f00aca3f..8a4753905 100644 --- a/plonky2x/src/frontend/eth/beacon/generators/validators.rs +++ b/plonky2x/src/frontend/eth/beacon/generators/validators.rs @@ -68,7 +68,6 @@ impl, const D: usize> SimpleGenerator let result = rt.block_on(async { self.client .get_validators_root(hex!(block_root.as_bytes()).to_string()) - .await .expect("failed to get validators root") }); diff --git a/plonky2x/src/frontend/eth/beacon/generators/withdrawal.rs b/plonky2x/src/frontend/eth/beacon/generators/withdrawal.rs index cf627b96b..691e7c072 100644 --- a/plonky2x/src/frontend/eth/beacon/generators/withdrawal.rs +++ b/plonky2x/src/frontend/eth/beacon/generators/withdrawal.rs @@ -83,7 +83,6 @@ impl, const D: usize> SimpleGenerator let result = rt.block_on(async { self.client .get_withdrawal(hex!(block_root.as_bytes()).to_string(), idx.as_u64()) - .await .expect("failed to get validators root") }); diff --git a/plonky2x/src/frontend/eth/beacon/generators/withdrawals.rs b/plonky2x/src/frontend/eth/beacon/generators/withdrawals.rs index f1493a81b..cdd427052 100644 --- a/plonky2x/src/frontend/eth/beacon/generators/withdrawals.rs +++ b/plonky2x/src/frontend/eth/beacon/generators/withdrawals.rs @@ -68,7 +68,6 @@ impl, const D: usize> SimpleGenerator let result = rt.block_on(async { self.client .get_withdrawals_root(hex!(block_root.as_bytes()).to_string()) - .await .expect("failed to get validators root") }); diff --git a/plonky2x/src/utils/eth/beacon/mod.rs b/plonky2x/src/utils/eth/beacon/mod.rs index 8720bb9c7..1724e5ab0 100644 --- a/plonky2x/src/utils/eth/beacon/mod.rs +++ b/plonky2x/src/utils/eth/beacon/mod.rs @@ -2,11 +2,10 @@ use anyhow::Result; use ethers::types::U256; use log::info; use num::BigInt; -use reqwest::Client; +use reqwest::blocking::Client; use serde::Deserialize; use serde_json::Value; use serde_with::serde_as; -use tokio::runtime::Runtime; use crate::utils::serde::deserialize_bigint; @@ -75,7 +74,7 @@ struct BeaconValidatorBalance { pub balance: String, } -/// The result returned from `/api/beacon/validator/[beacon_id]`. +/// The result returned from `/api/beacon/proof/validator/[beacon_id]`. #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct GetBeaconValidatorsRoot { @@ -86,7 +85,7 @@ pub struct GetBeaconValidatorsRoot { pub proof: Vec, } -/// The result returned from `/api/beacon/validator/[beacon_id]/[validator_idx]`. +/// The result returned from `/api/beacon/proof/validator/[beacon_id]/[validator_idx]`. #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct GetBeaconValidator { @@ -100,6 +99,14 @@ pub struct GetBeaconValidator { pub proof: Vec, } +/// The result returned from `/api/beacon/validator/[beacon_id]/[validator_idx]`. +/// Note that this endpoint returns only the validator struct, without any SSZ proofs. +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct GetBeaconValidatorWitness { + pub validator: BeaconValidator, +} + #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct GetBeaconBalancesRoot { @@ -171,16 +178,15 @@ impl BeaconClient { /// Gets the block root at `head`. pub fn get_finalized_block_root_sync(&self) -> Result { - let rt = Runtime::new().expect("failed to create tokio runtime"); - rt.block_on(async { self.get_finalized_block_root().await }) + self.get_finalized_block_root() } /// Gets the latest block root at `head` asynchronously. - pub async fn get_finalized_block_root(&self) -> Result { + pub fn get_finalized_block_root(&self) -> Result { let endpoint = format!("{}/eth/v1/beacon/headers/finalized", self.rpc_url); let client = Client::new(); - let response = client.get(endpoint).send().await?; - let parsed: Value = response.json().await?; + let response = client.get(endpoint).send()?; + let parsed: Value = response.json()?; if let Value::Object(data) = &parsed["data"] { if let Value::Object(data2) = &data["data"] { @@ -193,18 +199,36 @@ impl BeaconClient { /// Gets the validators root based on a beacon_id and the SSZ proof from /// `stateRoot -> validatorsRoot`. - pub async fn get_validators_root(&self, beacon_id: String) -> Result { + pub fn get_validators_root(&self, beacon_id: String) -> Result { let endpoint = format!("{}/api/beacon/validator/{}", self.rpc_url, beacon_id); let client = Client::new(); - let response = client.get(endpoint).send().await?; - let response: CustomResponse = response.json().await?; + let response = client.get(endpoint).send()?; + let response: CustomResponse = response.json()?; + assert!(response.success); + Ok(response.result) + } + + /// Gets the state of a validator based on a beacon_id and index, omitting any SSZ proofs. + /// With repeated calls on the same beacon_id, this should be faster than `get_validator`. + pub fn get_validator_witness( + &self, + beacon_id: String, + validator_idx: u64, + ) -> Result { + let endpoint = format!( + "{}/api/beacon/validator/{}/{}", + self.rpc_url, beacon_id, validator_idx + ); + let client = Client::new(); + let response = client.get(endpoint).send()?; + let response: CustomResponse = response.json()?; assert!(response.success); Ok(response.result) } /// Gets the state of a validator based on a beacon_id and index, including the SSZ proof from /// `validatorsRoot -> validator[validator_idx]`. - pub async fn get_validator( + pub fn get_validator( &self, beacon_id: String, validator_idx: u64, @@ -214,15 +238,15 @@ impl BeaconClient { self.rpc_url, beacon_id, validator_idx ); let client = Client::new(); - let response = client.get(endpoint).send().await?; - let response: CustomResponse = response.json().await?; + let response = client.get(endpoint).send()?; + let response: CustomResponse = response.json()?; assert!(response.success); Ok(response.result) } /// Gets the state of a validator based on a beacon_id and index, including the SSZ proof from /// `validatorsRoot -> validator[validator_idx]`. - pub async fn get_validator_by_pubkey( + pub fn get_validator_by_pubkey( &self, beacon_id: String, pubkey: String, @@ -233,25 +257,25 @@ impl BeaconClient { ); info!("{}", endpoint); let client = Client::new(); - let response = client.get(endpoint).send().await?; - let response: CustomResponse = response.json().await?; + let response = client.get(endpoint).send()?; + let response: CustomResponse = response.json()?; assert!(response.success); Ok(response.result) } /// Gets the balances root based on a beacon_id. - pub async fn get_balances_root(&self, beacon_id: String) -> Result { + pub fn get_balances_root(&self, beacon_id: String) -> Result { let endpoint = format!("{}/api/beacon/balance/{}", self.rpc_url, beacon_id); info!("{}", endpoint); let client = Client::new(); - let response = client.get(endpoint).send().await?; - let response: CustomResponse = response.json().await?; + let response = client.get(endpoint).send()?; + let response: CustomResponse = response.json()?; assert!(response.success); Ok(response.result) } /// Gets the balance of a validator based on a beacon_id and validator index. - pub async fn get_validator_balance_v2( + pub fn get_validator_balance_v2( &self, beacon_id: String, validator_idx: u64, @@ -261,14 +285,14 @@ impl BeaconClient { self.rpc_url, beacon_id, validator_idx ); let client = Client::new(); - let response = client.get(endpoint).send().await?; - let response: CustomResponse = response.json().await?; + let response = client.get(endpoint).send()?; + let response: CustomResponse = response.json()?; assert!(response.success); Ok(response.result) } /// Gets the balance of a validator based on a beacon_id and validator pubkey. - pub async fn get_validator_balance_by_pubkey_v2( + pub fn get_validator_balance_by_pubkey_v2( &self, beacon_id: String, pubkey: String, @@ -278,15 +302,15 @@ impl BeaconClient { self.rpc_url, beacon_id, pubkey ); let client = Client::new(); - let response = client.get(endpoint).send().await?; - let response: CustomResponse = response.json().await?; + let response = client.get(endpoint).send()?; + let response: CustomResponse = response.json()?; assert!(response.success); Ok(response.result) } /// Gets the balance of a validator based on a beacon_id and validator index. #[allow(unused)] - async fn get_validator_balance_deprecated( + fn get_validator_balance_deprecated( &self, beacon_id: String, validator_idx: u64, @@ -296,15 +320,15 @@ impl BeaconClient { self.rpc_url, beacon_id, validator_idx ); let client = Client::new(); - let response = client.get(endpoint).send().await?; - let response: BeaconResponse = response.json().await?; + let response = client.get(endpoint).send()?; + let response: BeaconResponse = response.json()?; let balance = response.data.data[0].balance.parse::()?; Ok(U256::from(balance)) } /// Gets the balance of a validator based on a beacon_id and validator pubkey. #[allow(unused)] - async fn get_validator_balance_by_pubkey_deprecated( + fn get_validator_balance_by_pubkey_deprecated( &self, beacon_id: String, pubkey: String, @@ -314,37 +338,34 @@ impl BeaconClient { self.rpc_url, beacon_id, pubkey ); let client = Client::new(); - let response = client.get(endpoint).send().await?; - let response: BeaconResponse = response.json().await?; + let response = client.get(endpoint).send()?; + let response: BeaconResponse = response.json()?; let balance = response.data.data[0].balance.parse::()?; Ok(U256::from(balance)) } - pub async fn get_withdrawals_root( - &self, - beacon_id: String, - ) -> Result { + pub fn get_withdrawals_root(&self, beacon_id: String) -> Result { let endpoint = format!("{}/api/beacon/withdrawal/{}", self.rpc_url, beacon_id); let client = Client::new(); - let response = client.get(endpoint).send().await?; - let response: CustomResponse = response.json().await?; + let response = client.get(endpoint).send()?; + let response: CustomResponse = response.json()?; assert!(response.success); Ok(response.result) } - pub async fn get_withdrawal(&self, beacon_id: String, idx: u64) -> Result { + pub fn get_withdrawal(&self, beacon_id: String, idx: u64) -> Result { let endpoint = format!( "{}/api/beacon/withdrawal/{}/{}", self.rpc_url, beacon_id, idx ); let client = Client::new(); - let response = client.get(endpoint).send().await?; - let response: CustomResponse = response.json().await?; + let response = client.get(endpoint).send()?; + let response: CustomResponse = response.json()?; assert!(response.success); Ok(response.result) } - pub async fn get_historical_block( + pub fn get_historical_block( &self, beacon_id: String, offset: u64, @@ -354,8 +375,8 @@ impl BeaconClient { self.rpc_url, beacon_id, offset ); let client = Client::new(); - let response = client.get(endpoint).send().await?; - let response: CustomResponse = response.json().await?; + let response = client.get(endpoint).send()?; + let response: CustomResponse = response.json()?; assert!(response.success); Ok(response.result) } @@ -373,54 +394,54 @@ mod tests { use super::*; use crate::utils; - #[tokio::test] #[cfg_attr(feature = "ci", ignore)] - async fn test_get_validators_root_by_slot() -> Result<()> { + #[test] + fn test_get_validators_root_by_slot() -> Result<()> { utils::setup_logger(); dotenv::dotenv()?; let rpc = env::var("CONSENSUS_RPC_1").unwrap(); let client = BeaconClient::new(rpc.to_string()); let slot = 7052735; - let result = client.get_validators_root(slot.to_string()).await?; + let result = client.get_validators_root(slot.to_string())?; debug!("{:?}", result); Ok(()) } - #[tokio::test] #[cfg_attr(feature = "ci", ignore)] - async fn test_get_validators_root_by_block_root() -> Result<()> { + #[test] + fn test_get_validators_root_by_block_root() -> Result<()> { utils::setup_logger(); dotenv::dotenv()?; let rpc = env::var("CONSENSUS_RPC_1").unwrap(); let client = BeaconClient::new(rpc.to_string()); let block_root = "0x6b6964f45d0aeff741260ec4faaf76bb79a009fc18ae17979784d92aec374946"; - let result = client.get_validators_root(block_root.to_string()).await?; + let result = client.get_validators_root(block_root.to_string())?; debug!("{:?}", result); Ok(()) } - #[tokio::test] #[cfg_attr(feature = "ci", ignore)] - async fn test_get_validator_by_slot() -> Result<()> { + #[test] + fn test_get_validator_by_slot() -> Result<()> { utils::setup_logger(); dotenv::dotenv()?; let rpc = env::var("CONSENSUS_RPC_1").unwrap(); let client = BeaconClient::new(rpc.to_string()); let slot = 7052735; - let result = client.get_validator(slot.to_string(), 0).await?; + let result = client.get_validator(slot.to_string(), 0)?; debug!("{:?}", result); Ok(()) } - #[tokio::test] #[cfg_attr(feature = "ci", ignore)] - async fn test_get_validator_by_block_root() -> Result<()> { + #[test] + fn test_get_validator_by_block_root() -> Result<()> { utils::setup_logger(); dotenv::dotenv()?; let rpc = env::var("CONSENSUS_RPC_1").unwrap(); let client = BeaconClient::new(rpc.to_string()); let block_root = "0x6b6964f45d0aeff741260ec4faaf76bb79a009fc18ae17979784d92aec374946"; - let result = client.get_validator(block_root.to_string(), 0).await?; + let result = client.get_validator(block_root.to_string(), 0)?; debug!("{:?}", result); Ok(()) }