From 75a4e1cbad311936b499930a2dbe2ccf32c00048 Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Thu, 31 Oct 2024 00:03:37 +0700 Subject: [PATCH 1/3] chore: remove EVM config --- .../src/contexts/aggregator.rs | 3 +- .../src/contexts/client.rs | 11 +- .../src/main.rs | 70 ++---- .../incredible-squaring-symbiotic/src/main.rs | 13 +- .../src/event_listener/evm.rs | 11 +- macros/blueprint-proc-macro/src/job.rs | 35 +-- sdk/src/event_listener/evm_contracts.rs | 215 +----------------- sdk/src/events_watcher/evm.rs | 54 ++--- 8 files changed, 66 insertions(+), 346 deletions(-) diff --git a/blueprints/incredible-squaring-eigenlayer/src/contexts/aggregator.rs b/blueprints/incredible-squaring-eigenlayer/src/contexts/aggregator.rs index 4b4f4c77..19656b52 100644 --- a/blueprints/incredible-squaring-eigenlayer/src/contexts/aggregator.rs +++ b/blueprints/incredible-squaring-eigenlayer/src/contexts/aggregator.rs @@ -60,7 +60,6 @@ impl AggregatorContext { pub async fn new( port_address: String, task_manager_address: Address, - http_rpc_url: String, wallet: EthereumWallet, sdk_config: StdGadgetConfiguration, ) -> Result { @@ -70,7 +69,7 @@ impl AggregatorContext { tasks: Arc::new(Mutex::new(HashMap::new())), tasks_responses: Arc::new(Mutex::new(HashMap::new())), bls_aggregation_service: None, - http_rpc_url, + http_rpc_url: sdk_config.http_rpc_endpoint.clone(), wallet, response_cache: Arc::new(Mutex::new(VecDeque::new())), sdk_config, diff --git a/blueprints/incredible-squaring-eigenlayer/src/contexts/client.rs b/blueprints/incredible-squaring-eigenlayer/src/contexts/client.rs index 178dd492..b774b90c 100644 --- a/blueprints/incredible-squaring-eigenlayer/src/contexts/client.rs +++ b/blueprints/incredible-squaring-eigenlayer/src/contexts/client.rs @@ -1,6 +1,7 @@ use alloy_rpc_client::ReqwestClient; use color_eyre::Result; use eigensdk::crypto_bls::{OperatorId, Signature}; +use gadget_sdk::{config::StdGadgetConfiguration, ctx::KeystoreContext}; use reqwest::Url; use serde::{Deserialize, Serialize}; use serde_json::json; @@ -20,17 +21,19 @@ pub struct SignedTaskResponse { } /// Client for interacting with the Aggregator RPC -#[derive(Debug, Clone)] +#[derive(Debug, Clone, KeystoreContext)] pub struct AggregatorClient { client: ReqwestClient, + #[config] + pub std_config: StdGadgetConfiguration, } impl AggregatorClient { /// Creates a new AggregatorClient - pub fn new(aggregator_address: &str) -> Result { + pub fn new(aggregator_address: &str, std_config: StdGadgetConfiguration) -> Result { let url = Url::parse(&format!("http://{}", aggregator_address))?; let client = ReqwestClient::new_http(url); - Ok(Self { client }) + Ok(Self { client, std_config }) } /// Sends a signed task response to the aggregator @@ -78,7 +81,7 @@ mod tests { #[test] fn test_new_client() { - let client = AggregatorClient::new("127.0.0.1:8545"); + let client = AggregatorClient::new("127.0.0.1:8545", Default::default()); assert!(client.is_ok()); } diff --git a/blueprints/incredible-squaring-eigenlayer/src/main.rs b/blueprints/incredible-squaring-eigenlayer/src/main.rs index df7711ed..451cd994 100644 --- a/blueprints/incredible-squaring-eigenlayer/src/main.rs +++ b/blueprints/incredible-squaring-eigenlayer/src/main.rs @@ -1,9 +1,7 @@ use alloy_network::EthereumWallet; -use alloy_provider::ProviderBuilder; use alloy_signer_local::PrivateKeySigner; -use color_eyre::Result; use gadget_sdk::{ - events_watcher::evm::DefaultNodeConfig, + events_watcher::evm::get_wallet_provider_http, info, runners::{eigenlayer::EigenlayerConfig, BlueprintRunner}, }; @@ -18,74 +16,34 @@ use incredible_squaring_blueprint_eigenlayer::{ #[gadget_sdk::main(env)] async fn main() { - // Get the ECDSA key from the private key seed using alloy let signer: PrivateKeySigner = AGGREGATOR_PRIVATE_KEY .parse() .expect("failed to generate wallet "); let wallet = EthereumWallet::from(signer); - let provider = ProviderBuilder::new() - .with_recommended_fillers() - .wallet(wallet.clone()) - .on_http(env.http_rpc_endpoint.parse()?); - info!("Task Manager Address: {:?}", *TASK_MANAGER_ADDRESS); + let provider = get_wallet_provider_http(&env.http_rpc_endpoint, wallet.clone()); + + let server_address = format!("{}:{}", env.bind_addr, 8081); + let aggregator_client = AggregatorClient::new(&server_address, env.clone())?; + let aggregator_context = + AggregatorContext::new(server_address, *TASK_MANAGER_ADDRESS, wallet, env.clone()) + .await + .unwrap(); + let contract = IncredibleSquaringTaskManager::IncredibleSquaringTaskManagerInstance::new( *TASK_MANAGER_ADDRESS, provider, ); - info!("Protocol: Eigenlayer"); - info!( - "Registry Coordinator Address: {:?}", - env.protocol_specific - .eigenlayer()? - .registry_coordinator_address - ); - info!( - "Operator State Retriever Address: {:?}", - env.protocol_specific - .eigenlayer()? - .operator_state_retriever_address - ); - info!( - "Delegation Manager Address: {:?}", - env.protocol_specific - .eigenlayer()? - .delegation_manager_address - ); - info!( - "Strategy Manager Address: {:?}", - env.protocol_specific.eigenlayer()?.strategy_manager_address - ); - info!( - "AVS Directory Address: {:?}", - env.protocol_specific.eigenlayer()?.avs_directory_address - ); - - let server_address = format!("{}:{}", env.bind_addr, 8081); - let aggregator_client = AggregatorClient::new(&server_address)?; - let x_square_eigen = XsquareEigenEventHandler:: { - ctx: aggregator_client, + let initialize_task = InitializeBlsTaskEventHandler { + ctx: aggregator_context.clone(), contract: contract.clone().into(), }; - let aggregator_context = AggregatorContext::new( - server_address, - *TASK_MANAGER_ADDRESS, - env.http_rpc_endpoint.clone(), - wallet, - env.clone(), - ) - .await - .unwrap(); - - let initialize_task = InitializeBlsTaskEventHandler:: { - ctx: aggregator_context.clone(), + let x_square_eigen = XsquareEigenEventHandler { + ctx: aggregator_client, contract: contract.clone().into(), }; - // let (handle, aggregator_shutdown_tx) = - // aggregator_context.start(env.ws_rpc_endpoint.clone()); - info!("~~~ Executing the incredible squaring blueprint ~~~"); let eigen_config = EigenlayerConfig {}; BlueprintRunner::new(eigen_config, env) diff --git a/blueprints/incredible-squaring-symbiotic/src/main.rs b/blueprints/incredible-squaring-symbiotic/src/main.rs index cf45407f..37bf6794 100644 --- a/blueprints/incredible-squaring-symbiotic/src/main.rs +++ b/blueprints/incredible-squaring-symbiotic/src/main.rs @@ -1,7 +1,6 @@ use alloy_network::EthereumWallet; -use alloy_provider::ProviderBuilder; use color_eyre::Result; -use gadget_sdk::events_watcher::evm::DefaultNodeConfig; +use gadget_sdk::events_watcher::evm::get_wallet_provider_http; use gadget_sdk::runners::symbiotic::SymbioticConfig; use gadget_sdk::runners::BlueprintRunner; use gadget_sdk::{info, keystore::BackendExt}; @@ -23,20 +22,16 @@ async fn main() { // Get the ECDSA key from the private key seed using alloy let operator_signer = env.keystore()?.ecdsa_key()?.alloy_key()?; let wallet = EthereumWallet::new(operator_signer); - - let provider = ProviderBuilder::new() - .with_recommended_fillers() - .wallet(wallet.clone()) - .on_http(env.http_rpc_endpoint.parse()?); + let provider = get_wallet_provider_http(&env.http_rpc_endpoint, wallet); let contract = IncredibleSquaringTaskManager::IncredibleSquaringTaskManagerInstance::new( *TASK_MANAGER_ADDRESS, provider, ); - let x_square = blueprint::XsquareEventHandler:: { + let x_square = blueprint::XsquareEventHandler { context: blueprint::MyContext {}, - contract: contract.clone().into(), + contract: contract.into(), }; info!("~~~ Executing the incredible squaring blueprint ~~~"); diff --git a/macros/blueprint-proc-macro/src/event_listener/evm.rs b/macros/blueprint-proc-macro/src/event_listener/evm.rs index 48464b12..2a48b5e5 100644 --- a/macros/blueprint-proc-macro/src/event_listener/evm.rs +++ b/macros/blueprint-proc-macro/src/event_listener/evm.rs @@ -10,7 +10,7 @@ pub(crate) fn get_evm_instance_data( let instance_base = event_handler.instance().unwrap(); let instance_name = format_ident!("{}Instance", instance_base); let instance_wrapper_name = format_ident!("{}InstanceWrapper", instance_base); - let instance = quote! { #instance_base::#instance_name }; + let instance = quote! { #instance_base::#instance_name, alloy_network::Ethereum> }; ( instance_base, @@ -110,12 +110,11 @@ pub(crate) fn generate_evm_event_handler( #[automatically_derived] #[async_trait::async_trait] - impl gadget_sdk::events_watcher::evm::EvmEventHandler for #struct_name + impl gadget_sdk::events_watcher::evm::EvmEventHandler for #struct_name where - T: Clone + Send + Sync + gadget_sdk::events_watcher::evm::Config +'static, - #instance_wrapper_name : std::ops::Deref>, + #instance_wrapper_name >: std::ops::Deref, alloy_network::Ethereum>>, { - type Contract = #instance_wrapper_name ; + type Contract = #instance_wrapper_name >; type Event = #event; const GENESIS_TX_HASH: alloy_primitives::FixedBytes<32> = alloy_primitives::FixedBytes([0; 32]); @@ -162,6 +161,6 @@ pub(crate) fn generate_evm_event_handler( } } - impl gadget_sdk::event_listener::markers::IsEvm for #struct_name {} + impl gadget_sdk::event_listener::markers::IsEvm for #struct_name {} } } diff --git a/macros/blueprint-proc-macro/src/job.rs b/macros/blueprint-proc-macro/src/job.rs index 8714dfd9..43f533b5 100644 --- a/macros/blueprint-proc-macro/src/job.rs +++ b/macros/blueprint-proc-macro/src/job.rs @@ -238,29 +238,16 @@ pub(crate) fn generate_event_workflow_tokenstream( idx, suffix.to_lowercase() ); - let is_not_evm = !matches!(listener_meta.listener_type, ListenerType::Evm); // convert the listener var, which is just a struct name, to an ident let listener = listener_meta.listener.to_token_stream(); - let type_args = if is_not_evm { - proc_macro2::TokenStream::default() - } else { - quote! { } - }; - - let bounded_type_args = if is_not_evm { - proc_macro2::TokenStream::default() - } else { - quote! { } - }; - - let autogen_struct_name = quote! { #struct_name #type_args }; + let autogen_struct_name = quote! { #struct_name }; // Check for special cases let next_listener = if matches!(listener_meta.listener_type, ListenerType::Evm) { // How to inject not just this event handler, but all event handlers here? let wrapper = quote! { - gadget_sdk::event_listener::evm_contracts::EthereumHandlerWrapper<#autogen_struct_name, _> + gadget_sdk::event_listener::evm_contracts::EthereumHandlerWrapper<#autogen_struct_name> }; let ctx_create = quote! { @@ -278,7 +265,7 @@ pub(crate) fn generate_event_workflow_tokenstream( }); quote! { - async fn #listener_function_name #bounded_type_args(ctx: &#autogen_struct_name) -> Option>> { + async fn #listener_function_name (ctx: &#autogen_struct_name) -> Option>> { static ONCE: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false); if !ONCE.load(std::sync::atomic::Ordering::Relaxed) { ONCE.store(true, std::sync::atomic::Ordering::Relaxed); @@ -305,7 +292,7 @@ pub(crate) fn generate_event_workflow_tokenstream( .map(|ctx| (quote! {self}, (*ctx).clone())) .expect("No context found"); - let autogen_struct_name = quote! { #struct_name #type_args }; + let autogen_struct_name = quote! { #struct_name }; let context_ty = event_handler_arg_types .first() @@ -413,7 +400,7 @@ pub(crate) fn generate_event_workflow_tokenstream( }; quote! { - async fn #listener_function_name #bounded_type_args(ctx: &#autogen_struct_name) -> Option>> { + async fn #listener_function_name (ctx: &#autogen_struct_name) -> Option>> { static ONCE: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false); if !ONCE.load(std::sync::atomic::Ordering::Relaxed) { ONCE.store(true, std::sync::atomic::Ordering::Relaxed); @@ -541,8 +528,6 @@ pub fn generate_autogen_struct( .collect::>(); let mut required_fields = vec![]; - let mut type_params_bounds = proc_macro2::TokenStream::default(); - let mut type_params = proc_macro2::TokenStream::default(); // Even if multiple tangle listeners, we only need this once if event_listener_args.has_tangle() { @@ -558,12 +543,8 @@ pub fn generate_autogen_struct( let (_, _, instance_wrapper_name, _) = get_evm_instance_data(event_listener_args); required_fields.push(quote! { - pub contract: #instance_wrapper_name, + pub contract: #instance_wrapper_name>, }); - - type_params = quote! { }; - type_params_bounds = - quote! { }; } let combined_event_listener = generate_combined_event_listener_selector(&struct_name); @@ -574,13 +555,13 @@ pub fn generate_autogen_struct( #[doc = #fn_name_string] #[doc = "`]"] #[derive(Clone)] - pub struct #struct_name #type_params_bounds { + pub struct #struct_name { #(#required_fields)* #(#additional_params)* } #[async_trait::async_trait] - impl #type_params_bounds gadget_sdk::events_watcher::InitializableEventHandler for #struct_name #type_params { + impl gadget_sdk::events_watcher::InitializableEventHandler for #struct_name { async fn init_event_handler( &self, ) -> Option>> { diff --git a/sdk/src/event_listener/evm_contracts.rs b/sdk/src/event_listener/evm_contracts.rs index 646929e4..6decf392 100644 --- a/sdk/src/event_listener/evm_contracts.rs +++ b/sdk/src/event_listener/evm_contracts.rs @@ -1,6 +1,6 @@ use super::EventListener; use crate::event_listener::get_exponential_backoff; -use crate::events_watcher::evm::{Config as ConfigT, EvmEventHandler}; +use crate::events_watcher::evm::EvmEventHandler; use crate::store::LocalDatabase; use crate::{error, Error}; use alloy_contract::Event; @@ -12,24 +12,21 @@ use tokio_retry::Retry; use tracing::{info, warn}; use uuid::Uuid; -pub struct EthereumHandlerWrapper, C: ConfigT> { +pub struct EthereumHandlerWrapper { handler: Arc, contract: W::Contract, chain_id: u64, local_db: LocalDatabase, - _phantom: std::marker::PhantomData, } -pub type EvmWatcherWrapperContext = (>::Contract, Arc); +pub type EvmWatcherWrapperContext = (::Contract, Arc); #[async_trait::async_trait] -impl> - EventListener< - Vec<(Watcher::Event, alloy_rpc_types::Log)>, - EvmWatcherWrapperContext, - > for EthereumHandlerWrapper +impl + EventListener, EvmWatcherWrapperContext> + for EthereumHandlerWrapper { - async fn new(context: &EvmWatcherWrapperContext) -> Result + async fn new(context: &EvmWatcherWrapperContext) -> Result where Self: Sized, { @@ -46,7 +43,6 @@ impl> local_db, handler: context.1.clone(), contract: context.0.clone(), - _phantom: std::marker::PhantomData, }) } @@ -149,7 +145,7 @@ impl> } } -impl> EthereumHandlerWrapper { +impl EthereumHandlerWrapper { async fn run_event_loop(&mut self) -> Result<(), Error> { while let Some(events) = self.next_event().await { if events.is_empty() { @@ -168,198 +164,3 @@ impl> EthereumHandlerWrapper, C: ConfigT> { -// handler: Arc, -// contract: W::Contract, -// chain_id: u64, -// target_block_number: Option, -// dest_block: Option, -// local_db: LocalDatabase, -// _phantom: std::marker::PhantomData, -// } - -// pub type EvmWatcherWrapperContext = (>::Contract, Arc); - -// #[async_trait::async_trait] -// impl> -// EventListener< -// Vec<(Watcher::Event, alloy_rpc_types::Log)>, -// EvmWatcherWrapperContext, -// > for EthereumHandlerWrapper -// { -// async fn new(context: &EvmWatcherWrapperContext) -> Result -// where -// Self: Sized, -// { -// let chain_id: u64 = context -// .0 -// .provider() -// .root() -// .get_chain_id() -// .await -// .map_err(|err| Error::Client(err.to_string()))?; - -// Ok(Self { -// chain_id, -// target_block_number: None, -// dest_block: None, -// local_db: LocalDatabase::open("./db"), -// handler: context.1.clone(), -// contract: context.0.clone(), -// _phantom: std::marker::PhantomData, -// }) -// } - -// async fn next_event(&mut self) -> Option> { -// let contract = &self.contract; -// let step = 100; - -// // we only query this once, at the start of the events watcher. -// // then we will update it later once we fully synced. -// self.target_block_number = Some(contract.provider().get_block_number().await.ok()?); - -// self.local_db.set( -// &format!("TARGET_BLOCK_NUMBER_{:?}", contract.address()), -// self.target_block_number.expect("qed"), -// ); - -// let deployed_at = contract -// .provider() -// .get_transaction_receipt(Watcher::GENESIS_TX_HASH) -// .await -// .ok()? -// .map(|receipt| receipt.block_number().unwrap_or_default()) -// .unwrap_or_default(); - -// loop { -// let block = self -// .local_db -// .get(&format!("LAST_BLOCK_NUMBER_{}", contract.address())) -// .unwrap_or(deployed_at); -// self.dest_block = Some(core::cmp::min( -// block + step, -// self.target_block_number.expect("qed"), -// )); - -// let events_filter = contract.event::( -// Filter::new() -// .from_block(BlockNumberOrTag::Number(block + 1)) -// .to_block(BlockNumberOrTag::Number(self.dest_block.expect("qed"))), -// ); - -// let events = events_filter.query().await.ok()?; -// let events: Vec<_> = events.into_iter().collect(); -// if events.is_empty() { -// continue; -// } - -// return Some(events); -// } -// } - -// async fn handle_event( -// &mut self, -// events: Vec<(Watcher::Event, alloy_rpc_types::Log)>, -// ) -> Result<(), Error> { -// const MAX_RETRIES: usize = 5; -// let mut tasks = vec![]; -// let current_block_number = events[0].1.block_number; -// for (event, log) in &events { -// let backoff = get_exponential_backoff::(); -// let handler = self.handler.clone(); -// let task = async move { -// Retry::spawn(backoff, || async { handler.handle(log, event).await }).await -// }; - -// tasks.push(task); -// } - -// let result = futures::future::join_all(tasks).await; -// // this event will be marked as handled if at least one handler succeeded. -// // this because, for the failed events, we already tried to handle them -// // many times (at this point), and there is no point in trying again. -// let mark_as_handled = result.iter().any(Result::is_ok); -// // also, for all the failed event handlers, we should print what went -// // wrong. -// for r in &result { -// if let Err(e) = r { -// error!(?e, %self.chain_id, "Error while handling the event"); -// } -// } - -// if mark_as_handled { -// self.local_db.set( -// &format!("LAST_BLOCK_NUMBER_{}", self.contract.address()), -// current_block_number.unwrap_or_default(), -// ); -// } else { -// error!( -// "{} | Error while handling event, all handlers failed.", -// self.chain_id -// ); -// warn!("{} | Restarting event watcher ...", self.chain_id); -// // this a transient error, so we will retry again. -// return Ok(()); -// } - -// let dest_block = self.dest_block.expect("qed"); - -// // move the block pointer to the destination block -// self.local_db.set( -// &format!("LAST_BLOCK_NUMBER_{}", self.contract.address()), -// dest_block, -// ); -// // if we fully synced, we can update the target block number -// let should_cooldown = dest_block == self.target_block_number.expect("qed"); -// if should_cooldown { -// let duration = tokio::time::Duration::from_secs(10); -// trace!("Cooldown a bit for {}ms", duration.as_millis()); -// tokio::time::sleep(duration).await; -// // update the latest block number -// self.target_block_number = Some( -// self.contract -// .provider() -// .get_block_number() -// .await -// .map_err(Into::::into)?, -// ); -// self.local_db.set( -// &format!("TARGET_BLOCK_NUMBER_{}", self.contract.address()), -// self.target_block_number.expect("qed"), -// ); -// } - -// Ok(()) -// } - -// async fn execute(&mut self) -> Result<(), Error> { -// const MAX_RETRY_COUNT: usize = 10; -// let mut backoff = get_exponential_backoff::(); - -// let mut retry_count = 0; -// loop { -// match self.run_event_loop().await { -// Ok(_) => continue, -// Err(e) => { -// if retry_count >= MAX_RETRY_COUNT { -// break Err(e); -// } -// retry_count += 1; -// tokio::time::sleep(backoff.nth(retry_count).unwrap()).await; -// } -// } -// } -// } -// } - -// impl> EthereumHandlerWrapper { -// async fn run_event_loop(&mut self) -> Result<(), Error> { -// while let Some(events) = self.next_event().await { -// self.handle_event(events).await?; -// } - -// crate::warn!("Event listener has stopped"); -// Err(Error::Other("Event listener has stopped".to_string())) -// } -// } diff --git a/sdk/src/events_watcher/evm.rs b/sdk/src/events_watcher/evm.rs index 1e766fac..42802178 100644 --- a/sdk/src/events_watcher/evm.rs +++ b/sdk/src/events_watcher/evm.rs @@ -3,52 +3,36 @@ use crate::events_watcher::error::Error; use alloy_network::{Ethereum, EthereumWallet}; use alloy_primitives::FixedBytes; -use alloy_provider::{ - fillers::{ChainIdFiller, FillProvider, GasFiller, JoinFill, NonceFiller, WalletFiller}, - Identity, Provider, ProviderBuilder, RootProvider, WsConnect, -}; +use alloy_provider::{Provider, ProviderBuilder, RootProvider, WsConnect}; use alloy_sol_types::SolEvent; -use alloy_transport::{BoxTransport, Transport}; -use alloy_transport_http::{Client, Http}; +use alloy_transport::BoxTransport; use std::ops::Deref; -pub trait Config: Send + Sync + Clone + 'static { - type TH: Transport + Clone + Send + Sync; - type PH: Provider + Clone + Send + Sync; -} - -#[derive(Debug, Copy, Clone)] -pub struct DefaultNodeConfig {} - -impl Config for DefaultNodeConfig { - type TH = Http; - type PH = FillProvider< - JoinFill< - JoinFill, NonceFiller>, ChainIdFiller>, - WalletFiller, +pub trait EvmContract: + Deref< + Target = alloy_contract::ContractInstance< + BoxTransport, + RootProvider, + Ethereum, >, - RootProvider>, - Http, - Ethereum, - >; -} - -pub trait EvmContract: - Deref> - + Send + > + Send + Clone + Sync + 'static { } impl< - T: Config, - X: Deref> - + Send + X: Deref< + Target = alloy_contract::ContractInstance< + BoxTransport, + RootProvider, + Ethereum, + >, + > + Send + Clone + Sync + 'static, - > EvmContract for X + > EvmContract for X { } @@ -58,9 +42,9 @@ impl EvmEvent for X {} /// A trait for watching events from a contract. /// EventWatcher trait exists for deployments that are smart-contract / EVM based #[async_trait::async_trait] -pub trait EvmEventHandler: Send + Sync + 'static { +pub trait EvmEventHandler: Send + Sync + 'static { /// The contract that this event watcher is watching. - type Contract: EvmContract; + type Contract: EvmContract; /// The type of event this handler is for. type Event: EvmEvent; /// The genesis transaction hash for the contract. From 7df36ec7bbf4f566f9c64a8fc72e3a44b4d9eb3e Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Thu, 31 Oct 2024 01:04:23 +0700 Subject: [PATCH 2/3] chore: attempt to remove hardcoded operator id --- blueprint-test-utils/src/helpers.rs | 5 ++-- .../src/jobs/compute_x_square.rs | 27 +++++++++++-------- .../incredible-squaring-symbiotic/src/main.rs | 1 - 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/blueprint-test-utils/src/helpers.rs b/blueprint-test-utils/src/helpers.rs index 0aa90ce5..2e40f651 100644 --- a/blueprint-test-utils/src/helpers.rs +++ b/blueprint-test-utils/src/helpers.rs @@ -127,8 +127,9 @@ impl BlueprintProcessManager { } if let Protocol::Eigenlayer = protocol { - in_memory_keystore.bls_bn254_generate_from_string("1371012690269088913462269866874713266643928125698382731338806296762673180359922".to_string()) + let public = in_memory_keystore.bls_bn254_generate_from_string("1371012690269088913462269866874713266643928125698382731338806296762673180359922".to_string()) .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; + println!("Public key: {:?}", public); }; let mut arguments = vec![ @@ -139,7 +140,7 @@ impl BlueprintProcessManager { format!("--ws-rpc-url={}", Url::parse(ws_endpoint).unwrap()), format!("--keystore-uri={}", keystore_uri_str.clone()), format!("--chain={}", SupportedChains::LocalTestnet), - format!("--vvv"), + format!("-vvv"), format!("--pretty"), format!("--blueprint-id={}", instance_id), format!("--service-id={}", instance_id), diff --git a/blueprints/incredible-squaring-eigenlayer/src/jobs/compute_x_square.rs b/blueprints/incredible-squaring-eigenlayer/src/jobs/compute_x_square.rs index d8b97a07..d9188a4d 100644 --- a/blueprints/incredible-squaring-eigenlayer/src/jobs/compute_x_square.rs +++ b/blueprints/incredible-squaring-eigenlayer/src/jobs/compute_x_square.rs @@ -1,14 +1,18 @@ #![allow(dead_code)] use crate::contexts::client::{AggregatorClient, SignedTaskResponse}; use crate::{noop, IncredibleSquaringTaskManager, INCREDIBLE_SQUARING_TASK_MANAGER_ABI_STRING}; -use alloy_primitives::keccak256; use alloy_primitives::{hex, Bytes, U256}; +use alloy_primitives::{keccak256, FixedBytes}; use alloy_sol_types::SolType; use ark_bn254::Fq; use ark_ff::{BigInteger, PrimeField}; +use color_eyre::owo_colors::OwoColorize; use color_eyre::Result; use eigensdk::crypto_bls::BlsKeyPair; use eigensdk::crypto_bls::OperatorId; +use eigensdk::types::operator::operator_id_from_g1_pub_key; +use gadget_sdk::ctx::KeystoreContext; +use gadget_sdk::keystore::BackendExt; use gadget_sdk::{error, info, job}; use std::{convert::Infallible, ops::Deref, sync::OnceLock}; use IncredibleSquaringTaskManager::TaskResponse; @@ -42,17 +46,18 @@ pub async fn xsquare_eigen( numberSquared: number_to_be_squared.saturating_pow(U256::from(2u32)), }; - let bls_key_pair = BlsKeyPair::new( - "1371012690269088913462269866874713266643928125698382731338806296762673180359922" - .to_string(), - ) - .unwrap(); + // let bls_key_pair = BlsKeyPair::new( + // "1371012690269088913462269866874713266643928125698382731338806296762673180359922" + // .to_string(), + // ) + // .unwrap(); - let operator_id = alloy_primitives::FixedBytes( - eigensdk::types::operator::operator_id_from_g1_pub_key(bls_key_pair.public_key()).unwrap(), - ); - let operator_id: OperatorId = - hex!("fd329fe7e54f459b9c104064efe0172db113a50b5f394949b4ef80b3c34ca7f5").into(); + let bls_key_pair = ctx.keystore().unwrap().bls_bn254_key().unwrap(); + let mut operator_id = operator_id_from_g1_pub_key(bls_key_pair.public_key()).unwrap(); + let operator_id = FixedBytes(operator_id); + println!("Operator ID: {:?}", operator_id); + // let operator_id: OperatorId = + // hex!("fd329fe7e54f459b9c104064efe0172db113a50b5f394949b4ef80b3c34ca7f5").into(); // Sign the Hashed Message and send it to the BLS Aggregator let msg_hash = keccak256(::abi_encode(&task_response)); diff --git a/blueprints/incredible-squaring-symbiotic/src/main.rs b/blueprints/incredible-squaring-symbiotic/src/main.rs index 37bf6794..b1610a7d 100644 --- a/blueprints/incredible-squaring-symbiotic/src/main.rs +++ b/blueprints/incredible-squaring-symbiotic/src/main.rs @@ -19,7 +19,6 @@ lazy_static! { #[gadget_sdk::main(env)] async fn main() { - // Get the ECDSA key from the private key seed using alloy let operator_signer = env.keystore()?.ecdsa_key()?.alloy_key()?; let wallet = EthereumWallet::new(operator_signer); let provider = get_wallet_provider_http(&env.http_rpc_endpoint, wallet); From b70e529463419cea6e5a859cac4d4b164cdd6de1 Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Thu, 31 Oct 2024 02:42:50 +0700 Subject: [PATCH 3/3] chore: fix fmt and ensure eigen test works --- Cargo.lock | 1 + Cargo.toml | 1 + .../src/contexts/client.rs | 2 +- .../src/jobs/compute_x_square.rs | 45 +++++++------------ sdk/Cargo.toml | 1 + sdk/src/runners/eigenlayer.rs | 15 +++++++ 6 files changed, 35 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 82d45a80..46424909 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4779,6 +4779,7 @@ dependencies = [ "lock_api", "log", "nix 0.29.0", + "num-bigint 0.4.6", "parking_lot 0.12.3", "prometheus", "rand", diff --git a/Cargo.toml b/Cargo.toml index 0931e770..42e87f16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -111,6 +111,7 @@ lock_api = "0.4.12" log = "0.4.22" multiaddr = { version = "0.18.1", default-features = false } nix = { version = "0.29.0", features = ["process", "signal"] } +num-bigint = "0.4.6" parking_lot = "0.12.3" proc-macro2 = "1.0" prometheus = { version = "0.13.4", default-features = false } diff --git a/blueprints/incredible-squaring-eigenlayer/src/contexts/client.rs b/blueprints/incredible-squaring-eigenlayer/src/contexts/client.rs index b774b90c..0028f4b2 100644 --- a/blueprints/incredible-squaring-eigenlayer/src/contexts/client.rs +++ b/blueprints/incredible-squaring-eigenlayer/src/contexts/client.rs @@ -20,7 +20,7 @@ pub struct SignedTaskResponse { pub operator_id: OperatorId, } -/// Client for interacting with the Aggregator RPC +/// Client for interacting with the Aggregator RPC server #[derive(Debug, Clone, KeystoreContext)] pub struct AggregatorClient { client: ReqwestClient, diff --git a/blueprints/incredible-squaring-eigenlayer/src/jobs/compute_x_square.rs b/blueprints/incredible-squaring-eigenlayer/src/jobs/compute_x_square.rs index d9188a4d..968930f0 100644 --- a/blueprints/incredible-squaring-eigenlayer/src/jobs/compute_x_square.rs +++ b/blueprints/incredible-squaring-eigenlayer/src/jobs/compute_x_square.rs @@ -1,23 +1,22 @@ #![allow(dead_code)] use crate::contexts::client::{AggregatorClient, SignedTaskResponse}; use crate::{noop, IncredibleSquaringTaskManager, INCREDIBLE_SQUARING_TASK_MANAGER_ABI_STRING}; -use alloy_primitives::{hex, Bytes, U256}; -use alloy_primitives::{keccak256, FixedBytes}; +use alloy_primitives::keccak256; +use alloy_primitives::{Bytes, U256}; use alloy_sol_types::SolType; -use ark_bn254::Fq; -use ark_ff::{BigInteger, PrimeField}; -use color_eyre::owo_colors::OwoColorize; use color_eyre::Result; -use eigensdk::crypto_bls::BlsKeyPair; -use eigensdk::crypto_bls::OperatorId; -use eigensdk::types::operator::operator_id_from_g1_pub_key; use gadget_sdk::ctx::KeystoreContext; use gadget_sdk::keystore::BackendExt; +use gadget_sdk::runners::eigenlayer::derive_operator_id; use gadget_sdk::{error, info, job}; use std::{convert::Infallible, ops::Deref, sync::OnceLock}; use IncredibleSquaringTaskManager::TaskResponse; -/// Returns x^2 saturating to [`u64::MAX`] if overflow occurs. +/// Sends a signed task response to the BLS Aggregator. +/// This job is triggered by the `NewTaskCreated` event emitted by the `IncredibleSquaringTaskManager`. +/// The job calculates the square of the number to be squared and sends the signed task response to the BLS Aggregator. +/// The job returns 1 if the task response was sent successfully. +/// The job returns 0 if the task response failed to send or failed to get the BLS key. #[job( id = 0, params(number_to_be_squared, task_created_block, quorum_numbers, quorum_threshold_percentage, task_index), @@ -46,18 +45,14 @@ pub async fn xsquare_eigen( numberSquared: number_to_be_squared.saturating_pow(U256::from(2u32)), }; - // let bls_key_pair = BlsKeyPair::new( - // "1371012690269088913462269866874713266643928125698382731338806296762673180359922" - // .to_string(), - // ) - // .unwrap(); - - let bls_key_pair = ctx.keystore().unwrap().bls_bn254_key().unwrap(); - let mut operator_id = operator_id_from_g1_pub_key(bls_key_pair.public_key()).unwrap(); - let operator_id = FixedBytes(operator_id); - println!("Operator ID: {:?}", operator_id); - // let operator_id: OperatorId = - // hex!("fd329fe7e54f459b9c104064efe0172db113a50b5f394949b4ef80b3c34ca7f5").into(); + let bls_key_pair = match ctx.keystore().and_then(|ks| Ok(ks.bls_bn254_key())) { + Ok(kp) => match kp { + Ok(k) => k, + Err(e) => return Ok(0), + }, + Err(e) => return Ok(0), + }; + let operator_id = derive_operator_id(bls_key_pair.public_key()); // Sign the Hashed Message and send it to the BLS Aggregator let msg_hash = keccak256(::abi_encode(&task_response)); @@ -101,11 +96,3 @@ pub fn convert_event_to_inputs( task_index, ) } - -/// Helper for converting a PrimeField to its U256 representation for Ethereum compatibility -/// (U256 reads data as big endian) -pub fn point_to_u256(point: Fq) -> U256 { - let point = point.into_bigint(); - let point_bytes = point.to_bytes_be(); - U256::from_be_slice(&point_bytes[..]) -} diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index 85340b52..bc0bc360 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -27,6 +27,7 @@ clap = { workspace = true, features = ["derive", "wrap_help"] } url = { workspace = true, features = ["serde"] } uuid = { workspace = true } failure = { workspace = true } +num-bigint = { workspace = true } # Keystore deps ed25519-zebra = { workspace = true } diff --git a/sdk/src/runners/eigenlayer.rs b/sdk/src/runners/eigenlayer.rs index 55725b60..b09673b4 100644 --- a/sdk/src/runners/eigenlayer.rs +++ b/sdk/src/runners/eigenlayer.rs @@ -151,3 +151,18 @@ impl BlueprintConfig for EigenlayerConfig { Ok(()) } } + +pub fn derive_operator_id( + pub_key: eigensdk::crypto_bls::BlsG1Point, +) -> alloy_primitives::FixedBytes<32> { + let pub_key_affine = pub_key.g1(); + + let x_int: num_bigint::BigUint = pub_key_affine.x.into(); + let y_int: num_bigint::BigUint = pub_key_affine.y.into(); + + let x_bytes = x_int.to_bytes_be(); + let y_bytes = y_int.to_bytes_be(); + + let hash = alloy_primitives::keccak256([x_bytes, y_bytes].concat()); + hash +}