1use crate::{
4 governance::model::Quorum,
5 helpers::network::service::NetworkSender,
6 metrics::try_core_metrics,
7 model::{
8 common::{
9 abort_req, emit_fail, send_reboot_to_req, take_random_signers,
10 },
11 event::{ValidationData, ValidationMetadata},
12 },
13 request::manager::{RebootType, RequestManager, RequestManagerMessage},
14 validation::{
15 coordinator::{ValiCoordinator, ValiCoordinatorMessage},
16 response::ResponseSummary,
17 worker::{
18 CurrentRequestRoles, CurrentWorkerRoles, ValiWorker,
19 ValiWorkerMessage,
20 },
21 },
22};
23use ave_actors::{
24 Actor, ActorContext, ActorError, ActorPath, ChildAction, Handler, Message,
25 NotPersistentActor,
26};
27
28use async_trait::async_trait;
29use ave_common::{
30 ValueWrapper,
31 identity::{
32 CryptoError, DigestIdentifier, HashAlgorithm, PublicKey, Signature,
33 Signed, hash_borsh,
34 },
35};
36
37use request::ValidationReq;
38use response::ValidationRes;
39use tracing::{Span, debug, error, info_span, warn};
40
41use std::{collections::HashSet, sync::Arc};
42
43pub mod coordinator;
44pub mod request;
45pub mod response;
46pub mod schema;
47pub mod worker;
48
49#[derive(Clone, Debug)]
50pub struct Validation {
51 our_key: Arc<PublicKey>,
52 quorum: Quorum,
54 validators_signatures: Vec<Signature>,
56
57 validators_response: Vec<ValidationMetadata>,
58
59 validators_quantity: u32,
60
61 request: Signed<ValidationReq>,
62
63 hash: HashAlgorithm,
64
65 network: Arc<NetworkSender>,
66
67 request_id: DigestIdentifier,
68
69 version: u64,
70
71 validation_request_hash: DigestIdentifier,
72
73 reboot: bool,
74
75 current_validators: HashSet<PublicKey>,
76
77 pending_validators: HashSet<PublicKey>,
78
79 init_state: Option<ValueWrapper>,
80
81 current_request_roles: CurrentRequestRoles,
82}
83
84impl Validation {
85 fn observe_event(result: &'static str) {
86 if let Some(metrics) = try_core_metrics() {
87 metrics.observe_protocol_event("validation", result);
88 }
89 }
90
91 pub fn new(
92 our_key: Arc<PublicKey>,
93 request: Signed<ValidationReq>,
94 init_state: Option<ValueWrapper>,
95 current_request_roles: CurrentRequestRoles,
96 quorum: Quorum,
97 hash: HashAlgorithm,
98 network: Arc<NetworkSender>,
99 ) -> Self {
100 Self {
101 our_key,
102 quorum,
103 init_state,
104 validators_response: vec![],
105 validators_signatures: vec![],
106 validators_quantity: 0,
107 request,
108 hash,
109 network,
110 request_id: DigestIdentifier::default(),
111 version: 0,
112 validation_request_hash: DigestIdentifier::default(),
113 reboot: false,
114 current_validators: HashSet::new(),
115 pending_validators: HashSet::new(),
116 current_request_roles,
117 }
118 }
119
120 fn check_validator(&mut self, validator: PublicKey) -> bool {
121 self.current_validators.remove(&validator)
122 }
123
124 async fn create_validators(
125 &self,
126 ctx: &mut ActorContext<Self>,
127 signer: PublicKey,
128 ) -> Result<(), ActorError> {
129 if signer != *self.our_key {
130 let child = ctx
131 .create_child(
132 &format!("{}", signer),
133 ValiCoordinator::new(
134 signer.clone(),
135 self.request_id.to_string(),
136 self.version,
137 self.network.clone(),
138 ),
139 )
140 .await?;
141
142 child
143 .tell(ValiCoordinatorMessage::NetworkValidation {
144 validation_req: Box::new(self.request.clone()),
145 node_key: signer,
146 })
147 .await?
148 } else {
149 let child = ctx
150 .create_child(
151 &format!("{}", signer),
152 ValiWorker {
153 node_key: (*self.our_key).clone(),
154 our_key: self.our_key.clone(),
155 init_state: self.init_state.clone(),
156 governance_id: self
157 .request
158 .content().get_governance_id().expect("The build process verified that the event request is valid")
159 ,
160 gov_version: self.request.content().get_gov_version(),
161 sn: self.request.content().get_sn(),
162 hash: self.hash,
163 network: self.network.clone(),
164 current_roles: CurrentWorkerRoles {
165 evaluation: self
166 .current_request_roles
167 .evaluation
168 .clone(),
169 approval: self.current_request_roles.approval.clone(),
170 },
171 stop:true
172 },
173 )
174 .await?;
175
176 child
177 .tell(ValiWorkerMessage::LocalValidation {
178 validation_req: Box::new(self.request.clone()),
179 })
180 .await?
181 }
182
183 Ok(())
184 }
185
186 async fn send_validation_to_req(
187 &self,
188 ctx: &ActorContext<Self>,
189 response: ValidationData,
190 ) -> Result<(), ActorError> {
191 let req_actor = ctx.get_parent::<RequestManager>().await?;
192
193 req_actor
194 .tell(RequestManagerMessage::ValidationRes {
195 request_id: self.request_id.clone(),
196 val_req: Box::new(self.request.content().clone()),
197 val_res: response,
198 })
199 .await?;
200
201 Ok(())
202 }
203
204 fn create_vali_req_hash(&self) -> Result<DigestIdentifier, CryptoError> {
205 hash_borsh(&*self.hash.hasher(), &self.request)
206 }
207
208 fn check_responses(&self) -> ResponseSummary {
209 let res_set: HashSet<ValidationMetadata> =
210 HashSet::from_iter(self.validators_response.iter().cloned());
211
212 if res_set.len() == 1 {
213 ResponseSummary::Ok
214 } else {
215 ResponseSummary::Reboot
216 }
217 }
218
219 fn build_validation_data(&self) -> ValidationData {
220 ValidationData {
221 validation_req_signature: self.request.signature().clone(),
222 validation_req_hash: self.validation_request_hash.clone(),
223 validators_signatures: self.validators_signatures.clone(),
224 validation_metadata: self.validators_response[0].clone(),
225 }
226 }
227}
228
229#[derive(Debug, Clone)]
230pub enum ValidationMessage {
231 Create {
232 request_id: DigestIdentifier,
233 version: u64,
234 signers: HashSet<PublicKey>,
235 },
236 Response {
237 validation_res: Box<ValidationRes>,
238 sender: PublicKey,
239 signature: Option<Signature>,
240 },
241}
242
243impl Message for ValidationMessage {}
244
245impl NotPersistentActor for Validation {}
246
247#[async_trait]
248impl Actor for Validation {
249 type Event = ();
250 type Message = ValidationMessage;
251 type Response = ();
252
253 fn get_span(_id: &str, parent_span: Option<Span>) -> tracing::Span {
254 parent_span.map_or_else(
255 || info_span!("Validation"),
256 |parent_span| info_span!(parent: parent_span, "Validation"),
257 )
258 }
259}
260
261#[async_trait]
262impl Handler<Self> for Validation {
263 async fn handle_message(
264 &mut self,
265 _sender: ActorPath,
266 msg: ValidationMessage,
267 ctx: &mut ActorContext<Self>,
268 ) -> Result<(), ActorError> {
269 match msg {
270 ValidationMessage::Create {
271 request_id,
272 version,
273 signers,
274 } => {
275 let vali_req_hash = match self.create_vali_req_hash() {
276 Ok(digest) => digest,
277 Err(e) => {
278 error!(
279 msg_type = "Create",
280 error = %e,
281 "Failed to create validation request hash"
282 );
283 return Err(emit_fail(
284 ctx,
285 ActorError::FunctionalCritical {
286 description: format!(
287 "Cannot create validation request hash: {}",
288 e
289 ),
290 },
291 )
292 .await);
293 }
294 };
295
296 self.validation_request_hash = vali_req_hash;
297 self.validators_quantity = signers.len() as u32;
298 self.request_id = request_id.clone();
299 self.version = version;
300
301 let validators_quantity = self.quorum.get_signers(
302 self.validators_quantity,
303 signers.len() as u32,
304 );
305
306 let (current_vali, pending_vali) =
307 take_random_signers(signers, validators_quantity as usize);
308 self.current_validators.clone_from(¤t_vali);
309 self.pending_validators.clone_from(&pending_vali);
310
311 for signer in current_vali.clone() {
312 if let Err(e) =
313 self.create_validators(ctx, signer.clone()).await
314 {
315 error!(
316 msg_type = "Create",
317 error = %e,
318 signer = %signer,
319 "Failed to create validator"
320 );
321 }
322 }
323
324 debug!(
325 msg_type = "Create",
326 request_id = %request_id,
327 version = version,
328 validators_count = current_vali.len(),
329 "Validation created and validators initialized"
330 );
331 }
332 ValidationMessage::Response {
333 validation_res,
334 sender,
335 signature,
336 } => {
337 if !self.reboot {
338 if self.check_validator(sender.clone()) {
339 match *validation_res {
340 ValidationRes::Create {
341 vali_req_hash,
342 subject_metadata,
343 } => {
344 let Some(signature) = signature else {
345 error!(
346 msg_type = "Response",
347 sender = %sender,
348 "Validation response without signature"
349 );
350 return Err(ActorError::Functional {
351 description: "Validation Response solver without signature".to_owned(),
352 });
353 };
354
355 if vali_req_hash != self.validation_request_hash
356 {
357 error!(
358 msg_type = "Response",
359 expected_hash = %self.validation_request_hash,
360 received_hash = %vali_req_hash,
361 "Invalid validation request hash"
362 );
363 return Err(ActorError::Functional {
364 description: "Validation Response, Invalid validation request hash".to_owned(),
365 });
366 }
367
368 self.validators_response.push(
369 ValidationMetadata::Metadata(
370 subject_metadata,
371 ),
372 );
373 self.validators_signatures.push(signature);
374 }
375 ValidationRes::Response {
376 vali_req_hash,
377 modified_metadata_hash,
378 } => {
379 let Some(signature) = signature else {
380 error!(
381 msg_type = "Response",
382 sender = %sender,
383 "Validation response without signature"
384 );
385 return Err(ActorError::Functional {
386 description: "Validation Response solver without signature".to_owned(),
387 });
388 };
389
390 if vali_req_hash != self.validation_request_hash
391 {
392 error!(
393 msg_type = "Response",
394 expected_hash = %self.validation_request_hash,
395 received_hash = %vali_req_hash,
396 "Invalid validation request hash"
397 );
398 return Err(ActorError::Functional {
399 description: "Validation Response, Invalid validation request hash".to_owned(),
400 });
401 }
402
403 self.validators_response.push(
404 ValidationMetadata::ModifiedHash(
405 modified_metadata_hash,
406 ),
407 );
408 self.validators_signatures.push(signature);
409 }
410 ValidationRes::TimeOut => {
411 Self::observe_event("timeout");
412 }
413 ValidationRes::Abort(error) => {
414 Self::observe_event("abort");
415 if let Err(e) = abort_req(
416 ctx,
417 self.request_id.clone(),
418 sender.clone(),
419 error,
420 self.request.content().get_sn(),
421 )
422 .await
423 {
424 error!(
425 msg_type = "Response",
426 error = %e,
427 sender = %sender,
428 "Failed to abort request"
429 );
430 return Err(emit_fail(ctx, e).await);
431 }
432 }
433 ValidationRes::Reboot => {
434 Self::observe_event("reboot");
435 if let Err(e) = send_reboot_to_req(
436 ctx,
437 self.request_id.clone(),
438 self.request
439 .content().get_governance_id().expect("The build process verified that the event request is valid"),
440 RebootType::Normal
441 )
442 .await
443 {
444 error!(
445 msg_type = "Response",
446 error = %e,
447 "Failed to send reboot to request actor"
448 );
449 return Err(emit_fail(ctx, e).await);
450 }
451
452 self.reboot = true;
453
454 return Ok(());
455 }
456 };
457
458 if self.quorum.check_quorum(
459 self.validators_quantity,
460 self.validators_response.len() as u32,
461 ) {
462 let summary = self.check_responses();
463 if matches!(summary, ResponseSummary::Reboot)
464 && let Err(e) = send_reboot_to_req(
465 ctx,
466 self.request_id.clone(),
467 self.request
468 .content().get_governance_id().expect("The build process verified that the event request is valid"),
469 RebootType::Diff
470 )
471 .await
472 {
473 error!(
474 msg_type = "Response",
475 error = %e,
476 "Failed to send reboot to request actor"
477 );
478 return Err(emit_fail(ctx, e).await);
479 }
480 if matches!(summary, ResponseSummary::Reboot) {
481 Self::observe_event("reboot");
482 }
483
484 let validation_data = self.build_validation_data();
485
486 if let Err(e) = self
487 .send_validation_to_req(ctx, validation_data)
488 .await
489 {
490 error!(
491 msg_type = "Response",
492 error = %e,
493 "Failed to send validation to request actor"
494 );
495 return Err(emit_fail(ctx, e).await);
496 };
497
498 if !matches!(summary, ResponseSummary::Reboot) {
499 Self::observe_event("success");
500 }
501
502 debug!(
503 msg_type = "Response",
504 request_id = %self.request_id,
505 version = self.version,
506 "Validation completed and sent to request"
507 );
508 } else if self.current_validators.is_empty()
509 && !self.pending_validators.is_empty()
510 {
511 let validators_quantity = self.quorum.get_signers(
512 self.validators_quantity,
513 self.pending_validators.len() as u32,
514 );
515
516 let (curren_vali, pending_vali) =
517 take_random_signers(
518 self.pending_validators.clone(),
519 validators_quantity as usize,
520 );
521 self.current_validators.clone_from(¤_vali);
522 self.pending_validators.clone_from(&pending_vali);
523
524 for signer in curren_vali.clone() {
525 if let Err(e) = self
526 .create_validators(ctx, signer.clone())
527 .await
528 {
529 error!(
530 msg_type = "Response",
531 error = %e,
532 signer = %signer,
533 "Failed to create validator from pending pool"
534 );
535 }
536 }
537
538 debug!(
539 msg_type = "Response",
540 new_validators = curren_vali.len(),
541 "Created additional validators from pending pool"
542 );
543 } else if self.current_validators.is_empty()
544 && let Err(e) = send_reboot_to_req(
545 ctx,
546 self.request_id.clone(),
547 self.request
548 .content().get_governance_id().expect("The build process verified that the event request is valid"),
549 RebootType::TimeOut
550 )
551 .await
552 {
553 error!(
554 msg_type = "Response",
555 error = %e,
556 "Failed to send reboot to request actor"
557 );
558 return Err(emit_fail(ctx, e).await);
559 } else if self.current_validators.is_empty() {
560 Self::observe_event("reboot");
561 }
562 } else {
563 warn!(
564 msg_type = "Response",
565 sender = %sender,
566 "Response from unexpected sender"
567 );
568 }
569 }
570 }
571 };
572 Ok(())
573 }
574
575 async fn on_child_fault(
576 &mut self,
577 error: ActorError,
578 ctx: &mut ActorContext<Self>,
579 ) -> ChildAction {
580 Self::observe_event("error");
581 error!(
582 request_id = %self.request_id,
583 version = self.version,
584 error = %error,
585 "Child fault in validation actor"
586 );
587 emit_fail(ctx, error).await;
588 ChildAction::Stop
589 }
590}
591
592#[cfg(test)]
593pub mod tests {
594 use core::panic;
595 use std::{sync::Arc, time::Duration};
596 use tempfile::TempDir;
597 use test_log::test;
598
599 use ave_actors::{ActorPath, ActorRef, PersistentActor, SystemRef};
600 use ave_common::{
601 Namespace, SchemaType,
602 identity::{
603 DigestIdentifier, HashAlgorithm, KeyPair, keys::Ed25519Signer,
604 },
605 request::{CreateRequest, EOLRequest},
606 response::RequestEventDB,
607 };
608 use tokio::sync::mpsc;
609
610 use crate::{
611 EventRequest, Node, NodeMessage, NodeResponse, Signed,
612 evaluation::tests::wait_request,
613 governance::{
614 Governance, GovernanceMessage, GovernanceResponse,
615 data::GovernanceData,
616 },
617 helpers::{
618 db::{ExternalDB, ReadStore},
619 network::service::NetworkSender,
620 },
621 model::common::node::SignTypesNode,
622 node::InitParamsNode,
623 request::{
624 RequestHandler, RequestHandlerMessage, RequestHandlerResponse,
625 tracking::RequestTracking,
626 },
627 system::tests::create_system,
628 };
629
630 async fn get_subject_state(
631 db: &Arc<ExternalDB>,
632 subject_id: &DigestIdentifier,
633 expected_sn: u64,
634 ) -> ave_common::response::SubjectDB {
635 let started = tokio::time::Instant::now();
636 loop {
637 match db.get_subject_state(&subject_id.to_string()).await {
638 Ok(state) if state.sn >= expected_sn => return state,
639 Ok(_) | Err(_)
640 if started.elapsed() < Duration::from_secs(5) =>
641 {
642 tokio::time::sleep(Duration::from_millis(10)).await;
643 }
644 Ok(state) => {
645 panic!(
646 "subject state not updated in time for {}: expected sn >= {}, got {}",
647 subject_id, expected_sn, state.sn
648 );
649 }
650 Err(error) => {
651 panic!(
652 "subject state not available in time for {}: {}",
653 subject_id, error
654 );
655 }
656 }
657 }
658 }
659
660 async fn get_event_sn(
661 db: &Arc<ExternalDB>,
662 subject_id: &DigestIdentifier,
663 sn: u64,
664 ) -> ave_common::response::LedgerDB {
665 let started = tokio::time::Instant::now();
666 loop {
667 match db.get_event_sn(&subject_id.to_string(), sn).await {
668 Ok(event) => return event,
669 Err(_) if started.elapsed() < Duration::from_secs(5) => {
670 tokio::time::sleep(Duration::from_millis(10)).await;
671 }
672 Err(error) => {
673 panic!(
674 "event {} for {} not available in time: {}",
675 sn, subject_id, error
676 );
677 }
678 }
679 }
680 }
681
682 pub async fn create_gov() -> (
683 SystemRef,
684 ActorRef<Node>,
685 ActorRef<RequestHandler>,
686 Arc<ExternalDB>,
687 ActorRef<Governance>,
688 ActorRef<RequestTracking>,
689 DigestIdentifier,
690 Vec<TempDir>,
691 ) {
692 let node_keys = KeyPair::Ed25519(Ed25519Signer::generate().unwrap());
693 let (system, .., _dirs) = create_system().await;
694
695 let (command_sender, _command_receiver) = mpsc::channel(10);
696 let network = Arc::new(NetworkSender::new(command_sender));
697
698 system.add_helper("network", network.clone()).await;
699
700 let public_key = Arc::new(node_keys.public_key());
701 let node_actor = system
702 .create_root_actor(
703 "node",
704 Node::initial(InitParamsNode {
705 key_pair: node_keys.clone(),
706 public_key: public_key.clone(),
707 hash: HashAlgorithm::Blake3,
708 is_service: true,
709 }),
710 )
711 .await
712 .unwrap();
713
714 let request_actor = system
715 .create_root_actor(
716 "request",
717 RequestHandler::initial((
718 public_key.clone(),
719 (HashAlgorithm::Blake3, network),
720 )),
721 )
722 .await
723 .unwrap();
724
725 let ext_db = system
726 .get_helper::<Arc<ExternalDB>>("ext_db")
727 .await
728 .unwrap();
729
730 let create_req = EventRequest::Create(CreateRequest {
731 name: Some("Name".to_string()),
732 description: Some("Description".to_string()),
733 governance_id: DigestIdentifier::default(),
734 schema_id: SchemaType::Governance,
735 namespace: Namespace::new(),
736 });
737
738 let response = node_actor
739 .ask(NodeMessage::SignRequest(Box::new(
740 SignTypesNode::EventRequest(create_req.clone()),
741 )))
742 .await
743 .unwrap();
744 let NodeResponse::SignRequest(signature) = response else {
745 panic!("Invalid Response")
746 };
747
748 let signed_event_req = Signed::from_parts(create_req, signature);
749
750 let RequestHandlerResponse::Ok(response) = request_actor
751 .ask(RequestHandlerMessage::NewRequest {
752 request: signed_event_req.clone(),
753 })
754 .await
755 .unwrap()
756 else {
757 panic!("Invalid response")
758 };
759
760 let owned_subj = response.subject_id;
761
762 let tracking = system
763 .get_actor::<RequestTracking>(&ActorPath::from(
764 "/user/request/tracking",
765 ))
766 .await
767 .unwrap();
768
769 wait_request(&tracking, response.request_id).await;
770
771 let subject_actor: ActorRef<Governance> = system
772 .get_actor(&ActorPath::from(format!(
773 "/user/node/subject_manager/{}",
774 owned_subj
775 )))
776 .await
777 .unwrap();
778
779 let GovernanceResponse::Metadata(metadata) = subject_actor
780 .ask(GovernanceMessage::GetMetadata)
781 .await
782 .unwrap()
783 else {
784 panic!("Invalid response")
785 };
786 let subject_data = get_subject_state(&ext_db, &owned_subj, 0).await;
787 let event = get_event_sn(&ext_db, &owned_subj, 0).await;
788
789 let RequestEventDB::Create {
790 name,
791 description,
792 schema_id,
793 namespace,
794 } = event.event
795 else {
796 panic!()
797 };
798
799 assert_eq!(metadata.name, name);
800 assert_eq!(metadata.name, subject_data.name);
801 assert_eq!(metadata.name.unwrap(), "Name");
802
803 assert_eq!(metadata.description, description);
804 assert_eq!(metadata.description, subject_data.description);
805 assert_eq!(metadata.description.unwrap(), "Description");
806
807 assert_eq!(metadata.subject_id.to_string(), event.subject_id);
808 assert_eq!(metadata.subject_id.to_string(), subject_data.subject_id);
809 assert_eq!(metadata.subject_id, owned_subj);
810
811 assert_eq!(
812 metadata.governance_id.to_string(),
813 subject_data.governance_id
814 );
815 assert_eq!(metadata.governance_id, owned_subj);
816
817 assert_eq!(
818 metadata.genesis_gov_version,
819 subject_data.genesis_gov_version
820 );
821 assert_eq!(metadata.genesis_gov_version, 0);
822
823 assert_eq!(metadata.schema_id.to_string(), schema_id);
824 assert_eq!(
825 metadata.schema_id.to_string(),
826 subject_data.schema_id.to_string()
827 );
828 assert_eq!(metadata.schema_id, SchemaType::Governance);
829
830 assert_eq!(metadata.namespace.to_string(), namespace);
831 assert_eq!(
832 metadata.namespace.to_string(),
833 subject_data.namespace.to_string()
834 );
835 assert_eq!(metadata.namespace, Namespace::new());
836
837 assert!(subject_data.new_owner.is_none());
838 assert!(metadata.new_owner.is_none());
839
840 assert_eq!(metadata.sn, event.sn);
841 assert_eq!(metadata.sn, subject_data.sn);
842 assert_eq!(metadata.sn, 0);
843
844 assert!(subject_data.active);
845 assert!(metadata.active);
846
847 assert_eq!(metadata.properties.0, subject_data.properties);
848 let gov = GovernanceData::try_from(metadata.properties).unwrap();
849 assert_eq!(gov.version, 0);
850
851 assert!(!gov.members.is_empty());
852 assert!(gov.roles_schema.is_empty());
853 assert!(gov.schemas.is_empty());
854 assert!(gov.policies_schema.is_empty());
855
856 (
857 system,
858 node_actor,
859 request_actor,
860 ext_db,
861 subject_actor,
862 tracking,
863 metadata.subject_id,
864 _dirs,
865 )
866 }
867
868 #[test(tokio::test)]
869 async fn test_create_gov() {
870 let _ = create_gov().await;
871 }
872
873 #[test(tokio::test)]
874 async fn test_eol_gov() {
875 let (
876 _system,
877 node_actor,
878 request_actor,
879 db,
880 subject_actor,
881 tracking,
882 subject_id,
883 _dirs,
884 ) = create_gov().await;
885
886 let eol_reques = EventRequest::EOL(EOLRequest {
887 subject_id: subject_id.clone(),
888 });
889
890 let response = node_actor
891 .ask(NodeMessage::SignRequest(Box::new(
892 SignTypesNode::EventRequest(eol_reques.clone()),
893 )))
894 .await
895 .unwrap();
896 let NodeResponse::SignRequest(signature) = response else {
897 panic!("Invalid Response")
898 };
899
900 let signed_event_req = Signed::from_parts(eol_reques, signature);
901
902 let RequestHandlerResponse::Ok(response) = request_actor
903 .ask(RequestHandlerMessage::NewRequest {
904 request: signed_event_req.clone(),
905 })
906 .await
907 .unwrap()
908 else {
909 panic!("Invalid response")
910 };
911
912 wait_request(&tracking, response.request_id).await;
913
914 let GovernanceResponse::Metadata(metadata) = subject_actor
915 .ask(GovernanceMessage::GetMetadata)
916 .await
917 .unwrap()
918 else {
919 panic!("Invalid response")
920 };
921
922 let subject_data = get_subject_state(&db, &subject_id, 1).await;
923 let event = get_event_sn(&db, &subject_id, 1).await;
924
925 let RequestEventDB::EOL = event.event else {
926 panic!()
927 };
928
929 assert_eq!(metadata.name, subject_data.name);
930 assert_eq!(metadata.name.unwrap(), "Name");
931
932 assert_eq!(metadata.description, subject_data.description);
933 assert_eq!(metadata.description.unwrap(), "Description");
934
935 assert_eq!(metadata.subject_id.to_string(), event.subject_id);
936 assert_eq!(metadata.subject_id.to_string(), subject_data.subject_id);
937 assert_eq!(metadata.subject_id, subject_id);
938
939 assert_eq!(
940 metadata.governance_id.to_string(),
941 subject_data.governance_id
942 );
943 assert_eq!(metadata.governance_id, subject_id);
944
945 assert_eq!(
946 metadata.genesis_gov_version,
947 subject_data.genesis_gov_version
948 );
949 assert_eq!(metadata.genesis_gov_version, 0);
950
951 assert_eq!(
952 metadata.schema_id.to_string(),
953 subject_data.schema_id.to_string()
954 );
955 assert_eq!(metadata.schema_id, SchemaType::Governance);
956
957 assert_eq!(
958 metadata.namespace.to_string(),
959 subject_data.namespace.to_string()
960 );
961 assert_eq!(metadata.namespace, Namespace::new());
962
963 assert!(subject_data.new_owner.is_none());
964 assert!(metadata.new_owner.is_none());
965
966 assert_eq!(metadata.sn, event.sn);
967 assert_eq!(metadata.sn, subject_data.sn);
968 assert_eq!(metadata.sn, 1);
969
970 assert!(!subject_data.active);
971 assert!(!metadata.active);
972
973 assert_eq!(metadata.properties.0, subject_data.properties);
974 let gov = GovernanceData::try_from(metadata.properties).unwrap();
975 assert_eq!(gov.version, 1);
976
977 assert!(!gov.members.is_empty());
978 assert!(gov.roles_schema.is_empty());
979 assert!(gov.schemas.is_empty());
980 assert!(gov.policies_schema.is_empty());
981
982 if !request_actor
983 .ask(RequestHandlerMessage::NewRequest {
984 request: signed_event_req.clone(),
985 })
986 .await
987 .is_err()
988 {
989 panic!("Invalid response")
990 }
991 }
992}