From e045b41ba6770a0355eff52bea2a7b6def25af0f Mon Sep 17 00:00:00 2001 From: Donovan Tjemmes <37707055+Tjemmmic@users.noreply.github.com> Date: Fri, 1 Nov 2024 06:09:46 -0500 Subject: [PATCH] fix: update runner protocol to automatically register (#30) * fix: utilize temporary directory for keystore in test * fix: switch runner protocol for registration --- Cargo.lock | 18 ++++++------ Cargo.toml | 1 + src/lib.rs | 49 +++++++++++++------------------- src/main.rs | 20 ++++--------- src/utils/constants.rs | 11 +++++++ src/utils/eigenlayer.rs | 63 ----------------------------------------- src/utils/mod.rs | 2 +- src/utils/tangle.rs | 48 +++++++++++++++++-------------- 8 files changed, 74 insertions(+), 138 deletions(-) create mode 100644 src/utils/constants.rs delete mode 100644 src/utils/eigenlayer.rs diff --git a/Cargo.lock b/Cargo.lock index f6355b3..894ed86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1754,7 +1754,7 @@ dependencies = [ [[package]] name = "blueprint-manager" version = "0.1.1" -source = "git+https://github.com/webb-tools/gadget?branch=donovan/avs-updates#c0b732016fb5791e1e80d0dadc25a09b75f4a8d1" +source = "git+https://github.com/webb-tools/gadget?branch=donovan/avs-updates#25798c2b43744c47b90ee151b3c661551f53be7d" dependencies = [ "async-trait", "auto_impl", @@ -1782,7 +1782,7 @@ dependencies = [ [[package]] name = "blueprint-test-utils" version = "0.1.1" -source = "git+https://github.com/webb-tools/gadget?branch=donovan/avs-updates#c0b732016fb5791e1e80d0dadc25a09b75f4a8d1" +source = "git+https://github.com/webb-tools/gadget?branch=donovan/avs-updates#25798c2b43744c47b90ee151b3c661551f53be7d" dependencies = [ "alloy-contract", "alloy-primitives 0.7.7", @@ -1805,6 +1805,7 @@ dependencies = [ "sp-core", "sp-io", "subxt", + "tempfile", "testcontainers", "thiserror", "tokio", @@ -2033,7 +2034,7 @@ dependencies = [ [[package]] name = "cargo-tangle" version = "0.2.1" -source = "git+https://github.com/webb-tools/gadget?branch=donovan/avs-updates#c0b732016fb5791e1e80d0dadc25a09b75f4a8d1" +source = "git+https://github.com/webb-tools/gadget?branch=donovan/avs-updates#25798c2b43744c47b90ee151b3c661551f53be7d" dependencies = [ "alloy-json-abi", "alloy-network", @@ -4479,7 +4480,7 @@ dependencies = [ [[package]] name = "gadget-blueprint-proc-macro" version = "0.2.3" -source = "git+https://github.com/webb-tools/gadget?branch=donovan/avs-updates#c0b732016fb5791e1e80d0dadc25a09b75f4a8d1" +source = "git+https://github.com/webb-tools/gadget?branch=donovan/avs-updates#25798c2b43744c47b90ee151b3c661551f53be7d" dependencies = [ "gadget-blueprint-proc-macro-core", "indexmap 2.6.0", @@ -4493,7 +4494,7 @@ dependencies = [ [[package]] name = "gadget-blueprint-proc-macro-core" version = "0.1.5" -source = "git+https://github.com/webb-tools/gadget?branch=donovan/avs-updates#c0b732016fb5791e1e80d0dadc25a09b75f4a8d1" +source = "git+https://github.com/webb-tools/gadget?branch=donovan/avs-updates#25798c2b43744c47b90ee151b3c661551f53be7d" dependencies = [ "cid", "ethereum-types", @@ -4503,7 +4504,7 @@ dependencies = [ [[package]] name = "gadget-context-derive" version = "0.1.3" -source = "git+https://github.com/webb-tools/gadget?branch=donovan/avs-updates#c0b732016fb5791e1e80d0dadc25a09b75f4a8d1" +source = "git+https://github.com/webb-tools/gadget?branch=donovan/avs-updates#25798c2b43744c47b90ee151b3c661551f53be7d" dependencies = [ "proc-macro2", "quote", @@ -4513,7 +4514,7 @@ dependencies = [ [[package]] name = "gadget-io" version = "0.0.4" -source = "git+https://github.com/webb-tools/gadget?branch=donovan/avs-updates#c0b732016fb5791e1e80d0dadc25a09b75f4a8d1" +source = "git+https://github.com/webb-tools/gadget?branch=donovan/avs-updates#25798c2b43744c47b90ee151b3c661551f53be7d" dependencies = [ "cfg-if", "clap 4.5.20", @@ -4535,7 +4536,7 @@ dependencies = [ [[package]] name = "gadget-sdk" version = "0.2.3" -source = "git+https://github.com/webb-tools/gadget?branch=donovan/avs-updates#c0b732016fb5791e1e80d0dadc25a09b75f4a8d1" +source = "git+https://github.com/webb-tools/gadget?branch=donovan/avs-updates#25798c2b43744c47b90ee151b3c661551f53be7d" dependencies = [ "alloy-contract", "alloy-network", @@ -11395,6 +11396,7 @@ dependencies = [ "reqwest 0.12.9", "serde_json", "structopt", + "tempfile", "tokio", "tokio-retry", "tracing", diff --git a/Cargo.toml b/Cargo.toml index 6238e18..9a40a9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ hex = "0.4.3" reqwest = "0.12.8" serde_json = "1.0.132" num-bigint = "0.4.6" +tempfile = "3.10.1" [dependencies.gadget-sdk] # version = "0.1.2" diff --git a/src/lib.rs b/src/lib.rs index 656cbd6..6c32525 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,3 @@ -pub use crate::utils::eigenlayer::*; use crate::utils::tangle::{bond_balance, update_session_key}; pub use crate::utils::tangle::{run_tangle_validator, BalanceTransferContext}; use color_eyre::eyre::Result; @@ -61,7 +60,11 @@ pub async fn tangle_avs_registration( let env = context.env.clone(); // Run Tangle Validator - run_tangle_validator().await.unwrap(); + run_tangle_validator(context.env.keystore_uri.as_str()) + .await + .map_err(|e| gadget_sdk::Error::Job { + reason: e.to_string(), + })?; bond_balance(&env.clone()) .await @@ -84,13 +87,13 @@ pub async fn tangle_avs_registration( #[cfg(test)] mod tests { use super::*; + pub use crate::utils::constants::*; use crate::utils::sol_imports::*; use alloy_primitives::U256; use alloy_provider::network::TransactionBuilder; use alloy_provider::Provider; use blueprint_test_utils::test_ext::NAME_IDS; use blueprint_test_utils::{inject_test_keys, KeyGenType}; - use gadget_sdk::config::protocol::TangleInstanceSettings; use gadget_sdk::config::{ContextConfig, GadgetCLICoreSettings, Protocol}; use gadget_sdk::ext::sp_core; use gadget_sdk::ext::sp_core::Pair; @@ -98,12 +101,12 @@ mod tests { use gadget_sdk::keystore::backend::fs::FilesystemKeystore; use gadget_sdk::keystore::backend::GenericKeyStore; use gadget_sdk::keystore::{Backend, BackendExt}; - use gadget_sdk::runners::tangle::TangleConfig; + use gadget_sdk::runners::eigenlayer::EigenlayerConfig; use gadget_sdk::runners::BlueprintRunner; use gadget_sdk::utils::evm::get_provider_http; use gadget_sdk::{alloy_rpc_types, error, info}; use std::net::IpAddr; - use std::path::PathBuf; + use std::path::Path; use std::str::FromStr; use std::time::Duration; use url::Url; @@ -191,7 +194,8 @@ mod tests { // Setup Keystores for test set_tangle_env_vars(); - let keystore_paths = generate_tangle_avs_keys().await; + let tmp_dir = tempfile::TempDir::new().unwrap(); // Create a temporary directory for the keystores + let keystore_paths = generate_tangle_avs_keys(tmp_dir.path()).await; // Get the operator's keys let operator_keystore_uri = keystore_paths[5].clone(); @@ -232,7 +236,6 @@ mod tests { ); // Tangle node url/port - let http_tangle_url = Url::parse("http://127.0.0.1:9948").unwrap(); let ws_tangle_url = Url::parse("ws://127.0.0.1:9948").unwrap(); let bind_port = ws_tangle_url.clone().port().unwrap(); @@ -243,7 +246,7 @@ mod tests { bind_port, test_mode: false, log_id: None, - http_rpc_url: http_tangle_url, + http_rpc_url: Url::parse(&http_endpoint).unwrap(), bootnodes: None, keystore_uri: operator_keystore_uri, chain: gadget_io::SupportedChains::LocalTestnet, @@ -253,11 +256,11 @@ mod tests { blueprint_id: Some(0), service_id: Some(0), skip_registration: Some(true), - protocol: Protocol::Tangle, + protocol: Protocol::Eigenlayer, registry_coordinator: Some(REGISTRY_COORDINATOR_ADDR), operator_state_retriever: Some(OPERATOR_STATE_RETRIEVER_ADDR), delegation_manager: Some(DELEGATION_MANAGER_ADDR), - ws_rpc_url: ws_tangle_url, + ws_rpc_url: Url::parse(&ws_endpoint).unwrap(), strategy_manager: Some(STRATEGY_MANAGER_ADDR), avs_directory: Some(AVS_DIRECTORY_ADDR), operator_registry: None, @@ -275,10 +278,6 @@ mod tests { let signer = env.first_sr25519_signer().unwrap(); let signer_id = signer.clone().account_id(); - // Register Operator on EigenLayer - info!("Registering to EigenLayer"); - register_to_eigenlayer(&env.clone()).await.unwrap(); - // Spawn task to transfer balance into Operator's account on Tangle let transfer_task = async move { tokio::time::sleep(Duration::from_secs(4)).await; @@ -305,13 +304,10 @@ mod tests { // Create Instance of the Event Handler let context = BalanceTransferContext { client: client.clone(), - address: Default::default(), env: env.clone(), }; - let tangle_settings = env.protocol_specific.tangle().unwrap(); - let TangleInstanceSettings { service_id, .. } = tangle_settings; let tangle_avs = RegisterToTangleEventHandler { - service_id: *service_id, + service_id: 0, context: context.clone(), client, signer, @@ -319,10 +315,8 @@ mod tests { // Start the Runner info!("~~~ Executing the Tangle AVS ~~~"); - let tangle_config = TangleConfig { - price_targets: Default::default(), - }; - BlueprintRunner::new(tangle_config, env.clone()) + let eigen_config = EigenlayerConfig {}; + BlueprintRunner::new(eigen_config, env.clone()) .job(tangle_avs) .run() .await @@ -387,17 +381,15 @@ mod tests { /// /// # Warning /// This function is specifically for testing. It will panic upon any errors and utilizes keys that are publicly visible. - pub(crate) async fn generate_tangle_avs_keys() -> Vec { + pub(crate) async fn generate_tangle_avs_keys(keystore_base_path: &Path) -> Vec { // Set up the Keys required for Tangle AVS let mut keystore_paths = Vec::new(); // First we inject the premade Tangle Account keys for (item, name) in NAME_IDS.iter().enumerate() { let tmp_store = Uuid::new_v4().to_string(); - let keystore_uri = PathBuf::from(format!( - "./target/keystores/{}/{tmp_store}/", - name.to_lowercase() - )); + let keystore_uri = + keystore_base_path.join(format!("keystores/{}/{tmp_store}/", name.to_lowercase())); assert!( !keystore_uri.exists(), "Keystore URI cannot exist: {}", @@ -414,7 +406,7 @@ mod tests { // Now we create a new Tangle Account for the Test let tmp_store = Uuid::new_v4().to_string(); - let keystore_uri = PathBuf::from(format!("./target/keystores/{}/{tmp_store}/", "testnode")); + let keystore_uri = keystore_base_path.join(format!("keystores/testnode/{tmp_store}/")); assert!( !keystore_uri.exists(), "Keystore URI cannot exist: {}", @@ -433,7 +425,6 @@ mod tests { ); let acco_suri = std::env::var("ACCO_SURI").expect("ACCO_SURI not set"); - // let suri = format!("//{acco_suri}"); let (_acco, acco_seed) = sp_core::sr25519::Pair::from_phrase(&acco_suri, None) .expect("Should be valid SR keypair"); info!("Found SR_SEED: {:?}", acco_seed); diff --git a/src/main.rs b/src/main.rs index a1fa0aa..8da0adb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,11 @@ use color_eyre::eyre::eyre; use color_eyre::Result; -use gadget_sdk::config::protocol::TangleInstanceSettings; use gadget_sdk::info; -use gadget_sdk::runners::tangle::TangleConfig; +use gadget_sdk::runners::eigenlayer::EigenlayerConfig; use gadget_sdk::runners::BlueprintRunner; use gadget_sdk::subxt_core::tx::signer::Signer; use tangle_avs as blueprint; -use tangle_avs::{register_to_eigenlayer, RegisterToTangleEventHandler}; +use tangle_avs::RegisterToTangleEventHandler; #[gadget_sdk::main(env)] async fn main() { @@ -17,28 +16,19 @@ async fn main() { let context = blueprint::BalanceTransferContext { client: client.clone(), - address: Default::default(), env: env.clone(), }; - info!("Registering to EigenLayer"); - register_to_eigenlayer(&env.clone()).await?; - - let tangle_settings = env.protocol_specific.tangle().unwrap(); - let TangleInstanceSettings { service_id, .. } = tangle_settings; - let tangle_avs = RegisterToTangleEventHandler { - service_id: *service_id, + service_id: 0, context: context.clone(), client, signer, }; info!("~~~ Executing the Tangle AVS ~~~"); - let tangle_config = TangleConfig { - price_targets: Default::default(), - }; - BlueprintRunner::new(tangle_config, env.clone()) + let eigen_config = EigenlayerConfig {}; + BlueprintRunner::new(eigen_config, env.clone()) .job(tangle_avs) .run() .await diff --git a/src/utils/constants.rs b/src/utils/constants.rs new file mode 100644 index 0000000..a42b8f3 --- /dev/null +++ b/src/utils/constants.rs @@ -0,0 +1,11 @@ +use alloy_primitives::{address, Address}; + +pub const AVS_DIRECTORY_ADDR: Address = address!("0000000000000000000000000000000000000000"); +pub const DELEGATION_MANAGER_ADDR: Address = address!("dc64a140aa3e981100a9beca4e685f962f0cf6c9"); +pub const ERC20_MOCK_ADDR: Address = address!("7969c5ed335650692bc04293b07f5bf2e7a673c0"); +pub const MAILBOX_ADDR: Address = address!("0000000000000000000000000000000000000000"); +pub const OPERATOR_STATE_RETRIEVER_ADDR: Address = + address!("1613beb3b2c4f22ee086b2b38c1476a3ce7f78e8"); +pub const REGISTRY_COORDINATOR_ADDR: Address = address!("c3e53f4d16ae77db1c982e75a937b9f60fe63690"); +pub const SERVICE_MANAGER_ADDR: Address = address!("67d269191c92caf3cd7723f116c85e6e9bf55933"); +pub const STRATEGY_MANAGER_ADDR: Address = address!("5fc8d32690cc91d4c39d9d3abcbd16989f875707"); diff --git a/src/utils/eigenlayer.rs b/src/utils/eigenlayer.rs deleted file mode 100644 index 24c41fc..0000000 --- a/src/utils/eigenlayer.rs +++ /dev/null @@ -1,63 +0,0 @@ -use alloy_primitives::{address, Address, Bytes}; -use color_eyre::eyre::{eyre, Result}; -use gadget_sdk::config::GadgetConfiguration; -use gadget_sdk::keystore::BackendExt; -use gadget_sdk::utils::evm::{register_as_operator, register_with_avs_registry_coordinator}; - -pub const AVS_DIRECTORY_ADDR: Address = address!("0000000000000000000000000000000000000000"); -pub const DELEGATION_MANAGER_ADDR: Address = address!("dc64a140aa3e981100a9beca4e685f962f0cf6c9"); -pub const ERC20_MOCK_ADDR: Address = address!("7969c5ed335650692bc04293b07f5bf2e7a673c0"); -pub const MAILBOX_ADDR: Address = address!("0000000000000000000000000000000000000000"); -pub const OPERATOR_STATE_RETRIEVER_ADDR: Address = - address!("1613beb3b2c4f22ee086b2b38c1476a3ce7f78e8"); -pub const REGISTRY_COORDINATOR_ADDR: Address = address!("c3e53f4d16ae77db1c982e75a937b9f60fe63690"); -pub const SERVICE_MANAGER_ADDR: Address = address!("67d269191c92caf3cd7723f116c85e6e9bf55933"); -pub const STRATEGY_MANAGER_ADDR: Address = address!("5fc8d32690cc91d4c39d9d3abcbd16989f875707"); - -/// Registers operator to EigenLayer and the AVS. -/// -/// # Environment Variables -/// - `EIGENLAYER_HTTP_ENDPOINT`: HTTP endpoint for EigenLayer. -/// - `EIGENLAYER_WS_ENDPOINT`: WebSocket endpoint for EigenLayer. -/// -/// # Errors -/// May return errors if: -/// - Environment variables are not set. -/// - Contract interactions fail. -/// - Registration processes encounter issues. -pub async fn register_to_eigenlayer( - env: &GadgetConfiguration, -) -> Result<()> { - // Read keys from keystore - let keystore = env.keystore()?; - let bls_key_pair = keystore.bls_bn254_key().map_err(|e| eyre!(e))?; - let ecdsa_pair = keystore.ecdsa_key().map_err(|e| eyre!(e))?; - - // Collect all necessary information from Environment Variables - let http_endpoint = std::env::var("EIGENLAYER_HTTP_ENDPOINT") - .map_err(|_| eyre!("EIGENLAYER_HTTP_ENDPOINT must be set"))?; - let _ws_endpoint = std::env::var("EIGENLAYER_WS_ENDPOINT") - .map_err(|_| eyre!("EIGENLAYER_WS_ENDPOINT must be set"))?; - - let _register_hash = register_as_operator( - DELEGATION_MANAGER_ADDR, - AVS_DIRECTORY_ADDR, - STRATEGY_MANAGER_ADDR, - &http_endpoint.clone(), - ecdsa_pair.clone(), - ) - .await - .map_err(|e| eyre!(e))?; - - let _register_hash = register_with_avs_registry_coordinator( - &http_endpoint.clone(), - ecdsa_pair, - bls_key_pair, - Bytes::from(vec![0]), - REGISTRY_COORDINATOR_ADDR, - OPERATOR_STATE_RETRIEVER_ADDR, - ) - .await?; - - Ok(()) -} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index c6761a8..f0e7258 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,3 +1,3 @@ -pub mod eigenlayer; +pub mod constants; pub mod sol_imports; pub mod tangle; diff --git a/src/utils/tangle.rs b/src/utils/tangle.rs index 5bb6dd3..a17729a 100644 --- a/src/utils/tangle.rs +++ b/src/utils/tangle.rs @@ -1,4 +1,3 @@ -use alloy_primitives::Address; use color_eyre::eyre::{eyre, Result}; use gadget_sdk::clients::tangle::runtime::TangleClient; use gadget_sdk::config::GadgetConfiguration; @@ -20,7 +19,6 @@ use url::Url; #[derive(Clone)] pub struct BalanceTransferContext { pub client: TangleClient, - pub address: Address, pub env: GadgetConfiguration, } @@ -50,7 +48,7 @@ pub async fn bond_balance(env: &GadgetConfiguration) -> ); let result = tx::tangle::send(&client, &sr25519_pair, &bond_stash_tx) .await - .unwrap(); + .map_err(|e| eyre!(e))?; info!("Stash Account Bonding Result: {:?}", result); Ok(()) @@ -61,14 +59,15 @@ pub async fn update_session_key(env: &GadgetConfiguration::new( - RpcClient::from_url(env.ws_rpc_endpoint.clone()) + RpcClient::from_url(ws_endpoint) .await .map_err(|e| eyre!(e))?, ) @@ -146,7 +145,7 @@ pub async fn update_session_key(env: &GadgetConfiguration Result { +pub async fn generate_keys(base_path: &str) -> Result { let mut manager = GadgetProcessManager::new(); let acco_seed = std::env::var("ACCO_SURI").map_err(|e| eyre!(e))?; @@ -158,11 +157,11 @@ pub async fn generate_keys() -> Result { // Key Generation Commands // TODO: Update base-path and chain to be variables let commands = [ - &format!("key insert --base-path test --chain local --scheme Sr25519 --suri \"//{acco_seed}\" --key-type acco"), - &format!("key insert --base-path test --chain local --scheme Sr25519 --suri \"//{babe_seed}\" --key-type babe"), - &format!("key insert --base-path test --chain local --scheme Sr25519 --suri \"//{imon_seed}\" --key-type imon"), - &format!("key insert --base-path test --chain local --scheme Ecdsa --suri \"//{role_seed}\" --key-type role"), - &format!("key insert --base-path test --chain local --scheme Ed25519 --suri \"//{gran_seed}\" --key-type gran"), + &format!("key insert --base-path {base_path} --chain local --scheme Sr25519 --suri \"//{acco_seed}\" --key-type acco"), + &format!("key insert --base-path {base_path} --chain local --scheme Sr25519 --suri \"//{babe_seed}\" --key-type babe"), + &format!("key insert --base-path {base_path} --chain local --scheme Sr25519 --suri \"//{imon_seed}\" --key-type imon"), + &format!("key insert --base-path {base_path} --chain local --scheme Ecdsa --suri \"//{role_seed}\" --key-type role"), + &format!("key insert --base-path {base_path} --chain local --scheme Ed25519 --suri \"//{gran_seed}\" --key-type gran"), ]; // Execute each command for (index, cmd) in commands.iter().enumerate() { @@ -181,8 +180,10 @@ pub async fn generate_keys() -> Result { // Execute the node-key generation command and capture its output trace!("Generating Node Key..."); + let node_path = format!("{base_path}/node-key"); + info!("Node key path: {}", node_path); let output = Command::new("./tangle-default-linux-amd64") - .args(["key", "generate-node-key", "--file", "test/node-key"]) + .args(["key", "generate-node-key", "--file", &node_path]) .output() .await .map_err(|e| eyre!("Command failed: {}", e))?; @@ -211,9 +212,13 @@ pub async fn generate_keys() -> Result { /// - The binary download fails /// - Setting executable permissions fails /// - The binary execution fails -pub async fn run_tangle_validator() -> Result<()> { +pub async fn run_tangle_validator(keystore_base_path: &str) -> Result<()> { + let keystore_base_path = keystore_base_path.trim_start_matches("file:"); + let mut manager = GadgetProcessManager::new(); + info!("Keystore Base Path: {}", keystore_base_path); + // Check if the binary exists if !std::path::Path::new("tangle-default-linux-amd64").exists() { let install = manager @@ -243,14 +248,13 @@ pub async fn run_tangle_validator() -> Result<()> { .map_err(|e| eyre!(e.to_string()))?; } - let _node_key = generate_keys() - .await - .map_err(|e| gadget_sdk::Error::Job { - reason: e.to_string(), - }) - .unwrap(); + let _node_key = + generate_keys(keystore_base_path) + .await + .map_err(|e| gadget_sdk::Error::Job { + reason: e.to_string(), + })?; - let base_path = "test"; let chain = "local"; let name = "TESTNODE"; let validator = "--validator"; @@ -259,7 +263,7 @@ pub async fn run_tangle_validator() -> Result<()> { let start_node_command = format!( "./tangle-default-linux-amd64 \ - --base-path {base_path} \ + --base-path {keystore_base_path} \ --chain {chain} \ --name {name} \ {validator} \