From 8a47584a74783c6c967a77111c981c60bc7f0b7e Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Tue, 5 Nov 2024 15:27:59 +0100 Subject: [PATCH] feat(cli): dirk delegations integration test --- bolt-cli/src/commands/delegate.rs | 41 +++++++++- bolt-cli/src/commands/send.rs | 12 +-- bolt-cli/src/common/dirk.rs | 86 ++++++++++++-------- bolt-cli/test_data/dirk/.gitignore | 3 +- bolt-cli/test_data/dirk/storage/000000.vlog | Bin 20 -> 0 bytes bolt-cli/test_data/dirk/storage/KEYREGISTRY | 1 - bolt-cli/test_data/dirk/storage/LOCK | 1 - bolt-cli/test_data/dirk/storage/MANIFEST | Bin 16 -> 0 bytes 8 files changed, 99 insertions(+), 45 deletions(-) delete mode 100644 bolt-cli/test_data/dirk/storage/000000.vlog delete mode 100644 bolt-cli/test_data/dirk/storage/KEYREGISTRY delete mode 100644 bolt-cli/test_data/dirk/storage/LOCK delete mode 100644 bolt-cli/test_data/dirk/storage/MANIFEST diff --git a/bolt-cli/src/commands/delegate.rs b/bolt-cli/src/commands/delegate.rs index 4f1d9721d..24f1e9a15 100644 --- a/bolt-cli/src/commands/delegate.rs +++ b/bolt-cli/src/commands/delegate.rs @@ -363,10 +363,10 @@ pub fn verify_message_signature(message: &SignedMessage, chain: Chain) -> Result mod tests { use crate::{ cli::{Action, Chain}, - common::{keystore::KeystoreSecret, parse_bls_public_key}, + common::{dirk, keystore, parse_bls_public_key}, }; - use super::{generate_from_keystore, verify_message_signature}; + use super::{generate_from_dirk, generate_from_keystore, verify_message_signature}; #[test] fn test_delegation_keystore_signer_lighthouse() -> eyre::Result<()> { @@ -374,7 +374,7 @@ mod tests { let keys_path = env!("CARGO_MANIFEST_DIR").to_string() + "/test_data/lighthouse/validators"; let secrets_path = env!("CARGO_MANIFEST_DIR").to_string() + "/test_data/lighthouse/secrets"; - let keystore_secret = KeystoreSecret::from_directory(&secrets_path)?; + let keystore_secret = keystore::KeystoreSecret::from_directory(&secrets_path)?; let delegatee_pubkey = "0x83eeddfac5e60f8fe607ee8713efb8877c295ad9f8ca075f4d8f6f2ae241a30dd57f78f6f3863a9fe0d5b5db9d550b93"; let delegatee_pubkey = parse_bls_public_key(delegatee_pubkey)?; @@ -394,4 +394,39 @@ mod tests { Ok(()) } + + /// Test generating signed delegations using a remote Dirk signer. + /// + /// ```shell + /// cargo test --package bolt --bin bolt -- commands::delegate::tests::test_delegation_dirk + /// --exact --show-output --ignored --nocapture + /// ``` + #[tokio::test] + #[ignore] + async fn test_delegation_dirk() -> eyre::Result<()> { + let _ = tracing_subscriber::fmt::try_init(); + let (mut dirk, mut dirk_proc) = dirk::test_util::start_dirk_test_server().await?; + + let delegatee_pubkey = "0x83eeddfac5e60f8fe607ee8713efb8877c295ad9f8ca075f4d8f6f2ae241a30dd57f78f6f3863a9fe0d5b5db9d550b93"; + let delegatee_pubkey = parse_bls_public_key(delegatee_pubkey)?; + let chain = Chain::Mainnet; + + let signed_delegations = generate_from_dirk( + &mut dirk, + delegatee_pubkey.clone(), + "wallet1".to_string(), + Some(vec!["secret".to_string()]), + chain, + Action::Delegate, + ) + .await?; + + let signed_message = signed_delegations.first().expect("to get signed delegation"); + + verify_message_signature(signed_message, chain)?; + + dirk_proc.kill()?; + + Ok(()) + } } diff --git a/bolt-cli/src/commands/send.rs b/bolt-cli/src/commands/send.rs index c2b7367eb..205ee95d5 100644 --- a/bolt-cli/src/commands/send.rs +++ b/bolt-cli/src/commands/send.rs @@ -27,14 +27,14 @@ impl SendCommand { let wallet: PrivateKeySigner = self.private_key.parse().wrap_err("invalid private key")?; if self.devnet { - self.send_devnet_transaction(&wallet).await + self.send_devnet_transaction(wallet).await } else { - self.send_transaction(&wallet).await + self.send_transaction(wallet).await } } /// Send a transaction. - async fn send_transaction(self, wallet: &PrivateKeySigner) -> Result<()> { + async fn send_transaction(self, wallet: PrivateKeySigner) -> Result<()> { let transaction_signer = EthereumWallet::from(wallet.clone()); let provider = ProviderBuilder::new() .with_recommended_fillers() @@ -90,7 +90,7 @@ impl SendCommand { vec![tx_hash], target_slot, target_url.clone(), - wallet, + &wallet, ) .await?; @@ -102,7 +102,7 @@ impl SendCommand { } /// Send a transaction on the Kurtosis devnet. - async fn send_devnet_transaction(self, wallet: &PrivateKeySigner) -> Result<()> { + async fn send_devnet_transaction(self, wallet: PrivateKeySigner) -> Result<()> { let transaction_signer = EthereumWallet::from(wallet.clone()); let el_url = self.devnet_execution_url.clone().wrap_err("missing devnet execution URL")?; let cl_url = self.devnet_beacon_url.clone().wrap_err("missing devnet beacon URL")?; @@ -137,7 +137,7 @@ impl SendCommand { vec![tx_hash], slot + 2, sidecar_url.clone(), - wallet, + &wallet, ) .await?; diff --git a/bolt-cli/src/common/dirk.rs b/bolt-cli/src/common/dirk.rs index 75148bab8..31862d08c 100644 --- a/bolt-cli/src/common/dirk.rs +++ b/bolt-cli/src/common/dirk.rs @@ -152,27 +152,42 @@ fn compose_credentials(creds: TlsCredentials) -> Result { } #[cfg(test)] -mod tests { - use std::{process::Command, time::Duration}; - - use super::*; +pub mod test_util { + use eyre::{bail, Context}; + use rustls::crypto::CryptoProvider; + use std::{ + fs, + process::{Child, Command}, + time::Duration, + }; + + use super::Dirk; + use crate::cli::TlsCredentials; + + /// Initialize the default TLS provider for the tests if not already set. + pub fn try_init_tls_provider() { + // Init the default rustls provider + if CryptoProvider::get_default().is_none() { + let _ = rustls::crypto::ring::default_provider().install_default(); + } + } - /// Test connecting to a DIRK server and listing available accounts. + /// Start a DIRK test server for testing (run on localhost:9091). /// - /// ```shell - /// cargo test --package bolt -- utils::dirk::tests::test_dirk_connection_e2e - /// --exact --show-output --ignored - /// ``` - #[tokio::test] - #[ignore] - async fn test_dirk_connection_e2e() -> eyre::Result<()> { - // Init the default rustls provider - let _ = rustls::crypto::ring::default_provider().install_default(); + /// Returns the DIRK client and the corresponding server process handle. + pub async fn start_dirk_test_server() -> eyre::Result<(Dirk, Child)> { + try_init_tls_provider(); let test_data_dir = env!("CARGO_MANIFEST_DIR").to_string() + "/test_data/dirk"; - // Init the DIRK config file - init_dirk_config(test_data_dir.clone())?; + // read the template json file from test_data + let template_path = test_data_dir.clone() + "/dirk.template.json"; + let template = fs::read_to_string(template_path).wrap_err("Failed to read template")?; + + // change the occurrence of $PWD to the current working directory in the template + let new_file = test_data_dir.clone() + "/dirk.json"; + let new_content = template.replace("$PWD", &test_data_dir); + fs::write(new_file, new_content).wrap_err("Failed to write dirk config file")?; // Check if dirk is installed (in $PATH) if Command::new("dirk") @@ -182,12 +197,11 @@ mod tests { .status() .is_err() { - eprintln!("DIRK is not installed in $PATH"); - return Ok(()); + bail!("DIRK is not installed in $PATH"); } // Start the DIRK server in the background - let mut dirk_proc = Command::new("dirk").arg("--base-dir").arg(&test_data_dir).spawn()?; + let dirk_proc = Command::new("dirk").arg("--base-dir").arg(&test_data_dir).spawn()?; // Wait for some time for the server to start up tokio::time::sleep(Duration::from_secs(3)).await; @@ -200,7 +214,26 @@ mod tests { ca_cert_path: Some(test_data_dir.clone() + "/security/ca.crt"), }; - let mut dirk = Dirk::connect(url, cred).await?; + let dirk = Dirk::connect(url, cred).await?; + + Ok((dirk, dirk_proc)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + /// Test connecting to a DIRK server and listing available accounts. + /// + /// ```shell + /// cargo test --package bolt --bin bolt -- common::dirk::tests::test_dirk_connection_e2e + /// --exact --show-output --ignored + /// ``` + #[tokio::test] + #[ignore] + async fn test_dirk_connection_e2e() -> eyre::Result<()> { + let (mut dirk, mut dirk_proc) = test_util::start_dirk_test_server().await?; let accounts = dirk.list_accounts("wallet1".to_string()).await?; println!("Dirk Accounts: {:?}", accounts); @@ -210,17 +243,4 @@ mod tests { Ok(()) } - - fn init_dirk_config(test_data_dir: String) -> eyre::Result<()> { - // read the template json file from test_data - let template_path = test_data_dir.clone() + "/dirk.template.json"; - let template = fs::read_to_string(template_path).wrap_err("Failed to read template")?; - - // change the occurrence of $PWD to the current working directory in the template - let new_file = test_data_dir.clone() + "/dirk.json"; - let new_content = template.replace("$PWD", &test_data_dir); - fs::write(new_file, new_content).wrap_err("Failed to write dirk config file")?; - - Ok(()) - } } diff --git a/bolt-cli/test_data/dirk/.gitignore b/bolt-cli/test_data/dirk/.gitignore index 98368746f..ccef4acf9 100644 --- a/bolt-cli/test_data/dirk/.gitignore +++ b/bolt-cli/test_data/dirk/.gitignore @@ -1 +1,2 @@ -dirk.json \ No newline at end of file +dirk.json +storage/ diff --git a/bolt-cli/test_data/dirk/storage/000000.vlog b/bolt-cli/test_data/dirk/storage/000000.vlog deleted file mode 100644 index ff7a6f8f9165d15432753d5c128d3d047deb74b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20 XcmZQzfPkhiE3ZTxvilwHAD#*TFq;Ok diff --git a/bolt-cli/test_data/dirk/storage/KEYREGISTRY b/bolt-cli/test_data/dirk/storage/KEYREGISTRY deleted file mode 100644 index cd3e15ea5..000000000 --- a/bolt-cli/test_data/dirk/storage/KEYREGISTRY +++ /dev/null @@ -1 +0,0 @@ -àÝõöƒA÷¸c¾ÈÁW•Hello Badger \ No newline at end of file diff --git a/bolt-cli/test_data/dirk/storage/LOCK b/bolt-cli/test_data/dirk/storage/LOCK deleted file mode 100644 index 31ab16834..000000000 --- a/bolt-cli/test_data/dirk/storage/LOCK +++ /dev/null @@ -1 +0,0 @@ -33375 diff --git a/bolt-cli/test_data/dirk/storage/MANIFEST b/bolt-cli/test_data/dirk/storage/MANIFEST deleted file mode 100644 index 0b5596943f5fb52aa3198b6cc783be43165b577a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16 ScmZ=tNiSkxU|