4 Commits

Author SHA1 Message Date
Skipper
929d50b589 housekeeping(server): clean too-broad visibility markers and organize imports
Some checks failed
ci/woodpecker/pr/server-audit Pipeline was successful
ci/woodpecker/pr/server-vet Pipeline failed
ci/woodpecker/pr/server-lint Pipeline failed
ci/woodpecker/pr/server-test Pipeline failed
ci/woodpecker/pr/useragent-analyze Pipeline failed
2026-04-18 13:30:09 +02:00
Skipper
70acfc99b5 merge: refactor-integrity-check into main 2026-04-18 13:19:13 +02:00
62dff3f810 Merge pull request 'refactor(hashing): introduce Hashable derive macro and migrate server types' (#82) from hashing-proc-macro into main
Some checks failed
ci/woodpecker/push/server-audit Pipeline was successful
ci/woodpecker/push/server-lint Pipeline was successful
ci/woodpecker/push/server-vet Pipeline failed
ci/woodpecker/push/server-test Pipeline was successful
Reviewed-on: #82
Reviewed-by: Stas <business@jexter.tech>
2026-04-08 00:18:40 +00:00
CleverWild
6e22f368c9 refactor(hashing): introduce Hashable derive macro and migrate server types
Some checks failed
ci/woodpecker/pr/server-audit Pipeline was successful
ci/woodpecker/pr/server-vet Pipeline failed
ci/woodpecker/pr/server-lint Pipeline was successful
ci/woodpecker/pr/server-test Pipeline was successful
2026-04-08 01:32:59 +02:00
80 changed files with 783 additions and 699 deletions

99
server/Cargo.lock generated
View File

@@ -95,7 +95,7 @@ dependencies = [
"either", "either",
"k256", "k256",
"once_cell", "once_cell",
"rand 0.8.5", "rand 0.8.6",
"secp256k1", "secp256k1",
"serde", "serde",
"serde_json", "serde_json",
@@ -516,7 +516,7 @@ dependencies = [
"alloy-signer", "alloy-signer",
"async-trait", "async-trait",
"k256", "k256",
"rand 0.8.5", "rand 0.8.6",
"thiserror 2.0.18", "thiserror 2.0.18",
] ]
@@ -697,13 +697,25 @@ dependencies = [
name = "arbiter-crypto" name = "arbiter-crypto"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"alloy",
"chrono", "chrono",
"hmac",
"memsafe", "memsafe",
"ml-dsa", "ml-dsa",
"rand 0.10.1", "rand 0.10.1",
"x-wing", "x-wing",
] ]
[[package]]
name = "arbiter-macros"
version = "0.1.0"
dependencies = [
"arbiter-crypto",
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]] [[package]]
name = "arbiter-proto" name = "arbiter-proto"
version = "0.1.0" version = "0.1.0"
@@ -738,6 +750,7 @@ dependencies = [
"alloy", "alloy",
"anyhow", "anyhow",
"arbiter-crypto", "arbiter-crypto",
"arbiter-macros",
"arbiter-proto", "arbiter-proto",
"arbiter-tokens-registry", "arbiter-tokens-registry",
"argon2", "argon2",
@@ -971,7 +984,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c"
dependencies = [ dependencies = [
"num-traits", "num-traits",
"rand 0.8.5", "rand 0.8.6",
] ]
[[package]] [[package]]
@@ -981,7 +994,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185"
dependencies = [ dependencies = [
"num-traits", "num-traits",
"rand 0.8.5", "rand 0.8.6",
] ]
[[package]] [[package]]
@@ -991,7 +1004,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a"
dependencies = [ dependencies = [
"num-traits", "num-traits",
"rand 0.8.5", "rand 0.8.6",
] ]
[[package]] [[package]]
@@ -1097,9 +1110,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]] [[package]]
name = "aws-lc-rs" name = "aws-lc-rs"
version = "1.16.2" version = "1.16.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f"
dependencies = [ dependencies = [
"aws-lc-sys", "aws-lc-sys",
"untrusted 0.7.1", "untrusted 0.7.1",
@@ -1108,9 +1121,9 @@ dependencies = [
[[package]] [[package]]
name = "aws-lc-sys" name = "aws-lc-sys"
version = "0.39.1" version = "0.40.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7"
dependencies = [ dependencies = [
"cc", "cc",
"cmake", "cmake",
@@ -1248,9 +1261,9 @@ dependencies = [
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.11.0" version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
[[package]] [[package]]
name = "bitvec" name = "bitvec"
@@ -1521,11 +1534,12 @@ checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
[[package]] [[package]]
name = "const_format" name = "const_format"
version = "0.2.35" version = "0.2.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" checksum = "4481a617ad9a412be3b97c5d403fef8ed023103368908b9c50af598ff467cc1e"
dependencies = [ dependencies = [
"const_format_proc_macros", "const_format_proc_macros",
"konst",
] ]
[[package]] [[package]]
@@ -2242,7 +2256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"rand 0.8.5", "rand 0.8.6",
"rustc-hex", "rustc-hex",
"static_assertions", "static_assertions",
] ]
@@ -2661,9 +2675,9 @@ dependencies = [
[[package]] [[package]]
name = "hyper-rustls" name = "hyper-rustls"
version = "0.27.8" version = "0.27.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2b52f86d1d4bc0d6b4e6826d960b1b333217e07d36b882dca570a5e1c48895b" checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f"
dependencies = [ dependencies = [
"http", "http",
"hyper", "hyper",
@@ -3126,6 +3140,21 @@ dependencies = [
"rand_core 0.10.1", "rand_core 0.10.1",
] ]
[[package]]
name = "konst"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb"
dependencies = [
"konst_macro_rules",
]
[[package]]
name = "konst_macro_rules"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37"
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.5.0" version = "1.5.0"
@@ -4062,9 +4091,9 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.8.5" version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
dependencies = [ dependencies = [
"libc", "libc",
"rand_chacha 0.3.1", "rand_chacha 0.3.1",
@@ -4377,7 +4406,7 @@ dependencies = [
"parity-scale-codec", "parity-scale-codec",
"primitive-types", "primitive-types",
"proptest", "proptest",
"rand 0.8.5", "rand 0.8.6",
"rand 0.9.4", "rand 0.9.4",
"rlp", "rlp",
"ruint-macro", "ruint-macro",
@@ -4516,9 +4545,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
[[package]] [[package]]
name = "rustls-webpki" name = "rustls-webpki"
version = "0.103.11" version = "0.103.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20a6af516fea4b20eccceaf166e8aa666ac996208e8a644ce3ef5aa783bc7cd4" checksum = "8279bb85272c9f10811ae6a6c547ff594d6a7f3c6c6b02ee9726d1d0dcfcdd06"
dependencies = [ dependencies = [
"aws-lc-rs", "aws-lc-rs",
"ring", "ring",
@@ -4623,7 +4652,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252"
dependencies = [ dependencies = [
"bitcoin_hashes", "bitcoin_hashes",
"rand 0.8.5", "rand 0.8.6",
"secp256k1-sys", "secp256k1-sys",
"serde", "serde",
] ]
@@ -5296,9 +5325,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.51.1" version = "1.52.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c" checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6"
dependencies = [ dependencies = [
"bytes", "bytes",
"libc", "libc",
@@ -5712,9 +5741,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.23.0" version = "1.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76"
dependencies = [ dependencies = [
"js-sys", "js-sys",
"wasm-bindgen", "wasm-bindgen",
@@ -5774,11 +5803,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]] [[package]]
name = "wasip2" name = "wasip2"
version = "1.0.2+wasi-0.2.9" version = "1.0.3+wasi-0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"
dependencies = [ dependencies = [
"wit-bindgen", "wit-bindgen 0.57.1",
] ]
[[package]] [[package]]
@@ -5787,7 +5816,7 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
dependencies = [ dependencies = [
"wit-bindgen", "wit-bindgen 0.51.0",
] ]
[[package]] [[package]]
@@ -5915,9 +5944,9 @@ dependencies = [
[[package]] [[package]]
name = "webpki-root-certs" name = "webpki-root-certs"
version = "1.0.6" version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c"
dependencies = [ dependencies = [
"rustls-pki-types", "rustls-pki-types",
] ]
@@ -6261,6 +6290,12 @@ dependencies = [
"wit-bindgen-rust-macro", "wit-bindgen-rust-macro",
] ]
[[package]]
name = "wit-bindgen"
version = "0.57.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
[[package]] [[package]]
name = "wit-bindgen-core" name = "wit-bindgen-core"
version = "0.51.0" version = "0.51.0"

View File

@@ -48,4 +48,4 @@ ml-dsa = { version = "0.1.0-rc.8", features = ["zeroize"] }
base64 = "0.22.1" base64 = "0.22.1"
kameo = {git = "https://github.com/hdbg/kameo.git", rev = "805b417"} kameo = {git = "https://github.com/hdbg/kameo.git", rev = "805b417"}
kameo_actors = {git = "https://github.com/hdbg/kameo.git", rev = "805b417"} kameo_actors = {git = "https://github.com/hdbg/kameo.git", rev = "805b417"}
hmac = "0.12.1"

View File

@@ -1,3 +1,7 @@
use crate::{
storage::StorageError,
transport::{ClientTransport, next_request_id},
};
use arbiter_crypto::authn::{self, CLIENT_CONTEXT, SigningKey}; use arbiter_crypto::authn::{self, CLIENT_CONTEXT, SigningKey};
use arbiter_proto::{ use arbiter_proto::{
ClientMetadata, ClientMetadata,
@@ -15,12 +19,8 @@ use arbiter_proto::{
shared::ClientInfo as ProtoClientInfo, shared::ClientInfo as ProtoClientInfo,
}, },
}; };
use chrono::DateTime;
use crate::{ use chrono::DateTime;
storage::StorageError,
transport::{ClientTransport, next_request_id},
};
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum AuthError { pub enum AuthError {

View File

@@ -1,8 +1,8 @@
use std::io::{self, Write};
use arbiter_client::ArbiterClient; use arbiter_client::ArbiterClient;
use arbiter_proto::{ClientMetadata, url::ArbiterUrl}; use arbiter_proto::{ClientMetadata, url::ArbiterUrl};
use std::io::{self, Write};
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
println!("Testing connection to Arbiter server..."); println!("Testing connection to Arbiter server...");

View File

@@ -1,21 +1,20 @@
use arbiter_crypto::authn::SigningKey; #[cfg(feature = "evm")]
use arbiter_proto::{ use crate::wallets::evm::ArbiterEvmWallet;
ClientMetadata, proto::arbiter_service_client::ArbiterServiceClient, url::ArbiterUrl,
};
use std::sync::Arc;
use tokio::sync::{Mutex, mpsc};
use tokio_stream::wrappers::ReceiverStream;
use tonic::transport::ClientTlsConfig;
use crate::{ use crate::{
StorageError, StorageError,
auth::{AuthError, authenticate}, auth::{AuthError, authenticate},
storage::{FileSigningKeyStorage, SigningKeyStorage}, storage::{FileSigningKeyStorage, SigningKeyStorage},
transport::{BUFFER_LENGTH, ClientTransport}, transport::{BUFFER_LENGTH, ClientTransport},
}; };
use arbiter_crypto::authn::SigningKey;
use arbiter_proto::{
ClientMetadata, proto::arbiter_service_client::ArbiterServiceClient, url::ArbiterUrl,
};
#[cfg(feature = "evm")] use std::sync::Arc;
use crate::wallets::evm::ArbiterEvmWallet; use tokio::sync::{Mutex, mpsc};
use tokio_stream::wrappers::ReceiverStream;
use tonic::transport::ClientTlsConfig;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum Error { pub enum Error {

View File

@@ -1,5 +1,6 @@
use arbiter_crypto::authn::SigningKey; use arbiter_crypto::authn::SigningKey;
use arbiter_proto::home_path; use arbiter_proto::home_path;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]

View File

@@ -1,4 +1,5 @@
use arbiter_proto::proto::client::{ClientRequest, ClientResponse}; use arbiter_proto::proto::client::{ClientRequest, ClientResponse};
use std::sync::atomic::{AtomicI32, Ordering}; use std::sync::atomic::{AtomicI32, Ordering};
use tokio::sync::mpsc; use tokio::sync::mpsc;

View File

@@ -1,13 +1,4 @@
use alloy::{ use crate::transport::{ClientTransport, next_request_id};
consensus::SignableTransaction,
network::TxSigner,
primitives::{Address, B256, ChainId, Signature},
signers::{Error, Result, Signer},
};
use async_trait::async_trait;
use std::sync::Arc;
use tokio::sync::Mutex;
use arbiter_proto::proto::{ use arbiter_proto::proto::{
client::{ client::{
ClientRequest, ClientRequest,
@@ -25,7 +16,15 @@ use arbiter_proto::proto::{
shared::evm::TransactionEvalError, shared::evm::TransactionEvalError,
}; };
use crate::transport::{ClientTransport, next_request_id}; use alloy::{
consensus::SignableTransaction,
network::TxSigner,
primitives::{Address, B256, ChainId, Signature},
signers::{Error, Result, Signer},
};
use async_trait::async_trait;
use std::sync::Arc;
use tokio::sync::Mutex;
/// A typed error payload returned by [`ArbiterEvmWallet`] transaction signing. /// A typed error payload returned by [`ArbiterEvmWallet`] transaction signing.
/// ///

View File

@@ -7,6 +7,8 @@ edition = "2024"
ml-dsa = {workspace = true, optional = true } ml-dsa = {workspace = true, optional = true }
rand = {workspace = true, optional = true} rand = {workspace = true, optional = true}
memsafe = {version = "0.4.0", optional = true} memsafe = {version = "0.4.0", optional = true}
hmac.workspace = true
alloy.workspace = true
x-wing = { version = "0.1.0-rc.0", features = ["zeroize"] } x-wing = { version = "0.1.0-rc.0", features = ["zeroize"] }
chrono.workspace = true chrono.workspace = true

View File

@@ -1,6 +1,5 @@
use std::hash::Hash;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use hmac::digest::Digest;
use ml_dsa::{ use ml_dsa::{
EncodedVerifyingKey, Error, KeyGen, MlDsa87, Seed, Signature as MlDsaSignature, EncodedVerifyingKey, Error, KeyGen, MlDsa87, Seed, Signature as MlDsaSignature,
SigningKey as MlDsaSigningKey, VerifyingKey as MlDsaVerifyingKey, signature::Keypair as _, SigningKey as MlDsaSigningKey, VerifyingKey as MlDsaVerifyingKey, signature::Keypair as _,
@@ -58,9 +57,9 @@ pub type KeyParams = MlDsa87;
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct PublicKey(Box<MlDsaVerifyingKey<KeyParams>>); pub struct PublicKey(Box<MlDsaVerifyingKey<KeyParams>>);
impl Hash for PublicKey { impl crate::hashing::Hashable for PublicKey {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { fn hash<H: Digest>(&self, hasher: &mut H) {
self.to_bytes().hash(state); hasher.update(self.to_bytes());
} }
} }
@@ -72,7 +71,7 @@ pub struct SigningKey(Box<MlDsaSigningKey<KeyParams>>);
impl PublicKey { impl PublicKey {
pub fn to_bytes(&self) -> Vec<u8> { pub fn to_bytes(&self) -> Vec<u8> {
self.0.encode().to_vec() self.0.encode().0.to_vec()
} }
pub fn verify(&self, challenge: &AuthChallenge, context: &[u8], signature: &Signature) -> bool { pub fn verify(&self, challenge: &AuthChallenge, context: &[u8], signature: &Signature) -> bool {
@@ -84,7 +83,7 @@ impl PublicKey {
impl Signature { impl Signature {
pub fn to_bytes(&self) -> Vec<u8> { pub fn to_bytes(&self) -> Vec<u8> {
self.0.encode().to_vec() self.0.encode().0.to_vec()
} }
} }

View File

@@ -1,21 +1,26 @@
use hmac::digest::Digest;
use std::collections::HashSet; use std::collections::HashSet;
pub use hmac::digest::Digest;
/// Deterministically hash a value by feeding its fields into the hasher in a consistent order. /// Deterministically hash a value by feeding its fields into the hasher in a consistent order.
#[diagnostic::on_unimplemented(
note = "for local types consider adding `#[derive(arbiter_macros::Hashable)]` to your `{Self}` type",
note = "for types from other crates check whether the crate offers a `Hashable` implementation"
)]
pub trait Hashable { pub trait Hashable {
fn hash<H: Digest>(&self, hasher: &mut H); fn hash<H: Digest>(&self, hasher: &mut H);
} }
macro_rules! impl_numeric { macro_rules! impl_numeric {
($($t:ty),*) => { ($($t:ty),*) => {
$( $(
impl Hashable for $t { impl Hashable for $t {
fn hash<H: Digest>(&self, hasher: &mut H) { fn hash<H: Digest>(&self, hasher: &mut H) {
hasher.update(&self.to_be_bytes()); hasher.update(&self.to_be_bytes());
}
} }
} )*
)* };
};
} }
impl_numeric!(u8, u16, u32, u64, i8, i16, i32, i64); impl_numeric!(u8, u16, u32, u64, i8, i16, i32, i64);

View File

@@ -1,6 +1,6 @@
#[cfg(feature = "authn")] #[cfg(feature = "authn")]
pub mod authn; pub mod authn;
pub mod hashing;
#[cfg(feature = "safecell")] #[cfg(feature = "safecell")]
pub mod safecell; pub mod safecell;

View File

@@ -1,7 +1,9 @@
use std::ops::{Deref, DerefMut};
use std::{any::type_name, fmt};
use memsafe::MemSafe; use memsafe::MemSafe;
use std::{
any::type_name,
fmt,
ops::{Deref, DerefMut},
};
pub trait SafeCellHandle<T> { pub trait SafeCellHandle<T> {
type CellRead<'a>: Deref<Target = T> type CellRead<'a>: Deref<Target = T>

View File

@@ -0,0 +1,18 @@
[package]
name = "arbiter-macros"
version = "0.1.0"
edition = "2024"
[lib]
proc-macro = true
[dependencies]
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "2.0", features = ["derive", "fold", "full", "visit-mut"] }
[dev-dependencies]
arbiter-crypto = { path = "../arbiter-crypto" }
[lints]
workspace = true

View File

@@ -0,0 +1,131 @@
use crate::utils::{HASHABLE_TRAIT_PATH, HMAC_DIGEST_PATH};
use proc_macro2::{Span, TokenStream, TokenTree};
use quote::quote;
use syn::{DataStruct, DeriveInput, Fields, Generics, Index, parse_quote, spanned::Spanned};
pub(crate) fn derive(input: &DeriveInput) -> TokenStream {
match &input.data {
syn::Data::Struct(struct_data) => hashable_struct(input, struct_data),
syn::Data::Enum(_) => {
syn::Error::new_spanned(input, "Hashable can currently be derived only for structs")
.to_compile_error()
}
syn::Data::Union(_) => {
syn::Error::new_spanned(input, "Hashable cannot be derived for unions")
.to_compile_error()
}
}
}
fn hashable_struct(input: &DeriveInput, struct_data: &syn::DataStruct) -> TokenStream {
let ident = &input.ident;
let hashable_trait = HASHABLE_TRAIT_PATH.to_path();
let hmac_digest = HMAC_DIGEST_PATH.to_path();
let generics = add_hashable_bounds(input.generics.clone(), &hashable_trait);
let field_accesses = collect_field_accesses(struct_data);
let hash_calls = build_hash_calls(&field_accesses, &hashable_trait);
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
quote! {
#[automatically_derived]
impl #impl_generics #hashable_trait for #ident #ty_generics #where_clause {
fn hash<H: #hmac_digest>(&self, hasher: &mut H) {
#(#hash_calls)*
}
}
}
}
fn add_hashable_bounds(mut generics: Generics, hashable_trait: &syn::Path) -> Generics {
for type_param in generics.type_params_mut() {
type_param.bounds.push(parse_quote!(#hashable_trait));
}
generics
}
struct FieldAccess {
access: TokenStream,
span: Span,
}
fn collect_field_accesses(struct_data: &DataStruct) -> Vec<FieldAccess> {
match &struct_data.fields {
Fields::Named(fields) => {
// Keep deterministic alphabetical order for named fields.
// Do not remove this sort, because it keeps hash output stable regardless of source order.
let mut named_fields = fields
.named
.iter()
.map(|field| {
let name = field
.ident
.as_ref()
.expect("Fields::Named(fields) must have names")
.clone();
(name.to_string(), name)
})
.collect::<Vec<_>>();
named_fields.sort_by(|a, b| a.0.cmp(&b.0));
named_fields
.into_iter()
.map(|(_, name)| FieldAccess {
access: quote! { #name },
span: name.span(),
})
.collect()
}
Fields::Unnamed(fields) => fields
.unnamed
.iter()
.enumerate()
.map(|(i, field)| FieldAccess {
access: {
let index = Index::from(i);
quote! { #index }
},
span: field.ty.span(),
})
.collect(),
Fields::Unit => Vec::new(),
}
}
fn build_hash_calls(
field_accesses: &[FieldAccess],
hashable_trait: &syn::Path,
) -> Vec<TokenStream> {
field_accesses
.iter()
.map(|field| {
let access = &field.access;
let call = quote! {
#hashable_trait::hash(&self.#access, hasher);
};
respan(call, field.span)
})
.collect()
}
/// Recursively set span on all tokens, including interpolated ones.
fn respan(tokens: TokenStream, span: Span) -> TokenStream {
tokens
.into_iter()
.map(|tt| match tt {
TokenTree::Group(g) => {
let mut new = proc_macro2::Group::new(g.delimiter(), respan(g.stream(), span));
new.set_span(span);
TokenTree::Group(new)
}
mut other => {
other.set_span(span);
other
}
})
.collect()
}

View File

@@ -0,0 +1,10 @@
use syn::{DeriveInput, parse_macro_input};
mod hashable;
mod utils;
#[proc_macro_derive(Hashable)]
pub fn derive_hashable(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as DeriveInput);
hashable::derive(&input).into()
}

View File

@@ -0,0 +1,19 @@
pub(crate) struct ToPath(pub(crate) &'static str);
impl ToPath {
pub(crate) fn to_path(&self) -> syn::Path {
syn::parse_str(self.0).expect("Invalid path")
}
}
macro_rules! ensure_path {
($path:path) => {{
#[cfg(test)]
#[expect(unused_imports)]
use $path as _;
ToPath(stringify!($path))
}};
}
pub(crate) const HASHABLE_TRAIT_PATH: ToPath = ensure_path!(::arbiter_crypto::hashing::Hashable);
pub(crate) const HMAC_DIGEST_PATH: ToPath = ensure_path!(::arbiter_crypto::hashing::Digest);

View File

@@ -54,11 +54,9 @@
//! as a closed outbound channel. //! as a closed outbound channel.
//! - [`Bi::recv`] returns `None` when the underlying transport closes. //! - [`Bi::recv`] returns `None` when the underlying transport closes.
//! - Message translation is intentionally out of scope for this module. //! - Message translation is intentionally out of scope for this module.
use std::marker::PhantomData;
use async_trait::async_trait; use async_trait::async_trait;
use kameo::{error::Infallible, prelude::*}; use kameo::{error::Infallible, prelude::*};
use std::marker::PhantomData;
/// Errors returned by transport adapters implementing [`Bi`]. /// Errors returned by transport adapters implementing [`Bi`].
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]

View File

@@ -1,10 +1,10 @@
use super::{Bi, Receiver, Sender};
use async_trait::async_trait; use async_trait::async_trait;
use futures::StreamExt; use futures::StreamExt;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use tokio_stream::wrappers::ReceiverStream; use tokio_stream::wrappers::ReceiverStream;
use super::{Bi, Receiver, Sender};
pub struct GrpcSender<Outbound> { pub struct GrpcSender<Outbound> {
tx: mpsc::Sender<Result<Outbound, tonic::Status>>, tx: mpsc::Sender<Result<Outbound, tonic::Status>>,
} }

View File

@@ -1,7 +1,6 @@
use std::fmt::Display;
use base64::{Engine as _, prelude::BASE64_URL_SAFE}; use base64::{Engine as _, prelude::BASE64_URL_SAFE};
use rustls_pki_types::CertificateDer; use rustls_pki_types::CertificateDer;
use std::fmt::Display;
const ARBITER_URL_SCHEME: &str = "arbiter"; const ARBITER_URL_SCHEME: &str = "arbiter";
const CERT_QUERY_KEY: &str = "cert"; const CERT_QUERY_KEY: &str = "cert";

View File

@@ -18,6 +18,7 @@ diesel-async = { version = "0.8.0", features = [
] } ] }
arbiter-proto.path = "../arbiter-proto" arbiter-proto.path = "../arbiter-proto"
arbiter-crypto.path = "../arbiter-crypto" arbiter-crypto.path = "../arbiter-crypto"
arbiter-macros.path = "../arbiter-macros"
tracing.workspace = true tracing.workspace = true
tracing-subscriber = { version = "0.3", features = ["env-filter"] } tracing-subscriber = { version = "0.3", features = ["env-filter"] }
tonic.workspace = true tonic.workspace = true
@@ -44,7 +45,7 @@ restructed = "0.2.2"
strum = { version = "0.28.0", features = ["derive"] } strum = { version = "0.28.0", features = ["derive"] }
pem = "3.0.6" pem = "3.0.6"
sha2.workspace = true sha2.workspace = true
hmac = "0.12" hmac.workspace = true
spki.workspace = true spki.workspace = true
alloy.workspace = true alloy.workspace = true
prost-types.workspace = true prost-types.workspace = true

View File

@@ -1,13 +1,13 @@
use crate::db::{self, DatabasePool, schema};
use arbiter_proto::{BOOTSTRAP_PATH, home_path}; use arbiter_proto::{BOOTSTRAP_PATH, home_path};
use diesel::QueryDsl; use diesel::QueryDsl;
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
use kameo::{Actor, messages}; use kameo::{Actor, messages};
use rand::{RngExt, distr::Alphanumeric, make_rng, rngs::StdRng}; use rand::{RngExt, distr::Alphanumeric, make_rng, rngs::StdRng};
use subtle::ConstantTimeEq as _; use subtle::ConstantTimeEq as _;
use thiserror::Error; use thiserror::Error;
use crate::db::{self, DatabasePool, schema};
const TOKEN_LENGTH: usize = 64; const TOKEN_LENGTH: usize = 64;
pub async fn generate_token() -> Result<String, std::io::Error> { pub async fn generate_token() -> Result<String, std::io::Error> {

View File

@@ -1,11 +1,3 @@
use alloy::{consensus::TxEip1559, primitives::Address, signers::Signature};
use diesel::{
ExpressionMethods, OptionalExtension as _, QueryDsl, SelectableHelper as _, dsl::insert_into,
};
use diesel_async::RunQueryDsl;
use kameo::{Actor, actor::ActorRef, messages};
use rand::{SeedableRng, rng, rngs::StdRng};
use crate::{ use crate::{
actors::vault::{CreateNew, Decrypt, Vault}, actors::vault::{CreateNew, Decrypt, Vault},
crypto::integrity, crypto::integrity,
@@ -24,6 +16,14 @@ use crate::{
}; };
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use alloy::{consensus::TxEip1559, primitives::Address, signers::Signature};
use diesel::{
ExpressionMethods, OptionalExtension as _, QueryDsl, SelectableHelper as _, dsl::insert_into,
};
use diesel_async::RunQueryDsl;
use kameo::{Actor, actor::ActorRef, messages};
use rand::{SeedableRng, rng, rngs::StdRng};
pub use crate::evm::safe_signer; pub use crate::evm::safe_signer;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]

View File

@@ -1,11 +1,3 @@
use std::ops::ControlFlow;
use kameo::{
Actor, messages,
prelude::{ActorId, ActorRef, ActorStopReason, Context, WeakActorRef},
reply::ReplySender,
};
use crate::{ use crate::{
actors::flow_coordinator::ApprovalError, actors::flow_coordinator::ApprovalError,
peers::{ peers::{
@@ -14,6 +6,13 @@ use crate::{
}, },
}; };
use kameo::{
Actor, messages,
prelude::{ActorId, ActorRef, ActorStopReason, Context, WeakActorRef},
reply::ReplySender,
};
use std::ops::ControlFlow;
pub struct Args { pub struct Args {
pub client: ClientProfile, pub client: ClientProfile,
pub user_agents: Vec<ActorRef<UserAgentSession>>, pub user_agents: Vec<ActorRef<UserAgentSession>>,

View File

@@ -1,4 +1,10 @@
use std::{collections::HashMap, ops::ControlFlow}; use crate::{
actors::{
flow_coordinator::client_connect_approval::ClientApprovalController,
useragent_registry::{GetConnected, UserAgentRegistry},
},
peers::client::{ClientProfile, session::ClientSession},
};
use kameo::{ use kameo::{
Actor, Actor,
@@ -7,16 +13,9 @@ use kameo::{
prelude::{ActorStopReason, Context, WeakActorRef}, prelude::{ActorStopReason, Context, WeakActorRef},
reply::DelegatedReply, reply::DelegatedReply,
}; };
use std::{collections::HashMap, ops::ControlFlow};
use tracing::info; use tracing::info;
use crate::{
actors::{
flow_coordinator::client_connect_approval::ClientApprovalController,
useragent_registry::{GetConnected, UserAgentRegistry},
},
peers::client::{ClientProfile, session::ClientSession},
};
pub mod client_connect_approval; pub mod client_connect_approval;
pub struct FlowCoordinator { pub struct FlowCoordinator {

View File

@@ -1,23 +1,20 @@
use kameo::actor::{ActorRef, Spawn};
use kameo_actors::{DeliveryStrategy, message_bus::MessageBus};
use thiserror::Error;
use crate::{ use crate::{
actors::{ actors::{
bootstrap::Bootstrapper, bootstrap::Bootstrapper, evm::EvmActor, flow_coordinator::FlowCoordinator,
evm::EvmActor, useragent_registry::UserAgentRegistry, vault::Vault,
flow_coordinator::FlowCoordinator,
useragent_registry::UserAgentRegistry,
vault::Vault,
}, },
db, db,
}; };
use kameo::actor::{ActorRef, Spawn};
use kameo_actors::{DeliveryStrategy, message_bus::MessageBus};
use thiserror::Error;
pub mod bootstrap; pub mod bootstrap;
pub mod evm; pub mod evm;
pub mod flow_coordinator; pub mod flow_coordinator;
pub mod vault;
pub mod useragent_registry; pub mod useragent_registry;
pub mod vault;
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum SpawnError { pub enum SpawnError {

View File

@@ -1,4 +1,4 @@
use std::{collections::HashMap, ops::ControlFlow}; use crate::peers::user_agent::UserAgentSession;
use kameo::{ use kameo::{
Actor, Actor,
@@ -7,10 +7,9 @@ use kameo::{
messages, messages,
prelude::{ActorStopReason, Context, WeakActorRef}, prelude::{ActorStopReason, Context, WeakActorRef},
}; };
use std::{collections::HashMap, ops::ControlFlow};
use tracing::info; use tracing::info;
use crate::peers::user_agent::UserAgentSession;
#[derive(Default)] #[derive(Default)]
pub struct UserAgentRegistry { pub struct UserAgentRegistry {
connected: HashMap<ActorId, ActorRef<UserAgentSession>>, connected: HashMap<ActorId, ActorRef<UserAgentSession>>,
@@ -32,7 +31,11 @@ impl Actor for UserAgentRegistry {
_: ActorStopReason, _: ActorStopReason,
) -> Result<ControlFlow<ActorStopReason>, Self::Error> { ) -> Result<ControlFlow<ActorStopReason>, Self::Error> {
if self.connected.remove(&id).is_some() { if self.connected.remove(&id).is_some() {
info!(?id, actor = "UserAgentRegistry", event = "useragent.disconnected"); info!(
?id,
actor = "UserAgentRegistry",
event = "useragent.disconnected"
);
} }
Ok(ControlFlow::Continue(())) Ok(ControlFlow::Continue(()))
} }

View File

@@ -1,3 +1,17 @@
use crate::{
crypto::{
KeyCell, derive_key,
encryption::v1::{self, Nonce},
integrity::v1::HmacSha256,
},
db::{
self,
models::{self, RootKeyHistory},
schema::{self},
},
};
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use chrono::Utc; use chrono::Utc;
use diesel::{ use diesel::{
ExpressionMethods as _, OptionalExtension, QueryDsl, SelectableHelper, ExpressionMethods as _, OptionalExtension, QueryDsl, SelectableHelper,
@@ -10,18 +24,6 @@ use kameo_actors::message_bus::{MessageBus, Publish};
use strum::{EnumDiscriminants, IntoDiscriminant}; use strum::{EnumDiscriminants, IntoDiscriminant};
use tracing::{error, info}; use tracing::{error, info};
use crate::crypto::{
KeyCell, derive_key,
encryption::v1::{self, Nonce},
integrity::v1::HmacSha256,
};
use crate::db::{
self,
models::{self, RootKeyHistory},
schema::{self},
};
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
pub mod events { pub mod events {
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@@ -213,7 +215,7 @@ impl Vault {
}); });
info!("Vault bootstrapped successfully"); info!("Vault bootstrapped successfully");
self.events.tell(Publish(events::Bootstrapped)).await; let _ = self.events.tell(Publish(events::Bootstrapped)).await;
Ok(()) Ok(())
} }
@@ -269,7 +271,7 @@ impl Vault {
}); });
info!("Vault unsealed successfully"); info!("Vault unsealed successfully");
self.events.tell(Publish(events::Unsealed)).await; let _ = self.events.tell(Publish(events::Unsealed)).await;
Ok(()) Ok(())
} }
@@ -399,7 +401,7 @@ impl Vault {
self.state = State::Sealed { self.state = State::Sealed {
root_key_history_id: *root_key_history_id, root_key_history_id: *root_key_history_id,
}; };
self.events.tell(Publish(events::VaultResealed)).await; let _ = self.events.tell(Publish(events::VaultResealed)).await;
Ok(()) Ok(())
} }
} }

View File

@@ -1,13 +1,12 @@
use std::sync::Arc;
use thiserror::Error;
use crate::{ use crate::{
actors::GlobalActors, actors::GlobalActors,
context::tls::TlsManager, context::tls::TlsManager,
db::{self}, db::{self},
}; };
use std::sync::Arc;
use thiserror::Error;
pub mod tls; pub mod tls;
#[derive(Error, Debug)] #[derive(Error, Debug)]

View File

@@ -1,17 +1,3 @@
use std::{net::Ipv4Addr, string::FromUtf8Error};
use diesel::{ExpressionMethods as _, QueryDsl, SelectableHelper as _};
use diesel_async::{AsyncConnection, RunQueryDsl};
use pem::Pem;
use rcgen::{
BasicConstraints, Certificate, CertificateParams, CertifiedIssuer, DistinguishedName, DnType,
IsCa, Issuer, KeyPair, KeyUsagePurpose, SanType,
};
use rustls::pki_types::pem::PemObject;
use thiserror::Error;
use tonic::transport::CertificateDer;
use crate::db::{ use crate::db::{
self, self,
models::{NewTlsHistory, TlsHistory}, models::{NewTlsHistory, TlsHistory},
@@ -21,6 +7,18 @@ use crate::db::{
}, },
}; };
use diesel::{ExpressionMethods as _, QueryDsl, SelectableHelper as _};
use diesel_async::{AsyncConnection, RunQueryDsl};
use pem::Pem;
use rcgen::{
BasicConstraints, Certificate, CertificateParams, CertifiedIssuer, DistinguishedName, DnType,
IsCa, Issuer, KeyPair, KeyUsagePurpose, SanType,
};
use rustls::pki_types::pem::PemObject;
use std::{net::Ipv4Addr, string::FromUtf8Error};
use thiserror::Error;
use tonic::transport::CertificateDer;
const ENCODE_CONFIG: pem::EncodeConfig = { const ENCODE_CONFIG: pem::EncodeConfig = {
let line_ending = match cfg!(target_family = "windows") { let line_ending = match cfg!(target_family = "windows") {
true => pem::LineEnding::CRLF, true => pem::LineEnding::CRLF,

View File

@@ -1,5 +1,4 @@
use argon2::password_hash::Salt as ArgonSalt; use argon2::password_hash::Salt as ArgonSalt;
use rand::{ use rand::{
Rng as _, SeedableRng, Rng as _, SeedableRng,
rngs::{StdRng, SysRng}, rngs::{StdRng, SysRng},
@@ -63,7 +62,7 @@ mod tests {
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
#[test] #[test]
pub fn derive_seal_key_deterministic() { fn derive_seal_key_deterministic() {
static PASSWORD: &[u8] = b"password"; static PASSWORD: &[u8] = b"password";
let password = SafeCell::new(PASSWORD.to_vec()); let password = SafeCell::new(PASSWORD.to_vec());
let password2 = SafeCell::new(PASSWORD.to_vec()); let password2 = SafeCell::new(PASSWORD.to_vec());
@@ -79,7 +78,7 @@ mod tests {
} }
#[test] #[test]
pub fn successful_derive() { fn successful_derive() {
static PASSWORD: &[u8] = b"password"; static PASSWORD: &[u8] = b"password";
let password = SafeCell::new(PASSWORD.to_vec()); let password = SafeCell::new(PASSWORD.to_vec());
let salt = generate_salt(); let salt = generate_salt();
@@ -93,7 +92,7 @@ mod tests {
#[test] #[test]
// We should fuzz this // We should fuzz this
pub fn test_nonce_increment() { fn test_nonce_increment() {
let mut nonce = Nonce([0u8; NONCE_LENGTH]); let mut nonce = Nonce([0u8; NONCE_LENGTH]);
nonce.increment(); nonce.increment();

View File

@@ -1,25 +1,18 @@
use crate::{ use crate::{
actors::vault::{self, GetState}, actors::vault::{self, GetState, SignIntegrity, Vault, VerifyIntegrity},
crypto::integrity::hashing::Hashable,
};
use hmac::Hmac;
use sha2::Sha256;
use diesel::{ExpressionMethods as _, QueryDsl, dsl::insert_into, sqlite::Sqlite};
use diesel_async::{AsyncConnection, RunQueryDsl};
use kameo::{actor::ActorRef, error::SendError};
use sha2::Digest as _;
pub mod hashing;
use crate::{
actors::vault::{SignIntegrity, Vault, VerifyIntegrity},
db::{ db::{
self, self,
models::{IntegrityEnvelope, NewIntegrityEnvelope}, models::{IntegrityEnvelope, NewIntegrityEnvelope},
schema::integrity_envelope, schema::integrity_envelope,
}, },
}; };
use arbiter_crypto::hashing::Hashable;
use diesel::{ExpressionMethods as _, QueryDsl, dsl::insert_into, sqlite::Sqlite};
use diesel_async::{AsyncConnection, RunQueryDsl};
use hmac::Hmac;
use kameo::{actor::ActorRef, error::SendError};
use sha2::{Digest as _, Sha256};
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum Error { pub enum Error {
@@ -194,9 +187,7 @@ pub async fn verify_entity<E: Integrable>(
Ok(false) => Err(Error::MacMismatch { Ok(false) => Err(Error::MacMismatch {
entity_kind: E::KIND, entity_kind: E::KIND,
}), }),
Err(SendError::HandlerError(vault::Error::Sealed)) => { Err(SendError::HandlerError(vault::Error::Sealed)) => Ok(AttestationStatus::Unavailable),
Ok(AttestationStatus::Unavailable)
}
Err(_) => Err(Error::VaultSend), Err(_) => Err(Error::VaultSend),
} }
} }
@@ -212,8 +203,6 @@ mod tests {
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
use kameo::{actor::ActorRef, prelude::Spawn}; use kameo::{actor::ActorRef, prelude::Spawn};
use sha2::Digest;
use crate::{ use crate::{
actors::{ actors::{
GlobalActors, GlobalActors,
@@ -223,21 +212,12 @@ mod tests {
}; };
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use super::hashing::Hashable;
use super::{Error, Integrable, sign_entity, verify_entity}; use super::{Error, Integrable, sign_entity, verify_entity};
#[derive(Clone, arbiter_macros::Hashable)]
#[derive(Clone)]
struct DummyEntity { struct DummyEntity {
payload_version: i32, payload_version: i32,
payload: Vec<u8>, payload: Vec<u8>,
} }
impl Hashable for DummyEntity {
fn hash<H: Digest>(&self, hasher: &mut H) {
self.payload_version.hash(hasher);
self.payload.hash(hasher);
}
}
impl Integrable for DummyEntity { impl Integrable for DummyEntity {
const KIND: &'static str = "dummy_entity"; const KIND: &'static str = "dummy_entity";
} }

View File

@@ -1,4 +1,5 @@
use std::ops::Deref as _; use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use encryption::v1::{Nonce, Salt};
use argon2::{Algorithm, Argon2}; use argon2::{Algorithm, Argon2};
use chacha20poly1305::{ use chacha20poly1305::{
@@ -9,14 +10,11 @@ use rand::{
Rng as _, SeedableRng as _, Rng as _, SeedableRng as _,
rngs::{StdRng, SysRng}, rngs::{StdRng, SysRng},
}; };
use std::ops::Deref as _;
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
pub mod encryption; pub mod encryption;
pub mod integrity; pub mod integrity;
use encryption::v1::{Nonce, Salt};
pub struct KeyCell(pub SafeCell<Key>); pub struct KeyCell(pub SafeCell<Key>);
impl From<SafeCell<Key>> for KeyCell { impl From<SafeCell<Key>> for KeyCell {
fn from(value: SafeCell<Key>) -> Self { fn from(value: SafeCell<Key>) -> Self {
@@ -144,7 +142,7 @@ mod tests {
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
#[test] #[test]
pub fn encrypt_decrypt() { fn encrypt_decrypt() {
static PASSWORD: &[u8] = b"password"; static PASSWORD: &[u8] = b"password";
let password = SafeCell::new(PASSWORD.to_vec()); let password = SafeCell::new(PASSWORD.to_vec());
let salt = generate_salt(); let salt = generate_salt();

View File

@@ -5,7 +5,6 @@ use diesel_async::{
sync_connection_wrapper::SyncConnectionWrapper, sync_connection_wrapper::SyncConnectionWrapper,
}; };
use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations}; use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations};
use thiserror::Error; use thiserror::Error;
use tracing::info; use tracing::info;

View File

@@ -1,12 +1,12 @@
#![allow(unused)] #![allow(unused)]
#![allow(clippy::all)] #![allow(clippy::all)]
use crate::db::schema::{ use crate::db::schema::{
self, aead_encrypted, arbiter_settings, evm_basic_grant, evm_ether_transfer_grant, self, aead_encrypted, arbiter_settings, evm_basic_grant, evm_ether_transfer_grant,
evm_ether_transfer_grant_target, evm_ether_transfer_limit, evm_token_transfer_grant, evm_ether_transfer_grant_target, evm_ether_transfer_limit, evm_token_transfer_grant,
evm_token_transfer_log, evm_token_transfer_volume_limit, evm_transaction_log, evm_wallet, evm_token_transfer_log, evm_token_transfer_volume_limit, evm_transaction_log, evm_wallet,
integrity_envelope, root_key_history, tls_history, integrity_envelope, root_key_history, tls_history,
}; };
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use diesel::{prelude::*, sqlite::Sqlite}; use diesel::{prelude::*, sqlite::Sqlite};
use restructed::Models; use restructed::Models;

View File

@@ -1,15 +1,3 @@
pub mod abi;
pub mod safe_signer;
use alloy::{
consensus::TxEip1559,
primitives::{TxKind, U256},
};
use chrono::Utc;
use diesel::{ExpressionMethods as _, QueryDsl as _, QueryResult, insert_into, sqlite::Sqlite};
use diesel_async::{AsyncConnection, RunQueryDsl};
use kameo::actor::ActorRef;
use crate::{ use crate::{
actors::vault::Vault, actors::vault::Vault,
crypto::integrity, crypto::integrity,
@@ -27,6 +15,18 @@ use crate::{
}, },
}; };
use alloy::{
consensus::TxEip1559,
primitives::{TxKind, U256},
};
use chrono::Utc;
use diesel::{ExpressionMethods as _, QueryDsl as _, QueryResult, insert_into, sqlite::Sqlite};
use diesel_async::{AsyncConnection, RunQueryDsl};
use kameo::actor::ActorRef;
pub mod abi;
pub mod safe_signer;
pub mod policies; pub mod policies;
mod utils; mod utils;

View File

@@ -1,4 +1,8 @@
use std::fmt::Display; use crate::{
crypto::integrity::v1::Integrable,
db::models::{self, EvmBasicGrant, EvmWalletAccess},
evm::utils,
};
use alloy::primitives::{Address, Bytes, ChainId, U256}; use alloy::primitives::{Address, Bytes, ChainId, U256};
use chrono::{DateTime, Duration, Utc}; use chrono::{DateTime, Duration, Utc};
@@ -6,15 +10,9 @@ use diesel::{
ExpressionMethods as _, QueryDsl, SelectableHelper, result::QueryResult, sqlite::Sqlite, ExpressionMethods as _, QueryDsl, SelectableHelper, result::QueryResult, sqlite::Sqlite,
}; };
use diesel_async::{AsyncConnection, RunQueryDsl}; use diesel_async::{AsyncConnection, RunQueryDsl};
use std::fmt::Display;
use thiserror::Error; use thiserror::Error;
use crate::{
crypto::integrity::v1::Integrable,
db::models::{self, EvmBasicGrant, EvmWalletAccess},
evm::utils,
};
pub mod ether_transfer; pub mod ether_transfer;
pub mod token_transfers; pub mod token_transfers;
@@ -127,19 +125,19 @@ pub enum SpecificMeaning {
TokenTransfer(token_transfers::Meaning), TokenTransfer(token_transfers::Meaning),
} }
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, arbiter_macros::Hashable)]
pub struct TransactionRateLimit { pub struct TransactionRateLimit {
pub count: u32, pub count: u32,
pub window: Duration, pub window: Duration,
} }
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, arbiter_macros::Hashable)]
pub struct VolumeRateLimit { pub struct VolumeRateLimit {
pub max_volume: U256, pub max_volume: U256,
pub window: Duration, pub window: Duration,
} }
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash, arbiter_macros::Hashable)]
pub struct SharedGrantSettings { pub struct SharedGrantSettings {
pub wallet_access_id: i32, pub wallet_access_id: i32,
pub chain: ChainId, pub chain: ChainId,
@@ -200,7 +198,7 @@ pub enum SpecificGrant {
TokenTransfer(token_transfers::Settings), TokenTransfer(token_transfers::Settings),
} }
#[derive(Debug)] #[derive(Debug, arbiter_macros::Hashable)]
pub struct CombinedSettings<PolicyGrant> { pub struct CombinedSettings<PolicyGrant> {
pub shared: SharedGrantSettings, pub shared: SharedGrantSettings,
pub specific: PolicyGrant, pub specific: PolicyGrant,
@@ -219,38 +217,3 @@ impl<P: Integrable> Integrable for CombinedSettings<P> {
const KIND: &'static str = P::KIND; const KIND: &'static str = P::KIND;
const VERSION: i32 = P::VERSION; const VERSION: i32 = P::VERSION;
} }
use crate::crypto::integrity::hashing::Hashable;
impl Hashable for TransactionRateLimit {
fn hash<H: sha2::Digest>(&self, hasher: &mut H) {
self.count.hash(hasher);
self.window.hash(hasher);
}
}
impl Hashable for VolumeRateLimit {
fn hash<H: sha2::Digest>(&self, hasher: &mut H) {
self.max_volume.hash(hasher);
self.window.hash(hasher);
}
}
impl Hashable for SharedGrantSettings {
fn hash<H: sha2::Digest>(&self, hasher: &mut H) {
self.wallet_access_id.hash(hasher);
self.chain.hash(hasher);
self.valid_from.hash(hasher);
self.valid_until.hash(hasher);
self.max_gas_fee_per_gas.hash(hasher);
self.max_priority_fee_per_gas.hash(hasher);
self.rate_limit.hash(hasher);
}
}
impl<P: Hashable> Hashable for CombinedSettings<P> {
fn hash<H: sha2::Digest>(&self, hasher: &mut H) {
self.shared.hash(hasher);
self.specific.hash(hasher);
}
}

View File

@@ -1,30 +1,33 @@
use std::collections::HashMap; use super::{DatabaseID, EvalContext, EvalViolation};
use std::fmt::Display;
use alloy::primitives::{Address, U256};
use chrono::{DateTime, Duration, Utc};
use diesel::dsl::{auto_type, insert_into};
use diesel::sqlite::Sqlite;
use diesel::{ExpressionMethods, JoinOnDsl, prelude::*};
use diesel_async::{AsyncConnection, RunQueryDsl};
use crate::crypto::integrity::v1::Integrable;
use crate::db::models::{
EvmBasicGrant, EvmEtherTransferGrant, EvmEtherTransferGrantTarget, EvmEtherTransferLimit,
NewEvmEtherTransferLimit, SqliteTimestamp,
};
use crate::db::schema::{evm_basic_grant, evm_ether_transfer_limit, evm_transaction_log};
use crate::evm::policies::{
CombinedSettings, Grant, SharedGrantSettings, SpecificGrant, SpecificMeaning, VolumeRateLimit,
};
use crate::{ use crate::{
crypto::integrity::v1::Integrable,
db::models::{
EvmBasicGrant, EvmEtherTransferGrant, EvmEtherTransferGrantTarget, EvmEtherTransferLimit,
NewEvmEtherTransferLimit, SqliteTimestamp,
},
db::schema::{evm_basic_grant, evm_ether_transfer_limit, evm_transaction_log},
db::{ db::{
models::{self, NewEvmEtherTransferGrant, NewEvmEtherTransferGrantTarget}, models::{self, NewEvmEtherTransferGrant, NewEvmEtherTransferGrantTarget},
schema::{evm_ether_transfer_grant, evm_ether_transfer_grant_target}, schema::{evm_ether_transfer_grant, evm_ether_transfer_grant_target},
}, },
evm::policies::{
CombinedSettings, Grant, SharedGrantSettings, SpecificGrant, SpecificMeaning,
VolumeRateLimit,
},
evm::{policies::Policy, utils}, evm::{policies::Policy, utils},
}; };
use alloy::primitives::{Address, U256};
use chrono::{DateTime, Duration, Utc};
use diesel::{
ExpressionMethods, JoinOnDsl,
dsl::{auto_type, insert_into},
prelude::*,
sqlite::Sqlite,
};
use diesel_async::{AsyncConnection, RunQueryDsl};
use std::{collections::HashMap, fmt::Display};
#[auto_type] #[auto_type]
fn grant_join() -> _ { fn grant_join() -> _ {
evm_ether_transfer_grant::table.inner_join( evm_ether_transfer_grant::table.inner_join(
@@ -32,8 +35,6 @@ fn grant_join() -> _ {
) )
} }
use super::{DatabaseID, EvalContext, EvalViolation};
// Plain ether transfer // Plain ether transfer
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Meaning { pub struct Meaning {
@@ -52,7 +53,7 @@ impl From<Meaning> for SpecificMeaning {
} }
// A grant for ether transfers, which can be scoped to specific target addresses and volume limits // A grant for ether transfers, which can be scoped to specific target addresses and volume limits
#[derive(Debug, Clone)] #[derive(Debug, Clone, arbiter_macros::Hashable)]
pub struct Settings { pub struct Settings {
pub target: Vec<Address>, pub target: Vec<Address>,
pub limit: VolumeRateLimit, pub limit: VolumeRateLimit,
@@ -61,15 +62,6 @@ impl Integrable for Settings {
const KIND: &'static str = "EtherTransfer"; const KIND: &'static str = "EtherTransfer";
} }
use crate::crypto::integrity::hashing::Hashable;
impl Hashable for Settings {
fn hash<H: sha2::Digest>(&self, hasher: &mut H) {
self.target.hash(hasher);
self.limit.hash(hasher);
}
}
impl From<Settings> for SpecificGrant { impl From<Settings> for SpecificGrant {
fn from(val: Settings) -> SpecificGrant { fn from(val: Settings) -> SpecificGrant {
SpecificGrant::EtherTransfer(val) SpecificGrant::EtherTransfer(val)

View File

@@ -1,25 +1,26 @@
use super::{EtherTransfer, Settings};
use crate::{
db::{
self, DatabaseConnection,
models::{
EvmBasicGrant, EvmWalletAccess, NewEvmBasicGrant, NewEvmTransactionLog, SqliteTimestamp,
},
schema::{evm_basic_grant, evm_transaction_log},
},
evm::{
policies::{
CombinedSettings, EvalContext, EvalViolation, Grant, Policy, SharedGrantSettings,
VolumeRateLimit,
},
utils,
},
};
use alloy::primitives::{Address, Bytes, U256, address}; use alloy::primitives::{Address, Bytes, U256, address};
use chrono::{Duration, Utc}; use chrono::{Duration, Utc};
use diesel::{SelectableHelper, insert_into}; use diesel::{SelectableHelper, insert_into};
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
use crate::db::{
self, DatabaseConnection,
models::{
EvmBasicGrant, EvmWalletAccess, NewEvmBasicGrant, NewEvmTransactionLog, SqliteTimestamp,
},
schema::{evm_basic_grant, evm_transaction_log},
};
use crate::evm::{
policies::{
CombinedSettings, EvalContext, EvalViolation, Grant, Policy, SharedGrantSettings,
VolumeRateLimit,
},
utils,
};
use super::{EtherTransfer, Settings};
const WALLET_ACCESS_ID: i32 = 1; const WALLET_ACCESS_ID: i32 = 1;
const CHAIN_ID: u64 = 1; const CHAIN_ID: u64 = 1;
@@ -340,7 +341,7 @@ proptest::proptest! {
) { ) {
use rand::{SeedableRng, seq::SliceRandom}; use rand::{SeedableRng, seq::SliceRandom};
use sha2::Digest; use sha2::Digest;
use crate::crypto::integrity::hashing::Hashable; use arbiter_crypto::hashing::Hashable;
let addrs: Vec<Address> = raw_addrs.iter().map(|b| Address::from(*b)).collect(); let addrs: Vec<Address> = raw_addrs.iter().map(|b| Address::from(*b)).collect();
let mut shuffled = addrs.clone(); let mut shuffled = addrs.clone();

View File

@@ -1,16 +1,4 @@
use std::collections::HashMap; use super::{DatabaseID, EvalContext, EvalViolation};
use crate::db::schema::{
evm_basic_grant, evm_token_transfer_grant, evm_token_transfer_log,
evm_token_transfer_volume_limit,
};
use crate::evm::{
abi::IERC20::transferCall,
policies::{
Grant, Policy, SharedGrantSettings, SpecificGrant, SpecificMeaning, VolumeRateLimit,
},
utils,
};
use crate::{ use crate::{
crypto::integrity::Integrable, crypto::integrity::Integrable,
db::models::{ db::models::{
@@ -18,20 +6,34 @@ use crate::{
NewEvmTokenTransferGrant, NewEvmTokenTransferLog, NewEvmTokenTransferVolumeLimit, NewEvmTokenTransferGrant, NewEvmTokenTransferLog, NewEvmTokenTransferVolumeLimit,
SqliteTimestamp, SqliteTimestamp,
}, },
db::schema::{
evm_basic_grant, evm_token_transfer_grant, evm_token_transfer_log,
evm_token_transfer_volume_limit,
},
evm::policies::CombinedSettings, evm::policies::CombinedSettings,
evm::{
abi::IERC20::transferCall,
policies::{
Grant, Policy, SharedGrantSettings, SpecificGrant, SpecificMeaning, VolumeRateLimit,
},
utils,
},
}; };
use arbiter_tokens_registry::evm::nonfungible::{self, TokenInfo};
use alloy::{ use alloy::{
primitives::{Address, U256}, primitives::{Address, U256},
sol_types::SolCall, sol_types::SolCall,
}; };
use arbiter_tokens_registry::evm::nonfungible::{self, TokenInfo};
use chrono::{DateTime, Duration, Utc}; use chrono::{DateTime, Duration, Utc};
use diesel::dsl::{auto_type, insert_into}; use diesel::{
use diesel::sqlite::Sqlite; ExpressionMethods,
use diesel::{ExpressionMethods, prelude::*}; dsl::{auto_type, insert_into},
prelude::*,
sqlite::Sqlite,
};
use diesel_async::{AsyncConnection, RunQueryDsl}; use diesel_async::{AsyncConnection, RunQueryDsl};
use std::collections::HashMap;
use super::{DatabaseID, EvalContext, EvalViolation};
#[auto_type] #[auto_type]
fn grant_join() -> _ { fn grant_join() -> _ {
@@ -62,7 +64,7 @@ impl From<Meaning> for SpecificMeaning {
} }
// A grant for token transfers, which can be scoped to specific target addresses and volume limits // A grant for token transfers, which can be scoped to specific target addresses and volume limits
#[derive(Debug, Clone)] #[derive(Debug, Clone, arbiter_macros::Hashable)]
pub struct Settings { pub struct Settings {
pub token_contract: Address, pub token_contract: Address,
pub target: Option<Address>, pub target: Option<Address>,
@@ -72,16 +74,6 @@ impl Integrable for Settings {
const KIND: &'static str = "TokenTransfer"; const KIND: &'static str = "TokenTransfer";
} }
use crate::crypto::integrity::hashing::Hashable;
impl Hashable for Settings {
fn hash<H: sha2::Digest>(&self, hasher: &mut H) {
self.token_contract.hash(hasher);
self.target.hash(hasher);
self.volume_limits.hash(hasher);
}
}
impl From<Settings> for SpecificGrant { impl From<Settings> for SpecificGrant {
fn from(val: Settings) -> SpecificGrant { fn from(val: Settings) -> SpecificGrant {
SpecificGrant::TokenTransfer(val) SpecificGrant::TokenTransfer(val)

View File

@@ -1,25 +1,28 @@
use alloy::primitives::{Address, Bytes, U256, address}; use super::{Settings, TokenTransfer};
use alloy::sol_types::SolCall; use crate::{
db::{
self, DatabaseConnection,
models::{EvmBasicGrant, EvmWalletAccess, NewEvmBasicGrant, SqliteTimestamp},
schema::evm_basic_grant,
},
evm::{
abi::IERC20::transferCall,
policies::{
CombinedSettings, EvalContext, EvalViolation, Grant, Policy, SharedGrantSettings,
VolumeRateLimit,
},
utils,
},
};
use alloy::{
primitives::{Address, Bytes, U256, address},
sol_types::SolCall,
};
use chrono::{Duration, Utc}; use chrono::{Duration, Utc};
use diesel::{SelectableHelper, insert_into}; use diesel::{SelectableHelper, insert_into};
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
use crate::db::{
self, DatabaseConnection,
models::{EvmBasicGrant, EvmWalletAccess, NewEvmBasicGrant, SqliteTimestamp},
schema::evm_basic_grant,
};
use crate::evm::{
abi::IERC20::transferCall,
policies::{
CombinedSettings, EvalContext, EvalViolation, Grant, Policy, SharedGrantSettings,
VolumeRateLimit,
},
utils,
};
use super::{Settings, TokenTransfer};
// DAI on Ethereum mainnet — present in the static token registry // DAI on Ethereum mainnet — present in the static token registry
const CHAIN_ID: u64 = 1; const CHAIN_ID: u64 = 1;
const DAI: Address = address!("6B175474E89094C44Da98b954EedeAC495271d0F"); const DAI: Address = address!("6B175474E89094C44Da98b954EedeAC495271d0F");
@@ -419,7 +422,7 @@ proptest::proptest! {
) { ) {
use rand::{SeedableRng, seq::SliceRandom}; use rand::{SeedableRng, seq::SliceRandom};
use sha2::Digest; use sha2::Digest;
use crate::crypto::integrity::hashing::Hashable; use arbiter_crypto::hashing::Hashable;
let limits: Vec<VolumeRateLimit> = raw_limits let limits: Vec<VolumeRateLimit> = raw_limits
.iter() .iter()

View File

@@ -1,4 +1,4 @@
use std::sync::Mutex; use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use alloy::{ use alloy::{
consensus::SignableTransaction, consensus::SignableTransaction,
@@ -6,9 +6,9 @@ use alloy::{
primitives::{Address, B256, ChainId, Signature}, primitives::{Address, B256, ChainId, Signature},
signers::{Error, Result, Signer, SignerSync, utils::secret_key_to_address}, signers::{Error, Result, Signer, SignerSync, utils::secret_key_to_address},
}; };
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use async_trait::async_trait; use async_trait::async_trait;
use k256::ecdsa::{self, RecoveryId, SigningKey, signature::hazmat::PrehashSigner}; use k256::ecdsa::{self, RecoveryId, SigningKey, signature::hazmat::PrehashSigner};
use std::sync::Mutex;
/// An Ethereum signer that stores its secp256k1 secret key inside a /// An Ethereum signer that stores its secp256k1 secret key inside a
/// hardware-protected [`MemSafe`] cell. /// hardware-protected [`MemSafe`] cell.

View File

@@ -2,20 +2,20 @@ use alloy::primitives::U256;
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
#[error("Expected {expected} bytes but got {actual} bytes")] #[error("Expected {expected} bytes but got {actual} bytes")]
pub struct LengthError { pub(super) struct LengthError {
pub expected: usize, pub(super) expected: usize,
pub actual: usize, pub(super) actual: usize,
} }
pub fn u256_to_bytes(value: U256) -> [u8; 32] { pub(super) fn u256_to_bytes(value: U256) -> [u8; 32] {
value.to_le_bytes() value.to_le_bytes()
} }
pub fn bytes_to_u256(bytes: &[u8]) -> Option<U256> { pub(super) fn bytes_to_u256(bytes: &[u8]) -> Option<U256> {
let bytes: [u8; 32] = bytes.try_into().ok()?; let bytes: [u8; 32] = bytes.try_into().ok()?;
Some(U256::from_le_bytes(bytes)) Some(U256::from_le_bytes(bytes))
} }
pub fn try_bytes_to_u256(bytes: &[u8]) -> diesel::result::QueryResult<U256> { pub(super) fn try_bytes_to_u256(bytes: &[u8]) -> diesel::result::QueryResult<U256> {
let bytes: [u8; 32] = bytes.try_into().map_err(|_| { let bytes: [u8; 32] = bytes.try_into().map_err(|_| {
diesel::result::Error::DeserializationError(Box::new(LengthError { diesel::result::Error::DeserializationError(Box::new(LengthError {
expected: 32, expected: 32,

View File

@@ -1,3 +1,7 @@
use crate::{
grpc::request_tracker::RequestTracker,
peers::client::{ClientConnection, session::ClientSession},
};
use arbiter_proto::{ use arbiter_proto::{
proto::client::{ proto::client::{
ClientRequest, ClientResponse, client_request::Payload as ClientRequestPayload, ClientRequest, ClientResponse, client_request::Payload as ClientRequestPayload,
@@ -5,15 +9,11 @@ use arbiter_proto::{
}, },
transport::{Receiver, Sender, grpc::GrpcBi}, transport::{Receiver, Sender, grpc::GrpcBi},
}; };
use kameo::actor::{ActorRef, Spawn as _}; use kameo::actor::{ActorRef, Spawn as _};
use tonic::Status; use tonic::Status;
use tracing::{info, warn}; use tracing::{info, warn};
use crate::{
grpc::request_tracker::RequestTracker,
peers::client::{ClientConnection, session::ClientSession},
};
mod auth; mod auth;
mod evm; mod evm;
mod inbound; mod inbound;

View File

@@ -1,3 +1,7 @@
use crate::{
grpc::request_tracker::RequestTracker,
peers::client::{self, ClientConnection, auth},
};
use arbiter_crypto::authn; use arbiter_crypto::authn;
use arbiter_proto::{ use arbiter_proto::{
ClientMetadata, ClientMetadata,
@@ -17,22 +21,18 @@ use arbiter_proto::{
}, },
transport::{Bi, Error as TransportError, Receiver, Sender, grpc::GrpcBi}, transport::{Bi, Error as TransportError, Receiver, Sender, grpc::GrpcBi},
}; };
use async_trait::async_trait; use async_trait::async_trait;
use tonic::Status; use tonic::Status;
use tracing::warn; use tracing::warn;
use crate::{ pub(super) struct AuthTransportAdapter<'a> {
grpc::request_tracker::RequestTracker,
peers::client::{self, ClientConnection, auth},
};
pub struct AuthTransportAdapter<'a> {
bi: &'a mut GrpcBi<ClientRequest, ClientResponse>, bi: &'a mut GrpcBi<ClientRequest, ClientResponse>,
request_tracker: &'a mut RequestTracker, request_tracker: &'a mut RequestTracker,
} }
impl<'a> AuthTransportAdapter<'a> { impl<'a> AuthTransportAdapter<'a> {
pub fn new( pub(super) fn new(
bi: &'a mut GrpcBi<ClientRequest, ClientResponse>, bi: &'a mut GrpcBi<ClientRequest, ClientResponse>,
request_tracker: &'a mut RequestTracker, request_tracker: &'a mut RequestTracker,
) -> Self { ) -> Self {
@@ -44,7 +44,7 @@ impl<'a> AuthTransportAdapter<'a> {
fn response_to_proto(response: auth::Outbound) -> AuthResponsePayload { fn response_to_proto(response: auth::Outbound) -> AuthResponsePayload {
match response { match response {
auth::Outbound::AuthChallenge { challenge } => { auth::Outbound::AuthChallenge { challenge } => {
AuthResponsePayload::Challenge(ProtoAuthChallenge { AuthResponsePayload::Challenge(ProtoAuthChallenge {
timestamp_nanos: challenge timestamp_nanos: challenge
.timestamp .timestamp
@@ -197,7 +197,7 @@ fn client_metadata_from_proto(metadata: ProtoClientInfo) -> ClientMetadata {
} }
} }
pub async fn start( pub(super) async fn start(
conn: &mut ClientConnection, conn: &mut ClientConnection,
bi: &mut GrpcBi<ClientRequest, ClientResponse>, bi: &mut GrpcBi<ClientRequest, ClientResponse>,
request_tracker: &mut RequestTracker, request_tracker: &mut RequestTracker,

View File

@@ -1,3 +1,10 @@
use crate::{
grpc::{
Convert, TryConvert,
common::inbound::{RawEvmAddress, RawEvmTransaction},
},
peers::client::session::{ClientSession, HandleSignTransaction, SignTransactionRpcError},
};
use arbiter_proto::proto::{ use arbiter_proto::proto::{
client::{ client::{
client_response::Payload as ClientResponsePayload, client_response::Payload as ClientResponsePayload,
@@ -11,18 +18,11 @@ use arbiter_proto::proto::{
evm_sign_transaction_response::Result as EvmSignTransactionResult, evm_sign_transaction_response::Result as EvmSignTransactionResult,
}, },
}; };
use kameo::actor::ActorRef; use kameo::actor::ActorRef;
use tonic::Status; use tonic::Status;
use tracing::warn; use tracing::warn;
use crate::{
grpc::{
Convert, TryConvert,
common::inbound::{RawEvmAddress, RawEvmTransaction},
},
peers::client::session::{ClientSession, HandleSignTransaction, SignTransactionRpcError},
};
fn wrap_response(payload: EvmResponsePayload) -> ClientResponsePayload { fn wrap_response(payload: EvmResponsePayload) -> ClientResponsePayload {
ClientResponsePayload::Evm(proto_evm::Response { ClientResponsePayload::Evm(proto_evm::Response {
payload: Some(payload), payload: Some(payload),

View File

@@ -1,3 +1,7 @@
use crate::{
actors::vault::VaultState,
peers::client::session::{ClientSession, Error, HandleQueryVaultState},
};
use arbiter_proto::proto::{ use arbiter_proto::proto::{
client::{ client::{
client_response::Payload as ClientResponsePayload, client_response::Payload as ClientResponsePayload,
@@ -8,15 +12,11 @@ use arbiter_proto::proto::{
}, },
shared::VaultState as ProtoVaultState, shared::VaultState as ProtoVaultState,
}; };
use kameo::{actor::ActorRef, error::SendError}; use kameo::{actor::ActorRef, error::SendError};
use tonic::Status; use tonic::Status;
use tracing::warn; use tracing::warn;
use crate::{
actors::vault::VaultState,
peers::client::session::{ClientSession, Error, HandleQueryVaultState},
};
pub(super) async fn dispatch( pub(super) async fn dispatch(
actor: &ActorRef<ClientSession>, actor: &ActorRef<ClientSession>,
req: proto_vault::Request, req: proto_vault::Request,

View File

@@ -1,2 +1,2 @@
pub mod inbound; pub(super) mod inbound;
pub mod outbound; pub(super) mod outbound;

View File

@@ -1,8 +1,8 @@
use alloy::{consensus::TxEip1559, primitives::Address, rlp::Decodable as _};
use crate::grpc::TryConvert; use crate::grpc::TryConvert;
pub struct RawEvmAddress(pub Vec<u8>); use alloy::{consensus::TxEip1559, primitives::Address, rlp::Decodable as _};
pub(in crate::grpc) struct RawEvmAddress(pub(in crate::grpc) Vec<u8>);
impl TryConvert for RawEvmAddress { impl TryConvert for RawEvmAddress {
type Output = Address; type Output = Address;
@@ -21,7 +21,7 @@ impl TryConvert for RawEvmAddress {
} }
} }
pub struct RawEvmTransaction(pub Vec<u8>); pub(in crate::grpc) struct RawEvmTransaction(pub(in crate::grpc) Vec<u8>);
impl TryConvert for RawEvmTransaction { impl TryConvert for RawEvmTransaction {
type Output = TxEip1559; type Output = TxEip1559;

View File

@@ -1,4 +1,10 @@
use alloy::primitives::U256; use crate::{
evm::{
PolicyError, VetError,
policies::{EvalViolation, SpecificMeaning},
},
grpc::Convert,
};
use arbiter_proto::proto::{ use arbiter_proto::proto::{
evm::{ evm::{
EvmError as ProtoEvmError, EvmError as ProtoEvmError,
@@ -14,13 +20,7 @@ use arbiter_proto::proto::{
}, },
}; };
use crate::{ use alloy::primitives::U256;
evm::{
PolicyError, VetError,
policies::{EvalViolation, SpecificMeaning},
},
grpc::Convert,
};
fn u256_to_proto_bytes(value: U256) -> Vec<u8> { fn u256_to_proto_bytes(value: U256) -> Vec<u8> {
value.to_be_bytes::<32>().to_vec() value.to_be_bytes::<32>().to_vec()

View File

@@ -1,3 +1,4 @@
use crate::peers::{client::ClientConnection, user_agent::UserAgentConnection};
use arbiter_proto::{ use arbiter_proto::{
proto::{ proto::{
client::{ClientRequest, ClientResponse}, client::{ClientRequest, ClientResponse},
@@ -5,14 +6,11 @@ use arbiter_proto::{
}, },
transport::grpc::GrpcBi, transport::grpc::GrpcBi,
}; };
use tokio_stream::wrappers::ReceiverStream; use tokio_stream::wrappers::ReceiverStream;
use tonic::{Request, Response, Status, async_trait}; use tonic::{Request, Response, Status, async_trait};
use tracing::info; use tracing::info;
use crate::{
peers::{client::ClientConnection, user_agent::UserAgentConnection},
};
mod request_tracker; mod request_tracker;
pub mod client; pub mod client;

View File

@@ -1,12 +1,12 @@
use tonic::Status; use tonic::Status;
#[derive(Default)] #[derive(Default)]
pub struct RequestTracker { pub(super) struct RequestTracker {
next_request_id: i32, next_request_id: i32,
} }
impl RequestTracker { impl RequestTracker {
pub fn request(&mut self, id: i32) -> Result<i32, Status> { pub(super) fn request(&mut self, id: i32) -> Result<i32, Status> {
if id < self.next_request_id { if id < self.next_request_id {
return Err(Status::invalid_argument("Duplicate request id")); return Err(Status::invalid_argument("Duplicate request id"));
} }
@@ -20,7 +20,7 @@ impl RequestTracker {
// This is used to set the response id for auth responses, which need to match the request id of the auth challenge request. // This is used to set the response id for auth responses, which need to match the request id of the auth challenge request.
// -1 offset is needed because request() increments the next_request_id after returning the current request id. // -1 offset is needed because request() increments the next_request_id after returning the current request id.
pub fn current_request_id(&self) -> i32 { pub(super) fn current_request_id(&self) -> i32 {
self.next_request_id - 1 self.next_request_id - 1
} }
} }

View File

@@ -1,5 +1,7 @@
use tokio::sync::mpsc; use crate::{
grpc::request_tracker::RequestTracker,
peers::user_agent::{OutOfBand, UserAgentConnection, UserAgentSession},
};
use arbiter_proto::{ use arbiter_proto::{
proto::user_agent::{ proto::user_agent::{
UserAgentRequest, UserAgentResponse, UserAgentRequest, UserAgentResponse,
@@ -8,16 +10,13 @@ use arbiter_proto::{
}, },
transport::{Error as TransportError, Receiver, Sender, grpc::GrpcBi}, transport::{Error as TransportError, Receiver, Sender, grpc::GrpcBi},
}; };
use async_trait::async_trait; use async_trait::async_trait;
use kameo::actor::ActorRef; use kameo::actor::ActorRef;
use tokio::sync::mpsc;
use tonic::Status; use tonic::Status;
use tracing::{error, info, warn}; use tracing::{error, info, warn};
use crate::{
grpc::request_tracker::RequestTracker,
peers::user_agent::{OutOfBand, UserAgentConnection, UserAgentSession},
};
mod auth; mod auth;
mod evm; mod evm;
mod inbound; mod inbound;
@@ -144,4 +143,3 @@ pub async fn start(
dispatch_loop(bi, actor.clone(), oob_receiver, request_tracker).await; dispatch_loop(bi, actor.clone(), oob_receiver, request_tracker).await;
actor.kill(); actor.kill();
} }

View File

@@ -1,3 +1,4 @@
use crate::{grpc::request_tracker::RequestTracker, peers::user_agent::auth};
use arbiter_crypto::authn; use arbiter_crypto::authn;
use arbiter_proto::{ use arbiter_proto::{
proto::user_agent::{ proto::user_agent::{
@@ -13,22 +14,18 @@ use arbiter_proto::{
}, },
transport::{Bi, Error as TransportError, Receiver, Sender, grpc::GrpcBi}, transport::{Bi, Error as TransportError, Receiver, Sender, grpc::GrpcBi},
}; };
use async_trait::async_trait; use async_trait::async_trait;
use tonic::Status; use tonic::Status;
use tracing::warn; use tracing::warn;
use crate::{ pub(super) struct AuthTransportAdapter<'a> {
grpc::request_tracker::RequestTracker,
peers::user_agent::{Credentials, UserAgentConnection, auth},
};
pub struct AuthTransportAdapter<'a> {
pub(super) bi: &'a mut GrpcBi<UserAgentRequest, UserAgentResponse>, pub(super) bi: &'a mut GrpcBi<UserAgentRequest, UserAgentResponse>,
pub(super) request_tracker: &'a mut RequestTracker, pub(super) request_tracker: &'a mut RequestTracker,
} }
impl<'a> AuthTransportAdapter<'a> { impl<'a> AuthTransportAdapter<'a> {
pub fn new( pub(super) fn new(
bi: &'a mut GrpcBi<UserAgentRequest, UserAgentResponse>, bi: &'a mut GrpcBi<UserAgentRequest, UserAgentResponse>,
request_tracker: &'a mut RequestTracker, request_tracker: &'a mut RequestTracker,
) -> Self { ) -> Self {
@@ -185,12 +182,3 @@ impl Receiver<auth::Inbound> for AuthTransportAdapter<'_> {
} }
impl Bi<auth::Inbound, Result<auth::Outbound, auth::Error>> for AuthTransportAdapter<'_> {} impl Bi<auth::Inbound, Result<auth::Outbound, auth::Error>> for AuthTransportAdapter<'_> {}
pub async fn start(
conn: &mut UserAgentConnection,
bi: &mut GrpcBi<UserAgentRequest, UserAgentResponse>,
request_tracker: &mut RequestTracker,
) -> Result<Credentials, auth::Error> {
let mut transport = AuthTransportAdapter::new(bi, request_tracker);
auth::authenticate(conn, &mut transport).await
}

View File

@@ -1,3 +1,17 @@
use crate::{
grpc::{
Convert, TryConvert,
common::inbound::{RawEvmAddress, RawEvmTransaction},
},
peers::user_agent::{
UserAgentSession,
session::handlers::{
GrantMutationError, HandleEvmWalletCreate, HandleEvmWalletList, HandleGrantCreate,
HandleGrantDelete, HandleGrantList, HandleSignTransaction,
SignTransactionError as SessionSignTransactionError,
},
},
};
use arbiter_proto::proto::{ use arbiter_proto::proto::{
evm::{ evm::{
EvmError as ProtoEvmError, EvmGrantCreateRequest, EvmGrantCreateResponse, EvmError as ProtoEvmError, EvmGrantCreateRequest, EvmGrantCreateResponse,
@@ -18,25 +32,11 @@ use arbiter_proto::proto::{
user_agent_response::Payload as UserAgentResponsePayload, user_agent_response::Payload as UserAgentResponsePayload,
}, },
}; };
use kameo::actor::ActorRef; use kameo::actor::ActorRef;
use tonic::Status; use tonic::Status;
use tracing::warn; use tracing::warn;
use crate::{
grpc::{
Convert, TryConvert,
common::inbound::{RawEvmAddress, RawEvmTransaction},
},
peers::user_agent::{
UserAgentSession,
session::handlers::{
GrantMutationError, HandleEvmWalletCreate, HandleEvmWalletList, HandleGrantCreate,
HandleGrantDelete, HandleGrantList, HandleSignTransaction,
SignTransactionError as SessionSignTransactionError,
},
},
};
fn wrap_evm_response(payload: EvmResponsePayload) -> UserAgentResponsePayload { fn wrap_evm_response(payload: EvmResponsePayload) -> UserAgentResponsePayload {
UserAgentResponsePayload::Evm(proto_evm::Response { UserAgentResponsePayload::Evm(proto_evm::Response {
payload: Some(payload), payload: Some(payload),

View File

@@ -1,26 +1,26 @@
use alloy::primitives::{Address, U256};
use arbiter_proto::proto::evm::{
EtherTransferSettings as ProtoEtherTransferSettings, SharedSettings as ProtoSharedSettings,
SpecificGrant as ProtoSpecificGrant, TokenTransferSettings as ProtoTokenTransferSettings,
TransactionRateLimit as ProtoTransactionRateLimit, VolumeRateLimit as ProtoVolumeRateLimit,
specific_grant::Grant as ProtoSpecificGrantType,
};
use arbiter_proto::proto::user_agent::sdk_client::{
WalletAccess, WalletAccessEntry as SdkClientWalletAccess,
};
use chrono::{DateTime, TimeZone, Utc};
use prost_types::Timestamp as ProtoTimestamp;
use tonic::Status;
use crate::db::models::{CoreEvmWalletAccess, NewEvmWalletAccess};
use crate::grpc::Convert;
use crate::{ use crate::{
db::models::{CoreEvmWalletAccess, NewEvmWalletAccess},
evm::policies::{ evm::policies::{
SharedGrantSettings, SpecificGrant, TransactionRateLimit, VolumeRateLimit, ether_transfer, SharedGrantSettings, SpecificGrant, TransactionRateLimit, VolumeRateLimit, ether_transfer,
token_transfers, token_transfers,
}, },
grpc::Convert,
grpc::TryConvert, grpc::TryConvert,
}; };
use arbiter_proto::{
proto::evm::{
EtherTransferSettings as ProtoEtherTransferSettings, SharedSettings as ProtoSharedSettings,
SpecificGrant as ProtoSpecificGrant, TokenTransferSettings as ProtoTokenTransferSettings,
TransactionRateLimit as ProtoTransactionRateLimit, VolumeRateLimit as ProtoVolumeRateLimit,
specific_grant::Grant as ProtoSpecificGrantType,
},
proto::user_agent::sdk_client::{WalletAccess, WalletAccessEntry as SdkClientWalletAccess},
};
use alloy::primitives::{Address, U256};
use chrono::{DateTime, TimeZone, Utc};
use prost_types::Timestamp as ProtoTimestamp;
use tonic::Status;
fn address_from_bytes(bytes: Vec<u8>) -> Result<Address, Status> { fn address_from_bytes(bytes: Vec<u8>) -> Result<Address, Status> {
if bytes.len() != 20 { if bytes.len() != 20 {

View File

@@ -1,3 +1,8 @@
use crate::{
db::models::EvmWalletAccess,
evm::policies::{SharedGrantSettings, SpecificGrant, TransactionRateLimit, VolumeRateLimit},
grpc::Convert,
};
use arbiter_proto::proto::{ use arbiter_proto::proto::{
evm::{ evm::{
EtherTransferSettings as ProtoEtherTransferSettings, SharedSettings as ProtoSharedSettings, EtherTransferSettings as ProtoEtherTransferSettings, SharedSettings as ProtoSharedSettings,
@@ -7,15 +12,10 @@ use arbiter_proto::proto::{
}, },
user_agent::sdk_client::{WalletAccess, WalletAccessEntry as ProtoSdkClientWalletAccess}, user_agent::sdk_client::{WalletAccess, WalletAccessEntry as ProtoSdkClientWalletAccess},
}; };
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use prost_types::Timestamp as ProtoTimestamp; use prost_types::Timestamp as ProtoTimestamp;
use crate::{
db::models::EvmWalletAccess,
evm::policies::{SharedGrantSettings, SpecificGrant, TransactionRateLimit, VolumeRateLimit},
grpc::Convert,
};
impl Convert for DateTime<Utc> { impl Convert for DateTime<Utc> {
type Output = ProtoTimestamp; type Output = ProtoTimestamp;

View File

@@ -1,3 +1,14 @@
use crate::{
db::models::NewEvmWalletAccess,
grpc::Convert,
peers::user_agent::{
OutOfBand, UserAgentSession,
session::handlers::{
HandleGrantEvmWalletAccess, HandleListWalletAccess, HandleNewClientApprove,
HandleRevokeEvmWalletAccess, HandleSdkClientList,
},
},
};
use arbiter_crypto::authn; use arbiter_crypto::authn;
use arbiter_proto::proto::{ use arbiter_proto::proto::{
shared::ClientInfo as ProtoClientMetadata, shared::ClientInfo as ProtoClientMetadata,
@@ -16,22 +27,11 @@ use arbiter_proto::proto::{
user_agent_response::Payload as UserAgentResponsePayload, user_agent_response::Payload as UserAgentResponsePayload,
}, },
}; };
use kameo::actor::ActorRef; use kameo::actor::ActorRef;
use tonic::Status; use tonic::Status;
use tracing::{info, warn}; use tracing::{info, warn};
use crate::{
db::models::NewEvmWalletAccess,
grpc::Convert,
peers::user_agent::{
OutOfBand, UserAgentSession,
session::handlers::{
HandleGrantEvmWalletAccess, HandleListWalletAccess, HandleNewClientApprove,
HandleRevokeEvmWalletAccess, HandleSdkClientList,
},
},
};
fn wrap_sdk_client_response(payload: SdkClientResponsePayload) -> UserAgentResponsePayload { fn wrap_sdk_client_response(payload: SdkClientResponsePayload) -> UserAgentResponsePayload {
UserAgentResponsePayload::SdkClient(proto_sdk_client::Response { UserAgentResponsePayload::SdkClient(proto_sdk_client::Response {
payload: Some(payload), payload: Some(payload),

View File

@@ -1,16 +1,21 @@
use arbiter_proto::proto::shared::VaultState as ProtoVaultState;
use arbiter_proto::proto::user_agent::{
user_agent_response::Payload as UserAgentResponsePayload,
vault::{self as proto_vault, request::Payload as VaultRequestPayload, response::Payload as VaultResponsePayload},
};
use kameo::actor::ActorRef;
use tonic::Status;
use tracing::warn;
use crate::{ use crate::{
actors::vault::VaultState, actors::vault::VaultState,
peers::user_agent::{UserAgentSession, session::handlers::HandleQueryVaultState}, peers::user_agent::{UserAgentSession, session::handlers::HandleQueryVaultState},
}; };
use arbiter_proto::{
proto::shared::VaultState as ProtoVaultState,
proto::user_agent::{
user_agent_response::Payload as UserAgentResponsePayload,
vault::{
self as proto_vault, request::Payload as VaultRequestPayload,
response::Payload as VaultResponsePayload,
},
},
};
use kameo::actor::ActorRef;
use tonic::Status;
use tracing::warn;
fn wrap_vault_response(payload: VaultResponsePayload) -> UserAgentResponsePayload { fn wrap_vault_response(payload: VaultResponsePayload) -> UserAgentResponsePayload {
UserAgentResponsePayload::Vault(proto_vault::Response { UserAgentResponsePayload::Vault(proto_vault::Response {

View File

@@ -1,13 +1,13 @@
use arbiter_proto::transport::{Bi, Error as TransportError, Receiver, Sender};
use async_trait::async_trait;
use tonic::Status;
use tracing::warn;
use super::auth::AuthTransportAdapter; use super::auth::AuthTransportAdapter;
use crate::{ use crate::{
grpc::TryConvert, grpc::TryConvert,
peers::user_agent::vault_gate::{self as vault_gate}, peers::user_agent::vault_gate::{self as vault_gate},
}; };
use arbiter_proto::transport::{Bi, Error as TransportError, Receiver, Sender};
use async_trait::async_trait;
use tonic::Status;
use tracing::warn;
mod inbound; mod inbound;
mod outbound; mod outbound;

View File

@@ -1,3 +1,9 @@
use crate::{
grpc::{Convert, TryConvert},
peers::user_agent::vault_gate::{
self as vault_gate, HandleBootstrapEncryptedKey, HandleHandshake, HandleUnsealEncryptedKey,
},
};
use arbiter_proto::proto::user_agent::{ use arbiter_proto::proto::user_agent::{
user_agent_request::Payload as UserAgentRequestPayload, user_agent_request::Payload as UserAgentRequestPayload,
vault::{ vault::{
@@ -7,14 +13,8 @@ use arbiter_proto::proto::user_agent::{
unseal::{self as proto_unseal, request::Payload as UnsealRequestPayload}, unseal::{self as proto_unseal, request::Payload as UnsealRequestPayload},
}, },
}; };
use tonic::Status;
use crate::{ use tonic::Status;
grpc::{Convert, TryConvert},
peers::user_agent::vault_gate::{
self as vault_gate, HandleBootstrapEncryptedKey, HandleHandshake, HandleUnsealEncryptedKey,
},
};
impl TryConvert for UserAgentRequestPayload { impl TryConvert for UserAgentRequestPayload {
type Output = vault_gate::Inbound; type Output = vault_gate::Inbound;

View File

@@ -1,3 +1,8 @@
use crate::{
actors::vault::VaultState,
grpc::{Convert, TryConvert},
peers::user_agent::vault_gate::{self as vault_gate},
};
use arbiter_proto::proto::{ use arbiter_proto::proto::{
shared::VaultState as ProtoVaultState, shared::VaultState as ProtoVaultState,
user_agent::{ user_agent::{
@@ -13,15 +18,10 @@ use arbiter_proto::proto::{
}, },
}, },
}; };
use tonic::Status; use tonic::Status;
use tracing::warn; use tracing::warn;
use crate::{
actors::vault::VaultState,
grpc::{Convert, TryConvert},
peers::user_agent::vault_gate::{self as vault_gate},
};
fn wrap_vault_response(payload: VaultResponsePayload) -> UserAgentResponsePayload { fn wrap_vault_response(payload: VaultResponsePayload) -> UserAgentResponsePayload {
UserAgentResponsePayload::Vault(proto_vault::Response { UserAgentResponsePayload::Vault(proto_vault::Response {
payload: Some(payload), payload: Some(payload),

View File

@@ -1,9 +1,9 @@
use std::net::SocketAddr;
use anyhow::anyhow;
use arbiter_proto::{proto::arbiter_service_server::ArbiterServiceServer, url::ArbiterUrl}; use arbiter_proto::{proto::arbiter_service_server::ArbiterServiceServer, url::ArbiterUrl};
use arbiter_server::{Server, actors::bootstrap::GetToken, context::ServerContext, db}; use arbiter_server::{Server, actors::bootstrap::GetToken, context::ServerContext, db};
use anyhow::anyhow;
use rustls::crypto::aws_lc_rs; use rustls::crypto::aws_lc_rs;
use std::net::SocketAddr;
use tonic::transport::{Identity, ServerTlsConfig}; use tonic::transport::{Identity, ServerTlsConfig};
use tracing::info; use tracing::info;

View File

@@ -1,17 +1,4 @@
use arbiter_crypto::authn::{self, AuthChallenge, CLIENT_CONTEXT}; use super::{ClientConnection, ClientCredentials, ClientProfile};
use arbiter_proto::{
ClientMetadata,
transport::{Bi, expect_message},
};
use chrono::Utc;
use diesel::{
ExpressionMethods as _, OptionalExtension as _, QueryDsl as _, SelectableHelper as _,
dsl::insert_into, update,
};
use diesel_async::RunQueryDsl as _;
use kameo::{actor::ActorRef, error::SendError};
use tracing::error;
use crate::{ use crate::{
actors::{ actors::{
GlobalActors, GlobalActors,
@@ -25,8 +12,20 @@ use crate::{
schema::program_client, schema::program_client,
}, },
}; };
use arbiter_crypto::authn::{self, AuthChallenge, CLIENT_CONTEXT};
use arbiter_proto::{
ClientMetadata,
transport::{Bi, expect_message},
};
use super::{ClientConnection, ClientCredentials, ClientProfile}; use chrono::Utc;
use diesel::{
ExpressionMethods as _, OptionalExtension as _, QueryDsl as _, SelectableHelper as _,
dsl::insert_into, update,
};
use diesel_async::RunQueryDsl as _;
use kameo::{actor::ActorRef, error::SendError};
use tracing::error;
#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)] #[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)]
pub enum Error { pub enum Error {

View File

@@ -1,21 +1,20 @@
use crate::{
actors::GlobalActors, crypto::integrity::Integrable, db, peers::client::session::ClientSession,
};
use arbiter_crypto::authn; use arbiter_crypto::authn;
use arbiter_macros::Hashable;
use arbiter_proto::{ClientMetadata, transport::Bi}; use arbiter_proto::{ClientMetadata, transport::Bi};
use kameo::actor::Spawn; use kameo::actor::Spawn;
use tracing::{error, info}; use tracing::{error, info};
use crate::{
actors::GlobalActors,
crypto::integrity::{Integrable, hashing::Hashable},
db,
peers::client::session::ClientSession,
};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ClientProfile { pub struct ClientProfile {
pub pubkey: authn::PublicKey, pub pubkey: authn::PublicKey,
pub metadata: ClientMetadata, pub metadata: ClientMetadata,
} }
#[derive(Hashable)]
pub struct ClientCredentials { pub struct ClientCredentials {
pub pubkey: authn::PublicKey, pub pubkey: authn::PublicKey,
} }
@@ -24,12 +23,6 @@ impl Integrable for ClientCredentials {
const KIND: &'static str = "client_credentials"; const KIND: &'static str = "client_credentials";
} }
impl Hashable for ClientCredentials {
fn hash<H: sha2::Digest>(&self, hasher: &mut H) {
hasher.update(self.pubkey.to_bytes());
}
}
pub struct ClientConnection { pub struct ClientConnection {
pub(crate) db: db::DatabasePool, pub(crate) db: db::DatabasePool,
pub(crate) actors: GlobalActors, pub(crate) actors: GlobalActors,

View File

@@ -1,8 +1,4 @@
use kameo::{Actor, messages}; use super::ClientConnection;
use tracing::error;
use alloy::{consensus::TxEip1559, primitives::Address, signers::Signature};
use crate::{ use crate::{
actors::{ actors::{
GlobalActors, GlobalActors,
@@ -14,7 +10,9 @@ use crate::{
evm::VetError, evm::VetError,
}; };
use super::ClientConnection; use alloy::{consensus::TxEip1559, primitives::Address, signers::Signature};
use kameo::{Actor, messages};
use tracing::error;
pub struct ClientSession { pub struct ClientSession {
props: ClientConnection, props: ClientConnection,

View File

@@ -1,12 +1,11 @@
use super::{Credentials, UserAgentConnection};
use arbiter_crypto::authn::{self, AuthChallenge}; use arbiter_crypto::authn::{self, AuthChallenge};
use arbiter_proto::transport::Bi; use arbiter_proto::transport::Bi;
use state::*;
use tracing::error; use tracing::error;
mod state; mod state;
use state::*;
use super::Credentials;
use super::UserAgentConnection;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Inbound { pub enum Inbound {

View File

@@ -1,30 +1,32 @@
use super::super::{Credentials, UserAgentConnection}; use super::{
use arbiter_crypto::authn::{self, AuthChallenge, USERAGENT_CONTEXT}; super::{Credentials, UserAgentConnection},
use arbiter_proto::transport::Bi; Error,
use diesel::{ExpressionMethods as _, OptionalExtension as _, QueryDsl}; };
use diesel_async::RunQueryDsl;
use tracing::error;
use super::Error;
use crate::{ use crate::{
actors::bootstrap::ConsumeToken, actors::bootstrap::ConsumeToken,
db::{DatabasePool, schema::useragent_client}, db::{DatabasePool, schema::useragent_client},
peers::user_agent::auth::Outbound, peers::user_agent::auth::Outbound,
}; };
use arbiter_crypto::authn::{self, AuthChallenge, USERAGENT_CONTEXT};
use arbiter_proto::transport::Bi;
pub struct ChallengeRequest { use diesel::{ExpressionMethods as _, OptionalExtension as _, QueryDsl};
pub pubkey: authn::PublicKey, use diesel_async::RunQueryDsl;
pub bootstrap_token: Option<String>, use tracing::error;
pub(super) struct ChallengeRequest {
pub(super) pubkey: authn::PublicKey,
pub(super) bootstrap_token: Option<String>,
} }
pub struct ChallengeContext { pub(super) struct ChallengeContext {
pub challenge: AuthChallenge, pub(super) challenge: AuthChallenge,
pub pubkey: authn::PublicKey, pub(super) pubkey: authn::PublicKey,
pub bootstrap_token: Option<String>, pub(super) bootstrap_token: Option<String>,
} }
pub struct ChallengeSolution { pub(super) struct ChallengeSolution {
pub solution: Vec<u8>, pub(super) solution: Vec<u8>,
} }
smlang::statemachine!( smlang::statemachine!(
@@ -74,13 +76,13 @@ async fn register_key(db: &DatabasePool, pubkey: &authn::PublicKey) -> Result<i3
Ok(id) Ok(id)
} }
pub struct AuthContext<'a, T: ?Sized> { pub(super) struct AuthContext<'a, T: ?Sized> {
pub(super) conn: &'a mut UserAgentConnection, pub(super) conn: &'a mut UserAgentConnection,
pub(super) transport: &'a mut T, pub(super) transport: &'a mut T,
} }
impl<'a, T: ?Sized> AuthContext<'a, T> { impl<'a, T: ?Sized> AuthContext<'a, T> {
pub fn new(conn: &'a mut UserAgentConnection, transport: &'a mut T) -> Self { pub(super) fn new(conn: &'a mut UserAgentConnection, transport: &'a mut T) -> Self {
Self { conn, transport } Self { conn, transport }
} }
} }

View File

@@ -8,40 +8,27 @@ use crate::{
peers::client::ClientProfile, peers::client::ClientProfile,
}; };
use arbiter_crypto::authn; use arbiter_crypto::authn;
use arbiter_macros::Hashable;
use arbiter_proto::transport::{Bi, Sender}; use arbiter_proto::transport::{Bi, Sender};
pub use auth::authenticate;
use kameo::actor::{ActorRef, Spawn as _};
pub use session::UserAgentSession;
use tokio::sync::oneshot;
use tracing::{error, warn};
use vault_gate::VaultGate; use vault_gate::VaultGate;
use crate::crypto::integrity::hashing::Hashable; use kameo::actor::{ActorRef, Spawn as _};
use tokio::sync::oneshot;
use tracing::{error, warn};
pub use auth::authenticate;
pub use session::UserAgentSession;
pub mod auth; pub mod auth;
pub mod session; pub mod session;
pub mod vault_gate; pub mod vault_gate;
#[derive(Debug, Clone)] #[derive(Debug, Clone, Hashable)]
pub struct Credentials { pub struct Credentials {
pub id: i32, pub id: i32,
pub pubkey: authn::PublicKey, pub pubkey: authn::PublicKey,
} }
impl Hashable for authn::PublicKey {
fn hash<H: sha2::Digest>(&self, hasher: &mut H) {
hasher.update(self.to_bytes());
}
}
impl Hashable for Credentials {
fn hash<H: sha2::Digest>(&self, hasher: &mut H) {
self.id.hash(hasher);
self.pubkey.hash(hasher);
}
}
impl Integrable for Credentials { impl Integrable for Credentials {
const KIND: &'static str = "useragent_credentials"; const KIND: &'static str = "useragent_credentials";
} }
@@ -193,7 +180,6 @@ where
Ok(UserAgentSession::spawn(UserAgentSession::new( Ok(UserAgentSession::spawn(UserAgentSession::new(
props.clone(), props.clone(),
creds,
oob_sender, oob_sender,
))) )))
} }

View File

@@ -1,32 +1,21 @@
use super::{Error, UserAgentSession};
use alloy::{consensus::TxEip1559, primitives::Address, signers::Signature}; use crate::{
use arbiter_crypto::{ actors::evm::{
authn,
safecell::SafeCellHandle as _,
};
use chacha20poly1305::aead::KeyInit;
use diesel::{ExpressionMethods as _, QueryDsl as _, SelectableHelper};
use diesel_async::{AsyncConnection, RunQueryDsl};
use kameo::error::SendError;
use kameo::messages;
use kameo::prelude::Context;
use tracing::error;
use crate::actors::flow_coordinator::client_connect_approval::ClientApprovalAnswer;
use crate::actors::evm::{
ClientSignTransaction, Generate, ListWallets, SignTransactionError as EvmSignError, ClientSignTransaction, Generate, ListWallets, SignTransactionError as EvmSignError,
UseragentCreateGrant, UseragentListGrants, UseragentCreateGrant, UseragentListGrants,
}; },
use crate::db::models::{ actors::flow_coordinator::client_connect_approval::ClientApprovalAnswer,
EvmWalletAccess, NewEvmWalletAccess, ProgramClient, ProgramClientMetadata,
};
use crate::evm::policies::{Grant, SpecificGrant};
use crate::{
actors::vault::VaultState, actors::vault::VaultState,
db::models::{EvmWalletAccess, NewEvmWalletAccess, ProgramClient, ProgramClientMetadata},
evm::policies::{Grant, SpecificGrant},
}; };
use arbiter_crypto::authn;
use super::{Error, UserAgentSession}; use alloy::{consensus::TxEip1559, primitives::Address, signers::Signature};
use diesel::{ExpressionMethods as _, QueryDsl as _, SelectableHelper};
use diesel_async::{AsyncConnection, RunQueryDsl};
use kameo::{error::SendError, messages, prelude::Context};
use tracing::error;
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum SignTransactionError { pub enum SignTransactionError {

View File

@@ -1,21 +1,18 @@
use arbiter_crypto::authn; use super::{OutOfBand, UserAgentConnection};
use std::{borrow::Cow, collections::HashMap};
use arbiter_proto::transport::Sender;
use kameo::{Actor, actor::ActorRef, messages};
use thiserror::Error;
use tracing::error;
use crate::{ use crate::{
actors::{ actors::{
flow_coordinator::client_connect_approval::ClientApprovalController, flow_coordinator::client_connect_approval::ClientApprovalController,
useragent_registry::ConnectUseragent, useragent_registry::ConnectUseragent,
}, },
peers::{client::ClientProfile, user_agent::Credentials}, peers::client::ClientProfile,
}; };
use arbiter_crypto::authn;
use arbiter_proto::transport::Sender;
use super::{OutOfBand, UserAgentConnection}; use kameo::{Actor, actor::ActorRef, messages};
use std::{borrow::Cow, collections::HashMap};
use thiserror::Error;
use tracing::error;
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum Error { pub enum Error {
@@ -53,7 +50,6 @@ pub struct PendingClientApproval {
} }
pub struct UserAgentSession { pub struct UserAgentSession {
creds: Credentials,
props: UserAgentConnection, props: UserAgentConnection,
sender: Box<dyn Sender<OutOfBand>>, sender: Box<dyn Sender<OutOfBand>>,
@@ -63,13 +59,8 @@ pub struct UserAgentSession {
pub mod handlers; pub mod handlers;
impl UserAgentSession { impl UserAgentSession {
pub(crate) fn new( pub(crate) fn new(props: UserAgentConnection, sender: Box<dyn Sender<OutOfBand>>) -> Self {
props: UserAgentConnection,
creds: Credentials,
sender: Box<dyn Sender<OutOfBand>>,
) -> Self {
Self { Self {
creds,
props, props,
sender, sender,
pending_client_approvals: Default::default(), pending_client_approvals: Default::default(),

View File

@@ -1,15 +1,3 @@
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use arbiter_proto::transport::Bi;
use chacha20poly1305::{AeadInPlace, KeyInit as _, XChaCha20Poly1305, XNonce};
use kameo::{Actor, error::SendError, messages, prelude::Message};
use kameo_actors::message_bus::Register;
use tokio::sync::oneshot;
use tracing::{error, info, warn};
use x25519_dalek::{EphemeralSecret, PublicKey, SharedSecret};
pub mod state;
use state::*;
use super::Credentials; use super::Credentials;
use crate::{ use crate::{
actors::{ actors::{
@@ -18,8 +6,18 @@ use crate::{
}, },
crypto::integrity::{self}, crypto::integrity::{self},
db::DatabasePool, db::DatabasePool,
peers::user_agent::UserAgentConnection,
}; };
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use state::*;
use chacha20poly1305::{AeadInPlace, KeyInit as _, XChaCha20Poly1305, XNonce};
use kameo::{Actor, error::SendError, messages, prelude::Message};
use kameo_actors::message_bus::Register;
use tokio::sync::oneshot;
use tracing::{error, info};
use x25519_dalek::{EphemeralSecret, PublicKey, SharedSecret};
pub mod state;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum Error { pub enum Error {

View File

@@ -1,10 +1,5 @@
use x25519_dalek::{PublicKey, SharedSecret}; use x25519_dalek::{PublicKey, SharedSecret};
pub struct Handshake {
client_pubkey: PublicKey,
}
#[derive(Default)] #[derive(Default)]
pub enum State { pub enum State {
#[default] #[default]

View File

@@ -1,21 +1,23 @@
use super::common::ChannelTransport;
use arbiter_crypto::{ use arbiter_crypto::{
authn::{self, AuthChallenge, CLIENT_CONTEXT}, authn::{self, AuthChallenge, CLIENT_CONTEXT},
safecell::{SafeCell, SafeCellHandle as _}, safecell::{SafeCell, SafeCellHandle as _},
}; };
use arbiter_proto::ClientMetadata; use arbiter_proto::{
use arbiter_proto::transport::{Receiver, Sender}; ClientMetadata,
transport::{Receiver, Sender},
};
use arbiter_server::{ use arbiter_server::{
actors::{GlobalActors, vault::Bootstrap}, actors::{GlobalActors, vault::Bootstrap},
crypto::integrity, crypto::integrity,
db::{self, schema}, db::{self, schema},
peers::client::{ClientConnection, ClientCredentials, auth, connect_client}, peers::client::{ClientConnection, ClientCredentials, auth, connect_client},
}; };
use diesel::{ExpressionMethods as _, NullableExpressionMethods as _, QueryDsl as _, insert_into}; use diesel::{ExpressionMethods as _, NullableExpressionMethods as _, QueryDsl as _, insert_into};
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
use ml_dsa::{KeyGen, MlDsa87, SigningKey, VerifyingKey, signature::Keypair as _}; use ml_dsa::{KeyGen, MlDsa87, SigningKey, VerifyingKey, signature::Keypair as _};
use super::common::ChannelTransport;
fn metadata(name: &str, description: Option<&str>, version: Option<&str>) -> ClientMetadata { fn metadata(name: &str, description: Option<&str>, version: Option<&str>) -> ClientMetadata {
ClientMetadata { ClientMetadata {
name: name.to_owned(), name: name.to_owned(),
@@ -103,7 +105,7 @@ async fn spawn_test_actors(db: &db::DatabasePool) -> GlobalActors {
#[tokio::test] #[tokio::test]
#[test_log::test] #[test_log::test]
pub async fn test_unregistered_pubkey_rejected() { async fn test_unregistered_pubkey_rejected() {
let db = db::create_test_pool().await; let db = db::create_test_pool().await;
let (server_transport, mut test_transport) = ChannelTransport::new(); let (server_transport, mut test_transport) = ChannelTransport::new();
@@ -130,7 +132,7 @@ pub async fn test_unregistered_pubkey_rejected() {
#[tokio::test] #[tokio::test]
#[test_log::test] #[test_log::test]
pub async fn test_challenge_auth() { async fn test_challenge_auth() {
let db = db::create_test_pool().await; let db = db::create_test_pool().await;
let actors = spawn_test_actors(&db).await; let actors = spawn_test_actors(&db).await;
@@ -197,7 +199,7 @@ pub async fn test_challenge_auth() {
#[tokio::test] #[tokio::test]
#[test_log::test] #[test_log::test]
pub async fn test_metadata_unchanged_does_not_append_history() { async fn test_metadata_unchanged_does_not_append_history() {
let db = db::create_test_pool().await; let db = db::create_test_pool().await;
let actors = spawn_test_actors(&db).await; let actors = spawn_test_actors(&db).await;
let new_key = MlDsa87::key_gen(&mut rand::rng()); let new_key = MlDsa87::key_gen(&mut rand::rng());
@@ -254,7 +256,7 @@ pub async fn test_metadata_unchanged_does_not_append_history() {
#[tokio::test] #[tokio::test]
#[test_log::test] #[test_log::test]
pub async fn test_metadata_change_appends_history_and_repoints_binding() { async fn test_metadata_change_appends_history_and_repoints_binding() {
let db = db::create_test_pool().await; let db = db::create_test_pool().await;
let actors = spawn_test_actors(&db).await; let actors = spawn_test_actors(&db).await;
let new_key = MlDsa87::key_gen(&mut rand::rng()); let new_key = MlDsa87::key_gen(&mut rand::rng());
@@ -341,7 +343,7 @@ pub async fn test_metadata_change_appends_history_and_repoints_binding() {
#[tokio::test] #[tokio::test]
#[test_log::test] #[test_log::test]
pub async fn test_challenge_auth_rejects_integrity_tag_mismatch() { async fn test_challenge_auth_rejects_integrity_tag_mismatch() {
let db = db::create_test_pool().await; let db = db::create_test_pool().await;
let actors = spawn_test_actors(&db).await; let actors = spawn_test_actors(&db).await;

View File

@@ -11,7 +11,7 @@ use diesel_async::RunQueryDsl;
use tokio::sync::mpsc; use tokio::sync::mpsc;
#[allow(dead_code)] #[allow(dead_code)]
pub async fn bootstrapped_vault(db: &db::DatabasePool) -> Vault { pub(crate) async fn bootstrapped_vault(db: &db::DatabasePool) -> Vault {
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()) let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus())
.await .await
.unwrap(); .unwrap();
@@ -23,7 +23,7 @@ pub async fn bootstrapped_vault(db: &db::DatabasePool) -> Vault {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub async fn root_key_history_id(db: &db::DatabasePool) -> i32 { pub(crate) async fn root_key_history_id(db: &db::DatabasePool) -> i32 {
let mut conn = db.get().await.unwrap(); let mut conn = db.get().await.unwrap();
let id = schema::arbiter_settings::table let id = schema::arbiter_settings::table
.select(schema::arbiter_settings::root_key_id) .select(schema::arbiter_settings::root_key_id)
@@ -34,14 +34,14 @@ pub async fn root_key_history_id(db: &db::DatabasePool) -> i32 {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub struct ChannelTransport<T, Y> { pub(crate) struct ChannelTransport<T, Y> {
receiver: mpsc::Receiver<T>, receiver: mpsc::Receiver<T>,
sender: mpsc::Sender<Y>, sender: mpsc::Sender<Y>,
} }
impl<T, Y> ChannelTransport<T, Y> { impl<T, Y> ChannelTransport<T, Y> {
#[allow(dead_code)] #[allow(dead_code)]
pub fn new() -> (Self, ChannelTransport<Y, T>) { pub(crate) fn new() -> (Self, ChannelTransport<Y, T>) {
let (tx1, rx1) = mpsc::channel(10); let (tx1, rx1) = mpsc::channel(10);
let (tx2, rx2) = mpsc::channel(10); let (tx2, rx2) = mpsc::channel(10);
( (

View File

@@ -1,8 +1,8 @@
use super::common::ChannelTransport;
use arbiter_crypto::{ use arbiter_crypto::{
authn::{self, AuthChallenge, USERAGENT_CONTEXT}, authn::{self, AuthChallenge, USERAGENT_CONTEXT},
safecell::{SafeCell, SafeCellHandle as _}, safecell::{SafeCell, SafeCellHandle as _},
}; };
use arbiter_proto::transport::{Error as TransportError, Receiver, Sender}; use arbiter_proto::transport::{Error as TransportError, Receiver, Sender};
use arbiter_server::{ use arbiter_server::{
actors::{GlobalActors, bootstrap::GetToken, vault::Bootstrap}, actors::{GlobalActors, bootstrap::GetToken, vault::Bootstrap},
@@ -10,14 +10,13 @@ use arbiter_server::{
db::{self, schema}, db::{self, schema},
peers::user_agent::{self, Credentials, UserAgentConnection, auth, vault_gate}, peers::user_agent::{self, Credentials, UserAgentConnection, auth, vault_gate},
}; };
use async_trait::async_trait; use async_trait::async_trait;
use diesel::{ExpressionMethods as _, QueryDsl, insert_into}; use diesel::{ExpressionMethods as _, QueryDsl, insert_into};
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
use ml_dsa::{KeyGen, MlDsa87, SigningKey, signature::Keypair as _}; use ml_dsa::{KeyGen, MlDsa87, SigningKey, signature::Keypair as _};
use tokio::sync::mpsc; use tokio::sync::mpsc;
use super::common::ChannelTransport;
fn sign_useragent_challenge( fn sign_useragent_challenge(
key: &SigningKey<MlDsa87>, key: &SigningKey<MlDsa87>,
challenge: &AuthChallenge, challenge: &AuthChallenge,
@@ -85,7 +84,10 @@ impl Receiver<auth::Inbound> for StartServerTransport {
#[async_trait] #[async_trait]
impl Sender<Result<auth::Outbound, auth::Error>> for StartServerTransport { impl Sender<Result<auth::Outbound, auth::Error>> for StartServerTransport {
async fn send(&mut self, item: Result<auth::Outbound, auth::Error>) -> Result<(), TransportError> { async fn send(
&mut self,
item: Result<auth::Outbound, auth::Error>,
) -> Result<(), TransportError> {
self.auth_tx self.auth_tx
.send(item) .send(item)
.await .await
@@ -118,8 +120,11 @@ impl Sender<Result<vault_gate::Outbound, vault_gate::Error>> for StartServerTran
} }
} }
impl arbiter_proto::transport::Bi<vault_gate::Inbound, Result<vault_gate::Outbound, vault_gate::Error>> impl
for StartServerTransport arbiter_proto::transport::Bi<
vault_gate::Inbound,
Result<vault_gate::Outbound, vault_gate::Error>,
> for StartServerTransport
{ {
} }
@@ -142,7 +147,7 @@ impl Sender<auth::Inbound> for StartTestTransport {
#[tokio::test] #[tokio::test]
#[test_log::test] #[test_log::test]
pub async fn test_bootstrap_token_auth() { async fn test_bootstrap_token_auth() {
let db = db::create_test_pool().await; let db = db::create_test_pool().await;
let actors = GlobalActors::spawn(db.clone()).await.unwrap(); let actors = GlobalActors::spawn(db.clone()).await.unwrap();
actors actors
@@ -207,7 +212,7 @@ pub async fn test_bootstrap_token_auth() {
#[tokio::test] #[tokio::test]
#[test_log::test] #[test_log::test]
pub async fn test_bootstrap_invalid_token_auth() { async fn test_bootstrap_invalid_token_auth() {
let db = db::create_test_pool().await; let db = db::create_test_pool().await;
let actors = GlobalActors::spawn(db.clone()).await.unwrap(); let actors = GlobalActors::spawn(db.clone()).await.unwrap();
@@ -260,7 +265,7 @@ pub async fn test_bootstrap_invalid_token_auth() {
#[tokio::test] #[tokio::test]
#[test_log::test] #[test_log::test]
pub async fn test_challenge_auth() { async fn test_challenge_auth() {
let db = db::create_test_pool().await; let db = db::create_test_pool().await;
let actors = GlobalActors::spawn(db.clone()).await.unwrap(); let actors = GlobalActors::spawn(db.clone()).await.unwrap();
actors actors
@@ -345,7 +350,7 @@ pub async fn test_challenge_auth() {
#[tokio::test] #[tokio::test]
#[test_log::test] #[test_log::test]
pub async fn test_challenge_auth_rejects_integrity_tag_mismatch_when_unsealed() { async fn test_challenge_auth_rejects_integrity_tag_mismatch_when_unsealed() {
let db = db::create_test_pool().await; let db = db::create_test_pool().await;
let actors = GlobalActors::spawn(db.clone()).await.unwrap(); let actors = GlobalActors::spawn(db.clone()).await.unwrap();
@@ -419,7 +424,7 @@ pub async fn test_challenge_auth_rejects_integrity_tag_mismatch_when_unsealed()
#[tokio::test] #[tokio::test]
#[test_log::test] #[test_log::test]
pub async fn test_challenge_auth_rejects_invalid_signature() { async fn test_challenge_auth_rejects_invalid_signature() {
let db = db::create_test_pool().await; let db = db::create_test_pool().await;
let actors = GlobalActors::spawn(db.clone()).await.unwrap(); let actors = GlobalActors::spawn(db.clone()).await.unwrap();
actors actors

View File

@@ -82,7 +82,7 @@ async fn client_dh_encrypt(
#[tokio::test] #[tokio::test]
#[test_log::test] #[test_log::test]
pub async fn test_unseal_success() { async fn test_unseal_success() {
let seal_key = b"test-seal-key"; let seal_key = b"test-seal-key";
let (_db, gate, _promotion_rx) = setup_sealed_gate(seal_key).await; let (_db, gate, _promotion_rx) = setup_sealed_gate(seal_key).await;
@@ -94,7 +94,7 @@ pub async fn test_unseal_success() {
#[tokio::test] #[tokio::test]
#[test_log::test] #[test_log::test]
pub async fn test_unseal_wrong_seal_key() { async fn test_unseal_wrong_seal_key() {
let (_db, gate, _promotion_rx) = setup_sealed_gate(b"correct-key").await; let (_db, gate, _promotion_rx) = setup_sealed_gate(b"correct-key").await;
let encrypted_key = client_dh_encrypt(&gate, b"wrong-key").await; let encrypted_key = client_dh_encrypt(&gate, b"wrong-key").await;
@@ -110,7 +110,7 @@ pub async fn test_unseal_wrong_seal_key() {
#[tokio::test] #[tokio::test]
#[test_log::test] #[test_log::test]
pub async fn test_unseal_corrupted_ciphertext() { async fn test_unseal_corrupted_ciphertext() {
let (_db, gate, _promotion_rx) = setup_sealed_gate(b"test-key").await; let (_db, gate, _promotion_rx) = setup_sealed_gate(b"test-key").await;
let client_secret = EphemeralSecret::random(); let client_secret = EphemeralSecret::random();
@@ -140,7 +140,7 @@ pub async fn test_unseal_corrupted_ciphertext() {
#[tokio::test] #[tokio::test]
#[test_log::test] #[test_log::test]
pub async fn test_unseal_retry_after_invalid_key() { async fn test_unseal_retry_after_invalid_key() {
let seal_key = b"real-seal-key"; let seal_key = b"real-seal-key";
let (_db, gate, _promotion_rx) = setup_sealed_gate(seal_key).await; let (_db, gate, _promotion_rx) = setup_sealed_gate(seal_key).await;

View File

@@ -1,5 +1,4 @@
use std::collections::{HashMap, HashSet}; use crate::common;
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use arbiter_server::{ use arbiter_server::{
actors::{ actors::{
@@ -12,10 +11,9 @@ use arbiter_server::{
use diesel::{ExpressionMethods as _, QueryDsl, SelectableHelper, dsl::sql_query}; use diesel::{ExpressionMethods as _, QueryDsl, SelectableHelper, dsl::sql_query};
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
use kameo::actor::{ActorRef, Spawn as _}; use kameo::actor::{ActorRef, Spawn as _};
use std::collections::{HashMap, HashSet};
use tokio::task::JoinSet; use tokio::task::JoinSet;
use crate::common;
async fn write_concurrently( async fn write_concurrently(
actor: ActorRef<Vault>, actor: ActorRef<Vault>,
prefix: &'static str, prefix: &'static str,

View File

@@ -1,3 +1,4 @@
use crate::common;
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use arbiter_server::{ use arbiter_server::{
actors::{ actors::{
@@ -11,8 +12,6 @@ use arbiter_server::{
use diesel::{QueryDsl, SelectableHelper}; use diesel::{QueryDsl, SelectableHelper};
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
use crate::common;
#[tokio::test] #[tokio::test]
#[test_log::test] #[test_log::test]
async fn test_bootstrap() { async fn test_bootstrap() {

View File

@@ -1,5 +1,4 @@
use std::collections::HashSet; use crate::common;
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use arbiter_server::{ use arbiter_server::{
actors::vault::Error, actors::vault::Error,
@@ -9,8 +8,7 @@ use arbiter_server::{
use diesel::{ExpressionMethods as _, QueryDsl, SelectableHelper, dsl::update}; use diesel::{ExpressionMethods as _, QueryDsl, SelectableHelper, dsl::update};
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
use std::collections::HashSet;
use crate::common;
#[tokio::test] #[tokio::test]
#[test_log::test] #[test_log::test]