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