1use std::{
7 net::SocketAddr,
8 sync::{Arc, Mutex},
9 time::Duration,
10};
11
12use async_trait::async_trait;
13use iota_config::genesis::Genesis;
14use iota_metrics::spawn_monitored_task;
15use iota_types::{
16 crypto::AuthorityKeyPair,
17 digests::TransactionDigest,
18 effects::TransactionEffectsAPI,
19 error::{IotaError, IotaResult},
20 iota_system_state::IotaSystemState,
21 messages_checkpoint::{CheckpointRequest, CheckpointResponse},
22 messages_grpc::{
23 GetTxStatusRequest, HandleCapabilityNotificationRequestV1,
24 HandleCapabilityNotificationResponseV1, HandleCertificateRequestV1,
25 HandleCertificateResponseV1, HandleSoftBundleCertificatesRequestV1,
26 HandleSoftBundleCertificatesResponseV1, HandleTransactionResponse, ObjectInfoRequest,
27 ObjectInfoResponse, SystemStateRequest, TransactionInfoRequest, TransactionInfoResponse,
28 TxStatusUpdate, ValidatorHealthRequest, ValidatorHealthResponse,
29 },
30 transaction::{Transaction, VerifiedTransaction},
31};
32use tracing::info;
33
34use crate::{
35 authority::{AuthorityState, test_authority_builder::TestAuthorityBuilder},
36 authority_client::{
37 validator::ValidatorAPI, validator_peer::ValidatorPeerAPI, validator_v2::ValidatorV2API,
38 },
39};
40
41#[derive(Clone, Copy, Default)]
42pub struct LocalAuthorityClientFaultConfig {
43 pub fail_before_handle_transaction: bool,
44 pub fail_after_handle_transaction: bool,
45 pub fail_before_handle_confirmation: bool,
46 pub fail_after_handle_confirmation: bool,
47 pub overload_retry_after_handle_transaction: Option<Duration>,
48}
49
50impl LocalAuthorityClientFaultConfig {
51 pub fn reset(&mut self) {
52 *self = Self::default();
53 }
54}
55
56#[derive(Clone)]
57pub struct LocalAuthorityClient {
58 pub state: Arc<AuthorityState>,
59 pub fault_config: LocalAuthorityClientFaultConfig,
60}
61
62#[async_trait]
63impl ValidatorPeerAPI for LocalAuthorityClient {
64 async fn get_checkpoint_v2(
65 &self,
66 _request: CheckpointRequest,
67 ) -> Result<CheckpointResponse, IotaError> {
68 unimplemented!()
69 }
70}
71#[async_trait]
72impl ValidatorV2API for LocalAuthorityClient {
73 async fn submit_tx(
74 &self,
75 _transactions: Vec<Transaction>,
76 _client_addr: Option<SocketAddr>,
77 ) -> Result<Vec<(TransactionDigest, TxStatusUpdate)>, IotaError> {
78 unimplemented!()
79 }
80 async fn get_tx_status(
81 &self,
82 _request: GetTxStatusRequest,
83 _client_addr: Option<SocketAddr>,
84 ) -> Result<Vec<(TransactionDigest, TxStatusUpdate)>, IotaError> {
85 unimplemented!()
86 }
87 async fn notify_capabilities_v2(
88 &self,
89 request: HandleCapabilityNotificationRequestV1,
90 ) -> Result<HandleCapabilityNotificationResponseV1, IotaError> {
91 let state = self.state.clone();
92 let epoch_store = state.load_epoch_store_one_call_per_task();
93
94 let verified_authority_capabilities =
95 epoch_store.verify_authority_capabilities(request.message)?;
96
97 info!(
98 "Received capability notification (v2): {:?}",
99 verified_authority_capabilities.data()
100 );
101
102 epoch_store.record_capabilities_v1(verified_authority_capabilities.data())?;
103
104 Ok(HandleCapabilityNotificationResponseV1 { _unused: false })
105 }
106 async fn health_check(
107 &self,
108 _request: ValidatorHealthRequest,
109 ) -> Result<ValidatorHealthResponse, IotaError> {
110 unimplemented!()
111 }
112}
113#[async_trait]
114impl ValidatorAPI for LocalAuthorityClient {
115 async fn handle_transaction(
116 &self,
117 transaction: Transaction,
118 _client_addr: Option<SocketAddr>,
119 ) -> Result<HandleTransactionResponse, IotaError> {
120 if self.fault_config.fail_before_handle_transaction {
121 return Err(IotaError::from("Mock error before handle_transaction"));
122 }
123 let state = self.state.clone();
124 let epoch_store = self.state.load_epoch_store_one_call_per_task();
125 let transaction = epoch_store
126 .signature_verifier
127 .verify_tx(transaction.data())
128 .map(|_| VerifiedTransaction::new_from_verified(transaction))?;
129 let result = state.handle_transaction(&epoch_store, transaction).await;
130 if self.fault_config.fail_after_handle_transaction {
131 return Err(IotaError::GenericAuthority {
132 error: "Mock error after handle_transaction".to_owned(),
133 });
134 }
135 if let Some(duration) = self.fault_config.overload_retry_after_handle_transaction {
136 return Err(IotaError::ValidatorOverloadedRetryAfter {
137 retry_after_secs: duration.as_secs(),
138 });
139 }
140 result
141 }
142
143 async fn handle_certificate_v1(
144 &self,
145 request: HandleCertificateRequestV1,
146 _client_addr: Option<SocketAddr>,
147 ) -> Result<HandleCertificateResponseV1, IotaError> {
148 let state = self.state.clone();
149 let fault_config = self.fault_config;
150 spawn_monitored_task!(Self::handle_certificate(state, request, fault_config))
151 .await
152 .unwrap()
153 }
154
155 async fn handle_soft_bundle_certificates_v1(
156 &self,
157 _request: HandleSoftBundleCertificatesRequestV1,
158 _client_addr: Option<SocketAddr>,
159 ) -> Result<HandleSoftBundleCertificatesResponseV1, IotaError> {
160 unimplemented!()
161 }
162
163 async fn handle_object_info_request(
164 &self,
165 request: ObjectInfoRequest,
166 ) -> Result<ObjectInfoResponse, IotaError> {
167 let state = self.state.clone();
168 state.handle_object_info_request(request).await
169 }
170
171 async fn handle_transaction_info_request(
173 &self,
174 request: TransactionInfoRequest,
175 ) -> Result<TransactionInfoResponse, IotaError> {
176 let state = self.state.clone();
177 state.handle_transaction_info_request(request).await
178 }
179
180 async fn handle_checkpoint(
181 &self,
182 request: CheckpointRequest,
183 ) -> Result<CheckpointResponse, IotaError> {
184 let state = self.state.clone();
185
186 state.handle_checkpoint_request(&request)
187 }
188
189 async fn handle_system_state_object(
190 &self,
191 _request: SystemStateRequest,
192 ) -> Result<IotaSystemState, IotaError> {
193 self.state.get_iota_system_state_object_for_testing()
194 }
195
196 async fn handle_capability_notification_v1(
197 &self,
198 request: HandleCapabilityNotificationRequestV1,
199 ) -> Result<HandleCapabilityNotificationResponseV1, IotaError> {
200 let state = self.state.clone();
201 let epoch_store = state.load_epoch_store_one_call_per_task();
202
203 let verified_authority_capabilities =
205 epoch_store.verify_authority_capabilities(request.message)?;
206
207 info!(
209 "Received capability notification: {:?}",
210 verified_authority_capabilities.data()
211 );
212
213 epoch_store.record_capabilities_v1(verified_authority_capabilities.data())?;
215
216 Ok(HandleCapabilityNotificationResponseV1 { _unused: false })
217 }
218}
219
220impl LocalAuthorityClient {
221 pub async fn new(secret: AuthorityKeyPair, genesis: &Genesis) -> Self {
222 let state = TestAuthorityBuilder::new()
223 .with_genesis_and_keypair(genesis, &secret)
224 .build()
225 .await;
226 Self {
227 state,
228 fault_config: LocalAuthorityClientFaultConfig::default(),
229 }
230 }
231
232 pub fn new_from_authority(state: Arc<AuthorityState>) -> Self {
233 Self {
234 state,
235 fault_config: LocalAuthorityClientFaultConfig::default(),
236 }
237 }
238
239 async fn handle_certificate(
244 state: Arc<AuthorityState>,
245 request: HandleCertificateRequestV1,
246 fault_config: LocalAuthorityClientFaultConfig,
247 ) -> Result<HandleCertificateResponseV1, IotaError> {
248 if fault_config.fail_before_handle_confirmation {
249 return Err(IotaError::GenericAuthority {
250 error: "Mock error before handle_confirmation_transaction".to_owned(),
251 });
252 }
253 let tx_digest = *request.certificate.digest();
256 let epoch_store = state.epoch_store_for_testing();
257 let signed_effects = match state
258 .get_signed_effects_and_maybe_resign(&tx_digest, &epoch_store)
259 {
260 Ok(Some(effects)) => effects,
261 _ => {
262 let certificate = epoch_store
263 .signature_verifier
264 .verify_cert(request.certificate)
265 .await?;
266 state.enqueue_certificates_for_execution(vec![certificate.clone()], &epoch_store);
268 let effects = state.notify_read_effects(&certificate).await?;
269 state.sign_effects(effects, &epoch_store)?
270 }
271 }
272 .into_inner();
273
274 let events = if request.include_events {
275 if signed_effects.events_digest().is_some() {
276 Some(state.get_transaction_events(signed_effects.transaction_digest())?)
277 } else {
278 None
279 }
280 } else {
281 None
282 };
283
284 if fault_config.fail_after_handle_confirmation {
285 return Err(IotaError::GenericAuthority {
286 error: "Mock error after handle_confirmation_transaction".to_owned(),
287 });
288 }
289
290 let input_objects = request
291 .include_input_objects
292 .then(|| state.get_transaction_input_objects(&signed_effects))
293 .and_then(Result::ok);
294
295 let output_objects = request
296 .include_output_objects
297 .then(|| state.get_transaction_output_objects(&signed_effects))
298 .and_then(Result::ok);
299
300 Ok(HandleCertificateResponseV1 {
301 signed_effects,
302 events,
303 input_objects,
304 output_objects,
305 auxiliary_data: None, })
307 }
308}
309
310type GetTxStatusResult = IotaResult<Vec<(TransactionDigest, TxStatusUpdate)>>;
311
312#[derive(Clone)]
313pub struct MockAuthorityApi {
314 delay: Duration,
315 count: Arc<Mutex<u32>>,
316 handle_object_info_request_result: Option<IotaResult<ObjectInfoResponse>>,
317 handle_capability_notification_result:
318 Option<IotaResult<HandleCapabilityNotificationResponseV1>>,
319 tx_status_stub: Arc<Mutex<Option<GetTxStatusResult>>>,
320}
321
322impl MockAuthorityApi {
323 pub fn new(delay: Duration, count: Arc<Mutex<u32>>) -> Self {
324 MockAuthorityApi {
325 delay,
326 count,
327 handle_object_info_request_result: None,
328 handle_capability_notification_result: None,
329 tx_status_stub: Arc::new(Mutex::new(None)),
330 }
331 }
332
333 pub fn set_handle_object_info_request(&mut self, result: IotaResult<ObjectInfoResponse>) {
334 self.handle_object_info_request_result = Some(result);
335 }
336
337 pub fn set_handle_capability_notification(
338 &mut self,
339 result: IotaResult<HandleCapabilityNotificationResponseV1>,
340 ) {
341 self.handle_capability_notification_result = Some(result);
342 }
343
344 pub fn stub_tx_status(&self, response: GetTxStatusResult) {
345 *self.tx_status_stub.lock().unwrap() = Some(response);
346 }
347}
348
349#[async_trait]
350impl ValidatorPeerAPI for MockAuthorityApi {
351 async fn get_checkpoint_v2(
352 &self,
353 _request: CheckpointRequest,
354 ) -> Result<CheckpointResponse, IotaError> {
355 unimplemented!()
356 }
357}
358#[async_trait]
359impl ValidatorV2API for MockAuthorityApi {
360 async fn submit_tx(
361 &self,
362 _transactions: Vec<Transaction>,
363 _client_addr: Option<SocketAddr>,
364 ) -> Result<Vec<(TransactionDigest, TxStatusUpdate)>, IotaError> {
365 unimplemented!()
366 }
367 async fn get_tx_status(
368 &self,
369 _request: GetTxStatusRequest,
370 _client_addr: Option<SocketAddr>,
371 ) -> Result<Vec<(TransactionDigest, TxStatusUpdate)>, IotaError> {
372 let Some(result) = self.tx_status_stub.lock().unwrap().clone() else {
373 return Err(IotaError::Unknown(
374 "MockAuthorityApi::get_tx_status was called without a stub".to_string(),
375 ));
376 };
377 tokio::time::sleep(self.delay).await;
378 result
379 }
380 async fn notify_capabilities_v2(
381 &self,
382 _request: HandleCapabilityNotificationRequestV1,
383 ) -> Result<HandleCapabilityNotificationResponseV1, IotaError> {
384 tokio::time::sleep(self.delay).await;
385
386 match &self.handle_capability_notification_result {
387 Some(result) => result.clone(),
388 None => Ok(HandleCapabilityNotificationResponseV1 { _unused: false }),
389 }
390 }
391 async fn health_check(
392 &self,
393 _request: ValidatorHealthRequest,
394 ) -> Result<ValidatorHealthResponse, IotaError> {
395 unimplemented!()
396 }
397}
398#[async_trait]
399impl ValidatorAPI for MockAuthorityApi {
400 async fn handle_transaction(
402 &self,
403 _transaction: Transaction,
404 _client_addr: Option<SocketAddr>,
405 ) -> Result<HandleTransactionResponse, IotaError> {
406 unimplemented!();
407 }
408
409 async fn handle_certificate_v1(
410 &self,
411 _request: HandleCertificateRequestV1,
412 _client_addr: Option<SocketAddr>,
413 ) -> Result<HandleCertificateResponseV1, IotaError> {
414 unimplemented!()
415 }
416
417 async fn handle_soft_bundle_certificates_v1(
418 &self,
419 _request: HandleSoftBundleCertificatesRequestV1,
420 _client_addr: Option<SocketAddr>,
421 ) -> Result<HandleSoftBundleCertificatesResponseV1, IotaError> {
422 unimplemented!()
423 }
424
425 async fn handle_object_info_request(
427 &self,
428 _request: ObjectInfoRequest,
429 ) -> Result<ObjectInfoResponse, IotaError> {
430 self.handle_object_info_request_result.clone().unwrap()
431 }
432
433 async fn handle_transaction_info_request(
435 &self,
436 request: TransactionInfoRequest,
437 ) -> Result<TransactionInfoResponse, IotaError> {
438 let count = {
439 let mut count = self.count.lock().unwrap();
440 *count += 1;
441 *count
442 };
443
444 if count < 15 {
446 tokio::time::sleep(self.delay).await;
447 }
448
449 Err(IotaError::TransactionNotFound {
450 digest: request.transaction_digest,
451 })
452 }
453
454 async fn handle_checkpoint(
455 &self,
456 _request: CheckpointRequest,
457 ) -> Result<CheckpointResponse, IotaError> {
458 unimplemented!();
459 }
460
461 async fn handle_system_state_object(
462 &self,
463 _request: SystemStateRequest,
464 ) -> Result<IotaSystemState, IotaError> {
465 unimplemented!();
466 }
467
468 async fn handle_capability_notification_v1(
469 &self,
470 _request: HandleCapabilityNotificationRequestV1,
471 ) -> Result<HandleCapabilityNotificationResponseV1, IotaError> {
472 tokio::time::sleep(self.delay).await;
473
474 match &self.handle_capability_notification_result {
475 Some(result) => result.clone(),
476 None => Ok(HandleCapabilityNotificationResponseV1 { _unused: false }),
477 }
478 }
479}
480
481#[derive(Clone)]
482pub struct HandleTransactionTestAuthorityClient {
483 pub tx_info_resp_to_return: IotaResult<HandleTransactionResponse>,
484 pub cert_resp_to_return: IotaResult<HandleCertificateResponseV1>,
485 pub sleep_duration_before_responding: Option<Duration>,
488}
489
490#[async_trait]
491impl ValidatorPeerAPI for HandleTransactionTestAuthorityClient {
492 async fn get_checkpoint_v2(
493 &self,
494 _request: CheckpointRequest,
495 ) -> Result<CheckpointResponse, IotaError> {
496 unimplemented!()
497 }
498}
499#[async_trait]
500impl ValidatorV2API for HandleTransactionTestAuthorityClient {
501 async fn submit_tx(
502 &self,
503 _transactions: Vec<Transaction>,
504 _client_addr: Option<SocketAddr>,
505 ) -> Result<Vec<(TransactionDigest, TxStatusUpdate)>, IotaError> {
506 unimplemented!()
507 }
508 async fn get_tx_status(
509 &self,
510 _request: GetTxStatusRequest,
511 _client_addr: Option<SocketAddr>,
512 ) -> Result<Vec<(TransactionDigest, TxStatusUpdate)>, IotaError> {
513 unimplemented!()
514 }
515 async fn notify_capabilities_v2(
516 &self,
517 _request: HandleCapabilityNotificationRequestV1,
518 ) -> Result<HandleCapabilityNotificationResponseV1, IotaError> {
519 unimplemented!()
520 }
521 async fn health_check(
522 &self,
523 _request: ValidatorHealthRequest,
524 ) -> Result<ValidatorHealthResponse, IotaError> {
525 unimplemented!()
526 }
527}
528
529#[async_trait]
530impl ValidatorAPI for HandleTransactionTestAuthorityClient {
531 async fn handle_transaction(
532 &self,
533 _transaction: Transaction,
534 _client_addr: Option<SocketAddr>,
535 ) -> Result<HandleTransactionResponse, IotaError> {
536 if let Some(duration) = self.sleep_duration_before_responding {
537 tokio::time::sleep(duration).await;
538 }
539 self.tx_info_resp_to_return.clone()
540 }
541
542 async fn handle_certificate_v1(
543 &self,
544 _request: HandleCertificateRequestV1,
545 _client_addr: Option<SocketAddr>,
546 ) -> Result<HandleCertificateResponseV1, IotaError> {
547 if let Some(duration) = self.sleep_duration_before_responding {
548 tokio::time::sleep(duration).await;
549 }
550 self.cert_resp_to_return.clone()
551 }
552
553 async fn handle_soft_bundle_certificates_v1(
554 &self,
555 _request: HandleSoftBundleCertificatesRequestV1,
556 _client_addr: Option<SocketAddr>,
557 ) -> Result<HandleSoftBundleCertificatesResponseV1, IotaError> {
558 unimplemented!()
559 }
560
561 async fn handle_object_info_request(
562 &self,
563 _request: ObjectInfoRequest,
564 ) -> Result<ObjectInfoResponse, IotaError> {
565 unimplemented!()
566 }
567
568 async fn handle_transaction_info_request(
569 &self,
570 _request: TransactionInfoRequest,
571 ) -> Result<TransactionInfoResponse, IotaError> {
572 unimplemented!()
573 }
574
575 async fn handle_checkpoint(
576 &self,
577 _request: CheckpointRequest,
578 ) -> Result<CheckpointResponse, IotaError> {
579 unimplemented!()
580 }
581
582 async fn handle_system_state_object(
583 &self,
584 _request: SystemStateRequest,
585 ) -> Result<IotaSystemState, IotaError> {
586 unimplemented!()
587 }
588
589 async fn handle_capability_notification_v1(
590 &self,
591 _request: HandleCapabilityNotificationRequestV1,
592 ) -> Result<HandleCapabilityNotificationResponseV1, IotaError> {
593 unimplemented!()
594 }
595}
596
597impl HandleTransactionTestAuthorityClient {
598 pub fn new() -> Self {
599 Self {
600 tx_info_resp_to_return: Err(IotaError::Unknown("".to_string())),
601 cert_resp_to_return: Err(IotaError::Unknown("".to_string())),
602 sleep_duration_before_responding: None,
603 }
604 }
605
606 pub fn set_tx_info_response(&mut self, resp: HandleTransactionResponse) {
607 self.tx_info_resp_to_return = Ok(resp);
608 }
609
610 pub fn set_tx_info_response_error(&mut self, error: IotaError) {
611 self.tx_info_resp_to_return = Err(error);
612 }
613
614 pub fn reset_tx_info_response(&mut self) {
615 self.tx_info_resp_to_return = Err(IotaError::Unknown("".to_string()));
616 }
617
618 pub fn set_cert_resp_to_return(&mut self, resp: HandleCertificateResponseV1) {
619 self.cert_resp_to_return = Ok(resp);
620 }
621
622 pub fn set_cert_resp_to_return_error(&mut self, error: IotaError) {
623 self.cert_resp_to_return = Err(error);
624 }
625
626 pub fn reset_cert_response(&mut self) {
627 self.cert_resp_to_return = Err(IotaError::Unknown("".to_string()));
628 }
629
630 pub fn set_sleep_duration_before_responding(&mut self, duration: Duration) {
631 self.sleep_duration_before_responding = Some(duration);
632 }
633}
634
635impl Default for HandleTransactionTestAuthorityClient {
636 fn default() -> Self {
637 Self::new()
638 }
639}