From d63726d053075a24bb2e3f6c822542d7eed92d84 Mon Sep 17 00:00:00 2001 From: Chris Tian Date: Mon, 18 Sep 2023 18:52:21 -0700 Subject: [PATCH] refactor: validator witness + using reqwest blocking --- plonky2x/Cargo.toml | 2 +- .../frontend/eth/beacon/generators/balance.rs | 7 +- .../eth/beacon/generators/balances.rs | 1 - .../eth/beacon/generators/historical.rs | 1 - .../src/frontend/eth/beacon/generators/mod.rs | 1 + .../eth/beacon/generators/validator.rs | 3 - .../beacon/generators/validator_witness.rs | 28 ++++ .../eth/beacon/generators/validators.rs | 1 - .../eth/beacon/generators/withdrawal.rs | 1 - .../eth/beacon/generators/withdrawals.rs | 1 - plonky2x/src/utils/eth/beacon/mod.rs | 131 ++++++++++-------- 11 files changed, 105 insertions(+), 72 deletions(-) create mode 100644 plonky2x/src/frontend/eth/beacon/generators/validator_witness.rs 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..2aa60106d 100644 --- a/plonky2x/src/frontend/eth/beacon/generators/mod.rs +++ b/plonky2x/src/frontend/eth/beacon/generators/mod.rs @@ -5,6 +5,7 @@ mod validator; mod validators; mod withdrawal; mod withdrawals; +mod validator_witness; pub use balance::BeaconBalanceGenerator; pub use balances::BeaconBalancesGenerator; 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 8e729ed2d..a39fea653 100644 --- a/plonky2x/src/frontend/eth/beacon/generators/withdrawal.rs +++ b/plonky2x/src/frontend/eth/beacon/generators/withdrawal.rs @@ -82,7 +82,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 bb3deba3a..ead0ea649 100644 --- a/plonky2x/src/utils/eth/beacon/mod.rs +++ b/plonky2x/src/utils/eth/beacon/mod.rs @@ -1,11 +1,10 @@ use anyhow::Result; use ethers::types::U256; 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; @@ -74,7 +73,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 { @@ -85,7 +84,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 { @@ -99,6 +98,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 { @@ -170,16 +177,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"] { @@ -192,18 +198,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, @@ -213,15 +237,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, @@ -232,25 +256,25 @@ impl BeaconClient { ); println!("{}", 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); println!("{}", 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, @@ -260,14 +284,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, @@ -277,15 +301,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, @@ -295,15 +319,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, @@ -313,37 +337,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, @@ -353,8 +374,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) } @@ -370,50 +391,46 @@ mod tests { use super::*; - #[tokio::test] #[cfg_attr(feature = "ci", ignore)] - async fn test_get_validators_root_by_slot() -> Result<()> { + fn test_get_validators_root_by_slot() -> Result<()> { 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())?; println!("{:?}", result); Ok(()) } - #[tokio::test] #[cfg_attr(feature = "ci", ignore)] - async fn test_get_validators_root_by_block_root() -> Result<()> { + fn test_get_validators_root_by_block_root() -> Result<()> { 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())?; println!("{:?}", result); Ok(()) } - #[tokio::test] #[cfg_attr(feature = "ci", ignore)] - async fn test_get_validator_by_slot() -> Result<()> { + fn test_get_validator_by_slot() -> Result<()> { 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)?; println!("{:?}", result); Ok(()) } - #[tokio::test] #[cfg_attr(feature = "ci", ignore)] - async fn test_get_validator_by_block_root() -> Result<()> { + fn test_get_validator_by_block_root() -> Result<()> { 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)?; println!("{:?}", result); Ok(()) }