@@ -50,11 +50,13 @@ pub struct QueryRoot<C> {
5050
5151/// The root GraphQL mutation type.
5252pub struct MutationRoot < C > {
53+ /// The chain from which new faucet chains are opened.
5354 main_chain_id : ChainId ,
54- tmp_chain_id : Arc < Mutex < Option < ChainId > > > ,
55+ /// The chain that is currently used to open requested chains for clients.
56+ faucet_chain_id : Arc < Mutex < Option < ChainId > > > ,
5557 context : Arc < Mutex < C > > ,
5658 amount : Amount ,
57- max_claims_per_chain : u32 ,
59+ faucet_init_balance : Amount ,
5860 end_timestamp : Timestamp ,
5961 start_timestamp : Timestamp ,
6062 start_balance : Amount ,
@@ -123,54 +125,28 @@ where
123125 C : ClientContext ,
124126{
125127 async fn do_claim ( & self , owner : AccountOwner ) -> Result < ClaimOutcome , Error > {
126- let main_client = self
127- . context
128- . lock ( )
129- . await
130- . make_chain_client ( self . main_chain_id ) ?;
131- let maybe_tmp_chain_id = * self . tmp_chain_id . lock ( ) . await ;
132- let main_balance = main_client. local_balance ( ) . await ?;
133- let tmp_chain_id = match maybe_tmp_chain_id {
134- Some ( tmp_chain_id) => tmp_chain_id,
135- None => {
136- let key_pair = main_client. key_pair ( ) . await ?;
137- let balance = self
138- . amount
139- . try_add ( MAX_FEE ) ?
140- . try_mul ( u128:: from ( self . max_claims_per_chain ) ) ?
141- . try_add ( MAX_FEE ) ? // One more block fee for closing the chain.
142- . min ( main_balance. try_sub ( MAX_FEE ) ?) ;
143- let ownership = main_client. chain_state_view ( ) . await ?. ownership ( ) . clone ( ) ;
144- let ( message_id, certificate) = main_client
145- . open_chain ( ownership, ApplicationPermissions :: default ( ) , balance)
146- . await ?
147- . try_unwrap ( ) ?;
148- let chain_id = ChainId :: child ( message_id) ;
149- info ! ( "Switching to a new faucet chain {chain_id:8}" ) ;
150- self . context
151- . lock ( )
152- . await
153- . update_wallet_for_new_chain (
154- chain_id,
155- Some ( key_pair) ,
156- certificate. block ( ) . header . timestamp ,
157- )
158- . await ?;
159- * self . tmp_chain_id . lock ( ) . await = Some ( chain_id) ;
160- chain_id
161- }
128+ let maybe_faucet_chain_id = * self . faucet_chain_id . lock ( ) . await ;
129+ let faucet_chain_id = match maybe_faucet_chain_id {
130+ Some ( faucet_chain_id) => faucet_chain_id,
131+ None => self . open_new_faucet_chain ( ) . await ?,
132+ } ;
133+ let ( faucet_client, main_client) = {
134+ let guard = self . context . lock ( ) . await ;
135+ (
136+ guard. make_chain_client ( faucet_chain_id) ?,
137+ guard. make_chain_client ( self . main_chain_id ) ?,
138+ )
162139 } ;
163- let tmp_client = self . context . lock ( ) . await . make_chain_client ( tmp_chain_id) ?;
164140
165141 if self . start_timestamp < self . end_timestamp {
166- let local_time = tmp_client . storage_client ( ) . clock ( ) . current_time ( ) ;
142+ let local_time = faucet_client . storage_client ( ) . clock ( ) . current_time ( ) ;
167143 if local_time < self . end_timestamp {
168144 let full_duration = self
169145 . end_timestamp
170146 . delta_since ( self . start_timestamp )
171147 . as_micros ( ) ;
172148 let remaining_duration = self . end_timestamp . delta_since ( local_time) . as_micros ( ) ;
173- let balance = tmp_client
149+ let balance = faucet_client
174150 . local_balance ( )
175151 . await ?
176152 . try_add ( main_client. local_balance ( ) . await ?) ?;
@@ -190,27 +166,31 @@ where
190166 }
191167
192168 let ownership = ChainOwnership :: single ( owner) ;
193- let result = tmp_client
169+ let ( message_id , certificate ) = faucet_client
194170 . open_chain ( ownership, ApplicationPermissions :: default ( ) , self . amount )
195- . await ;
196- self . context . lock ( ) . await . update_wallet ( & tmp_client) . await ?;
197- let ( message_id, certificate) = result?. try_unwrap ( ) ?;
171+ . await ?
172+ . try_unwrap ( ) ?;
173+ self . context
174+ . lock ( )
175+ . await
176+ . update_wallet ( & faucet_client)
177+ . await ?;
198178
199179 // Only keep using this chain if there will still be enough balance to close it.
200- if tmp_client . local_balance ( ) . await ? < self . amount . try_add ( MAX_FEE . try_mul ( 2 ) ?) ? {
180+ if faucet_client . local_balance ( ) . await ? < self . amount . try_add ( MAX_FEE . try_mul ( 2 ) ?) ? {
201181 // TODO(#1795): Move the remaining tokens back to the main chain.
202- match tmp_client . close_chain ( ) . await {
182+ match faucet_client . close_chain ( ) . await {
203183 Ok ( outcome) => {
204184 outcome. try_unwrap ( ) ?;
205185 }
206- Err ( err) => tracing:: warn!( "Failed to close the chain: {err:?}" ) ,
186+ Err ( err) => tracing:: warn!( "Failed to close the temporary faucet chain: {err:?}" ) ,
207187 }
208188 self . context
209189 . lock ( )
210190 . await
211- . forget_chain ( & tmp_chain_id )
191+ . forget_chain ( & faucet_chain_id )
212192 . await ?;
213- self . tmp_chain_id . lock ( ) . await . take ( ) ;
193+ self . faucet_chain_id . lock ( ) . await . take ( ) ;
214194 }
215195
216196 let chain_id = ChainId :: child ( message_id) ;
@@ -220,6 +200,35 @@ where
220200 certificate_hash : certificate. hash ( ) ,
221201 } )
222202 }
203+
204+ async fn open_new_faucet_chain ( & self ) -> Result < ChainId , Error > {
205+ let main_client = self
206+ . context
207+ . lock ( )
208+ . await
209+ . make_chain_client ( self . main_chain_id ) ?;
210+ let main_balance = main_client. local_balance ( ) . await ?;
211+ let key_pair = main_client. key_pair ( ) . await ?;
212+ let balance = self . faucet_init_balance . min ( main_balance. try_sub ( MAX_FEE ) ?) ;
213+ let ownership = main_client. chain_state_view ( ) . await ?. ownership ( ) . clone ( ) ;
214+ let ( message_id, certificate) = main_client
215+ . open_chain ( ownership, ApplicationPermissions :: default ( ) , balance)
216+ . await ?
217+ . try_unwrap ( ) ?;
218+ let chain_id = ChainId :: child ( message_id) ;
219+ info ! ( "Switching to a new faucet chain {chain_id:8}" ) ;
220+ self . context
221+ . lock ( )
222+ . await
223+ . update_wallet_for_new_chain (
224+ chain_id,
225+ Some ( key_pair) ,
226+ certificate. block ( ) . header . timestamp ,
227+ )
228+ . await ?;
229+ * self . faucet_chain_id . lock ( ) . await = Some ( chain_id) ;
230+ Ok ( chain_id)
231+ }
223232}
224233
225234impl < C > MutationRoot < C > {
@@ -240,15 +249,15 @@ where
240249 C : ClientContext ,
241250{
242251 main_chain_id : ChainId ,
243- tmp_chain_id : Arc < Mutex < Option < ChainId > > > ,
252+ faucet_chain_id : Arc < Mutex < Option < ChainId > > > ,
244253 context : Arc < Mutex < C > > ,
245254 genesis_config : Arc < GenesisConfig > ,
246255 config : ChainListenerConfig ,
247256 storage : C :: Storage ,
248257 port : NonZeroU16 ,
249258 amount : Amount ,
250259 end_timestamp : Timestamp ,
251- max_claims_per_chain : u32 ,
260+ faucet_init_balance : Amount ,
252261 start_timestamp : Timestamp ,
253262 start_balance : Amount ,
254263}
@@ -260,14 +269,14 @@ where
260269 fn clone ( & self ) -> Self {
261270 Self {
262271 main_chain_id : self . main_chain_id ,
263- tmp_chain_id : Arc :: clone ( & self . tmp_chain_id ) ,
272+ faucet_chain_id : Arc :: clone ( & self . faucet_chain_id ) ,
264273 context : Arc :: clone ( & self . context ) ,
265274 genesis_config : Arc :: clone ( & self . genesis_config ) ,
266275 config : self . config . clone ( ) ,
267276 storage : self . storage . clone ( ) ,
268277 port : self . port ,
269278 amount : self . amount ,
270- max_claims_per_chain : self . max_claims_per_chain ,
279+ faucet_init_balance : self . faucet_init_balance ,
271280 end_timestamp : self . end_timestamp ,
272281 start_timestamp : self . start_timestamp ,
273282 start_balance : self . start_balance ,
@@ -292,21 +301,25 @@ where
292301 config : ChainListenerConfig ,
293302 storage : C :: Storage ,
294303 ) -> anyhow:: Result < Self > {
304+ let faucet_init_balance = amount
305+ . try_add ( MAX_FEE ) ?
306+ . try_mul ( u128:: from ( max_claims_per_chain) ) ?
307+ . try_add ( MAX_FEE ) ?; // One more block fee for closing the chain.
295308 let client = context. make_chain_client ( chain_id) ?;
296309 let context = Arc :: new ( Mutex :: new ( context) ) ;
297310 let start_timestamp = client. storage_client ( ) . clock ( ) . current_time ( ) ;
298311 client. process_inbox ( ) . await ?;
299312 let start_balance = client. local_balance ( ) . await ?;
300313 Ok ( Self {
301314 main_chain_id : chain_id,
302- tmp_chain_id : Arc :: new ( Mutex :: new ( None ) ) ,
315+ faucet_chain_id : Arc :: new ( Mutex :: new ( None ) ) ,
303316 context,
304317 genesis_config,
305318 config,
306319 storage,
307320 port,
308321 amount,
309- max_claims_per_chain ,
322+ faucet_init_balance ,
310323 end_timestamp,
311324 start_timestamp,
312325 start_balance,
@@ -316,10 +329,10 @@ where
316329 pub fn schema ( & self ) -> Schema < QueryRoot < C > , MutationRoot < C > , EmptySubscription > {
317330 let mutation_root = MutationRoot {
318331 main_chain_id : self . main_chain_id ,
319- tmp_chain_id : Arc :: clone ( & self . tmp_chain_id ) ,
332+ faucet_chain_id : Arc :: clone ( & self . faucet_chain_id ) ,
320333 context : Arc :: clone ( & self . context ) ,
321334 amount : self . amount ,
322- max_claims_per_chain : self . max_claims_per_chain ,
335+ faucet_init_balance : self . faucet_init_balance ,
323336 end_timestamp : self . end_timestamp ,
324337 start_timestamp : self . start_timestamp ,
325338 start_balance : self . start_balance ,
0 commit comments