tycho_core/storage/block/
package_entry.rs

1use std::hash::Hash;
2
3use tycho_block_util::archive::ArchiveEntryType;
4use tycho_storage::kv::{StoredValue, StoredValueBuffer};
5use tycho_types::cell::HashBytes;
6use tycho_types::models::*;
7
8#[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
9pub struct PartialBlockId {
10    pub shard: ShardIdent,
11    pub seqno: u32,
12    pub root_hash: HashBytes,
13}
14
15impl PartialBlockId {
16    pub fn as_short_id(&self) -> BlockIdShort {
17        BlockIdShort {
18            shard: self.shard,
19            seqno: self.seqno,
20        }
21    }
22
23    pub fn make_full(&self, file_hash: HashBytes) -> BlockId {
24        BlockId {
25            shard: self.shard,
26            seqno: self.seqno,
27            root_hash: self.root_hash,
28            file_hash,
29        }
30    }
31}
32
33impl From<BlockId> for PartialBlockId {
34    fn from(value: BlockId) -> Self {
35        Self {
36            shard: value.shard,
37            seqno: value.seqno,
38            root_hash: value.root_hash,
39        }
40    }
41}
42
43impl From<&BlockId> for PartialBlockId {
44    fn from(value: &BlockId) -> Self {
45        Self {
46            shard: value.shard,
47            seqno: value.seqno,
48            root_hash: value.root_hash,
49        }
50    }
51}
52
53impl StoredValue for PartialBlockId {
54    const SIZE_HINT: usize = 4 + 8 + 4 + 32;
55
56    type OnStackSlice = [u8; Self::SIZE_HINT];
57
58    fn serialize<T: StoredValueBuffer>(&self, buffer: &mut T) {
59        let mut result = [0; Self::SIZE_HINT];
60        result[..4].copy_from_slice(&self.shard.workchain().to_be_bytes());
61        result[4..12].copy_from_slice(&self.shard.prefix().to_be_bytes());
62        result[12..16].copy_from_slice(&self.seqno.to_be_bytes());
63        result[16..48].copy_from_slice(self.root_hash.as_slice());
64
65        buffer.write_raw_slice(&result);
66    }
67
68    fn deserialize(reader: &mut &[u8]) -> Self
69    where
70        Self: Sized,
71    {
72        assert_eq!(reader.len(), Self::SIZE_HINT, "invalid partial id");
73
74        let workchain = i32::from_be_bytes(reader[..4].try_into().unwrap());
75        let prefix = u64::from_be_bytes(reader[4..12].try_into().unwrap());
76        let seqno = u32::from_be_bytes(reader[12..16].try_into().unwrap());
77        let root_hash = HashBytes::from_slice(&reader[16..48]);
78
79        *reader = &reader[Self::SIZE_HINT..];
80
81        Self {
82            shard: ShardIdent::new(workchain, prefix).expect("invalid shard ident"),
83            seqno,
84            root_hash,
85        }
86    }
87}
88
89/// Package entry id.
90#[derive(Debug, Hash, Eq, PartialEq)]
91pub struct PackageEntryKey {
92    pub block_id: PartialBlockId,
93    pub ty: ArchiveEntryType,
94}
95
96impl PackageEntryKey {
97    pub fn block(block_id: &BlockId) -> Self {
98        Self {
99            block_id: block_id.into(),
100            ty: ArchiveEntryType::Block,
101        }
102    }
103
104    pub fn proof(block_id: &BlockId) -> Self {
105        Self {
106            block_id: block_id.into(),
107            ty: ArchiveEntryType::Proof,
108        }
109    }
110
111    pub fn queue_diff(block_id: &BlockId) -> Self {
112        Self {
113            block_id: block_id.into(),
114            ty: ArchiveEntryType::QueueDiff,
115        }
116    }
117}
118
119impl From<(BlockId, ArchiveEntryType)> for PackageEntryKey {
120    fn from((block_id, ty): (BlockId, ArchiveEntryType)) -> Self {
121        Self {
122            block_id: block_id.into(),
123            ty,
124        }
125    }
126}
127
128impl StoredValue for PackageEntryKey {
129    const SIZE_HINT: usize = 4 + 8 + 4 + 32 + 1;
130
131    type OnStackSlice = [u8; Self::SIZE_HINT];
132
133    fn serialize<T: StoredValueBuffer>(&self, buffer: &mut T) {
134        let mut result = [0; Self::SIZE_HINT];
135        result[..4].copy_from_slice(&self.block_id.shard.workchain().to_be_bytes());
136        result[4..12].copy_from_slice(&self.block_id.shard.prefix().to_be_bytes());
137        result[12..16].copy_from_slice(&self.block_id.seqno.to_be_bytes());
138        result[16..48].copy_from_slice(self.block_id.root_hash.as_slice());
139        result[48] = self.ty as u8;
140        buffer.write_raw_slice(&result);
141    }
142
143    fn deserialize(reader: &mut &[u8]) -> Self
144    where
145        Self: Sized,
146    {
147        assert_eq!(reader.len(), Self::SIZE_HINT, "invalid package entry");
148
149        let workchain = i32::from_be_bytes(reader[..4].try_into().unwrap());
150        let prefix = u64::from_be_bytes(reader[4..12].try_into().unwrap());
151        let seqno = u32::from_be_bytes(reader[12..16].try_into().unwrap());
152        let root_hash = HashBytes::from_slice(&reader[16..48]);
153        let ty = ArchiveEntryType::from_byte(reader[48]).expect("invalid entry type");
154
155        *reader = &reader[Self::SIZE_HINT..];
156
157        Self {
158            block_id: PartialBlockId {
159                shard: ShardIdent::new(workchain, prefix).expect("invalid shard ident"),
160                seqno,
161                root_hash,
162            },
163            ty,
164        }
165    }
166}
167
168/// Block data entry id.
169#[derive(Debug, Hash, Eq, PartialEq)]
170pub struct BlockDataEntryKey {
171    pub block_id: PartialBlockId,
172    pub chunk_index: u32,
173}
174
175impl StoredValue for BlockDataEntryKey {
176    const SIZE_HINT: usize = 4 + 8 + 4 + 32 + 4;
177
178    type OnStackSlice = [u8; Self::SIZE_HINT];
179
180    fn serialize<T: StoredValueBuffer>(&self, buffer: &mut T) {
181        let mut result = [0; Self::SIZE_HINT];
182        result[..4].copy_from_slice(&self.block_id.shard.workchain().to_be_bytes());
183        result[4..12].copy_from_slice(&self.block_id.shard.prefix().to_be_bytes());
184        result[12..16].copy_from_slice(&self.block_id.seqno.to_be_bytes());
185        result[16..48].copy_from_slice(self.block_id.root_hash.as_slice());
186        result[48..52].copy_from_slice(&self.chunk_index.to_be_bytes());
187        buffer.write_raw_slice(&result);
188    }
189
190    fn deserialize(reader: &mut &[u8]) -> Self
191    where
192        Self: Sized,
193    {
194        assert_eq!(reader.len(), Self::SIZE_HINT, "invalid block data entry");
195
196        let workchain = i32::from_be_bytes(reader[..4].try_into().unwrap());
197        let prefix = u64::from_be_bytes(reader[4..12].try_into().unwrap());
198        let seqno = u32::from_be_bytes(reader[12..16].try_into().unwrap());
199        let root_hash = HashBytes::from_slice(&reader[16..48]);
200        let chunk_index = u32::from_be_bytes(reader[48..52].try_into().unwrap());
201
202        *reader = &reader[Self::SIZE_HINT..];
203
204        Self {
205            block_id: PartialBlockId {
206                shard: ShardIdent::new(workchain, prefix).expect("invalid shard ident"),
207                seqno,
208                root_hash,
209            },
210            chunk_index,
211        }
212    }
213}