holochain_integrity_types/
entry.rs

1//! An Entry is a unit of data in a Holochain Source Chain.
2//!
3//! This module contains all the necessary definitions for Entry, which broadly speaking
4//! refers to any data which will be written into the ContentAddressableStorage, or the EntityAttributeValueStorage.
5//! It defines serialization behaviour for entries. Here you can find the complete list of
6//! entry_types, and special entries, like deletion_entry and cap_entry.
7
8use crate::capability::CapClaim;
9use crate::capability::CapGrant;
10use crate::capability::ZomeCallCapGrant;
11use crate::countersigning::CounterSigningSessionData;
12use crate::AppEntryDef;
13use crate::EntryDefIndex;
14use crate::EntryType;
15use crate::ZomeIndex;
16use holo_hash::hash_type;
17use holo_hash::ActionHash;
18use holo_hash::AgentPubKey;
19use holo_hash::EntryHash;
20use holo_hash::HashableContent;
21use holo_hash::HashableContentBytes;
22use holochain_serialized_bytes::prelude::*;
23
24mod app_entry_bytes;
25mod error;
26pub use app_entry_bytes::*;
27pub use error::*;
28
29/// Entries larger than this number of bytes cannot be created
30pub const ENTRY_SIZE_LIMIT: usize = 4 * 1000 * 1000; // 4MB
31
32/// The data type written to the source chain when explicitly granting a capability.
33/// NB: this is not simply `CapGrant`, because the `CapGrant::ChainAuthor`
34/// grant is already implied by `Entry::Agent`, so that should not be committed
35/// to a chain. This is a type alias because if we add other capability types
36/// in the future, we may want to include them
37pub type CapGrantEntry = ZomeCallCapGrant;
38
39/// The data type written to the source chain to denote a capability claim
40pub type CapClaimEntry = CapClaim;
41
42/// An Entry paired with its EntryHash
43pub type EntryHashed = holo_hash::HoloHashed<Entry>;
44
45/// Helper trait for deserializing [`Entry`]s to the correct type.
46///
47/// This is implemented by the `hdk_entry_types` proc_macro.
48pub trait EntryTypesHelper: Sized {
49    /// The error associated with this conversion.
50    type Error;
51    /// Check if the [`ZomeIndex`] and [`EntryDefIndex`] matches one of the
52    /// `ZomeEntryTypesKey::from(Self::variant)` and if
53    /// it does deserialize the [`Entry`] into that type.
54    fn deserialize_from_type<Z, I>(
55        zome_index: Z,
56        entry_def_index: I,
57        entry: &Entry,
58    ) -> Result<Option<Self>, Self::Error>
59    where
60        Z: Into<ZomeIndex>,
61        I: Into<EntryDefIndex>;
62}
63
64impl EntryTypesHelper for () {
65    type Error = core::convert::Infallible;
66
67    fn deserialize_from_type<Z, I>(
68        _zome_index: Z,
69        _entry_def_index: I,
70        _entry: &Entry,
71    ) -> Result<Option<Self>, Self::Error>
72    where
73        Z: Into<ZomeIndex>,
74        I: Into<EntryDefIndex>,
75    {
76        Ok(Some(()))
77    }
78}
79
80impl From<EntryHashed> for Entry {
81    fn from(entry_hashed: EntryHashed) -> Self {
82        entry_hashed.into_content()
83    }
84}
85
86/// Structure holding the entry portion of a chain record.
87#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, SerializedBytes)]
88#[cfg_attr(
89    feature = "fuzzing",
90    derive(arbitrary::Arbitrary, proptest_derive::Arbitrary)
91)]
92#[serde(tag = "entry_type", content = "entry")]
93pub enum Entry {
94    /// The `Agent` system entry, the third entry of every source chain,
95    /// which grants authoring capability for this agent.
96    Agent(AgentPubKey),
97    /// The application entry data for entries that aren't system created entries
98    App(AppEntryBytes),
99    /// Application entry data for entries that need countersigning to move forward multiple chains together.
100    CounterSign(Box<CounterSigningSessionData>, AppEntryBytes),
101    /// The capability claim system entry which allows committing a granted permission
102    /// for later use
103    CapClaim(CapClaimEntry),
104    /// The capability grant system entry which allows granting of application defined
105    /// capabilities
106    CapGrant(CapGrantEntry),
107}
108
109impl Entry {
110    /// If this entry represents a capability grant, return a `CapGrant`.
111    pub fn as_cap_grant(&self) -> Option<CapGrant> {
112        match self {
113            Entry::Agent(key) => Some(CapGrant::ChainAuthor(key.clone())),
114            Entry::CapGrant(data) => Some(CapGrant::RemoteAgent(data.clone())),
115            _ => None,
116        }
117    }
118
119    /// If this entry represents a capability claim, return a `CapClaim`.
120    pub fn as_cap_claim(&self) -> Option<&CapClaim> {
121        match self {
122            Entry::CapClaim(claim) => Some(claim),
123            _ => None,
124        }
125    }
126
127    /// If this entry represents an App entry, return `AppEntryBytes`.
128    pub fn as_app_entry(&self) -> Option<&AppEntryBytes> {
129        match self {
130            Entry::App(bytes) => Some(bytes),
131            _ => None,
132        }
133    }
134
135    /// Create an Entry::App from SerializedBytes
136    pub fn app(sb: SerializedBytes) -> Result<Self, EntryError> {
137        Ok(Entry::App(AppEntryBytes::try_from(sb)?))
138    }
139
140    /// Create an Entry::App from SerializedBytes
141    pub fn app_fancy<SB: TryInto<SerializedBytes, Error = SerializedBytesError>>(
142        sb: SB,
143    ) -> Result<Self, EntryError> {
144        Ok(Entry::App(AppEntryBytes::try_from(sb.try_into()?)?))
145    }
146
147    /// Get an EntryType based on the type of this Entry.
148    /// If the entry type is Entry, and no entry def is specified, return None
149    pub fn entry_type(&self, entry_def: Option<AppEntryDef>) -> Option<EntryType> {
150        match (self, entry_def) {
151            (Entry::Agent(_), _) => Some(EntryType::AgentPubKey),
152            (Entry::CapClaim(_), _) => Some(EntryType::CapClaim),
153            (Entry::CapGrant(_), _) => Some(EntryType::CapGrant),
154            (Entry::App(_), Some(aed)) | (Entry::CounterSign(_, _), Some(aed)) => {
155                Some(EntryType::App(aed))
156            }
157            _ => None,
158        }
159    }
160}
161
162impl HashableContent for Entry {
163    type HashType = hash_type::Entry;
164
165    fn hash_type(&self) -> Self::HashType {
166        hash_type::Entry
167    }
168
169    fn hashable_content(&self) -> HashableContentBytes {
170        match self {
171            Entry::Agent(agent_pubkey) => {
172                // We must retype this AgentPubKey as an EntryHash so that the
173                // prefix bytes match the Entry prefix
174                HashableContentBytes::Prehashed39(
175                    EntryHash::from(agent_pubkey.clone()).into_inner(),
176                )
177            }
178            entry => HashableContentBytes::Content(
179                entry
180                    .try_into()
181                    .expect("Could not serialize HashableContent"),
182            ),
183        }
184    }
185}
186
187/// Zome input for must_get_valid_record.
188#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
189pub struct MustGetValidRecordInput(pub ActionHash);
190
191impl MustGetValidRecordInput {
192    /// Constructor.
193    pub fn new(action_hash: ActionHash) -> Self {
194        Self(action_hash)
195    }
196
197    /// Consumes self for inner.
198    pub fn into_inner(self) -> ActionHash {
199        self.0
200    }
201}
202
203/// Zome input for must_get_entry.
204#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
205pub struct MustGetEntryInput(pub EntryHash);
206
207impl MustGetEntryInput {
208    /// Constructor.
209    pub fn new(entry_hash: EntryHash) -> Self {
210        Self(entry_hash)
211    }
212
213    /// Consumes self for inner.
214    pub fn into_inner(self) -> EntryHash {
215        self.0
216    }
217}
218
219/// Zome input for must_get_action.
220#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
221pub struct MustGetActionInput(pub ActionHash);
222
223impl MustGetActionInput {
224    /// Constructor.
225    pub fn new(action_hash: ActionHash) -> Self {
226        Self(action_hash)
227    }
228
229    /// Consumes self for inner.
230    pub fn into_inner(self) -> ActionHash {
231        self.0
232    }
233}