aven_protocol/claim/membership/
evidence.rs1use super::*;
3use crate::base64_bytes;
4use serde::{Deserialize, Serialize};
5
6pub const MAX_EVIDENCE_JSON_BYTES: usize =
9 base64_bytes::encoded_len(MAX_CHAIN_BYTES) + 4 * (3 * MAX_TRANSITIONS + 3) + 16384;
10
11#[derive(Clone, Serialize, Deserialize)]
12#[serde(deny_unknown_fields)]
13pub struct EvidenceRecord {
14 #[serde(
15 serialize_with = "base64_bytes::serialize",
16 deserialize_with = "declaration_bytes"
17 )]
18 pub declaration: Vec<u8>,
19 #[serde(
20 serialize_with = "base64_bytes::serialize",
21 deserialize_with = "request_bytes"
22 )]
23 pub request: Vec<u8>,
24 #[serde(
25 serialize_with = "base64_bytes::serialize",
26 deserialize_with = "record_bytes"
27 )]
28 pub record: Vec<u8>,
29}
30#[derive(Clone, Serialize, Deserialize)]
31#[serde(deny_unknown_fields)]
32pub struct Evidence {
33 #[serde(
34 serialize_with = "base64_bytes::serialize",
35 deserialize_with = "genesis_bytes"
36 )]
37 pub genesis: Vec<u8>,
38 #[serde(
39 serialize_with = "base64_bytes::serialize",
40 deserialize_with = "publication_bytes"
41 )]
42 pub publication: Vec<u8>,
43 #[serde(
44 serialize_with = "base64_bytes::serialize",
45 deserialize_with = "descriptor_bytes"
46 )]
47 pub descriptor: Vec<u8>,
48 #[serde(deserialize_with = "records")]
49 pub transitions: Vec<EvidenceRecord>,
50}
51fn record_bytes<'de, D: serde::Deserializer<'de>>(d: D) -> std::result::Result<Vec<u8>, D::Error> {
52 base64_bytes::bounded::<D, MAX_RECORD_BYTES>(d)
53}
54fn declaration_bytes<'de, D: serde::Deserializer<'de>>(
55 d: D,
56) -> std::result::Result<Vec<u8>, D::Error> {
57 base64_bytes::bounded::<D, DECLARATION_BYTES>(d)
58}
59fn request_bytes<'de, D: serde::Deserializer<'de>>(d: D) -> std::result::Result<Vec<u8>, D::Error> {
60 base64_bytes::bounded::<D, REQUEST_BYTES>(d)
61}
62fn genesis_bytes<'de, D: serde::Deserializer<'de>>(d: D) -> std::result::Result<Vec<u8>, D::Error> {
63 base64_bytes::bounded::<D, GENESIS_BYTES>(d)
64}
65fn publication_bytes<'de, D: serde::Deserializer<'de>>(
66 d: D,
67) -> std::result::Result<Vec<u8>, D::Error> {
68 base64_bytes::bounded::<D, PUBLICATION_BYTES>(d)
69}
70fn descriptor_bytes<'de, D: serde::Deserializer<'de>>(
71 d: D,
72) -> std::result::Result<Vec<u8>, D::Error> {
73 base64_bytes::bounded::<D, { crate::artifact::codec::MAX_DESCRIPTOR_BYTES }>(d)
74}
75fn records<'de, D: serde::Deserializer<'de>>(
76 d: D,
77) -> std::result::Result<Vec<EvidenceRecord>, D::Error> {
78 struct Records;
79 impl<'de> serde::de::Visitor<'de> for Records {
80 type Value = Vec<EvidenceRecord>;
81 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 f.write_str("bounded transition evidence")
83 }
84 fn visit_seq<A: serde::de::SeqAccess<'de>>(
85 self,
86 mut seq: A,
87 ) -> std::result::Result<Self::Value, A::Error> {
88 if seq.size_hint().is_some_and(|n| n > MAX_TRANSITIONS) {
89 return Err(serde::de::Error::custom("membership-limit"));
90 }
91 let mut result = Vec::new();
92 let mut total = 0usize;
93 while let Some(record) = seq.next_element::<EvidenceRecord>()? {
94 total += record.declaration.len() + record.request.len() + record.record.len();
95 if result.len() == MAX_TRANSITIONS || total > MAX_CHAIN_BYTES {
96 return Err(serde::de::Error::custom("membership-limit"));
97 }
98 result.push(record);
99 }
100 Ok(result)
101 }
102 }
103 d.deserialize_seq(Records)
104}
105impl Evidence {
106 pub fn enrollment(
109 &self,
110 peer: &Joiner,
111 outcome: Hash,
112 ) -> Result<(VerifiedEnrollment, Membership)> {
113 let mut enrollment = None;
114 let current = self.replay(|before, a| {
115 if enrollment.is_none() && hash(&a.record) == outcome {
116 enrollment = Some(peer.verify_enrollment(before, &a.declaration, &a.record)?);
117 }
118 Ok(())
119 })?;
120 let verified = enrollment.context("error enrollment-outcome-missing")?;
121 ensure!(
122 current.extends(verified.membership()),
123 "error membership-fork"
124 );
125 Ok((verified, current))
126 }
127 pub fn decode(bytes: &[u8]) -> Result<(Self, Membership)> {
129 let evidence = Self::decode_unverified(bytes)?;
130 let membership = evidence.verify()?;
131 Ok((evidence, membership))
132 }
133 pub fn decode_unverified(bytes: &[u8]) -> Result<Self> {
135 ensure!(
136 bytes.len() <= MAX_EVIDENCE_JSON_BYTES,
137 "error membership-limit"
138 );
139 serde_json::from_slice(bytes).map_err(|_| anyhow::anyhow!("error membership-evidence"))
140 }
141 pub fn verify(&self) -> Result<Membership> {
142 self.replay(|_, _| Ok(()))
143 }
144 fn replay(
147 &self,
148 mut visit: impl FnMut(&Membership, &EvidenceRecord) -> Result<()>,
149 ) -> Result<Membership> {
150 ensure!(
151 self.transitions.len() <= MAX_TRANSITIONS,
152 "error membership-limit"
153 );
154 let mut size = self
155 .genesis
156 .len()
157 .checked_add(self.publication.len())
158 .and_then(|n| n.checked_add(self.descriptor.len()))
159 .context("error membership-limit")?;
160 for a in &self.transitions {
161 ensure!(
162 (a.declaration.len() == DECLARATION_BYTES && a.request.len() == REQUEST_BYTES
163 || a.declaration.is_empty() && a.request.is_empty())
164 && a.record.len() <= MAX_RECORD_BYTES,
165 "error membership-limit"
166 );
167 size = size
168 .checked_add(a.declaration.len())
169 .and_then(|n| n.checked_add(a.request.len()))
170 .and_then(|n| n.checked_add(a.record.len()))
171 .context("error membership-limit")?;
172 }
173 ensure!(size <= MAX_CHAIN_BYTES, "error membership-limit");
174 let genesis = Genesis::from_record(&self.genesis)?;
175 let mut m = Membership::from_publication(&genesis, &self.descriptor, &self.publication)?;
176 for a in &self.transitions {
177 visit(&m, a)?;
178 m = m.append(&a.declaration, &a.request, &a.record)?;
179 }
180 Ok(m)
181 }
182}
183#[derive(Clone, Serialize, Deserialize)]
184#[serde(deny_unknown_fields)]
185pub struct Mailbox {
186 #[serde(
187 serialize_with = "base64_bytes::serialize",
188 deserialize_with = "declaration_bytes"
189 )]
190 pub declaration: Vec<u8>,
191 #[serde(with = "base64_bytes::option")]
192 pub request: Option<Vec<u8>>,
193 #[serde(with = "base64_bytes::option")]
194 pub admission: Option<Vec<u8>>,
195}