1use crate::{
5 MAX_SPAN_BATCH_ELEMENTS, SpanBatchBits, SpanBatchError, SpanBatchTransactionData,
6 SpanDecodingError, read_tx_data,
7};
8use alloc::vec::Vec;
9use alloy_consensus::{Transaction, TxEnvelope, TxType};
10use alloy_eips::eip2718::Encodable2718;
11use alloy_primitives::{Address, Bytes, PrimitiveSignature as Signature, U256, bytes};
12use alloy_rlp::{Buf, Decodable, Encodable};
13
14#[derive(Debug, Default, Clone, PartialEq, Eq)]
16pub struct SpanBatchTransactions {
17 pub total_block_tx_count: u64,
19 pub contract_creation_bits: SpanBatchBits,
21 pub tx_sigs: Vec<Signature>,
23 pub tx_nonces: Vec<u64>,
25 pub tx_gases: Vec<u64>,
27 pub tx_tos: Vec<Address>,
29 pub tx_datas: Vec<Vec<u8>>,
31 pub protected_bits: SpanBatchBits,
33 pub tx_types: Vec<TxType>,
35 pub legacy_tx_count: u64,
37}
38
39impl SpanBatchTransactions {
40 pub fn encode(&self, w: &mut dyn bytes::BufMut) -> Result<(), SpanBatchError> {
42 self.encode_contract_creation_bits(w)?;
43 self.encode_tx_sigs(w)?;
44 self.encode_tx_tos(w)?;
45 self.encode_tx_datas(w)?;
46 self.encode_tx_nonces(w)?;
47 self.encode_tx_gases(w)?;
48 self.encode_protected_bits(w)?;
49 Ok(())
50 }
51
52 pub fn decode(&mut self, r: &mut &[u8]) -> Result<(), SpanBatchError> {
54 self.decode_contract_creation_bits(r)?;
55 self.decode_tx_sigs(r)?;
56 self.decode_tx_tos(r)?;
57 self.decode_tx_datas(r)?;
58 self.decode_tx_nonces(r)?;
59 self.decode_tx_gases(r)?;
60 self.decode_protected_bits(r)?;
61 Ok(())
62 }
63
64 pub fn encode_contract_creation_bits(
66 &self,
67 w: &mut dyn bytes::BufMut,
68 ) -> Result<(), SpanBatchError> {
69 SpanBatchBits::encode(w, self.total_block_tx_count as usize, &self.contract_creation_bits)?;
70 Ok(())
71 }
72
73 pub fn encode_protected_bits(&self, w: &mut dyn bytes::BufMut) -> Result<(), SpanBatchError> {
75 SpanBatchBits::encode(w, self.legacy_tx_count as usize, &self.protected_bits)?;
76 Ok(())
77 }
78
79 pub fn encode_tx_sigs(&self, w: &mut dyn bytes::BufMut) -> Result<(), SpanBatchError> {
81 let mut y_parity_bits = SpanBatchBits::default();
82 for (i, sig) in self.tx_sigs.iter().enumerate() {
83 y_parity_bits.set_bit(i, sig.v());
84 }
85
86 SpanBatchBits::encode(w, self.total_block_tx_count as usize, &y_parity_bits)?;
87 for sig in &self.tx_sigs {
88 w.put_slice(&sig.r().to_be_bytes::<32>());
89 w.put_slice(&sig.s().to_be_bytes::<32>());
90 }
91 Ok(())
92 }
93
94 pub fn encode_tx_nonces(&self, w: &mut dyn bytes::BufMut) -> Result<(), SpanBatchError> {
96 let mut buf = [0u8; 10];
97 for nonce in &self.tx_nonces {
98 let slice = unsigned_varint::encode::u64(*nonce, &mut buf);
99 w.put_slice(slice);
100 }
101 Ok(())
102 }
103
104 pub fn encode_tx_gases(&self, w: &mut dyn bytes::BufMut) -> Result<(), SpanBatchError> {
106 let mut buf = [0u8; 10];
107 for gas in &self.tx_gases {
108 let slice = unsigned_varint::encode::u64(*gas, &mut buf);
109 w.put_slice(slice);
110 }
111 Ok(())
112 }
113
114 pub fn encode_tx_tos(&self, w: &mut dyn bytes::BufMut) -> Result<(), SpanBatchError> {
116 for to in &self.tx_tos {
117 w.put_slice(to.as_ref());
118 }
119 Ok(())
120 }
121
122 pub fn encode_tx_datas(&self, w: &mut dyn bytes::BufMut) -> Result<(), SpanBatchError> {
124 for data in &self.tx_datas {
125 w.put_slice(data);
126 }
127 Ok(())
128 }
129
130 pub fn decode_contract_creation_bits(&mut self, r: &mut &[u8]) -> Result<(), SpanBatchError> {
132 if self.total_block_tx_count > MAX_SPAN_BATCH_ELEMENTS {
133 return Err(SpanBatchError::TooBigSpanBatchSize);
134 }
135
136 self.contract_creation_bits = SpanBatchBits::decode(r, self.total_block_tx_count as usize)?;
137 Ok(())
138 }
139
140 pub fn decode_protected_bits(&mut self, r: &mut &[u8]) -> Result<(), SpanBatchError> {
142 if self.legacy_tx_count > MAX_SPAN_BATCH_ELEMENTS {
143 return Err(SpanBatchError::TooBigSpanBatchSize);
144 }
145
146 self.protected_bits = SpanBatchBits::decode(r, self.legacy_tx_count as usize)?;
147 Ok(())
148 }
149
150 pub fn decode_tx_sigs(&mut self, r: &mut &[u8]) -> Result<(), SpanBatchError> {
152 let y_parity_bits = SpanBatchBits::decode(r, self.total_block_tx_count as usize)?;
153 let mut sigs = Vec::with_capacity(self.total_block_tx_count as usize);
154 for i in 0..self.total_block_tx_count {
155 let y_parity = y_parity_bits.get_bit(i as usize).expect("same length");
156 let r_val = U256::from_be_slice(&r[..32]);
157 let s_val = U256::from_be_slice(&r[32..64]);
158 sigs.push(Signature::new(r_val, s_val, y_parity == 1));
159 r.advance(64);
160 }
161 self.tx_sigs = sigs;
162 Ok(())
163 }
164
165 pub fn decode_tx_nonces(&mut self, r: &mut &[u8]) -> Result<(), SpanBatchError> {
167 let mut nonces = Vec::with_capacity(self.total_block_tx_count as usize);
168 for _ in 0..self.total_block_tx_count {
169 let (nonce, remaining) = unsigned_varint::decode::u64(r)
170 .map_err(|_| SpanBatchError::Decoding(SpanDecodingError::TxNonces))?;
171 nonces.push(nonce);
172 *r = remaining;
173 }
174 self.tx_nonces = nonces;
175 Ok(())
176 }
177
178 pub fn decode_tx_gases(&mut self, r: &mut &[u8]) -> Result<(), SpanBatchError> {
180 let mut gases = Vec::with_capacity(self.total_block_tx_count as usize);
181 for _ in 0..self.total_block_tx_count {
182 let (gas, remaining) = unsigned_varint::decode::u64(r)
183 .map_err(|_| SpanBatchError::Decoding(SpanDecodingError::TxNonces))?;
184 gases.push(gas);
185 *r = remaining;
186 }
187 self.tx_gases = gases;
188 Ok(())
189 }
190
191 pub fn decode_tx_tos(&mut self, r: &mut &[u8]) -> Result<(), SpanBatchError> {
193 let mut tos = Vec::with_capacity(self.total_block_tx_count as usize);
194 let contract_creation_count = self.contract_creation_count();
195 for _ in 0..(self.total_block_tx_count - contract_creation_count) {
196 let to = Address::from_slice(&r[..20]);
197 tos.push(to);
198 r.advance(20);
199 }
200 self.tx_tos = tos;
201 Ok(())
202 }
203
204 pub fn decode_tx_datas(&mut self, r: &mut &[u8]) -> Result<(), SpanBatchError> {
206 let mut tx_datas = Vec::new();
207 let mut tx_types = Vec::new();
208
209 for _ in 0..self.total_block_tx_count {
212 let (tx_data, tx_type) = read_tx_data(r)?;
213 tx_datas.push(tx_data);
214 tx_types.push(tx_type);
215 if matches!(tx_type, TxType::Legacy) {
216 self.legacy_tx_count += 1;
217 }
218 }
219
220 self.tx_datas = tx_datas;
221 self.tx_types = tx_types;
222
223 Ok(())
224 }
225
226 pub fn contract_creation_count(&self) -> u64 {
228 self.contract_creation_bits.as_ref().iter().map(|b| b.count_ones() as u64).sum()
229 }
230
231 pub fn full_txs(&self, chain_id: u64) -> Result<Vec<Vec<u8>>, SpanBatchError> {
233 let mut txs = Vec::new();
234 let mut to_idx = 0;
235 let mut protected_bit_idx = 0;
236 for idx in 0..self.total_block_tx_count {
237 let mut datas = self.tx_datas[idx as usize].as_slice();
238 let tx = SpanBatchTransactionData::decode(&mut datas)
239 .map_err(|_| SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData))?;
240 let nonce = self
241 .tx_nonces
242 .get(idx as usize)
243 .ok_or(SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData))?;
244 let gas = self
245 .tx_gases
246 .get(idx as usize)
247 .ok_or(SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData))?;
248 let bit = self
249 .contract_creation_bits
250 .get_bit(idx as usize)
251 .ok_or(SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData))?;
252 let to = if bit == 0 {
253 if self.tx_tos.len() <= to_idx {
254 return Err(SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData));
255 }
256 to_idx += 1;
257 Some(self.tx_tos[to_idx - 1])
258 } else {
259 None
260 };
261 let sig = *self
262 .tx_sigs
263 .get(idx as usize)
264 .ok_or(SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData))?;
265 let is_protected = if tx.tx_type() == TxType::Legacy {
266 protected_bit_idx += 1;
267 self.protected_bits.get_bit(protected_bit_idx - 1).unwrap_or_default() == 1
268 } else {
269 true
270 };
271 let tx_envelope = tx.to_signed_tx(*nonce, *gas, to, chain_id, sig, is_protected)?;
272 let mut buf = Vec::new();
273 tx_envelope.encode_2718(&mut buf);
274 txs.push(buf);
275 }
276 Ok(txs)
277 }
278
279 pub fn add_txs(&mut self, txs: Vec<Bytes>, chain_id: u64) -> Result<(), SpanBatchError> {
281 let total_block_tx_count = txs.len() as u64;
282 let offset = self.total_block_tx_count;
283
284 for i in 0..total_block_tx_count {
285 let tx_enveloped = TxEnvelope::decode(&mut txs[i as usize].as_ref())
286 .map_err(|_| SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData))?;
287 let span_batch_tx = SpanBatchTransactionData::try_from(&tx_enveloped)?;
288
289 let tx_type = tx_enveloped.tx_type();
290 if matches!(tx_type, TxType::Legacy) {
291 let protected_bit = tx_enveloped.is_replay_protected();
292 self.protected_bits.set_bit(self.legacy_tx_count as usize, protected_bit);
293 self.legacy_tx_count += 1;
294 }
295
296 let (signature, to, nonce, gas, tx_chain_id) = match &tx_enveloped {
297 TxEnvelope::Legacy(tx) => {
298 let (tx, sig) = (tx.tx(), tx.signature());
299 (sig, tx.to(), tx.nonce(), tx.gas_limit(), tx.chain_id())
300 }
301 TxEnvelope::Eip2930(tx) => {
302 let (tx, sig) = (tx.tx(), tx.signature());
303 (sig, tx.to(), tx.nonce(), tx.gas_limit(), tx.chain_id())
304 }
305 TxEnvelope::Eip1559(tx) => {
306 let (tx, sig) = (tx.tx(), tx.signature());
307 (sig, tx.to(), tx.nonce(), tx.gas_limit(), tx.chain_id())
308 }
309 TxEnvelope::Eip7702(tx) => {
310 let (tx, sig) = (tx.tx(), tx.signature());
311 (sig, tx.to(), tx.nonce(), tx.gas_limit(), tx.chain_id())
312 }
313 _ => {
314 return Err(SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData))
315 }
316 };
317
318 if tx_enveloped.is_replay_protected() &&
319 tx_chain_id
320 .ok_or(SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData))? !=
321 chain_id
322 {
323 return Err(SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData));
324 }
325
326 let contract_creation_bit = match to {
327 Some(address) => {
328 self.tx_tos.push(address);
329 0
330 }
331 None => 1,
332 };
333 let mut tx_data_buf = Vec::new();
334 span_batch_tx.encode(&mut tx_data_buf);
335
336 self.tx_sigs.push(*signature);
337 self.contract_creation_bits.set_bit((i + offset) as usize, contract_creation_bit == 1);
338 self.tx_nonces.push(nonce);
339 self.tx_datas.push(tx_data_buf);
340 self.tx_gases.push(gas);
341 self.tx_types.push(tx_type);
342 }
343 self.total_block_tx_count += total_block_tx_count;
344 Ok(())
345 }
346}
347
348#[cfg(test)]
349mod tests {
350 use super::*;
351 use alloc::vec;
352 use alloy_consensus::{Signed, TxEip1559, TxEip2930, TxEip7702};
353 use alloy_primitives::{PrimitiveSignature as Signature, TxKind, address};
354
355 #[test]
356 fn test_span_batch_transactions_add_empty_txs() {
357 let mut span_batch_txs = SpanBatchTransactions::default();
358 let txs = vec![];
359 let chain_id = 1;
360 let result = span_batch_txs.add_txs(txs, chain_id);
361 assert!(result.is_ok());
362 assert_eq!(span_batch_txs.total_block_tx_count, 0);
363 }
364
365 #[test]
366 fn test_span_batch_transactions_add_eip2930_tx_wrong_chain_id() {
367 let sig = Signature::test_signature();
368 let to = address!("0123456789012345678901234567890123456789");
369 let tx = TxEnvelope::Eip2930(Signed::new_unchecked(
370 TxEip2930 { to: TxKind::Call(to), ..Default::default() },
371 sig,
372 Default::default(),
373 ));
374 let mut span_batch_txs = SpanBatchTransactions::default();
375 let mut buf = vec![];
376 tx.encode(&mut buf);
377 let txs = vec![Bytes::from(buf)];
378 let chain_id = 1;
379 let err = span_batch_txs.add_txs(txs, chain_id).unwrap_err();
380 assert_eq!(err, SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData));
381 }
382
383 #[test]
384 fn test_span_batch_transactions_add_eip2930_tx() {
385 let sig = Signature::test_signature();
386 let to = address!("0123456789012345678901234567890123456789");
387 let tx = TxEnvelope::Eip2930(Signed::new_unchecked(
388 TxEip2930 { to: TxKind::Call(to), chain_id: 1, ..Default::default() },
389 sig,
390 Default::default(),
391 ));
392 let mut span_batch_txs = SpanBatchTransactions::default();
393 let mut buf = vec![];
394 tx.encode(&mut buf);
395 let txs = vec![Bytes::from(buf)];
396 let chain_id = 1;
397 let result = span_batch_txs.add_txs(txs, chain_id);
398 assert_eq!(result, Ok(()));
399 assert_eq!(span_batch_txs.total_block_tx_count, 1);
400 }
401
402 #[test]
403 fn test_span_batch_transactions_add_eip1559_tx() {
404 let sig = Signature::test_signature();
405 let to = address!("0123456789012345678901234567890123456789");
406 let tx = TxEnvelope::Eip1559(Signed::new_unchecked(
407 TxEip1559 { to: TxKind::Call(to), chain_id: 1, ..Default::default() },
408 sig,
409 Default::default(),
410 ));
411 let mut span_batch_txs = SpanBatchTransactions::default();
412 let mut buf = vec![];
413 tx.encode(&mut buf);
414 let txs = vec![Bytes::from(buf)];
415 let chain_id = 1;
416 let result = span_batch_txs.add_txs(txs, chain_id);
417 assert_eq!(result, Ok(()));
418 assert_eq!(span_batch_txs.total_block_tx_count, 1);
419 }
420
421 #[test]
422 fn test_span_batch_transactions_add_eip7702_tx() {
423 let sig = Signature::test_signature();
424 let to = address!("0123456789012345678901234567890123456789");
425 let tx = TxEnvelope::Eip7702(Signed::new_unchecked(
426 TxEip7702 { to, chain_id: 1, ..Default::default() },
427 sig,
428 Default::default(),
429 ));
430 let mut span_batch_txs = SpanBatchTransactions::default();
431 let mut buf = vec![];
432 tx.encode(&mut buf);
433 let txs = vec![Bytes::from(buf)];
434 let chain_id = 1;
435 let result = span_batch_txs.add_txs(txs, chain_id);
436 assert_eq!(result, Ok(()));
437 assert_eq!(span_batch_txs.total_block_tx_count, 1);
438 }
439}