From 437b572dfacb5252161bee4a40b2a42ea1fd9b50 Mon Sep 17 00:00:00 2001 From: Dustin Xie Date: Mon, 22 Apr 2024 17:41:15 -0700 Subject: [PATCH] [action] pass tx type to ToEthTx() method --- action/action.go | 3 +- action/builder_test.go | 2 +- action/candidate_activate.go | 22 ++++++----- action/candidate_endorsement.go | 22 ++++++----- action/candidate_register.go | 21 ++++++----- action/candidate_transfer_ownership.go | 22 ++++++----- action/candidate_transfer_ownership_test.go | 6 +-- action/candidate_update.go | 21 ++++++----- action/claimreward.go | 21 ++++++----- action/claimreward_test.go | 4 +- action/depositreward.go | 21 ++++++----- action/depositreward_test.go | 4 +- action/evm_transaction.go | 6 ++- action/execution.go | 39 +++++--------------- action/grantreward.go | 21 ++++++----- action/grantreward_test.go | 2 +- action/rlp_tx.go | 34 +++++++++++++++++ action/rlp_tx_test.go | 29 ++++++++------- action/sealedenvelope.go | 6 +-- action/sealedenvelope_test.go | 2 +- action/stake_adddeposit.go | 21 ++++++----- action/stake_changecandidate.go | 21 ++++++----- action/stake_create.go | 21 ++++++----- action/stake_migrate.go | 21 ++++++----- action/stake_reclaim.go | 41 ++++++++++++--------- action/stake_restake.go | 21 ++++++----- action/stake_transferownership.go | 21 ++++++----- action/transfer.go | 23 +++++++----- api/web3server_utils.go | 4 +- 29 files changed, 288 insertions(+), 214 deletions(-) diff --git a/action/action.go b/action/action.go index 9a841957f5..d65f536826 100644 --- a/action/action.go +++ b/action/action.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/iotexproject/go-pkgs/crypto" + "github.com/iotexproject/iotex-proto/golang/iotextypes" "github.com/pkg/errors" ) @@ -24,7 +25,7 @@ type ( // EthCompatibleAction is the action which is compatible to be converted to eth tx EthCompatibleAction interface { - ToEthTx(uint32) (*types.Transaction, error) + ToEthTx(uint32, iotextypes.Encoding) (*types.Transaction, error) } TxContainer interface { diff --git a/action/builder_test.go b/action/builder_test.go index bdbb92171f..811aea4505 100644 --- a/action/builder_test.go +++ b/action/builder_test.go @@ -167,7 +167,7 @@ func TestEthTxUtils(t *testing.T) { SetAddress(addr). SetData([]byte("any")). SetAmount(big.NewInt(1)).Build() - tx, _ := act.ToEthTx(chainID) + tx, _ := act.ToEthTx(chainID, iotextypes.Encoding_ETHEREUM_EIP155) var ( signer1, _ = NewEthSigner(iotextypes.Encoding_ETHEREUM_EIP155, chainID) diff --git a/action/candidate_activate.go b/action/candidate_activate.go index 2ba644547f..f31307d56c 100644 --- a/action/candidate_activate.go +++ b/action/candidate_activate.go @@ -2,6 +2,7 @@ package action import ( "bytes" + "fmt" "math/big" "strings" @@ -37,6 +38,8 @@ const ( var ( candidateActivateMethod abi.Method + _ EthCompatibleAction = (*CandidateActivate)(nil) + _ TxDataBasic = (*CandidateActivate)(nil) ) // CandidateActivate is the action to update a candidate's bucket @@ -102,19 +105,20 @@ func (cr *CandidateActivate) encodeABIBinary() ([]byte, error) { } // ToEthTx returns an Ethereum transaction which corresponds to this action -func (cr *CandidateActivate) ToEthTx(_ uint32) (*types.Transaction, error) { +func (cr *CandidateActivate) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { data, err := cr.encodeABIBinary() if err != nil { return nil, err } - return types.NewTx(&types.LegacyTx{ - Nonce: cr.Nonce(), - GasPrice: cr.GasPrice(), - Gas: cr.GasLimit(), - To: &_stakingProtocolEthAddr, - Value: big.NewInt(0), - Data: data, - }), nil + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + return stakingToLegacyTx(cr, data), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) + } } // NewCandidateActivate returns a CandidateActivate action diff --git a/action/candidate_endorsement.go b/action/candidate_endorsement.go index 1ed59d014c..4a174882bc 100644 --- a/action/candidate_endorsement.go +++ b/action/candidate_endorsement.go @@ -2,6 +2,7 @@ package action import ( "bytes" + "fmt" "math/big" "strings" @@ -95,6 +96,8 @@ var ( candidateEndorsementEndorseMethod abi.Method caniddateEndorsementIntentToRevokeMethod abi.Method candidateEndorsementRevokeMethod abi.Method + _ EthCompatibleAction = (*CandidateEndorsement)(nil) + _ TxDataBasic = (*CandidateEndorsement)(nil) ) type ( @@ -220,19 +223,20 @@ func (act *CandidateEndorsement) encodeABIBinary() ([]byte, error) { } // ToEthTx returns an Ethereum transaction which corresponds to this action -func (act *CandidateEndorsement) ToEthTx(_ uint32) (*types.Transaction, error) { +func (act *CandidateEndorsement) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { data, err := act.encodeABIBinary() if err != nil { return nil, err } - return types.NewTx(&types.LegacyTx{ - Nonce: act.Nonce(), - GasPrice: act.GasPrice(), - Gas: act.GasLimit(), - To: &_stakingProtocolEthAddr, - Value: big.NewInt(0), - Data: data, - }), nil + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + return stakingToLegacyTx(act, data), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) + } } // NewCandidateEndorsementLegacy returns a CandidateEndorsement action diff --git a/action/candidate_register.go b/action/candidate_register.go index 7c8e3ec974..f7e9f49047 100644 --- a/action/candidate_register.go +++ b/action/candidate_register.go @@ -7,6 +7,7 @@ package action import ( "bytes" + "fmt" "math/big" "strings" @@ -94,6 +95,7 @@ var ( ErrInvalidOwner = errors.New("invalid owner address") _ EthCompatibleAction = (*CandidateRegister)(nil) + _ TxDataBasic = (*CandidateRegister)(nil) ) // CandidateRegister is the action to register a candidate @@ -384,19 +386,20 @@ func ethAddrToNativeAddr(in interface{}) (address.Address, error) { } // ToEthTx converts action to eth-compatible tx -func (cr *CandidateRegister) ToEthTx(_ uint32) (*types.Transaction, error) { +func (cr *CandidateRegister) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { data, err := cr.encodeABIBinary() if err != nil { return nil, err } - return types.NewTx(&types.LegacyTx{ - Nonce: cr.Nonce(), - GasPrice: cr.GasPrice(), - Gas: cr.GasLimit(), - To: &_stakingProtocolEthAddr, - Value: big.NewInt(0), - Data: data, - }), nil + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + return stakingToLegacyTx(cr, data), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) + } } // IsValidCandidateName check if a candidate name string is valid. diff --git a/action/candidate_transfer_ownership.go b/action/candidate_transfer_ownership.go index b756c56aae..d2f34ed9d0 100644 --- a/action/candidate_transfer_ownership.go +++ b/action/candidate_transfer_ownership.go @@ -2,6 +2,7 @@ package action import ( "bytes" + "fmt" "math/big" "strings" @@ -47,6 +48,8 @@ const ( var ( // _candidateTransferOwnershipMethod is the interface of the abi encoding of candidate transfer ownership action _candidateTransferOwnershipMethod abi.Method + _ EthCompatibleAction = (*CandidateTransferOwnership)(nil) + _ TxDataBasic = (*CandidateTransferOwnership)(nil) ) func init() { @@ -190,17 +193,18 @@ func (act *CandidateTransferOwnership) SanityCheck() error { } // ToEthTx returns an Ethereum transaction which corresponds to this action -func (act *CandidateTransferOwnership) ToEthTx(_ uint32) (*types.Transaction, error) { +func (act *CandidateTransferOwnership) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { data, err := act.encodeABIBinary() if err != nil { return nil, err } - return types.NewTx(&types.LegacyTx{ - Nonce: act.Nonce(), - GasPrice: act.GasPrice(), - Gas: act.GasLimit(), - To: &_stakingProtocolEthAddr, - Value: big.NewInt(0), - Data: data, - }), nil + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + return stakingToLegacyTx(act, data), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) + } } diff --git a/action/candidate_transfer_ownership_test.go b/action/candidate_transfer_ownership_test.go index 9688b65c56..51f3718510 100644 --- a/action/candidate_transfer_ownership_test.go +++ b/action/candidate_transfer_ownership_test.go @@ -5,11 +5,11 @@ import ( "math/big" "testing" + "github.com/iotexproject/iotex-address/address" + "github.com/iotexproject/iotex-proto/golang/iotextypes" "github.com/pkg/errors" "github.com/stretchr/testify/require" - "github.com/iotexproject/iotex-address/address" - "github.com/iotexproject/iotex-core/pkg/util/byteutil" ) @@ -133,7 +133,7 @@ func TestCandidateTransferOwnershipToEthTx(t *testing.T) { require := require.New(t) cr, err := NewCandidateTransferOwnership(1, 1000000, big.NewInt(1000), "io10a298zmzvrt4guq79a9f4x7qedj59y7ery84he", []byte("payload")) require.NoError(err) - ethTx, err := cr.ToEthTx(0) + ethTx, err := cr.ToEthTx(0, iotextypes.Encoding_ETHEREUM_EIP155) require.NoError(err) require.NotNil(ethTx) require.Equal(byteutil.Must(cr.EncodeABIBinary()), ethTx.Data()) diff --git a/action/candidate_update.go b/action/candidate_update.go index 7e7d39caf1..e675146648 100644 --- a/action/candidate_update.go +++ b/action/candidate_update.go @@ -7,6 +7,7 @@ package action import ( "bytes" + "fmt" "math/big" "strings" @@ -57,6 +58,7 @@ var ( // _candidateUpdateMethod is the interface of the abi encoding of stake action _candidateUpdateMethod abi.Method _ EthCompatibleAction = (*CandidateUpdate)(nil) + _ TxDataBasic = (*CandidateUpdate)(nil) ) // CandidateUpdate is the action to update a candidate @@ -244,17 +246,18 @@ func NewCandidateUpdateFromABIBinary(data []byte) (*CandidateUpdate, error) { } // ToEthTx converts action to eth-compatible tx -func (cu *CandidateUpdate) ToEthTx(_ uint32) (*types.Transaction, error) { +func (cu *CandidateUpdate) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { data, err := cu.encodeABIBinary() if err != nil { return nil, err } - return types.NewTx(&types.LegacyTx{ - Nonce: cu.Nonce(), - GasPrice: cu.GasPrice(), - Gas: cu.GasLimit(), - To: &_stakingProtocolEthAddr, - Value: big.NewInt(0), - Data: data, - }), nil + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + return stakingToLegacyTx(cu, data), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) + } } diff --git a/action/claimreward.go b/action/claimreward.go index b7852b1e30..57be8e5f84 100644 --- a/action/claimreward.go +++ b/action/claimreward.go @@ -7,6 +7,7 @@ package action import ( "bytes" + "fmt" "math/big" "strings" @@ -73,6 +74,7 @@ var ( _claimRewardingMethodV1 abi.Method _claimRewardingMethodV2 abi.Method _ EthCompatibleAction = (*ClaimFromRewardingFund)(nil) + _ TxDataBasic = (*ClaimFromRewardingFund)(nil) errWrongMethodSig = errors.New("wrong method signature") ) @@ -225,19 +227,20 @@ func (c *ClaimFromRewardingFund) encodeABIBinary() ([]byte, error) { } // ToEthTx converts action to eth-compatible tx -func (c *ClaimFromRewardingFund) ToEthTx(_ uint32) (*types.Transaction, error) { +func (c *ClaimFromRewardingFund) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { data, err := c.encodeABIBinary() if err != nil { return nil, err } - return types.NewTx(&types.LegacyTx{ - Nonce: c.Nonce(), - GasPrice: c.GasPrice(), - Gas: c.GasLimit(), - To: &_rewardingProtocolEthAddr, - Value: big.NewInt(0), - Data: data, - }), nil + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + return rewardingToLegacyTx(c, data), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) + } } // NewClaimFromRewardingFundFromABIBinary decodes data into action diff --git a/action/claimreward_test.go b/action/claimreward_test.go index 261b882680..c2df635352 100644 --- a/action/claimreward_test.go +++ b/action/claimreward_test.go @@ -92,7 +92,7 @@ func TestClaimRewardToEthTx(t *testing.T) { builder.SetAmount(big.NewInt(101)) rc := builder.Build() - tx, err := rc.ToEthTx(0) + tx, err := rc.ToEthTx(0, 0) r.NoError(err) r.Equal(tx.To().String(), _rewardingProtocolEthAddr.String()) r.Equal(tx.Data()[:4], _claimRewardingMethodV1.ID) @@ -105,7 +105,7 @@ func TestClaimRewardToEthTx(t *testing.T) { builder.SetData([]byte{1, 2, 3}) builder.SetAddress(addr) rc = builder.Build() - tx, err = rc.ToEthTx(0) + tx, err = rc.ToEthTx(0, iotextypes.Encoding_ETHEREUM_EIP155) r.NoError(err) r.Equal(tx.Data()[:4], _claimRewardingMethodV2.ID) r.Equal(tx.Value().String(), "0") diff --git a/action/depositreward.go b/action/depositreward.go index 724b64acfb..b538c0cad2 100644 --- a/action/depositreward.go +++ b/action/depositreward.go @@ -7,6 +7,7 @@ package action import ( "bytes" + "fmt" "math/big" "strings" @@ -48,6 +49,7 @@ var ( _depositRewardMethod abi.Method _ EthCompatibleAction = (*DepositToRewardingFund)(nil) + _ TxDataBasic = (*DepositToRewardingFund)(nil) ) func init() { @@ -159,19 +161,20 @@ func (d *DepositToRewardingFund) encodeABIBinary() ([]byte, error) { } // ToEthTx converts action to eth-compatible tx -func (d *DepositToRewardingFund) ToEthTx(_ uint32) (*types.Transaction, error) { +func (d *DepositToRewardingFund) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { data, err := d.encodeABIBinary() if err != nil { return nil, err } - return types.NewTx(&types.LegacyTx{ - Nonce: d.Nonce(), - GasPrice: d.GasPrice(), - Gas: d.GasLimit(), - To: &_rewardingProtocolEthAddr, - Value: big.NewInt(0), - Data: data, - }), nil + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + return rewardingToLegacyTx(d, data), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) + } } // NewDepositToRewardingFundFromABIBinary decodes data into action diff --git a/action/depositreward_test.go b/action/depositreward_test.go index 1329231946..fd4e313120 100644 --- a/action/depositreward_test.go +++ b/action/depositreward_test.go @@ -104,7 +104,7 @@ func TestDepositRewardToEthTx(t *testing.T) { rp := &DepositToRewardingFund{} rp.amount = big.NewInt(101) - tx, err := rp.ToEthTx(0) + tx, err := rp.ToEthTx(0, 0) r.NoError(err) r.EqualValues(_rewardingProtocolEthAddr, *tx.To()) r.EqualValues( @@ -114,7 +114,7 @@ func TestDepositRewardToEthTx(t *testing.T) { r.EqualValues("0", tx.Value().String()) rp.data = []byte{1, 2, 3} - tx, err = rp.ToEthTx(0) + tx, err = rp.ToEthTx(0, 0) r.NoError(err) r.EqualValues(_rewardingProtocolEthAddr, *tx.To()) r.EqualValues( diff --git a/action/evm_transaction.go b/action/evm_transaction.go index 8264448e67..18e48a39af 100644 --- a/action/evm_transaction.go +++ b/action/evm_transaction.go @@ -22,10 +22,14 @@ type ( inner TxData } - TxData interface { + TxDataBasic interface { Nonce() uint64 GasLimit() uint64 GasPrice() *big.Int + } + + TxData interface { + TxDataBasic Amount() *big.Int To() *common.Address Data() []byte diff --git a/action/execution.go b/action/execution.go index f7b993180d..fe5000e5a7 100644 --- a/action/execution.go +++ b/action/execution.go @@ -7,6 +7,7 @@ package action import ( "encoding/hex" + "fmt" "math/big" "github.com/ethereum/go-ethereum/common" @@ -16,7 +17,6 @@ import ( "github.com/pkg/errors" "google.golang.org/protobuf/proto" - "github.com/iotexproject/iotex-core/pkg/util/addrutil" "github.com/iotexproject/iotex-core/pkg/util/byteutil" "github.com/iotexproject/iotex-core/pkg/version" ) @@ -250,33 +250,14 @@ func (ex *Execution) SanityCheck() error { } // ToEthTx converts action to eth-compatible tx -func (ex *Execution) ToEthTx(evmNetworkID uint32) (*types.Transaction, error) { - var ethAddr *common.Address - if ex.contract != EmptyAddress { - addr, err := addrutil.IoAddrToEvmAddr(ex.contract) - if err != nil { - return nil, err - } - ethAddr = &addr - } - if len(ex.accessList) > 0 { - return types.NewTx(&types.AccessListTx{ - ChainID: big.NewInt(int64(evmNetworkID)), - Nonce: ex.Nonce(), - GasPrice: ex.GasPrice(), - Gas: ex.GasLimit(), - To: ethAddr, - Value: ex.amount, - Data: ex.data, - AccessList: ex.accessList, - }), nil +func (ex *Execution) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + return toLegacyTx(ex), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) } - return types.NewTx(&types.LegacyTx{ - Nonce: ex.Nonce(), - GasPrice: ex.GasPrice(), - Gas: ex.GasLimit(), - To: ethAddr, - Value: ex.amount, - Data: ex.data, - }), nil } diff --git a/action/grantreward.go b/action/grantreward.go index b0a9065458..dcafc7effa 100644 --- a/action/grantreward.go +++ b/action/grantreward.go @@ -6,6 +6,7 @@ package action import ( + "fmt" "math/big" "strings" @@ -20,6 +21,7 @@ import ( var ( _grantRewardMethod abi.Method _ EthCompatibleAction = (*GrantReward)(nil) + _ TxDataBasic = (*GrantReward)(nil) ) const ( @@ -136,19 +138,20 @@ func (g *GrantReward) encodeABIBinary() ([]byte, error) { } // ToEthTx converts a grant reward action to an ethereum transaction -func (g *GrantReward) ToEthTx(_ uint32) (*types.Transaction, error) { +func (g *GrantReward) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { data, err := g.encodeABIBinary() if err != nil { return nil, err } - return types.NewTx(&types.LegacyTx{ - Nonce: g.Nonce(), - GasPrice: g.GasPrice(), - Gas: g.GasLimit(), - To: &_rewardingProtocolEthAddr, - Data: data, - Value: big.NewInt(0), - }), nil + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + return rewardingToLegacyTx(g, data), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) + } } // GrantRewardBuilder is the struct to build GrantReward diff --git a/action/grantreward_test.go b/action/grantreward_test.go index f6b162744a..a867f67548 100644 --- a/action/grantreward_test.go +++ b/action/grantreward_test.go @@ -32,7 +32,7 @@ func TestGrandReward(t *testing.T) { cost, err := g.Cost() require.NoError(err) require.Equal(big.NewInt(0), cost) - ethTx, err := g.ToEthTx(0) + ethTx, err := g.ToEthTx(0, 0) require.NoError(err) require.NotNil(ethTx) require.Equal(byteutil.Must(g.EncodeABIBinary()), ethTx.Data()) diff --git a/action/rlp_tx.go b/action/rlp_tx.go index 08b280438c..16c3e76512 100644 --- a/action/rlp_tx.go +++ b/action/rlp_tx.go @@ -5,6 +5,7 @@ import ( "math/big" "strings" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/iotexproject/go-pkgs/crypto" "github.com/iotexproject/go-pkgs/hash" @@ -120,3 +121,36 @@ func ExtractTypeSigPubkey(tx *types.Transaction) (iotextypes.Encoding, []byte, c pubkey, err = crypto.RecoverPubkey(rawHash[:], sig) return encoding, sig, pubkey, err } + +// ====================================== +// utility funcs to convert native action to eth tx +// ====================================== +func stakingToLegacyTx(basic TxDataBasic, data []byte) *types.Transaction { + return basicToLegacyTx(basic, &_stakingProtocolEthAddr, &big.Int{}, data) +} + +func rewardingToLegacyTx(basic TxDataBasic, data []byte) *types.Transaction { + return basicToLegacyTx(basic, &_rewardingProtocolEthAddr, &big.Int{}, data) +} + +func basicToLegacyTx(basic TxDataBasic, to *common.Address, value *big.Int, data []byte) *types.Transaction { + return types.NewTx(&types.LegacyTx{ + Nonce: basic.Nonce(), + GasPrice: basic.GasPrice(), + Gas: basic.GasLimit(), + To: to, + Value: value, + Data: data, + }) +} + +func toLegacyTx(tx TxData) *types.Transaction { + return types.NewTx(&types.LegacyTx{ + Nonce: tx.Nonce(), + GasPrice: tx.GasPrice(), + Gas: tx.GasLimit(), + To: tx.To(), + Value: tx.Amount(), + Data: tx.Data(), + }) +} diff --git a/action/rlp_tx_test.go b/action/rlp_tx_test.go index e2bcddb192..777348d8ac 100644 --- a/action/rlp_tx_test.go +++ b/action/rlp_tx_test.go @@ -80,7 +80,7 @@ func TestGenerateRlp(t *testing.T) { require.Contains(v.err, ErrNilAction.Error()) continue } - tx, err := act.ToEthTx(0) + tx, err := act.ToEthTx(0, 0) if err != nil { require.Contains(err.Error(), v.err) continue @@ -512,6 +512,7 @@ func TestEthTxDecodeVerify(t *testing.T) { tx, err := DecodeEtherTx(v.raw) require.NoError(err) encoding, sig, pubkey, err := ExtractTypeSigPubkey(tx) + require.NoError(err) require.Equal(v.encoding, encoding) V, _, _ := tx.RawSignatureValues() recID := V.Uint64() @@ -581,11 +582,11 @@ func TestEthTxDecodeVerify(t *testing.T) { } // evm tx conversion - var rlpTx *types.Transaction + var evmTx *types.Transaction if i == 0 { act, ok := selp.Action().(EthCompatibleAction) require.True(ok) - rlpTx, err = act.ToEthTx(uint32(tx.ChainId().Uint64())) + evmTx, err = act.ToEthTx(uint32(tx.ChainId().Uint64()), selp.encoding) require.NoError(err) } else { // tx unfolding @@ -602,20 +603,20 @@ func TestEthTxDecodeVerify(t *testing.T) { require.False(ok) act, ok := selp.Action().(EthCompatibleAction) require.True(ok) - rlpTx, err = act.ToEthTx(uint32(tx.ChainId().Uint64())) + evmTx, err = act.ToEthTx(uint32(tx.ChainId().Uint64()), selp.encoding) require.NoError(err) } // verify against original tx - require.Equal(v.nonce, rlpTx.Nonce()) - require.Equal(v.price, rlpTx.GasPrice().String()) - require.Equal(v.limit, rlpTx.Gas()) + require.Equal(v.nonce, evmTx.Nonce()) + require.Equal(v.price, evmTx.GasPrice().String()) + require.Equal(v.limit, evmTx.Gas()) if v.to == "" { - require.Nil(rlpTx.To()) + require.Nil(evmTx.To()) } else { - require.Equal(v.to, rlpTx.To().Hex()) + require.Equal(v.to, evmTx.To().Hex()) } - require.Equal(v.amount, rlpTx.Value().String()) - require.Equal(v.dataLen, len(rlpTx.Data())) + require.Equal(v.amount, evmTx.Value().String()) + require.Equal(v.dataLen, len(evmTx.Data())) } }) } @@ -1014,7 +1015,7 @@ func TestEthTxDecodeVerifyV2(t *testing.T) { } // build eth tx from test case var ( - tx = MustNoErrorV(tt.action.ToEthTx(chainID)) + tx = MustNoErrorV(tt.action.ToEthTx(chainID, tt.encoding)) signer = MustNoErrorV(NewEthSigner(tt.encoding, chainID)) signature = MustNoErrorV(sk.Sign(tx.Hash().Bytes())) builttx = MustNoErrorV(RawTxToSignedTx(tx, signer, signature)) @@ -1048,7 +1049,7 @@ func TestEthTxDecodeVerifyV2(t *testing.T) { r.NoError(err) action, ok := sealed.Action().(EthCompatibleAction) r.True(ok) - convertedrawtx, err := action.ToEthTx(chainID) + convertedrawtx, err := action.ToEthTx(chainID, tt.encoding) r.NoError(err) r.NoError(sealed.VerifySignature()) convertedsignedtx, err := RawTxToSignedTx(convertedrawtx, signer, signature) @@ -1172,7 +1173,7 @@ func TestIssue3944(t *testing.T) { // test, err := generateRLPTestData("migrateStake", _evmNetworkID, iotextypes.Encoding_ETHEREUM_EIP155, identityset.PrivateKey(1), act) // fmt.Sprintf("test=%+v", test) func generateRLPTestData(actType string, chainID uint32, encoding iotextypes.Encoding, sk iotexcrypto.PrivateKey, act EthCompatibleAction) (*rlpTest, error) { - tx, err := act.ToEthTx(chainID) + tx, err := act.ToEthTx(chainID, encoding) if err != nil { return nil, err } diff --git a/action/sealedenvelope.go b/action/sealedenvelope.go index 33baae7ba6..436f829a2f 100644 --- a/action/sealedenvelope.go +++ b/action/sealedenvelope.go @@ -49,7 +49,7 @@ func (sealed *SealedEnvelope) envelopeHash() (hash.Hash256, error) { if !ok { return hash.ZeroHash256, ErrInvalidAct } - tx, err := act.ToEthTx(sealed.evmNetworkID) + tx, err := act.ToEthTx(sealed.evmNetworkID, sealed.encoding) if err != nil { return hash.ZeroHash256, err } @@ -91,7 +91,7 @@ func (sealed *SealedEnvelope) calcHash() (hash.Hash256, error) { if !ok { return hash.ZeroHash256, ErrInvalidAct } - tx, err := act.ToEthTx(sealed.evmNetworkID) + tx, err := act.ToEthTx(sealed.evmNetworkID, sealed.encoding) if err != nil { return hash.ZeroHash256, err } @@ -176,7 +176,7 @@ func (sealed *SealedEnvelope) loadProto(pbAct *iotextypes.Action, evmID uint32) if !ok { return ErrInvalidAct } - tx, err := act.ToEthTx(evmID) + tx, err := act.ToEthTx(evmID, encoding) if err != nil { return err } diff --git a/action/sealedenvelope_test.go b/action/sealedenvelope_test.go index 4ecbd1977a..090faf2840 100644 --- a/action/sealedenvelope_test.go +++ b/action/sealedenvelope_test.go @@ -118,7 +118,7 @@ func TestSealedEnvelope_Actions(t *testing.T) { selp := FakeSeal(elp, identityset.PrivateKey(27).PublicKey()) act, ok := selp.Action().(EthCompatibleAction) require.True(ok) - rlp, err := act.ToEthTx(0) + rlp, err := act.ToEthTx(0, 0) require.NoError(err) require.Equal(elp.Nonce(), rlp.Nonce()) diff --git a/action/stake_adddeposit.go b/action/stake_adddeposit.go index 588dc2f14b..ffd2bfd671 100644 --- a/action/stake_adddeposit.go +++ b/action/stake_adddeposit.go @@ -7,6 +7,7 @@ package action import ( "bytes" + "fmt" "math/big" "strings" @@ -58,6 +59,7 @@ var ( // _depositToStakeMethod is the interface of the abi encoding of stake action _depositToStakeMethod abi.Method _ EthCompatibleAction = (*DepositToStake)(nil) + _ TxDataBasic = (*DepositToStake)(nil) ) // DepositToStake defines the action of stake add deposit @@ -220,17 +222,18 @@ func NewDepositToStakeFromABIBinary(data []byte) (*DepositToStake, error) { } // ToEthTx converts action to eth-compatible tx -func (ds *DepositToStake) ToEthTx(_ uint32) (*types.Transaction, error) { +func (ds *DepositToStake) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { data, err := ds.encodeABIBinary() if err != nil { return nil, err } - return types.NewTx(&types.LegacyTx{ - Nonce: ds.Nonce(), - GasPrice: ds.GasPrice(), - Gas: ds.GasLimit(), - To: &_stakingProtocolEthAddr, - Value: big.NewInt(0), - Data: data, - }), nil + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + return stakingToLegacyTx(ds, data), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) + } } diff --git a/action/stake_changecandidate.go b/action/stake_changecandidate.go index 1dadc4844b..e37fd44cd6 100644 --- a/action/stake_changecandidate.go +++ b/action/stake_changecandidate.go @@ -7,6 +7,7 @@ package action import ( "bytes" + "fmt" "math/big" "strings" @@ -58,6 +59,7 @@ var ( // _changeCandidateMethod is the interface of the abi encoding of stake action _changeCandidateMethod abi.Method _ EthCompatibleAction = (*ChangeCandidate)(nil) + _ TxDataBasic = (*ChangeCandidate)(nil) ) // ChangeCandidate defines the action of changing stake candidate ts the other @@ -205,17 +207,18 @@ func NewChangeCandidateFromABIBinary(data []byte) (*ChangeCandidate, error) { } // ToEthTx converts action to eth-compatible tx -func (cc *ChangeCandidate) ToEthTx(_ uint32) (*types.Transaction, error) { +func (cc *ChangeCandidate) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { data, err := cc.encodeABIBinary() if err != nil { return nil, err } - return types.NewTx(&types.LegacyTx{ - Nonce: cc.Nonce(), - GasPrice: cc.GasPrice(), - Gas: cc.GasLimit(), - To: &_stakingProtocolEthAddr, - Value: big.NewInt(0), - Data: data, - }), nil + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + return stakingToLegacyTx(cc, data), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) + } } diff --git a/action/stake_create.go b/action/stake_create.go index a25f86a968..fb6217e0e5 100644 --- a/action/stake_create.go +++ b/action/stake_create.go @@ -7,6 +7,7 @@ package action import ( "bytes" + "fmt" "math/big" "strings" @@ -67,6 +68,7 @@ var ( // _createStakeMethod is the interface of the abi encoding of stake action _createStakeMethod abi.Method _ EthCompatibleAction = (*CreateStake)(nil) + _ TxDataBasic = (*CreateStake)(nil) errDecodeFailure = errors.New("failed to decode the data") ) @@ -261,17 +263,18 @@ func NewCreateStakeFromABIBinary(data []byte) (*CreateStake, error) { } // ToEthTx converts action to eth-compatible tx -func (cs *CreateStake) ToEthTx(_ uint32) (*types.Transaction, error) { +func (cs *CreateStake) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { data, err := cs.encodeABIBinary() if err != nil { return nil, err } - return types.NewTx(&types.LegacyTx{ - Nonce: cs.Nonce(), - GasPrice: cs.GasPrice(), - Gas: cs.GasLimit(), - To: &_stakingProtocolEthAddr, - Value: big.NewInt(0), - Data: data, - }), nil + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + return stakingToLegacyTx(cs, data), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) + } } diff --git a/action/stake_migrate.go b/action/stake_migrate.go index dd518153eb..5c2ff64f13 100644 --- a/action/stake_migrate.go +++ b/action/stake_migrate.go @@ -2,6 +2,7 @@ package action import ( "bytes" + "fmt" "math/big" "strings" @@ -42,6 +43,7 @@ var ( // migrateStakeMethod is the interface of the abi encoding of migrate stake action migrateStakeMethod abi.Method _ EthCompatibleAction = (*MigrateStake)(nil) + _ TxDataBasic = (*MigrateStake)(nil) ) type MigrateStake struct { @@ -145,17 +147,18 @@ func NewMigrateStakeFromABIBinary(data []byte) (*MigrateStake, error) { } // ToEthTx converts action to eth-compatible tx -func (ms *MigrateStake) ToEthTx(_ uint32) (*types.Transaction, error) { +func (ms *MigrateStake) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { data, err := ms.encodeABIBinary() if err != nil { return nil, err } - return types.NewTx(&types.LegacyTx{ - Nonce: ms.Nonce(), - GasPrice: ms.GasPrice(), - Gas: ms.GasLimit(), - To: &_stakingProtocolEthAddr, - Value: big.NewInt(0), - Data: data, - }), nil + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + return stakingToLegacyTx(ms, data), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) + } } diff --git a/action/stake_reclaim.go b/action/stake_reclaim.go index 06f2a5f5da..cf2567b7dd 100644 --- a/action/stake_reclaim.go +++ b/action/stake_reclaim.go @@ -7,6 +7,7 @@ package action import ( "bytes" + "fmt" "math/big" "strings" @@ -73,7 +74,9 @@ var ( // _withdrawStakeMethod is the interface of the abi encoding of withdrawStake action _withdrawStakeMethod abi.Method _ EthCompatibleAction = (*Unstake)(nil) + _ TxDataBasic = (*Unstake)(nil) _ EthCompatibleAction = (*WithdrawStake)(nil) + _ TxDataBasic = (*WithdrawStake)(nil) ) func init() { @@ -212,19 +215,20 @@ func NewUnstakeFromABIBinary(data []byte) (*Unstake, error) { } // ToEthTx converts action to eth-compatible tx -func (su *Unstake) ToEthTx(_ uint32) (*types.Transaction, error) { +func (su *Unstake) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { data, err := su.encodeABIBinary() if err != nil { return nil, err } - return types.NewTx(&types.LegacyTx{ - Nonce: su.Nonce(), - GasPrice: su.GasPrice(), - Gas: su.GasLimit(), - To: &_stakingProtocolEthAddr, - Value: big.NewInt(0), - Data: data, - }), nil + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + return stakingToLegacyTx(su, data), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) + } } // WithdrawStake defines the action of stake withdraw @@ -307,17 +311,18 @@ func NewWithdrawStakeFromABIBinary(data []byte) (*WithdrawStake, error) { } // ToEthTx converts action to eth-compatible tx -func (sw *WithdrawStake) ToEthTx(_ uint32) (*types.Transaction, error) { +func (sw *WithdrawStake) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { data, err := sw.encodeABIBinary() if err != nil { return nil, err } - return types.NewTx(&types.LegacyTx{ - Nonce: sw.Nonce(), - GasPrice: sw.GasPrice(), - Gas: sw.GasLimit(), - To: &_stakingProtocolEthAddr, - Value: big.NewInt(0), - Data: data, - }), nil + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + return stakingToLegacyTx(sw, data), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) + } } diff --git a/action/stake_restake.go b/action/stake_restake.go index a3315458f9..b9e6ec2f7f 100644 --- a/action/stake_restake.go +++ b/action/stake_restake.go @@ -7,6 +7,7 @@ package action import ( "bytes" + "fmt" "math/big" "strings" @@ -63,6 +64,7 @@ var ( // _restakeMethod is the interface of the abi encoding of stake action _restakeMethod abi.Method _ EthCompatibleAction = (*Restake)(nil) + _ TxDataBasic = (*Restake)(nil) ) // Restake defines the action of stake again @@ -212,17 +214,18 @@ func NewRestakeFromABIBinary(data []byte) (*Restake, error) { } // ToEthTx converts action to eth-compatible tx -func (rs *Restake) ToEthTx(_ uint32) (*types.Transaction, error) { +func (rs *Restake) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { data, err := rs.encodeABIBinary() if err != nil { return nil, err } - return types.NewTx(&types.LegacyTx{ - Nonce: rs.Nonce(), - GasPrice: rs.GasPrice(), - Gas: rs.GasLimit(), - To: &_stakingProtocolEthAddr, - Value: big.NewInt(0), - Data: data, - }), nil + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + return stakingToLegacyTx(rs, data), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) + } } diff --git a/action/stake_transferownership.go b/action/stake_transferownership.go index 2f45a0614d..4760fd56b2 100644 --- a/action/stake_transferownership.go +++ b/action/stake_transferownership.go @@ -7,6 +7,7 @@ package action import ( "bytes" + "fmt" "math/big" "strings" @@ -55,6 +56,7 @@ var ( // _transferStakeMethod is the interface of the abi encoding of stake action _transferStakeMethod abi.Method _ EthCompatibleAction = (*TransferStake)(nil) + _ TxDataBasic = (*TransferStake)(nil) ) // TransferStake defines the action of transfering stake ownership ts the other @@ -202,17 +204,18 @@ func NewTransferStakeFromABIBinary(data []byte) (*TransferStake, error) { } // ToEthTx converts action to eth-compatible tx -func (ts *TransferStake) ToEthTx(_ uint32) (*types.Transaction, error) { +func (ts *TransferStake) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { data, err := ts.encodeABIBinary() if err != nil { return nil, err } - return types.NewTx(&types.LegacyTx{ - Nonce: ts.Nonce(), - GasPrice: ts.GasPrice(), - Gas: ts.GasLimit(), - To: &_stakingProtocolEthAddr, - Value: big.NewInt(0), - Data: data, - }), nil + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + return stakingToLegacyTx(ts, data), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) + } } diff --git a/action/transfer.go b/action/transfer.go index 4e74d2c24c..b3aa226c4c 100644 --- a/action/transfer.go +++ b/action/transfer.go @@ -6,6 +6,7 @@ package action import ( + "fmt" "math/big" "github.com/ethereum/go-ethereum/common" @@ -29,6 +30,7 @@ const ( var ( _ hasDestination = (*Transfer)(nil) _ EthCompatibleAction = (*Transfer)(nil) + _ TxDataBasic = (*Transfer)(nil) ) // Transfer defines the struct of account-based transfer @@ -155,18 +157,19 @@ func (tsf *Transfer) SanityCheck() error { } // ToEthTx converts action to eth-compatible tx -func (tsf *Transfer) ToEthTx(_ uint32) (*types.Transaction, error) { +func (tsf *Transfer) ToEthTx(evmNetworkID uint32, encoding iotextypes.Encoding) (*types.Transaction, error) { addr, err := address.FromString(tsf.recipient) if err != nil { return nil, err } - ethAddr := common.BytesToAddress(addr.Bytes()) - return types.NewTx(&types.LegacyTx{ - Nonce: tsf.Nonce(), - GasPrice: tsf.GasPrice(), - Gas: tsf.GasLimit(), - To: ðAddr, - Value: tsf.amount, - Data: tsf.payload, - }), nil + switch encoding { + case iotextypes.Encoding_IOTEX_PROTOBUF: + // treat native tx as EVM LegacyTx + fallthrough + case iotextypes.Encoding_ETHEREUM_EIP155, iotextypes.Encoding_ETHEREUM_UNPROTECTED: + to := common.BytesToAddress(addr.Bytes()) + return basicToLegacyTx(tsf, &to, tsf.amount, tsf.payload), nil + default: + panic(fmt.Sprintf("unsupported encoding %d", encoding)) + } } diff --git a/api/web3server_utils.go b/api/web3server_utils.go index 773eaff04e..7def16319a 100644 --- a/api/web3server_utils.go +++ b/api/web3server_utils.go @@ -126,7 +126,7 @@ func getRecipientAndContractAddrFromAction(selp *action.SealedEnvelope, receipt actHash, _ := selp.Hash() return nil, nil, errors.Wrapf(errUnsupportedAction, "actHash: %s", hex.EncodeToString(actHash[:])) } - ethTx, err := act.ToEthTx(0) + ethTx, err := act.ToEthTx(0, iotextypes.Encoding(selp.Encoding())) if err != nil { return nil, nil, err } @@ -482,7 +482,7 @@ func newGetTransactionResult( actHash, _ := selp.Hash() return nil, errors.Wrapf(errUnsupportedAction, "actHash: %s", hex.EncodeToString(actHash[:])) } - ethTx, err := act.ToEthTx(0) + ethTx, err := act.ToEthTx(evmChainID, iotextypes.Encoding(selp.Encoding())) if err != nil { return nil, err }