coven_protocol/membership/
head_predecessor.rs1use super::{AuthorHead, MembershipHeadActivation, MembershipHeadRef};
2use crate::objects::ExactObjectRef;
3use crate::store_commit::StoreProtocolError;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
9pub enum MembershipHeadPredecessor {
10 Direct {
11 head: MembershipHeadRef,
12 },
13 Accepted {
14 head: MembershipHeadRef,
15 acceptance: ExactObjectRef,
16 },
17}
18
19impl MembershipHeadPredecessor {
20 pub fn head(&self) -> &MembershipHeadRef {
21 match self {
22 Self::Direct { head } | Self::Accepted { head, .. } => head,
23 }
24 }
25
26 pub fn acceptance(&self) -> Option<&ExactObjectRef> {
27 match self {
28 Self::Direct { .. } => None,
29 Self::Accepted { acceptance, .. } => Some(acceptance),
30 }
31 }
32
33 pub fn verify_head(&self, head: &AuthorHead) -> Result<(), StoreProtocolError> {
34 self.head().object.verify(&head.to_bytes())?;
35 if self.head().coord != head.entry_coord() || self.head().head_hash != head.head_hash() {
36 return Err(StoreProtocolError::Malformed(
37 "membership predecessor differs from its exact head".into(),
38 ));
39 }
40 match (self, &head.activation) {
41 (Self::Direct { .. }, MembershipHeadActivation::Direct) => Ok(()),
42 (
43 Self::Accepted { acceptance, .. },
44 MembershipHeadActivation::StoreCommit {
45 acceptance_slot, ..
46 },
47 ) if acceptance.slot() == acceptance_slot => Ok(()),
48 _ => Err(StoreProtocolError::Malformed(
49 "membership predecessor omits or changes its exact acceptance result".into(),
50 )),
51 }
52 }
53}