Skip to main content

ossa_core/store/
v0.rs

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
10// pub struct Store<Id, T> {
11//     id: Id,
12//     state: T,
13//     metadata: Metadata<T>,
14// }
15//
16// impl<Id, T: Clone> Store<Id, T> {
17//     pub fn create_new(initial_state:T) -> Store<Id, T> {
18//         let meta = Metadata {
19//             initial_state: initial_state.clone(),
20//             nonce: crate::util::generate_nonce(),
21//             protocol_version: protocol::LATEST_VERSION,
22//         };
23//         let id = unimplemented!();
24//         Store {
25//             id,
26//             state: initial_state,
27//             metadata: meta,
28//         };
29//     }
30// }
31//
32// /// Metadata for a store.
33// pub struct Metadata<T> {
34//     protocol_version: protocol::Version,
35//     nonce: Nonce,
36//     initial_state: T,
37// }
38
39/// All block are 2^14 bytes (16KiB) (or less if last block).
40pub(crate) const BLOCK_SIZE: u64 = 1 << 14;
41/// Limit on the number of merkle nodes a peer can request.
42pub(crate) const MERKLE_REQUEST_LIMIT: u64 = 16;
43/// Limit on the number of blocks a peer can request.
44pub(crate) const BLOCK_REQUEST_LIMIT: u64 = 16;
45
46/// A store's Metadata header.
47#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
48pub struct MetadataHeader<Hash> {
49    /// A random nonce to distinguish the store.
50    pub nonce: Nonce,
51
52    /// The protocol version of this store.
53    pub protocol_version: protocol::Version,
54
55    /// Type of state that the store holds.
56    pub store_type: TypeId,
57
58    /// Size in bytes of the initial state.
59    pub initial_state_size: u64,
60
61    /// Hash (merkle root) of the hashes of the initial state's blocks.
62    pub merkle_root: Hash, // TODO: Make this an actual binary (or 512-ary) tree?
63                           //
64                           // TODO:
65                           // Owner?
66                           // Encryption options
67                           // Access control options?
68}
69
70// TODO: Signature of MetadataHeader by `owner`.
71
72impl<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    /// Compute the store id for the `MetadataHeader`.
89    /// This function must be updated any time `MetadataHeader` is updated.
90    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    /// Validate the metadata with respect to the store id.
104    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)] // , Deserialize, Serialize)]
118                 // TODO: Get rid of this? Or rename it? InitialStateBuilder?
119pub struct MetadataBody<Hash> {
120    /// Serialized (and encrypted) initial state of the store.
121    //  TODO: Eventually merkelize the initial state in chunks.
122    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
145// pub type StoreId = [u8; 32];
146// pub type TypeId = [u8; 32];
147// pub type Hash = [u8; 32];
148pub type Nonce = [u8; 32];