rock_n_rollup/plugins/
dac.rs1use crate::core::{Runtime, PREIMAGE_HASH_SIZE};
2
3pub struct PreimageHash {
4 inner: [u8; PREIMAGE_HASH_SIZE],
5}
6
7impl TryFrom<&str> for PreimageHash {
8 type Error = ();
9
10 fn try_from(value: &str) -> Result<Self, Self::Error> {
11 let decoded = hex::decode(value).map_err(|_| ())?;
12 let inner = decoded.try_into().map_err(|_| ())?;
13 Ok(Self { inner })
14 }
15}
16
17impl AsRef<[u8; PREIMAGE_HASH_SIZE]> for PreimageHash {
18 fn as_ref(&self) -> &[u8; PREIMAGE_HASH_SIZE] {
19 &self.inner
20 }
21}
22
23impl<'a> TryFrom<&'a [u8]> for PreimageHash {
24 type Error = ();
25
26 fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
27 let inner = value.try_into().map_err(|_| ())?;
28 Ok(Self { inner })
29 }
30}
31
32impl<'a> TryFrom<&'a Vec<u8>> for PreimageHash {
33 type Error = ();
34
35 fn try_from(value: &'a Vec<u8>) -> Result<Self, Self::Error> {
36 let inner = value.clone().try_into().map_err(|_| ())?;
37 Ok(Self { inner })
38 }
39}
40
41impl PreimageHash {
42 fn new(inner: [u8; PREIMAGE_HASH_SIZE]) -> Self {
43 Self { inner }
44 }
45}
46
47#[derive(Debug)]
49pub struct V0SliceContentPage<'a> {
50 inner: &'a [u8],
51}
52
53#[derive(Debug)]
55pub struct V0SliceHashPage<'a> {
56 inner: &'a [u8],
58}
59
60#[derive(Debug)]
64pub enum SlicePage<'a> {
65 V0ContentPage(V0SliceContentPage<'a>),
67 V0HashPage(V0SliceHashPage<'a>),
69}
70
71#[derive(Debug)]
73pub enum SlicePageError {
74 InvalidTag(Option<u8>),
76 InvalidSizePrefix,
78}
79
80pub const MAX_PAGE_SIZE: usize = 4096;
82
83pub(crate) const PAGE_TAG_SIZE: usize = 1;
85
86pub(crate) const PAGE_SIZE_PREFIX_SIZE: usize = 4;
88
89pub(crate) const MAX_USABLE_PAGE_SIZE: usize =
91 MAX_PAGE_SIZE - (PAGE_TAG_SIZE + PAGE_SIZE_PREFIX_SIZE);
92
93impl<'a> V0SliceContentPage<'a> {
94 pub const MAX_CONTENT_SIZE: usize = MAX_USABLE_PAGE_SIZE;
96
97 fn parse(slice: &'a [u8]) -> Result<Self, SlicePageError> {
99 if slice.len() < 4 {
100 return Err(SlicePageError::InvalidSizePrefix);
101 }
102
103 let size = u32::from_be_bytes([slice[0], slice[1], slice[2], slice[3]]) as usize;
104
105 let end_offset = 4 + size;
106
107 if slice.len() < end_offset {
108 return Err(SlicePageError::InvalidSizePrefix);
109 }
110
111 Ok(Self {
112 inner: &slice[4..end_offset],
113 })
114 }
115}
116
117impl<'a> V0SliceHashPage<'a> {
118 pub const MAX_HASHES_PER_PAGE: usize = MAX_USABLE_PAGE_SIZE / PREIMAGE_HASH_SIZE;
120
121 pub fn hashes(&self) -> impl Iterator<Item = &'a [u8; PREIMAGE_HASH_SIZE]> {
123 self.inner
127 .chunks_exact(PREIMAGE_HASH_SIZE)
128 .map(|chunk| chunk.try_into().expect("Guaranteed to be exact."))
129 }
130
131 fn parse(slice: &'a [u8]) -> Result<Self, SlicePageError> {
133 if slice.len() < 4 {
134 return Err(SlicePageError::InvalidSizePrefix);
135 }
136
137 let size = u32::from_be_bytes([slice[0], slice[1], slice[2], slice[3]]) as usize;
138
139 let end_offset = 4 + size; if slice.len() < end_offset || size % PREIMAGE_HASH_SIZE != 0 {
142 return Err(SlicePageError::InvalidSizePrefix);
143 }
144
145 Ok(Self {
146 inner: &slice[4..end_offset],
147 })
148 }
149}
150
151impl<'a> TryFrom<&'a [u8]> for SlicePage<'a> {
152 type Error = SlicePageError;
153
154 fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
155 match value {
156 [0, rest @ ..] => Ok(SlicePage::V0ContentPage(V0SliceContentPage::parse(rest)?)),
157 [1, rest @ ..] => Ok(SlicePage::V0HashPage(V0SliceHashPage::parse(rest)?)),
158 _ => Err(SlicePageError::InvalidTag(value.first().cloned())),
159 }
160 }
161}
162
163pub fn reveal_loop<Host: Runtime>(
169 host: &mut Host,
170 level: usize,
171 hash: &PreimageHash,
172 max_dac_levels: usize,
173 acc: &mut Vec<Vec<u8>>,
174) -> Result<(), ()> {
175 if level >= max_dac_levels {
176 return Err(());
177 }
178
179 let page = host.reveal_preimage(hash.as_ref())?;
180 let page = page.as_ref();
181
182 let page = SlicePage::try_from(page).map_err(|_| ())?;
183
184 match page {
185 SlicePage::V0HashPage(hashes) => {
186 for hash in hashes.hashes() {
187 let hash = PreimageHash::new(*hash); reveal_loop(host, level + 1, &hash, max_dac_levels, acc)?;
189 }
190 Ok(())
191 }
192 SlicePage::V0ContentPage(content) => {
193 let content = content.inner.to_vec();
194 acc.push(content);
195 Ok(())
196 }
197 }
198}
199
200pub trait Dac {
201 fn read_from_dac(&mut self, hash: &PreimageHash) -> Result<Vec<u8>, ()>;
203}
204
205impl<R> Dac for R
206where
207 R: Runtime,
208{
209 fn read_from_dac(&mut self, hash: &PreimageHash) -> Result<Vec<u8>, ()> {
210 let mut data = Vec::default();
211 reveal_loop(self, 0, hash, 3, &mut data)?;
212 let data = data.iter().flatten().copied().collect::<Vec<u8>>();
213 Ok(data)
214 }
215}