github.com/iotexproject/iotex-core@v1.14.1-rc1/action/rlp_tx_test.go (about)

     1  package action
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"math/big"
     7  	"testing"
     8  
     9  	"github.com/ethereum/go-ethereum/common"
    10  	"github.com/ethereum/go-ethereum/core/types"
    11  	"github.com/iotexproject/go-pkgs/crypto"
    12  	"github.com/iotexproject/go-pkgs/hash"
    13  	"github.com/iotexproject/iotex-address/address"
    14  	"github.com/iotexproject/iotex-proto/golang/iotextypes"
    15  	"github.com/stretchr/testify/require"
    16  	"google.golang.org/protobuf/proto"
    17  )
    18  
    19  func TestGenerateRlp(t *testing.T) {
    20  	require := require.New(t)
    21  
    22  	ab := AbstractAction{
    23  		version:  1,
    24  		nonce:    2,
    25  		gasLimit: 1000,
    26  		gasPrice: new(big.Int),
    27  	}
    28  	rlpTsf := &Transfer{
    29  		AbstractAction: ab,
    30  		recipient:      "io1x9qa70ewgs24xwak66lz5dgm9ku7ap80vw3071",
    31  	}
    32  	rlpTsf1 := &Transfer{
    33  		AbstractAction: ab,
    34  		amount:         big.NewInt(100),
    35  		recipient:      "",
    36  	}
    37  	hT1, _ := hex.DecodeString("87e39e819193ae46472eb1320739b34c4c3b38ea321c7cc503432bdcfd0cbf15")
    38  	rlpTsf2 := &Transfer{
    39  		AbstractAction: ab,
    40  		recipient:      "io1x9qa70ewgs24xwak66lz5dgm9ku7ap80vw3070",
    41  	}
    42  	hT2, _ := hex.DecodeString("eaaf38a552809a9bdb1509c8093bd2c74eb07baff862dae692c1d2b865478b14")
    43  	rlpExec := &Execution{
    44  		AbstractAction: ab,
    45  		amount:         big.NewInt(100),
    46  		data:           _signByte,
    47  	}
    48  	hE1, _ := hex.DecodeString("fcdd0c3d07f438d6e67ea852b40e5dc256d75f5e1fa9ac3ca96030efeb634150")
    49  	rlpExec1 := &Execution{
    50  		AbstractAction: ab,
    51  		contract:       "io1x9qa70ewgs24xwak66lz5dgm9ku7ap80vw3070",
    52  		amount:         big.NewInt(100),
    53  		data:           _signByte,
    54  	}
    55  	hE2, _ := hex.DecodeString("fee3db88ee7d7defa9eded672d08fc8641f760f3a11d404a53276ad6f412b8a5")
    56  	rlpTests := []struct {
    57  		act  Action
    58  		sig  []byte
    59  		err  string
    60  		hash hash.Hash256
    61  	}{
    62  		{nil, _validSig, ErrNilAction.Error(), hash.ZeroHash256},
    63  		{rlpTsf, _validSig, address.ErrInvalidAddr.Error(), hash.ZeroHash256},
    64  		{rlpTsf1, _signByte, "address length = 0, expecting 41", hash.ZeroHash256},
    65  		{rlpTsf1, _validSig, "", hash.BytesToHash256(hT1)},
    66  		{rlpTsf2, _validSig, "", hash.BytesToHash256(hT2)},
    67  		{rlpExec, _validSig, "", hash.BytesToHash256(hE1)},
    68  		{rlpExec1, _validSig, "", hash.BytesToHash256(hE2)},
    69  	}
    70  
    71  	for _, v := range rlpTests {
    72  		act, ok := v.act.(EthCompatibleAction)
    73  		if !ok {
    74  			require.Contains(v.err, ErrNilAction.Error())
    75  			continue
    76  		}
    77  		tx, err := act.ToEthTx(0)
    78  		if err != nil {
    79  			require.Contains(err.Error(), v.err)
    80  			continue
    81  		}
    82  		signer, err := NewEthSigner(iotextypes.Encoding_ETHEREUM_EIP155, _evmNetworkID)
    83  		require.NoError(err)
    84  		h, err := rlpSignedHash(tx, signer, v.sig)
    85  		if err != nil {
    86  			require.Contains(err.Error(), v.err)
    87  		}
    88  		require.Equal(v.hash, h)
    89  	}
    90  }
    91  
    92  func TestRlpDecodeVerify(t *testing.T) {
    93  	require := require.New(t)
    94  
    95  	oldTests := rlpTests[:len(rlpTests)-1]
    96  	for _, v := range oldTests {
    97  		// decode received RLP tx
    98  		tx, sig, pubkey, err := DecodeRawTx(v.raw, _evmNetworkID)
    99  		require.NoError(err)
   100  		require.EqualValues(types.LegacyTxType, tx.Type())
   101  		require.True(tx.Protected())
   102  		require.EqualValues(v.chainID, tx.ChainId().Uint64())
   103  		require.Equal(v.pubkey, pubkey.HexString())
   104  		require.Equal(v.pkhash, hex.EncodeToString(pubkey.Hash()))
   105  
   106  		// convert to our Execution
   107  		pb := &iotextypes.Action{
   108  			Encoding: iotextypes.Encoding_ETHEREUM_EIP155,
   109  		}
   110  		pb.Core = convertToNativeProto(tx, v.actType)
   111  		pb.SenderPubKey = pubkey.Bytes()
   112  		pb.Signature = sig
   113  
   114  		// send on wire
   115  		bs, err := proto.Marshal(pb)
   116  		require.NoError(err)
   117  
   118  		// receive from API
   119  		proto.Unmarshal(bs, pb)
   120  		selp := &SealedEnvelope{}
   121  		require.NoError(selp.loadProto(pb, _evmNetworkID))
   122  		act, ok := selp.Action().(EthCompatibleAction)
   123  		require.True(ok)
   124  		rlpTx, err := act.ToEthTx(_evmNetworkID)
   125  		require.NoError(err)
   126  
   127  		// verify against original tx
   128  		require.Equal(v.nonce, rlpTx.Nonce())
   129  		require.Equal(v.price, rlpTx.GasPrice().String())
   130  		require.Equal(v.limit, rlpTx.Gas())
   131  		if v.to == "" {
   132  			require.Nil(rlpTx.To())
   133  		} else {
   134  			require.Equal(v.to, rlpTx.To().Hex())
   135  		}
   136  		require.Equal(v.amount, rlpTx.Value().String())
   137  		require.Equal(v.dataLen, len(rlpTx.Data()))
   138  		h, err := selp.Hash()
   139  		require.NoError(err)
   140  		require.Equal(v.hash, hex.EncodeToString(h[:]))
   141  		require.Equal(pubkey, selp.SrcPubkey())
   142  		require.True(bytes.Equal(sig, selp.signature))
   143  		raw, err := selp.envelopeHash()
   144  		require.NoError(err)
   145  		signer, err := NewEthSigner(iotextypes.Encoding_ETHEREUM_RLP, _evmNetworkID)
   146  		require.NoError(err)
   147  		rawHash := signer.Hash(tx)
   148  		require.True(bytes.Equal(rawHash[:], raw[:]))
   149  		require.NotEqual(raw, h)
   150  		require.NoError(selp.VerifySignature())
   151  	}
   152  }
   153  
   154  var (
   155  	// deterministic deployment: https://github.com/Arachnid/deterministic-deployment-proxy
   156  	// see example at https://etherscan.io/tx/0xeddf9e61fb9d8f5111840daef55e5fde0041f5702856532cdbb5a02998033d26
   157  	deterministicDeploymentTx = "0xf8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222"
   158  
   159  	// example access list tx, created with a random chainID value = 0x7a69 = 31337
   160  	accessListTx = "0x01f8a0827a690184ee6b280082520894a0ee7a142d267c1f36714e4a8f75612f20a797206480f838f794a0ee7a142d267c1f36714e4a8f75612f20a79720e1a0000000000000000000000000000000000000000000000000000000000000000001a0eb211dfd353d76d43ea31a130ff36ac4eb7b379eae4d49fa2376741daf32f9ffa07ab673241d75e103f81ddd4aa34dd6849faf2f0f593eebe61a68fed74490a348"
   161  
   162  	rlpTests = []struct {
   163  		actType  string
   164  		raw      string
   165  		nonce    uint64
   166  		limit    uint64
   167  		price    string
   168  		amount   string
   169  		to       string
   170  		chainID  uint32
   171  		encoding iotextypes.Encoding
   172  		dataLen  int
   173  		hash     string
   174  		pubkey   string
   175  		pkhash   string
   176  	}{
   177  		{
   178  			"transfer",
   179  			"f86e8085e8d4a51000825208943141df3f2e4415533bb6d6be2a351b2db9ee84ef88016345785d8a0000808224c6a0204d25fc0d7d8b3fdf162c6ee820f888f5533b1c382d79d5cbc8ec1d9091a9a8a016f1a58d7e0d0fd24be800f64a2d6433c5fcb31e3fc7562b7fbe62bc382a95bb",
   180  			0,
   181  			21000,
   182  			"1000000000000",
   183  			"100000000000000000",
   184  			"0x3141df3f2e4415533bb6d6be2A351B2db9ee84EF",
   185  			_evmNetworkID,
   186  			iotextypes.Encoding_ETHEREUM_EIP155,
   187  			0,
   188  			"eead45fe6b510db9ed6dce9187280791c04bbaadd90c54a7f4b1f75ced382ff1",
   189  			"041ba784140be115e8fa8698933e9318558a895c75c7943100f0677e4d84ff2763ff68720a0d22c12d093a2d692d1e8292c3b7672fccf3b3db46a6e0bdad93be17",
   190  			"87eea07540789af85b64947aea21a3f00400b597",
   191  		},
   192  		{
   193  			"execution",
   194  			"f8ab0d85e8d4a5100082520894ac7ac39de679b19aae042c0ce19facb86e0a411780b844a9059cbb0000000000000000000000003141df3f2e4415533bb6d6be2a351b2db9ee84ef000000000000000000000000000000000000000000000000000000003b9aca008224c5a0fac4e25db03c99fec618b74a962d322a334234696eb62c7e5b9889132ff4f4d7a02c88e451572ca36b6f690ce23ff9d6695dd71e888521fa706a8fc8c279099a61",
   195  			13,
   196  			21000,
   197  			"1000000000000",
   198  			"0",
   199  			"0xAC7AC39De679b19AaE042c0cE19fAcB86e0A4117",
   200  			_evmNetworkID,
   201  			iotextypes.Encoding_ETHEREUM_EIP155,
   202  			68,
   203  			"7467dd6ccd4f3d7b6dc0002b26a45ad0b75a1793da4e3557cf6ff2582cbe25c9",
   204  			"041ba784140be115e8fa8698933e9318558a895c75c7943100f0677e4d84ff2763ff68720a0d22c12d093a2d692d1e8292c3b7672fccf3b3db46a6e0bdad93be17",
   205  			"87eea07540789af85b64947aea21a3f00400b597",
   206  		},
   207  		{
   208  			"execution",
   209  			"f9024f2e830f42408381b3208080b901fc608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061019c806100606000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063445df0ac146100465780638da5cb5b14610064578063fdacd576146100ae575b600080fd5b61004e6100dc565b6040518082815260200191505060405180910390f35b61006c6100e2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100da600480360360208110156100c457600080fd5b8101908080359060200190929190505050610107565b005b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561016457806001819055505b5056fea265627a7a72315820e54fe55a78b9d8bec22b4d3e6b94b7e59799daee3940423eb1aa30fe643eeb9a64736f6c634300051000328224c5a0439310c2d5509fc42486171b910cf8107542c86e23202a3a8ba43129cabcdbfea038966d36b41916f619c64bdc8c3ddcb021b35ea95d44875eb8201e9422fd98f0",
   210  			46,
   211  			8500000,
   212  			"1000000",
   213  			"0",
   214  			EmptyAddress,
   215  			_evmNetworkID,
   216  			iotextypes.Encoding_ETHEREUM_EIP155,
   217  			508,
   218  			"b676128dae841742e3ab6e518acb30badc6b26230fe870821d1de08c85823067",
   219  			"049c6567f527f8fc98c0875d3d80097fcb4d5b7bfe037fc9dd5dbeaf563d58d7ff17a4f2b85df9734ecdb276622738e28f0b7cf224909ab7b128c5ca748729b0d2",
   220  			"1904bfcb93edc9bf961eead2e5c0de81dcc1d37d",
   221  		},
   222  		{
   223  			"stakeCreate",
   224  			"f901670980828ca09404c22afae6a03438b8fed74cb1cf441168df3f1280b90104a3d374c400000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000004746573740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008224c6a02d359322fb1eb0ef44008b587d28160fb237ae716da2735aef9ce2702af52151a03518f334c585c31cec1d9c0ec81fd4c4f70d3ab661502a5aeb1f6eb07bc01854",
   225  			9,
   226  			36000,
   227  			"0",
   228  			"0",
   229  			"0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12",
   230  			_evmNetworkID,
   231  			iotextypes.Encoding_ETHEREUM_EIP155,
   232  			260,
   233  			"f59e5f9ba10ec50fdd1ebb41c75c6d54cfc634428620930b6ba6300847127241",
   234  			"04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b",
   235  			"1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e",
   236  		},
   237  		{
   238  			"stakeAddDeposit",
   239  			"f8e60980825aa09404c22afae6a03438b8fed74cb1cf441168df3f1280b88434e8e14500000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000008224c6a0b4af40981b992eab4f15afe1bab1d4c498069cae8fa4ea3e0800d732f282fadea073de47b280905d5ccd4fc329e9c1f10b0bdefe1f4a3f4f8b00918680428ae7dd",
   240  			9,
   241  			23200,
   242  			"0",
   243  			"0",
   244  			"0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12",
   245  			_evmNetworkID,
   246  			iotextypes.Encoding_ETHEREUM_EIP155,
   247  			132,
   248  			"8823b599b46cd907c4691aa71b5668b835be76a8358fa9beb866610e27598592",
   249  			"04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b",
   250  			"1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e",
   251  		},
   252  		{
   253  			"changeCandidate",
   254  			"f9012609808273a09404c22afae6a03438b8fed74cb1cf441168df3f1280b8c4fb3d51380000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000004746573740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008224c6a06087932dec4df781917c12d31feb80c8e61b2317e3a0820401f3c095746a765da0549df65b7d94fdec196bc70e6dda056fec873664c064036e55fd3bc7e766a595",
   255  			9,
   256  			29600,
   257  			"0",
   258  			"0",
   259  			"0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12",
   260  			_evmNetworkID,
   261  			iotextypes.Encoding_ETHEREUM_EIP155,
   262  			196,
   263  			"23f29aebf4b193b02dd78866d56ea7a7b1cdbf27604d34868bb82993c216b4ec",
   264  			"04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b",
   265  			"1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e",
   266  		},
   267  		{
   268  			"unstake",
   269  			"f8c609808252089404c22afae6a03438b8fed74cb1cf441168df3f1280b8642bde151d0000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000008224c6a0bd261cf9c6a2412272c660742a902965611d838176b2ad22b39219dadeedb312a02beef231cc90e4fbd6b928b28aea6ca1ccaf4f793f9d05bc0186e0e09b920a0a",
   270  			9,
   271  			21000,
   272  			"0",
   273  			"0",
   274  			"0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12",
   275  			_evmNetworkID,
   276  			iotextypes.Encoding_ETHEREUM_EIP155,
   277  			100,
   278  			"0c8560b135d325573e6aad484d71e2887835acce7fd4a78eddcb24efe6071516",
   279  			"04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b",
   280  			"1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e",
   281  		},
   282  		{
   283  			"withdrawStake",
   284  			"f8c609808252089404c22afae6a03438b8fed74cb1cf441168df3f1280b864d179ffb50000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000008224c5a0526ec8247ce5ae1c8542776cf28a85c7bc2f17e1abc3de5cfbfd20fd85aeeca3a07a6db0a7ae08b6b6aeeae4a1446dcc6f090589e7835d63ebc0a1db783c5e2c89",
   285  			9,
   286  			21000,
   287  			"0",
   288  			"0",
   289  			"0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12",
   290  			_evmNetworkID,
   291  			iotextypes.Encoding_ETHEREUM_EIP155,
   292  			100,
   293  			"49cc2e14f3d1c03d7e36686d962995ea0f30f65f948d5a59181a5504bc58c102",
   294  			"04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b",
   295  			"1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e",
   296  		},
   297  		{
   298  			"restake",
   299  			"f9010609808267209404c22afae6a03438b8fed74cb1cf441168df3f1280b8a44c4fee4b000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000008224c5a0078638f1f00ab532522558e2e4f394f13bfe134a8687ac4639ebead60f63e0dba019dc91f08c1f422de44aa7e6b25ada0632f29bc22242900b3a60f7f371301f02",
   300  			9,
   301  			26400,
   302  			"0",
   303  			"0",
   304  			"0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12",
   305  			_evmNetworkID,
   306  			iotextypes.Encoding_ETHEREUM_EIP155,
   307  			164,
   308  			"c3d30b0fccf9d59ece79419d329e50082a8b6d86dee1b9f424f8852e154713d1",
   309  			"04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b",
   310  			"1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e",
   311  		},
   312  		{
   313  			"transferStake",
   314  			"f8e60980825aa09404c22afae6a03438b8fed74cb1cf441168df3f1280b8849cb560bb0000000000000000000000003041a575c7a70021e3082929798c8c3fdaa9d8240000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000008224c5a07fd84321b04de059cbfdf12dcd383d3e554c569705f32035bc435b8d996c8bdba00df629ef4d9135d73bb60d49815761bc0a6ee7eb66770106dc9e809cd105d570",
   315  			9,
   316  			23200,
   317  			"0",
   318  			"0",
   319  			"0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12",
   320  			_evmNetworkID,
   321  			iotextypes.Encoding_ETHEREUM_EIP155,
   322  			132,
   323  			"a60b2546839e889a0ef89be4f224fb70dab3e4ddb6f65391ff708b01116593c1",
   324  			"04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b",
   325  			"1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e",
   326  		},
   327  		{
   328  			"candidateRegister",
   329  			"f901c709808252089404c22afae6a03438b8fed74cb1cf441168df3f1280b90164bee5f7b700000000000000000000000000000000000000000000000000000000000001000000000000000000000000003041a575c7a70021e3082929798c8c3fdaa9d8240000000000000000000000003041a575c7a70021e3082929798c8c3fdaa9d8240000000000000000000000003041a575c7a70021e3082929798c8c3fdaa9d82400000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000004746573740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008224c5a07b4fd9921e47c13bb52fc5e0df47f4dc0bffcf6e7877e13c7e559b4a7d3b9825a0073a3a029822aa43506834bef8b1ed30d6bb436d758d7cf583deb48a4efefd6a",
   330  			9,
   331  			21000,
   332  			"0",
   333  			"0",
   334  			"0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12",
   335  			_evmNetworkID,
   336  			iotextypes.Encoding_ETHEREUM_EIP155,
   337  			356,
   338  			"9aa470cbdc3b3fd8f51aae4770d6a58cf4016be18201f0efbae6d83d0b2aa096",
   339  			"04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b",
   340  			"1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e",
   341  		},
   342  		{
   343  			"candidateUpdate",
   344  			"f9010609808252089404c22afae6a03438b8fed74cb1cf441168df3f1280b8a4435f9f2200000000000000000000000000000000000000000000000000000000000000600000000000000000000000003041a575c7a70021e3082929798c8c3fdaa9d8240000000000000000000000003041a575c7a70021e3082929798c8c3fdaa9d824000000000000000000000000000000000000000000000000000000000000000474657374000000000000000000000000000000000000000000000000000000008224c6a04df6545da871debef84476198e76167d4dfe6fb83098a5a49dbab734352f20f1a0220686494f8b09751bbeb5c63729e7ecc5c504f952c67e926461db98588854b6",
   345  			9,
   346  			21000,
   347  			"0",
   348  			"0",
   349  			"0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12",
   350  			_evmNetworkID,
   351  			iotextypes.Encoding_ETHEREUM_EIP155,
   352  			164,
   353  			"7a8d96d35c939bf1634d587b1f471c0f3f96ba750d64d43289c9eef267718ef0",
   354  			"04dc4c548c3a478278a6a09ffa8b5c4b384368e49654b35a6961ee8288fc889cdc39e9f8194e41abdbfac248ef9dc3f37b131a36ee2c052d974c21c1d2cd56730b",
   355  			"1e14d5373e1af9cc77f0032ad2cd0fba8be5ea2e",
   356  		},
   357  		{
   358  			"rewardingClaim",
   359  			"f8c6806482520894a576c141e5659137ddda4223d209d4744b2106be80b8642df163ef0000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000008224c6a03d62943431b8ca0e8ea0a9c79dc8f64df14c965ca5486da124804013778ed566a065956b185116b65cec0ec9bcf9539e924784a4b448190b0aa9d017f1719be921",
   360  			0,
   361  			21000,
   362  			"100",
   363  			"0",
   364  			"0xA576C141e5659137ddDa4223d209d4744b2106BE",
   365  			_evmNetworkID,
   366  			iotextypes.Encoding_ETHEREUM_EIP155,
   367  			100,
   368  			"4d26d0736ebd9e69bd5994f3730b05a2d48c810b3bb54818be65d02004cf4ff4",
   369  			"04830579b50e01602c2015c24e72fbc48bca1cca1e601b119ca73abe2e0b5bd61fcb7874567e091030d6b644f927445d80e00b3f9ca0c566c21c30615e94c343da",
   370  			"8d38efe45794d7fceea10b2262c23c12245959db",
   371  		},
   372  		{
   373  			"rewardingDeposit",
   374  			"f8c6016482520894a576c141e5659137ddda4223d209d4744b2106be80b86427852a6b0000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000008224c6a013b7679dbabcb0f97b93942436f5072cca3c7fe43451a8fedcdf3c84c1344e1da02af4cc67594c0200b59f4e30ba149af15e546acbfc69fa31f14e8788ab063d85",
   375  			1,
   376  			21000,
   377  			"100",
   378  			"0",
   379  			"0xA576C141e5659137ddDa4223d209d4744b2106BE",
   380  			_evmNetworkID,
   381  			iotextypes.Encoding_ETHEREUM_EIP155,
   382  			100,
   383  			"842fea9a292c0bc7a1e05a14a8255ed8dc945fdae7c01a6b70f5213ebe35583b",
   384  			"04830579b50e01602c2015c24e72fbc48bca1cca1e601b119ca73abe2e0b5bd61fcb7874567e091030d6b644f927445d80e00b3f9ca0c566c21c30615e94c343da",
   385  			"8d38efe45794d7fceea10b2262c23c12245959db",
   386  		},
   387  		{
   388  			"candidateActivate",
   389  			"f88a7885e8d4a510008252089404c22afae6a03438b8fed74cb1cf441168df3f1280a4ef68b1a400000000000000000000000000000000000000000000000000000000000000018224c6a05d21ebb92203797ce49a95febe4430cfdfd32deb9284c80fee5d600124a77791a05ac4871b1b1200433f197aee068007b52f2b096e27fe473874ceab89661fad2a",
   390  			120,
   391  			21000,
   392  			"1000000000000",
   393  			"0",
   394  			"0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12",
   395  			_evmNetworkID,
   396  			iotextypes.Encoding_ETHEREUM_EIP155,
   397  			36,
   398  			"db61959a804781ea9da78d6d4ce6054e1ea940ae4a2cac3853f5262728a9369e",
   399  			"049ea260dc05a824a8a7e92d3b87e47ce06384e1eee15d446494a20d299c1bd11900edc2df5697aa00b2256c286193239f83740d079b032b9fbe085b791fa10950",
   400  			"065e1164818487818e6ba714e8d80b91718ad758",
   401  		},
   402  		{
   403  			"candidateEndorsement",
   404  			"f8ab7885e8d4a510008252089404c22afae6a03438b8fed74cb1cf441168df3f1280b8448a8a5d51000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000018224c5a0cb0c5d443925b98776645793fe8bfdeb34ca1d364d1c389521f5a4c715a42a91a07c1bb620307a78fb463bb8204a43d4bf32acd6efed0cb6b7c00eb7ae13da1ad6",
   405  			120,
   406  			21000,
   407  			"1000000000000",
   408  			"0",
   409  			"0x04C22AfaE6a03438b8FED74cb1Cf441168DF3F12",
   410  			_evmNetworkID,
   411  			iotextypes.Encoding_ETHEREUM_EIP155,
   412  			68,
   413  			"008d08ae3327ae395fdc0b16497e181c4eb6633cf796c174e8819cbb2a29194c",
   414  			"049ea260dc05a824a8a7e92d3b87e47ce06384e1eee15d446494a20d299c1bd11900edc2df5697aa00b2256c286193239f83740d079b032b9fbe085b791fa10950",
   415  			"065e1164818487818e6ba714e8d80b91718ad758",
   416  		},
   417  		{
   418  			"unprotected",
   419  			deterministicDeploymentTx,
   420  			0,
   421  			100000,
   422  			"100000000000",
   423  			"0",
   424  			EmptyAddress,
   425  			0,
   426  			iotextypes.Encoding_ETHEREUM_UNPROTECTED,
   427  			83,
   428  			"eddf9e61fb9d8f5111840daef55e5fde0041f5702856532cdbb5a02998033d26",
   429  			"040a98b1acb38ed9cd8d0e8f1f03b1588bae140586f8a8049197b65013a3c17690151ae422e3fdfb26be2e6a4465b1f9cf5c26a5635109929a0d0a11734124d50a",
   430  			"3fab184622dc19b6109349b94811493bf2a45362",
   431  		},
   432  	}
   433  )
   434  
   435  func TestNewEthSignerError(t *testing.T) {
   436  	require := require.New(t)
   437  	singer, err := NewEthSigner(iotextypes.Encoding_ETHEREUM_ACCESSLIST, 1)
   438  	require.ErrorIs(err, ErrInvalidAct)
   439  	require.Nil(singer)
   440  
   441  	tx := types.NewTx(&types.DynamicFeeTx{
   442  		To:        nil,
   443  		Nonce:     4,
   444  		Value:     big.NewInt(4),
   445  		Gas:       4,
   446  		GasTipCap: big.NewInt(44),
   447  		GasFeeCap: big.NewInt(1045),
   448  	})
   449  	_, _, _, err = ExtractTypeSigPubkey(tx)
   450  	require.ErrorIs(err, ErrNotSupported)
   451  }
   452  
   453  func TestEthTxDecodeVerify(t *testing.T) {
   454  	require := require.New(t)
   455  
   456  	for _, v := range rlpTests {
   457  		// decode received RLP tx
   458  		tx, err := DecodeEtherTx(v.raw)
   459  		require.NoError(err)
   460  		encoding, sig, pubkey, err := ExtractTypeSigPubkey(tx)
   461  		require.Equal(v.encoding, encoding)
   462  		V, _, _ := tx.RawSignatureValues()
   463  		recID := V.Uint64()
   464  		if encoding == iotextypes.Encoding_ETHEREUM_EIP155 {
   465  			require.EqualValues(types.LegacyTxType, tx.Type())
   466  			require.True(tx.Protected())
   467  			require.Less(uint64(28), recID)
   468  		} else if encoding == iotextypes.Encoding_ETHEREUM_UNPROTECTED {
   469  			require.EqualValues(types.LegacyTxType, tx.Type())
   470  			require.False(tx.Protected())
   471  			require.Zero(tx.ChainId().Uint64())
   472  			// unprotected tx has V = 27, 28
   473  			require.True(27 == recID || 28 == recID)
   474  			require.True(27 == sig[64] || 28 == sig[64])
   475  		}
   476  		require.EqualValues(v.chainID, tx.ChainId().Uint64())
   477  		require.Equal(v.pubkey, pubkey.HexString())
   478  		require.Equal(v.pkhash, hex.EncodeToString(pubkey.Hash()))
   479  
   480  		// convert to our Execution
   481  		pb := &iotextypes.Action{
   482  			Encoding: encoding,
   483  		}
   484  		pb.Core = convertToNativeProto(tx, v.actType)
   485  		pb.SenderPubKey = pubkey.Bytes()
   486  		pb.Signature = sig
   487  
   488  		// send on wire
   489  		bs, err := proto.Marshal(pb)
   490  		require.NoError(err)
   491  
   492  		// receive from API
   493  		proto.Unmarshal(bs, pb)
   494  		selp, err := (&Deserializer{}).SetEvmNetworkID(v.chainID).ActionToSealedEnvelope(pb)
   495  		require.NoError(err)
   496  		act, ok := selp.Action().(EthCompatibleAction)
   497  		require.True(ok)
   498  		rlpTx, err := act.ToEthTx(uint32(tx.ChainId().Uint64()))
   499  		require.NoError(err)
   500  
   501  		// verify against original tx
   502  		require.Equal(v.nonce, rlpTx.Nonce())
   503  		require.Equal(v.price, rlpTx.GasPrice().String())
   504  		require.Equal(v.limit, rlpTx.Gas())
   505  		if v.to == "" {
   506  			require.Nil(rlpTx.To())
   507  		} else {
   508  			require.Equal(v.to, rlpTx.To().Hex())
   509  		}
   510  		require.Equal(v.amount, rlpTx.Value().String())
   511  		require.Equal(v.dataLen, len(rlpTx.Data()))
   512  		h, err := selp.Hash()
   513  		require.NoError(err)
   514  		require.Equal(v.hash, hex.EncodeToString(h[:]))
   515  		require.Equal(pubkey, selp.SrcPubkey())
   516  		require.True(bytes.Equal(sig, selp.signature))
   517  		raw, err := selp.envelopeHash()
   518  		require.NoError(err)
   519  		signer, err := NewEthSigner(encoding, uint32(tx.ChainId().Uint64()))
   520  		require.NoError(err)
   521  		rawHash := signer.Hash(tx)
   522  		require.True(bytes.Equal(rawHash[:], raw[:]))
   523  		require.NotEqual(raw, h)
   524  		require.NoError(selp.VerifySignature())
   525  	}
   526  }
   527  
   528  func convertToNativeProto(tx *types.Transaction, actType string) *iotextypes.ActionCore {
   529  	elpBuilder := &EnvelopeBuilder{}
   530  	elpBuilder.SetGasLimit(tx.Gas()).SetGasPrice(tx.GasPrice()).SetNonce(tx.Nonce())
   531  	switch actType {
   532  	case "transfer":
   533  		elp, _ := elpBuilder.BuildTransfer(tx)
   534  		return elp.Proto()
   535  	case "execution", "unprotected", "accesslist":
   536  		elp, _ := elpBuilder.BuildExecution(tx)
   537  		return elp.Proto()
   538  	case "stakeCreate", "stakeAddDeposit", "changeCandidate", "unstake", "withdrawStake", "restake",
   539  		"transferStake", "candidateRegister", "candidateUpdate", "candidateActivate", "candidateEndorsement":
   540  		elp, _ := elpBuilder.BuildStakingAction(tx)
   541  		return elp.Proto()
   542  	case "rewardingClaim", "rewardingDeposit":
   543  		elp, _ := elpBuilder.BuildRewardingAction(tx)
   544  		return elp.Proto()
   545  	default:
   546  		panic("unsupported")
   547  	}
   548  }
   549  
   550  func TestIssue3944(t *testing.T) {
   551  	r := require.New(t)
   552  	// the sample tx below is the web3 format tx on the testnet:
   553  	// https://testnet.iotexscan.io/tx/fcaf377ff3cc785d60c58de7e121d6a2e79e1c58c189ea8641f3ea61f7605285
   554  	// or you can get it using ethclient code:
   555  	// {
   556  	//		cli, _ := ethclient.Dial("https://babel-api.testnet.iotex.io")
   557  	// 		tx, _, err := cli.TransactionByHash(context.Background(), common.HexToHash("0xfcaf377ff3cc785d60c58de7e121d6a2e79e1c58c189ea8641f3ea61f7605285"))
   558  	// }
   559  	var (
   560  		hash    = "0xfcaf377ff3cc785d60c58de7e121d6a2e79e1c58c189ea8641f3ea61f7605285"
   561  		data, _ = hex.DecodeString("f3fef3a3000000000000000000000000fdff3eafde9a0cc42d18aab2a7454b1105f19edf00000000000000000000000000000000000000000000002086ac351052600000")
   562  		to      = common.HexToAddress("0xd313b3131e238C635f2fE4a84EaDaD71b3ed25fa")
   563  		sig, _  = hex.DecodeString("adff1da88c93f4e80c27bab0d613147fb7aeeed6e976231695de52cd9ac5aa8a3094e02759b838514f8376e05ceb266badc791ac2e7045ee7c15e58fc626980b1b")
   564  	)
   565  	tx := types.NewTx(&types.LegacyTx{
   566  		Nonce:    83,
   567  		To:       &to,
   568  		Value:    new(big.Int),
   569  		Gas:      39295,
   570  		GasPrice: big.NewInt(1000000000000),
   571  		Data:     data,
   572  		V:        big.NewInt(int64(sig[64])),
   573  		R:        new(big.Int).SetBytes(sig[:32]),
   574  		S:        new(big.Int).SetBytes(sig[32:64]),
   575  	})
   576  
   577  	r.EqualValues(types.LegacyTxType, tx.Type())
   578  	r.False(tx.Protected())
   579  	v, q, s := tx.RawSignatureValues()
   580  	r.Equal(sig[:32], q.Bytes())
   581  	r.Equal(sig[32:64], s.Bytes())
   582  	r.Equal("1b", v.Text(16))
   583  	r.NotEqual(hash, tx.Hash().Hex()) // hash does not match with wrong V value in signature
   584  
   585  	signer, err := NewEthSigner(iotextypes.Encoding_ETHEREUM_EIP155, 4690)
   586  	r.NoError(err)
   587  	tx1, err := RawTxToSignedTx(tx, signer, sig)
   588  	r.NoError(err)
   589  	r.True(tx1.Protected())
   590  	r.EqualValues(4690, tx1.ChainId().Uint64())
   591  	v, q, s = tx1.RawSignatureValues()
   592  	r.Equal(sig[:32], q.Bytes())
   593  	r.Equal(sig[32:64], s.Bytes())
   594  	r.Equal("9415", v.String()) // this is the correct V value corresponding to chainID = 4690
   595  	r.Equal(hash, tx1.Hash().Hex())
   596  }
   597  
   598  func TestBackwardComp(t *testing.T) {
   599  	r := require.New(t)
   600  	for _, chainID := range []uint32{_evmNetworkID, _evmNetworkID + 1, 31337, 0} {
   601  		_, _, _, err := DecodeRawTx(deterministicDeploymentTx, chainID)
   602  		r.Equal(crypto.ErrInvalidKey, err)
   603  		_, _, _, err = DecodeRawTx(accessListTx, chainID)
   604  		r.ErrorContains(err, "typed transaction too short")
   605  	}
   606  }