1use core::convert::TryFrom;
2use core::fmt::Debug;
3
4use bitcoin::{
5 consensus::encode::{self, VarInt},
6 hashes::{sha256, Hash, HashEngine},
7};
8
9use super::{apdu::ClientCommandCode, merkle::MerkleTree};
10
11pub struct DelegatedStore {
23 yielded: Vec<Vec<u8>>,
24 queue: Vec<Vec<u8>>,
25 known_preimages: Vec<([u8; 32], Vec<u8>)>,
26 trees: Vec<MerkleTree>,
27}
28
29impl DelegatedStore {
30 pub fn new() -> Self {
31 Self {
32 yielded: Vec::new(),
33 queue: Vec::new(),
34 known_preimages: Vec::new(),
35 trees: Vec::new(),
36 }
37 }
38
39 pub fn add_known_preimage(&mut self, element: Vec<u8>) {
43 let mut engine = sha256::Hash::engine();
44 engine.input(&element);
45 let hash = sha256::Hash::from_engine(engine).to_byte_array();
46 self.known_preimages.push((hash, element));
47 }
48
49 pub fn add_known_list(&mut self, elements: &[impl AsRef<[u8]>]) -> [u8; 32] {
58 let mut leaves = Vec::with_capacity(elements.len());
59 for element in elements {
60 let mut preimage = vec![0x00];
61 preimage.extend_from_slice(element.as_ref());
62 let mut engine = sha256::Hash::engine();
63 engine.input(&preimage);
64 let hash = sha256::Hash::from_engine(engine).to_byte_array();
65 self.known_preimages.push((hash, preimage));
66 leaves.push(hash);
67 }
68 let tree = MerkleTree::new(leaves);
69 let root_hash = *tree.root_hash();
70 self.trees.push(tree);
71 root_hash
72 }
73
74 pub fn add_known_mapping(&mut self, mapping: &[(Vec<u8>, Vec<u8>)]) {
79 let mut sorted: Vec<&(Vec<u8>, Vec<u8>)> = mapping.iter().collect();
80 sorted.sort_by(|(k1, _), (k2, _)| k1.as_slice().cmp(k2));
81
82 let mut keys = Vec::with_capacity(sorted.len());
83 let mut values = Vec::with_capacity(sorted.len());
84 for (key, value) in sorted {
85 keys.push(key.as_slice());
86 values.push(value.as_slice());
87 }
88 self.add_known_list(&keys);
89 self.add_known_list(&values);
90 }
91
92 pub fn execute(&mut self, command: Vec<u8>) -> Result<Vec<u8>, StoreError> {
95 if command.is_empty() {
96 return Err(StoreError::EmptyInput);
97 }
98 match ClientCommandCode::try_from(command[0]) {
99 Ok(ClientCommandCode::Yield) => {
100 self.yielded.push(command[1..].to_vec());
101 Ok(Vec::new())
102 }
103 Ok(ClientCommandCode::GetPreimage) => {
104 get_preimage_command(&mut self.queue, &self.known_preimages, &command[1..])
105 }
106 Ok(ClientCommandCode::GetMerkleLeafProof) => {
107 get_merkle_leaf_proof(&mut self.queue, &self.trees, &command[1..])
108 }
109 Ok(ClientCommandCode::GetMerkleLeafIndex) => {
110 get_merkle_leaf_index(&self.trees, &command[1..])
111 }
112 Ok(ClientCommandCode::GetMoreElements) => get_more_elements(&mut self.queue),
113 Err(()) => Err(StoreError::UnknownCommand(command[0])),
114 }
115 }
116
117 pub fn yielded(self) -> Vec<Vec<u8>> {
119 self.yielded
120 }
121}
122
123fn get_preimage_command(
124 queue: &mut Vec<Vec<u8>>,
125 known_preimages: &[([u8; 32], Vec<u8>)],
126 request: &[u8],
127) -> Result<Vec<u8>, StoreError> {
128 if request.len() != 33 || request[0] != b'\0' {
129 return Err(StoreError::UnsupportedRequest(
130 ClientCommandCode::GetPreimage as u8,
131 ));
132 };
133
134 let (_, preimage) = known_preimages
135 .iter()
136 .find(|(hash, _)| hash == &request[1..])
137 .ok_or(StoreError::UnknownHash)?;
138
139 let preimage_len_out = encode::serialize(&VarInt(preimage.len() as u64));
140
141 let max_payload_size = 255 - preimage_len_out.len() - 1;
144
145 let payload_size = if preimage.len() > max_payload_size {
146 max_payload_size
147 } else {
148 preimage.len()
149 };
150
151 if payload_size < preimage.len() {
152 for byte in &preimage[payload_size..] {
153 queue.push(vec![*byte]);
154 }
155 }
156
157 let mut response = preimage_len_out;
158 response.extend_from_slice(&(payload_size as u8).to_be_bytes());
159 response.extend_from_slice(&preimage[..payload_size]);
160 Ok(response)
161}
162
163fn get_merkle_leaf_proof(
164 queue: &mut Vec<Vec<u8>>,
165 trees: &[MerkleTree],
166 request: &[u8],
167) -> Result<Vec<u8>, StoreError> {
168 if !queue.is_empty() {
169 return Err(StoreError::UnexpectedQueue);
170 } else if request.len() < 34 {
171 return Err(StoreError::UnsupportedRequest(
172 ClientCommandCode::GetMerkleLeafProof as u8,
173 ));
174 };
175
176 let root = &request[0..32];
177 let (tree_size, read): (VarInt, usize) = encode::deserialize_partial(&request[32..])
178 .map_err(|_| StoreError::UnsupportedRequest(ClientCommandCode::GetMerkleLeafProof as u8))?;
179
180 let leaf_index: VarInt = encode::deserialize(&request[32 + read..])
182 .map_err(|_| StoreError::UnsupportedRequest(ClientCommandCode::GetMerkleLeafProof as u8))?;
183
184 let tree = trees
185 .iter()
186 .find(|tree| tree.root_hash() == root)
187 .ok_or(StoreError::UnknownHash)?;
188
189 if leaf_index >= tree_size || tree_size.0 != tree.size() as u64 {
190 return Err(StoreError::InvalidIndexOrSize);
191 }
192
193 let proof = tree
194 .get_leaf_proof(leaf_index.0 as usize)
195 .ok_or(StoreError::InvalidIndexOrSize)?;
196
197 let len_proof = proof.len();
198 let mut first_part_proof = Vec::new();
199 let mut n_response_elements = 0;
200 for (i, p) in proof.into_iter().enumerate() {
201 if i < 6 {
204 first_part_proof.extend(p);
205 n_response_elements += 1;
206 } else {
207 queue.push(p);
209 }
210 }
211
212 let mut response = tree.get_leaf(leaf_index.0 as usize).unwrap().to_vec();
213 response.extend_from_slice(&(len_proof as u8).to_be_bytes());
214 response.extend_from_slice(&(n_response_elements as u8).to_be_bytes());
215 response.extend_from_slice(&first_part_proof);
216 Ok(response)
217}
218
219fn get_merkle_leaf_index(trees: &[MerkleTree], request: &[u8]) -> Result<Vec<u8>, StoreError> {
220 if request.len() < 64 {
221 return Err(StoreError::UnsupportedRequest(
222 ClientCommandCode::GetMerkleLeafIndex as u8,
223 ));
224 }
225 let root = &request[0..32];
226 let hash = &request[32..64];
227
228 let tree = trees
229 .iter()
230 .find(|tree| tree.root_hash() == root)
231 .ok_or(StoreError::UnknownHash)?;
232
233 let leaf_index = tree.get_leaf_index(hash).ok_or(StoreError::UnknownHash)?;
234
235 let mut response = 1_u8.to_be_bytes().to_vec();
236 response.extend(encode::serialize(&VarInt(leaf_index as u64)));
237 Ok(response)
238}
239
240fn get_more_elements(queue: &mut Vec<Vec<u8>>) -> Result<Vec<u8>, StoreError> {
241 if queue.is_empty() {
242 return Err(StoreError::UnexpectedQueue);
243 }
244
245 let element_length = queue[0].len();
247 if queue.iter().any(|e| e.len() != element_length) {
248 return Err(StoreError::UnexpectedQueue);
249 }
250
251 let mut response_elements = Vec::new();
252 let mut n_added_elements = 0;
253 for element in queue.iter() {
254 if response_elements.len() + element_length <= 253 {
255 response_elements.extend_from_slice(element);
256 n_added_elements += 1;
257 }
258 }
259 *queue = queue[n_added_elements..].to_vec();
260
261 let mut response = (n_added_elements as u8).to_be_bytes().to_vec();
262 response.extend((element_length as u8).to_be_bytes());
263 response.extend(response_elements);
264 Ok(response)
265}
266
267pub fn get_merkleized_map_commitment(mapping: &[(Vec<u8>, Vec<u8>)]) -> Vec<u8> {
272 let mut sorted: Vec<&(Vec<u8>, Vec<u8>)> = mapping.iter().collect();
273 sorted.sort_by(|(k1, _), (k2, _)| k1.as_slice().cmp(k2));
274
275 let mut keys_hashes: Vec<[u8; 32]> = Vec::with_capacity(sorted.len());
276 let mut values_hashes: Vec<[u8; 32]> = Vec::with_capacity(sorted.len());
277 for (key, value) in &sorted {
278 let mut preimage = vec![0x00];
279 preimage.extend_from_slice(key);
280 let mut engine = sha256::Hash::engine();
281 engine.input(&preimage);
282 keys_hashes.push(sha256::Hash::from_engine(engine).to_byte_array());
283
284 let mut preimage = vec![0x00];
285 preimage.extend_from_slice(value);
286 let mut engine = sha256::Hash::engine();
287 engine.input(&preimage);
288 values_hashes.push(sha256::Hash::from_engine(engine).to_byte_array());
289 }
290
291 let mut commitment = encode::serialize(&VarInt(sorted.len() as u64));
292 commitment.extend(MerkleTree::new(keys_hashes).root_hash());
293 commitment.extend(MerkleTree::new(values_hashes).root_hash());
294 commitment
295}
296
297#[derive(Debug)]
298pub enum StoreError {
299 EmptyInput,
300 UnknownCommand(u8),
301 UnsupportedRequest(u8),
302 InvalidIndexOrSize,
303 UnknownHash,
304 UnknownMerkleRoot,
305 UnexpectedQueue,
306}