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_without_propierties_hash,
378 propierties_hash,
379 event_request_hash,
380 viewpoints_hash,
381 } => {
382 let Some(signature) = signature else {
383 error!(
384 msg_type = "Response",
385 sender = %sender,
386 "Validation response without signature"
387 );
388 return Err(ActorError::Functional {
389 description: "Validation Response solver without signature".to_owned(),
390 });
391 };
392
393 if vali_req_hash != self.validation_request_hash
394 {
395 error!(
396 msg_type = "Response",
397 expected_hash = %self.validation_request_hash,
398 received_hash = %vali_req_hash,
399 "Invalid validation request hash"
400 );
401 return Err(ActorError::Functional {
402 description: "Validation Response, Invalid validation request hash".to_owned(),
403 });
404 }
405
406 self.validators_response.push(
407 ValidationMetadata::ModifiedHash {
408 modified_metadata_without_propierties_hash,
409 propierties_hash,
410 event_request_hash,
411 viewpoints_hash,
412 },
413 );
414 self.validators_signatures.push(signature);
415 }
416 ValidationRes::TimeOut => {
417 Self::observe_event("timeout");
418 }
419 ValidationRes::Abort(error) => {
420 Self::observe_event("abort");
421 if let Err(e) = abort_req(
422 ctx,
423 self.request_id.clone(),
424 sender.clone(),
425 error,
426 self.request.content().get_sn(),
427 )
428 .await
429 {
430 error!(
431 msg_type = "Response",
432 error = %e,
433 sender = %sender,
434 "Failed to abort request"
435 );
436 return Err(emit_fail(ctx, e).await);
437 }
438 }
439 ValidationRes::Reboot => {
440 Self::observe_event("reboot");
441 if let Err(e) = send_reboot_to_req(
442 ctx,
443 self.request_id.clone(),
444 self.request
445 .content().get_governance_id().expect("The build process verified that the event request is valid"),
446 RebootType::Normal
447 )
448 .await
449 {
450 error!(
451 msg_type = "Response",
452 error = %e,
453 "Failed to send reboot to request actor"
454 );
455 return Err(emit_fail(ctx, e).await);
456 }
457
458 self.reboot = true;
459
460 return Ok(());
461 }
462 };
463
464 if self.quorum.check_quorum(
465 self.validators_quantity,
466 self.validators_response.len() as u32,
467 ) {
468 let summary = self.check_responses();
469 if matches!(summary, ResponseSummary::Reboot)
470 && let Err(e) = send_reboot_to_req(
471 ctx,
472 self.request_id.clone(),
473 self.request
474 .content().get_governance_id().expect("The build process verified that the event request is valid"),
475 RebootType::Diff
476 )
477 .await
478 {
479 error!(
480 msg_type = "Response",
481 error = %e,
482 "Failed to send reboot to request actor"
483 );
484 return Err(emit_fail(ctx, e).await);
485 }
486 if matches!(summary, ResponseSummary::Reboot) {
487 Self::observe_event("reboot");
488 return Ok(());
489 }
490
491 let validation_data = self.build_validation_data();
492
493 if let Err(e) = self
494 .send_validation_to_req(ctx, validation_data)
495 .await
496 {
497 error!(
498 msg_type = "Response",
499 error = %e,
500 "Failed to send validation to request actor"
501 );
502 return Err(emit_fail(ctx, e).await);
503 };
504
505 if !matches!(summary, ResponseSummary::Reboot) {
506 Self::observe_event("success");
507 }
508
509 debug!(
510 msg_type = "Response",
511 request_id = %self.request_id,
512 version = self.version,
513 "Validation completed and sent to request"
514 );
515 } else if self.current_validators.is_empty()
516 && !self.pending_validators.is_empty()
517 {
518 let validators_quantity = self.quorum.get_signers(
519 self.validators_quantity,
520 self.pending_validators.len() as u32,
521 );
522
523 let (curren_vali, pending_vali) =
524 take_random_signers(
525 self.pending_validators.clone(),
526 validators_quantity as usize,
527 );
528 self.current_validators.clone_from(¤_vali);
529 self.pending_validators.clone_from(&pending_vali);
530
531 for signer in curren_vali.clone() {
532 if let Err(e) = self
533 .create_validators(ctx, signer.clone())
534 .await
535 {
536 error!(
537 msg_type = "Response",
538 error = %e,
539 signer = %signer,
540 "Failed to create validator from pending pool"
541 );
542 }
543 }
544
545 debug!(
546 msg_type = "Response",
547 new_validators = curren_vali.len(),
548 "Created additional validators from pending pool"
549 );
550 } else if self.current_validators.is_empty()
551 && let Err(e) = send_reboot_to_req(
552 ctx,
553 self.request_id.clone(),
554 self.request
555 .content().get_governance_id().expect("The build process verified that the event request is valid"),
556 RebootType::TimeOut
557 )
558 .await
559 {
560 error!(
561 msg_type = "Response",
562 error = %e,
563 "Failed to send reboot to request actor"
564 );
565 return Err(emit_fail(ctx, e).await);
566 } else if self.current_validators.is_empty() {
567 Self::observe_event("reboot");
568 }
569 } else {
570 warn!(
571 msg_type = "Response",
572 sender = %sender,
573 "Response from unexpected sender"
574 );
575 }
576 }
577 }
578 };
579 Ok(())
580 }
581
582 async fn on_child_fault(
583 &mut self,
584 error: ActorError,
585 ctx: &mut ActorContext<Self>,
586 ) -> ChildAction {
587 Self::observe_event("error");
588 error!(
589 request_id = %self.request_id,
590 version = self.version,
591 error = %error,
592 "Child fault in validation actor"
593 );
594 emit_fail(ctx, error).await;
595 ChildAction::Stop
596 }
597}
598
599#[cfg(test)]
600pub mod tests {
601 use core::panic;
602 use std::{sync::Arc, time::Duration};
603 use tempfile::TempDir;
604 use test_log::test;
605
606 use ave_actors::{ActorPath, ActorRef, PersistentActor, SystemRef};
607 use ave_common::{
608 Namespace, SchemaType,
609 identity::{
610 DigestIdentifier, HashAlgorithm, KeyPair, keys::Ed25519Signer,
611 },
612 request::{CreateRequest, EOLRequest},
613 response::RequestEventDB,
614 };
615 use tokio::sync::mpsc;
616
617 use crate::{
618 EventRequest, Node, NodeMessage, NodeResponse, Signed,
619 evaluation::tests::wait_request,
620 governance::{
621 Governance, GovernanceMessage, GovernanceResponse,
622 data::GovernanceData,
623 },
624 helpers::{
625 db::{ExternalDB, ReadStore},
626 network::service::NetworkSender,
627 },
628 model::common::node::SignTypesNode,
629 node::InitParamsNode,
630 request::{
631 RequestHandler, RequestHandlerMessage, RequestHandlerResponse,
632 tracking::RequestTracking,
633 },
634 system::tests::create_system,
635 };
636
637 async fn get_subject_state(
638 db: &Arc<ExternalDB>,
639 subject_id: &DigestIdentifier,
640 expected_sn: u64,
641 ) -> ave_common::response::SubjectDB {
642 let started = tokio::time::Instant::now();
643 loop {
644 match db.get_subject_state(&subject_id.to_string()).await {
645 Ok(state) if state.sn >= expected_sn => return state,
646 Ok(_) | Err(_)
647 if started.elapsed() < Duration::from_secs(5) =>
648 {
649 tokio::time::sleep(Duration::from_millis(10)).await;
650 }
651 Ok(state) => {
652 panic!(
653 "subject state not updated in time for {}: expected sn >= {}, got {}",
654 subject_id, expected_sn, state.sn
655 );
656 }
657 Err(error) => {
658 panic!(
659 "subject state not available in time for {}: {}",
660 subject_id, error
661 );
662 }
663 }
664 }
665 }
666
667 async fn get_event_sn(
668 db: &Arc<ExternalDB>,
669 subject_id: &DigestIdentifier,
670 sn: u64,
671 ) -> ave_common::response::LedgerDB {
672 let started = tokio::time::Instant::now();
673 loop {
674 match db.get_event_sn(&subject_id.to_string(), sn).await {
675 Ok(event) => return event,
676 Err(_) if started.elapsed() < Duration::from_secs(5) => {
677 tokio::time::sleep(Duration::from_millis(10)).await;
678 }
679 Err(error) => {
680 panic!(
681 "event {} for {} not available in time: {}",
682 sn, subject_id, error
683 );
684 }
685 }
686 }
687 }
688
689 pub async fn create_gov() -> (
690 SystemRef,
691 ActorRef<Node>,
692 ActorRef<RequestHandler>,
693 Arc<ExternalDB>,
694 ActorRef<Governance>,
695 ActorRef<RequestTracking>,
696 DigestIdentifier,
697 Vec<TempDir>,
698 ) {
699 let node_keys = KeyPair::Ed25519(Ed25519Signer::generate().unwrap());
700 let (system, .., _dirs) = create_system().await;
701
702 let (command_sender, _command_receiver) = mpsc::channel(10);
703 let network = Arc::new(NetworkSender::new(command_sender));
704
705 system.add_helper("network", network.clone()).await;
706
707 let public_key = Arc::new(node_keys.public_key());
708 let node_actor = system
709 .create_root_actor(
710 "node",
711 Node::initial(InitParamsNode {
712 key_pair: node_keys.clone(),
713 public_key: public_key.clone(),
714 hash: HashAlgorithm::Blake3,
715 is_service: true,
716 only_clear_events: false,
717 ledger_batch_size: 100,
718 }),
719 )
720 .await
721 .unwrap();
722
723 let request_actor = system
724 .create_root_actor(
725 "request",
726 RequestHandler::initial((
727 public_key.clone(),
728 (HashAlgorithm::Blake3, network),
729 )),
730 )
731 .await
732 .unwrap();
733
734 let ext_db = system
735 .get_helper::<Arc<ExternalDB>>("ext_db")
736 .await
737 .unwrap();
738
739 let create_req = EventRequest::Create(CreateRequest {
740 name: Some("Name".to_string()),
741 description: Some("Description".to_string()),
742 governance_id: DigestIdentifier::default(),
743 schema_id: SchemaType::Governance,
744 namespace: Namespace::new(),
745 });
746
747 let response = node_actor
748 .ask(NodeMessage::SignRequest(Box::new(
749 SignTypesNode::EventRequest(create_req.clone()),
750 )))
751 .await
752 .unwrap();
753 let NodeResponse::SignRequest(signature) = response else {
754 panic!("Invalid Response")
755 };
756
757 let signed_event_req = Signed::from_parts(create_req, signature);
758
759 let RequestHandlerResponse::Ok(response) = request_actor
760 .ask(RequestHandlerMessage::NewRequest {
761 request: signed_event_req.clone(),
762 })
763 .await
764 .unwrap()
765 else {
766 panic!("Invalid response")
767 };
768
769 let owned_subj = response.subject_id;
770
771 let tracking = system
772 .get_actor::<RequestTracking>(&ActorPath::from(
773 "/user/request/tracking",
774 ))
775 .await
776 .unwrap();
777
778 wait_request(&tracking, response.request_id).await;
779
780 let subject_actor: ActorRef<Governance> = system
781 .get_actor(&ActorPath::from(format!(
782 "/user/node/subject_manager/{}",
783 owned_subj
784 )))
785 .await
786 .unwrap();
787
788 let GovernanceResponse::Metadata(metadata) = subject_actor
789 .ask(GovernanceMessage::GetMetadata)
790 .await
791 .unwrap()
792 else {
793 panic!("Invalid response")
794 };
795 let subject_data = get_subject_state(&ext_db, &owned_subj, 0).await;
796 let event = get_event_sn(&ext_db, &owned_subj, 0).await;
797
798 let RequestEventDB::Create {
799 name,
800 description,
801 schema_id,
802 namespace,
803 } = event.event
804 else {
805 panic!()
806 };
807
808 assert_eq!(metadata.name, name);
809 assert_eq!(metadata.name, subject_data.name);
810 assert_eq!(metadata.name.unwrap(), "Name");
811
812 assert_eq!(metadata.description, description);
813 assert_eq!(metadata.description, subject_data.description);
814 assert_eq!(metadata.description.unwrap(), "Description");
815
816 assert_eq!(metadata.subject_id.to_string(), event.subject_id);
817 assert_eq!(metadata.subject_id.to_string(), subject_data.subject_id);
818 assert_eq!(metadata.subject_id, owned_subj);
819
820 assert_eq!(
821 metadata.governance_id.to_string(),
822 subject_data.governance_id
823 );
824 assert_eq!(metadata.governance_id, owned_subj);
825
826 assert_eq!(
827 metadata.genesis_gov_version,
828 subject_data.genesis_gov_version
829 );
830 assert_eq!(metadata.genesis_gov_version, 0);
831
832 assert_eq!(metadata.schema_id.to_string(), schema_id);
833 assert_eq!(
834 metadata.schema_id.to_string(),
835 subject_data.schema_id.to_string()
836 );
837 assert_eq!(metadata.schema_id, SchemaType::Governance);
838
839 assert_eq!(metadata.namespace.to_string(), namespace);
840 assert_eq!(
841 metadata.namespace.to_string(),
842 subject_data.namespace.to_string()
843 );
844 assert_eq!(metadata.namespace, Namespace::new());
845
846 assert!(subject_data.new_owner.is_none());
847 assert!(metadata.new_owner.is_none());
848
849 assert_eq!(metadata.sn, event.sn);
850 assert_eq!(metadata.sn, subject_data.sn);
851 assert_eq!(metadata.sn, 0);
852
853 assert!(subject_data.active);
854 assert!(metadata.active);
855
856 assert_eq!(metadata.properties.0, subject_data.properties);
857 let gov = GovernanceData::try_from(metadata.properties).unwrap();
858 assert_eq!(gov.version, 0);
859
860 assert!(!gov.members.is_empty());
861 assert!(gov.roles_schema.is_empty());
862 assert!(gov.schemas.is_empty());
863 assert!(gov.policies_schema.is_empty());
864
865 (
866 system,
867 node_actor,
868 request_actor,
869 ext_db,
870 subject_actor,
871 tracking,
872 metadata.subject_id,
873 _dirs,
874 )
875 }
876
877 #[test(tokio::test)]
878 async fn test_create_gov() {
879 let _ = create_gov().await;
880 }
881
882 #[test(tokio::test)]
883 async fn test_eol_gov() {
884 let (
885 _system,
886 node_actor,
887 request_actor,
888 db,
889 subject_actor,
890 tracking,
891 subject_id,
892 _dirs,
893 ) = create_gov().await;
894
895 let eol_reques = EventRequest::EOL(EOLRequest {
896 subject_id: subject_id.clone(),
897 });
898
899 let response = node_actor
900 .ask(NodeMessage::SignRequest(Box::new(
901 SignTypesNode::EventRequest(eol_reques.clone()),
902 )))
903 .await
904 .unwrap();
905 let NodeResponse::SignRequest(signature) = response else {
906 panic!("Invalid Response")
907 };
908
909 let signed_event_req = Signed::from_parts(eol_reques, signature);
910
911 let RequestHandlerResponse::Ok(response) = request_actor
912 .ask(RequestHandlerMessage::NewRequest {
913 request: signed_event_req.clone(),
914 })
915 .await
916 .unwrap()
917 else {
918 panic!("Invalid response")
919 };
920
921 wait_request(&tracking, response.request_id).await;
922
923 let GovernanceResponse::Metadata(metadata) = subject_actor
924 .ask(GovernanceMessage::GetMetadata)
925 .await
926 .unwrap()
927 else {
928 panic!("Invalid response")
929 };
930
931 let subject_data = get_subject_state(&db, &subject_id, 1).await;
932 let event = get_event_sn(&db, &subject_id, 1).await;
933
934 let RequestEventDB::EOL = event.event else {
935 panic!()
936 };
937
938 assert_eq!(metadata.name, subject_data.name);
939 assert_eq!(metadata.name.unwrap(), "Name");
940
941 assert_eq!(metadata.description, subject_data.description);
942 assert_eq!(metadata.description.unwrap(), "Description");
943
944 assert_eq!(metadata.subject_id.to_string(), event.subject_id);
945 assert_eq!(metadata.subject_id.to_string(), subject_data.subject_id);
946 assert_eq!(metadata.subject_id, subject_id);
947
948 assert_eq!(
949 metadata.governance_id.to_string(),
950 subject_data.governance_id
951 );
952 assert_eq!(metadata.governance_id, subject_id);
953
954 assert_eq!(
955 metadata.genesis_gov_version,
956 subject_data.genesis_gov_version
957 );
958 assert_eq!(metadata.genesis_gov_version, 0);
959
960 assert_eq!(
961 metadata.schema_id.to_string(),
962 subject_data.schema_id.to_string()
963 );
964 assert_eq!(metadata.schema_id, SchemaType::Governance);
965
966 assert_eq!(
967 metadata.namespace.to_string(),
968 subject_data.namespace.to_string()
969 );
970 assert_eq!(metadata.namespace, Namespace::new());
971
972 assert!(subject_data.new_owner.is_none());
973 assert!(metadata.new_owner.is_none());
974
975 assert_eq!(metadata.sn, event.sn);
976 assert_eq!(metadata.sn, subject_data.sn);
977 assert_eq!(metadata.sn, 1);
978
979 assert!(!subject_data.active);
980 assert!(!metadata.active);
981
982 assert_eq!(metadata.properties.0, subject_data.properties);
983 let gov = GovernanceData::try_from(metadata.properties).unwrap();
984 assert_eq!(gov.version, 1);
985
986 assert!(!gov.members.is_empty());
987 assert!(gov.roles_schema.is_empty());
988 assert!(gov.schemas.is_empty());
989 assert!(gov.policies_schema.is_empty());
990
991 if !request_actor
992 .ask(RequestHandlerMessage::NewRequest {
993 request: signed_event_req.clone(),
994 })
995 .await
996 .is_err()
997 {
998 panic!("Invalid response")
999 }
1000 }
1001}