holochain_zome_types/warrant.rs
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
//! Types for warrants
use holo_hash::*;
use holochain_integrity_types::Signature;
pub use holochain_serialized_bytes::prelude::*;
use kitsune_p2p_timestamp::Timestamp;
use crate::signature::Signed;
/// A Warrant is an authored, timestamped proof of wrongdoing by another agent.
#[derive(
Clone,
Debug,
Serialize,
Deserialize,
SerializedBytes,
Eq,
PartialEq,
Hash,
derive_more::From,
derive_more::Deref,
)]
#[cfg_attr(
feature = "fuzzing",
derive(arbitrary::Arbitrary, proptest_derive::Arbitrary,)
)]
pub struct Warrant {
/// The self-proving part of the warrant containing evidence of bad behavior
#[deref]
pub proof: WarrantProof,
/// The author of the warrant
pub author: AgentPubKey,
/// Time when the warrant was issued
pub timestamp: Timestamp,
}
impl Warrant {
/// Constructor
pub fn new(proof: WarrantProof, author: AgentPubKey, timestamp: Timestamp) -> Self {
Self {
proof,
author,
timestamp,
}
}
/// Constructor with timestamp set to now()
#[cfg(feature = "full")]
pub fn new_now(proof: WarrantProof, author: AgentPubKey) -> Self {
Self {
proof,
author,
timestamp: Timestamp::now(),
}
}
}
impl HashableContent for Warrant {
type HashType = holo_hash::hash_type::Warrant;
fn hash_type(&self) -> Self::HashType {
Self::HashType::new()
}
fn hashable_content(&self) -> HashableContentBytes {
HashableContentBytes::Content(self.try_into().expect("Could not serialize Warrant"))
}
}
/// The self-proving part of a Warrant which demonstrates bad behavior by another agent
#[derive(
Clone, Debug, Serialize, Deserialize, SerializedBytes, Eq, PartialEq, Hash, derive_more::From,
)]
#[cfg_attr(
feature = "fuzzing",
derive(arbitrary::Arbitrary, proptest_derive::Arbitrary,)
)]
pub enum WarrantProof {
/// Signifies evidence of a breach of chain integrity
ChainIntegrity(ChainIntegrityWarrant),
}
/// Just the type of the warrant
#[derive(
Clone,
Copy,
Debug,
Serialize,
Deserialize,
SerializedBytes,
Eq,
PartialEq,
Hash,
derive_more::From,
)]
#[cfg_attr(
feature = "fuzzing",
derive(arbitrary::Arbitrary, proptest_derive::Arbitrary,)
)]
pub enum WarrantType {
// NOTE: the values here cannot overlap with ActionType,
// because they occupy the same field in the Action table.
//
/// Signifies evidence of a breach of chain integrity
ChainIntegrityWarrant,
}
impl From<Warrant> for WarrantType {
fn from(warrant: Warrant) -> Self {
warrant.get_type()
}
}
#[cfg(any(feature = "sqlite", feature = "sqlite-encrypted"))]
impl rusqlite::ToSql for WarrantType {
fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput> {
Ok(rusqlite::types::ToSqlOutput::Owned(
format!("{:?}", self).into(),
))
}
}
/// A warrant which is sent to AgentActivity authorities
#[derive(Clone, Debug, Serialize, Deserialize, SerializedBytes, Eq, PartialEq, Hash)]
#[cfg_attr(
feature = "fuzzing",
derive(arbitrary::Arbitrary, proptest_derive::Arbitrary)
)]
pub enum ChainIntegrityWarrant {
/// Something invalid was authored on a chain.
/// When we receive this warrant, we fetch the Action and validate it
/// under every applicable DhtOpType.
// TODO: include ChainOpType, which allows the receipient to only run
// validation for that op type. At the time of writing, this was
// non-trivial because ChainOpType is in a downstream crate.
InvalidChainOp {
/// The author of the action
action_author: AgentPubKey,
/// The hash of the action to fetch by
action: ActionHashAndSig,
/// Whether to run app or sys validation
validation_type: ValidationType,
},
/// Proof of chain fork.
ChainFork {
/// Author of the chain which is forked
chain_author: AgentPubKey,
/// Two actions of the same seq number which prove the fork
action_pair: (ActionHashAndSig, ActionHashAndSig),
},
}
/// Action hash with the signature of the action at that hash
pub type ActionHashAndSig = (ActionHash, Signature);
impl WarrantProof {
/// Basis hash where this warrant should be delivered.
/// Warrants always have the authoring agent as a basis, so that warrants
/// can be accumulated by the agent activity authorities.
pub fn dht_basis(&self) -> OpBasis {
self.action_author().clone().into()
}
/// The author of the action which led to this warrant, i.e. the target of the warrant
pub fn action_author(&self) -> &AgentPubKey {
match self {
Self::ChainIntegrity(w) => match w {
ChainIntegrityWarrant::InvalidChainOp { action_author, .. } => action_author,
ChainIntegrityWarrant::ChainFork { chain_author, .. } => chain_author,
},
}
}
/// Get the warrant type
pub fn get_type(&self) -> WarrantType {
match self {
Self::ChainIntegrity(_) => WarrantType::ChainIntegrityWarrant,
}
}
}
/// Not necessary but nice to have
#[derive(
Clone, Debug, Serialize, Deserialize, SerializedBytes, Eq, PartialEq, Hash, derive_more::Display,
)]
#[cfg_attr(
feature = "fuzzing",
derive(arbitrary::Arbitrary, proptest_derive::Arbitrary)
)]
pub enum ValidationType {
/// Sys validation
Sys,
/// App validation
App,
}
/// A signed warrant with timestamp
pub type SignedWarrant = Signed<Warrant>;