diff --git a/Cargo.lock b/Cargo.lock index e3866f12..330f97ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1946,6 +1946,7 @@ dependencies = [ "sp-core", "sp-io", "subxt", + "tempfile", "testcontainers", "thiserror", "tokio", @@ -5903,6 +5904,7 @@ dependencies = [ "lazy_static", "libp2p", "lock_api", + "num-bigint 0.4.6", "parking_lot 0.12.3", "reqwest 0.12.9", "serde", diff --git a/Cargo.toml b/Cargo.toml index 190ef14e..6b4dcea3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -113,6 +113,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/blueprint-test-utils/Cargo.toml b/blueprint-test-utils/Cargo.toml index cd42e7fc..5406cbe9 100644 --- a/blueprint-test-utils/Cargo.toml +++ b/blueprint-test-utils/Cargo.toml @@ -53,6 +53,7 @@ alloy-transport = { workspace = true } # Utility testcontainers = { workspace = true } uuid = { workspace = true, features = ["v4"] } +tempfile = { workspace = true } [dev-dependencies] cargo_metadata = { workspace = true } diff --git a/blueprint-test-utils/src/helpers.rs b/blueprint-test-utils/src/helpers.rs index 71f0e4af..41832f6a 100644 --- a/blueprint-test-utils/src/helpers.rs +++ b/blueprint-test-utils/src/helpers.rs @@ -1,18 +1,11 @@ -use crate::test_ext::{find_open_tcp_bind_port, NAME_IDS}; use alloy_contract::{CallBuilder, CallDecoder}; use alloy_primitives::hex; -use alloy_provider::{network::Ethereum, Provider}; use alloy_rpc_types::TransactionReceipt; -use alloy_transport::{Transport, TransportError}; -use gadget_io::SupportedChains; use gadget_sdk::config::protocol::{EigenlayerContractAddresses, SymbioticContractAddresses}; -use gadget_sdk::config::Protocol; use gadget_sdk::error; -use gadget_sdk::keystore::backend::fs::FilesystemKeystore; -use gadget_sdk::keystore::Backend; use std::collections::HashMap; use std::net::IpAddr; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::str::FromStr; use std::sync::Arc; use thiserror::Error; @@ -20,6 +13,14 @@ use tokio::process::Child; use tokio::sync::Mutex; use url::Url; +use crate::test_ext::{find_open_tcp_bind_port, NAME_IDS}; +use crate::{inject_test_keys, KeyGenType}; +use alloy_provider::{network::Ethereum, Provider}; +use alloy_transport::{Transport, TransportError}; +use gadget_io::SupportedChains; + +use gadget_sdk::config::Protocol; + #[derive(Error, Debug)] pub enum BlueprintError { #[error("Transport error occurred: {0}")] @@ -88,9 +89,10 @@ impl BlueprintProcessManager { http_endpoint: &str, ws_endpoint: &str, protocol: Protocol, + keystore_path: &str, ) -> Result { - let tmp_dir = std::env::current_dir()?; - let keystore_uri = tmp_dir.join(format!( + let keystore_path = Path::new(&keystore_path); + let keystore_uri = keystore_path.join(format!( "keystores/{}/{}", NAME_IDS[instance_id].to_lowercase(), uuid::Uuid::new_v4() @@ -105,33 +107,24 @@ impl BlueprintProcessManager { std::path::absolute(&keystore_uri).expect("Failed to resolve keystore URI"); let keystore_uri_str = format!("file:{}", keystore_uri_normalized.display()); - let filesystem_keystore = FilesystemKeystore::open(keystore_uri_str.clone()) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; - // let _ = ANVIL_PRIVATE_KEYS.iter().enumerate().map(|(key, _)| inject_test_keys(&keystore_uri_normalized.clone(), KeyGenType::Anvil(key))); - - for seed in [ - "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", - "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", - "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", - "0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", - "0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a", - "0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba", - "0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e", - "0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356", - "0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97", - "0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6", - ] { - let seed_bytes = hex::decode(&seed[2..]).expect("Invalid hex seed"); - filesystem_keystore - .ecdsa_generate_new(Some(&seed_bytes)) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; + match protocol { + Protocol::Tangle => { + inject_test_keys(&keystore_uri.clone(), KeyGenType::Tangle(0)) + .await + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; + } + Protocol::Eigenlayer => { + inject_test_keys(&keystore_uri.clone(), KeyGenType::Anvil(0)) + .await + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; + } + Protocol::Symbiotic => { + inject_test_keys(&keystore_uri.clone(), KeyGenType::Anvil(0)) + .await + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; + } } - if let Protocol::Eigenlayer = protocol { - filesystem_keystore.bls_bn254_generate_from_string("1371012690269088913462269866874713266643928125698382731338806296762673180359922".to_string()) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; - }; - let mut arguments = vec![ "run".to_string(), format!("--target-addr={}", IpAddr::from_str("127.0.0.1").unwrap()), @@ -223,6 +216,7 @@ impl BlueprintProcessManager { http_endpoint: &str, ws_endpoint: &str, protocol: Protocol, + keystore_path: &str, ) -> Result<(), std::io::Error> { for (index, program_path) in blueprint_paths.into_iter().enumerate() { let process = Self::start_blueprint_process( @@ -231,6 +225,7 @@ impl BlueprintProcessManager { http_endpoint, ws_endpoint, protocol, + keystore_path, ) .await?; self.processes.lock().await.push(process); diff --git a/blueprint-test-utils/src/incredible_squaring_helpers.rs b/blueprint-test-utils/src/incredible_squaring_helpers.rs index 4e0472de..73f928b1 100644 --- a/blueprint-test-utils/src/incredible_squaring_helpers.rs +++ b/blueprint-test-utils/src/incredible_squaring_helpers.rs @@ -81,6 +81,7 @@ pub async fn setup_task_spawner( loop { tokio::time::sleep(std::time::Duration::from_millis(10000)).await; + info!("Creating a new task..."); if get_receipt( task_manager .createNewTask(U256::from(2), 100u32, quorums.clone()) diff --git a/blueprint-test-utils/src/lib.rs b/blueprint-test-utils/src/lib.rs index dde14363..4ecd38a9 100644 --- a/blueprint-test-utils/src/lib.rs +++ b/blueprint-test-utils/src/lib.rs @@ -19,6 +19,7 @@ use libp2p::Multiaddr; pub use log; use sp_core::Pair as PairT; use std::error::Error; +use std::ffi::OsStr; use std::net::IpAddr; use std::path::{Path, PathBuf}; use std::time::Duration; @@ -64,13 +65,15 @@ pub struct PerTestNodeInput { /// Runs a test node using a top-down approach and invoking the blueprint manager to auto manage /// execution of blueprints and their associated services for the test node. -pub async fn run_test_blueprint_manager( +pub async fn run_test_blueprint_manager + 'static>( input: PerTestNodeInput, ) -> BlueprintManagerHandle { let name_lower = NAME_IDS[input.instance_id as usize].to_lowercase(); + let keystore_path = Path::new(&input.extra_input); + let tmp_store = Uuid::new_v4().to_string(); - let keystore_uri = PathBuf::from(format!("./target/keystores/{name_lower}/{tmp_store}/",)); + let keystore_uri = keystore_path.join(format!("keystores/{name_lower}/{tmp_store}/")); assert!( !keystore_uri.exists(), @@ -82,11 +85,11 @@ pub async fn run_test_blueprint_manager( .expect("Failed to get current directory"); let keystore_uri_normalized = - std::path::absolute(keystore_uri).expect("Failed to resolve keystore URI"); + std::path::absolute(keystore_uri.clone()).expect("Failed to resolve keystore URI"); let keystore_uri_str = format!("file:{}", keystore_uri_normalized.display()); inject_test_keys( - &keystore_uri_normalized, + &keystore_uri, KeyGenType::Tangle(input.instance_id as usize), ) .await @@ -155,19 +158,30 @@ pub enum KeyGenType { Tangle(usize), } -/// Adds keys relevant for the test to the keystore, and performs some necessary -/// cross-compatability tests to ensure key use consistency between different parts of the codebase +/// Adds keys for testing to the keystore. +/// +/// # Arguments +/// +/// - `keystore_path`: The path for the keystore. +/// - `key_gen_type`: The type of key to generate, specified by the [`KeyGenType`] enum. +/// +/// # Key Generation /// -/// Accepted `node_index` values: -/// - 0-4: Pre-made Tangle accounts (SR25519 and ECDSA are predetermined while BLS is random) -/// - 5+: Randomly generated keys (All key types are generated randomly) +/// Depending on the [`KeyGenType`] provided: +/// - `Random`: Generates all random keys. +/// - `Anvil(index)`: Injects the pre-made Anvil ECDSA key from the 10 Anvil dev keys based on the provided index (0-9) and generates a random keys for each other key type +/// - `Tangle(index)`: Injects the pre-made Tangle ED25519, ECDSA, and SR25519 keys based on the provided index (0-4). Randomly generates BLS keys /// /// # Errors /// -/// - If the keystore path cannot be created -/// - If key generation fails for any reason `Invalid Seed` or `Random Key Generation Failed` Error -/// - If the sanity checks for the generated keys fail +/// This function will return an error if: +/// - The keystore path cannot be created. +/// - Key generation fails for any reason (e.g., invalid seed, random generation failure). +/// - The given index is out of bounds for Anvil or Tangle key types. /// +/// # Returns +/// +/// Returns `Ok(())` if the keys were successfully injected, otherwise returns an `Err`. pub async fn inject_test_keys>( keystore_path: P, key_gen_type: KeyGenType, @@ -193,6 +207,13 @@ pub async fn inject_test_keys>( /// Injects the pre-made Anvil key of the given index where that index is 0-9 /// +/// # Keys Generated +/// - `SR25519`: Random +/// - `ED25519`: Random +/// - `ECDSA`: Anvil Dev Key +/// - `BLS BN254`: Random +/// - `BLS381`: Random +/// /// # Errors /// - Fails if the given index is out of bounds /// - May fail if the keystore path cannot be created or accessed @@ -206,15 +227,31 @@ fn inject_anvil_key>(keystore_path: P, seed: &str) -> color_eyre: keystore .ecdsa_generate_new(Some(&seed_bytes)) .map_err(|e| eyre!(e))?; - keystore .bls_bn254_generate_new(None) .map_err(|e| eyre!(e))?; + keystore.sr25519_generate_new(None).map_err(|e| eyre!(e))?; + keystore.ed25519_generate_new(None).map_err(|e| eyre!(e))?; + keystore.bls381_generate_new(None).map_err(|e| eyre!(e))?; Ok(()) } -/// Injects the pre-made Tangle key of the given index where that index is 0-4 +/// Injects the pre-made Tangle keys of the given index where that index is 0-4 +/// +/// # Keys Generated +/// - `SR25519`: Tangle Dev Key +/// - `ED25519`: Tangle Dev Key +/// - `ECDSA`: Tangle Dev Key +/// - `BLS BN254`: Random +/// - `BLS381`: Random +/// +/// # Indices +/// - 0: Alice +/// - 1: Bob +/// - 2: Charlie +/// - 3:Dave +/// - 4: Eve /// /// # Errors /// - Fails if the given index is out of bounds @@ -225,13 +262,12 @@ fn inject_tangle_key>(keystore_path: P, name: &str) -> color_eyre keystore_path.as_ref(), )?); - let suri = format!("//{name}"); // <---- is the exact same as the ones in the chainspec + let suri = format!("//{name}"); let sr = sp_core::sr25519::Pair::from_string(&suri, None).expect("Should be valid SR keypair"); let sr_seed = &sr.as_ref().secret.to_bytes(); let ed = sp_core::ed25519::Pair::from_string(&suri, None).expect("Should be valid ED keypair"); - // using Pair::from_string is the exact same as TPublic::from_string in the chainspec let ed_seed = &ed.seed(); let ecdsa = @@ -240,16 +276,17 @@ fn inject_tangle_key>(keystore_path: P, name: &str) -> color_eyre keystore .sr25519_generate_new(Some(sr_seed)) - .expect("Invalid SR25519 seed"); + .map_err(|e| eyre!(e))?; keystore .ed25519_generate_new(Some(ed_seed)) - .expect("Should be valid ED25519 seed"); + .map_err(|e| eyre!(e))?; keystore .ecdsa_generate_new(Some(&ecdsa_seed)) - .expect("Invalid ECDSA seed"); + .map_err(|e| eyre!(e))?; + keystore.bls381_generate_new(None).map_err(|e| eyre!(e))?; keystore .bls_bn254_generate_new(None) - .expect("Random BLS Key Generation Failed"); + .map_err(|e| eyre!(e))?; // Perform sanity checks on conversions between secrets to ensure // consistency as the program executes @@ -295,10 +332,18 @@ fn inject_tangle_key>(keystore_path: P, name: &str) -> color_eyre panic!("Failed to load ed25519 key: {err}"); } } + Ok(()) } -/// Injects a random key into the keystore at the given path +/// Injects randomly generated keys into the keystore at the given path +/// +/// # Keys Generated +/// - `SR25519` - Random +/// - `ED25519` - Random +/// - `ECDSA` - Random +/// - `BLS BN254` - Random +/// - `BLS381` - Random /// /// # Errors /// - May fail if the keystore path cannot be created or accessed @@ -307,15 +352,13 @@ pub fn inject_random_key>(keystore_path: P) -> color_eyre::Result let keystore = GenericKeyStore::::Fs(FilesystemKeystore::open( keystore_path.as_ref(), )?); - keystore - .sr25519_generate_new(None) - .expect("Random SR25519 Key Generation Failed"); - keystore - .ecdsa_generate_new(None) - .expect("Random ECDSA Key Generation Failed"); + keystore.sr25519_generate_new(None).map_err(|e| eyre!(e))?; + keystore.ed25519_generate_new(None).map_err(|e| eyre!(e))?; + keystore.ecdsa_generate_new(None).map_err(|e| eyre!(e))?; keystore .bls_bn254_generate_new(None) - .expect("Random BLS Key Generation Failed"); + .map_err(|e| eyre!(e))?; + keystore.bls381_generate_new(None).map_err(|e| eyre!(e))?; Ok(()) } @@ -542,6 +585,9 @@ macro_rules! test_blueprint { setup_log(); let mut base_path = std::env::current_dir().expect("Failed to get current directory"); + let tmp_dir = tempfile::TempDir::new().unwrap(); // Create a temporary directory for the keystores + let tmp_dir_path = format!("{}", tmp_dir.path().display()); + base_path.push($blueprint_path); base_path .canonicalize() @@ -562,8 +608,8 @@ macro_rules! test_blueprint { signer_evm: None, }; - new_test_ext_blueprint_manager::<$N, 1, (), _, _>( - (), + new_test_ext_blueprint_manager::<$N, 1, String, _, _>( + tmp_dir_path, opts, run_test_blueprint_manager, ) @@ -660,6 +706,8 @@ mod tests_standard { async fn test_externalities_gadget_starts() { setup_log(); let mut base_path = std::env::current_dir().expect("Failed to get current directory"); + let tmp_dir = tempfile::TempDir::new().unwrap(); // Create a temporary directory for the keystores + let tmp_dir_path = format!("{}", tmp_dir.path().display()); base_path.push("../blueprints/incredible-squaring"); base_path @@ -680,57 +728,61 @@ mod tests_standard { const INPUT: u64 = 10; const OUTPUT: u64 = INPUT.pow(2); - new_test_ext_blueprint_manager::<5, 1, (), _, _>((), opts, run_test_blueprint_manager) + new_test_ext_blueprint_manager::<5, 1, String, _, _>( + tmp_dir_path, + opts, + run_test_blueprint_manager, + ) + .await + .execute_with_async(move |client, handles, blueprint| async move { + // At this point, blueprint has been deployed, every node has registered + // as an operator for the relevant services, and, all gadgets are running + + // What's left: Submit a job, wait for the job to finish, then assert the job results + let keypair = handles[0].sr25519_id().clone(); + let selected_service = &blueprint.services[0]; + let service_id = selected_service.id; + let call_id = get_next_call_id(client) + .await + .expect("Failed to get next job id") + .saturating_sub(1); + + info!("Submitting job with params service ID: {service_id}, call ID: {call_id}"); + + // Pass the arguments + let mut job_args = Args::new(); + let input = + api::runtime_types::tangle_primitives::services::field::Field::Uint64(INPUT); + job_args.push(input); + + // Next step: submit a job under that service/job id + if let Err(err) = submit_job( + client, + &keypair, + service_id, + Job::from(call_id as u8), + job_args, + ) .await - .execute_with_async(move |client, handles, blueprint| async move { - // At this point, blueprint has been deployed, every node has registered - // as an operator for the relevant services, and, all gadgets are running + { + error!("Failed to submit job: {err}"); + panic!("Failed to submit job: {err}"); + } - // What's left: Submit a job, wait for the job to finish, then assert the job results - let keypair = handles[0].sr25519_id().clone(); - let selected_service = &blueprint.services[0]; - let service_id = selected_service.id; - let call_id = get_next_call_id(client) + // Step 2: wait for the job to complete + let job_results = + wait_for_completion_of_tangle_job(client, service_id, call_id, handles.len()) .await - .expect("Failed to get next job id") - .saturating_sub(1); - - info!("Submitting job with params service ID: {service_id}, call ID: {call_id}"); - - // Pass the arguments - let mut job_args = Args::new(); - let input = - api::runtime_types::tangle_primitives::services::field::Field::Uint64(INPUT); - job_args.push(input); - - // Next step: submit a job under that service/job id - if let Err(err) = submit_job( - client, - &keypair, - service_id, - Job::from(call_id as u8), - job_args, - ) - .await - { - error!("Failed to submit job: {err}"); - panic!("Failed to submit job: {err}"); - } - - // Step 2: wait for the job to complete - let job_results = - wait_for_completion_of_tangle_job(client, service_id, call_id, handles.len()) - .await - .expect("Failed to wait for job completion"); + .expect("Failed to wait for job completion"); - // Step 3: Get the job results, compare to expected value(s) - let expected_result = - api::runtime_types::tangle_primitives::services::field::Field::Uint64(OUTPUT); - assert_eq!(job_results.service_id, service_id); - assert_eq!(job_results.call_id, call_id); - assert_eq!(job_results.result[0], expected_result); - }) - .await + // Step 3: Get the job results, compare to expected value(s) + let expected_result = + api::runtime_types::tangle_primitives::services::field::Field::Uint64(OUTPUT); + assert_eq!(job_results.service_id, service_id); + assert_eq!(job_results.call_id, call_id); + assert_eq!(job_results.result[0], expected_result); + }) + .await } #[tokio::test(flavor = "multi_thread")] @@ -813,12 +865,16 @@ mod tests_standard { .canonicalize() .unwrap(); + let tmp_dir = tempfile::TempDir::new().unwrap(); + let keystore_path = &format!("{}", tmp_dir.path().display()); + blueprint_process_manager .start_blueprints( vec![xsquare_task_program_path], &http_endpoint, ws_endpoint.as_ref(), Protocol::Eigenlayer, + keystore_path, ) .await .unwrap(); diff --git a/blueprints/incredible-squaring-eigenlayer/Cargo.toml b/blueprints/incredible-squaring-eigenlayer/Cargo.toml index 23177997..97a8ee99 100644 --- a/blueprints/incredible-squaring-eigenlayer/Cargo.toml +++ b/blueprints/incredible-squaring-eigenlayer/Cargo.toml @@ -53,6 +53,7 @@ bip39 = { workspace = true } thiserror = { workspace = true } jsonrpc-core = { workspace = true } jsonrpc-http-server = { workspace = true } +num-bigint = { workspace = true } [dev-dependencies] blueprint-test-utils = { workspace = true } diff --git a/blueprints/incredible-squaring-eigenlayer/src/contexts/mod.rs b/blueprints/incredible-squaring-eigenlayer/src/contexts/mod.rs index 47404ef0..d4f5d94b 100644 --- a/blueprints/incredible-squaring-eigenlayer/src/contexts/mod.rs +++ b/blueprints/incredible-squaring-eigenlayer/src/contexts/mod.rs @@ -1,2 +1,3 @@ pub mod aggregator; pub mod client; +pub mod x_square; diff --git a/blueprints/incredible-squaring-eigenlayer/src/contexts/x_square.rs b/blueprints/incredible-squaring-eigenlayer/src/contexts/x_square.rs new file mode 100644 index 00000000..dfec91e3 --- /dev/null +++ b/blueprints/incredible-squaring-eigenlayer/src/contexts/x_square.rs @@ -0,0 +1,9 @@ +use crate::contexts::client::AggregatorClient; +use gadget_sdk::config::GadgetConfiguration; +use parking_lot::RawRwLock; + +#[derive(Clone)] +pub struct EigenSquareContext { + pub client: AggregatorClient, + pub env: GadgetConfiguration, +} 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 0040a4a0..afc38617 100644 --- a/blueprints/incredible-squaring-eigenlayer/src/jobs/compute_x_square.rs +++ b/blueprints/incredible-squaring-eigenlayer/src/jobs/compute_x_square.rs @@ -1,8 +1,9 @@ #![allow(dead_code)] -use crate::contexts::client::{AggregatorClient, SignedTaskResponse}; +use crate::contexts::client::SignedTaskResponse; +use crate::contexts::x_square::EigenSquareContext; use crate::{IncredibleSquaringTaskManager, INCREDIBLE_SQUARING_TASK_MANAGER_ABI_STRING}; use alloy_primitives::keccak256; -use alloy_primitives::{hex, Bytes, U256}; +use alloy_primitives::{Bytes, U256}; use alloy_sol_types::SolType; use ark_bn254::Fq; use ark_ff::{BigInteger, PrimeField}; @@ -10,6 +11,7 @@ use color_eyre::Result; use eigensdk::crypto_bls::BlsKeyPair; use eigensdk::crypto_bls::OperatorId; use gadget_sdk::event_listener::evm::contracts::EvmContractEventListener; +use gadget_sdk::keystore::BackendExt; use gadget_sdk::{error, info, job}; use std::{convert::Infallible, ops::Deref}; use IncredibleSquaringTaskManager::TaskResponse; @@ -26,30 +28,40 @@ use IncredibleSquaringTaskManager::TaskResponse; ), )] pub async fn xsquare_eigen( - ctx: AggregatorClient, + ctx: EigenSquareContext, number_to_be_squared: U256, task_created_block: u32, quorum_numbers: Bytes, quorum_threshold_percentage: u8, task_index: u32, ) -> std::result::Result { + let client = ctx.client.clone(); + let env = ctx.env.clone(); + // Calculate our response to job let task_response = TaskResponse { referenceTaskIndex: task_index, numberSquared: number_to_be_squared.saturating_pow(U256::from(2u32)), }; - let bls_key_pair = BlsKeyPair::new( - "1371012690269088913462269866874713266643928125698382731338806296762673180359922" - .to_string(), - ) - .unwrap(); + let bls_key_pair = match env.keystore() { + Ok(keystore) => { + let pair = keystore.bls_bn254_key(); + match pair { + Ok(pair) => pair, + Err(e) => { + error!("Failed to get BLS key pair: {:#?}", e); + return Ok(1); + } + } + } + Err(e) => { + error!("Failed to get keystore: {:#?}", e); + return Ok(1); + } + }; - 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 operator_id: OperatorId = operator_id_from_key(bls_key_pair.clone()); // Sign the Hashed Message and send it to the BLS Aggregator let msg_hash = keccak256(::abi_encode(&task_response)); @@ -63,7 +75,7 @@ pub async fn xsquare_eigen( "Sending signed task response to BLS Aggregator: {:#?}", signed_response ); - if let Err(e) = ctx.send_signed_task_response(signed_response).await { + if let Err(e) = client.send_signed_task_response(signed_response).await { error!("Failed to send signed task response: {:?}", e); return Ok(0); } @@ -71,6 +83,20 @@ pub async fn xsquare_eigen( Ok(1) } +/// Generate the Operator ID from the BLS Keypair +pub fn operator_id_from_key(key: BlsKeyPair) -> OperatorId { + let pub_key = key.public_key(); + 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(); + + keccak256([x_bytes, y_bytes].concat()) +} + /// Converts the event to inputs. /// /// Uses a tuple to represent the return type because diff --git a/blueprints/incredible-squaring-eigenlayer/src/main.rs b/blueprints/incredible-squaring-eigenlayer/src/main.rs index 2395c63e..3e07fa7d 100644 --- a/blueprints/incredible-squaring-eigenlayer/src/main.rs +++ b/blueprints/incredible-squaring-eigenlayer/src/main.rs @@ -6,6 +6,7 @@ use gadget_sdk::{ info, runners::{eigenlayer::EigenlayerConfig, BlueprintRunner}, }; +use incredible_squaring_blueprint_eigenlayer::contexts::x_square::EigenSquareContext; use incredible_squaring_blueprint_eigenlayer::{ constants::{AGGREGATOR_PRIVATE_KEY, TASK_MANAGER_ADDRESS}, contexts::{aggregator::AggregatorContext, client::AggregatorClient}, @@ -60,8 +61,12 @@ async fn main() { let server_address = format!("{}:{}", env.target_addr, 8081); let aggregator_client = AggregatorClient::new(&server_address)?; + let ctx = EigenSquareContext { + client: aggregator_client, + env: env.clone(), + }; let x_square_eigen = XsquareEigenEventHandler { - ctx: aggregator_client, + ctx, contract: contract.clone(), contract_instance: Default::default(), }; diff --git a/blueprints/incredible-squaring/README.md b/blueprints/incredible-squaring/README.md index ecac94d3..a9aa3ae4 100644 --- a/blueprints/incredible-squaring/README.md +++ b/blueprints/incredible-squaring/README.md @@ -28,7 +28,7 @@ bash ./scripts/run-standalone-local.sh --clean - Then, use the following command to run the gadget that uses the blueprint: ```bash -RUST_LOG=incredible_squaring_gadget,gadget_sdk=trace,error cargo run -p incredible-squaring-blueprint -- run --url=ws://localhost:9944 --base-path=./target/keystore --blueprint-id=0 --service-id=0 --bind-addr=0.0.0.0 --bind-port= +RUST_LOG=incredible_squaring_gadget,gadget_sdk=trace,error cargo run -p incredible-squaring-blueprint -- run --url=ws://localhost:9944 --base-path=./target/keystore --blueprint-id=0 --service-id=0 --target-addr=0.0.0.0 --target-port= ``` That's it! You should see the gadget running and listening for incoming requests on the Local Tangle Network.