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 }