Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(eth-rpc): Conversion types and functions between Ethereum txs and blocks and Tendermint ones. #1856

Merged
merged 16 commits into from
May 5, 2024

Conversation

Unique-Divine
Copy link
Member

@Unique-Divine Unique-Divine commented Apr 27, 2024

Purpose / Abstract

Tip

  1. Please review parent PRs first.

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added in-memory EventBus for real-time topic management and event distribution in Ethereum pubsub.
    • Introduced conversion types and functions for Ethereum transactions and blocks in relation to Tendermint.
    • Implemented new Ethereum RPC functionalities, including transaction conversion, block formatting, and error handling in transactions.
  • Bug Fixes

    • Updated import paths and corrected inconsistencies in key prefixes and function names for clarity and consistency.
  • Tests

    • Added comprehensive test suites for new functionalities in Ethereum pubsub, block handling, and Ethereum RPC types to ensure robustness and concurrency handling.
  • Documentation

    • Updated CHANGELOG and comments for better clarity and documentation of changes.
  • Chores

    • Modified import orders and updated environment variables in integration test workflows for improved development practices.

@Unique-Divine Unique-Divine requested a review from a team as a code owner April 27, 2024 01:50
Copy link
Contributor

coderabbitai bot commented Apr 27, 2024

Walkthrough

This update enhances Ethereum integration with features like in-memory EventBus for real-time event management, and new Ethereum RPC functionalities. It also includes significant refactoring, renaming the types package to eth and updating numerous references and import paths across various files. Testing enhancements and new functionalities in Ethereum transaction handling and RPC operations are notable additions.

Changes

Files or Directories Change Summary
eth-pubsub, eth-rpc Added EventBus for real-time event management and new Ethereum RPC functionalities.
eth/*.go, eth/crypto/hd/*.go, eth/eip712/*, eth/encoding/codec/codec.go, eth/encoding/config_test.go, eth/rpc/*, proto/eth/* Renamed package from types to eth and updated import paths and references.
eth/assert_test.go, eth/chain_id_test.go, eth/codec_test.go, eth/crypto/hd/algorithm_test.go, eth/crypto/hd/benchmark_test.go, eth/safe_math_test.go, eth/rpc/rpc_test.go, x/evm/genesis_test.go, x/evm/evmtest/eth_test.go Enhanced testing for various functionalities including Ethereum transactions, addresses, and safe math operations.
cmd/nibid/cmd/root.go, cmd/nibid/cmd/testnet.go Updated CLI descriptions and package aliases for better clarity and structure.
x/evm/README.md, x/evm/genesis.go, x/evm/params.go, x/evm/tx.go, x/evm/evmtest/eth.go Introduced and updated functionalities related to EVM genesis accounts, parameters, and transaction handling.

Poem

🐰🌟
In the land of code, where the bits do hop,
A rabbit worked, with no intent to stop.
From Ethereum's weave, to Tendermint's thread,
An EventBus blooms, and new paths are tread.
Cheers to the devs, with each merge and commit,
In the blockchain burrow, where the CodeRabbits sit!
🌟🐰


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

// Base app does not support queries for height less than or equal to 1, and
// the base app uses 0 indexing.
//
// Ethereum uses 1 indexing for the intial block height, therefore <= 2 means
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct the typographical error in the comment.

- // Ethereum uses 1 indexing for the intial block height, therefore <= 2 means
+ // Ethereum uses 1 indexing for the initial block height, therefore <= 2 means

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// Ethereum uses 1 indexing for the intial block height, therefore <= 2 means
// Ethereum uses 1 indexing for the initial block height, therefore <= 2 means

Comment on lines 68 to 85
// AddTopic adds a new topic with the specified name and message source
func (m *memEventBus) AddTopic(name string, src <-chan coretypes.ResultEvent) error {
m.topicsMux.RLock()
_, ok := m.topics[name]
m.topicsMux.RUnlock()

if ok {
return errors.New("topic already registered")
}

m.topicsMux.Lock()
m.topics[name] = src
m.topicsMux.Unlock()

go m.publishTopic(name, src)

return nil
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AddTopic method correctly handles the addition of new topics, including thread-safe checks and the initialization of the publishing goroutine. However, consider handling the potential race condition between checking if a topic exists and adding it. This could be mitigated by using a single write lock for the entire operation.

- m.topicsMux.RLock()
- _, ok := m.topics[name]
- m.topicsMux.RUnlock()
- if ok {
+ m.topicsMux.Lock()
+ if _, ok := m.topics[name]; ok {
+   m.topicsMux.Unlock()
    return errors.New("topic already registered")
  }
- m.topicsMux.Lock()
  m.topics[name] = src
  m.topicsMux.Unlock()

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// AddTopic adds a new topic with the specified name and message source
func (m *memEventBus) AddTopic(name string, src <-chan coretypes.ResultEvent) error {
m.topicsMux.RLock()
_, ok := m.topics[name]
m.topicsMux.RUnlock()
if ok {
return errors.New("topic already registered")
}
m.topicsMux.Lock()
m.topics[name] = src
m.topicsMux.Unlock()
go m.publishTopic(name, src)
return nil
}
// AddTopic adds a new topic with the specified name and message source
func (m *memEventBus) AddTopic(name string, src <-chan coretypes.ResultEvent) error {
m.topicsMux.Lock()
if _, ok := m.topics[name]; ok {
m.topicsMux.Unlock()
return errors.New("topic already registered")
}
m.topics[name] = src
m.topicsMux.Unlock()
go m.publishTopic(name, src)
return nil
}

Copy link

codecov bot commented Apr 27, 2024

Codecov Report

Attention: Patch coverage is 58.47619% with 218 lines in your changes are missing coverage. Please review.

Project coverage is 71.97%. Comparing base (ffcea96) to head (045cf6d).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1856      +/-   ##
==========================================
+ Coverage   68.59%   71.97%   +3.37%     
==========================================
  Files         176      183       +7     
  Lines       10091    10514     +423     
==========================================
+ Hits         6922     7567     +645     
+ Misses       2747     2475     -272     
- Partials      422      472      +50     
Files Coverage Δ
cmd/nibid/cmd/testnet.go 73.30% <100.00%> (ø)
eth/assert.go 100.00% <ø> (ø)
eth/chain_id.go 86.66% <ø> (ø)
eth/codec.go 100.00% <100.00%> (ø)
eth/crypto/ethsecp256k1/ethsecp256k1.go 68.67% <ø> (ø)
eth/eip712/domain.go 100.00% <ø> (ø)
eth/eip712/eip712.go 100.00% <ø> (ø)
eth/eip712/encoding.go 80.70% <100.00%> (ø)
eth/eip712/encoding_legacy.go 79.41% <100.00%> (ø)
eth/eip712/message.go 84.12% <ø> (ø)
... and 28 more

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Out of diff range and nitpick comments (2)
eth/eip712/preprocess_test.go (1)

Line range hint 19-20: Handling of nil input should be checked before other conditions to avoid potential null pointer dereferences.

- } else if i == nil {
+ if i == nil {
eth/types/chain_id_test.go (1)

54-56: Ensure that the test case description accurately reflects the test scenario. The description "cannot invalid base" seems grammatically incorrect and unclear.

Comment on lines +19 to +20
} else if i == nil {
return sdkmath.Int{}, fmt.Errorf("received nil pointer for *big.Int")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Properly handle nil input before other conditions to prevent null pointer dereferences.

- } else if i == nil {
+ if i == nil {

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
} else if i == nil {
return sdkmath.Int{}, fmt.Errorf("received nil pointer for *big.Int")
if i == nil {
return sdkmath.Int{}, fmt.Errorf("received nil pointer for *big.Int")

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

Out of diff range and nitpick comments (11)
eth/assert.go (1)

Line range hint 18-18: The function ValidateAddress uses common.IsHexAddress for validation, which is appropriate. However, consider adding a comment to clarify what constitutes a valid Ethereum address for readers unfamiliar with Ethereum's address format.

x/evm/codec.go (2)

Line range hint 14-14: Consider adding unit tests for the init function to ensure that the legacy Amino codec is registered correctly.

Would you like me to help by creating a test case for this function?


Line range hint 49-49: The registration of transaction types should be accompanied by documentation explaining each type's use case and structure.

Consider adding comments detailing the purpose and structure of DynamicFeeTx, AccessListTx, and LegacyTx.

eth/state_encoder_test.go (1)

87-88: The panic handling in TestEncoderEthAddr is appropriate, but consider adding a specific test case to document what conditions lead to a panic.

It would be beneficial to add a comment or a test case that explicitly states under what conditions a panic is expected in TestEncoderEthAddr.

eth/assert_test.go (1)

36-57: The function IsZeroAddress is tested well. Consider adding a performance benchmark to assess the function's efficiency, especially if used frequently in the codebase.

Consider adding a performance benchmark for IsZeroAddress to evaluate its efficiency under load.

eth/crypto/hd/algorithm_test.go (1)

Line range hint 90-108: Refactor to use table-driven tests for better maintainability.

+ tests := []struct {
+   name string
+   path string
+   expectError bool
+ }{
+   {"valid path", eth.BIP44HDPath, false},
+   {"invalid path", "44'/60'/0'/0/0", true},
+ }
+ for _, tc := range tests {
+   t.Run(tc.name, func(t *testing.T) {
+     bz, err := EthSecp256k1.Derive()(mnemonic, keyring.DefaultBIP39Passphrase, tc.path)
+     if tc.expectError {
+       require.Error(t, err)
+     } else {
+       require.NoError(t, err)
+       require.NotEmpty(t, bz)
+     }
+   })
+ }

This test case can be refactored into a table-driven format to enhance readability and maintainability. This approach allows easy addition of new test scenarios and makes the test cases more structured.

x/evm/errors.go (1)

2-2: Ensure the package comment is present for better code documentation.

Consider adding a package comment at the beginning of the file to explain the purpose and scope of the evm package. This enhances code readability and maintainability, especially for new contributors.

x/evm/legacy_tx.go (1)

Line range hint 129-196: Refactor AsEthereumData to improve error handling.

+ if err := tx.Validate(); err != nil {
+   return nil, err
+ }
  return &gethcore.LegacyTx{
    Nonce:    tx.GetNonce(),
    GasPrice: tx.GetGasPrice(),
    Gas:      tx.GetGas(),
    To:       tx.GetTo(),
    Value:    tx.GetValue(),
    Data:     tx.GetData(),
    V:        v,
    R:        r,
    S:        s,
  }, nil

Consider adding a validation step in the AsEthereumData method to ensure that the transaction data is valid before constructing the gethcore.LegacyTx object. This can prevent issues downstream where invalid data might be processed.

eth/rpc/block.go (1)

1-1: Ensure the file has a proper header comment.

Add a header comment at the beginning of the file to explain its purpose and the types of functions it contains. This helps in maintaining a good documentation standard and aids new developers in understanding the file's role in the project.

x/evm/chain_config.go (1)

2-2: Consider adding more detailed comments for each configuration parameter.

Enhance the documentation within the ChainConfig structure by adding detailed comments for each parameter, explaining its purpose and impact. This improves code readability and helps maintainers and developers understand the configuration options better.

proto/eth/evm/v1/tx.proto (1)

12-12: Enhance documentation for each protobuf message.

Add detailed comments for each protobuf message and field to explain their purpose and usage. This is particularly important for complex fields or those with non-obvious implications, as it aids in understanding and maintaining the code.

@@ -363,7 +363,7 @@ func (s *StateDB) Suicide(addr common.Address) bool {
// - Add the contents of the optional tx access list (2930)
//
// This method should only be called if Yolov3/Berlin/2929+2930 is applicable at the current number.
func (s *StateDB) PrepareAccessList(sender common.Address, dst *common.Address, precompiles []common.Address, list ethtypes.AccessList) {
func (s *StateDB) PrepareAccessList(sender common.Address, dst *common.Address, precompiles []common.Address, list gethcore.AccessList) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review the implementation of PrepareAccessList for potential optimization.

Consider refactoring the method to reduce redundancy and improve performance, especially in scenarios with large access lists.

evm.QueryClient
}

// NewQueryClient creates a new gRPC query client
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The NewQueryClient function is implemented correctly to instantiate a QueryClient. However, ensure that the TODO comment is addressed promptly as it relates to critical testing.

Would you like me to help with implementing the test for GetProof as mentioned in the TODO comment?

@@ -61,7 +61,7 @@ func TestKeyring(t *testing.T) {
require.NoError(t, err)
require.Equal(t, string(EthSecp256k1Type), pubKey.Type())

hdPath := ethtypes.BIP44HDPath
hdPath := eth.BIP44HDPath
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider handling potential data races when setting environment variables.

+ sync.Mutex.Lock()
  os.Setenv(hdWalletFixEnv, "true")
  wallet, err := NewFromMnemonic(mnemonic)
  os.Setenv(hdWalletFixEnv, "")
+ sync.Mutex.Unlock()

Using environment variables in tests can lead to data races when tests are run in parallel. Consider using a mutex to synchronize access to environment variables or refactor to use instance-specific configuration.


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
hdPath := eth.BIP44HDPath
hdPath := eth.BIP44HDPath
sync.Mutex.Lock()
os.Setenv(hdWalletFixEnv, "true")
wallet, err := NewFromMnemonic(mnemonic)
os.Setenv(hdWalletFixEnv, "")
sync.Mutex.Unlock()

@@ -1,5 +1,5 @@
// Copyright (c) 2023-2024 Nibi, Inc.
package types
package evm
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding unit tests for NewExecErrorWithReason.

It appears that there are no unit tests for the NewExecErrorWithReason function. Would you like me to help by writing some test cases or should I open a GitHub issue to track this task?

@@ -72,7 +72,7 @@ func (tx *LegacyTx) GetChainID() *big.Int {
}

// GetAccessList returns nil
func (tx *LegacyTx) GetAccessList() geth.AccessList {
func (tx *LegacyTx) GetAccessList() gethcore.AccessList {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add support for access lists if applicable.

Legacy transactions do not support access lists, but if there is a requirement to simulate or convert to a type that supports them, consider implementing this functionality. Would you like assistance with this?

@@ -1,5 +1,5 @@
// Copyright (c) 2023-2024 Nibi, Inc.
package types
package evm
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding more comprehensive tests for access list transactions.

Given the complexity of access list transactions, consider adding more comprehensive tests to cover various edge cases and error conditions. Would you like help in writing these tests or should I open a GitHub issue to track this task?

Comment on lines +91 to +120
func (s *SuiteSafeMath) TestSafeInt64() {
tests := []struct {
name string
input uint64
expectErr bool
}{
{
name: "Valid conversion",
input: maxInt64, // Maximum value for int64
expectErr: false,
},
{
name: "Invalid conversion causes overflow",
input: uint64(maxInt64) + 1, // Exceeds maximum int64 value
expectErr: true,
},
}

for _, tc := range tests {
s.Run(tc.name, func() {
result, err := eth.SafeInt64(tc.input)
if tc.expectErr {
s.Error(err, "Expected an error due to overflow but did not get one")
} else {
s.NoError(err, "Did not expect an error but got one")
s.Equal(int64(tc.input), result, "The results should match")
}
})
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests for SafeInt64 handle edge cases well. Consider adding a test for the boundary condition where the input is just below the overflow threshold.

Would you like me to add a test case for the boundary condition in SafeInt64?

Comment on lines +93 to +101
func filterImplsForEth(implTypeUrls []string) []string {
typeUrls := []string{}
for _, typeUrl := range implTypeUrls {
if strings.Contains(typeUrl, "eth") {
typeUrls = append(typeUrls, typeUrl)
}
}
return typeUrls
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function filterImplsForEth is used to filter implementations. Consider adding a test specifically for this function to ensure its correctness across a range of inputs.

Would you like me to help by creating a test case for the filterImplsForEth function?

Comment on lines +102 to +126
// TestConcurrentAccess: Tests the system's behavior under high concurrency,
// specifically ensuring that the lock can handle multiple locking and unlocking
// operations on the same address without leading to race conditions or
// deadlocks.
func (s *SuiteAddrLocker) TestConcurrentAccess() {
locker := &rpc.AddrLocker{}
addr := common.HexToAddress("0x789")
var wg sync.WaitGroup

// Spawn 100 goroutines, each locking and unlocking the same address.
// Each routine will hod the lock briefly to simulate work done during the
// lock (like an Ethereum query).
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
locker.LockAddr(addr)
time.Sleep(time.Millisecond * 5) // Simulate work
locker.UnlockAddr(addr)
wg.Done()
}()
}

// Cleanup: Wait for all goroutines to complete
wg.Wait()
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TestConcurrentAccess test is essential for ensuring that the locking mechanism can handle high levels of concurrency without issues. Consider adding more varied scenarios to this test to cover more complex interactions.

Would you like me to add more scenarios to the TestConcurrentAccess test to cover more complex interactions?

Comment on lines +61 to +73
// OverrideAccount indicates the overriding fields of account during the execution of
// a message call.
// Note, state and stateDiff can't be specified at the same time. If state is
// set, message execution will only use the data in the given state. Otherwise
// if statDiff is set, all diff will be applied first and then execute the call
// message.
type OverrideAccount struct {
Nonce *hexutil.Uint64 `json:"nonce"`
Code *hexutil.Bytes `json:"code"`
Balance **hexutil.Big `json:"balance"`
State *map[common.Hash]common.Hash `json:"state"`
StateDiff *map[common.Hash]common.Hash `json:"stateDiff"`
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OverrideAccount type allows for state overrides during message calls. It's crucial to ensure that this functionality is secure and does not introduce potential vulnerabilities.

Consider adding security audits or reviews specifically for the functionality provided by OverrideAccount to ensure it does not introduce security vulnerabilities.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Comment on lines +24 to +63
func (s *SuiteStorage) TestStorageValidate() {
testCases := []struct {
name string
storage Storage
wantPass bool
}{
{
name: "valid storage",
storage: Storage{
NewStateFromEthHashes(common.BytesToHash([]byte{1, 2, 3}), common.BytesToHash([]byte{1, 2, 3})),
},
wantPass: true,
},
{
name: "empty storage key bytes",
storage: Storage{
{Key: ""},
},
wantPass: false,
},
{
name: "duplicated storage key",
storage: Storage{
{Key: common.BytesToHash([]byte{1, 2, 3}).String()},
{Key: common.BytesToHash([]byte{1, 2, 3}).String()},
},
wantPass: false,
},
}

for _, tc := range testCases {
tc := tc
err := tc.storage.Validate()
if tc.wantPass {
s.NoError(err, tc.name)
} else {
s.Error(err, tc.name)
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using descriptive variable names or adding comments for byte arrays used as keys to enhance readability.

- NewStateFromEthHashes(common.BytesToHash([]byte{1, 2, 3}), common.BytesToHash([]byte{1, 2, 3})),
+ keyBytes := []byte{1, 2, 3}
+ NewStateFromEthHashes(common.BytesToHash(keyBytes), common.BytesToHash(keyBytes)),

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
func (s *SuiteStorage) TestStorageValidate() {
testCases := []struct {
name string
storage Storage
wantPass bool
}{
{
name: "valid storage",
storage: Storage{
NewStateFromEthHashes(common.BytesToHash([]byte{1, 2, 3}), common.BytesToHash([]byte{1, 2, 3})),
},
wantPass: true,
},
{
name: "empty storage key bytes",
storage: Storage{
{Key: ""},
},
wantPass: false,
},
{
name: "duplicated storage key",
storage: Storage{
{Key: common.BytesToHash([]byte{1, 2, 3}).String()},
{Key: common.BytesToHash([]byte{1, 2, 3}).String()},
},
wantPass: false,
},
}
for _, tc := range testCases {
tc := tc
err := tc.storage.Validate()
if tc.wantPass {
s.NoError(err, tc.name)
} else {
s.Error(err, tc.name)
}
}
}
func (s *SuiteStorage) TestStorageValidate() {
testCases := []struct {
name string
storage Storage
wantPass bool
}{
{
name: "valid storage",
storage: Storage{
keyBytes := []byte{1, 2, 3}
NewStateFromEthHashes(common.BytesToHash(keyBytes), common.BytesToHash(keyBytes)),
},
wantPass: true,
},
{
name: "empty storage key bytes",
storage: Storage{
{Key: ""},
},
wantPass: false,
},
{
name: "duplicated storage key",
storage: Storage{
{Key: common.BytesToHash([]byte{1, 2, 3}).String()},
{Key: common.BytesToHash([]byte{1, 2, 3}).String()},
},
wantPass: false,
},
}
for _, tc := range testCases {
tc := tc
err := tc.storage.Validate()
if tc.wantPass {
s.NoError(err, tc.name)
} else {
s.Error(err, tc.name)
}
}
}

Comment on lines +58 to +81
func (s *MsgsSuite) TestMsgEthereumTx_Constructor() {
evmTx := &evm.EvmTxArgs{
Nonce: 0,
To: &s.to,
GasLimit: 100000,
Input: []byte("test"),
}
msg := evm.NewTx(evmTx)

// suite.Require().Equal(msg.Data.To, suite.to.Hex())
s.Require().Equal(msg.Route(), evm.RouterKey)
s.Require().Equal(msg.Type(), evm.TypeMsgEthereumTx)
// suite.Require().NotNil(msg.To())
s.Require().Equal(msg.GetMsgs(), []sdk.Msg{msg})
s.Require().Panics(func() { msg.GetSigners() })
s.Require().Panics(func() { msg.GetSignBytes() })

evmTx2 := &evm.EvmTxArgs{
Nonce: 0,
GasLimit: 100000,
Input: []byte("test"),
}
msg = evm.NewTx(evmTx2)
s.Require().NotNil(msg)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider removing or uncommenting the commented-out assertions to clarify their necessity for the test.

- // suite.Require().Equal(msg.Data.To, suite.to.Hex())
- // suite.Require().NotNil(msg.To())

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
func (s *MsgsSuite) TestMsgEthereumTx_Constructor() {
evmTx := &evm.EvmTxArgs{
Nonce: 0,
To: &s.to,
GasLimit: 100000,
Input: []byte("test"),
}
msg := evm.NewTx(evmTx)
// suite.Require().Equal(msg.Data.To, suite.to.Hex())
s.Require().Equal(msg.Route(), evm.RouterKey)
s.Require().Equal(msg.Type(), evm.TypeMsgEthereumTx)
// suite.Require().NotNil(msg.To())
s.Require().Equal(msg.GetMsgs(), []sdk.Msg{msg})
s.Require().Panics(func() { msg.GetSigners() })
s.Require().Panics(func() { msg.GetSignBytes() })
evmTx2 := &evm.EvmTxArgs{
Nonce: 0,
GasLimit: 100000,
Input: []byte("test"),
}
msg = evm.NewTx(evmTx2)
s.Require().NotNil(msg)
func (s *MsgsSuite) TestMsgEthereumTx_Constructor() {
evmTx := &evm.EvmTxArgs{
Nonce: 0,
To: &s.to,
GasLimit: 100000,
Input: []byte("test"),
}
msg := evm.NewTx(evmTx)
s.Require().Equal(msg.Route(), evm.RouterKey)
s.Require().Equal(msg.Type(), evm.TypeMsgEthereumTx)
s.Require().Equal(msg.GetMsgs(), []sdk.Msg{msg})
s.Require().Panics(func() { msg.GetSigners() })
s.Require().Panics(func() { msg.GetSignBytes() })
evmTx2 := &evm.EvmTxArgs{
Nonce: 0,
GasLimit: 100000,
Input: []byte("test"),
}
msg = evm.NewTx(evmTx2)
s.Require().NotNil(msg)
}

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Out of diff range and nitpick comments (1)
cmd/nibid/cmd/root.go (1)

Line range hint 51-78: Ensure consistency in command descriptions and error handling in NewRootCmd.

- cmd.SetOut(cmd.OutOrStdout())
- cmd.SetErr(cmd.ErrOrStderr())
+ // Ensure standard output and error streams are set for the command
+ cmd.SetOut(cmd.OutOrStdout())
+ cmd.SetErr(cmd.ErrOrStderr())
Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between 14f8a2c and db03210.
Files ignored due to path filters (2)
  • go.mod is excluded by !**/*.mod, !**/*.mod
  • go.sum is excluded by !**/*.sum, !**/*.sum
Files selected for processing (10)
  • cmd/nibid/cmd/root.go (5 hunks)
  • cmd/nibid/cmd/testnet.go (1 hunks)
  • eth/rpc/rpc.go (1 hunks)
  • eth/rpc/rpc_test.go (1 hunks)
  • eth/state_encoder.go (2 hunks)
  • x/evm/README.md (1 hunks)
  • x/evm/evmtest/eth.go (1 hunks)
  • x/evm/evmtest/eth_test.go (1 hunks)
  • x/evm/params.go (3 hunks)
  • x/evm/tx.go (10 hunks)
Files skipped from review due to trivial changes (2)
  • cmd/nibid/cmd/testnet.go
  • x/evm/README.md
Files skipped from review as they are similar to previous changes (4)
  • eth/rpc/rpc.go
  • eth/state_encoder.go
  • x/evm/params.go
  • x/evm/tx.go
Additional comments not posted (1)
x/evm/evmtest/eth_test.go (1)

20-33: Ensure proper error handling in TestSampleFns.

Verification successful

The error handling in the function TestSampleFns within eth_test.go has been verified. The use of s.NoError is appropriately implemented to check for errors after operations that could potentially fail. This confirms that the error handling is as expected based on the review comment.

  • s.NoError(err) is used after creating a new Ethereum transaction message to ensure no errors occurred.
  • s.NoError(ethTxMsg.ValidateBasic()) is used to check each Ethereum transaction message in a loop, ensuring each message is valid.
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify proper error handling in TestSampleFns.

# Test: Search for error handling patterns in TestSampleFns. Expect: Proper error handling.
rg --type go 's.NoError' 'x/evm/evmtest/eth_test.go'

Length of output: 104

Comment on lines +25 to +59
func (s *SuiteRPC) TestRawTxToEthTx() {
type TestCase struct {
tx cmt.Tx
clientCtx client.Context
wantErr string
}
type TestCaseSetupFn = func() TestCase

for _, tcSetup := range []TestCaseSetupFn{
func() TestCase {
_, _, clientCtx := evmtest.NewEthTxMsgAsCmt(s.T())
txBz := []byte("tx")
return TestCase{
tx: txBz, // invalid bytes
clientCtx: clientCtx, // valid clientCtx
wantErr: "failed to unmarshal JSON",
}
},
func() TestCase {
txBz, _, clientCtx := evmtest.NewEthTxMsgAsCmt(s.T())
return TestCase{
tx: txBz, // valid bytes
clientCtx: clientCtx, // valid clientCtx
wantErr: "", // happy
}
},
} {
tc := tcSetup()
ethTxs, err := rpc.RawTxToEthTx(tc.clientCtx, tc.tx)
if tc.wantErr != "" {
s.Require().ErrorContains(err, tc.wantErr, "ethTxs: %s", ethTxs)
continue
}
s.Require().NoError(err, "ethTxs: %s", ethTxs)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactor test cases in TestRawTxToEthTx for clarity and maintainability.

- for _, tcSetup := range []TestCaseSetupFn{
-   func() TestCase {
-     _, _, clientCtx := evmtest.NewEthTxMsgAsCmt(s.T())
-     txBz := []byte("tx")
-     return TestCase{
-       tx:        txBz,      // invalid bytes
-       clientCtx: clientCtx, // valid clientCtx
-       wantErr:   "failed to unmarshal JSON",
-     }
-   },
-   func() TestCase {
-     txBz, _, clientCtx := evmtest.NewEthTxMsgAsCmt(s.T())
-     return TestCase{
-       tx:        txBz,      // valid bytes
-       clientCtx: clientCtx, // valid clientCtx
-       wantErr:   "",        // happy
-     }
-   },
- } {
+ testCases := []TestCase{
+   {
+     tx:        []byte("tx"), // invalid bytes
+     clientCtx: evmtest.NewEthTxMsgAsCmt(s.T()).clientCtx, // valid clientCtx
+     wantErr:   "failed to unmarshal JSON",
+   },
+   {
+     tx:        evmtest.NewEthTxMsgAsCmt(s.T()).txBz, // valid bytes
+     clientCtx: evmtest.NewEthTxMsgAsCmt(s.T()).clientCtx, // valid clientCtx
+     wantErr:   "", // happy
+   },
+ }
+ for _, tc := range testCases {

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
func (s *SuiteRPC) TestRawTxToEthTx() {
type TestCase struct {
tx cmt.Tx
clientCtx client.Context
wantErr string
}
type TestCaseSetupFn = func() TestCase
for _, tcSetup := range []TestCaseSetupFn{
func() TestCase {
_, _, clientCtx := evmtest.NewEthTxMsgAsCmt(s.T())
txBz := []byte("tx")
return TestCase{
tx: txBz, // invalid bytes
clientCtx: clientCtx, // valid clientCtx
wantErr: "failed to unmarshal JSON",
}
},
func() TestCase {
txBz, _, clientCtx := evmtest.NewEthTxMsgAsCmt(s.T())
return TestCase{
tx: txBz, // valid bytes
clientCtx: clientCtx, // valid clientCtx
wantErr: "", // happy
}
},
} {
tc := tcSetup()
ethTxs, err := rpc.RawTxToEthTx(tc.clientCtx, tc.tx)
if tc.wantErr != "" {
s.Require().ErrorContains(err, tc.wantErr, "ethTxs: %s", ethTxs)
continue
}
s.Require().NoError(err, "ethTxs: %s", ethTxs)
}
func (s *SuiteRPC) TestRawTxToEthTx() {
type TestCase struct {
tx cmt.Tx
clientCtx client.Context
wantErr string
}
type TestCaseSetupFn = func() TestCase
testCases := []TestCase{
{
tx: []byte("tx"), // invalid bytes
clientCtx: evmtest.NewEthTxMsgAsCmt(s.T()).clientCtx, // valid clientCtx
wantErr: "failed to unmarshal JSON",
},
{
tx: evmtest.NewEthTxMsgAsCmt(s.T()).txBz, // valid bytes
clientCtx: evmtest.NewEthTxMsgAsCmt(s.T()).clientCtx, // valid clientCtx
wantErr: "", // happy
},
}
for _, tc := range testCases {
ethTxs, err := rpc.RawTxToEthTx(tc.clientCtx, tc.tx)
if tc.wantErr != "" {
s.Require().ErrorContains(err, tc.wantErr, "ethTxs: %s", ethTxs)
continue
}
s.Require().NoError(err, "ethTxs: %s", ethTxs)
}

Comment on lines +45 to +72
// NewEthTxMsgAsCmt: Helper that returns an Ethereum tx msg converted into
// tx bytes used in the Consensus Engine.
func NewEthTxMsgAsCmt(t *testing.T) (
txBz cmt.Tx,
ethTxMsgs []*evm.MsgEthereumTx,
clientCtx client.Context,
) {
// Build a TxBuilder that can understand Ethereum types
encCfg := encoding.MakeConfig(app.ModuleBasics)
evm.RegisterInterfaces(encCfg.InterfaceRegistry)
eth.RegisterInterfaces(encCfg.InterfaceRegistry)
txConfig := encCfg.TxConfig
clientCtx = client.Context{
TxConfig: txConfig,
InterfaceRegistry: encCfg.InterfaceRegistry,
}
txBuilder := clientCtx.TxConfig.NewTxBuilder()

// Build a consensus tx with a few Eth tx msgs
ethTxMsgs = NewEthTxMsgs(3)
assert.NoError(t,
txBuilder.SetMsgs(ethTxMsgs[0], ethTxMsgs[1], ethTxMsgs[2]),
)
tx := txBuilder.GetTx()
txBz, err := clientCtx.TxConfig.TxEncoder()(tx)
assert.NoError(t, err)
return txBz, ethTxMsgs, clientCtx
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optimize NewEthTxMsgAsCmt by reducing redundancy in transaction message creation.

- ethTxMsgs = NewEthTxMsgs(3)
- assert.NoError(t,
-   txBuilder.SetMsgs(ethTxMsgs[0], ethTxMsgs[1], ethTxMsgs[2]),
- )
+ ethTxMsgs = NewEthTxMsgs(3)
+ assert.NoError(t, txBuilder.SetMsgs(ethTxMsgs...))

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// NewEthTxMsgAsCmt: Helper that returns an Ethereum tx msg converted into
// tx bytes used in the Consensus Engine.
func NewEthTxMsgAsCmt(t *testing.T) (
txBz cmt.Tx,
ethTxMsgs []*evm.MsgEthereumTx,
clientCtx client.Context,
) {
// Build a TxBuilder that can understand Ethereum types
encCfg := encoding.MakeConfig(app.ModuleBasics)
evm.RegisterInterfaces(encCfg.InterfaceRegistry)
eth.RegisterInterfaces(encCfg.InterfaceRegistry)
txConfig := encCfg.TxConfig
clientCtx = client.Context{
TxConfig: txConfig,
InterfaceRegistry: encCfg.InterfaceRegistry,
}
txBuilder := clientCtx.TxConfig.NewTxBuilder()
// Build a consensus tx with a few Eth tx msgs
ethTxMsgs = NewEthTxMsgs(3)
assert.NoError(t,
txBuilder.SetMsgs(ethTxMsgs[0], ethTxMsgs[1], ethTxMsgs[2]),
)
tx := txBuilder.GetTx()
txBz, err := clientCtx.TxConfig.TxEncoder()(tx)
assert.NoError(t, err)
return txBz, ethTxMsgs, clientCtx
}
// NewEthTxMsgAsCmt: Helper that returns an Ethereum tx msg converted into
// tx bytes used in the Consensus Engine.
func NewEthTxMsgAsCmt(t *testing.T) (
txBz cmt.Tx,
ethTxMsgs []*evm.MsgEthereumTx,
clientCtx client.Context,
) {
// Build a TxBuilder that can understand Ethereum types
encCfg := encoding.MakeConfig(app.ModuleBasics)
evm.RegisterInterfaces(encCfg.InterfaceRegistry)
eth.RegisterInterfaces(encCfg.InterfaceRegistry)
txConfig := encCfg.TxConfig
clientCtx = client.Context{
TxConfig: txConfig,
InterfaceRegistry: encCfg.InterfaceRegistry,
}
txBuilder := clientCtx.TxConfig.NewTxBuilder()
// Build a consensus tx with a few Eth tx msgs
ethTxMsgs = NewEthTxMsgs(3)
assert.NoError(t, txBuilder.SetMsgs(ethTxMsgs...))
tx := txBuilder.GetTx()
txBz, err := clientCtx.TxConfig.TxEncoder()(tx)
assert.NoError(t, err)
return txBz, ethTxMsgs, clientCtx
}

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between db03210 and 045cf6d.
Files selected for processing (1)
  • CHANGELOG.md (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.md

@Unique-Divine Unique-Divine merged commit 2bd7a14 into main May 5, 2024
13 of 15 checks passed
@Unique-Divine Unique-Divine deleted the ud/evm-rpc branch May 5, 2024 21:22
@Unique-Divine Unique-Divine added the x: evm Relates to Nibiru EVM or the EVM Module label May 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
x: evm Relates to Nibiru EVM or the EVM Module
Projects
Status: ✅ Completed
Development

Successfully merging this pull request may close these issues.

1 participant