refactor-integrity-check #90
@@ -2,17 +2,9 @@ syntax = "proto3";
|
||||
|
||||
package arbiter.user_agent.auth;
|
||||
|
||||
enum KeyType {
|
||||
KEY_TYPE_UNSPECIFIED = 0;
|
||||
KEY_TYPE_ED25519 = 1;
|
||||
KEY_TYPE_ECDSA_SECP256K1 = 2;
|
||||
KEY_TYPE_RSA = 3;
|
||||
}
|
||||
|
||||
message AuthChallengeRequest {
|
||||
bytes pubkey = 1;
|
||||
optional string bootstrap_token = 2;
|
||||
KeyType key_type = 3;
|
||||
}
|
||||
|
||||
message AuthChallenge {
|
||||
|
||||
@@ -8,7 +8,10 @@ use kameo::{
|
||||
|
||||
use crate::{
|
||||
actors::flow_coordinator::ApprovalError,
|
||||
peers::{client::ClientProfile, user_agent::{UserAgentSession, session::BeginNewClientApproval}},
|
||||
peers::{
|
||||
client::ClientProfile,
|
||||
user_agent::{UserAgentSession, session::BeginNewClientApproval},
|
||||
},
|
||||
};
|
||||
|
||||
pub struct Args {
|
||||
|
||||
@@ -9,7 +9,13 @@ use kameo::{
|
||||
};
|
||||
use tracing::info;
|
||||
|
||||
use crate::{actors::flow_coordinator::client_connect_approval::ClientApprovalController, peers::{client::{ClientProfile, session::ClientSession}, user_agent::UserAgentSession}};
|
||||
use crate::{
|
||||
actors::flow_coordinator::client_connect_approval::ClientApprovalController,
|
||||
peers::{
|
||||
client::{ClientProfile, session::ClientSession},
|
||||
user_agent::UserAgentSession,
|
||||
},
|
||||
};
|
||||
|
||||
pub mod client_connect_approval;
|
||||
|
||||
|
||||
@@ -4,8 +4,7 @@ use thiserror::Error;
|
||||
|
||||
use crate::{
|
||||
actors::{
|
||||
bootstrap::Bootstrapper, evm::EvmActor, flow_coordinator::FlowCoordinator,
|
||||
vault::Vault,
|
||||
bootstrap::Bootstrapper, evm::EvmActor, flow_coordinator::FlowCoordinator, vault::Vault,
|
||||
},
|
||||
db,
|
||||
};
|
||||
|
||||
@@ -147,7 +147,7 @@ impl Vault {
|
||||
Ok(nonce)
|
||||
}
|
||||
|
||||
fn expect_unsealed<'a>(state: &'a mut State) -> Result<&'a mut Unsealed, Error> {
|
||||
fn expect_unsealed(state: &mut State) -> Result<&mut Unsealed, Error> {
|
||||
match state {
|
||||
State::Unsealed(unsealed) => Ok(unsealed),
|
||||
State::Unbootstrapped => Err(Error::NotBootstrapped),
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use crate::{actors::vault, crypto::integrity::hashing::Hashable};
|
||||
use arbiter_crypto::safecell::SafeCellHandle as _;
|
||||
use hmac::{Hmac, Mac as _};
|
||||
use crate::{
|
||||
actors::vault::{self, GetState},
|
||||
crypto::integrity::hashing::Hashable,
|
||||
};
|
||||
use hmac::Hmac;
|
||||
use sha2::Sha256;
|
||||
|
||||
use diesel::{ExpressionMethods as _, QueryDsl, dsl::insert_into, sqlite::Sqlite};
|
||||
@@ -199,6 +201,11 @@ pub async fn verify_entity<E: Integrable>(
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn is_signing_available(vault: &ActorRef<Vault>) -> Result<bool, Error> {
|
||||
let state = vault.ask(GetState).await.map_err(|_| Error::VaultSend)?;
|
||||
Ok(matches!(state, vault::VaultState::Unsealed))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use diesel::{ExpressionMethods as _, QueryDsl};
|
||||
@@ -208,7 +215,10 @@ mod tests {
|
||||
use sha2::Digest;
|
||||
|
||||
use crate::{
|
||||
actors::{GlobalActors, vault::{Bootstrap, Vault}},
|
||||
actors::{
|
||||
GlobalActors,
|
||||
vault::{Bootstrap, Vault},
|
||||
},
|
||||
db::{self, schema},
|
||||
};
|
||||
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
|
||||
|
||||
@@ -10,8 +10,8 @@ use tonic::Status;
|
||||
use tracing::{info, warn};
|
||||
|
||||
use crate::{
|
||||
peers::client::{ClientConnection, session::ClientSession},
|
||||
grpc::request_tracker::RequestTracker,
|
||||
peers::client::{ClientConnection, session::ClientSession},
|
||||
};
|
||||
|
||||
mod auth;
|
||||
|
||||
@@ -22,8 +22,8 @@ use tonic::Status;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::{
|
||||
peers::client::{self, ClientConnection, auth},
|
||||
grpc::request_tracker::RequestTracker,
|
||||
peers::client::{self, ClientConnection, auth},
|
||||
};
|
||||
|
||||
pub struct AuthTransportAdapter<'a> {
|
||||
|
||||
@@ -16,11 +16,11 @@ use tonic::Status;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::{
|
||||
peers::client::session::{ClientSession, HandleSignTransaction, SignTransactionRpcError},
|
||||
grpc::{
|
||||
Convert, TryConvert,
|
||||
common::inbound::{RawEvmAddress, RawEvmTransaction},
|
||||
},
|
||||
peers::client::session::{ClientSession, HandleSignTransaction, SignTransactionRpcError},
|
||||
};
|
||||
|
||||
fn wrap_response(payload: EvmResponsePayload) -> ClientResponsePayload {
|
||||
|
||||
@@ -13,8 +13,8 @@ use tonic::Status;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::{
|
||||
peers::client::session::{ClientSession, Error, HandleQueryVaultState},
|
||||
actors::vault::VaultState,
|
||||
peers::client::session::{ClientSession, Error, HandleQueryVaultState},
|
||||
};
|
||||
|
||||
pub(super) async fn dispatch(
|
||||
|
||||
@@ -10,8 +10,8 @@ use tonic::{Request, Response, Status, async_trait};
|
||||
use tracing::info;
|
||||
|
||||
use crate::{
|
||||
peers::{client::ClientConnection, user_agent::UserAgentConnection},
|
||||
grpc::user_agent::start,
|
||||
peers::{client::ClientConnection, user_agent::UserAgentConnection},
|
||||
};
|
||||
|
||||
mod request_tracker;
|
||||
|
||||
@@ -14,8 +14,8 @@ use tonic::Status;
|
||||
use tracing::{error, info, warn};
|
||||
|
||||
use crate::{
|
||||
peers::user_agent::{OutOfBand, UserAgentConnection, UserAgentSession},
|
||||
grpc::request_tracker::RequestTracker,
|
||||
peers::user_agent::{OutOfBand, UserAgentConnection, UserAgentSession},
|
||||
};
|
||||
|
||||
mod auth;
|
||||
@@ -124,7 +124,7 @@ pub async fn start(
|
||||
) {
|
||||
let mut request_tracker = RequestTracker::default();
|
||||
|
||||
let pubkey = match auth::start(&mut conn, &mut bi, &mut request_tracker).await {
|
||||
let (id, pubkey) = match auth::start(&mut conn, &mut bi, &mut request_tracker).await {
|
||||
Ok(pubkey) => pubkey,
|
||||
Err(e) => {
|
||||
warn!(error = ?e, "Authentication failed");
|
||||
@@ -132,13 +132,19 @@ pub async fn start(
|
||||
}
|
||||
};
|
||||
|
||||
info!(?pubkey, "User authenticated successfully");
|
||||
|
||||
let (oob_sender, oob_receiver) = mpsc::channel(16);
|
||||
let oob_adapter = OutOfBandAdapter(oob_sender);
|
||||
|
||||
let actor = UserAgentSession::spawn(UserAgentSession::new(conn, Box::new(oob_adapter)));
|
||||
let actor = UserAgentSession::spawn(UserAgentSession::new(
|
||||
conn,
|
||||
id,
|
||||
pubkey,
|
||||
Box::new(oob_adapter),
|
||||
));
|
||||
let actor_for_cleanup = actor.clone();
|
||||
|
||||
info!(?pubkey, "User authenticated successfully");
|
||||
dispatch_loop(bi, actor, oob_receiver, request_tracker).await;
|
||||
actor_for_cleanup.kill();
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ use tonic::Status;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::{
|
||||
peers::user_agent::{UserAgentConnection, auth},
|
||||
grpc::request_tracker::RequestTracker,
|
||||
peers::user_agent::{UserAgentConnection, auth},
|
||||
};
|
||||
|
||||
pub struct AuthTransportAdapter<'a> {
|
||||
@@ -140,7 +140,6 @@ impl Receiver<auth::Inbound> for AuthTransportAdapter<'_> {
|
||||
AuthRequestPayload::ChallengeRequest(ProtoAuthChallengeRequest {
|
||||
pubkey,
|
||||
bootstrap_token,
|
||||
key_type: _,
|
||||
}) => {
|
||||
let Ok(pubkey) = authn::PublicKey::try_from(pubkey.as_slice()) else {
|
||||
warn!(
|
||||
@@ -168,7 +167,7 @@ pub async fn start(
|
||||
conn: &mut UserAgentConnection,
|
||||
bi: &mut GrpcBi<UserAgentRequest, UserAgentResponse>,
|
||||
request_tracker: &mut RequestTracker,
|
||||
) -> Result<authn::PublicKey, auth::Error> {
|
||||
) -> Result<(i32, authn::PublicKey), auth::Error> {
|
||||
let transport = AuthTransportAdapter::new(bi, request_tracker);
|
||||
auth::authenticate(conn, transport).await
|
||||
}
|
||||
|
||||
@@ -23,6 +23,10 @@ use tonic::Status;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::{
|
||||
grpc::{
|
||||
Convert, TryConvert,
|
||||
common::inbound::{RawEvmAddress, RawEvmTransaction},
|
||||
},
|
||||
peers::user_agent::{
|
||||
UserAgentSession,
|
||||
session::connection::{
|
||||
@@ -31,10 +35,6 @@ use crate::{
|
||||
SignTransactionError as SessionSignTransactionError,
|
||||
},
|
||||
},
|
||||
grpc::{
|
||||
Convert, TryConvert,
|
||||
common::inbound::{RawEvmAddress, RawEvmTransaction},
|
||||
},
|
||||
};
|
||||
|
||||
fn wrap_evm_response(payload: EvmResponsePayload) -> UserAgentResponsePayload {
|
||||
|
||||
@@ -21,6 +21,8 @@ use tonic::Status;
|
||||
use tracing::{info, warn};
|
||||
|
||||
use crate::{
|
||||
db::models::NewEvmWalletAccess,
|
||||
grpc::Convert,
|
||||
peers::user_agent::{
|
||||
OutOfBand, UserAgentSession,
|
||||
session::connection::{
|
||||
@@ -28,8 +30,6 @@ use crate::{
|
||||
HandleRevokeEvmWalletAccess, HandleSdkClientList,
|
||||
},
|
||||
},
|
||||
db::models::NewEvmWalletAccess,
|
||||
grpc::Convert,
|
||||
};
|
||||
|
||||
fn wrap_sdk_client_response(payload: SdkClientResponsePayload) -> UserAgentResponsePayload {
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
use crate::context::ServerContext;
|
||||
|
||||
pub mod actors;
|
||||
pub mod peers;
|
||||
pub mod context;
|
||||
pub mod crypto;
|
||||
pub mod db;
|
||||
pub mod evm;
|
||||
pub mod grpc;
|
||||
pub mod peers;
|
||||
pub mod utils;
|
||||
|
||||
pub struct Server {
|
||||
|
||||
@@ -14,7 +14,9 @@ use tracing::error;
|
||||
|
||||
use crate::{
|
||||
actors::{
|
||||
GlobalActors, flow_coordinator::{self, RequestClientApproval}, vault::Vault
|
||||
GlobalActors,
|
||||
flow_coordinator::{self, RequestClientApproval},
|
||||
vault::Vault,
|
||||
},
|
||||
crypto::integrity::{self, AttestationStatus},
|
||||
db::{
|
||||
@@ -187,10 +189,7 @@ async fn create_nonce(
|
||||
.await
|
||||
}
|
||||
|
||||
async fn approve_new_client(
|
||||
actors: &GlobalActors,
|
||||
profile: ClientProfile,
|
||||
) -> Result<(), Error> {
|
||||
async fn approve_new_client(actors: &GlobalActors, profile: ClientProfile) -> Result<(), Error> {
|
||||
let result = actors
|
||||
.flow_coordinator
|
||||
.ask(RequestClientApproval { client: profile })
|
||||
|
||||
@@ -6,7 +6,8 @@ use tracing::{error, info};
|
||||
use crate::{
|
||||
actors::GlobalActors,
|
||||
crypto::integrity::{Integrable, hashing::Hashable},
|
||||
db, peers::client::session::ClientSession,
|
||||
db,
|
||||
peers::client::session::ClientSession,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
pub mod client;
|
||||
pub mod user_agent;
|
||||
pub mod client;
|
||||
@@ -69,7 +69,7 @@ fn parse_auth_event(payload: Inbound) -> AuthEvents {
|
||||
pub async fn authenticate<T>(
|
||||
props: &mut UserAgentConnection,
|
||||
transport: T,
|
||||
) -> Result<authn::PublicKey, Error>
|
||||
) -> Result<(i32, authn::PublicKey), Error>
|
||||
where
|
||||
T: Bi<Inbound, Result<Outbound, Error>> + Send,
|
||||
{
|
||||
@@ -82,7 +82,7 @@ where
|
||||
};
|
||||
|
||||
match state.process_event(parse_auth_event(payload)).await {
|
||||
Ok(AuthStates::AuthOk(key)) => return Ok(key.clone()),
|
||||
Ok(AuthStates::AuthOk(result)) => return Ok((result.id, result.pubkey.clone())),
|
||||
Err(AuthError::ActionFailed(err)) => {
|
||||
error!(?err, "State machine action failed");
|
||||
return Err(err);
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
use super::super::{UserAgentConnection, UserAgentCredentials};
|
||||
use arbiter_crypto::authn::{self, USERAGENT_CONTEXT};
|
||||
use arbiter_proto::transport::Bi;
|
||||
use diesel::{ExpressionMethods as _, OptionalExtension as _, QueryDsl, update};
|
||||
use diesel_async::{AsyncConnection, RunQueryDsl};
|
||||
use kameo::actor::ActorRef;
|
||||
use tracing::error;
|
||||
use super::super::{UserAgentCredentials, UserAgentConnection};
|
||||
|
||||
use super::Error;
|
||||
use crate::peers::user_agent::auth::Outbound;
|
||||
use crate::{
|
||||
actors::{
|
||||
bootstrap::ConsumeToken,
|
||||
vault::Vault,
|
||||
},
|
||||
actors::{bootstrap::ConsumeToken, vault::Vault},
|
||||
crypto::integrity,
|
||||
db::{DatabasePool, schema::useragent_client},
|
||||
};
|
||||
@@ -27,6 +24,7 @@ pub struct BootstrapAuthRequest {
|
||||
}
|
||||
|
||||
pub struct ChallengeContext {
|
||||
pub id: i32,
|
||||
pub challenge_nonce: i32,
|
||||
pub key: authn::PublicKey,
|
||||
}
|
||||
@@ -35,13 +33,18 @@ pub struct ChallengeSolution {
|
||||
pub solution: Vec<u8>,
|
||||
}
|
||||
|
||||
pub struct AuthOk {
|
||||
pub id: i32,
|
||||
pub pubkey: authn::PublicKey,
|
||||
}
|
||||
|
||||
smlang::statemachine!(
|
||||
name: Auth,
|
||||
custom_error: true,
|
||||
transitions: {
|
||||
*Init + AuthRequest(ChallengeRequest) / async prepare_challenge = SentChallenge(ChallengeContext),
|
||||
Init + BootstrapAuthRequest(BootstrapAuthRequest) / async verify_bootstrap_token = AuthOk(authn::PublicKey),
|
||||
SentChallenge(ChallengeContext) + ReceivedSolution(ChallengeSolution) / async verify_solution = AuthOk(authn::PublicKey),
|
||||
Init + BootstrapAuthRequest(BootstrapAuthRequest) / async verify_bootstrap_token = AuthOk(AuthOk),
|
||||
SentChallenge(ChallengeContext) + ReceivedSolution(ChallengeSolution) / async verify_solution = AuthOk(AuthOk),
|
||||
}
|
||||
);
|
||||
|
||||
@@ -110,12 +113,12 @@ async fn create_nonce(
|
||||
db: &DatabasePool,
|
||||
vault: &ActorRef<Vault>,
|
||||
pubkey: &authn::PublicKey,
|
||||
) -> Result<i32, Error> {
|
||||
) -> Result<(i32, i32), Error> {
|
||||
let mut db_conn = db.get().await.map_err(|e| {
|
||||
error!(error = ?e, "Database pool error");
|
||||
Error::internal("Database unavailable")
|
||||
})?;
|
||||
let new_nonce = db_conn
|
||||
let (id, new_nonce) = db_conn
|
||||
.exclusive_transaction(|conn| {
|
||||
Box::pin(async move {
|
||||
let (id, new_nonce): (i32, i32) = update(useragent_client::table)
|
||||
@@ -144,59 +147,36 @@ async fn create_nonce(
|
||||
Error::internal("Database error")
|
||||
})?;
|
||||
|
||||
Result::<_, Error>::Ok(new_nonce)
|
||||
Result::<_, Error>::Ok((id, new_nonce))
|
||||
})
|
||||
})
|
||||
.await?;
|
||||
Ok(new_nonce)
|
||||
Ok((id, new_nonce))
|
||||
}
|
||||
|
||||
async fn register_key(
|
||||
db: &DatabasePool,
|
||||
vault: &ActorRef<Vault>,
|
||||
pubkey: &authn::PublicKey,
|
||||
) -> Result<(), Error> {
|
||||
async fn register_key(db: &DatabasePool, pubkey: &authn::PublicKey) -> Result<i32, Error> {
|
||||
let pubkey_bytes = pubkey.to_bytes();
|
||||
let mut conn = db.get().await.map_err(|e| {
|
||||
error!(error = ?e, "Database pool error");
|
||||
Error::internal("Database unavailable")
|
||||
})?;
|
||||
|
||||
conn.transaction(|conn| {
|
||||
Box::pin(async move {
|
||||
const NONCE_START: i32 = 1;
|
||||
const NONCE_START: i32 = 1;
|
||||
|
||||
let id: i32 = diesel::insert_into(useragent_client::table)
|
||||
.values((
|
||||
useragent_client::public_key.eq(pubkey_bytes),
|
||||
useragent_client::nonce.eq(NONCE_START),
|
||||
))
|
||||
.returning(useragent_client::id)
|
||||
.get_result(conn)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!(error = ?e, "Database error");
|
||||
Error::internal("Database operation failed")
|
||||
})?;
|
||||
let id: i32 = diesel::insert_into(useragent_client::table)
|
||||
.values((
|
||||
useragent_client::public_key.eq(pubkey_bytes),
|
||||
useragent_client::nonce.eq(NONCE_START),
|
||||
))
|
||||
.returning(useragent_client::id)
|
||||
.get_result(&mut conn)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!(error = ?e, "Database error");
|
||||
Error::internal("Database operation failed")
|
||||
})?;
|
||||
|
||||
let entity = UserAgentCredentials {
|
||||
pubkey: pubkey.clone(),
|
||||
nonce: NONCE_START,
|
||||
};
|
||||
|
||||
integrity::sign_entity(conn, vault, &entity, id)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!(error = ?e, "Failed to sign integrity tag for new user-agent key");
|
||||
Error::internal("Failed to register public key")
|
||||
})?;
|
||||
|
||||
Result::<_, Error>::Ok(())
|
||||
})
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
pub struct AuthContext<'a, T> {
|
||||
@@ -222,7 +202,7 @@ where
|
||||
) -> Result<ChallengeContext, Self::Error> {
|
||||
verify_integrity(&self.conn.db, &self.conn.actors.vault, &pubkey).await?;
|
||||
|
||||
let nonce = create_nonce(&self.conn.db, &self.conn.actors.vault, &pubkey).await?;
|
||||
let (id, nonce) = create_nonce(&self.conn.db, &self.conn.actors.vault, &pubkey).await?;
|
||||
|
||||
self.transport
|
||||
.send(Ok(Outbound::AuthChallenge { nonce }))
|
||||
@@ -233,6 +213,7 @@ where
|
||||
})?;
|
||||
|
||||
Ok(ChallengeContext {
|
||||
id,
|
||||
challenge_nonce: nonce,
|
||||
key: pubkey,
|
||||
})
|
||||
@@ -243,7 +224,7 @@ where
|
||||
async fn verify_bootstrap_token(
|
||||
&mut self,
|
||||
BootstrapAuthRequest { pubkey, token }: BootstrapAuthRequest,
|
||||
) -> Result<authn::PublicKey, Self::Error> {
|
||||
) -> Result<AuthOk, Self::Error> {
|
||||
let token_ok: bool = self
|
||||
.conn
|
||||
.actors
|
||||
@@ -264,12 +245,12 @@ where
|
||||
|
||||
match token_ok {
|
||||
true => {
|
||||
register_key(&self.conn.db, &self.conn.actors.vault, &pubkey).await?;
|
||||
let id = register_key(&self.conn.db, &pubkey).await?;
|
||||
self.transport
|
||||
.send(Ok(Outbound::AuthSuccess))
|
||||
.await
|
||||
.map_err(|_| Error::Transport)?;
|
||||
Ok(pubkey)
|
||||
Ok(AuthOk { id, pubkey })
|
||||
}
|
||||
false => {
|
||||
error!("Invalid bootstrap token provided");
|
||||
@@ -287,11 +268,12 @@ where
|
||||
async fn verify_solution(
|
||||
&mut self,
|
||||
ChallengeContext {
|
||||
id,
|
||||
challenge_nonce,
|
||||
key,
|
||||
}: &ChallengeContext,
|
||||
ChallengeSolution { solution }: ChallengeSolution,
|
||||
) -> Result<authn::PublicKey, Self::Error> {
|
||||
) -> Result<AuthOk, Self::Error> {
|
||||
let signature = authn::Signature::try_from(solution.as_slice()).map_err(|_| {
|
||||
error!("Failed to decode signature in challenge solution");
|
||||
Error::InvalidChallengeSolution
|
||||
@@ -305,7 +287,7 @@ where
|
||||
.send(Ok(Outbound::AuthSuccess))
|
||||
.await
|
||||
.map_err(|_| Error::Transport)?;
|
||||
Ok(key.clone())
|
||||
Ok(AuthOk { id: *id, pubkey: key.clone() })
|
||||
}
|
||||
false => {
|
||||
self.transport
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
use crate::{
|
||||
actors::GlobalActors,
|
||||
crypto::integrity::Integrable,
|
||||
db, peers::client::ClientProfile,
|
||||
actors::GlobalActors, crypto::integrity::Integrable, db, peers::client::ClientProfile,
|
||||
};
|
||||
use arbiter_crypto::authn;
|
||||
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
use arbiter_crypto::authn;
|
||||
use diesel::{ExpressionMethods, QueryDsl};
|
||||
use diesel_async::{AsyncConnection, RunQueryDsl};
|
||||
use kameo_actors::message_bus::Register;
|
||||
|
||||
use std::{borrow::Cow, collections::HashMap};
|
||||
|
||||
use arbiter_proto::transport::Sender;
|
||||
use async_trait::async_trait;
|
||||
use kameo::{Actor, actor::ActorRef, messages};
|
||||
use kameo::{Actor, actor::ActorRef, messages, prelude::Message};
|
||||
use thiserror::Error;
|
||||
use tracing::error;
|
||||
|
||||
use crate::{actors::flow_coordinator::{RegisterUserAgent, client_connect_approval::ClientApprovalController}, peers::client::ClientProfile};
|
||||
use crate::{
|
||||
actors::{
|
||||
flow_coordinator::{RegisterUserAgent, client_connect_approval::ClientApprovalController},
|
||||
vault::events,
|
||||
}, crypto::integrity, db::schema::useragent_client, peers::{client::ClientProfile, user_agent::UserAgentCredentials}
|
||||
};
|
||||
mod state;
|
||||
use state::{DummyContext, UserAgentEvents, UserAgentStateMachine};
|
||||
|
||||
@@ -50,6 +58,8 @@ pub struct PendingClientApproval {
|
||||
}
|
||||
|
||||
pub struct UserAgentSession {
|
||||
id: i32,
|
||||
pubkey: authn::PublicKey,
|
||||
props: UserAgentConnection,
|
||||
state: UserAgentStateMachine<DummyContext>,
|
||||
sender: Box<dyn Sender<OutOfBand>>,
|
||||
@@ -60,31 +70,22 @@ pub struct UserAgentSession {
|
||||
pub mod connection;
|
||||
|
||||
impl UserAgentSession {
|
||||
pub(crate) fn new(props: UserAgentConnection, sender: Box<dyn Sender<OutOfBand>>) -> Self {
|
||||
pub(crate) fn new(
|
||||
props: UserAgentConnection,
|
||||
id: i32,
|
||||
pubkey: authn::PublicKey,
|
||||
sender: Box<dyn Sender<OutOfBand>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
id,
|
||||
props,
|
||||
pubkey,
|
||||
state: UserAgentStateMachine::new(DummyContext),
|
||||
sender,
|
||||
pending_client_approvals: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_test(db: crate::db::DatabasePool, actors: crate::actors::GlobalActors) -> Self {
|
||||
struct DummySender;
|
||||
|
||||
#[async_trait]
|
||||
impl Sender<OutOfBand> for DummySender {
|
||||
async fn send(
|
||||
&mut self,
|
||||
_item: OutOfBand,
|
||||
) -> Result<(), arbiter_proto::transport::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Self::new(UserAgentConnection::new(db, actors), Box::new(DummySender))
|
||||
}
|
||||
|
||||
fn transition(&mut self, event: UserAgentEvents) -> Result<(), Error> {
|
||||
self.state.process_event(event).map_err(|e| {
|
||||
error!(?e, "State transition failed");
|
||||
@@ -127,6 +128,61 @@ impl UserAgentSession {
|
||||
}
|
||||
}
|
||||
|
||||
impl Message<events::VaultBootstrapped> for UserAgentSession {
|
||||
type Reply = Result<(), Error>;
|
||||
|
||||
async fn handle(
|
||||
&mut self,
|
||||
_: events::VaultBootstrapped,
|
||||
ctx: &mut kameo::prelude::Context<Self, Self::Reply>,
|
||||
) -> Self::Reply {
|
||||
let Ok(mut conn) = self.props.db.get().await else {
|
||||
error!("Failed to get database connection for vault bootstrapped event");
|
||||
ctx.stop();
|
||||
return Err(Error::internal("Failed to get database connection"));
|
||||
};
|
||||
|
||||
|
||||
let result = conn.exclusive_transaction(|conn| {
|
||||
Box::pin(async {
|
||||
let nonce: i32 = useragent_client::table
|
||||
.filter(useragent_client::id.eq(self.id))
|
||||
.select(useragent_client::nonce)
|
||||
.first::<i32>(conn)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!(?e, "Failed to get nonce for useragent bootstrapping");
|
||||
Error::internal("Failed to sign user agent credentials")
|
||||
})?;
|
||||
|
||||
let entity = UserAgentCredentials {
|
||||
pubkey: self.pubkey.clone(),
|
||||
nonce,
|
||||
};
|
||||
|
||||
integrity::sign_entity(conn, &self.props.actors.vault, &entity, self.id)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!(?e, "Failed to sign user agent credentials during vault bootstrapping");
|
||||
Error::internal("Failed to sign user agent credentials")
|
||||
})?;
|
||||
|
||||
Result::<_, Error>::Ok(())
|
||||
})
|
||||
}).await;
|
||||
|
||||
match result {
|
||||
Ok(_) => Ok(()),
|
||||
Err(err) => {
|
||||
error!(?err, "Error during vault bootstrapping");
|
||||
ctx.stop();
|
||||
Err(err)
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
impl Actor for UserAgentSession {
|
||||
type Args = Self;
|
||||
|
||||
@@ -136,6 +192,21 @@ impl Actor for UserAgentSession {
|
||||
args: Self::Args,
|
||||
this: kameo::prelude::ActorRef<Self>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
args.props
|
||||
.actors
|
||||
.events
|
||||
.tell(Register(
|
||||
this.clone().recipient::<events::VaultBootstrapped>(),
|
||||
))
|
||||
.await
|
||||
.map_err(|err| {
|
||||
error!(
|
||||
?err,
|
||||
"Failed to register user agent connection with event bus"
|
||||
);
|
||||
Error::internal("Failed to register user agent connection with event bus")
|
||||
})?;
|
||||
|
||||
args.props
|
||||
.actors
|
||||
.flow_coordinator
|
||||
|
||||
@@ -14,7 +14,7 @@ use kameo::prelude::Context;
|
||||
use tracing::{error, info};
|
||||
use x25519_dalek::{EphemeralSecret, PublicKey};
|
||||
|
||||
use crate::{actors::vault::VaultState, peers::user_agent::session::state::{UnsealContext, UserAgentEvents}};
|
||||
use crate::actors::flow_coordinator::client_connect_approval::ClientApprovalAnswer;
|
||||
use crate::actors::{
|
||||
evm::{
|
||||
ClientSignTransaction, Generate, ListWallets, SignTransactionError as EvmSignError,
|
||||
@@ -27,10 +27,11 @@ use crate::db::models::{
|
||||
};
|
||||
use crate::evm::policies::{Grant, SpecificGrant};
|
||||
use crate::{
|
||||
actors::flow_coordinator::client_connect_approval::ClientApprovalAnswer,
|
||||
actors::vault::VaultState,
|
||||
peers::user_agent::session::state::{UnsealContext, UserAgentEvents},
|
||||
};
|
||||
|
||||
use super::{UserAgentSession, state, Error};
|
||||
use super::{Error, UserAgentSession, state};
|
||||
|
||||
impl UserAgentSession {
|
||||
fn take_unseal_secret(&mut self) -> Result<(EphemeralSecret, PublicKey), Error> {
|
||||
|
||||
@@ -5,14 +5,10 @@ use arbiter_crypto::{
|
||||
use arbiter_proto::ClientMetadata;
|
||||
use arbiter_proto::transport::{Receiver, Sender};
|
||||
use arbiter_server::{
|
||||
actors::{
|
||||
GlobalActors,
|
||||
|
||||
vault::Bootstrap,
|
||||
},
|
||||
peers::client::{ClientConnection, ClientCredentials, auth, connect_client},
|
||||
actors::{GlobalActors, vault::Bootstrap},
|
||||
crypto::integrity,
|
||||
db::{self, schema},
|
||||
peers::client::{ClientConnection, ClientCredentials, auth, connect_client},
|
||||
};
|
||||
use diesel::{ExpressionMethods as _, NullableExpressionMethods as _, QueryDsl as _, insert_into};
|
||||
use diesel_async::RunQueryDsl;
|
||||
|
||||
@@ -12,7 +12,9 @@ use tokio::sync::mpsc;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn bootstrapped_vault(db: &db::DatabasePool) -> Vault {
|
||||
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()).await.unwrap();
|
||||
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus())
|
||||
.await
|
||||
.unwrap();
|
||||
actor
|
||||
.bootstrap(SafeCell::new(b"test-seal-key".to_vec()))
|
||||
.await
|
||||
|
||||
@@ -5,15 +5,10 @@ use arbiter_crypto::{
|
||||
|
||||
use arbiter_proto::transport::{Receiver, Sender};
|
||||
use arbiter_server::{
|
||||
actors::{
|
||||
GlobalActors,
|
||||
bootstrap::GetToken,
|
||||
vault::Bootstrap,
|
||||
|
||||
},
|
||||
peers::user_agent::{UserAgentConnection, UserAgentCredentials, auth},
|
||||
actors::{GlobalActors, bootstrap::GetToken, vault::Bootstrap},
|
||||
crypto::integrity,
|
||||
db::{self, schema},
|
||||
peers::user_agent::{UserAgentConnection, UserAgentCredentials, auth},
|
||||
};
|
||||
use diesel::{ExpressionMethods as _, QueryDsl, insert_into};
|
||||
use diesel_async::RunQueryDsl;
|
||||
|
||||
@@ -3,13 +3,12 @@ use arbiter_server::{
|
||||
actors::{
|
||||
GlobalActors,
|
||||
vault::{Bootstrap, Seal},
|
||||
|
||||
},
|
||||
peers::user_agent::{
|
||||
UserAgentSession,
|
||||
session::connection::{HandleUnsealEncryptedKey, HandleUnsealRequest, UnsealError},
|
||||
},
|
||||
db,
|
||||
peers::user_agent::{
|
||||
UserAgentSession,
|
||||
session::connection::{HandleUnsealEncryptedKey, HandleUnsealRequest, UnsealError},
|
||||
},
|
||||
};
|
||||
|
||||
use chacha20poly1305::{AeadInPlace, XChaCha20Poly1305, XNonce, aead::KeyInit};
|
||||
|
||||
@@ -2,7 +2,10 @@ use std::collections::{HashMap, HashSet};
|
||||
|
||||
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
|
||||
use arbiter_server::{
|
||||
actors::{GlobalActors, vault::{CreateNew, Error, Vault}},
|
||||
actors::{
|
||||
GlobalActors,
|
||||
vault::{CreateNew, Error, Vault},
|
||||
},
|
||||
db::{self, models, schema},
|
||||
};
|
||||
|
||||
@@ -161,7 +164,9 @@ async fn decrypt_roundtrip_after_high_concurrency() {
|
||||
let writes = write_concurrently(actor, "roundtrip", 40).await;
|
||||
let expected: HashMap<i32, Vec<u8>> = writes.into_iter().collect();
|
||||
|
||||
let mut decryptor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()).await.unwrap();
|
||||
let mut decryptor = Vault::new(db.clone(), GlobalActors::spawn_message_bus())
|
||||
.await
|
||||
.unwrap();
|
||||
decryptor
|
||||
.try_unseal(SafeCell::new(b"test-seal-key".to_vec()))
|
||||
.await
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
|
||||
use arbiter_server::{
|
||||
actors::{GlobalActors, vault::{Error, Vault}},
|
||||
actors::{
|
||||
GlobalActors,
|
||||
vault::{Error, Vault},
|
||||
},
|
||||
crypto::encryption::v1::{Nonce, ROOT_KEY_TAG},
|
||||
db::{self, models, schema},
|
||||
peers::user_agent::{
|
||||
UserAgentSession,
|
||||
session::connection::{HandleUnsealEncryptedKey, HandleUnsealRequest, UnsealError},
|
||||
},
|
||||
};
|
||||
|
||||
use diesel::{QueryDsl, SelectableHelper};
|
||||
@@ -18,7 +17,9 @@ use crate::common;
|
||||
#[test_log::test]
|
||||
async fn test_bootstrap() {
|
||||
let db = db::create_test_pool().await;
|
||||
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()).await.unwrap();
|
||||
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let seal_key = SafeCell::new(b"test-seal-key".to_vec());
|
||||
actor.bootstrap(seal_key).await.unwrap();
|
||||
@@ -52,7 +53,9 @@ async fn test_bootstrap_rejects_double() {
|
||||
#[test_log::test]
|
||||
async fn test_create_new_before_bootstrap_fails() {
|
||||
let db = db::create_test_pool().await;
|
||||
let mut actor = Vault::new(db, GlobalActors::spawn_message_bus()).await.unwrap();
|
||||
let mut actor = Vault::new(db, GlobalActors::spawn_message_bus())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let err = actor
|
||||
.create_new(SafeCell::new(b"data".to_vec()))
|
||||
@@ -65,7 +68,9 @@ async fn test_create_new_before_bootstrap_fails() {
|
||||
#[test_log::test]
|
||||
async fn test_decrypt_before_bootstrap_fails() {
|
||||
let db = db::create_test_pool().await;
|
||||
let mut actor = Vault::new(db, GlobalActors::spawn_message_bus()).await.unwrap();
|
||||
let mut actor = Vault::new(db, GlobalActors::spawn_message_bus())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let err = actor.decrypt(1).await.unwrap_err();
|
||||
assert!(matches!(err, Error::NotBootstrapped));
|
||||
@@ -78,7 +83,9 @@ async fn test_new_restores_sealed_state() {
|
||||
let actor = common::bootstrapped_vault(&db).await;
|
||||
drop(actor);
|
||||
|
||||
let mut actor2 = Vault::new(db, GlobalActors::spawn_message_bus()).await.unwrap();
|
||||
let mut actor2 = Vault::new(db, GlobalActors::spawn_message_bus())
|
||||
.await
|
||||
.unwrap();
|
||||
let err = actor2.decrypt(1).await.unwrap_err();
|
||||
assert!(matches!(err, Error::NotBootstrapped));
|
||||
}
|
||||
@@ -96,7 +103,9 @@ async fn test_unseal_correct_password() {
|
||||
.unwrap();
|
||||
drop(actor);
|
||||
|
||||
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()).await.unwrap();
|
||||
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus())
|
||||
.await
|
||||
.unwrap();
|
||||
let seal_key = SafeCell::new(b"test-seal-key".to_vec());
|
||||
actor.try_unseal(seal_key).await.unwrap();
|
||||
|
||||
@@ -117,7 +126,9 @@ async fn test_unseal_wrong_then_correct_password() {
|
||||
.unwrap();
|
||||
drop(actor);
|
||||
|
||||
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()).await.unwrap();
|
||||
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let bad_key = SafeCell::new(b"wrong-password".to_vec());
|
||||
let err = actor.try_unseal(bad_key).await.unwrap_err();
|
||||
|
||||
@@ -61,11 +61,6 @@ Future<Connection> connectAndAuthorize(
|
||||
final req = ua_auth.AuthChallengeRequest(
|
||||
pubkey: pubkey,
|
||||
bootstrapToken: bootstrapToken,
|
||||
keyType: switch (key.alg) {
|
||||
KeyAlgorithm.rsa => ua_auth.KeyType.KEY_TYPE_RSA,
|
||||
KeyAlgorithm.ecdsa => ua_auth.KeyType.KEY_TYPE_ECDSA_SECP256K1,
|
||||
KeyAlgorithm.ed25519 => ua_auth.KeyType.KEY_TYPE_ED25519,
|
||||
},
|
||||
);
|
||||
final response = await connection.ask(
|
||||
UserAgentRequest(auth: ua_auth.Request(challengeRequest: req)),
|
||||
|
||||
@@ -414,6 +414,79 @@ class GasLimitExceededViolation extends $pb.GeneratedMessage {
|
||||
void clearMaxPriorityFeePerGas() => $_clearField(2);
|
||||
}
|
||||
|
||||
class EvalViolation_ChainIdMismatch extends $pb.GeneratedMessage {
|
||||
factory EvalViolation_ChainIdMismatch({
|
||||
$fixnum.Int64? expected,
|
||||
$fixnum.Int64? actual,
|
||||
}) {
|
||||
final result = create();
|
||||
if (expected != null) result.expected = expected;
|
||||
if (actual != null) result.actual = actual;
|
||||
return result;
|
||||
}
|
||||
|
||||
EvalViolation_ChainIdMismatch._();
|
||||
|
||||
factory EvalViolation_ChainIdMismatch.fromBuffer($core.List<$core.int> data,
|
||||
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||
create()..mergeFromBuffer(data, registry);
|
||||
factory EvalViolation_ChainIdMismatch.fromJson($core.String json,
|
||||
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||
create()..mergeFromJson(json, registry);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||
_omitMessageNames ? '' : 'EvalViolation.ChainIdMismatch',
|
||||
package:
|
||||
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'),
|
||||
createEmptyInstance: create)
|
||||
..a<$fixnum.Int64>(
|
||||
1, _omitFieldNames ? '' : 'expected', $pb.PbFieldType.OU6,
|
||||
defaultOrMaker: $fixnum.Int64.ZERO)
|
||||
..a<$fixnum.Int64>(2, _omitFieldNames ? '' : 'actual', $pb.PbFieldType.OU6,
|
||||
defaultOrMaker: $fixnum.Int64.ZERO)
|
||||
..hasRequiredFields = false;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
EvalViolation_ChainIdMismatch clone() => deepCopy();
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
EvalViolation_ChainIdMismatch copyWith(
|
||||
void Function(EvalViolation_ChainIdMismatch) updates) =>
|
||||
super.copyWith(
|
||||
(message) => updates(message as EvalViolation_ChainIdMismatch))
|
||||
as EvalViolation_ChainIdMismatch;
|
||||
|
||||
@$core.override
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static EvalViolation_ChainIdMismatch create() =>
|
||||
EvalViolation_ChainIdMismatch._();
|
||||
@$core.override
|
||||
EvalViolation_ChainIdMismatch createEmptyInstance() => create();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static EvalViolation_ChainIdMismatch getDefault() => _defaultInstance ??=
|
||||
$pb.GeneratedMessage.$_defaultFor<EvalViolation_ChainIdMismatch>(create);
|
||||
static EvalViolation_ChainIdMismatch? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$fixnum.Int64 get expected => $_getI64(0);
|
||||
@$pb.TagNumber(1)
|
||||
set expected($fixnum.Int64 value) => $_setInt64(0, value);
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasExpected() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearExpected() => $_clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$fixnum.Int64 get actual => $_getI64(1);
|
||||
@$pb.TagNumber(2)
|
||||
set actual($fixnum.Int64 value) => $_setInt64(1, value);
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasActual() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearActual() => $_clearField(2);
|
||||
}
|
||||
|
||||
enum EvalViolation_Kind {
|
||||
invalidTarget,
|
||||
gasLimitExceeded,
|
||||
@@ -421,6 +494,7 @@ enum EvalViolation_Kind {
|
||||
volumetricLimitExceeded,
|
||||
invalidTime,
|
||||
invalidTransactionType,
|
||||
chainIdMismatch,
|
||||
notSet
|
||||
}
|
||||
|
||||
@@ -432,6 +506,7 @@ class EvalViolation extends $pb.GeneratedMessage {
|
||||
$0.Empty? volumetricLimitExceeded,
|
||||
$0.Empty? invalidTime,
|
||||
$0.Empty? invalidTransactionType,
|
||||
EvalViolation_ChainIdMismatch? chainIdMismatch,
|
||||
}) {
|
||||
final result = create();
|
||||
if (invalidTarget != null) result.invalidTarget = invalidTarget;
|
||||
@@ -442,6 +517,7 @@ class EvalViolation extends $pb.GeneratedMessage {
|
||||
if (invalidTime != null) result.invalidTime = invalidTime;
|
||||
if (invalidTransactionType != null)
|
||||
result.invalidTransactionType = invalidTransactionType;
|
||||
if (chainIdMismatch != null) result.chainIdMismatch = chainIdMismatch;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -462,6 +538,7 @@ class EvalViolation extends $pb.GeneratedMessage {
|
||||
4: EvalViolation_Kind.volumetricLimitExceeded,
|
||||
5: EvalViolation_Kind.invalidTime,
|
||||
6: EvalViolation_Kind.invalidTransactionType,
|
||||
7: EvalViolation_Kind.chainIdMismatch,
|
||||
0: EvalViolation_Kind.notSet
|
||||
};
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||
@@ -469,7 +546,7 @@ class EvalViolation extends $pb.GeneratedMessage {
|
||||
package:
|
||||
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'),
|
||||
createEmptyInstance: create)
|
||||
..oo(0, [1, 2, 3, 4, 5, 6])
|
||||
..oo(0, [1, 2, 3, 4, 5, 6, 7])
|
||||
..a<$core.List<$core.int>>(
|
||||
1, _omitFieldNames ? '' : 'invalidTarget', $pb.PbFieldType.OY)
|
||||
..aOM<GasLimitExceededViolation>(
|
||||
@@ -483,6 +560,9 @@ class EvalViolation extends $pb.GeneratedMessage {
|
||||
subBuilder: $0.Empty.create)
|
||||
..aOM<$0.Empty>(6, _omitFieldNames ? '' : 'invalidTransactionType',
|
||||
subBuilder: $0.Empty.create)
|
||||
..aOM<EvalViolation_ChainIdMismatch>(
|
||||
7, _omitFieldNames ? '' : 'chainIdMismatch',
|
||||
subBuilder: EvalViolation_ChainIdMismatch.create)
|
||||
..hasRequiredFields = false;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
@@ -510,6 +590,7 @@ class EvalViolation extends $pb.GeneratedMessage {
|
||||
@$pb.TagNumber(4)
|
||||
@$pb.TagNumber(5)
|
||||
@$pb.TagNumber(6)
|
||||
@$pb.TagNumber(7)
|
||||
EvalViolation_Kind whichKind() => _EvalViolation_KindByTag[$_whichOneof(0)]!;
|
||||
@$pb.TagNumber(1)
|
||||
@$pb.TagNumber(2)
|
||||
@@ -517,6 +598,7 @@ class EvalViolation extends $pb.GeneratedMessage {
|
||||
@$pb.TagNumber(4)
|
||||
@$pb.TagNumber(5)
|
||||
@$pb.TagNumber(6)
|
||||
@$pb.TagNumber(7)
|
||||
void clearKind() => $_clearField($_whichOneof(0));
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
@@ -582,6 +664,18 @@ class EvalViolation extends $pb.GeneratedMessage {
|
||||
void clearInvalidTransactionType() => $_clearField(6);
|
||||
@$pb.TagNumber(6)
|
||||
$0.Empty ensureInvalidTransactionType() => $_ensure(5);
|
||||
|
||||
@$pb.TagNumber(7)
|
||||
EvalViolation_ChainIdMismatch get chainIdMismatch => $_getN(6);
|
||||
@$pb.TagNumber(7)
|
||||
set chainIdMismatch(EvalViolation_ChainIdMismatch value) =>
|
||||
$_setField(7, value);
|
||||
@$pb.TagNumber(7)
|
||||
$core.bool hasChainIdMismatch() => $_has(6);
|
||||
@$pb.TagNumber(7)
|
||||
void clearChainIdMismatch() => $_clearField(7);
|
||||
@$pb.TagNumber(7)
|
||||
EvalViolation_ChainIdMismatch ensureChainIdMismatch() => $_ensure(6);
|
||||
}
|
||||
|
||||
/// Transaction was classified but no grant covers it
|
||||
|
||||
@@ -195,12 +195,31 @@ const EvalViolation$json = {
|
||||
'9': 0,
|
||||
'10': 'invalidTransactionType'
|
||||
},
|
||||
{
|
||||
'1': 'chain_id_mismatch',
|
||||
'3': 7,
|
||||
'4': 1,
|
||||
'5': 11,
|
||||
'6': '.arbiter.shared.evm.EvalViolation.ChainIdMismatch',
|
||||
'9': 0,
|
||||
'10': 'chainIdMismatch'
|
||||
},
|
||||
],
|
||||
'3': [EvalViolation_ChainIdMismatch$json],
|
||||
'8': [
|
||||
{'1': 'kind'},
|
||||
],
|
||||
};
|
||||
|
||||
@$core.Deprecated('Use evalViolationDescriptor instead')
|
||||
const EvalViolation_ChainIdMismatch$json = {
|
||||
'1': 'ChainIdMismatch',
|
||||
'2': [
|
||||
{'1': 'expected', '3': 1, '4': 1, '5': 4, '10': 'expected'},
|
||||
{'1': 'actual', '3': 2, '4': 1, '5': 4, '10': 'actual'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `EvalViolation`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List evalViolationDescriptor = $convert.base64Decode(
|
||||
'Cg1FdmFsVmlvbGF0aW9uEicKDmludmFsaWRfdGFyZ2V0GAEgASgMSABSDWludmFsaWRUYXJnZX'
|
||||
@@ -211,7 +230,10 @@ final $typed_data.Uint8List evalViolationDescriptor = $convert.base64Decode(
|
||||
'YuRW1wdHlIAFIXdm9sdW1ldHJpY0xpbWl0RXhjZWVkZWQSOwoMaW52YWxpZF90aW1lGAUgASgL'
|
||||
'MhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SABSC2ludmFsaWRUaW1lElIKGGludmFsaWRfdHJhbn'
|
||||
'NhY3Rpb25fdHlwZRgGIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eUgAUhZpbnZhbGlkVHJh'
|
||||
'bnNhY3Rpb25UeXBlQgYKBGtpbmQ=');
|
||||
'bnNhY3Rpb25UeXBlEl8KEWNoYWluX2lkX21pc21hdGNoGAcgASgLMjEuYXJiaXRlci5zaGFyZW'
|
||||
'QuZXZtLkV2YWxWaW9sYXRpb24uQ2hhaW5JZE1pc21hdGNoSABSD2NoYWluSWRNaXNtYXRjaBpF'
|
||||
'Cg9DaGFpbklkTWlzbWF0Y2gSGgoIZXhwZWN0ZWQYASABKARSCGV4cGVjdGVkEhYKBmFjdHVhbB'
|
||||
'gCIAEoBFIGYWN0dWFsQgYKBGtpbmQ=');
|
||||
|
||||
@$core.Deprecated('Use noMatchingGrantErrorDescriptor instead')
|
||||
const NoMatchingGrantError$json = {
|
||||
|
||||
@@ -24,12 +24,10 @@ class AuthChallengeRequest extends $pb.GeneratedMessage {
|
||||
factory AuthChallengeRequest({
|
||||
$core.List<$core.int>? pubkey,
|
||||
$core.String? bootstrapToken,
|
||||
KeyType? keyType,
|
||||
}) {
|
||||
final result = create();
|
||||
if (pubkey != null) result.pubkey = pubkey;
|
||||
if (bootstrapToken != null) result.bootstrapToken = bootstrapToken;
|
||||
if (keyType != null) result.keyType = keyType;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -50,8 +48,6 @@ class AuthChallengeRequest extends $pb.GeneratedMessage {
|
||||
..a<$core.List<$core.int>>(
|
||||
1, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY)
|
||||
..aOS(2, _omitFieldNames ? '' : 'bootstrapToken')
|
||||
..aE<KeyType>(3, _omitFieldNames ? '' : 'keyType',
|
||||
enumValues: KeyType.values)
|
||||
..hasRequiredFields = false;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
@@ -90,15 +86,6 @@ class AuthChallengeRequest extends $pb.GeneratedMessage {
|
||||
$core.bool hasBootstrapToken() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearBootstrapToken() => $_clearField(2);
|
||||
|
||||
@$pb.TagNumber(3)
|
||||
KeyType get keyType => $_getN(2);
|
||||
@$pb.TagNumber(3)
|
||||
set keyType(KeyType value) => $_setField(3, value);
|
||||
@$pb.TagNumber(3)
|
||||
$core.bool hasKeyType() => $_has(2);
|
||||
@$pb.TagNumber(3)
|
||||
void clearKeyType() => $_clearField(3);
|
||||
}
|
||||
|
||||
class AuthChallenge extends $pb.GeneratedMessage {
|
||||
|
||||
@@ -14,31 +14,6 @@ import 'dart:core' as $core;
|
||||
|
||||
import 'package:protobuf/protobuf.dart' as $pb;
|
||||
|
||||
class KeyType extends $pb.ProtobufEnum {
|
||||
static const KeyType KEY_TYPE_UNSPECIFIED =
|
||||
KeyType._(0, _omitEnumNames ? '' : 'KEY_TYPE_UNSPECIFIED');
|
||||
static const KeyType KEY_TYPE_ED25519 =
|
||||
KeyType._(1, _omitEnumNames ? '' : 'KEY_TYPE_ED25519');
|
||||
static const KeyType KEY_TYPE_ECDSA_SECP256K1 =
|
||||
KeyType._(2, _omitEnumNames ? '' : 'KEY_TYPE_ECDSA_SECP256K1');
|
||||
static const KeyType KEY_TYPE_RSA =
|
||||
KeyType._(3, _omitEnumNames ? '' : 'KEY_TYPE_RSA');
|
||||
|
||||
static const $core.List<KeyType> values = <KeyType>[
|
||||
KEY_TYPE_UNSPECIFIED,
|
||||
KEY_TYPE_ED25519,
|
||||
KEY_TYPE_ECDSA_SECP256K1,
|
||||
KEY_TYPE_RSA,
|
||||
];
|
||||
|
||||
static final $core.List<KeyType?> _byValue =
|
||||
$pb.ProtobufEnum.$_initByValueList(values, 3);
|
||||
static KeyType? valueOf($core.int value) =>
|
||||
value < 0 || value >= _byValue.length ? null : _byValue[value];
|
||||
|
||||
const KeyType._(super.value, super.name);
|
||||
}
|
||||
|
||||
class AuthResult extends $pb.ProtobufEnum {
|
||||
static const AuthResult AUTH_RESULT_UNSPECIFIED =
|
||||
AuthResult._(0, _omitEnumNames ? '' : 'AUTH_RESULT_UNSPECIFIED');
|
||||
|
||||
@@ -15,22 +15,6 @@ import 'dart:convert' as $convert;
|
||||
import 'dart:core' as $core;
|
||||
import 'dart:typed_data' as $typed_data;
|
||||
|
||||
@$core.Deprecated('Use keyTypeDescriptor instead')
|
||||
const KeyType$json = {
|
||||
'1': 'KeyType',
|
||||
'2': [
|
||||
{'1': 'KEY_TYPE_UNSPECIFIED', '2': 0},
|
||||
{'1': 'KEY_TYPE_ED25519', '2': 1},
|
||||
{'1': 'KEY_TYPE_ECDSA_SECP256K1', '2': 2},
|
||||
{'1': 'KEY_TYPE_RSA', '2': 3},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `KeyType`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
||||
final $typed_data.Uint8List keyTypeDescriptor = $convert.base64Decode(
|
||||
'CgdLZXlUeXBlEhgKFEtFWV9UWVBFX1VOU1BFQ0lGSUVEEAASFAoQS0VZX1RZUEVfRUQyNTUxOR'
|
||||
'ABEhwKGEtFWV9UWVBFX0VDRFNBX1NFQ1AyNTZLMRACEhAKDEtFWV9UWVBFX1JTQRAD');
|
||||
|
||||
@$core.Deprecated('Use authResultDescriptor instead')
|
||||
const AuthResult$json = {
|
||||
'1': 'AuthResult',
|
||||
@@ -67,14 +51,6 @@ const AuthChallengeRequest$json = {
|
||||
'10': 'bootstrapToken',
|
||||
'17': true
|
||||
},
|
||||
{
|
||||
'1': 'key_type',
|
||||
'3': 3,
|
||||
'4': 1,
|
||||
'5': 14,
|
||||
'6': '.arbiter.user_agent.auth.KeyType',
|
||||
'10': 'keyType'
|
||||
},
|
||||
],
|
||||
'8': [
|
||||
{'1': '_bootstrap_token'},
|
||||
@@ -84,9 +60,8 @@ const AuthChallengeRequest$json = {
|
||||
/// Descriptor for `AuthChallengeRequest`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List authChallengeRequestDescriptor = $convert.base64Decode(
|
||||
'ChRBdXRoQ2hhbGxlbmdlUmVxdWVzdBIWCgZwdWJrZXkYASABKAxSBnB1YmtleRIsCg9ib290c3'
|
||||
'RyYXBfdG9rZW4YAiABKAlIAFIOYm9vdHN0cmFwVG9rZW6IAQESOwoIa2V5X3R5cGUYAyABKA4y'
|
||||
'IC5hcmJpdGVyLnVzZXJfYWdlbnQuYXV0aC5LZXlUeXBlUgdrZXlUeXBlQhIKEF9ib290c3RyYX'
|
||||
'BfdG9rZW4=');
|
||||
'RyYXBfdG9rZW4YAiABKAlIAFIOYm9vdHN0cmFwVG9rZW6IAQFCEgoQX2Jvb3RzdHJhcF90b2tl'
|
||||
'bg==');
|
||||
|
||||
@$core.Deprecated('Use authChallengeDescriptor instead')
|
||||
const AuthChallenge$json = {
|
||||
|
||||
Reference in New Issue
Block a user