Skip to content

Commit 20e003f

Browse files
feat(primitives): re-export alloy Recovered (#13670)
1 parent fbf7430 commit 20e003f

File tree

7 files changed

+39
-179
lines changed

7 files changed

+39
-179
lines changed

crates/optimism/node/src/txpool.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl TryFrom<RecoveredTx<OpTransactionSigned>> for OpPooledTransaction {
6060
fn try_from(value: RecoveredTx<OpTransactionSigned>) -> Result<Self, Self::Error> {
6161
let (tx, signer) = value.into_parts();
6262
let pooled: RecoveredTx<op_alloy_consensus::OpPooledTransaction> =
63-
RecoveredTx::from_signed_transaction(tx.try_into()?, signer);
63+
RecoveredTx::new_unchecked(tx.try_into()?, signer);
6464
Ok(pooled.into())
6565
}
6666
}
@@ -84,7 +84,7 @@ impl PoolTransaction for OpPooledTransaction {
8484
tx: RecoveredTx<Self::Consensus>,
8585
) -> Result<RecoveredTx<Self::Pooled>, Self::TryFromConsensusError> {
8686
let (tx, signer) = tx.into_parts();
87-
Ok(RecoveredTx::from_signed_transaction(tx.try_into()?, signer))
87+
Ok(RecoveredTx::new_unchecked(tx.try_into()?, signer))
8888
}
8989

9090
fn hash(&self) -> &TxHash {
@@ -459,7 +459,7 @@ mod tests {
459459
});
460460
let signature = Signature::test_signature();
461461
let signed_tx = OpTransactionSigned::new_unhashed(deposit_tx, signature);
462-
let signed_recovered = RecoveredTx::from_signed_transaction(signed_tx, signer);
462+
let signed_recovered = RecoveredTx::new_unchecked(signed_tx, signer);
463463
let len = signed_recovered.encode_2718_len();
464464
let pooled_tx = OpPooledTransaction::new(signed_recovered, len);
465465
let outcome = validator.validate_one(origin, pooled_tx);

crates/optimism/node/tests/it/priority.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl OpPayloadTransactions for CustomTxPriority {
6767
..Default::default()
6868
};
6969
let signature = sender.sign_transaction_sync(&mut end_of_block_tx).unwrap();
70-
let end_of_block_tx = RecoveredTx::from_signed_transaction(
70+
let end_of_block_tx = RecoveredTx::new_unchecked(
7171
OpTransactionSigned::new_unhashed(
7272
OpTypedTransaction::Eip1559(end_of_block_tx),
7373
signature,

crates/primitives/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ pub use reth_primitives_traits::{
4444
pub use static_file::StaticFileSegment;
4545

4646
pub use alloy_consensus::{
47-
transaction::{PooledTransaction, TransactionMeta},
47+
transaction::{PooledTransaction, Recovered as RecoveredTx, TransactionMeta},
4848
ReceiptWithBloom,
4949
};
5050
pub use transaction::{
5151
util::secp256k1::{public_key_to_address, recover_signer_unchecked, sign_message},
52-
InvalidTransactionError, PooledTransactionsElementEcRecovered, RecoveredTx, Transaction,
53-
TransactionSigned, TransactionSignedEcRecovered, TxType,
52+
InvalidTransactionError, PooledTransactionsElementEcRecovered, Transaction, TransactionSigned,
53+
TransactionSignedEcRecovered, TxType,
5454
};
5555

5656
// Re-exports

crates/primitives/src/transaction/mod.rs

Lines changed: 13 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Transaction types.
22
3+
use crate::RecoveredTx;
34
use alloc::vec::Vec;
45
pub use alloy_consensus::transaction::PooledTransaction;
56
use alloy_consensus::{
@@ -16,7 +17,7 @@ use alloy_eips::{
1617
use alloy_primitives::{
1718
keccak256, Address, Bytes, ChainId, PrimitiveSignature as Signature, TxHash, TxKind, B256, U256,
1819
};
19-
use alloy_rlp::{Decodable, Encodable, Error as RlpError, Header};
20+
use alloy_rlp::{Decodable, Encodable, Header};
2021
use core::hash::{Hash, Hasher};
2122
use derive_more::{AsRef, Deref};
2223
use once_cell as _;
@@ -912,15 +913,15 @@ impl TransactionSigned {
912913
/// Returns the [`RecoveredTx`] transaction with the given sender.
913914
#[inline]
914915
pub const fn with_signer(self, signer: Address) -> RecoveredTx<Self> {
915-
RecoveredTx::from_signed_transaction(self, signer)
916+
RecoveredTx::new_unchecked(self, signer)
916917
}
917918

918919
/// Consumes the type, recover signer and return [`RecoveredTx`]
919920
///
920921
/// Returns `None` if the transaction's signature is invalid, see also [`Self::recover_signer`].
921922
pub fn into_ecrecovered(self) -> Option<RecoveredTx<Self>> {
922923
let signer = self.recover_signer()?;
923-
Some(RecoveredTx { signed_transaction: self, signer })
924+
Some(RecoveredTx::new_unchecked(self, signer))
924925
}
925926

926927
/// Consumes the type, recover signer and return [`RecoveredTx`] _without
@@ -930,7 +931,7 @@ impl TransactionSigned {
930931
/// [`Self::recover_signer_unchecked`].
931932
pub fn into_ecrecovered_unchecked(self) -> Option<RecoveredTx<Self>> {
932933
let signer = self.recover_signer_unchecked()?;
933-
Some(RecoveredTx { signed_transaction: self, signer })
934+
Some(RecoveredTx::new_unchecked(self, signer))
934935
}
935936

936937
/// Tries to recover signer and return [`RecoveredTx`]. _without ensuring that
@@ -941,7 +942,7 @@ impl TransactionSigned {
941942
pub fn try_into_ecrecovered_unchecked(self) -> Result<RecoveredTx<Self>, Self> {
942943
match self.recover_signer_unchecked() {
943944
None => Err(self),
944-
Some(signer) => Ok(RecoveredTx { signed_transaction: self, signer }),
945+
Some(signer) => Ok(RecoveredTx::new_unchecked(self, signer)),
945946
}
946947
}
947948

@@ -1184,13 +1185,13 @@ impl alloy_consensus::Transaction for TransactionSigned {
11841185

11851186
impl From<RecoveredTx<Self>> for TransactionSigned {
11861187
fn from(recovered: RecoveredTx<Self>) -> Self {
1187-
recovered.signed_transaction
1188+
recovered.into_tx()
11881189
}
11891190
}
11901191

11911192
impl From<RecoveredTx<PooledTransaction>> for TransactionSigned {
11921193
fn from(recovered: RecoveredTx<PooledTransaction>) -> Self {
1193-
recovered.signed_transaction.into()
1194+
recovered.into_tx().into()
11941195
}
11951196
}
11961197

@@ -1521,105 +1522,12 @@ impl<'a> arbitrary::Arbitrary<'a> for TransactionSigned {
15211522
/// Type alias kept for backward compatibility.
15221523
pub type TransactionSignedEcRecovered<T = TransactionSigned> = RecoveredTx<T>;
15231524

1524-
/// Signed transaction with recovered signer.
1525-
#[derive(Debug, Clone, PartialEq, Hash, Eq, AsRef, Deref)]
1526-
pub struct RecoveredTx<T = TransactionSigned> {
1527-
/// Signer of the transaction
1528-
signer: Address,
1529-
/// Signed transaction
1530-
#[deref]
1531-
#[as_ref]
1532-
signed_transaction: T,
1533-
}
1534-
1535-
// === impl RecoveredTx ===
1536-
1537-
impl<T> RecoveredTx<T> {
1538-
/// Signer of transaction recovered from signature
1539-
pub const fn signer(&self) -> Address {
1540-
self.signer
1541-
}
1542-
1543-
/// Reference to the signer of transaction recovered from signature
1544-
pub const fn signer_ref(&self) -> &Address {
1545-
&self.signer
1546-
}
1547-
1548-
/// Returns a reference to [`TransactionSigned`]
1549-
pub const fn tx(&self) -> &T {
1550-
&self.signed_transaction
1551-
}
1552-
1553-
/// Transform back to [`TransactionSigned`]
1554-
pub fn into_tx(self) -> T {
1555-
self.signed_transaction
1556-
}
1557-
1558-
/// Dissolve Self to its component
1559-
pub fn into_parts(self) -> (T, Address) {
1560-
(self.signed_transaction, self.signer)
1561-
}
1562-
1563-
/// Create [`RecoveredTx`] from [`TransactionSigned`] and [`Address`] of the
1564-
/// signer.
1565-
#[inline]
1566-
pub const fn from_signed_transaction(signed_transaction: T, signer: Address) -> Self {
1567-
Self { signed_transaction, signer }
1568-
}
1569-
1570-
/// Applies the given closure to the inner transactions.
1571-
pub fn map_transaction<Tx>(self, f: impl FnOnce(T) -> Tx) -> RecoveredTx<Tx> {
1572-
RecoveredTx::from_signed_transaction(f(self.signed_transaction), self.signer)
1573-
}
1574-
}
1575-
1576-
impl<T: Encodable> Encodable for RecoveredTx<T> {
1577-
/// This encodes the transaction _with_ the signature, and an rlp header.
1578-
///
1579-
/// Refer to docs for [`TransactionSigned::encode`] for details on the exact format.
1580-
fn encode(&self, out: &mut dyn bytes::BufMut) {
1581-
self.signed_transaction.encode(out)
1582-
}
1583-
1584-
fn length(&self) -> usize {
1585-
self.signed_transaction.length()
1586-
}
1587-
}
1588-
1589-
impl<T: SignedTransaction> Decodable for RecoveredTx<T> {
1590-
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
1591-
let signed_transaction = T::decode(buf)?;
1592-
let signer = signed_transaction
1593-
.recover_signer()
1594-
.ok_or(RlpError::Custom("Unable to recover decoded transaction signer."))?;
1595-
Ok(Self { signer, signed_transaction })
1596-
}
1597-
}
1598-
1599-
impl<T: Encodable2718> Encodable2718 for RecoveredTx<T> {
1600-
fn type_flag(&self) -> Option<u8> {
1601-
self.signed_transaction.type_flag()
1602-
}
1603-
1604-
fn encode_2718_len(&self) -> usize {
1605-
self.signed_transaction.encode_2718_len()
1606-
}
1607-
1608-
fn encode_2718(&self, out: &mut dyn alloy_rlp::BufMut) {
1609-
self.signed_transaction.encode_2718(out)
1610-
}
1611-
1612-
fn trie_hash(&self) -> B256 {
1613-
self.signed_transaction.trie_hash()
1614-
}
1615-
}
1616-
16171525
/// Extension trait for [`SignedTransaction`] to convert it into [`RecoveredTx`].
16181526
pub trait SignedTransactionIntoRecoveredExt: SignedTransaction {
16191527
/// Tries to recover signer and return [`RecoveredTx`] by cloning the type.
16201528
fn try_ecrecovered(&self) -> Option<RecoveredTx<Self>> {
16211529
let signer = self.recover_signer()?;
1622-
Some(RecoveredTx { signed_transaction: self.clone(), signer })
1530+
Some(RecoveredTx::new_unchecked(self.clone(), signer))
16231531
}
16241532

16251533
/// Tries to recover signer and return [`RecoveredTx`].
@@ -1629,7 +1537,7 @@ pub trait SignedTransactionIntoRecoveredExt: SignedTransaction {
16291537
fn try_into_ecrecovered(self) -> Result<RecoveredTx<Self>, Self> {
16301538
match self.recover_signer() {
16311539
None => Err(self),
1632-
Some(signer) => Ok(RecoveredTx { signed_transaction: self, signer }),
1540+
Some(signer) => Ok(RecoveredTx::new_unchecked(self, signer)),
16331541
}
16341542
}
16351543

@@ -1639,12 +1547,12 @@ pub trait SignedTransactionIntoRecoveredExt: SignedTransaction {
16391547
/// Returns `None` if the transaction's signature is invalid.
16401548
fn into_ecrecovered_unchecked(self) -> Option<RecoveredTx<Self>> {
16411549
let signer = self.recover_signer_unchecked()?;
1642-
Some(RecoveredTx::from_signed_transaction(self, signer))
1550+
Some(RecoveredTx::new_unchecked(self, signer))
16431551
}
16441552

16451553
/// Returns the [`RecoveredTx`] transaction with the given sender.
16461554
fn with_signer(self, signer: Address) -> RecoveredTx<Self> {
1647-
RecoveredTx::from_signed_transaction(self, signer)
1555+
RecoveredTx::new_unchecked(self, signer)
16481556
}
16491557
}
16501558

@@ -1895,7 +1803,7 @@ where
18951803
mod tests {
18961804
use crate::{
18971805
transaction::{TxEip1559, TxKind, TxLegacy},
1898-
RecoveredTx, Transaction, TransactionSigned,
1806+
Transaction, TransactionSigned,
18991807
};
19001808
use alloy_consensus::Transaction as _;
19011809
use alloy_eips::eip2718::{Decodable2718, Encodable2718};
@@ -2148,17 +2056,6 @@ mod tests {
21482056
assert_eq!(encoded, input);
21492057
}
21502058

2151-
#[test]
2152-
fn test_decode_signed_ec_recovered_transaction() {
2153-
// random tx: <https://etherscan.io/getRawTx?tx=0x9448608d36e721ef403c53b00546068a6474d6cbab6816c3926de449898e7bce>
2154-
let input = hex!("02f871018302a90f808504890aef60826b6c94ddf4c5025d1a5742cf12f74eec246d4432c295e487e09c3bbcc12b2b80c080a0f21a4eacd0bf8fea9c5105c543be5a1d8c796516875710fafafdf16d16d8ee23a001280915021bb446d1973501a67f93d2b38894a514b976e7b46dc2fe54598d76");
2155-
let tx = TransactionSigned::decode(&mut &input[..]).unwrap();
2156-
let recovered = tx.into_ecrecovered().unwrap();
2157-
2158-
let decoded = RecoveredTx::decode(&mut &alloy_rlp::encode(&recovered)[..]).unwrap();
2159-
assert_eq!(recovered, decoded)
2160-
}
2161-
21622059
#[test]
21632060
fn test_decode_tx() {
21642061
// some random transactions pulled from hive tests

crates/primitives/src/transaction/pooled.rs

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,13 @@
11
//! Defines the types for blob transactions, legacy, and other EIP-2718 transactions included in a
22
//! response to `GetPooledTransactions`.
33
4-
use crate::{RecoveredTx, TransactionSigned};
4+
use crate::RecoveredTx;
55
use alloy_consensus::transaction::PooledTransaction;
6-
use alloy_eips::eip4844::BlobTransactionSidecar;
7-
use reth_primitives_traits::transaction::error::TransactionConversionError;
86

7+
// TODO: remove this foreign type
98
/// A signed pooled transaction with recovered signer.
109
pub type PooledTransactionsElementEcRecovered<T = PooledTransaction> = RecoveredTx<T>;
1110

12-
impl PooledTransactionsElementEcRecovered {
13-
/// Transform back to [`RecoveredTx`]
14-
pub fn into_ecrecovered_transaction(self) -> RecoveredTx<TransactionSigned> {
15-
let (tx, signer) = self.into_parts();
16-
RecoveredTx::from_signed_transaction(tx.into(), signer)
17-
}
18-
19-
/// Converts from an EIP-4844 [`RecoveredTx`] to a
20-
/// [`PooledTransactionsElementEcRecovered`] with the given sidecar.
21-
///
22-
/// Returns the transaction is not an EIP-4844 transaction.
23-
pub fn try_from_blob_transaction(
24-
tx: RecoveredTx<TransactionSigned>,
25-
sidecar: BlobTransactionSidecar,
26-
) -> Result<Self, RecoveredTx<TransactionSigned>> {
27-
let RecoveredTx { signer, signed_transaction } = tx;
28-
let transaction = signed_transaction
29-
.try_into_pooled_eip4844(sidecar)
30-
.map_err(|tx| RecoveredTx { signer, signed_transaction: tx })?;
31-
Ok(Self::from_signed_transaction(transaction, signer))
32-
}
33-
}
34-
35-
/// Converts a `Recovered` into a `PooledTransactionsElementEcRecovered`.
36-
impl TryFrom<RecoveredTx<TransactionSigned>> for PooledTransactionsElementEcRecovered {
37-
type Error = TransactionConversionError;
38-
39-
fn try_from(tx: RecoveredTx<TransactionSigned>) -> Result<Self, Self::Error> {
40-
match PooledTransaction::try_from(tx.signed_transaction) {
41-
Ok(pooled_transaction) => {
42-
Ok(Self::from_signed_transaction(pooled_transaction, tx.signer))
43-
}
44-
Err(_) => Err(TransactionConversionError::UnsupportedForP2P),
45-
}
46-
}
47-
}
48-
4911
#[cfg(test)]
5012
mod tests {
5113
use super::*;

crates/transaction-pool/src/test_utils/mock.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,7 +1047,8 @@ impl TryFrom<RecoveredTx<TransactionSigned>> for MockTransaction {
10471047

10481048
impl From<PooledTransactionsElementEcRecovered> for MockTransaction {
10491049
fn from(tx: PooledTransactionsElementEcRecovered) -> Self {
1050-
tx.into_ecrecovered_transaction().try_into().expect(
1050+
let (tx, signer) = tx.into_parts();
1051+
RecoveredTx::<TransactionSigned>::new_unchecked(tx.into(), signer).try_into().expect(
10511052
"Failed to convert from PooledTransactionsElementEcRecovered to MockTransaction",
10521053
)
10531054
}
@@ -1058,7 +1059,7 @@ impl From<MockTransaction> for RecoveredTx<TransactionSigned> {
10581059
let signed_tx =
10591060
TransactionSigned::new(tx.clone().into(), Signature::test_signature(), *tx.hash());
10601061

1061-
Self::from_signed_transaction(signed_tx, tx.sender())
1062+
Self::new_unchecked(signed_tx, tx.sender())
10621063
}
10631064
}
10641065

@@ -1180,7 +1181,7 @@ impl proptest::arbitrary::Arbitrary for MockTransaction {
11801181

11811182
arb::<(TransactionSigned, Address)>()
11821183
.prop_map(|(signed_transaction, signer)| {
1183-
RecoveredTx::from_signed_transaction(signed_transaction, signer)
1184+
RecoveredTx::new_unchecked(signed_transaction, signer)
11841185
.try_into()
11851186
.expect("Failed to create an Arbitrary MockTransaction via RecoveredTx")
11861187
})

0 commit comments

Comments
 (0)