From 85d0a27e2c021469a32c82763ebcdabec68a4a2e Mon Sep 17 00:00:00 2001 From: Bertrand Darbon Date: Tue, 25 Feb 2025 12:19:43 +0100 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=94=92=EF=B8=8F=20Use=20keyring=20to?= =?UTF-8?q?=20store=20random=20private=20key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The private key is randomly generated & stored given the validator name We can set the private key using an hex string in an env var (meant for kubernetes setup using kube secrets) In testing env, the private keys are deterministically generated from the validator name, to keep same behavior as before. --- .github/workflows/ci.yml | 2 ++ Cargo.lock | 50 +++++++++++++++++++++++++++ Cargo.toml | 2 ++ src/bin/hyle.rs | 2 ++ src/utils/crypto.rs | 75 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 131 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e0b89647a..581ed7f9d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,6 +50,7 @@ jobs: wget https://github.com/risc0/risc0/releases/download/v1.2.0/cargo-risczero-x86_64-unknown-linux-gnu.tgz tar xzvf cargo-risczero-x86_64-unknown-linux-gnu.tgz echo "$PWD" >> $GITHUB_PATH + - uses: t1m0thyj/unlock-keyring@v1 - run: cargo build --verbose - run: cargo nextest run --profile ci --workspace - name: Upload test results to Codecov @@ -80,6 +81,7 @@ jobs: wget https://github.com/risc0/risc0/releases/download/v1.2.0/cargo-risczero-x86_64-unknown-linux-gnu.tgz tar xzvf cargo-risczero-x86_64-unknown-linux-gnu.tgz echo "$PWD" >> $GITHUB_PATH + - uses: t1m0thyj/unlock-keyring@v1 - name: Generate code coverage run: cargo llvm-cov --workspace --lib --lcov --output-path lcov.info -- --test-threads=1 - name: Upload coverage to Codecov diff --git a/Cargo.lock b/Cargo.lock index e5a77d2fd..f5f39fb22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1518,6 +1518,30 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" +[[package]] +name = "dbus" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" +dependencies = [ + "libc", + "libdbus-sys", + "winapi", +] + +[[package]] +name = "dbus-secret-service" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42a16374481d92aed73ae45b1f120207d8e71d24fb89f357fadbd8f946fd84b" +dependencies = [ + "dbus", + "futures-util", + "num", + "once_cell", + "rand 0.8.5", +] + [[package]] name = "der" version = "0.7.9" @@ -2563,6 +2587,7 @@ dependencies = [ "hyle-verifiers", "hyllar", "indexmap 2.7.1", + "keyring", "opentelemetry", "opentelemetry-prometheus", "opentelemetry_sdk", @@ -2596,6 +2621,7 @@ dependencies = [ "utoipa-axum", "utoipa-swagger-ui", "uuid-tld", + "whoami", ] [[package]] @@ -3139,6 +3165,20 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "keyring" +version = "3.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f8fe839464d4e4b37d756d7e910063696af79a7e877282cb1825e4ec5f10833" +dependencies = [ + "byteorder", + "dbus-secret-service", + "log", + "security-framework 2.11.1", + "security-framework 3.2.0", + "windows-sys 0.59.0", +] + [[package]] name = "lazy-regex" version = "3.4.1" @@ -3177,6 +3217,15 @@ version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +[[package]] +name = "libdbus-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" +dependencies = [ + "pkg-config", +] + [[package]] name = "libloading" version = "0.8.6" @@ -7682,6 +7731,7 @@ checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" dependencies = [ "redox_syscall 0.5.8", "wasite", + "web-sys", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 0b54ec1ad..9751916f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -133,6 +133,8 @@ utoipa = { version = "5.3.1", features = ["axum_extras"] } utoipa-swagger-ui = { version = "9.0.0", features = ["axum"] } utoipa-axum = { version = "0.2.0" } testcontainers-modules = { version = "0.11.6", features = ["postgres"] } +keyring = { version = "3", features = ["apple-native", "windows-native", "sync-secret-service"] } +whoami = "1.5.2" [dev-dependencies] amm = { path = "./crates/contracts/amm", features = ["client"] } diff --git a/src/bin/hyle.rs b/src/bin/hyle.rs index 37689d9ff..da77b3f22 100644 --- a/src/bin/hyle.rs +++ b/src/bin/hyle.rs @@ -88,6 +88,8 @@ async fn main() -> Result<()> { ), )?; + info!("Loaded key {:?} for validator", pubkey); + let pg; if args.pg { if std::fs::metadata(&config.data_directory).is_ok() { diff --git a/src/utils/crypto.rs b/src/utils/crypto.rs index cf0f234a4..72e67e691 100644 --- a/src/utils/crypto.rs +++ b/src/utils/crypto.rs @@ -1,3 +1,30 @@ +//! # BlstCrypto +//! +//! The `BlstCrypto` struct is used to manage cryptographic keys and operations. +//! +//! ## Initialization +//! +//! The function `new` is used to initialize a `BlstCrypto` instance. The behavior of this function depends on the environment: +//! +//! ```rust +//! use crate::utils::crypto::BlstCrypto; +//! +//! let validator_name = String::from("validator_name"); +//! let crypto = BlstCrypto::new(validator_name).expect("Failed to initialize BlstCrypto"); +//! ``` +//! +//! ### Non-Test Environment +//! +//! This module load the private key seed from the environment variable `HYLE_VALIDATOR_SECRET`. +//! The content of the variable must be a hexadecimal string. +//! If the variable is not set, it tries to load the key from the keyring. +//! +//! Note: you can use tools like seahorse (https://wiki.gnome.org/Apps/Seahorse) to manage your keyring +//! +//! ### Test Environment +//! +//! In a test environment the modules generates a secret key based on the validator name, which is less secure but suitable for testing purposes. +//! #![allow(dead_code, unused_variables)] use std::sync::Arc; @@ -30,6 +57,53 @@ const DST: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_"; pub const SIG_SIZE: usize = 48; impl BlstCrypto { + #[cfg(not(test))] + pub fn new(validator_name: String) -> Result { + let sk = Self::load_from_env().or_else(|err| { + println!("Could not load secret from env: {}", err); + Self::load_from_keyring(&validator_name) + })?; + + let validator_pubkey = as_validator_pubkey(sk.sk_to_pk()); + + Ok(BlstCrypto { + sk, + validator_pubkey, + }) + } + + /// Load the secret key from the environment variable `HYLE_VALIDATOR_SECRET`. + #[cfg(not(test))] + fn load_from_env() -> Result { + let secret = std::env::var("HYLE_VALIDATOR_SECRET") + .map_err(|_| anyhow!("HYLE_VALIDATOR_SECRET not set"))?; + SecretKey::key_gen(&hex::decode(secret)?, &[]) + .map_err(|e| anyhow!("Could not generate key from keyring secret: {:?}", e)) + } + + /// Load the secret key from the keyring. If the key does not exist, a new random one is generated. + #[cfg(not(test))] + fn load_from_keyring(validator_name: &str) -> Result { + let user = whoami::username(); + let entry = keyring::Entry::new_with_target("hyle", validator_name, &user)?; + + let sk = match entry.get_password() { + Ok(secret) => SecretKey::key_gen(&hex::decode(secret)?, &[]) + .map_err(|e| anyhow!("Could not generate key from keyring secret: {:?}", e))?, + Err(keyring::Error::NoEntry) => { + let mut ikm = [0u8; 32]; + rand::rng().fill(&mut ikm); + entry.set_password(&hex::encode(ikm))?; + SecretKey::key_gen(&ikm, &[]) + .map_err(|e| anyhow!("Could not generate new key: {:?}", e))? + } + Err(e) => bail!("Could not get secret: {:?}", e), + }; + + Ok(sk) + } + + #[cfg(test)] pub fn new(validator_name: String) -> Result { // TODO load secret key from keyring or other // here basically secret_key <=> validator_id which is very badly secure ! @@ -49,6 +123,7 @@ impl BlstCrypto { }) } + #[cfg(test)] pub fn new_random() -> Result { let mut rng = rand::rng(); let id: String = (0..32) From e9baf42cb172fa222872fef345cf0ce59186a303 Mon Sep 17 00:00:00 2001 From: Bertrand Darbon Date: Tue, 25 Feb 2025 12:29:28 +0100 Subject: [PATCH 2/4] install deps ? --- .github/workflows/ci.yml | 9 ++++++++- .github/workflows/clippy.yml | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 581ed7f9d..1e28aca1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,6 +24,9 @@ jobs: - uses: actions/checkout@v4 - run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }} + // For keyring dependencies + - run: sudo apt install libdbus-1-dev pkg-config + - name: Cache Docker layers id: image-cache uses: actions/cache@v4 @@ -76,6 +79,8 @@ jobs: - uses: Swatinem/rust-cache@v2 with: save-if: ${{ github.ref == 'refs/heads/main' }} + // For keyring dependencies + - run: sudo apt install libdbus-1-dev pkg-config - name: Install r0vm run: | wget https://github.com/risc0/risc0/releases/download/v1.2.0/cargo-risczero-x86_64-unknown-linux-gnu.tgz @@ -105,6 +110,8 @@ jobs: - uses: Swatinem/rust-cache@v2 with: save-if: ${{ github.ref == 'refs/heads/main' }} + // For keyring dependencies + - run: sudo apt install libdbus-1-dev pkg-config - name: Build model run: cargo build -p hyle-model --no-default-features - name: Build @@ -118,4 +125,4 @@ jobs: steps: - uses: actions/checkout@v4 - name: Machete - uses: bnjbvr/cargo-machete@main + uses: bnjbvr/cargo-machete@v0.7.1 diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 3e9b69db5..9a2e7226c 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -16,6 +16,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + // For keyring dependencies + - run: sudo apt install libdbus-1-dev pkg-config - uses: actions-rs/toolchain@v1 with: toolchain: stable From f2c7b658d112fbf0080ae9c3977aaed0457f26db Mon Sep 17 00:00:00 2001 From: Bertrand Darbon Date: Tue, 25 Feb 2025 12:39:48 +0100 Subject: [PATCH 3/4] fix comments in workflows --- .github/workflows/ci.yml | 6 +++--- .github/workflows/clippy.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1e28aca1e..a5de7c751 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: - uses: actions/checkout@v4 - run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }} - // For keyring dependencies + # For keyring dependencies - run: sudo apt install libdbus-1-dev pkg-config - name: Cache Docker layers @@ -79,7 +79,7 @@ jobs: - uses: Swatinem/rust-cache@v2 with: save-if: ${{ github.ref == 'refs/heads/main' }} - // For keyring dependencies + # For keyring dependencies - run: sudo apt install libdbus-1-dev pkg-config - name: Install r0vm run: | @@ -110,7 +110,7 @@ jobs: - uses: Swatinem/rust-cache@v2 with: save-if: ${{ github.ref == 'refs/heads/main' }} - // For keyring dependencies + # For keyring dependencies - run: sudo apt install libdbus-1-dev pkg-config - name: Build model run: cargo build -p hyle-model --no-default-features diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 9a2e7226c..ef4c0200e 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - // For keyring dependencies + # For keyring dependencies - run: sudo apt install libdbus-1-dev pkg-config - uses: actions-rs/toolchain@v1 with: From 36f2e1d3a9f582e1a43709e508c2fbdfefac320c Mon Sep 17 00:00:00 2001 From: Bertrand Darbon Date: Wed, 26 Feb 2025 11:07:59 +0100 Subject: [PATCH 4/4] make e2e tests don't use keyring --- .github/workflows/ci.yml | 2 -- src/bin/hyle.rs | 2 +- src/consensus.rs | 2 +- src/genesis.rs | 14 +++++++------- src/mempool.rs | 26 +++++++++++++------------- src/mempool/storage.rs | 34 +++++++++++++++++----------------- src/single_node_consensus.rs | 2 +- src/tests/autobahn_testing.rs | 4 ++-- src/utils/crypto.rs | 24 ++++++++++++++---------- src/utils/integration_test.rs | 2 +- tests/fixtures/test_helpers.rs | 9 ++++++++- 11 files changed, 65 insertions(+), 56 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c810194d..0367691db 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,7 +53,6 @@ jobs: wget https://github.com/risc0/risc0/releases/download/v1.3.0/cargo-risczero-x86_64-unknown-linux-gnu.tgz tar xzvf cargo-risczero-x86_64-unknown-linux-gnu.tgz echo "$PWD" >> $GITHUB_PATH - - uses: t1m0thyj/unlock-keyring@v1 - run: cargo build --verbose - run: cargo nextest run --profile ci --workspace - name: Upload test results to Codecov @@ -86,7 +85,6 @@ jobs: wget https://github.com/risc0/risc0/releases/download/v1.3.0/cargo-risczero-x86_64-unknown-linux-gnu.tgz tar xzvf cargo-risczero-x86_64-unknown-linux-gnu.tgz echo "$PWD" >> $GITHUB_PATH - - uses: t1m0thyj/unlock-keyring@v1 - name: Generate code coverage run: cargo llvm-cov --workspace --lib --lcov --output-path lcov.info -- --test-threads=1 - name: Upload coverage to Codecov diff --git a/src/bin/hyle.rs b/src/bin/hyle.rs index da77b3f22..2a1fcc4dc 100644 --- a/src/bin/hyle.rs +++ b/src/bin/hyle.rs @@ -72,7 +72,7 @@ async fn main() -> Result<()> { let mut config = conf::Conf::new(args.config_file, args.data_directory, args.run_indexer) .context("reading config file")?; - let crypto = Arc::new(BlstCrypto::new(config.id.clone()).context("Could not create crypto")?); + let crypto = Arc::new(BlstCrypto::new(&config.id).context("Could not create crypto")?); let pubkey = Some(crypto.validator_pubkey().clone()); setup_tracing( diff --git a/src/consensus.rs b/src/consensus.rs index 320526016..0a8b589a1 100644 --- a/src/consensus.rs +++ b/src/consensus.rs @@ -1166,7 +1166,7 @@ pub mod test { } async fn new_node(name: &str) -> Self { - let crypto = crypto::BlstCrypto::new(name.into()).unwrap(); + let crypto = crypto::BlstCrypto::new(name).unwrap(); Self::new(name, crypto.clone()).await } diff --git a/src/genesis.rs b/src/genesis.rs index d0dbb9375..5558dedec 100644 --- a/src/genesis.rs +++ b/src/genesis.rs @@ -545,7 +545,7 @@ mod tests { let shared_bus = SharedMessageBus::default(); let bus = GenesisBusClient::new_from_bus(shared_bus.new_handle()).await; let test_bus = TestGenesisBusClient::new_from_bus(shared_bus.new_handle()).await; - let crypto = Arc::new(BlstCrypto::new(config.id.clone()).unwrap()); + let crypto = Arc::new(BlstCrypto::new(&config.id).unwrap()); ( Genesis { config: Arc::new(config), @@ -705,7 +705,7 @@ mod tests { let (mut genesis, mut bus) = new(config.clone()).await; bus.send(PeerEvent::NewPeer { name: "node-2".into(), - pubkey: BlstCrypto::new("node-2".into()) + pubkey: BlstCrypto::new("node-2") .unwrap() .validator_pubkey() .clone(), @@ -714,7 +714,7 @@ mod tests { .expect("send"); bus.send(PeerEvent::NewPeer { name: "node-3".into(), - pubkey: BlstCrypto::new("node-3".into()) + pubkey: BlstCrypto::new("node-3") .unwrap() .validator_pubkey() .clone(), @@ -723,7 +723,7 @@ mod tests { .expect("send"); bus.send(PeerEvent::NewPeer { name: "node-4".into(), - pubkey: BlstCrypto::new("node-4".into()) + pubkey: BlstCrypto::new("node-4") .unwrap() .validator_pubkey() .clone(), @@ -739,7 +739,7 @@ mod tests { let (mut genesis, mut bus) = new(config).await; bus.send(PeerEvent::NewPeer { name: "node-4".into(), - pubkey: BlstCrypto::new("node-4".into()) + pubkey: BlstCrypto::new("node-4") .unwrap() .validator_pubkey() .clone(), @@ -748,7 +748,7 @@ mod tests { .expect("send"); bus.send(PeerEvent::NewPeer { name: "node-2".into(), - pubkey: BlstCrypto::new("node-2".into()) + pubkey: BlstCrypto::new("node-2") .unwrap() .validator_pubkey() .clone(), @@ -757,7 +757,7 @@ mod tests { .expect("send"); bus.send(PeerEvent::NewPeer { name: "node-3".into(), - pubkey: BlstCrypto::new("node-3".into()) + pubkey: BlstCrypto::new("node-3") .unwrap() .validator_pubkey() .clone(), diff --git a/src/mempool.rs b/src/mempool.rs index 5bb770efb..10a40dd71 100644 --- a/src/mempool.rs +++ b/src/mempool.rs @@ -1239,7 +1239,7 @@ pub mod test { } pub async fn new(name: &str) -> Self { - let crypto = BlstCrypto::new(name.into()).unwrap(); + let crypto = BlstCrypto::new(name).unwrap(); let shared_bus = SharedMessageBus::new(BusMetrics::global("global".to_string())); let out_receiver = get_receiver::(&shared_bus).await; @@ -1626,10 +1626,10 @@ pub mod test { // Adding 4 other validators // Total voting_power = 500; f = 167 --> You need at least 2 signatures to send PoDAUpdate - let crypto2 = BlstCrypto::new("validator2".into()).unwrap(); - let crypto3 = BlstCrypto::new("validator3".into()).unwrap(); - let crypto4 = BlstCrypto::new("validator4".into()).unwrap(); - let crypto5 = BlstCrypto::new("validator5".into()).unwrap(); + let crypto2 = BlstCrypto::new("validator2").unwrap(); + let crypto3 = BlstCrypto::new("validator3").unwrap(); + let crypto4 = BlstCrypto::new("validator4").unwrap(); + let crypto5 = BlstCrypto::new("validator5").unwrap(); ctx.setup_node(&[pubkey, crypto2.clone(), crypto3.clone(), crypto4, crypto5]); let register_tx = make_register_contract_tx(ContractName::new("test1")); @@ -1668,7 +1668,7 @@ pub mod test { ctx.setup_node(&[pubkey]); // Adding new validator - let temp_crypto = BlstCrypto::new("validator1".into()).unwrap(); + let temp_crypto = BlstCrypto::new("validator1").unwrap(); ctx.add_trusted_validator(temp_crypto.validator_pubkey()); // Sending transaction to mempool as RestApiMessage @@ -1764,7 +1764,7 @@ pub mod test { ); let size = LaneBytesSize(data_proposal.estimate_size() as u64); - let temp_crypto = BlstCrypto::new("temp_crypto".into()).unwrap(); + let temp_crypto = BlstCrypto::new("temp_crypto").unwrap(); let signed_msg = temp_crypto.sign(MempoolNetMessage::DataVote(data_proposal.hashed(), size))?; assert!(ctx @@ -1797,7 +1797,7 @@ pub mod test { ctx.make_data_proposal_with_pending_txs()?; // Add new validator - let crypto2 = BlstCrypto::new("2".into()).unwrap(); + let crypto2 = BlstCrypto::new("2").unwrap(); ctx.add_trusted_validator(crypto2.validator_pubkey()); let signed_msg = crypto2.sign(MempoolNetMessage::DataVote( @@ -1833,7 +1833,7 @@ pub mod test { ctx.make_data_proposal_with_pending_txs()?; // Add new validator - let crypto2 = BlstCrypto::new("2".into()).unwrap(); + let crypto2 = BlstCrypto::new("2").unwrap(); ctx.add_trusted_validator(crypto2.validator_pubkey()); let signed_msg = crypto2.sign(MempoolNetMessage::DataVote( @@ -1848,7 +1848,7 @@ pub mod test { #[test_log::test(tokio::test)] async fn test_sending_sync_request() -> Result<()> { let mut ctx = MempoolTestCtx::new("mempool").await; - let crypto2 = BlstCrypto::new("2".into()).unwrap(); + let crypto2 = BlstCrypto::new("2").unwrap(); let pubkey2 = crypto2.validator_pubkey(); ctx.handle_consensus_event(ConsensusProposal { @@ -1889,7 +1889,7 @@ pub mod test { ctx.last_validator_lane_entry(ctx.validator_pubkey()); // Add new validator - let crypto2 = BlstCrypto::new("2".into()).unwrap(); + let crypto2 = BlstCrypto::new("2").unwrap(); ctx.add_trusted_validator(crypto2.validator_pubkey()); let signed_msg = crypto2.sign(MempoolNetMessage::SyncRequest( @@ -1935,8 +1935,8 @@ pub mod test { ) = ctx.last_validator_lane_entry(ctx.validator_pubkey()); // Add new validator - let crypto2 = BlstCrypto::new("2".into()).unwrap(); - let crypto3 = BlstCrypto::new("3".into()).unwrap(); + let crypto2 = BlstCrypto::new("2").unwrap(); + let crypto3 = BlstCrypto::new("3").unwrap(); ctx.add_trusted_validator(crypto2.validator_pubkey()); diff --git a/src/mempool/storage.rs b/src/mempool/storage.rs index 8645a0dd3..75d470e86 100644 --- a/src/mempool/storage.rs +++ b/src/mempool/storage.rs @@ -630,7 +630,7 @@ mod tests { #[test_log::test(tokio::test)] async fn test_put_contains_get() { - let crypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); @@ -653,7 +653,7 @@ mod tests { #[test_log::test(tokio::test)] async fn test_update() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); let data_proposal = DataProposal::new(None, vec![]); @@ -679,10 +679,10 @@ mod tests { #[test_log::test(tokio::test)] async fn test_on_data_proposal() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); - let crypto2: BlstCrypto = crypto::BlstCrypto::new("2".to_owned()).unwrap(); + let crypto2: BlstCrypto = crypto::BlstCrypto::new("2").unwrap(); let pubkey2 = crypto2.validator_pubkey(); let mut storage = setup_storage(pubkey); @@ -708,10 +708,10 @@ mod tests { #[test_log::test(tokio::test)] async fn test_on_data_proposal_fork() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); - let crypto2: BlstCrypto = crypto::BlstCrypto::new("2".to_owned()).unwrap(); + let crypto2: BlstCrypto = crypto::BlstCrypto::new("2").unwrap(); let pubkey2 = crypto2.validator_pubkey(); let mut storage = setup_storage(pubkey); @@ -738,11 +738,11 @@ mod tests { #[test_log::test(tokio::test)] async fn test_on_data_vote() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); - let crypto2: BlstCrypto = crypto::BlstCrypto::new("2".to_owned()).unwrap(); + let crypto2: BlstCrypto = crypto::BlstCrypto::new("2").unwrap(); let data_proposal = DataProposal::new(None, vec![]); // 1 creates a DP @@ -766,13 +766,13 @@ mod tests { #[test_log::test(tokio::test)] async fn test_on_poda_update() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); - let crypto2: BlstCrypto = crypto::BlstCrypto::new("2".to_owned()).unwrap(); + let crypto2: BlstCrypto = crypto::BlstCrypto::new("2").unwrap(); let pubkey2 = crypto2.validator_pubkey(); - let crypto3: BlstCrypto = crypto::BlstCrypto::new("3".to_owned()).unwrap(); + let crypto3: BlstCrypto = crypto::BlstCrypto::new("3").unwrap(); let dp = DataProposal::new(None, vec![]); @@ -799,7 +799,7 @@ mod tests { #[test_log::test(tokio::test)] async fn test_get_lane_entries_between_hashes() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); let dp1 = DataProposal::new(None, vec![]); @@ -862,7 +862,7 @@ mod tests { #[test_log::test(tokio::test)] async fn test_new_data_proposal() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); @@ -882,7 +882,7 @@ mod tests { #[test_log::test(tokio::test)] async fn test_new_data_proposal_empty() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); @@ -898,7 +898,7 @@ mod tests { #[test_log::test] fn test_lane_size() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); @@ -929,7 +929,7 @@ mod tests { #[test_log::test(tokio::test)] async fn test_get_lane_pending_entries() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); let data_proposal = DataProposal::new(None, vec![]); @@ -946,7 +946,7 @@ mod tests { #[test_log::test(tokio::test)] async fn test_get_latest_car_and_new_cut() { - let crypto: BlstCrypto = crypto::BlstCrypto::new("1".to_owned()).unwrap(); + let crypto: BlstCrypto = crypto::BlstCrypto::new("1").unwrap(); let pubkey = crypto.validator_pubkey(); let mut storage = setup_storage(pubkey); let staking = Staking::new(); diff --git a/src/single_node_consensus.rs b/src/single_node_consensus.rs index 4562ec234..5b7e3b3c7 100644 --- a/src/single_node_consensus.rs +++ b/src/single_node_consensus.rs @@ -236,7 +236,7 @@ mod tests { impl TestContext { pub async fn new(name: &str) -> Self { - let crypto = BlstCrypto::new(name.into()).unwrap(); + let crypto = BlstCrypto::new(name).unwrap(); let shared_bus = SharedMessageBus::new(BusMetrics::global("global".to_string())); let conf = Arc::new(Conf::default()); let store = SingleNodeConsensusStore::default(); diff --git a/src/tests/autobahn_testing.rs b/src/tests/autobahn_testing.rs index 161589359..ab73c9b31 100644 --- a/src/tests/autobahn_testing.rs +++ b/src/tests/autobahn_testing.rs @@ -274,7 +274,7 @@ impl AutobahnTestCtx { pub fn generate_cryptos(nb: usize) -> Vec { (0..nb) .map(|i| { - let crypto = crypto::BlstCrypto::new(format!("node-{i}")).unwrap(); + let crypto = crypto::BlstCrypto::new(&format!("node-{i}")).unwrap(); info!("node {}: {}", i, crypto.validator_pubkey()); crypto }) @@ -730,7 +730,7 @@ async fn autobahn_rejoin_flow() { 0, ); - let crypto = crypto::BlstCrypto::new("node-3".to_owned()).unwrap(); + let crypto = crypto::BlstCrypto::new("node-3").unwrap(); let mut joining_node = AutobahnTestCtx::new("node-3", crypto).await; joining_node .consensus_ctx diff --git a/src/utils/crypto.rs b/src/utils/crypto.rs index 72e67e691..27213580c 100644 --- a/src/utils/crypto.rs +++ b/src/utils/crypto.rs @@ -58,10 +58,10 @@ pub const SIG_SIZE: usize = 48; impl BlstCrypto { #[cfg(not(test))] - pub fn new(validator_name: String) -> Result { + pub fn new(validator_name: &str) -> Result { let sk = Self::load_from_env().or_else(|err| { println!("Could not load secret from env: {}", err); - Self::load_from_keyring(&validator_name) + Self::load_from_keyring(validator_name) })?; let validator_pubkey = as_validator_pubkey(sk.sk_to_pk()); @@ -104,14 +104,9 @@ impl BlstCrypto { } #[cfg(test)] - pub fn new(validator_name: String) -> Result { - // TODO load secret key from keyring or other + pub fn new(validator_name: &str) -> Result { // here basically secret_key <=> validator_id which is very badly secure ! - let validator_name_bytes = validator_name.as_bytes(); - let mut ikm = [0u8; 32]; - let len = std::cmp::min(validator_name_bytes.len(), 32); - #[allow(clippy::indexing_slicing, reason = "len checked")] - ikm[..len].copy_from_slice(&validator_name_bytes[..len]); + let ikm = Self::secret_from_name(validator_name); let sk = SecretKey::key_gen(&ikm, &[]) .map_err(|e| anyhow!("Could not generate key: {:?}", e))?; @@ -123,13 +118,22 @@ impl BlstCrypto { }) } + pub fn secret_from_name(validator_name: &str) -> [u8; 32] { + let validator_name_bytes = validator_name.as_bytes(); + let mut ikm = [0u8; 32]; + let len = std::cmp::min(validator_name_bytes.len(), 32); + #[allow(clippy::indexing_slicing, reason = "len checked")] + ikm[..len].copy_from_slice(&validator_name_bytes[..len]); + ikm + } + #[cfg(test)] pub fn new_random() -> Result { let mut rng = rand::rng(); let id: String = (0..32) .map(|_| rng.random_range(33..127) as u8 as char) // Caractères imprimables ASCII .collect(); - Self::new(id.as_str().into()) + Self::new(id.as_str()) } pub fn validator_pubkey(&self) -> &ValidatorPublicKey { diff --git a/src/utils/integration_test.rs b/src/utils/integration_test.rs index 0f2653868..6df9335a5 100644 --- a/src/utils/integration_test.rs +++ b/src/utils/integration_test.rs @@ -91,7 +91,7 @@ impl NodeIntegrationCtxBuilder { pub async fn new() -> Self { let tmpdir = tempfile::tempdir().unwrap(); let bus = SharedMessageBus::new(BusMetrics::global("default".to_string())); - let crypto = BlstCrypto::new("test".to_owned()).unwrap(); + let crypto = BlstCrypto::new("test").unwrap(); let mut conf = Conf::new( None, tmpdir.path().to_str().map(|s| s.to_owned()), diff --git a/tests/fixtures/test_helpers.rs b/tests/fixtures/test_helpers.rs index fb2019357..fb4d536cc 100644 --- a/tests/fixtures/test_helpers.rs +++ b/tests/fixtures/test_helpers.rs @@ -5,7 +5,10 @@ use client_sdk::transaction_builder::{ProvableBlobTx, StateUpdater, TxExecutor}; use hyle::{ model::BlobTransaction, rest::client::NodeApiHttpClient, - utils::conf::{Conf, Consensus}, + utils::{ + conf::{Conf, Consensus}, + crypto::BlstCrypto, + }, }; use hyle_model::TxHash; use rand::Rng; @@ -108,6 +111,10 @@ impl TestProcess { ron::ser::to_writer(std::fs::File::create(&conf_file).unwrap(), &conf).unwrap(); cmd.env("RISC0_DEV_MODE", "1"); + + let secret = BlstCrypto::secret_from_name(&conf.id); + cmd.env("HYLE_VALIDATOR_SECRET", hex::encode(secret)); + Self { conf, dir: tmpdir,