Skip to content

Commit cc2c2cc

Browse files
authored
refactor: simplify EthTx implementation (#6760)
1 parent 37418a6 commit cc2c2cc

File tree

5 files changed

+55
-67
lines changed

5 files changed

+55
-67
lines changed

src/eth/transaction.rs

Lines changed: 51 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
use super::{derive_eip_155_chain_id, validate_eip155_chain_id};
55
use crate::eth::{LEGACY_V_VALUE_27, LEGACY_V_VALUE_28};
6+
use crate::rpc::eth::ApiEthTx;
67
use crate::shim::crypto::Signature;
78
use crate::shim::fvm_shared_latest;
89
use anyhow::{Context, bail, ensure};
@@ -13,6 +14,7 @@ use num::{BigInt, Signed as _, bigint::Sign};
1314
use num_derive::FromPrimitive;
1415
use num_traits::cast::ToPrimitive;
1516
use rlp::Rlp;
17+
use spire_enum::prelude::delegated_enum;
1618

1719
use crate::{
1820
message::{Message as _, SignedMessage},
@@ -60,11 +62,12 @@ pub enum EVMMethod {
6062

6163
/// Ethereum transaction which can be of different types.
6264
/// The currently supported types are defined in [FIP-0091](https://github.com/filecoin-project/FIPs/blob/020bcb412ee20a2879b4a710337959c51b938d3b/FIPS/fip-0091.md).
65+
#[delegated_enum(impl_conversions)]
6366
#[derive(Debug)]
6467
pub enum EthTx {
65-
Homestead(Box<EthLegacyHomesteadTxArgs>),
66-
Eip1559(Box<EthEip1559TxArgs>),
67-
Eip155(Box<EthLegacyEip155TxArgs>),
68+
Homestead(EthLegacyHomesteadTxArgs),
69+
Eip1559(EthEip1559TxArgs),
70+
Eip155(EthLegacyEip155TxArgs),
6871
}
6972

7073
impl EthTx {
@@ -85,33 +88,29 @@ impl EthTx {
8588
let valid_eip_155_signature_lengths = calc_valid_eip155_sig_len(eth_chain_id);
8689

8790
let tx: Self = if sig_len == EIP_1559_SIG_LEN {
88-
let args = EthEip1559TxArgsBuilder::default()
91+
EthEip1559TxArgsBuilder::default()
8992
.chain_id(eth_chain_id)
9093
.unsigned_message(msg.message())?
9194
.build()?
92-
.with_signature(msg.signature())?;
93-
EthTx::Eip1559(Box::new(args))
95+
.with_signature(msg.signature())?
96+
.into()
9497
} else if sig_len == HOMESTEAD_SIG_LEN
9598
|| sig_len == valid_eip_155_signature_lengths.0 as usize
9699
|| sig_len == valid_eip_155_signature_lengths.1 as usize
97100
{
98101
// process based on the first byte of the signature
99102
match *msg.signature().bytes().first().expect("infallible") {
100-
HOMESTEAD_SIG_PREFIX => {
101-
let args = EthLegacyHomesteadTxArgsBuilder::default()
102-
.unsigned_message(msg.message())?
103-
.build()?
104-
.with_signature(msg.signature())?;
105-
EthTx::Homestead(Box::new(args))
106-
}
107-
EIP_155_SIG_PREFIX => {
108-
let args = EthLegacyEip155TxArgsBuilder::default()
109-
.chain_id(eth_chain_id)
110-
.unsigned_message(msg.message())?
111-
.build()?
112-
.with_signature(msg.signature())?;
113-
EthTx::Eip155(Box::new(args))
114-
}
103+
HOMESTEAD_SIG_PREFIX => EthLegacyHomesteadTxArgsBuilder::default()
104+
.unsigned_message(msg.message())?
105+
.build()?
106+
.with_signature(msg.signature())?
107+
.into(),
108+
EIP_155_SIG_PREFIX => EthLegacyEip155TxArgsBuilder::default()
109+
.chain_id(eth_chain_id)
110+
.unsigned_message(msg.message())?
111+
.build()?
112+
.with_signature(msg.signature())?
113+
.into(),
115114
_ => bail!("unsupported signature prefix"),
116115
}
117116
} else {
@@ -128,9 +127,9 @@ impl EthTx {
128127
pub fn get_signed_message(&self, eth_chain_id: EthChainId) -> anyhow::Result<SignedMessage> {
129128
let from = self.sender(eth_chain_id)?;
130129
let msg = match self {
131-
Self::Homestead(tx) => (*tx).get_signed_message(from)?,
132-
Self::Eip1559(tx) => (*tx).get_signed_message(from, eth_chain_id)?,
133-
Self::Eip155(tx) => (*tx).get_signed_message(from, eth_chain_id)?,
130+
Self::Homestead(tx) => tx.get_signed_message(from)?,
131+
Self::Eip1559(tx) => tx.get_signed_message(from, eth_chain_id)?,
132+
Self::Eip155(tx) => tx.get_signed_message(from, eth_chain_id)?,
134133
};
135134
Ok(msg)
136135
}
@@ -141,34 +140,30 @@ impl EthTx {
141140
eth_chain_id: EthChainId,
142141
) -> anyhow::Result<Message> {
143142
let msg = match self {
144-
Self::Homestead(tx) => (*tx).get_unsigned_message(from)?,
145-
Self::Eip1559(tx) => (*tx).get_unsigned_message(from, eth_chain_id)?,
146-
Self::Eip155(tx) => (*tx).get_unsigned_message(from, eth_chain_id)?,
143+
Self::Homestead(tx) => tx.get_unsigned_message(from)?,
144+
Self::Eip1559(tx) => tx.get_unsigned_message(from, eth_chain_id)?,
145+
Self::Eip155(tx) => tx.get_unsigned_message(from, eth_chain_id)?,
147146
};
148147
Ok(msg)
149148
}
150149

151150
pub fn rlp_unsigned_message(&self, eth_chain_id: EthChainId) -> anyhow::Result<Vec<u8>> {
152151
match self {
153-
Self::Homestead(tx) => (*tx).rlp_unsigned_message(),
154-
Self::Eip1559(tx) => (*tx).rlp_unsigned_message(),
155-
Self::Eip155(tx) => (*tx).rlp_unsigned_message(eth_chain_id),
152+
Self::Homestead(tx) => tx.rlp_unsigned_message(),
153+
Self::Eip1559(tx) => tx.rlp_unsigned_message(),
154+
Self::Eip155(tx) => tx.rlp_unsigned_message(eth_chain_id),
156155
}
157156
}
158157

159158
pub fn rlp_signed_message(&self) -> anyhow::Result<Vec<u8>> {
160-
match self {
161-
Self::Homestead(tx) => (*tx).rlp_signed_message(),
162-
Self::Eip1559(tx) => (*tx).rlp_signed_message(),
163-
Self::Eip155(tx) => (*tx).rlp_signed_message(),
164-
}
159+
delegate_eth_tx!(self.rlp_signed_message())
165160
}
166161

167162
fn signature(&self, eth_chain_id: EthChainId) -> anyhow::Result<Signature> {
168163
match self {
169-
Self::Homestead(tx) => (*tx).signature(),
170-
Self::Eip1559(tx) => (*tx).signature(),
171-
Self::Eip155(tx) => (*tx).signature(eth_chain_id),
164+
Self::Homestead(tx) => tx.signature(),
165+
Self::Eip1559(tx) => tx.signature(),
166+
Self::Eip155(tx) => tx.signature(eth_chain_id),
172167
}
173168
}
174169

@@ -178,9 +173,9 @@ impl EthTx {
178173
eth_chain_id: EthChainId,
179174
) -> anyhow::Result<Vec<u8>> {
180175
match self {
181-
Self::Homestead(tx) => (*tx).to_verifiable_signature(sig),
182-
Self::Eip1559(tx) => (*tx).to_verifiable_signature(sig),
183-
Self::Eip155(tx) => (*tx).to_verifiable_signature(sig, eth_chain_id),
176+
Self::Homestead(tx) => tx.to_verifiable_signature(sig),
177+
Self::Eip1559(tx) => tx.to_verifiable_signature(sig),
178+
Self::Eip155(tx) => tx.to_verifiable_signature(sig, eth_chain_id),
184179
}
185180
}
186181

@@ -221,6 +216,12 @@ impl EthTx {
221216
}
222217
}
223218

219+
impl From<EthTx> for ApiEthTx {
220+
fn from(value: EthTx) -> Self {
221+
delegate_eth_tx!(value.into())
222+
}
223+
}
224+
224225
/// Checks if a signed Filecoin message is valid for sending to Ethereum.
225226
pub fn is_valid_eth_tx_for_sending(
226227
eth_chain_id: EthChainId,
@@ -388,7 +389,7 @@ fn parse_eip1559_tx(data: &[u8]) -> anyhow::Result<EthTx> {
388389
s,
389390
};
390391

391-
Ok(EthTx::Eip1559(Box::new(tx_args)))
392+
Ok(tx_args.into())
392393
}
393394

394395
fn parse_legacy_tx(data: &[u8]) -> anyhow::Result<EthTx> {
@@ -441,13 +442,13 @@ fn parse_legacy_tx(data: &[u8]) -> anyhow::Result<EthTx> {
441442
r,
442443
s,
443444
};
444-
return Ok(EthTx::Homestead(Box::new(tx_args)));
445+
return Ok(tx_args.into());
445446
}
446447

447448
// For EIP-155 transactions, validate chain ID protection
448449
validate_eip155_chain_id(chain_id, &v)?;
449450

450-
Ok(EthTx::Eip155(Box::new(EthLegacyEip155TxArgs {
451+
Ok(EthLegacyEip155TxArgs {
451452
chain_id,
452453
nonce,
453454
gas_price,
@@ -458,7 +459,8 @@ fn parse_legacy_tx(data: &[u8]) -> anyhow::Result<EthTx> {
458459
v,
459460
r,
460461
s,
461-
})))
462+
}
463+
.into())
462464
}
463465

464466
#[derive(Debug)]
@@ -763,7 +765,7 @@ pub(crate) mod tests {
763765
"7820796778417228639067439047870612492553874254089570360061550763595363987236",
764766
)
765767
.unwrap();
766-
let tx = EthTx::Eip1559(Box::new(tx_args));
768+
let tx = EthTx::from(tx_args);
767769
let sig = tx.signature(calibnet::ETH_CHAIN_ID);
768770
assert!(sig.is_ok());
769771
assert!(
@@ -807,7 +809,7 @@ pub(crate) mod tests {
807809
16,
808810
)
809811
.unwrap();
810-
let tx = EthTx::Eip155(Box::new(tx_args));
812+
let tx = EthTx::from(tx_args);
811813
let sig = tx.signature(calibnet::ETH_CHAIN_ID);
812814
assert!(sig.is_ok());
813815
assert!(
@@ -852,15 +854,15 @@ pub(crate) mod tests {
852854
16,
853855
)
854856
.unwrap();
855-
let tx = EthTx::Homestead(Box::new(tx_args.clone()));
857+
let tx = EthTx::from(tx_args.clone());
856858
let expected_hash = ethereum_types::H256::from_str(
857859
"0x3ebc897150feeff6caa1b2e5992e347e8409e9e35fa30f7f5f8fcda3f7c965c7",
858860
)
859861
.unwrap();
860862
assert_eq!(expected_hash, tx.eth_hash().unwrap());
861863
// Note: `v` value 27 is for homestead
862864
tx_args.v = BigInt::from_str_radix("1b", 16).unwrap();
863-
let tx = EthTx::Homestead(Box::new(tx_args.clone()));
865+
let tx = EthTx::from(tx_args.clone());
864866
let sig = tx.signature(calibnet::ETH_CHAIN_ID);
865867
assert!(sig.is_ok());
866868
assert!(

src/rpc/methods/eth/eth_tx.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,3 @@ impl From<EthEip1559TxArgs> for ApiEthTx {
102102
}
103103
}
104104
}
105-
106-
impl From<EthTx> for ApiEthTx {
107-
fn from(value: EthTx) -> Self {
108-
use EthTx::*;
109-
match value {
110-
Homestead(tx) => (*tx).into(),
111-
Eip1559(tx) => (*tx).into(),
112-
Eip155(tx) => (*tx).into(),
113-
}
114-
}
115-
}

src/shim/crypto.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,7 @@ mod tests {
353353

354354
// Create a base EIP-1559 transaction
355355
fn create_eip1559_tx() -> EthTx {
356-
EthTx::Eip1559(Box::new(
357-
EthEip1559TxArgsBuilder::default()
356+
EthEip1559TxArgsBuilder::default()
358357
.chain_id(TEST_CHAIN_ID)
359358
.nonce(486_u64)
360359
.to(Some(ethereum_types::H160::from_str("0xeb4a9cdb9f42d3a503d580a39b6e3736eb21fffd").unwrap().into()))
@@ -364,9 +363,7 @@ mod tests {
364363
.gas_limit(37442471_u64)
365364
.input(hex::decode("383487be000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000660d4d120000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000003b6261666b726569656f6f75326d36356276376561786e7767656d7562723675787269696867366474646e6c7a663469616f37686c6e6a6d647372750000000000").unwrap())
366365
.build()
367-
.unwrap()
368-
)
369-
)
366+
.unwrap().into()
370367
}
371368

372369
fn create_signed_message(signature_type: SignatureType) -> (Address, SignedMessage) {

src/tool/subcommands/api_cmd/stateful_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ async fn invoke_contract(client: &rpc::Client, tx: &TestTransaction) -> anyhow::
347347
.unsigned_message(&unsigned_msg.message)?
348348
.build()
349349
.map_err(|e| anyhow::anyhow!("Failed to build EIP-1559 transaction: {}", e))?;
350-
let eth_tx = crate::eth::EthTx::Eip1559(Box::new(eth_tx_args));
350+
let eth_tx = crate::eth::EthTx::from(eth_tx_args);
351351
let data = eth_tx.rlp_unsigned_message(ETH_CHAIN_ID)?;
352352

353353
let sig = client.call(WalletSign::request((tx.from, data))?).await?;

src/wallet/subcommands/wallet_cmd.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ impl WalletCommands {
559559
.chain_id(eth_chain_id)
560560
.unsigned_message(&message)?
561561
.build()?;
562-
let eth_tx = EthTx::Eip1559(Box::new(eth_tx_args));
562+
let eth_tx = EthTx::from(eth_tx_args);
563563
let sig = crate::key_management::sign(
564564
sig_type,
565565
key.key_info.private_key(),

0 commit comments

Comments
 (0)