1- use std:: sync :: Arc ;
1+ use std:: time :: { Duration , Instant } ;
22
33use alloy:: { primitives:: Address , rpc:: types:: beacon:: BlsSignature } ;
44use eyre:: WrapErr ;
@@ -15,39 +15,76 @@ use super::{
1515 } ,
1616} ;
1717use crate :: {
18+ constants:: SIGNER_JWT_EXPIRATION ,
1819 signer:: { BlsPublicKey , EcdsaSignature } ,
20+ types:: { Jwt , ModuleId } ,
21+ utils:: create_jwt,
1922 DEFAULT_REQUEST_TIMEOUT ,
2023} ;
2124
2225/// Client used by commit modules to request signatures via the Signer API
2326#[ derive( Debug , Clone ) ]
2427pub struct SignerClient {
2528 /// Url endpoint of the Signer Module
26- url : Arc < Url > ,
29+ url : Url ,
2730 client : reqwest:: Client ,
31+ last_jwt_refresh : Instant ,
32+ module_id : ModuleId ,
33+ jwt_secret : Jwt ,
2834}
2935
3036impl SignerClient {
3137 /// Create a new SignerClient
32- pub fn new ( signer_server_url : Url , jwt : & str ) -> eyre:: Result < Self > {
33- let mut headers = HeaderMap :: new ( ) ;
38+ pub fn new ( signer_server_url : Url , jwt_secret : Jwt , module_id : ModuleId ) -> eyre:: Result < Self > {
39+ let jwt = create_jwt ( & module_id , & jwt_secret ) ? ;
3440
3541 let mut auth_value =
3642 HeaderValue :: from_str ( & format ! ( "Bearer {}" , jwt) ) . wrap_err ( "invalid jwt" ) ?;
3743 auth_value. set_sensitive ( true ) ;
44+
45+ let mut headers = HeaderMap :: new ( ) ;
3846 headers. insert ( AUTHORIZATION , auth_value) ;
47+
3948 let client = reqwest:: Client :: builder ( )
4049 . timeout ( DEFAULT_REQUEST_TIMEOUT )
4150 . default_headers ( headers)
4251 . build ( ) ?;
4352
44- Ok ( Self { url : signer_server_url. into ( ) , client } )
53+ Ok ( Self {
54+ url : signer_server_url,
55+ client,
56+ last_jwt_refresh : Instant :: now ( ) ,
57+ module_id,
58+ jwt_secret,
59+ } )
60+ }
61+
62+ fn refresh_jwt ( & mut self ) -> Result < ( ) , SignerClientError > {
63+ if self . last_jwt_refresh . elapsed ( ) > Duration :: from_secs ( SIGNER_JWT_EXPIRATION ) {
64+ let jwt = create_jwt ( & self . module_id , & self . jwt_secret ) ?;
65+
66+ let mut auth_value =
67+ HeaderValue :: from_str ( & format ! ( "Bearer {}" , jwt) ) . wrap_err ( "invalid jwt" ) ?;
68+ auth_value. set_sensitive ( true ) ;
69+
70+ let mut headers = HeaderMap :: new ( ) ;
71+ headers. insert ( AUTHORIZATION , auth_value) ;
72+
73+ self . client = reqwest:: Client :: builder ( )
74+ . timeout ( DEFAULT_REQUEST_TIMEOUT )
75+ . default_headers ( headers)
76+ . build ( ) ?;
77+ }
78+
79+ Ok ( ( ) )
4580 }
4681
4782 /// Request a list of validator pubkeys for which signatures can be
4883 /// requested.
4984 // TODO: add more docs on how proxy keys work
50- pub async fn get_pubkeys ( & self ) -> Result < GetPubkeysResponse , SignerClientError > {
85+ pub async fn get_pubkeys ( & mut self ) -> Result < GetPubkeysResponse , SignerClientError > {
86+ self . refresh_jwt ( ) ?;
87+
5188 let url = self . url . join ( GET_PUBKEYS_PATH ) ?;
5289 let res = self . client . get ( url) . send ( ) . await ?;
5390
@@ -62,10 +99,12 @@ impl SignerClient {
6299 }
63100
64101 /// Send a signature request
65- async fn request_signature < T > ( & self , request : & SignRequest ) -> Result < T , SignerClientError >
102+ async fn request_signature < T > ( & mut self , request : & SignRequest ) -> Result < T , SignerClientError >
66103 where
67104 T : for < ' de > Deserialize < ' de > ,
68105 {
106+ self . refresh_jwt ( ) ?;
107+
69108 let url = self . url . join ( REQUEST_SIGNATURE_PATH ) ?;
70109 let res = self . client . post ( url) . json ( & request) . send ( ) . await ?;
71110
@@ -85,33 +124,35 @@ impl SignerClient {
85124 }
86125
87126 pub async fn request_consensus_signature (
88- & self ,
127+ & mut self ,
89128 request : SignConsensusRequest ,
90129 ) -> Result < BlsSignature , SignerClientError > {
91130 self . request_signature ( & request. into ( ) ) . await
92131 }
93132
94133 pub async fn request_proxy_signature_ecdsa (
95- & self ,
134+ & mut self ,
96135 request : SignProxyRequest < Address > ,
97136 ) -> Result < EcdsaSignature , SignerClientError > {
98137 self . request_signature ( & request. into ( ) ) . await
99138 }
100139
101140 pub async fn request_proxy_signature_bls (
102- & self ,
141+ & mut self ,
103142 request : SignProxyRequest < BlsPublicKey > ,
104143 ) -> Result < BlsSignature , SignerClientError > {
105144 self . request_signature ( & request. into ( ) ) . await
106145 }
107146
108147 async fn generate_proxy_key < T > (
109- & self ,
148+ & mut self ,
110149 request : & GenerateProxyRequest ,
111150 ) -> Result < SignedProxyDelegation < T > , SignerClientError >
112151 where
113152 T : ProxyId + for < ' de > Deserialize < ' de > ,
114153 {
154+ self . refresh_jwt ( ) ?;
155+
115156 let url = self . url . join ( GENERATE_PROXY_KEY_PATH ) ?;
116157 let res = self . client . post ( url) . json ( & request) . send ( ) . await ?;
117158
@@ -131,7 +172,7 @@ impl SignerClient {
131172 }
132173
133174 pub async fn generate_proxy_key_bls (
134- & self ,
175+ & mut self ,
135176 consensus_pubkey : BlsPublicKey ,
136177 ) -> Result < SignedProxyDelegation < BlsPublicKey > , SignerClientError > {
137178 let request = GenerateProxyRequest :: new ( consensus_pubkey, EncryptionScheme :: Bls ) ;
@@ -142,7 +183,7 @@ impl SignerClient {
142183 }
143184
144185 pub async fn generate_proxy_key_ecdsa (
145- & self ,
186+ & mut self ,
146187 consensus_pubkey : BlsPublicKey ,
147188 ) -> Result < SignedProxyDelegation < Address > , SignerClientError > {
148189 let request = GenerateProxyRequest :: new ( consensus_pubkey, EncryptionScheme :: Ecdsa ) ;
0 commit comments