Skip to content

Commit

Permalink
fix: use enveloped encoding for typed transactions (#239)
Browse files Browse the repository at this point in the history
* fix: use enveloped encoding for typed transactions

remove redundant method

fix: remove encode_enveloped

* improve docs for `encode_signed`
* fix vec with_capacity and `into_signed` for 4844 with sidecar

fix more raw tx encodings, need to fix length

hmm this is all network encoding?

still TODO: clear up api boundaries

remove encode_signed, decode_signed

large refactors to encoding logic

todo: analogous methods on Signed, fix tests

fix tests

fix more tests and lints

remove incorrect doc

remove unnecessary printlns

remove deref, remove tagged legacy

fix tests

fix Encodable length and add test

* fix API changes from tx builder

* add test rlp data
  • Loading branch information
Rjected authored Mar 13, 2024
1 parent 0c588bf commit d0794e5
Show file tree
Hide file tree
Showing 10 changed files with 721 additions and 313 deletions.
37 changes: 14 additions & 23 deletions crates/consensus/src/receipt/envelope.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{Receipt, ReceiptWithBloom, TxType};
use alloy_eips::eip2718::{Decodable2718, Eip2718Error, Encodable2718};
use alloy_eips::eip2718::{Decodable2718, Encodable2718};
use alloy_rlp::{length_of_length, BufMut, Decodable, Encodable};

/// Receipt envelope, as defined in [EIP-2718].
Expand All @@ -16,8 +16,6 @@ use alloy_rlp::{length_of_length, BufMut, Decodable, Encodable};
pub enum ReceiptEnvelope {
/// Receipt envelope with no type flag.
Legacy(ReceiptWithBloom),
/// Receipt envelope with type flag 0.
TaggedLegacy(ReceiptWithBloom),
/// Receipt envelope with type flag 1, containing a [EIP-2930] receipt.
///
/// [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930
Expand All @@ -36,7 +34,7 @@ impl ReceiptEnvelope {
/// Return the [`TxType`] of the inner receipt.
pub const fn tx_type(&self) -> TxType {
match self {
Self::Legacy(_) | Self::TaggedLegacy(_) => TxType::Legacy,
Self::Legacy(_) => TxType::Legacy,
Self::Eip2930(_) => TxType::Eip2930,
Self::Eip1559(_) => TxType::Eip1559,
Self::Eip4844(_) => TxType::Eip4844,
Expand All @@ -47,23 +45,17 @@ impl ReceiptEnvelope {
/// however, future receipt types may be added.
pub const fn as_receipt_with_bloom(&self) -> Option<&ReceiptWithBloom> {
match self {
Self::Legacy(t)
| Self::TaggedLegacy(t)
| Self::Eip2930(t)
| Self::Eip1559(t)
| Self::Eip4844(t) => Some(t),
Self::Legacy(t) | Self::Eip2930(t) | Self::Eip1559(t) | Self::Eip4844(t) => Some(t),
}
}

/// Return the inner receipt. Currently this is infallible, however, future
/// receipt types may be added.
pub const fn as_receipt(&self) -> Option<&Receipt> {
match self {
Self::Legacy(t)
| Self::TaggedLegacy(t)
| Self::Eip2930(t)
| Self::Eip1559(t)
| Self::Eip4844(t) => Some(&t.receipt),
Self::Legacy(t) | Self::Eip2930(t) | Self::Eip1559(t) | Self::Eip4844(t) => {
Some(&t.receipt)
}
}
}

Expand Down Expand Up @@ -100,7 +92,6 @@ impl Decodable for ReceiptEnvelope {
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
match Self::network_decode(buf) {
Ok(t) => Ok(t),
Err(Eip2718Error::RlpError(e)) => Err(e),
Err(_) => Err(alloy_rlp::Error::Custom("Unexpected type")),
}
}
Expand All @@ -110,7 +101,6 @@ impl Encodable2718 for ReceiptEnvelope {
fn type_flag(&self) -> Option<u8> {
match self {
Self::Legacy(_) => None,
Self::TaggedLegacy(_) => Some(TxType::Legacy as u8),
Self::Eip2930(_) => Some(TxType::Eip2930 as u8),
Self::Eip1559(_) => Some(TxType::Eip1559 as u8),
Self::Eip4844(_) => Some(TxType::Eip4844 as u8),
Expand All @@ -131,30 +121,31 @@ impl Encodable2718 for ReceiptEnvelope {
}

impl Decodable2718 for ReceiptEnvelope {
fn typed_decode(ty: u8, buf: &mut &[u8]) -> Result<Self, Eip2718Error> {
fn typed_decode(ty: u8, buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
let receipt = Decodable::decode(buf)?;
match ty.try_into()? {
TxType::Legacy => Ok(Self::TaggedLegacy(receipt)),
match ty.try_into().map_err(|_| alloy_rlp::Error::Custom("Unexpected type"))? {
TxType::Eip2930 => Ok(Self::Eip2930(receipt)),
TxType::Eip1559 => Ok(Self::Eip1559(receipt)),
TxType::Eip4844 => Ok(Self::Eip4844(receipt)),
TxType::Legacy => {
Err(alloy_rlp::Error::Custom("type-0 eip2718 transactions are not supported"))
}
}
}

fn fallback_decode(buf: &mut &[u8]) -> Result<Self, Eip2718Error> {
fn fallback_decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
Ok(Self::Legacy(Decodable::decode(buf)?))
}
}

#[cfg(any(test, feature = "arbitrary"))]
impl<'a> arbitrary::Arbitrary<'a> for ReceiptEnvelope {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let tx_type = u.int_in_range(-1..=2)?;
let tx_type = u.int_in_range(0..=2)?;
let receipt = Receipt::arbitrary(u)?.with_bloom();

match tx_type {
-1 => Ok(Self::Legacy(receipt)),
0 => Ok(Self::TaggedLegacy(receipt)),
0 => Ok(Self::Legacy(receipt)),
1 => Ok(Self::Eip2930(receipt)),
2 => Ok(Self::Eip1559(receipt)),
_ => unreachable!(),
Expand Down
40 changes: 5 additions & 35 deletions crates/consensus/src/signed.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::transaction::SignableTransaction;
use alloy_primitives::{Signature, B256};
use alloy_rlp::BufMut;

/// A transaction with a signature and hash seal.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
Expand All @@ -10,14 +9,6 @@ pub struct Signed<T, Sig = Signature> {
hash: B256,
}

impl<T> std::ops::Deref for Signed<T> {
type Target = T;

fn deref(&self) -> &Self::Target {
&self.tx
}
}

impl<T, Sig> Signed<T, Sig> {
/// Returns a reference to the transaction.
pub const fn tx(&self) -> &T {
Expand All @@ -33,6 +24,11 @@ impl<T, Sig> Signed<T, Sig> {
pub const fn hash(&self) -> &B256 {
&self.hash
}

/// Splits the transaction into parts.
pub fn into_parts(self) -> (T, Sig, B256) {
(self.tx, self.signature, self.hash)
}
}

impl<T: SignableTransaction<Sig>, Sig> Signed<T, Sig> {
Expand All @@ -45,32 +41,6 @@ impl<T: SignableTransaction<Sig>, Sig> Signed<T, Sig> {
pub fn signature_hash(&self) -> B256 {
self.tx.signature_hash()
}

/// Output the signed RLP for the transaction.
pub fn encode_signed(&self, out: &mut dyn BufMut) {
self.tx.encode_signed(&self.signature, out);
}

/// Produce the RLP encoded signed transaction.
pub fn rlp_signed(&self) -> Vec<u8> {
let mut buf = vec![];
self.encode_signed(&mut buf);
buf
}
}

impl<T: SignableTransaction<Sig>, Sig> alloy_rlp::Encodable for Signed<T, Sig> {
fn encode(&self, out: &mut dyn BufMut) {
self.tx.encode_signed(&self.signature, out)
}

// TODO: impl length
}

impl<T: SignableTransaction<Sig>, Sig> alloy_rlp::Decodable for Signed<T, Sig> {
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
<T as SignableTransaction<Sig>>::decode_signed(buf)
}
}

#[cfg(feature = "k256")]
Expand Down
Loading

0 comments on commit d0794e5

Please sign in to comment.