From fa9f23db980de9573a72a8ed5c24955eec5d6799 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Mon, 22 Apr 2024 12:04:25 +0200 Subject: [PATCH] feat(op): signature encoding (#7769) Co-authored-by: Roman Krasiuk --- crates/primitives/src/transaction/mod.rs | 14 ++++++++++--- .../primitives/src/transaction/signature.rs | 20 +++++++++++++++++-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs index 775950eea..31cb277f0 100644 --- a/crates/primitives/src/transaction/mod.rs +++ b/crates/primitives/src/transaction/mod.rs @@ -997,8 +997,9 @@ impl TransactionSignedNoHash { } // pre bedrock system transactions were sent from the zero address as legacy - // transactions with an empty signature Note: this is very hacky and only - // relevant for op-mainnet pre bedrock + // transactions with an empty signature + // + // NOTE: this is very hacky and only relevant for op-mainnet pre bedrock if self.is_legacy() && self.signature == Signature::optimism_deposit_tx_signature() { return Some(Address::ZERO) } @@ -2213,7 +2214,14 @@ mod tests { ); let encoded = &alloy_rlp::encode(signed_tx); - assert_eq!(hex!("c98080808080801b8080"), encoded[..]); + assert_eq!( + if cfg!(feature = "optimism") { + hex!("c9808080808080808080") + } else { + hex!("c98080808080801b8080") + }, + &encoded[..] + ); assert_eq!(MIN_LENGTH_LEGACY_TX_ENCODED, encoded.len()); TransactionSigned::decode(&mut &encoded[..]).unwrap(); diff --git a/crates/primitives/src/transaction/signature.rs b/crates/primitives/src/transaction/signature.rs index 200bf6989..84ae2915f 100644 --- a/crates/primitives/src/transaction/signature.rs +++ b/crates/primitives/src/transaction/signature.rs @@ -82,6 +82,14 @@ impl Signature { // EIP-155: v = {0, 1} + CHAIN_ID * 2 + 35 self.odd_y_parity as u64 + chain_id * 2 + 35 } else { + #[cfg(feature = "optimism")] + // pre bedrock system transactions were sent from the zero address as legacy + // transactions with an empty signature + // + // NOTE: this is very hacky and only relevant for op-mainnet pre bedrock + if *self == Self::optimism_deposit_tx_signature() { + return 0 + } self.odd_y_parity as u64 + 27 } } @@ -92,12 +100,20 @@ impl Signature { buf: &mut &[u8], ) -> alloy_rlp::Result<(Self, Option)> { let v = u64::decode(buf)?; - let r = Decodable::decode(buf)?; - let s = Decodable::decode(buf)?; + let r: U256 = Decodable::decode(buf)?; + let s: U256 = Decodable::decode(buf)?; if v < 35 { // non-EIP-155 legacy scheme, v = 27 for even y-parity, v = 28 for odd y-parity if v != 27 && v != 28 { + #[cfg(feature = "optimism")] + // pre bedrock system transactions were sent from the zero address as legacy + // transactions with an empty signature + // + // NOTE: this is very hacky and only relevant for op-mainnet pre bedrock + if v == 0 && r.is_zero() && s.is_zero() { + return Ok((Signature { r, s, odd_y_parity: false }, None)) + } return Err(RlpError::Custom("invalid Ethereum signature (V is not 27 or 28)")) } let odd_y_parity = v == 28;