From d50b17875a8020cd4a3ad5ffaca25d9ed004e564 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Wed, 18 Sep 2024 17:28:57 +0300 Subject: [PATCH] fix: enforce correct parity encoding for typed transactions --- crates/consensus/src/transaction/eip1559.rs | 6 +++++- crates/consensus/src/transaction/eip2930.rs | 6 +++++- crates/consensus/src/transaction/eip4844.rs | 6 +++++- crates/consensus/src/transaction/eip7702.rs | 6 +++++- crates/consensus/src/transaction/legacy.rs | 6 +++++- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/crates/consensus/src/transaction/eip1559.rs b/crates/consensus/src/transaction/eip1559.rs index 108c7e8a4c6..de59cc1c4bd 100644 --- a/crates/consensus/src/transaction/eip1559.rs +++ b/crates/consensus/src/transaction/eip1559.rs @@ -1,7 +1,7 @@ use crate::{EncodableSignature, SignableTransaction, Signed, Transaction, TxType}; use alloc::vec::Vec; use alloy_eips::{eip2930::AccessList, eip7702::SignedAuthorization}; -use alloy_primitives::{keccak256, Bytes, ChainId, Signature, TxKind, B256, U256}; +use alloy_primitives::{keccak256, Bytes, ChainId, Parity, Signature, TxKind, B256, U256}; use alloy_rlp::{BufMut, Decodable, Encodable, Header}; use core::mem; @@ -212,6 +212,10 @@ impl TxEip1559 { let tx = Self::decode_fields(buf)?; let signature = Signature::decode_rlp_vrs(buf)?; + if !matches!(signature.v(), Parity::Parity(_)) { + return Err(alloy_rlp::Error::Custom("invalid parity for typed transaction")); + } + let signed = tx.into_signed(signature); if buf.len() + header.payload_length != original_len { return Err(alloy_rlp::Error::ListLengthMismatch { diff --git a/crates/consensus/src/transaction/eip2930.rs b/crates/consensus/src/transaction/eip2930.rs index 5ed91a2b6f0..0c58da01e0e 100644 --- a/crates/consensus/src/transaction/eip2930.rs +++ b/crates/consensus/src/transaction/eip2930.rs @@ -1,7 +1,7 @@ use crate::{EncodableSignature, SignableTransaction, Signed, Transaction, TxType}; use alloc::vec::Vec; use alloy_eips::{eip2930::AccessList, eip7702::SignedAuthorization}; -use alloy_primitives::{keccak256, Bytes, ChainId, Signature, TxKind, B256, U256}; +use alloy_primitives::{keccak256, Bytes, ChainId, Parity, Signature, TxKind, B256, U256}; use alloy_rlp::{length_of_length, BufMut, Decodable, Encodable, Header}; use core::mem; @@ -205,6 +205,10 @@ impl TxEip2930 { let tx = Self::decode_fields(buf)?; let signature = Signature::decode_rlp_vrs(buf)?; + if !matches!(signature.v(), Parity::Parity(_)) { + return Err(alloy_rlp::Error::Custom("invalid parity for typed transaction")); + } + let signed = tx.into_signed(signature); if buf.len() + header.payload_length != original_len { return Err(alloy_rlp::Error::ListLengthMismatch { diff --git a/crates/consensus/src/transaction/eip4844.rs b/crates/consensus/src/transaction/eip4844.rs index 78bb4d28650..d29133c25f8 100644 --- a/crates/consensus/src/transaction/eip4844.rs +++ b/crates/consensus/src/transaction/eip4844.rs @@ -2,7 +2,7 @@ use crate::{EncodableSignature, SignableTransaction, Signed, Transaction, TxType use alloc::vec::Vec; use alloy_eips::{eip2930::AccessList, eip4844::DATA_GAS_PER_BLOB, eip7702::SignedAuthorization}; -use alloy_primitives::{keccak256, Address, Bytes, ChainId, Signature, TxKind, B256, U256}; +use alloy_primitives::{keccak256, Address, Bytes, ChainId, Parity, Signature, TxKind, B256, U256}; use alloy_rlp::{length_of_length, BufMut, Decodable, Encodable, Header}; use core::mem; @@ -615,6 +615,10 @@ impl TxEip4844 { let tx = Self::decode_fields(buf)?; let signature = Signature::decode_rlp_vrs(buf)?; + if !matches!(signature.v(), Parity::Parity(_)) { + return Err(alloy_rlp::Error::Custom("invalid parity for typed transaction")); + } + let signed = tx.into_signed(signature); if buf.len() + header.payload_length != original_len { return Err(alloy_rlp::Error::ListLengthMismatch { diff --git a/crates/consensus/src/transaction/eip7702.rs b/crates/consensus/src/transaction/eip7702.rs index c13bda3bf98..6b1616623e0 100644 --- a/crates/consensus/src/transaction/eip7702.rs +++ b/crates/consensus/src/transaction/eip7702.rs @@ -4,7 +4,7 @@ use alloy_eips::{ eip2930::AccessList, eip7702::{constants::EIP7702_TX_TYPE_ID, SignedAuthorization}, }; -use alloy_primitives::{keccak256, Address, Bytes, ChainId, Signature, TxKind, B256, U256}; +use alloy_primitives::{keccak256, Address, Bytes, ChainId, Parity, Signature, TxKind, B256, U256}; use alloy_rlp::{BufMut, Decodable, Encodable, Header}; use core::mem; @@ -221,6 +221,10 @@ impl TxEip7702 { let tx = Self::decode_fields(buf)?; let signature = Signature::decode_rlp_vrs(buf)?; + if !matches!(signature.v(), Parity::Parity(_)) { + return Err(alloy_rlp::Error::Custom("invalid parity for typed transaction")); + } + let signed = tx.into_signed(signature); if buf.len() + header.payload_length != original_len { return Err(alloy_rlp::Error::ListLengthMismatch { diff --git a/crates/consensus/src/transaction/legacy.rs b/crates/consensus/src/transaction/legacy.rs index c3ecdc5437c..68d0e364fcd 100644 --- a/crates/consensus/src/transaction/legacy.rs +++ b/crates/consensus/src/transaction/legacy.rs @@ -2,7 +2,7 @@ use core::mem; use alloc::vec::Vec; use alloy_eips::{eip2930::AccessList, eip7702::SignedAuthorization}; -use alloy_primitives::{keccak256, Bytes, ChainId, Signature, TxKind, B256, U256}; +use alloy_primitives::{keccak256, Bytes, ChainId, Parity, Signature, TxKind, B256, U256}; use alloy_rlp::{length_of_length, BufMut, Decodable, Encodable, Header, Result}; use crate::{EncodableSignature, SignableTransaction, Signed, Transaction, TxType}; @@ -171,6 +171,10 @@ impl TxLegacy { let mut tx = Self::decode_fields(buf)?; let signature = Signature::decode_rlp_vrs(buf)?; + if !matches!(signature.v(), Parity::Eip155(_) | Parity::NonEip155(_)) { + return Err(alloy_rlp::Error::Custom("invalid parity for legacy transaction")); + } + // extract chain id from signature let v = signature.v(); tx.chain_id = v.chain_id();