github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evm/types/utils_test.go (about)

     1  package types
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"math/big"
     7  	"strings"
     8  	"sync"
     9  	"testing"
    10  
    11  	ethcmn "github.com/ethereum/go-ethereum/common"
    12  	ethtypes "github.com/ethereum/go-ethereum/core/types"
    13  	"github.com/ethereum/go-ethereum/crypto"
    14  	"github.com/ethereum/go-ethereum/rlp"
    15  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
    16  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    17  	"github.com/fibonacci-chain/fbc/libs/tendermint/global"
    18  	"github.com/fibonacci-chain/fbc/libs/tendermint/types"
    19  	"github.com/stretchr/testify/require"
    20  )
    21  
    22  func TestEvmDataEncoding(t *testing.T) {
    23  	addr := ethcmn.HexToAddress("0x5dE8a020088a2D6d0a23c204FFbeD02790466B49")
    24  	bloom := ethtypes.BytesToBloom([]byte{0x1, 0x3})
    25  	ret := []byte{0x5, 0x8}
    26  
    27  	data := ResultData{
    28  		ContractAddress: addr,
    29  		Bloom:           bloom,
    30  		Logs: []*ethtypes.Log{{
    31  			Data:        []byte{1, 2, 3, 4},
    32  			BlockNumber: 17,
    33  		}},
    34  		Ret: ret,
    35  	}
    36  
    37  	enc, err := EncodeResultData(&data)
    38  	require.NoError(t, err)
    39  
    40  	res, err := DecodeResultData(enc)
    41  	require.NoError(t, err)
    42  	require.Equal(t, addr, res.ContractAddress)
    43  	require.Equal(t, bloom, res.Bloom)
    44  	require.Equal(t, data.Logs, res.Logs)
    45  	require.Equal(t, ret, res.Ret)
    46  
    47  	// error check
    48  	_, err = DecodeResultData(enc[1:])
    49  	require.Error(t, err)
    50  }
    51  
    52  func TestValidateSigner(t *testing.T) {
    53  	const digest = "default digest"
    54  	digestHash := crypto.Keccak256([]byte(digest))
    55  	priv, err := crypto.GenerateKey()
    56  	require.NotNil(t, priv)
    57  	require.NoError(t, err)
    58  
    59  	ethAddr := crypto.PubkeyToAddress(priv.PublicKey)
    60  	require.NoError(t, err)
    61  
    62  	sig, err := crypto.Sign(digestHash, priv)
    63  	require.NoError(t, err)
    64  
    65  	err = ValidateSigner(digestHash, sig, ethAddr)
    66  	require.NoError(t, err)
    67  
    68  	// different eth address
    69  	otherEthAddr := ethcmn.BytesToAddress([]byte{1})
    70  	err = ValidateSigner(digestHash, sig, otherEthAddr)
    71  	require.Error(t, err)
    72  
    73  	// invalid digestHash
    74  	err = ValidateSigner(digestHash[1:], sig, otherEthAddr)
    75  	require.Error(t, err)
    76  }
    77  
    78  func TestResultData_String(t *testing.T) {
    79  	const expectedResultDataStr = `ResultData:
    80  	ContractAddress: 0x5dE8a020088a2D6d0a23c204FFbeD02790466B49
    81  	Bloom: 259
    82  	Ret: [5 8]
    83  	TxHash: 0x0000000000000000000000000000000000000000000000000000000000000000	
    84  	Logs: 
    85  		{0x0000000000000000000000000000000000000000 [] [1 2 3 4] 17 0x0000000000000000000000000000000000000000000000000000000000000000 0 0x0000000000000000000000000000000000000000000000000000000000000000 0 false}
    86   		{0x0000000000000000000000000000000000000000 [] [5 6 7 8] 18 0x0000000000000000000000000000000000000000000000000000000000000000 0 0x0000000000000000000000000000000000000000000000000000000000000000 0 false}`
    87  	addr := ethcmn.HexToAddress("0x5dE8a020088a2D6d0a23c204FFbeD02790466B49")
    88  	bloom := ethtypes.BytesToBloom([]byte{0x1, 0x3})
    89  	ret := []byte{0x5, 0x8}
    90  
    91  	data := ResultData{
    92  		ContractAddress: addr,
    93  		Bloom:           bloom,
    94  		Logs: []*ethtypes.Log{
    95  			{
    96  				Data:        []byte{1, 2, 3, 4},
    97  				BlockNumber: 17,
    98  			},
    99  			{
   100  				Data:        []byte{5, 6, 7, 8},
   101  				BlockNumber: 18,
   102  			}},
   103  		Ret: ret,
   104  	}
   105  
   106  	require.True(t, strings.EqualFold(expectedResultDataStr, data.String()))
   107  }
   108  
   109  func TestTxDecoder(t *testing.T) {
   110  	expectUint64, expectedBigInt, expectedBytes := uint64(1024), big.NewInt(1024), []byte("default payload")
   111  	expectedEthAddr := ethcmn.BytesToAddress([]byte("test_address"))
   112  	expectedEthMsg := NewMsgEthereumTx(expectUint64, &expectedEthAddr, expectedBigInt, expectUint64, expectedBigInt, expectedBytes)
   113  
   114  	// register codec
   115  	cdc := codec.New()
   116  	cdc.RegisterInterface((*sdk.Tx)(nil), nil)
   117  	RegisterCodec(cdc)
   118  
   119  	txbytes := cdc.MustMarshalBinaryLengthPrefixed(expectedEthMsg)
   120  	txDecoder := TxDecoder(cdc)
   121  	tx, err := txDecoder(txbytes)
   122  	require.NoError(t, err)
   123  
   124  	msgs := tx.GetMsgs()
   125  	require.Equal(t, 1, len(msgs))
   126  	require.NoError(t, msgs[0].ValidateBasic())
   127  	require.True(t, strings.EqualFold(expectedEthMsg.Route(), msgs[0].Route()))
   128  	require.True(t, strings.EqualFold(expectedEthMsg.Type(), msgs[0].Type()))
   129  
   130  	require.NoError(t, tx.ValidateBasic())
   131  
   132  	// error check
   133  	_, err = txDecoder([]byte{})
   134  	require.Error(t, err)
   135  
   136  	_, err = txDecoder(txbytes[1:])
   137  	require.Error(t, err)
   138  
   139  	oldHeight := types.GetMilestoneVenusHeight()
   140  	defer types.UnittestOnlySetMilestoneVenusHeight(oldHeight)
   141  	rlpBytes, err := rlp.EncodeToBytes(&expectedEthMsg)
   142  	require.Nil(t, err)
   143  
   144  	for _, c := range []struct {
   145  		curHeight          int64
   146  		venusHeight        int64
   147  		enableAminoDecoder bool
   148  		enableRLPDecoder   bool
   149  	}{
   150  		{999, 0, true, false},
   151  		{999, 1000, true, false},
   152  		{1000, 1000, false, true},
   153  		{1500, 1000, false, true},
   154  	} {
   155  		types.UnittestOnlySetMilestoneVenusHeight(c.venusHeight)
   156  		_, err = TxDecoder(cdc)(txbytes, c.curHeight)
   157  		require.Equal(t, c.enableAminoDecoder, err == nil)
   158  		_, err = TxDecoder(cdc)(rlpBytes, c.curHeight)
   159  		require.Equal(t, c.enableRLPDecoder, err == nil)
   160  
   161  		// use global height when height is not pass through parameters.
   162  		global.SetGlobalHeight(c.curHeight)
   163  		_, err = TxDecoder(cdc)(txbytes)
   164  		require.Equal(t, c.enableAminoDecoder, err == nil)
   165  		_, err = TxDecoder(cdc)(rlpBytes)
   166  		require.Equal(t, c.enableRLPDecoder, err == nil)
   167  	}
   168  }
   169  
   170  func TestEthLogAmino(t *testing.T) {
   171  	tests := []ethtypes.Log{
   172  		{},
   173  		{Topics: []ethcmn.Hash{}, Data: []byte{}},
   174  		{
   175  			Address: ethcmn.HexToAddress("0x5dE8a020088a2D6d0a23c204FFbeD02790466B49"),
   176  			Topics: []ethcmn.Hash{
   177  				ethcmn.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"),
   178  				ethcmn.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"),
   179  				ethcmn.HexToHash("0x1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF"),
   180  			},
   181  			Data:        []byte{1, 2, 3, 4},
   182  			BlockNumber: 17,
   183  			TxHash:      ethcmn.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"),
   184  			TxIndex:     123456,
   185  			BlockHash:   ethcmn.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"),
   186  			Index:       543121,
   187  			Removed:     false,
   188  		},
   189  		{
   190  			Address: ethcmn.HexToAddress("0x5dE8a020088a2D6d0a23c204FFbeD02790466B49"),
   191  			Topics: []ethcmn.Hash{
   192  				ethcmn.HexToHash("0x00000000FF0000000000000000000AC0000000000000EF000000000000000000"),
   193  				ethcmn.HexToHash("0x1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF"),
   194  			},
   195  			Data:        []byte{5, 6, 7, 8},
   196  			BlockNumber: math.MaxUint64,
   197  			TxHash:      ethcmn.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"),
   198  			TxIndex:     math.MaxUint,
   199  			BlockHash:   ethcmn.HexToHash("0x1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF"),
   200  			Index:       math.MaxUint,
   201  			Removed:     true,
   202  		},
   203  	}
   204  	cdc := codec.New()
   205  	for _, test := range tests {
   206  		bz, err := cdc.MarshalBinaryBare(test)
   207  		require.NoError(t, err)
   208  
   209  		bz2, err := MarshalEthLogToAmino(&test)
   210  		require.NoError(t, err)
   211  		require.EqualValues(t, bz, bz2)
   212  
   213  		var expect ethtypes.Log
   214  		err = cdc.UnmarshalBinaryBare(bz, &expect)
   215  		require.NoError(t, err)
   216  
   217  		actual, err := UnmarshalEthLogFromAmino(bz)
   218  		require.NoError(t, err)
   219  		require.EqualValues(t, expect, *actual)
   220  	}
   221  }
   222  
   223  func TestResultDataAmino(t *testing.T) {
   224  	addr := ethcmn.HexToAddress("0x5dE8a020088a2D6d0a23c204FFbeD02790466B49")
   225  	bloom := ethtypes.BytesToBloom([]byte{0x1, 0x3, 0x5, 0x7})
   226  	ret := []byte{0x5, 0x8}
   227  
   228  	cdc := codec.New()
   229  	cdc.RegisterInterface((*sdk.Tx)(nil), nil)
   230  	RegisterCodec(cdc)
   231  
   232  	testDataSet := []ResultData{
   233  		{},
   234  		{Logs: []*ethtypes.Log{}, Ret: []byte{}},
   235  		{
   236  			ContractAddress: addr,
   237  			Bloom:           bloom,
   238  			Logs: []*ethtypes.Log{
   239  				{
   240  					Data:        []byte{1, 2, 3, 4},
   241  					BlockNumber: 17,
   242  					Index:       10,
   243  				},
   244  				{
   245  					Data:        []byte{1, 2, 3, 4},
   246  					BlockNumber: 17,
   247  					Index:       10,
   248  				},
   249  				{
   250  					Data:        []byte{1, 2, 3, 4},
   251  					BlockNumber: 17,
   252  					Index:       10,
   253  				},
   254  				nil,
   255  			},
   256  			Ret:    ret,
   257  			TxHash: ethcmn.HexToHash("0x00"),
   258  		},
   259  		{
   260  			ContractAddress: addr,
   261  			Bloom:           bloom,
   262  			Logs: []*ethtypes.Log{
   263  				nil,
   264  				{
   265  					Removed: true,
   266  				},
   267  			},
   268  			Ret:    ret,
   269  			TxHash: ethcmn.HexToHash("0x00"),
   270  		},
   271  	}
   272  
   273  	for i, data := range testDataSet {
   274  		expect, err := cdc.MarshalBinaryBare(data)
   275  		require.NoError(t, err)
   276  
   277  		actual, err := data.MarshalToAmino(cdc)
   278  		require.NoError(t, err)
   279  		require.EqualValues(t, expect, actual)
   280  		t.Log(fmt.Sprintf("%d pass\n", i))
   281  
   282  		var expectRd ResultData
   283  		err = cdc.UnmarshalBinaryBare(expect, &expectRd)
   284  		require.NoError(t, err)
   285  		var actualRd ResultData
   286  		err = actualRd.UnmarshalFromAmino(cdc, expect)
   287  		require.NoError(t, err)
   288  		require.EqualValues(t, expectRd, actualRd)
   289  
   290  		encoded, err := EncodeResultData(&data)
   291  		require.NoError(t, err)
   292  		decodedRd, err := DecodeResultData(encoded)
   293  		require.NoError(t, err)
   294  		require.EqualValues(t, expectRd, decodedRd)
   295  	}
   296  }
   297  
   298  func BenchmarkDecodeResultData(b *testing.B) {
   299  	addr := ethcmn.HexToAddress("0x5dE8a020088a2D6d0a23c204FFbeD02790466B49")
   300  	bloom := ethtypes.BytesToBloom([]byte{0x1, 0x3})
   301  	ret := []byte{0x5, 0x8}
   302  
   303  	data := ResultData{
   304  		ContractAddress: addr,
   305  		Bloom:           bloom,
   306  		Logs: []*ethtypes.Log{{
   307  			Data:        []byte{1, 2, 3, 4},
   308  			BlockNumber: 17,
   309  		}},
   310  		Ret:    ret,
   311  		TxHash: ethcmn.BigToHash(big.NewInt(10)),
   312  	}
   313  
   314  	enc, err := EncodeResultData(&data)
   315  	require.NoError(b, err)
   316  	b.ResetTimer()
   317  	b.Run("amino", func(b *testing.B) {
   318  		for i := 0; i < b.N; i++ {
   319  			var rd ResultData
   320  			err = ModuleCdc.UnmarshalBinaryLengthPrefixed(enc, &rd)
   321  			if err != nil {
   322  				panic("err should be nil")
   323  			}
   324  		}
   325  	})
   326  	b.Run("unmarshaler", func(b *testing.B) {
   327  		for i := 0; i < b.N; i++ {
   328  			_, err = DecodeResultData(enc)
   329  			if err != nil {
   330  				panic("err should be nil")
   331  			}
   332  		}
   333  	})
   334  }
   335  
   336  func TestEthStringer(t *testing.T) {
   337  	max := 10
   338  	wg := &sync.WaitGroup{}
   339  	wg.Add(max)
   340  	for i := 0; i < max; i++ {
   341  		go func() {
   342  			addr := GenerateEthAddress()
   343  			h := addr.Hash()
   344  			require.Equal(t, addr.String(), EthAddressStringer(addr).String())
   345  			require.Equal(t, h.String(), EthHashStringer(h).String())
   346  			wg.Done()
   347  		}()
   348  	}
   349  	wg.Wait()
   350  }
   351  
   352  func BenchmarkEthAddressStringer(b *testing.B) {
   353  	addr := GenerateEthAddress()
   354  	b.ResetTimer()
   355  	b.Run("eth", func(b *testing.B) {
   356  		b.ReportAllocs()
   357  		for i := 0; i < b.N; i++ {
   358  			_ = addr.String()
   359  		}
   360  	})
   361  	b.Run("fbc stringer", func(b *testing.B) {
   362  		b.ReportAllocs()
   363  		for i := 0; i < b.N; i++ {
   364  			_ = EthAddressStringer(addr).String()
   365  		}
   366  	})
   367  }
   368  
   369  func BenchmarkEthHashStringer(b *testing.B) {
   370  	addr := GenerateEthAddress()
   371  	h := addr.Hash()
   372  	b.ResetTimer()
   373  	b.Run("eth", func(b *testing.B) {
   374  		b.ReportAllocs()
   375  		for i := 0; i < b.N; i++ {
   376  			_ = h.String()
   377  		}
   378  	})
   379  	b.Run("fbc stringer", func(b *testing.B) {
   380  		b.ReportAllocs()
   381  		for i := 0; i < b.N; i++ {
   382  			_ = EthHashStringer(h).String()
   383  		}
   384  	})
   385  }