11use crate :: {
22 args:: {
3- AddFundsArgs , AddIdentityArgs , AddNetworkArgs , BalanceCommand , Cli , ClusterConfigArgs , Command , ComputeArgs ,
4- ConfigCommand , DeleteValuesArgs , EditIdentityArgs , EditNetworkArgs , IdentityGenArgs , InspectNucArgs ,
5- OverwritePermissionsArgs , PreprocessingPoolStatusArgs , RemoveIdentityArgs , RemoveNetworkArgs ,
6- RetrievePermissionsArgs , RetrieveValuesArgs , ShowIdentityArgs , ShowNetworkArgs , StoreProgramArgs ,
7- StoreValuesArgs , UpdatePermissionsArgs , UseContextArgs , ValidateNucArgs ,
3+ AddFundsArgs , AddIdentityArgs , AddNetworkArgs , BalanceCommand , CheckRevokedArgs , Cli , ClusterConfigArgs ,
4+ Command , ComputeArgs , ConfigCommand , DeleteValuesArgs , EditIdentityArgs , EditNetworkArgs , IdentityGenArgs ,
5+ InspectNucArgs , NilauthCommand , NilauthSubscriptionCommand , OverwritePermissionsArgs ,
6+ PreprocessingPoolStatusArgs , RemoveIdentityArgs , RemoveNetworkArgs , RetrievePermissionsArgs ,
7+ RetrieveValuesArgs , RevokeTokenArgs , ShowIdentityArgs , ShowNetworkArgs , StoreProgramArgs , StoreValuesArgs ,
8+ UpdatePermissionsArgs , UseContextArgs , ValidateNucArgs ,
89 } ,
910 context:: ContextConfig ,
1011 parse_input_file,
@@ -16,16 +17,17 @@ use chrono::{DateTime, Utc};
1617use clap:: { error:: ErrorKind , CommandFactory } ;
1718use clap_utils:: shell_completions:: { handle_shell_completions, ShellCompletionsArgs } ;
1819use log:: { debug, info} ;
20+ use nilauth_client:: client:: { DefaultNilauthClient , NilauthClient } ;
1921use nillion_client:: {
2022 grpc:: payments:: AccountBalanceResponse ,
2123 operation:: { InitialState , PaidOperation , PaidVmOperation } ,
22- payments:: TxHash ,
24+ payments:: { NillionChainClient , NillionChainPrivateKey , TxHash } ,
2325 vm:: VmClient ,
2426 Ed25519SigningKey , Secp256k1SigningKey , TokenAmount , UserId ,
2527} ;
2628use nillion_nucs:: {
2729 envelope:: { DecodedNucToken , NucTokenEnvelope } ,
28- k256,
30+ k256:: { self , SecretKey } ,
2931 token:: { NucToken , ProofHash } ,
3032 validator:: NucValidator ,
3133} ;
@@ -39,20 +41,22 @@ use std::{
3941 path:: Path ,
4042} ;
4143use tools_config:: {
44+ client:: ClientParameters ,
4245 identities:: { Identity , Kind } ,
43- networks:: { NetworkConfig , PaymentsConfig } ,
46+ networks:: { NetworkConfig , NilauthConfig , PaymentsConfig } ,
4447 NamedConfig , ToolConfig ,
4548} ;
4649use user_keypair:: SigningKey ;
4750use uuid:: Uuid ;
4851
4952pub struct Runner {
5053 client : VmClient ,
54+ parameters : ClientParameters ,
5155}
5256
5357impl Runner {
54- pub fn new ( client : VmClient ) -> Self {
55- Self { client }
58+ pub fn new ( client : VmClient , parameters : ClientParameters ) -> Self {
59+ Self { client, parameters }
5660 }
5761
5862 /// run a command
@@ -74,6 +78,7 @@ impl Runner {
7478 Command :: Balance ( BalanceCommand :: AddFunds ( args) ) => self . add_funds ( args) . await ,
7579 Command :: Config ( ConfigCommand :: Payments ) => self . payments_config ( ) . await ,
7680 Command :: Config ( ConfigCommand :: Cluster ( args) ) => self . cluster_config ( args) . await ,
81+ Command :: Nilauth ( cmd) => self . handle_nilauth ( cmd) . await ,
7782 Command :: IdentityGen ( _)
7883 | Command :: Identities ( _)
7984 | Command :: Networks ( _)
@@ -450,6 +455,7 @@ impl Runner {
450455 nilchain_private_key,
451456 nilchain_chain_id,
452457 nilchain_gas_price,
458+ nilauth_endpoint,
453459 } = args;
454460 let payments = nilchain_rpc_endpoint. map ( |nilchain_rpc_endpoint| PaymentsConfig {
455461 nilchain_chain_id,
@@ -459,7 +465,8 @@ impl Runner {
459465 nilchain_private_key : nilchain_private_key. expect ( "private key not set" ) ,
460466 gas_price : nilchain_gas_price,
461467 } ) ;
462- NetworkConfig { bootnode, payments } . write_to_file ( & name) ?;
468+ let nilauth = nilauth_endpoint. map ( |endpoint| NilauthConfig { endpoint } ) ;
469+ NetworkConfig { bootnode, payments, nilauth } . write_to_file ( & name) ?;
463470 Ok ( Box :: new ( format ! ( "Network {} added" , name) ) )
464471 }
465472
@@ -487,7 +494,7 @@ impl Runner {
487494
488495 pub fn show_network ( args : ShowNetworkArgs ) -> Result < Box < dyn SerializeAsAny > > {
489496 let config = NetworkConfig :: read_from_config ( & args. name ) ?;
490- let NetworkConfig { bootnode, payments } = config;
497+ let NetworkConfig { bootnode, payments, nilauth } = config;
491498 let mut output = BTreeMap :: from ( [ ( "bootnode" , bootnode) ] ) ;
492499
493500 if let Some ( payments) = payments {
@@ -517,6 +524,10 @@ impl Runner {
517524 output. insert ( "nilchain_gas_price" , gas_price. to_string ( ) ) ;
518525 }
519526 }
527+ if let Some ( nilauth) = nilauth {
528+ let NilauthConfig { endpoint } = nilauth;
529+ output. insert ( "nilauth_endpoint" , endpoint) ;
530+ }
520531 Ok ( Box :: new ( output) )
521532 }
522533
@@ -701,6 +712,119 @@ impl Runner {
701712 Ok ( Box :: new ( info) )
702713 }
703714
715+ async fn handle_nilauth ( & self , cmd : NilauthCommand ) -> Result < Box < dyn SerializeAsAny > > {
716+ let identity = Identity :: read_from_config ( & self . parameters . identity ) ?;
717+ let key = match identity. kind {
718+ Kind :: Secp256k1 => SecretKey :: from_slice ( & identity. private_key ) ?,
719+ Kind :: Ed25519 => bail ! ( "ed25519 not supported" ) ,
720+ } ;
721+ let config = NetworkConfig :: read_from_config ( & self . parameters . network ) ?;
722+ let nilauth = config. nilauth . ok_or_else ( || anyhow ! ( "no nilauth config" ) ) ?;
723+ let client = DefaultNilauthClient :: new ( nilauth. endpoint ) ?;
724+ match cmd {
725+ NilauthCommand :: Subscription ( NilauthSubscriptionCommand :: Pay ) => {
726+ self . pay_nilauth_subscription ( & client, config. payments , key) . await
727+ }
728+ NilauthCommand :: Subscription ( NilauthSubscriptionCommand :: Status ) => {
729+ self . nilauth_subscription_status ( & client, key) . await
730+ }
731+ NilauthCommand :: Token => self . nilauth_request_token ( & client, key) . await ,
732+ NilauthCommand :: Revoke ( args) => self . nilauth_revoke_token ( & client, key, args) . await ,
733+ NilauthCommand :: CheckRevoked ( args) => self . nilauth_check_revoked ( & client, args) . await ,
734+ }
735+ }
736+
737+ async fn pay_nilauth_subscription (
738+ & self ,
739+ nilauth_client : & dyn NilauthClient ,
740+ nilchain_config : Option < PaymentsConfig > ,
741+ key : SecretKey ,
742+ ) -> Result < Box < dyn SerializeAsAny > > {
743+ #[ derive( Serialize ) ]
744+ struct Output {
745+ tx_hash : String ,
746+ }
747+
748+ let payments = nilchain_config. ok_or_else ( || anyhow ! ( "no payments config" ) ) ?;
749+ let nilchain_key =
750+ NillionChainPrivateKey :: from_hex ( & payments. nilchain_private_key ) . context ( "invalid payments private key" ) ?;
751+ let mut nilchain_client = NillionChainClient :: new ( payments. nilchain_rpc_endpoint , nilchain_key)
752+ . await
753+ . context ( "creating nilchain client" ) ?;
754+ if let Some ( gas_price) = payments. gas_price {
755+ nilchain_client. set_gas_price ( gas_price) ;
756+ }
757+
758+ let tx_hash = nilauth_client. pay_subscription ( & mut nilchain_client, & key. public_key ( ) ) . await ?;
759+ Ok ( Box :: new ( Output { tx_hash : tx_hash. to_string ( ) } ) )
760+ }
761+
762+ async fn nilauth_subscription_status (
763+ & self ,
764+ nilauth_client : & dyn NilauthClient ,
765+ key : SecretKey ,
766+ ) -> Result < Box < dyn SerializeAsAny > > {
767+ #[ derive( Serialize ) ]
768+ struct Output {
769+ subscribed : bool ,
770+
771+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
772+ expires_at : Option < DateTime < Utc > > ,
773+ }
774+
775+ let subscription = nilauth_client. subscription_status ( & key) . await ?;
776+ let output =
777+ Output { subscribed : subscription. subscribed , expires_at : subscription. details . map ( |s| s. expires_at ) } ;
778+ Ok ( Box :: new ( output) )
779+ }
780+
781+ async fn nilauth_request_token (
782+ & self ,
783+ nilauth_client : & dyn NilauthClient ,
784+ key : SecretKey ,
785+ ) -> Result < Box < dyn SerializeAsAny > > {
786+ #[ derive( Serialize ) ]
787+ struct Output {
788+ token : String ,
789+ }
790+
791+ let token = nilauth_client. request_token ( & key) . await ?;
792+ Ok ( Box :: new ( Output { token } ) )
793+ }
794+
795+ async fn nilauth_revoke_token (
796+ & self ,
797+ nilauth_client : & dyn NilauthClient ,
798+ key : SecretKey ,
799+ args : RevokeTokenArgs ,
800+ ) -> Result < Box < dyn SerializeAsAny > > {
801+ let token = NucTokenEnvelope :: decode ( & args. token ) ?;
802+ nilauth_client. revoke_token ( & token, & key) . await ?;
803+ Ok ( Box :: new ( "Token revoked" . to_string ( ) ) )
804+ }
805+
806+ async fn nilauth_check_revoked (
807+ & self ,
808+ nilauth_client : & dyn NilauthClient ,
809+ args : CheckRevokedArgs ,
810+ ) -> Result < Box < dyn SerializeAsAny > > {
811+ #[ derive( Serialize ) ]
812+ struct Token {
813+ hash : ProofHash ,
814+ revoked_at : DateTime < Utc > ,
815+ }
816+
817+ #[ derive( Serialize ) ]
818+ struct Output {
819+ tokens : Vec < Token > ,
820+ }
821+
822+ let token = NucTokenEnvelope :: decode ( & args. token ) ?;
823+ let tokens = nilauth_client. lookup_revoked_tokens ( & token) . await ?;
824+ let tokens = tokens. into_iter ( ) . map ( |t| Token { hash : t. token_hash , revoked_at : t. revoked_at } ) . collect ( ) ;
825+ Ok ( Box :: new ( Output { tokens } ) )
826+ }
827+
704828 async fn serialize_quote < ' a , O : PaidVmOperation > (
705829 & self ,
706830 operation : PaidOperation < ' a , O , InitialState > ,
0 commit comments