Skip to content

Commit

Permalink
feat: add batch utilities
Browse files Browse the repository at this point in the history
  • Loading branch information
refcell committed Oct 27, 2024
1 parent b8bd7c4 commit 85fcd9d
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 2 deletions.
5 changes: 4 additions & 1 deletion crates/protocol/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ mod iter;
pub use iter::FrameIter;

mod utils;
pub use utils::{starts_with_2718_deposit, to_system_config, OpBlockConversionError};
pub use utils::{
convert_v_to_y_parity, is_protected_v, read_tx_data, starts_with_2718_deposit,
to_system_config, OpBlockConversionError,
};

mod channel;
pub use channel::{
Expand Down
81 changes: 80 additions & 1 deletion crates/protocol/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
//! Utility methods used by protocol types.

use crate::{block_info::DecodeError, L1BlockInfoBedrock, L1BlockInfoEcotone, L1BlockInfoTx};
use alloc::vec::Vec;
use alloy_consensus::{TxEnvelope, TxType};
use alloy_primitives::B256;
use alloy_rlp::{Buf, Header};
use op_alloy_consensus::{OpBlock, OpTxEnvelope};
use op_alloy_genesis::{RollupConfig, SystemConfig};

use crate::{
block_info::DecodeError, L1BlockInfoBedrock, L1BlockInfoEcotone, L1BlockInfoTx, SpanBatchError,
SpanDecodingError,
};

/// Returns if the given `value` is a deposit transaction.
pub fn starts_with_2718_deposit<B>(value: &B) -> bool
where
Expand Down Expand Up @@ -224,6 +231,78 @@ fn u24(input: &[u8], idx: u32) -> u32 {
+ (u32::from(input[(idx + 2) as usize]) << 16)
}

/// Reads transaction data from a reader.
#[allow(unused)]
pub fn read_tx_data(r: &mut &[u8]) -> Result<(Vec<u8>, TxType), SpanBatchError> {
let mut tx_data = Vec::new();
let first_byte =
*r.first().ok_or(SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData))?;
let mut tx_type = 0;
if first_byte <= 0x7F {
// EIP-2718: Non-legacy tx, so write tx type
tx_type = first_byte;
tx_data.push(tx_type);
r.advance(1);
}

// Read the RLP header with a different reader pointer. This prevents the initial pointer from
// being advanced in the case that what we read is invalid.
let rlp_header = Header::decode(&mut (**r).as_ref())
.map_err(|_| SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData))?;

let tx_payload = if rlp_header.list {
// Grab the raw RLP for the transaction data from `r`. It was unaffected since we copied it.
let payload_length_with_header = rlp_header.payload_length + rlp_header.length();
let payload = r[0..payload_length_with_header].to_vec();
r.advance(payload_length_with_header);
Ok(payload)
} else {
Err(SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData))
}?;
tx_data.extend_from_slice(&tx_payload);

Ok((
tx_data,
tx_type
.try_into()
.map_err(|_| SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionType))?,
))
}

/// Converts a `v` value to a y parity bit, from the transaaction type.
#[allow(unused)]
pub const fn convert_v_to_y_parity(v: u64, tx_type: TxType) -> Result<bool, SpanBatchError> {
match tx_type {
TxType::Legacy => {
if v != 27 && v != 28 {
// EIP-155: v = 2 * chain_id + 35 + yParity
Ok((v - 35) & 1 == 1)
} else {
// Unprotected legacy txs must have v = 27 or 28
Ok(v - 27 == 1)
}
}
TxType::Eip2930 | TxType::Eip1559 => Ok(v == 1),
_ => Err(SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionType)),
}
}

/// Checks if the signature of the passed [TxEnvelope] is protected.
#[allow(unused)]
pub const fn is_protected_v(tx: &TxEnvelope) -> bool {
match tx {
TxEnvelope::Legacy(tx) => {
let v = tx.signature().v().to_u64();
if 64 - v.leading_zeros() <= 8 {
return v != 27 && v != 28 && v != 1 && v != 0;
}
// anything not 27 or 28 is considered protected
true
}
_ => true,
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit 85fcd9d

Please sign in to comment.