From 9dbb18ae820798aa911f68b9fd66efb3a8b4d413 Mon Sep 17 00:00:00 2001 From: Skipper Date: Fri, 1 May 2026 10:58:10 +0200 Subject: [PATCH] WIP: some things --- protobufs/shared/vault.proto | 7 +- server/Cargo.lock | 210 ++++++++++++++++-- server/crates/arbiter-crypto/src/safecell.rs | 10 +- server/crates/arbiter-server/Cargo.toml | 1 + .../arbiter-server/src/actors/vault/mod.rs | 195 +++++++++++++--- .../crates/arbiter-server/src/crypto/mod.rs | 6 +- .../arbiter-server/src/evm/safe_signer.rs | 2 +- .../arbiter-server/src/grpc/client/vault.rs | 1 + .../arbiter-server/src/grpc/operator/vault.rs | 3 +- .../src/grpc/operator/vault_gate/outbound.rs | 3 +- 10 files changed, 384 insertions(+), 54 deletions(-) diff --git a/protobufs/shared/vault.proto b/protobufs/shared/vault.proto index 795539f..9e5c2d3 100644 --- a/protobufs/shared/vault.proto +++ b/protobufs/shared/vault.proto @@ -5,7 +5,8 @@ package arbiter.shared; enum VaultState { VAULT_STATE_UNSPECIFIED = 0; VAULT_STATE_UNBOOTSTRAPPED = 1; - VAULT_STATE_SEALED = 2; - VAULT_STATE_UNSEALED = 3; - VAULT_STATE_ERROR = 4; + VAULT_STATE_BOOSTRAPPING = 2; + VAULT_STATE_SEALED = 3; + VAULT_STATE_UNSEALED = 4; + VAULT_STATE_ERROR = 5; } diff --git a/server/Cargo.lock b/server/Cargo.lock index e36c264..ba262e3 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -24,7 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ "crypto-common 0.1.7", - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -786,6 +786,7 @@ dependencies = [ "tonic", "tracing", "tracing-subscriber", + "vsss-rs", "x25519-dalek 2.0.1", ] @@ -1283,7 +1284,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -1612,8 +1613,22 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array", + "generic-array 0.14.7", "rand_core 0.6.4", + "serdect 0.2.0", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-bigint" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96272c2ff28b807e09250b180ad1fb7889a3258f7455759b5c3c58b719467130" +dependencies = [ + "num-traits", + "rand_core 0.6.4", + "serdect 0.3.0", "subtle", "zeroize", ] @@ -1624,7 +1639,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ - "generic-array", + "generic-array 0.14.7", "rand_core 0.6.4", "typenum", ] @@ -1927,7 +1942,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -2007,7 +2022,7 @@ dependencies = [ "digest 0.10.7", "elliptic-curve", "rfc6979", - "serdect", + "serdect 0.2.0", "signature 2.2.0", "spki 0.7.3", ] @@ -2040,16 +2055,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", - "crypto-bigint", + "crypto-bigint 0.5.5", "digest 0.10.7", "ff", - "generic-array", + "generic-array 0.14.7", "group", + "hkdf", "pkcs8 0.10.2", "rand_core 0.6.4", "sec1", - "serdect", + "serdect 0.2.0", "subtle", + "tap", + "zeroize", +] + +[[package]] +name = "elliptic-curve-tools" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1de2b6fae800f08032a6ea32995b52925b1d451bff9d445c8ab2932323277faf" +dependencies = [ + "elliptic-curve", + "heapless", + "hex", + "multiexp", + "serde", "zeroize", ] @@ -2123,6 +2154,7 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ + "bitvec", "rand_core 0.6.4", "subtle", ] @@ -2323,6 +2355,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "generic-array" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dab9e9188e97a93276e1fe7b56401b851e2b45a46d045ca658100c1303ada649" +dependencies = [ + "rustversion", + "serde_core", + "typenum", +] + [[package]] name = "getrandom" version = "0.2.17" @@ -2406,6 +2449,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -2446,6 +2498,16 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.5.0" @@ -2473,6 +2535,15 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac 0.12.1", +] + [[package]] name = "hmac" version = "0.12.1" @@ -2543,6 +2614,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d46837a0ed51fe95bd3b05de33cd64a1ee88fc797477ca48446872504507c5" dependencies = [ "ctutils", + "serde", "typenum", "zeroize", ] @@ -2808,7 +2880,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -2947,7 +3019,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "once_cell", - "serdect", + "serdect 0.2.0", "sha2 0.10.9", "signature 2.2.0", ] @@ -3290,6 +3362,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "multiexp" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ec2ce93a6f06ac6cae04c1da3f2a6a24fcfc1f0eb0b4e0f3d302f0df45326cb" +dependencies = [ + "ff", + "group", + "rand_core 0.6.4", + "rustversion", + "std-shims", + "zeroize", +] + [[package]] name = "multimap" version = "0.10.1" @@ -3321,6 +3407,20 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -3329,6 +3429,19 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", + "rand 0.8.6", + "serde", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", + "rand 0.8.6", + "serde", ] [[package]] @@ -3346,6 +3459,29 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", + "serde", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -4454,9 +4590,9 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der 0.7.10", - "generic-array", + "generic-array 0.14.7", "pkcs8 0.10.2", - "serdect", + "serdect 0.2.0", "subtle", "zeroize", ] @@ -4622,6 +4758,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serdect" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f42f67da2385b51a5f9652db9c93d78aeaf7610bf5ec366080b6de810604af53" +dependencies = [ + "base16ct", + "serde", +] + [[package]] name = "sha2" version = "0.10.9" @@ -4787,6 +4933,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" + [[package]] name = "spki" version = "0.7.3" @@ -4831,6 +4983,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "std-shims" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "227c4f8561598188d0df96dbe749824576174bba278b5b6bb2eacff1066067d0" +dependencies = [ + "hashbrown 0.16.1", + "rustversion", + "spin", +] + [[package]] name = "string_morph" version = "0.1.0" @@ -5574,6 +5737,27 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "vsss-rs" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ec751bdcc8bda099e269b24cc6b4ad14f9ce8b0490c1599174070e792ecd70c" +dependencies = [ + "crypto-bigint 0.5.5", + "crypto-bigint 0.6.1", + "elliptic-curve", + "elliptic-curve-tools", + "generic-array 1.4.1", + "hex", + "hybrid-array", + "num", + "rand_core 0.6.4", + "serde", + "sha3 0.10.9", + "subtle", + "zeroize", +] + [[package]] name = "wait-timeout" version = "0.2.1" diff --git a/server/crates/arbiter-crypto/src/safecell.rs b/server/crates/arbiter-crypto/src/safecell.rs index 15b0044..b16194c 100644 --- a/server/crates/arbiter-crypto/src/safecell.rs +++ b/server/crates/arbiter-crypto/src/safecell.rs @@ -22,7 +22,7 @@ pub trait SafeCellHandle { fn read(&mut self) -> Self::CellRead<'_>; fn write(&mut self) -> Self::CellWrite<'_>; - fn new_inline(f: F) -> Self + fn new_inline_default(f: F) -> Self where Self: Sized, T: Default, @@ -36,6 +36,14 @@ pub trait SafeCellHandle { cell } + fn new_inline(f: Box) -> Self + where + Self: Sized, + F: for<'a> FnOnce() -> T, + { + Self::new(f()) + } + #[inline(always)] fn read_inline(&mut self, f: F) -> R where diff --git a/server/crates/arbiter-server/Cargo.toml b/server/crates/arbiter-server/Cargo.toml index 7790bd6..bc7cb3f 100644 --- a/server/crates/arbiter-server/Cargo.toml +++ b/server/crates/arbiter-server/Cargo.toml @@ -50,6 +50,7 @@ subtle = "2.6.1" x25519-dalek.workspace = true k256.workspace = true kameo_actors.workspace = true +vsss-rs = "5.4.0" [dev-dependencies] proptest = "1.11.0" diff --git a/server/crates/arbiter-server/src/actors/vault/mod.rs b/server/crates/arbiter-server/src/actors/vault/mod.rs index 51b7e33..a17ef63 100644 --- a/server/crates/arbiter-server/src/actors/vault/mod.rs +++ b/server/crates/arbiter-server/src/actors/vault/mod.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use crate::{ crypto::{ KeyCell, derive_key, @@ -6,7 +8,7 @@ use crate::{ }, db::{ self, - models::{self, RootKeyHistory, RootKeyHistoryId}, + models::{self, OperatorId, OperatorIdentityId, RootKeyHistory, RootKeyHistoryId}, schema::{self}, }, }; @@ -15,10 +17,11 @@ use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; use chrono::Utc; use diesel::{ ExpressionMethods as _, OptionalExtension, QueryDsl, SelectableHelper, - dsl::{insert_into, update}, + dsl::{count, insert_into, update}, + select, }; use diesel_async::{AsyncConnection, RunQueryDsl}; -use hmac::{KeyInit as _, Mac as _}; +use hmac::{KeyInit as _, Mac as _, digest::common}; use kameo::{Actor, Reply, actor::ActorRef, messages}; use kameo_actors::message_bus::{MessageBus, Publish}; use strum::{EnumDiscriminants, IntoDiscriminant}; @@ -62,6 +65,15 @@ pub enum Error { BrokenDatabase, } +#[derive(Debug, thiserror::Error)] +pub enum UnsealError {} + +#[derive(Debug, thiserror::Error)] +pub enum BootstrapError { + #[error("That operator already contributed his share")] + AlreadyContributed, +} + struct Unsealed { root_key_history_id: RootKeyHistoryId, root_key: KeyCell, @@ -73,8 +85,15 @@ enum State { #[default] Unbootstrapped, + Bootstrapping { + declared_operators: u64, + current_passphrases: HashMap>>, + }, + Sealed { + threshold: u64, // basically, quorum size root_key_history_id: RootKeyHistoryId, + current_shares: HashMap>>, }, Unsealed(Unsealed), } @@ -90,7 +109,6 @@ pub struct Vault { events: ActorRef, } -#[messages] impl Vault { pub async fn new(db: db::DatabasePool, events: ActorRef) -> Result { let state = { @@ -103,9 +121,17 @@ impl Vault { .await?; match root_key_history { - Some(root_key_history) => State::Sealed { - root_key_history_id: root_key_history.id, - }, + Some(root_key_history) => { + let operator_count: i64 = schema::operator::table + .count() + .get_result(&mut conn) + .await?; + State::Sealed { + root_key_history_id: root_key_history.id, + current_shares: HashMap::default(), + threshold: shamir_threshold(operator_count.cast_unsigned()), // invariant: db couldn't return negative number of rows + } + } None => State::Unbootstrapped, } }; @@ -154,19 +180,28 @@ impl Vault { const fn expect_unsealed(state: &mut State) -> Result<&mut Unsealed, Error> { match state { State::Unsealed(unsealed) => Ok(unsealed), + State::Bootstrapping { .. } => Err(Error::NotBootstrapped), State::Unbootstrapped => Err(Error::NotBootstrapped), State::Sealed { .. } => Err(Error::Sealed), } } - #[message] - pub async fn bootstrap(&mut self, seal_key_raw: SafeCell>) -> Result<(), Error> { - if !matches!(self.state, State::Unbootstrapped) { + pub async fn finalize_bootstrap(&mut self) -> Result<(), Error> { + let State::Bootstrapping { + declared_operators, + current_passphrases, + } = &mut self.state + else { return Err(Error::AlreadyBootstrapped); - } - let salt = v1::generate_salt(); - let mut seal_key = derive_key(seal_key_raw, &salt); + }; let mut root_key = KeyCell::new_secure_random(); + let root_key_salt = v1::generate_salt(); + + let mut seal_key = KeyCell::new_secure_random(); + + let shares = seal_key.0.read_inline(|seal_key| { + generate_shamir_shares(current_passphrases.len() as u64, seal_key.as_slice()) + }); // Zero nonces are fine because they are one-time let root_key_nonce = Nonce::default(); @@ -182,11 +217,21 @@ impl Vault { }) })?; + let data_encryption_nonce_bytes = data_encryption_nonce.to_vec(); let mut conn = self.db.get().await?; - let data_encryption_nonce_bytes = data_encryption_nonce.to_vec(); let root_key_history_id = conn .transaction(async |conn| { + for ((operator_id, raw_passphrase), raw_share) in + current_passphrases.iter_mut().zip(shares.iter()) + { + let salt = v1::generate_salt(); + let mut share_seal_key = derive_key(&mut raw_passphrase, &salt); + let share_encryption_nonce = Nonce::default(); + + let share_key = derive_key(&mut raw_passphrase, &salt); + } + let root_key_history_id = insert_into(schema::root_key_history::table) .values(&models::NewRootKeyHistory { ciphertext: root_key_ciphertext.clone(), @@ -194,7 +239,7 @@ impl Vault { root_key_encryption_nonce: root_key_nonce.to_vec(), data_encryption_nonce: data_encryption_nonce_bytes.clone(), schema_version: 1, - salt: salt.to_vec(), + salt: root_key_salt.to_vec(), }) .returning(schema::root_key_history::id) .get_result(&mut *conn) @@ -221,11 +266,59 @@ impl Vault { Ok(()) } +} + +// Seal / unseal / bootstrap stuff. Will be separated into another actor, eventually +#[messages] +impl Vault { + #[message] + pub async fn start_bootstrap(&mut self, declared_operators: u64) -> Result<(), Error> { + if !matches!(&self.state, State::Unbootstrapped) { + return Err(Error::AlreadyBootstrapped); + } + + self.state = State::Bootstrapping { + declared_operators, + current_passphrases: HashMap::default(), + }; + Ok(()) + } #[message] - pub async fn try_unseal(&mut self, seal_key_raw: SafeCell>) -> Result<(), Error> { + pub async fn contribute_bootstrap( + &mut self, + operator: OperatorIdentityId, + key_raw: SafeCell>, + ) -> Result<(), Error> { + let State::Bootstrapping { + current_passphrases, + declared_operators, + } = &mut self.state + else { + return Err(Error::AlreadyBootstrapped); + }; + + if current_passphrases.contains_key(&operator) { + return Err(Error::AlreadyBootstrapped); + } + current_passphrases.insert(operator, key_raw); + + if current_passphrases.len() == declared_operators { + return self.finalize_bootstrap(seal_key_raw); + } + + Ok(()) + } + + #[message] + pub async fn contribute_unseal( + &mut self, + operator: OperatorId, + key_raw: SafeCell>, + ) -> Result<(), Error> { let State::Sealed { root_key_history_id, + current_shares, } = &self.state else { return Err(Error::NotBootstrapped); @@ -246,7 +339,7 @@ impl Vault { error!("Broken database: invalid salt for root key"); Error::BrokenDatabase })?; - let mut seal_key = derive_key(seal_key_raw, &salt); + let mut seal_key = derive_key(key_raw, &salt); let mut root_key = SafeCell::new(current_key.ciphertext.clone()); @@ -277,6 +370,25 @@ impl Vault { Ok(()) } + #[message] + pub async fn seal(&mut self) -> Result<(), Error> { + let Unsealed { + root_key_history_id, + .. + } = Self::expect_unsealed(&mut self.state)?; + + self.state = State::Sealed { + root_key_history_id: *root_key_history_id, + current_shares: HashMap::new(), + }; + let _ = self.events.tell(Publish(events::VaultResealed)).await; + Ok(()) + } +} + +// Server-side cryptographic operations +#[messages] +impl Vault { #[message] pub async fn decrypt(&mut self, aead_id: i32) -> Result>, Error> { let Unsealed { root_key, .. } = Self::expect_unsealed(&mut self.state)?; @@ -394,26 +506,47 @@ impl Vault { Ok(hmac.verify_slice(&expected_mac).is_ok()) } +} - #[message] - pub async fn seal(&mut self) -> Result<(), Error> { - let Unsealed { - root_key_history_id, - .. - } = Self::expect_unsealed(&mut self.state)?; - - self.state = State::Sealed { - root_key_history_id: *root_key_history_id, - }; - let _ = self.events.tell(Publish(events::VaultResealed)).await; - Ok(()) +/// According to the spec, the quorum is 50% + 1 +/// with exception for 1 and 2 operators, those require exactly the number of operators registered +fn shamir_threshold(comittee_size: u64) -> u64 { + if comittee_size == 2 || comittee_size == 1 { + return comittee_size; } + + let half_comittee = match comittee_size % 2 != 0 { + true => (comittee_size - 1) / 2, + false => comittee_size / 2, + }; + + half_comittee + 1 +} + +/// Beware: this function accepts raw key references (without memory protection) +fn generate_shamir_shares(threshold: u64, key: &[u8]) -> Vec>> { + use vsss_rs::{shamir, *}; + + type P256Share = DefaultShare, IdentifierPrimeField>; + + let mut osrng = rand_core::OsRng::default(); + let sk = SecretKey::random(&mut osrng); + let nzs = sk.to_nonzero_scalar(); + let shared_secret = IdentifierPrimeField(*nzs.as_ref()); + let res = shamir::split_secret::(2, 3, &shared_secret, &mut osrng); + assert!(res.is_ok()); + let shares = res.unwrap(); + let res = shares.combine(); + assert!(res.is_ok()); + let scalar = res.unwrap(); + let nzs_dup = NonZeroScalar::from_repr(scalar.0.to_repr()).unwrap(); + let sk_dup = SecretKey::from(nzs_dup); + assert_eq!(sk_dup.to_bytes(), sk.to_bytes()); } #[cfg(test)] mod tests { use crate::actors::GlobalActors; - use crate::db::models::RootKeyHistory; use arbiter_crypto::safecell::SafeCellHandle as _; use super::*; @@ -423,7 +556,7 @@ mod tests { .await .unwrap(); let seal_key = SafeCell::new(b"test-seal-key".to_vec()); - actor.bootstrap(seal_key).await.unwrap(); + actor.finalize_bootstrap(seal_key).await.unwrap(); actor } diff --git a/server/crates/arbiter-server/src/crypto/mod.rs b/server/crates/arbiter-server/src/crypto/mod.rs index 440cb24..13f2485 100644 --- a/server/crates/arbiter-server/src/crypto/mod.rs +++ b/server/crates/arbiter-server/src/crypto/mod.rs @@ -28,7 +28,7 @@ impl TryFrom>> for KeyCell { if value.len() != size_of::() { return Err(()); } - let cell = SafeCell::new_inline(|cell_write: &mut Key| { + let cell = SafeCell::new_inline_default(|cell_write: &mut Key| { cell_write.copy_from_slice(&value); }); Ok(Self(cell)) @@ -37,7 +37,7 @@ impl TryFrom>> for KeyCell { impl KeyCell { pub fn new_secure_random() -> Self { - let key = SafeCell::new_inline(|key_buffer: &mut Key| { + let key = SafeCell::new_inline_default(|key_buffer: &mut Key| { let mut rng = StdRng::try_from_rng(&mut SysRng) .expect("Rng failure is unrecoverable and should panic"); rng.fill_bytes(key_buffer); @@ -94,7 +94,7 @@ impl KeyCell { } /// Derive a fixed-length key from the password using Argon2id, which is designed for password hashing and key derivation. -pub fn derive_key(mut password: SafeCell>, salt: &Salt) -> KeyCell { +pub fn derive_key(password: &mut SafeCell>, salt: &Salt) -> KeyCell { let params = { #[cfg(debug_assertions)] { diff --git a/server/crates/arbiter-server/src/evm/safe_signer.rs b/server/crates/arbiter-server/src/evm/safe_signer.rs index 02597a8..300b142 100644 --- a/server/crates/arbiter-server/src/evm/safe_signer.rs +++ b/server/crates/arbiter-server/src/evm/safe_signer.rs @@ -44,7 +44,7 @@ impl std::fmt::Debug for SafeSigner { /// Returns the protected key bytes and the derived Ethereum address. pub fn generate(rng: &mut impl rand::Rng) -> (SafeCell<[u8; 32]>, Address) { loop { - let mut cell = SafeCell::new_inline(|w: &mut [u8; 32]| { + let mut cell = SafeCell::new_inline_default(|w: &mut [u8; 32]| { rng.fill_bytes(w); }); diff --git a/server/crates/arbiter-server/src/grpc/client/vault.rs b/server/crates/arbiter-server/src/grpc/client/vault.rs index f5561b9..95d4ba8 100644 --- a/server/crates/arbiter-server/src/grpc/client/vault.rs +++ b/server/crates/arbiter-server/src/grpc/client/vault.rs @@ -31,6 +31,7 @@ pub(super) async fn dispatch( VaultRequestPayload::QueryState(()) => { let state = match actor.ask(HandleQueryVaultState {}).await { Ok(VaultState::Unbootstrapped) => ProtoVaultState::Unbootstrapped, + Ok(VaultState::Bootstrapping) => ProtoVaultState::Boostrapping, Ok(VaultState::Sealed) => ProtoVaultState::Sealed, Ok(VaultState::Unsealed) => ProtoVaultState::Unsealed, Err(SendError::HandlerError(Error::Internal)) => ProtoVaultState::Error, diff --git a/server/crates/arbiter-server/src/grpc/operator/vault.rs b/server/crates/arbiter-server/src/grpc/operator/vault.rs index ac1c293..582ab13 100644 --- a/server/crates/arbiter-server/src/grpc/operator/vault.rs +++ b/server/crates/arbiter-server/src/grpc/operator/vault.rs @@ -3,7 +3,6 @@ use crate::{ peers::operator::{OperatorSession, session::handlers::HandleQueryVaultState}, }; use arbiter_proto::{ - proto::shared::VaultState as ProtoVaultState, proto::operator::{ operator_response::Payload as OperatorResponsePayload, vault::{ @@ -11,6 +10,7 @@ use arbiter_proto::{ response::Payload as VaultResponsePayload, }, }, + proto::shared::VaultState as ProtoVaultState, }; use kameo::actor::ActorRef; @@ -47,6 +47,7 @@ async fn handle_query_vault_state( let state = match actor.ask(HandleQueryVaultState {}).await { Ok(VaultState::Unbootstrapped) => ProtoVaultState::Unbootstrapped, Ok(VaultState::Sealed) => ProtoVaultState::Sealed, + Ok(VaultState::Bootstrapping) => ProtoVaultState::Boostrapping, Ok(VaultState::Unsealed) => ProtoVaultState::Unsealed, Err(err) => { warn!(error = ?err, "Failed to query vault state"); diff --git a/server/crates/arbiter-server/src/grpc/operator/vault_gate/outbound.rs b/server/crates/arbiter-server/src/grpc/operator/vault_gate/outbound.rs index 4a2f072..268b7d5 100644 --- a/server/crates/arbiter-server/src/grpc/operator/vault_gate/outbound.rs +++ b/server/crates/arbiter-server/src/grpc/operator/vault_gate/outbound.rs @@ -4,7 +4,6 @@ use crate::{ peers::operator::vault_gate::{self as vault_gate}, }; use arbiter_proto::proto::{ - shared::VaultState as ProtoVaultState, operator::{ operator_response::Payload as OperatorResponsePayload, vault::{ @@ -17,6 +16,7 @@ use arbiter_proto::proto::{ }, }, }, + shared::VaultState as ProtoVaultState, }; use tonic::Status; @@ -46,6 +46,7 @@ impl Convert for VaultState { fn convert(self) -> OperatorResponsePayload { let proto_state = match self { Self::Unbootstrapped => ProtoVaultState::Unbootstrapped, + Self::Bootstrapping => ProtoVaultState::Boostrapping, Self::Sealed => ProtoVaultState::Sealed, Self::Unsealed => ProtoVaultState::Unsealed, };