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