Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: actually use envelope encoding for pooled tx #6832

Merged
merged 1 commit into from Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
66 changes: 63 additions & 3 deletions crates/primitives/src/transaction/pooled.rs
Expand Up @@ -10,7 +10,7 @@ use crate::{
EIP4844_TX_TYPE_ID,
};
use alloy_rlp::{Decodable, Encodable, Error as RlpError, Header, EMPTY_LIST_CODE};
use bytes::Buf;
use bytes::{Buf, BytesMut};
use derive_more::{AsRef, Deref};
use reth_codecs::add_arbitrary_tests;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -317,14 +317,61 @@ impl PooledTransactionsElement {
Self::Deposit { transaction, .. } => transaction.payload_len_without_header(),
}
}

/// Returns the enveloped encoded transactions.
///
/// See also [TransactionSigned::encode_enveloped]
pub fn envelope_encoded(&self) -> Bytes {
let mut buf = BytesMut::new();
self.encode_enveloped(&mut buf);
buf.freeze().into()
}

/// Encodes the transaction into the "raw" format (e.g. `eth_sendRawTransaction`).
/// This format is also referred to as "binary" encoding.
///
/// For legacy transactions, it encodes the RLP of the transaction into the buffer:
/// `rlp(tx-data)`
/// For EIP-2718 typed it encodes the type of the transaction followed by the rlp of the
/// transaction: `tx-type || rlp(tx-data)`
pub fn encode_enveloped(&self, out: &mut dyn bytes::BufMut) {
// The encoding of `tx-data` depends on the transaction type. Refer to these docs for more
// information on the exact format:
// - Legacy: TxLegacy::encode_with_signature
// - EIP-2930: TxEip2930::encode_with_signature
// - EIP-1559: TxEip1559::encode_with_signature
// - EIP-4844: BlobTransaction::encode_with_type_inner
match self {
Self::Legacy { transaction, signature, .. } => {
transaction.encode_with_signature(signature, out)
}
Self::Eip2930 { transaction, signature, .. } => {
transaction.encode_with_signature(signature, out, false)
}
Self::Eip1559 { transaction, signature, .. } => {
transaction.encode_with_signature(signature, out, false)
}
Self::BlobTransaction(blob_tx) => {
// The inner encoding is used with `with_header` set to true, making the final
// encoding:
// `tx_type || rlp([transaction_payload_body, blobs, commitments, proofs]))`
blob_tx.encode_with_type_inner(out, false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, this is right

}
#[cfg(feature = "optimism")]
Self::Deposit { transaction, .. } => {
transaction.encode(out, false);
}
}
}
}

impl Encodable for PooledTransactionsElement {
/// Encodes an enveloped post EIP-4844 [PooledTransactionsElement].
///
/// For legacy transactions, this encodes the transaction as `rlp(tx-data)`.
///
/// For EIP-2718 transactions, this encodes the transaction as `rlp(tx_type || rlp(tx-data)))`.
/// For EIP-2718 transactions, this encodes the transaction as `rlp(tx_type || rlp(tx-data)))`,
/// ___including__ the RLP-header for the entire transaction.
fn encode(&self, out: &mut dyn bytes::BufMut) {
// The encoding of `tx-data` depends on the transaction type. Refer to these docs for more
// information on the exact format:
Expand Down Expand Up @@ -646,7 +693,7 @@ impl From<TransactionSignedEcRecovered> for PooledTransactionsElementEcRecovered
#[cfg(test)]
mod tests {
use super::*;
use alloy_primitives::hex;
use alloy_primitives::{address, hex};
use assert_matches::assert_matches;

#[test]
Expand Down Expand Up @@ -690,6 +737,19 @@ mod tests {
}
}

// <https://holesky.etherscan.io/tx/0x7f60faf8a410a80d95f7ffda301d5ab983545913d3d789615df3346579f6c849>
#[test]
fn decode_eip1559_enveloped() {
let data = hex!("02f903d382426882ba09832dc6c0848674742682ed9694714b6a4ea9b94a8a7d9fd362ed72630688c8898c80b90364492d24749189822d8512430d3f3ff7a2ede675ac08265c08e2c56ff6fdaa66dae1cdbe4a5d1d7809f3e99272d067364e597542ac0c369d69e22a6399c3e9bee5da4b07e3f3fdc34c32c3d88aa2268785f3e3f8086df0934b10ef92cfffc2e7f3d90f5e83302e31382e302d64657600000000000000000000000000000000000000000000569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd000000000000000000000000e1e210594771824dad216568b91c9cb4ceed361c00000000000000000000000000000000000000000000000000000000000546e00000000000000000000000000000000000000000000000000000000000e4e1c00000000000000000000000000000000000000000000000000000000065d6750c00000000000000000000000000000000000000000000000000000000000f288000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002cf600000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000000f1628e56fa6d8c50e5b984a58c0df14de31c7b857ce7ba499945b99252976a93d06dcda6776fc42167fbe71cb59f978f5ef5b12577a90b132d14d9c6efa528076f0161d7bf03643cfc5490ec5084f4a041db7f06c50bd97efa08907ba79ddcac8b890f24d12d8db31abbaaf18985d54f400449ee0559a4452afe53de5853ce090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000064ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000c080a01428023fc54a27544abc421d5d017b9a7c5936ad501cbdecd0d9d12d04c1a033a0753104bbf1c87634d6ff3f0ffa0982710612306003eb022363b57994bdef445a"
);

let res = PooledTransactionsElement::decode_enveloped(data.into()).unwrap();
assert_eq!(
res.into_transaction().to(),
Some(address!("714b6a4ea9b94a8a7d9fd362ed72630688c8898c"))
);
}

#[test]
fn legacy_valid_pooled_decoding() {
// d3 <- payload length, d3 - c0 = 0x13 = 19
Expand Down
11 changes: 4 additions & 7 deletions crates/rpc/rpc/src/eth/api/transactions.rs
Expand Up @@ -11,7 +11,6 @@ use crate::{
},
EthApi, EthApiSpec,
};
use alloy_rlp::Encodable;
use async_trait::async_trait;
use reth_network_api::NetworkInfo;
use reth_node_api::ConfigureEvmEnv;
Expand Down Expand Up @@ -440,12 +439,10 @@ where

async fn raw_transaction_by_hash(&self, hash: B256) -> EthResult<Option<Bytes>> {
// Note: this is mostly used to fetch pooled transactions so we check the pool first
if let Some(tx) = self.pool().get_pooled_transaction_element(hash).map(|tx| {
let mut buf = Vec::new();
tx.encode(&mut buf);
buf
}) {
return Ok(Some(tx.into()));
if let Some(tx) =
self.pool().get_pooled_transaction_element(hash).map(|tx| tx.envelope_encoded())
{
return Ok(Some(tx));
}

self.on_blocking_task(|this| async move {
Expand Down