1use ossa_typeable::{TypeId, Typeable};
2use serde::{Deserialize, Serialize};
3use std::fmt::Debug;
4use tracing::warn;
5
6use crate::util::merkle_tree::MerkleTree;
7use crate::util::{generate_nonce, Hash};
8use crate::{protocol, util};
9
10pub(crate) const BLOCK_SIZE: u64 = 1 << 14;
41pub(crate) const MERKLE_REQUEST_LIMIT: u64 = 16;
43pub(crate) const BLOCK_REQUEST_LIMIT: u64 = 16;
45
46#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
48pub struct MetadataHeader<Hash> {
49 pub nonce: Nonce,
51
52 pub protocol_version: protocol::Version,
54
55 pub store_type: TypeId,
57
58 pub initial_state_size: u64,
60
61 pub merkle_root: Hash, }
69
70impl<H: Hash + Debug> MetadataHeader<H> {
73 pub fn generate<T: Typeable>(initial_state: &MetadataBody<H>) -> MetadataHeader<H> {
74 let nonce = generate_nonce();
75 let protocol_version = protocol::LATEST_VERSION;
76 let store_type = T::type_ident();
77 let initial_state_size = initial_state.initial_state.len() as u64;
78 let merkle_root = initial_state.merkle_root();
79 MetadataHeader {
80 nonce,
81 protocol_version,
82 store_type,
83 initial_state_size,
84 merkle_root,
85 }
86 }
87
88 pub fn store_id<StoreId>(&self) -> StoreId
91 where
92 H: Into<StoreId>,
93 {
94 let mut h = H::new();
95 H::update(&mut h, self.nonce);
96 H::update(&mut h, [self.protocol_version.as_byte()]);
97 H::update(&mut h, self.store_type);
98 H::update(&mut h, self.initial_state_size.to_be_bytes());
99 H::update(&mut h, self.merkle_root);
100 H::finalize(h).into()
101 }
102
103 pub fn validate_store_id<StoreId: Eq>(&self, store_id: StoreId) -> bool
105 where
106 H: Into<StoreId>,
107 {
108 warn!("TODO: Check other properties like upper bounds on constants, etc");
109 store_id == self.store_id()
110 }
111
112 pub fn block_count(&self) -> u64 {
113 self.initial_state_size.div_ceil(BLOCK_SIZE)
114 }
115}
116
117#[derive(Debug)] pub struct MetadataBody<Hash> {
120 initial_state: Vec<u8>,
123 merkle_tree: MerkleTree<Hash>,
124}
125
126impl<H: Hash + Debug> MetadataBody<H> {
127 pub(crate) fn new<T: Serialize>(initial_state: &T) -> MetadataBody<H> {
128 let initial_state = serde_cbor::to_vec(initial_state).expect("TODO");
129 let merkle_tree = MerkleTree::from_chunks(initial_state.chunks(BLOCK_SIZE as usize));
130 MetadataBody {
131 initial_state,
132 merkle_tree,
133 }
134 }
135
136 pub fn merkle_root(&self) -> H {
137 self.merkle_tree.merkle_root()
138 }
139
140 pub fn build(self) -> (MerkleTree<H>, Vec<u8>) {
141 (self.merkle_tree, self.initial_state)
142 }
143}
144
145pub type Nonce = [u8; 32];