feat(evm): add grant management for EVM wallets
This commit is contained in:
@@ -15,9 +15,9 @@ use crate::{
|
||||
schema,
|
||||
},
|
||||
evm::{
|
||||
self, RunKind,
|
||||
self, ListGrantsError, RunKind,
|
||||
policies::{
|
||||
FullGrant, SharedGrantSettings, SpecificGrant, SpecificMeaning,
|
||||
FullGrant, Grant, SharedGrantSettings, SpecificGrant, SpecificMeaning,
|
||||
ether_transfer::EtherTransfer, token_transfers::TokenTransfer,
|
||||
},
|
||||
},
|
||||
@@ -194,19 +194,12 @@ impl EvmActor {
|
||||
}
|
||||
|
||||
#[message]
|
||||
pub async fn useragent_list_grants(
|
||||
&mut self,
|
||||
wallet_id: Option<i32>,
|
||||
) -> Result<Vec<EvmBasicGrant>, Error> {
|
||||
let mut conn = self.db.get().await?;
|
||||
let mut query = schema::evm_basic_grant::table
|
||||
.select(EvmBasicGrant::as_select())
|
||||
.filter(schema::evm_basic_grant::revoked_at.is_null())
|
||||
.into_boxed();
|
||||
if let Some(wid) = wallet_id {
|
||||
query = query.filter(schema::evm_basic_grant::wallet_id.eq(wid));
|
||||
pub async fn useragent_list_grants(&mut self) -> Result<Vec<Grant<SpecificGrant>>, Error> {
|
||||
match self.engine.list_all_grants().await {
|
||||
Ok(grants) => Ok(grants),
|
||||
Err(ListGrantsError::Database(db)) => Err(Error::Database(db)),
|
||||
Err(ListGrantsError::Pool(pool)) => Err(Error::DatabasePool(pool)),
|
||||
}
|
||||
Ok(query.load(&mut conn).await?)
|
||||
}
|
||||
|
||||
#[message]
|
||||
|
||||
@@ -34,7 +34,7 @@ smlang::statemachine!(
|
||||
custom_error: true,
|
||||
transitions: {
|
||||
*Init + AuthRequest(ChallengeRequest) / async prepare_challenge = SentChallenge(ChallengeContext),
|
||||
Init + BootstrapAuthRequest(BootstrapAuthRequest) [async verify_bootstrap_token] / provide_key_bootstrap = AuthOk(AuthPublicKey),
|
||||
Init + BootstrapAuthRequest(BootstrapAuthRequest) / async verify_bootstrap_token = AuthOk(AuthPublicKey),
|
||||
SentChallenge(ChallengeContext) + ReceivedSolution(ChallengeSolution) / async verify_solution = AuthOk(AuthPublicKey),
|
||||
}
|
||||
);
|
||||
@@ -136,9 +136,9 @@ impl AuthStateMachineContext for AuthContext<'_> {
|
||||
#[allow(missing_docs)]
|
||||
#[allow(clippy::result_unit_err)]
|
||||
async fn verify_bootstrap_token(
|
||||
&self,
|
||||
BootstrapAuthRequest { pubkey, token }: &BootstrapAuthRequest,
|
||||
) -> Result<bool, Self::Error> {
|
||||
&mut self,
|
||||
BootstrapAuthRequest { pubkey, token }: BootstrapAuthRequest,
|
||||
) -> Result<AuthPublicKey, Self::Error> {
|
||||
let token_ok: bool = self
|
||||
.conn
|
||||
.actors
|
||||
@@ -157,16 +157,15 @@ impl AuthStateMachineContext for AuthContext<'_> {
|
||||
return Err(Error::InvalidBootstrapToken);
|
||||
}
|
||||
|
||||
register_key(&self.conn.db, pubkey).await?;
|
||||
register_key(&self.conn.db, &pubkey).await?;
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
self.conn
|
||||
.transport
|
||||
.send(Ok(Response::AuthOk))
|
||||
.await
|
||||
.map_err(|_| Error::Transport)?;
|
||||
|
||||
fn provide_key_bootstrap(
|
||||
&mut self,
|
||||
event_data: BootstrapAuthRequest,
|
||||
) -> Result<AuthPublicKey, Self::Error> {
|
||||
Ok(event_data.pubkey)
|
||||
Ok(pubkey)
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
use alloy::primitives::Address;
|
||||
use arbiter_proto::transport::Bi;
|
||||
use arbiter_proto::{transport::Bi};
|
||||
use kameo::actor::Spawn as _;
|
||||
use tracing::{error, info};
|
||||
|
||||
use crate::{
|
||||
actors::{GlobalActors, evm, user_agent::session::UserAgentSession},
|
||||
db::{self, models::KeyType},
|
||||
db::{self, models::KeyType}, evm::policies::{Grant, SpecificGrant},
|
||||
evm::policies::SharedGrantSettings,
|
||||
};
|
||||
|
||||
#[derive(Debug, thiserror::Error, PartialEq)]
|
||||
@@ -109,6 +110,16 @@ pub enum Request {
|
||||
ClientConnectionResponse {
|
||||
approved: bool,
|
||||
},
|
||||
|
||||
ListGrants,
|
||||
EvmGrantCreate {
|
||||
client_id: i32,
|
||||
shared: SharedGrantSettings,
|
||||
specific: SpecificGrant,
|
||||
},
|
||||
EvmGrantDelete {
|
||||
grant_id: i32,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -123,6 +134,10 @@ pub enum Response {
|
||||
ClientConnectionCancel,
|
||||
EvmWalletCreate(Result<(), evm::Error>),
|
||||
EvmWalletList(Vec<Address>),
|
||||
|
||||
ListGrants(Vec<Grant<SpecificGrant>>),
|
||||
EvmGrantCreate(Result<i32, evm::Error>),
|
||||
EvmGrantDelete(Result<(), evm::Error>),
|
||||
}
|
||||
|
||||
pub type Transport = Box<dyn Bi<Request, Result<Response, TransportResponseError>> + Send>;
|
||||
|
||||
@@ -7,7 +7,8 @@ use tracing::{error, info};
|
||||
use x25519_dalek::{EphemeralSecret, PublicKey};
|
||||
|
||||
use crate::actors::{
|
||||
evm::{Generate, ListWallets},
|
||||
evm::{Generate, ListWallets, UseragentListGrants},
|
||||
evm::{UseragentCreateGrant, UseragentDeleteGrant},
|
||||
keyholder::{self, Bootstrap, TryUnseal},
|
||||
user_agent::{
|
||||
BootstrapError, Request, Response, TransportResponseError, UnsealError, VaultState,
|
||||
@@ -40,6 +41,7 @@ impl UserAgentSession {
|
||||
self.handle_bootstrap_encrypted_key(nonce, ciphertext, associated_data)
|
||||
.await
|
||||
}
|
||||
Request::ListGrants => self.handle_grant_list().await,
|
||||
Request::QueryVaultState => self.handle_query_vault_state().await,
|
||||
Request::EvmWalletCreate => self.handle_evm_wallet_create().await,
|
||||
Request::EvmWalletList => self.handle_evm_wallet_list().await,
|
||||
@@ -48,6 +50,12 @@ impl UserAgentSession {
|
||||
| Request::ClientConnectionResponse { .. } => {
|
||||
Err(TransportResponseError::UnexpectedRequestPayload)
|
||||
}
|
||||
Request::EvmGrantCreate {
|
||||
client_id,
|
||||
shared,
|
||||
specific,
|
||||
} => self.handle_grant_create(client_id, shared, specific).await,
|
||||
Request::EvmGrantDelete { grant_id } => self.handle_grant_delete(grant_id).await,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -286,3 +294,56 @@ impl UserAgentSession {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl UserAgentSession {
|
||||
async fn handle_grant_list(&mut self) -> Output {
|
||||
match self.props.actors.evm.ask(UseragentListGrants {}).await {
|
||||
Ok(grants) => Ok(Response::ListGrants(grants)),
|
||||
Err(err) => {
|
||||
error!(?err, "EVM grant list failed");
|
||||
Err(TransportResponseError::KeyHolderActorUnreachable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_grant_create(
|
||||
&mut self,
|
||||
client_id: i32,
|
||||
basic: crate::evm::policies::SharedGrantSettings,
|
||||
grant: crate::evm::policies::SpecificGrant,
|
||||
) -> Output {
|
||||
match self
|
||||
.props
|
||||
.actors
|
||||
.evm
|
||||
.ask(UseragentCreateGrant {
|
||||
client_id,
|
||||
basic,
|
||||
grant,
|
||||
})
|
||||
.await
|
||||
{
|
||||
Ok(grant_id) => Ok(Response::EvmGrantCreate(Ok(grant_id))),
|
||||
Err(err) => {
|
||||
error!(?err, "EVM grant create failed");
|
||||
Err(TransportResponseError::KeyHolderActorUnreachable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_grant_delete(&mut self, grant_id: i32) -> Output {
|
||||
match self
|
||||
.props
|
||||
.actors
|
||||
.evm
|
||||
.ask(UseragentDeleteGrant { grant_id })
|
||||
.await
|
||||
{
|
||||
Ok(()) => Ok(Response::EvmGrantDelete(Ok(()))),
|
||||
Err(err) => {
|
||||
error!(?err, "EVM grant delete failed");
|
||||
Err(TransportResponseError::KeyHolderActorUnreachable)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user