1use crate::entry_def::EntryVisibility;
2use crate::link::LinkTag;
3use crate::link::LinkType;
4use crate::EntryRateWeight;
5use crate::MembraneProof;
6use crate::RateWeight;
7use holo_hash::impl_hashable_content;
8use holo_hash::ActionHash;
9use holo_hash::AgentPubKey;
10use holo_hash::AnyLinkableHash;
11use holo_hash::DnaHash;
12use holo_hash::EntryHash;
13use holo_hash::HashableContent;
14use holo_hash::HoloHashed;
15use holochain_serialized_bytes::prelude::*;
16use holochain_timestamp::Timestamp;
17use std::borrow::Borrow;
18use std::fmt::{Display, Formatter};
19use std::hash::Hash;
20
21pub mod builder;
22pub mod conversions;
23
24pub const POST_GENESIS_SEQ_THRESHOLD: u32 = 3;
28
29#[allow(missing_docs)]
36#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, SerializedBytes, Hash)]
37#[serde(tag = "type")]
38pub enum Action {
39 Dna(Dna),
41 AgentValidationPkg(AgentValidationPkg),
42 InitZomesComplete(InitZomesComplete),
43 CreateLink(CreateLink),
44 DeleteLink(DeleteLink),
45 CloseChain(CloseChain),
46 OpenChain(OpenChain),
47 Create(Create),
48 Update(Update),
49 Delete(Delete),
50}
51
52impl Display for Action {
54 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
55 match self {
56 Action::Dna(dna) =>
57 write!(f, "dna={:?}", dna),
58
59 Action::AgentValidationPkg(avp) =>
60 write!(
61 f,
62 "agent_validation_pkg=[author={}, timestamp={:?}]",
63 avp.author, avp.timestamp
64 ),
65
66 Action::InitZomesComplete(izc) =>
67 write!(
68 f,
69 "init_zomes_complete=[author={}, timestamp={:?}]",
70 izc.author, izc.timestamp
71 ),
72 Action::CreateLink(link) => write!(f, "create_link=[author={}, timestamp={:?}, base_address={}, target_address={}, zome_index={}, link_type={:?}]", link.author, link.timestamp, link.base_address, link.target_address, link.zome_index, link.link_type),
73 Action::DeleteLink(link) => write!(f, "delete_link=[author={}, timestamp={:?}]", link.author, link.timestamp),
74 Action::OpenChain(oc) => write!(
75 f,
76 "open_chain=[author={}, timestamp={:?}]",
77 oc.author, oc.timestamp
78 ),
79 Action::CloseChain(cc) => write!(
80 f,
81 "close_chain=[author={}, timestamp={:?}]",
82 cc.author, cc.timestamp
83 ),
84 Action::Create(create) => write!(f, "create=[author={}, timestamp={:?}, entry_type={:?}, entry_hash={}]", create.author, create.timestamp, create.entry_type, create.entry_hash),
85 Action::Update(update) => write!(f, "create=[author={}, timestamp={:?}, original_action_address={}, original_entry_address={}, entry_type={:?}, entry_hash={}]", update.author, update.timestamp, update.original_action_address, update.original_entry_address, update.entry_type, update.entry_hash),
86 Action::Delete(delete) => write!(f, "create=[author={}, timestamp={:?}, deletes_address={}, deletes_entry_address={}]", delete.author, delete.timestamp, delete.deletes_address, delete.deletes_entry_address),
87 }
88 }
89}
90
91#[derive(Clone, Debug, Serialize, PartialEq, Eq, Hash)]
92#[serde(tag = "type")]
93pub(crate) enum ActionRef<'a> {
97 Dna(&'a Dna),
98 AgentValidationPkg(&'a AgentValidationPkg),
99 InitZomesComplete(&'a InitZomesComplete),
100 CreateLink(&'a CreateLink),
101 DeleteLink(&'a DeleteLink),
102 OpenChain(&'a OpenChain),
103 CloseChain(&'a CloseChain),
104 Create(&'a Create),
105 Update(&'a Update),
106 Delete(&'a Delete),
107}
108
109pub type ActionHashed = HoloHashed<Action>;
110
111impl ActionHashedContainer for ActionHashed {
112 fn action(&self) -> &Action {
113 self.as_content()
114 }
115
116 fn action_hash(&self) -> &ActionHash {
117 &self.hash
118 }
119}
120
121impl ActionSequenceAndHash for ActionHashed {
122 fn action_seq(&self) -> u32 {
123 self.content.action_seq()
124 }
125
126 fn address(&self) -> &ActionHash {
127 &self.hash
128 }
129}
130
131macro_rules! write_into_action {
133 ($($n:ident $(<$w : ty>)?),*,) => {
134
135 #[derive(serde::Serialize, serde::Deserialize, SerializedBytes, PartialEq, Eq, Clone, Debug)]
138 pub enum ActionType {
139 $($n,)*
140 }
141
142 impl std::fmt::Display for ActionType {
143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144 write!(
145 f,
146 "{}",
147 match self {
148 $( ActionType::$n => stringify!($n), )*
149 }
150 )
151 }
152 }
153
154 impl From<&Action> for ActionType {
155 fn from(action: &Action) -> ActionType {
156 match action {
157 $(
158 Action::$n(_) => ActionType::$n,
159 )*
160 }
161 }
162 }
163 };
164}
165
166pub trait ActionWeighed {
174 type Unweighed: ActionUnweighed;
175 type Weight: Default;
176
177 fn into_action(self) -> Action;
179
180 fn unweighed(self) -> Self::Unweighed;
185}
186
187pub trait ActionUnweighed: Sized {
195 type Weighed: ActionWeighed;
196 type Weight: Default;
197
198 fn weighed(self, weight: Self::Weight) -> Self::Weighed;
202
203 #[cfg(feature = "test_utils")]
205 fn weightless(self) -> Self::Weighed {
206 self.weighed(Default::default())
207 }
208}
209
210impl<I: ActionWeighed> From<I> for Action {
211 fn from(i: I) -> Self {
212 i.into_action()
213 }
214}
215
216write_into_action! {
217 Dna,
218 AgentValidationPkg,
219 InitZomesComplete,
220 OpenChain,
221 CloseChain,
222
223 Create<EntryRateWeight>,
224 Update<EntryRateWeight>,
225 Delete<RateWeight>,
226
227 CreateLink<RateWeight>,
228 DeleteLink,
229}
230
231macro_rules! match_action {
233 ($h:ident => |$i:ident| { $($t:tt)* }) => {
234 match $h {
235 Action::Dna($i) => { $($t)* }
236 Action::AgentValidationPkg($i) => { $($t)* }
237 Action::InitZomesComplete($i) => { $($t)* }
238 Action::CreateLink($i) => { $($t)* }
239 Action::DeleteLink($i) => { $($t)* }
240 Action::OpenChain($i) => { $($t)* }
241 Action::CloseChain($i) => { $($t)* }
242 Action::Create($i) => { $($t)* }
243 Action::Update($i) => { $($t)* }
244 Action::Delete($i) => { $($t)* }
245 }
246 };
247}
248
249impl Action {
250 pub fn entry_data(&self) -> Option<(&EntryHash, &EntryType)> {
254 match self {
255 Self::Create(Create {
256 entry_hash,
257 entry_type,
258 ..
259 }) => Some((entry_hash, entry_type)),
260 Self::Update(Update {
261 entry_hash,
262 entry_type,
263 ..
264 }) => Some((entry_hash, entry_type)),
265 _ => None,
266 }
267 }
268
269 pub fn into_entry_data(self) -> Option<(EntryHash, EntryType)> {
271 match self {
272 Self::Create(Create {
273 entry_hash,
274 entry_type,
275 ..
276 }) => Some((entry_hash, entry_type)),
277 Self::Update(Update {
278 entry_hash,
279 entry_type,
280 ..
281 }) => Some((entry_hash, entry_type)),
282 _ => None,
283 }
284 }
285
286 pub fn entry_visibility(&self) -> Option<&EntryVisibility> {
287 self.entry_data()
288 .map(|(_, entry_type)| entry_type.visibility())
289 }
290
291 pub fn entry_hash(&self) -> Option<&EntryHash> {
292 self.entry_data().map(|d| d.0)
293 }
294
295 pub fn entry_type(&self) -> Option<&EntryType> {
296 self.entry_data().map(|d| d.1)
297 }
298
299 pub fn action_type(&self) -> ActionType {
300 self.into()
301 }
302
303 pub fn author(&self) -> &AgentPubKey {
306 match_action!(self => |i| { &i.author })
307 }
308
309 pub fn signer(&self) -> &AgentPubKey {
312 match self {
313 Action::CloseChain(CloseChain {
320 new_target: Some(MigrationTarget::Agent(agent)),
321 ..
322 }) => agent,
323
324 _ => self.author(),
326 }
327 }
328
329 pub fn timestamp(&self) -> Timestamp {
331 match_action!(self => |i| { i.timestamp })
332 }
333
334 pub fn action_seq(&self) -> u32 {
336 match self {
337 Self::Dna(Dna { .. }) => 0,
339 Self::AgentValidationPkg(AgentValidationPkg { action_seq, .. })
340 | Self::InitZomesComplete(InitZomesComplete { action_seq, .. })
341 | Self::CreateLink(CreateLink { action_seq, .. })
342 | Self::DeleteLink(DeleteLink { action_seq, .. })
343 | Self::Delete(Delete { action_seq, .. })
344 | Self::CloseChain(CloseChain { action_seq, .. })
345 | Self::OpenChain(OpenChain { action_seq, .. })
346 | Self::Create(Create { action_seq, .. })
347 | Self::Update(Update { action_seq, .. }) => *action_seq,
348 }
349 }
350
351 pub fn prev_action(&self) -> Option<&ActionHash> {
353 Some(match self {
354 Self::Dna(Dna { .. }) => return None,
355 Self::AgentValidationPkg(AgentValidationPkg { prev_action, .. }) => prev_action,
356 Self::InitZomesComplete(InitZomesComplete { prev_action, .. }) => prev_action,
357 Self::CreateLink(CreateLink { prev_action, .. }) => prev_action,
358 Self::DeleteLink(DeleteLink { prev_action, .. }) => prev_action,
359 Self::Delete(Delete { prev_action, .. }) => prev_action,
360 Self::CloseChain(CloseChain { prev_action, .. }) => prev_action,
361 Self::OpenChain(OpenChain { prev_action, .. }) => prev_action,
362 Self::Create(Create { prev_action, .. }) => prev_action,
363 Self::Update(Update { prev_action, .. }) => prev_action,
364 })
365 }
366
367 pub fn prev_action_mut(&mut self) -> Option<&mut ActionHash> {
369 Some(match self {
370 Self::Dna(Dna { .. }) => return None,
371 Self::AgentValidationPkg(AgentValidationPkg { prev_action, .. }) => prev_action,
372 Self::InitZomesComplete(InitZomesComplete { prev_action, .. }) => prev_action,
373 Self::CreateLink(CreateLink { prev_action, .. }) => prev_action,
374 Self::DeleteLink(DeleteLink { prev_action, .. }) => prev_action,
375 Self::Delete(Delete { prev_action, .. }) => prev_action,
376 Self::CloseChain(CloseChain { prev_action, .. }) => prev_action,
377 Self::OpenChain(OpenChain { prev_action, .. }) => prev_action,
378 Self::Create(Create { prev_action, .. }) => prev_action,
379 Self::Update(Update { prev_action, .. }) => prev_action,
380 })
381 }
382
383 pub fn is_genesis(&self) -> bool {
384 self.action_seq() < POST_GENESIS_SEQ_THRESHOLD
385 }
386
387 pub fn rate_data(&self) -> RateWeight {
388 match self {
389 Self::CreateLink(CreateLink { weight, .. }) => weight.clone(),
390 Self::Delete(Delete { weight, .. }) => weight.clone(),
391 Self::Create(Create { weight, .. }) => weight.clone().into(),
392 Self::Update(Update { weight, .. }) => weight.clone().into(),
393
394 Self::Dna(Dna { .. })
396 | Self::AgentValidationPkg(AgentValidationPkg { .. })
397 | Self::InitZomesComplete(InitZomesComplete { .. })
398 | Self::DeleteLink(DeleteLink { .. })
399 | Self::CloseChain(CloseChain { .. })
400 | Self::OpenChain(OpenChain { .. }) => RateWeight::default(),
401 }
402 }
403
404 pub fn entry_rate_data(&self) -> Option<EntryRateWeight> {
405 match self {
406 Self::Create(Create { weight, .. }) => Some(weight.clone()),
407 Self::Update(Update { weight, .. }) => Some(weight.clone()),
408
409 Self::CreateLink(CreateLink { .. }) => None,
412 Self::Delete(Delete { .. }) => None,
413
414 Self::Dna(Dna { .. })
416 | Self::AgentValidationPkg(AgentValidationPkg { .. })
417 | Self::InitZomesComplete(InitZomesComplete { .. })
418 | Self::DeleteLink(DeleteLink { .. })
419 | Self::CloseChain(CloseChain { .. })
420 | Self::OpenChain(OpenChain { .. }) => Some(EntryRateWeight::default()),
421 }
422 }
423}
424
425impl_hashable_content!(Action, Action);
426
427macro_rules! impl_hashable_content_for_ref {
430 ($n: ident) => {
431 impl HashableContent for $n {
432 type HashType = holo_hash::hash_type::Action;
433
434 fn hash_type(&self) -> Self::HashType {
435 use holo_hash::PrimitiveHashType;
436 holo_hash::hash_type::Action::new()
437 }
438
439 fn hashable_content(&self) -> holo_hash::HashableContentBytes {
440 let h = ActionRef::$n(self);
441 let sb = SerializedBytes::from(UnsafeBytes::from(
442 holochain_serialized_bytes::encode(&h)
443 .expect("Could not serialize HashableContent"),
444 ));
445 holo_hash::HashableContentBytes::Content(sb)
446 }
447 }
448 };
449}
450
451impl_hashable_content_for_ref!(Dna);
452impl_hashable_content_for_ref!(AgentValidationPkg);
453impl_hashable_content_for_ref!(InitZomesComplete);
454impl_hashable_content_for_ref!(CreateLink);
455impl_hashable_content_for_ref!(DeleteLink);
456impl_hashable_content_for_ref!(CloseChain);
457impl_hashable_content_for_ref!(OpenChain);
458impl_hashable_content_for_ref!(Create);
459impl_hashable_content_for_ref!(Update);
460impl_hashable_content_for_ref!(Delete);
461
462#[derive(
466 Debug,
467 Copy,
468 Clone,
469 Hash,
470 PartialEq,
471 Eq,
472 PartialOrd,
473 Ord,
474 Serialize,
475 Deserialize,
476 SerializedBytes,
477)]
478pub struct ZomeIndex(pub u8);
479
480impl ZomeIndex {
481 pub fn new(u: u8) -> Self {
482 Self(u)
483 }
484}
485
486#[derive(
487 Debug,
488 Copy,
489 Clone,
490 Hash,
491 PartialEq,
492 Eq,
493 PartialOrd,
494 Ord,
495 Serialize,
496 Deserialize,
497 SerializedBytes,
498)]
499pub struct EntryDefIndex(pub u8);
500
501#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, SerializedBytes, Hash)]
503pub struct Dna {
504 pub author: AgentPubKey,
505 pub timestamp: Timestamp,
506 pub hash: DnaHash,
508}
509
510#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, SerializedBytes, Hash)]
513pub struct AgentValidationPkg {
514 pub author: AgentPubKey,
515 pub timestamp: Timestamp,
516 pub action_seq: u32,
517 pub prev_action: ActionHash,
518
519 pub membrane_proof: Option<MembraneProof>,
520}
521
522#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, SerializedBytes, Hash)]
525pub struct InitZomesComplete {
526 pub author: AgentPubKey,
527 pub timestamp: Timestamp,
528 pub action_seq: u32,
529 pub prev_action: ActionHash,
530}
531
532#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, SerializedBytes, Hash)]
535pub struct CreateLink<W = RateWeight> {
536 pub author: AgentPubKey,
537 pub timestamp: Timestamp,
538 pub action_seq: u32,
539 pub prev_action: ActionHash,
540
541 pub base_address: AnyLinkableHash,
542 pub target_address: AnyLinkableHash,
543 pub zome_index: ZomeIndex,
544 pub link_type: LinkType,
545 pub tag: LinkTag,
546
547 pub weight: W,
548}
549
550#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, SerializedBytes, Hash)]
552pub struct DeleteLink {
553 pub author: AgentPubKey,
554 pub timestamp: Timestamp,
555 pub action_seq: u32,
556 pub prev_action: ActionHash,
557
558 pub base_address: AnyLinkableHash,
562 pub link_add_address: ActionHash,
564}
565
566#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, SerializedBytes, Hash)]
574pub enum MigrationTarget {
575 Dna(DnaHash),
577 Agent(AgentPubKey),
579}
580
581impl From<DnaHash> for MigrationTarget {
582 fn from(dna: DnaHash) -> Self {
583 MigrationTarget::Dna(dna)
584 }
585}
586
587impl From<AgentPubKey> for MigrationTarget {
588 fn from(agent: AgentPubKey) -> Self {
589 MigrationTarget::Agent(agent)
590 }
591}
592
593#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, SerializedBytes, Hash)]
601pub struct CloseChain {
602 pub author: AgentPubKey,
603 pub timestamp: Timestamp,
604 pub action_seq: u32,
605 pub prev_action: ActionHash,
606
607 pub new_target: Option<MigrationTarget>,
608}
609
610#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, SerializedBytes, Hash)]
613pub struct OpenChain {
614 pub author: AgentPubKey,
615 pub timestamp: Timestamp,
616 pub action_seq: u32,
617 pub prev_action: ActionHash,
618
619 pub prev_target: MigrationTarget,
620 pub close_hash: ActionHash,
623}
624
625#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, SerializedBytes, Hash)]
628pub struct Create<W = EntryRateWeight> {
629 pub author: AgentPubKey,
630 pub timestamp: Timestamp,
631 pub action_seq: u32,
632 pub prev_action: ActionHash,
633
634 pub entry_type: EntryType,
635 pub entry_hash: EntryHash,
636
637 pub weight: W,
638}
639
640#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, SerializedBytes, Hash)]
655pub struct Update<W = EntryRateWeight> {
656 pub author: AgentPubKey,
657 pub timestamp: Timestamp,
658 pub action_seq: u32,
659 pub prev_action: ActionHash,
660
661 pub original_action_address: ActionHash,
662 pub original_entry_address: EntryHash,
663
664 pub entry_type: EntryType,
665 pub entry_hash: EntryHash,
666
667 pub weight: W,
668}
669
670#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, SerializedBytes, Hash)]
677pub struct Delete<W = RateWeight> {
678 pub author: AgentPubKey,
679 pub timestamp: Timestamp,
680 pub action_seq: u32,
681 pub prev_action: ActionHash,
682
683 pub deletes_address: ActionHash,
685 pub deletes_entry_address: EntryHash,
686
687 pub weight: W,
688}
689
690#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, SerializedBytes, Hash)]
693pub struct UpdateAction {
694 pub author: AgentPubKey,
695 pub timestamp: Timestamp,
696 pub action_seq: u32,
697 pub prev_action: ActionHash,
698
699 pub original_action_address: ActionHash,
700}
701
702#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, SerializedBytes, Hash)]
705pub struct DeleteAction {
706 pub author: AgentPubKey,
707 pub timestamp: Timestamp,
708 pub action_seq: u32,
709 pub prev_action: ActionHash,
710
711 pub deletes_address: ActionHash,
713}
714
715#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, SerializedBytes, Hash)]
719pub enum EntryType {
720 AgentPubKey,
722 App(AppEntryDef),
724 CapClaim,
726 CapGrant,
728}
729
730impl EntryType {
731 pub fn visibility(&self) -> &EntryVisibility {
732 match self {
733 EntryType::AgentPubKey => &EntryVisibility::Public,
734 EntryType::App(app_entry_def) => app_entry_def.visibility(),
735 EntryType::CapClaim => &EntryVisibility::Private,
736 EntryType::CapGrant => &EntryVisibility::Private,
737 }
738 }
739}
740
741impl std::fmt::Display for EntryType {
742 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
743 match self {
744 EntryType::AgentPubKey => write!(f, "AgentPubKey"),
745 EntryType::App(app_entry_def) => write!(
746 f,
747 "App({:?}, {:?})",
748 app_entry_def.entry_index(),
749 app_entry_def.visibility()
750 ),
751 EntryType::CapClaim => write!(f, "CapClaim"),
752 EntryType::CapGrant => write!(f, "CapGrant"),
753 }
754 }
755}
756
757#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, SerializedBytes, Hash)]
759pub struct AppEntryDef {
760 pub entry_index: EntryDefIndex,
763 pub zome_index: ZomeIndex,
765 pub visibility: EntryVisibility,
768}
769
770impl AppEntryDef {
771 pub fn new(
772 entry_index: EntryDefIndex,
773 zome_index: ZomeIndex,
774 visibility: EntryVisibility,
775 ) -> Self {
776 Self {
777 entry_index,
778 zome_index,
779 visibility,
780 }
781 }
782
783 pub fn entry_index(&self) -> EntryDefIndex {
784 self.entry_index
785 }
786 pub fn zome_index(&self) -> ZomeIndex {
787 self.zome_index
788 }
789 pub fn visibility(&self) -> &EntryVisibility {
790 &self.visibility
791 }
792}
793
794impl From<EntryDefIndex> for u8 {
795 fn from(ei: EntryDefIndex) -> Self {
796 ei.0
797 }
798}
799
800impl ZomeIndex {
801 pub fn index(&self) -> usize {
803 self.0 as usize
804 }
805}
806
807impl std::ops::Deref for ZomeIndex {
808 type Target = u8;
809
810 fn deref(&self) -> &Self::Target {
811 &self.0
812 }
813}
814
815impl Borrow<u8> for ZomeIndex {
816 fn borrow(&self) -> &u8 {
817 &self.0
818 }
819}
820
821pub trait ActionHashedContainer: ActionSequenceAndHash {
822 fn action(&self) -> &Action;
823
824 fn action_hash(&self) -> &ActionHash;
825}
826
827pub trait ActionSequenceAndHash {
828 fn action_seq(&self) -> u32;
829 fn address(&self) -> &ActionHash;
830}
831
832impl ActionSequenceAndHash for (u32, ActionHash) {
833 fn action_seq(&self) -> u32 {
834 self.0
835 }
836
837 fn address(&self) -> &ActionHash {
838 &self.1
839 }
840}