33
44use super :: { derive_eip_155_chain_id, validate_eip155_chain_id} ;
55use crate :: eth:: { LEGACY_V_VALUE_27 , LEGACY_V_VALUE_28 } ;
6+ use crate :: rpc:: eth:: ApiEthTx ;
67use crate :: shim:: crypto:: Signature ;
78use crate :: shim:: fvm_shared_latest;
89use anyhow:: { Context , bail, ensure} ;
@@ -13,6 +14,7 @@ use num::{BigInt, Signed as _, bigint::Sign};
1314use num_derive:: FromPrimitive ;
1415use num_traits:: cast:: ToPrimitive ;
1516use rlp:: Rlp ;
17+ use spire_enum:: prelude:: delegated_enum;
1618
1719use 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 ) ]
6467pub 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
7073impl 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.
225226pub 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
394395fn 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 ! (
0 commit comments