aven_protocol/
artifact.rs1pub mod catalog;
5pub mod codec;
6pub mod staging;
7
8use crate::context::LocalSharedStatePackageContext;
9use catalog::{Artifact, Declaration};
10use codec::*;
11
12#[derive(Clone, Copy, Debug, PartialEq, Eq)]
14pub enum Error {
15 Invalid,
16 ResourceLimit,
17 Authentication,
18 Unsupported,
19}
20impl std::fmt::Display for Error {
21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22 f.write_str(match self {
23 Self::Invalid => "invalid bootstrap representation",
24 Self::ResourceLimit => "bootstrap codec resource limit exceeded",
25 Self::Authentication => "bootstrap authentication failed",
26 Self::Unsupported => "unsupported bootstrap format version",
27 })
28 }
29}
30impl std::error::Error for Error {}
31pub type Result<T> = std::result::Result<T, Error>;
32
33#[derive(Clone, Debug, PartialEq, Eq)]
35pub struct EncryptedArtifact<'a> {
36 pub total_plaintext_bytes: u64,
37 pub aggregate_commitment: [u8; 32],
38 pub chunks: Vec<EncryptedChunk<'a>>,
39}
40
41#[derive(Clone, Debug, PartialEq, Eq)]
42pub struct EncryptedChunk<'a> {
43 pub record_commitment: [u8; 32],
44 pub record: std::borrow::Cow<'a, [u8]>,
45}
46
47impl EncryptedArtifact<'_> {
48 pub fn into_records(self) -> Vec<Vec<u8>> {
50 self.chunks
51 .into_iter()
52 .map(|chunk| chunk.record.into_owned())
53 .collect()
54 }
55}
56
57#[derive(Clone, PartialEq, Eq)]
58pub struct Descriptor {
59 pub vault: [u8; 32],
60 pub stream: [u8; 32],
61 pub generation: [u8; 32],
62 pub bootstrap: [u8; 32],
63 pub membership: [u8; 32],
65 pub prefix: u64,
66 pub catalogs: [Declaration; 3],
67 pub manifest: Artifact,
68}
69
70impl Descriptor {
71 pub fn context(&self) -> LocalSharedStatePackageContext {
72 LocalSharedStatePackageContext {
73 vault_id: self.vault,
74 generation_id: self.generation,
75 }
76 }
77 pub fn binding(&self) -> Vec<u8> {
78 let mut out = b"AVBP\0\x02\x01".to_vec();
79 for id in [
80 self.vault,
81 self.stream,
82 self.generation,
83 self.bootstrap,
84 self.membership,
85 ] {
86 out.extend_from_slice(&id);
87 }
88 u64_bytes(&mut out, self.prefix);
89 for (index, declaration) in self.catalogs.iter().enumerate() {
90 out.push(index as u8 + 1);
91 declaration.write(&mut out);
92 }
93 out
94 }
95 pub fn encode(&self) -> Result<Vec<u8>> {
96 let mut out = self.binding();
97 self.manifest.write(&mut out)?;
98 Ok(out)
99 }
100 pub fn decode(bytes: &[u8]) -> Result<Self> {
101 bound(number(bytes.len())?, MAX_DESCRIPTOR_BYTES as u64)?;
102 let mut r = Reader(bytes);
103 valid(r.take(4)? == b"AVBP")?;
104 if r.take(2)? != [0, 2] {
105 return Err(Error::Unsupported);
106 }
107 valid(r.byte()? == 1)?;
108 let vault = r.array()?;
109 let stream = r.array()?;
110 let generation = r.array()?;
111 let bootstrap = r.array()?;
112 let membership = r.array()?;
113 let prefix = r.u64()?;
114 valid(prefix < i64::MAX as u64)?;
115 bound(prefix, RECORD_LIMIT)?;
116 valid(r.byte()? == 1)?;
117 let data = Declaration::read(&mut r)?;
118 valid(r.byte()? == 2)?;
119 let ids = Declaration::read(&mut r)?;
120 valid(r.byte()? == 3)?;
121 let images = Declaration::read(&mut r)?;
122 let manifest = Artifact::read(&mut r, CHUNK, false)?;
123 r.end()?;
124 Ok(Self {
125 vault,
126 stream,
127 generation,
128 bootstrap,
129 membership,
130 prefix,
131 catalogs: [data, ids, images],
132 manifest,
133 })
134 }
135}
136
137pub fn state_catalog(state: &Artifact) -> Result<Vec<u8>> {
138 let mut row = vec![1];
139 state.write(&mut row)?;
140 stream(1, &[row])
141}
142
143pub fn decode_state_catalog(bytes: &[u8]) -> Result<Artifact> {
144 let records = read_stream(bytes, 1)?;
145 valid(records.len() == 1)?;
146 let mut r = Reader(records[0]);
147 valid(r.byte()? == 1)?;
148 let state = Artifact::read(&mut r, STATE_LIMIT, false)?;
149 r.end()?;
150 Ok(state)
151}
152
153#[cfg(test)]
154mod tests;