tycho_core/storage/block/
package_entry.rs1use 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#[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#[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}