ab_core_primitives/transaction/
owned.rs1mod builder_buffer;
4
5use crate::transaction::owned::builder_buffer::BuilderBuffer;
6use crate::transaction::{Transaction, TransactionHeader, TransactionSlot};
7use ab_aligned_buffer::SharedAlignedBuffer;
8use ab_io_type::trivial_type::TrivialType;
9use core::slice;
10
11#[derive(Debug, Default, Copy, Clone, TrivialType)]
13#[repr(C)]
14pub struct OwnedTransactionLengths {
15 pub read_slots: u16,
17 pub write_slots: u16,
19 pub payload: u32,
21 pub seal: u32,
23 pub padding: [u8; 4],
25}
26
27#[derive(Debug, thiserror::Error)]
29pub enum OwnedTransactionError {
30 #[error("Not enough bytes")]
32 NotEnoughBytes,
33 #[error("Invalid padding")]
35 InvalidPadding,
36 #[error("Payload is not a multiple of `u128`")]
38 PayloadIsNotMultipleOfU128,
39 #[error("Expected number of bytes: {actual} != {expected}")]
41 UnexpectedNumberOfBytes {
42 actual: u32,
44 expected: u32,
46 },
47}
48
49#[derive(Debug, Clone)]
63pub struct OwnedTransaction {
64 buffer: SharedAlignedBuffer,
65}
66
67impl OwnedTransaction {
68 pub fn build(header: &TransactionHeader) -> OwnedTransactionBuilder {
70 OwnedTransactionBuilder {
71 buffer: BuilderBuffer::new(header),
72 }
73 }
74
75 pub fn from_buffer(buffer: SharedAlignedBuffer) -> Result<Self, OwnedTransactionError> {
77 if (buffer.len() as usize)
78 < size_of::<TransactionHeader>() + size_of::<OwnedTransactionLengths>()
79 {
80 return Err(OwnedTransactionError::NotEnoughBytes);
81 }
82
83 let lengths = unsafe {
85 buffer
86 .as_ptr()
87 .add(size_of::<TransactionHeader>())
88 .cast::<OwnedTransactionLengths>()
89 .read()
90 };
91 let OwnedTransactionLengths {
92 read_slots,
93 write_slots,
94 payload,
95 seal,
96 padding,
97 } = lengths;
98
99 if padding != [0; _] {
100 return Err(OwnedTransactionError::InvalidPadding);
101 }
102
103 if payload % u128::SIZE != 0 {
104 return Err(OwnedTransactionError::PayloadIsNotMultipleOfU128);
105 }
106
107 let expected = (size_of::<TransactionHeader>() as u32
108 + size_of::<OwnedTransactionLengths>() as u32)
109 .saturating_add(u32::from(read_slots))
110 .saturating_add(u32::from(write_slots))
111 .saturating_add(payload)
112 .saturating_add(seal);
113
114 if buffer.len() != expected {
115 return Err(OwnedTransactionError::UnexpectedNumberOfBytes {
116 actual: buffer.len(),
117 expected,
118 });
119 }
120
121 Ok(Self { buffer })
122 }
123
124 pub fn buffer(&self) -> &SharedAlignedBuffer {
131 &self.buffer
132 }
133
134 pub fn transaction(&self) -> Transaction<'_> {
136 let lengths = unsafe {
138 self.buffer
139 .as_ptr()
140 .add(size_of::<TransactionHeader>())
141 .cast::<OwnedTransactionLengths>()
142 .read()
143 };
144 let OwnedTransactionLengths {
145 read_slots,
146 write_slots,
147 payload,
148 seal,
149 padding: _,
150 } = lengths;
151
152 Transaction {
153 header: unsafe {
156 self.buffer
157 .as_ptr()
158 .cast::<TransactionHeader>()
159 .as_ref_unchecked()
160 },
161 read_slots: unsafe {
164 slice::from_raw_parts(
165 self.buffer
166 .as_ptr()
167 .add(size_of::<TransactionHeader>())
168 .add(size_of::<OwnedTransactionLengths>())
169 .cast::<TransactionSlot>(),
170 usize::from(read_slots),
171 )
172 },
173 write_slots: unsafe {
176 slice::from_raw_parts(
177 self.buffer
178 .as_ptr()
179 .add(size_of::<TransactionHeader>())
180 .add(size_of::<OwnedTransactionLengths>())
181 .cast::<TransactionSlot>()
182 .add(usize::from(read_slots)),
183 usize::from(write_slots),
184 )
185 },
186 payload: unsafe {
189 slice::from_raw_parts(
190 self.buffer
191 .as_ptr()
192 .add(size_of::<TransactionHeader>())
193 .add(size_of::<OwnedTransactionLengths>())
194 .add(
195 size_of::<TransactionSlot>()
196 * (usize::from(read_slots) + usize::from(write_slots)),
197 )
198 .cast::<u128>(),
199 payload as usize,
200 )
201 },
202 seal: unsafe {
205 slice::from_raw_parts(
206 self.buffer
207 .as_ptr()
208 .add(size_of::<TransactionHeader>())
209 .add(size_of::<OwnedTransactionLengths>())
210 .add(
211 size_of::<TransactionSlot>()
212 * (usize::from(read_slots) + usize::from(write_slots))
213 + payload as usize,
214 ),
215 seal as usize,
216 )
217 },
218 }
219 }
220}
221
222#[derive(Debug, thiserror::Error)]
224pub enum OwnedTransactionBuilderError {
225 #[error("Too many read slots")]
227 TooManyReadSlots,
228 #[error("Too many write slots")]
230 TooManyWriteSlots,
231 #[error("Payload too large")]
233 PayloadTooLarge,
234 #[error("Payload is not a multiple of `u128`")]
236 PayloadIsNotMultipleOfU128,
237 #[error("Seal too large")]
239 SealTooLarge,
240 #[error("Transaction too large")]
242 TransactionTooLarge,
243}
244
245#[derive(Debug, Clone)]
247pub struct OwnedTransactionBuilder {
248 buffer: BuilderBuffer,
249}
250
251impl OwnedTransactionBuilder {
252 pub fn with_read_slot(
254 mut self,
255 slot: &TransactionSlot,
256 ) -> Result<OwnedTransactionBuilder, OwnedTransactionBuilderError> {
257 self.buffer.append_read_slots(slice::from_ref(slot))?;
258 Ok(OwnedTransactionBuilder {
259 buffer: self.buffer,
260 })
261 }
262
263 pub fn with_read_slots(
265 mut self,
266 slots: &[TransactionSlot],
267 ) -> Result<OwnedTransactionBuilder, OwnedTransactionBuilderError> {
268 self.buffer.append_read_slots(slots)?;
269 Ok(OwnedTransactionBuilder {
270 buffer: self.buffer,
271 })
272 }
273
274 pub fn with_write_slot(
276 mut self,
277 slot: &TransactionSlot,
278 ) -> Result<OwnedTransactionBuilderWithWriteSlot, OwnedTransactionBuilderError> {
279 self.buffer.append_write_slots(slice::from_ref(slot))?;
280 Ok(OwnedTransactionBuilderWithWriteSlot {
281 buffer: self.buffer,
282 })
283 }
284
285 pub fn with_write_slots(
287 mut self,
288 slots: &[TransactionSlot],
289 ) -> Result<OwnedTransactionBuilderWithWriteSlot, OwnedTransactionBuilderError> {
290 self.buffer.append_write_slots(slots)?;
291 Ok(OwnedTransactionBuilderWithWriteSlot {
292 buffer: self.buffer,
293 })
294 }
295
296 pub fn with_payload(
298 mut self,
299 payload: &[u8],
300 ) -> Result<OwnedTransactionBuilderWithPayload, OwnedTransactionBuilderError> {
301 self.buffer.append_payload(payload)?;
302 Ok(OwnedTransactionBuilderWithPayload {
303 buffer: self.buffer,
304 })
305 }
306
307 pub fn with_seal(
309 mut self,
310 seal: &[u8],
311 ) -> Result<OwnedTransaction, OwnedTransactionBuilderError> {
312 self.buffer.append_seal(seal)?;
313 self.finish()
314 }
315
316 pub fn finish(self) -> Result<OwnedTransaction, OwnedTransactionBuilderError> {
318 let buffer = self.buffer.finish()?.into_shared();
319 Ok(OwnedTransaction { buffer })
320 }
321}
322
323#[derive(Debug, Clone)]
325pub struct OwnedTransactionBuilderWithWriteSlot {
326 buffer: BuilderBuffer,
327}
328
329impl OwnedTransactionBuilderWithWriteSlot {
330 pub fn with_write_slot(
332 mut self,
333 slot: &TransactionSlot,
334 ) -> Result<Self, OwnedTransactionBuilderError> {
335 self.buffer.append_write_slots(slice::from_ref(slot))?;
336 Ok(Self {
337 buffer: self.buffer,
338 })
339 }
340
341 pub fn with_write_slots(
343 mut self,
344 slots: &[TransactionSlot],
345 ) -> Result<Self, OwnedTransactionBuilderError> {
346 self.buffer.append_write_slots(slots)?;
347 Ok(Self {
348 buffer: self.buffer,
349 })
350 }
351
352 pub fn with_payload(
354 mut self,
355 payload: &[u8],
356 ) -> Result<OwnedTransactionBuilderWithPayload, OwnedTransactionBuilderError> {
357 self.buffer.append_payload(payload)?;
358 Ok(OwnedTransactionBuilderWithPayload {
359 buffer: self.buffer,
360 })
361 }
362
363 pub fn with_seal(
365 mut self,
366 seal: &[u8],
367 ) -> Result<OwnedTransaction, OwnedTransactionBuilderError> {
368 self.buffer.append_seal(seal)?;
369 self.finish()
370 }
371
372 pub fn finish(self) -> Result<OwnedTransaction, OwnedTransactionBuilderError> {
374 let buffer = self.buffer.finish()?.into_shared();
375 Ok(OwnedTransaction { buffer })
376 }
377}
378
379#[derive(Debug, Clone)]
381pub struct OwnedTransactionBuilderWithPayload {
382 buffer: BuilderBuffer,
383}
384
385impl OwnedTransactionBuilderWithPayload {
386 pub fn with_payload(mut self, payload: &[u8]) -> Result<Self, OwnedTransactionBuilderError> {
388 self.buffer.append_payload(payload)?;
389 Ok(Self {
390 buffer: self.buffer,
391 })
392 }
393
394 pub fn with_seal(
396 mut self,
397 seal: &[u8],
398 ) -> Result<OwnedTransaction, OwnedTransactionBuilderError> {
399 self.buffer.append_seal(seal)?;
400 self.finish()
401 }
402
403 pub fn finish(self) -> Result<OwnedTransaction, OwnedTransactionBuilderError> {
405 let buffer = self.buffer.finish()?.into_shared();
406 Ok(OwnedTransaction { buffer })
407 }
408}