-
Notifications
You must be signed in to change notification settings - Fork 10
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
Local state using remote registers #562
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThe pull request introduces significant changes across multiple files, primarily focused on refactoring the client implementations from the Changes
Possibly related PRs
Suggested labels
Poem
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? TipsChatThere are 3 ways to chat with CodeRabbit:
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 using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 11
Outside diff range and nitpick comments (11)
services/evm/remote_ledger.go (2)
19-21
: Implement caching mechanism as per TODO comments.The TODO comments suggest adding a register cache for specific cadence heights using a two-queue cache (2q) from
golang-lru/v2
. Implementing this cache could improve performance by reducing redundant register fetches and enhancing local state management.Would you like assistance in implementing this caching mechanism or opening a GitHub issue to track this task?
Line range hint
112-123
: Pass context from caller instead of usingcontext.Background()
.In the
getRegister
method, usingcontext.Background()
does not allow for request cancellation or deadlines, which can be important for resource management and responsive systems.Modify
getRegister
to accept acontext.Context
parameter:-func (l *remoteLedger) getRegister(registerID flow.RegisterID) ([]byte, error) { +func (l *remoteLedger) getRegister(ctx context.Context, registerID flow.RegisterID) ([]byte, error) {Update the method body to use the provided context:
- response, err := l.execution.GetRegisterValues( - context.Background(), + response, err := l.execution.GetRegisterValues( + ctx, &executiondata.GetRegisterValuesRequest{ BlockHeight: l.height, RegisterIds: []*entities.RegisterID{id}, }, )Also, update all calls to
getRegister
to pass an appropriate context, potentially allowing for cancellation and timeouts:func (l *remoteLedger) GetValue(owner, key []byte) ([]byte, error) { // ... + ctx := /* obtain context from caller or create one */ register, err := l.getRegister(ctx, id) // ... }
services/evm/executor.go (4)
21-21
: UpdateStateDB
toReadOnlyView
as indicatedThe struct field on line 21 uses
types.StateDB
, but the inline comment suggests changing it totypes.ReadOnlyView
. Consider making this update to reflect the intended design.Would you like assistance in refactoring the code to use
types.ReadOnlyView
?
139-139
: Implement tracer for enhanced debuggingLine 139 sets
Tracer: nil
with a TODO comment about handling the tracer. Implementing a tracer can be valuable for debugging and monitoring transaction execution.Would you like assistance in setting up a tracer or integrating tracing capabilities?
141-142
: SetExtraPrecompiledContracts
if requiredThe commented-out line on 141 hints at potentially setting
ExtraPrecompiledContracts
. If your application relies on additional precompiled contracts, you should configure them here.Do you need help determining which precompiled contracts to include and how to set them?
43-47
: Handle potential ledger initialization errors gracefullyIn the
NewBlockExecutor
function, ifstate.NewStateDB
fails (lines 43-47), the error is returned directly. Ensure that the error provides sufficient context for troubleshooting.Consider wrapping the error to include additional context:
if err != nil { - return nil, err + return nil, fmt.Errorf("failed to initialize StateDB: %w", err) }bootstrap/bootstrap.go (1)
212-212
: Enhance error message for clarityWhen handling the error returned by
evm.NewEVM
, the current error message refers to "EVM requester," which may not accurately reflect the component being initialized.Update the error message for better clarity:
if err != nil { - return fmt.Errorf("failed to create EVM requester: %w", err) + return fmt.Errorf("failed to initialize EVM instance: %w", err) }services/evm/client.go (4)
54-57
: Address the TODO: Extract transaction submission logicThe TODO comment suggests that transaction submission should be extracted into another type, possibly
FlowClient
, whileEVMClient
should handle only state queries and execution of calls and gas estimations. Separating these concerns can improve code organization and clarity.Would you like assistance in refactoring the code to implement this separation, or should I open a new GitHub issue to track this task?
Line range hint
118-194
: Consider renamingNewEVM
toNewRemoteClient
for consistencyThe function
NewEVM
initializes and returns a*RemoteClient
. To enhance code clarity and maintain consistency, consider renaming the function toNewRemoteClient
.Apply this diff to rename the function and update references:
-func NewEVM( +func NewRemoteClient( client *CrossSporkClient, config *config.Config, signer crypto.Signer, logger zerolog.Logger, blocks storage.BlockIndexer, txPool *TxPool, collector metrics.Collector, ) (*RemoteClient, error) { ... }Ensure all calls to
NewEVM
are updated accordingly.
Line range hint
462-480
: Ensure robust address replacement inreplaceAddresses
functionThe
replaceAddresses
function manually replaces import statements and addresses in the script usingstrings.ReplaceAll
. To enhance robustness and prevent potential issues with partial matches or malformed scripts, consider using regular expressions for pattern matching and replacement.Use
regexp
to accurately match import statements:import "regexp" // At the beginning of the function var importRegex = regexp.MustCompile(`import\s+(\w+)`) func (e *RemoteClient) replaceAddresses(script []byte) []byte { s := string(script) sc := systemcontracts.SystemContractsForChain(e.config.FlowNetworkID) contracts := []systemcontracts.SystemContract{sc.EVMContract, sc.FungibleToken, sc.FlowToken} for _, contract := range contracts { s = importRegex.ReplaceAllStringFunc(s, func(match string) string { if strings.Contains(match, contract.Name) { return fmt.Sprintf("import %s from %s", contract.Name, contract.Address.HexWithPrefix()) } return match }) } s = strings.ReplaceAll(s, "0xCOA", e.config.COAAddress.HexWithPrefix()) return []byte(s) }This approach ensures only the correct import statements are replaced.
482-493
: Simplify height conversion logic inevmToCadenceHeight
The function checks if
height < 0
to determine if it should fetch the latest block height. SinceLatestBlockHeight
is a constant representing the latest height, consider simplifying the logic by directly comparing againstLatestBlockHeight
.Apply this diff to simplify the condition:
func (e *RemoteClient) evmToCadenceHeight(height int64) (uint64, error) { - if height < 0 { + if uint64(height) == LatestBlockHeight { h, err := e.client.GetLatestBlockHeader(context.Background(), true) if err != nil { return 0, err } return h.Height, nil }This change makes the code clearer and directly relates to the
LatestBlockHeight
constant.
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (15)
- api/api.go (3 hunks)
- bootstrap/bootstrap.go (7 hunks)
- services/evm/client.go (14 hunks)
- services/evm/cross-spork_client.go (1 hunks)
- services/evm/cross-spork_client_test.go (1 hunks)
- services/evm/executor.go (1 hunks)
- services/evm/kms_key_rotation_signer.go (1 hunks)
- services/evm/pool.go (1 hunks)
- services/evm/remote_ledger.go (3 hunks)
- services/evm/remote_ledger_test.go (1 hunks)
- services/evm/rotation_signer.go (1 hunks)
- services/evm/rotation_signer_test.go (1 hunks)
- services/ingestion/subscriber.go (3 hunks)
- services/ingestion/subscriber_test.go (6 hunks)
- services/requester/requester_test.go (0 hunks)
Files not reviewed due to no reviewable changes (1)
- services/requester/requester_test.go
Files skipped from review due to trivial changes (2)
- services/evm/cross-spork_client_test.go
- services/evm/remote_ledger_test.go
Additional comments not posted (25)
services/evm/rotation_signer.go (1)
1-1
: Verify the impact of the package change on the codebase.The package change from
requester
toevm
indicates a refactoring or reorganization of the codebase. This change is acceptable as it categorizes the file under the Ethereum Virtual Machine (EVM) functionality.However, please ensure that:
- The package change is consistently applied across the codebase.
- Import statements in other files that depend on this file are updated accordingly.
- The package change does not introduce any build or runtime issues.
Run the following script to verify the package usage and imports:
Verification successful
Package change successfully verified
The package change from "requester" to "evm" has been consistently applied across the codebase. All files in the services/evm directory now use the "package evm" declaration, and there are no remnants of the old package name "requester". The change appears to be correctly implemented without any inconsistencies.
- No import statements were found for either the old or new package names, suggesting internal usage within the same module.
- Multiple files in the services/evm directory now use the "package evm" declaration.
The package change has been successfully refactored, and no further action is required.
Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the package change and its impact on the codebase. # Test 1: Search for import statements of the old package. Expect: No occurrences. rg --type go $'requester "github.com/onflow/flow-evm-gateway/services/evm"' # Test 2: Search for import statements of the new package. Expect: Only valid occurrences. rg --type go $'evm "github.com/onflow/flow-evm-gateway/services/evm"' # Test 3: Ensure the package change is consistent across the codebase. # 3.1: Search for files with the old package declaration. Expect: No occurrences. rg --type go $'package requester' # 3.2: Search for files with the new package declaration. Expect: Only valid occurrences. rg --type go $'package evm'Length of output: 649
services/evm/rotation_signer_test.go (2)
1-1
: LGTM!The package name change from
requester
toevm
is consistent with the PR objective of refactoring the client implementations. This change does not affect the functionality of the tests.
5-6
: Skipped commenting.The reordering of import statements is a cosmetic change that does not affect the functionality of the code. It is a common practice to group standard library imports at the top of the import block.
services/evm/kms_key_rotation_signer.go (1)
1-1
: Verify the impact of the package change on the codebase.The package declaration change from
package requester
topackage evm
suggests a reorganization of the codebase. This aligns with the AI-generated summary.Please ensure that:
- Import statements in other files that depend on this file are updated to reflect the new package.
- The intended functionality and usage of this file within the broader application architecture are not adversely affected by this change.
You can use the following script to search for import statements that may need to be updated:
Verification successful
Package change implemented correctly, minor updates recommended
The package change from
requester
toevm
for the filekms_key_rotation_signer.go
has been implemented correctly and consistently across the codebase. No import statements using the old package name were found, indicating that dependencies have been properly updated.However, there are a few remaining references to "requester" in comments and error messages:
- In
services/evm/client.go
:
- A log message
- A comment mentioning "EVM requester"
- In
bootstrap/bootstrap.go
:
- An error message mentioning "EVM requester"
Consider updating these references to maintain consistency with the new package name.
Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Search for import statements that may need to be updated due to the package change. # Test: Search for import statements of the old package name. Expect: No results. rg --type go $'requester \"github.com/onflow/flow-evm-gateway/services/evm\"'Length of output: 76
Script:
#!/bin/bash # Description: Perform additional checks to verify the package change impact # Test 1: Verify the command execution by searching for a known Go keyword echo "Test 1: Searching for 'package' keyword" rg --type go "^package" # Test 2: Search for any references to the old package name (requester) in Go files echo "Test 2: Searching for 'requester' references" rg --type go "requester" # Test 3: Look for import statements using the new package name (evm) echo "Test 3: Searching for new 'evm' package imports" rg --type go "evm \"github.com/onflow/flow-evm-gateway/services/evm\""Length of output: 3760
services/evm/cross-spork_client.go (1)
1-1
: LGTM!The package declaration change from
requester
toevm
is appropriate and aligns the code with the Ethereum Virtual Machine (EVM) related functionality.services/ingestion/subscriber.go (2)
13-13
: LGTM!The import statement change from
requester
toevm
is consistent with the refactoring objective and looks good.
33-33
: Looks good!The updates to the
client
field type in theRPCSubscriber
struct and theNewRPCSubscriber
constructor parameter type are consistent with the refactoring of the client dependency fromrequester
toevm
. The changes align well with the import statement modification.Also applies to: 43-43
services/ingestion/subscriber_test.go (5)
Line range hint
38-43
: LGTM!The updated import path and instantiation of
CrossSporkClient
usingevm.NewCrossSporkClient
are consistent with the refactoring of client implementations from therequester
package to theevm
package.
Line range hint
78-83
: LGTM!The updated import path and instantiation of
CrossSporkClient
usingevm.NewCrossSporkClient
are consistent with the refactoring of client implementations from therequester
package to theevm
package.
Line range hint
180-185
: LGTM!The updated import path and instantiation of
CrossSporkClient
usingevm.NewCrossSporkClient
are consistent with the refactoring of client implementations from therequester
package to theevm
package.
Line range hint
243-248
: LGTM!The updated import path and instantiation of
CrossSporkClient
usingevm.NewCrossSporkClient
are consistent with the refactoring of client implementations from therequester
package to theevm
package.
Line range hint
305-310
: LGTM!The updated import path and instantiation of
CrossSporkClient
usingevm.NewCrossSporkClient
are consistent with the refactoring of client implementations from therequester
package to theevm
package.api/api.go (3)
28-28
: Refactoring of client implementations.The import changes indicate a refactoring of the client implementations, with the
evm
package fromservices
replacing therequester
package. This aligns with the subsequent changes to theBlockChainAPI
struct and constructor.
86-86
:BlockChainAPI
struct updated to useEVMClient
.The
evm
field in theBlockChainAPI
struct has been updated to use theEVMClient
type from theevm
package. This change aligns with the refactoring of the client implementations and ensures theBlockChainAPI
interacts with the appropriate client.
99-99
:NewBlockChainAPI
constructor updated to acceptEVMClient
.The
evm
parameter in theNewBlockChainAPI
constructor has been updated to accept anEVMClient
instead of aRequester
. This change ensures the constructor initializes theBlockChainAPI
with the appropriate client type, aligning with the refactoring of the client implementations.services/evm/remote_ledger.go (1)
35-44
: Initialization of cache maps is correct.The
newRemoteLedger
function correctly initializes thediffs
andslabs
maps for caching, setting up the local state for efficient access.services/evm/executor.go (3)
74-75
: Clarify error handling in transaction executionThe comment on line 74 questions whether returning the error as-is is appropriate, noting that the service might restart and retry. Ensure that this error handling aligns with the desired behavior of the service, and consider implementing retry logic or more detailed error handling if necessary.
Is additional error handling or retry logic needed here to handle transient errors during
bv.RunTransaction(tx)
?
120-121
: Verify default gas usage and gas price settingsThe comment on line 120 suggests checking the values for
DirectCallBaseGasUsage
. Ensure thattypes.DefaultDirectCallBaseGasUsage
andtypes.DefaultDirectCallGasPrice
are appropriate for your network's requirements.Are these default values suitable for your use case, or do they need to be adjusted?
115-142
: Complete configuration ofblockContext
Several fields in the
blockContext
are marked with TODO comments (lines 120, 139, 141). Ensure that all necessary fields are properly set to accurately reflect the execution context.Review the
blockContext
setup to confirm that all required fields are configured and that any optional fields are addressed as needed.bootstrap/bootstrap.go (6)
406-406
: UpdatesetupStorage
to accept new client typeThe
setupStorage
function's parameter has been updated to acceptclient *evm.CrossSporkClient
. Ensure that the function uses this client correctly for storage setup and that all interactions with the client are compatible with its new type.
363-363
: Verify all usages ofsetupCrossSporkClient
are updatedThe return type of the
setupCrossSporkClient
function has changed to(*evm.CrossSporkClient, error)
. Ensure that all callers of this function have been updated to handle the new return type correctly.Execute the following script to locate and review all calls to
setupCrossSporkClient
:#!/bin/bash # Description: Find all usages of setupCrossSporkClient to verify proper handling of the new return type. # Test: Search for calls to setupCrossSporkClient. # Expect: Calls correctly handle the new return type. rg --type go 'setupCrossSporkClient\(' -A 2
195-197
: Validate signer initialization withevm
package functionsThe signer initialization now uses
evm.NewKeyRotationSigner
andevm.NewKMSKeyRotationSigner
. Ensure these functions are correctly implemented and compatible with the existing signer usage. Confirm that all necessary parameters are provided and that error handling is properly managed.Use the following script to verify the definitions and usages:
#!/bin/bash # Description: Verify the correct implementation of signer initialization functions. # Test: Retrieve the definitions of the new signer functions. # Expect: Functions are properly defined with expected parameters. rg --type go 'func NewKeyRotationSigner' -A 5 rg --type go 'func NewKMSKeyRotationSigner' -A 5
389-389
: Confirm proper initialization ofevm.CrossSporkClient
The
evm.CrossSporkClient
is being initialized withevm.NewCrossSporkClient
. Verify that all required parameters are correctly provided and that the client is properly configured for cross-spork operations.Use this script to examine the definition and initialization logic:
#!/bin/bash # Description: Review the constructor of evm.CrossSporkClient for correct usage. # Test: Retrieve the definition of NewCrossSporkClient. # Expect: Parameters match expected configuration. rg --type go 'func NewCrossSporkClient' -A 10
210-210
: Avoid naming conflict with variableevm
Assigning the variable name
evm
to the instance created byevm.NewEVM
can lead to confusion between the variable and the package nameevm
. This can impact code readability and maintainability.Consider renaming the variable to something more descriptive, such as
evmInstance
orevmService
. Apply the following diff to rename the variable:- evm, err := evm.NewEVM( + evmService, err := evm.NewEVM(Ensure all subsequent references to this variable are updated accordingly.
Likely invalid or redundant comment.
47-47
: Ensure consistent usage of*evm.CrossSporkClient
The
client
field in theBootstrap
struct has been updated to use*evm.CrossSporkClient
. Please verify that all references to this client throughout the codebase have been updated to match the new type to prevent any potential type mismatches or runtime errors.Run the following script to check for any outdated references to the old
*requester.CrossSporkClient
:Verification successful
Verification successful:
*evm.CrossSporkClient
usage is consistentThe codebase has been thoroughly checked, and all references to
CrossSporkClient
are correctly using theevm
package. TheBootstrap
struct inbootstrap/bootstrap.go
is properly updated to use*evm.CrossSporkClient
. No instances of the old*requester.CrossSporkClient
were found.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Search for any remaining usages of the old CrossSporkClient type. # Test: Look for occurrences of the old client type. # Expect: No matches found. rg --type go '\*requester\.CrossSporkClient'Length of output: 854
Script:
#!/bin/bash # Search for all usages of CrossSporkClient in Go files echo "Searching for CrossSporkClient usages:" rg --type go 'CrossSporkClient' echo -e "\nExamining Bootstrap struct definition:" rg --type go 'type Bootstrap struct' -A 10 bootstrap/bootstrap.goLength of output: 3126
@@ -1,4 +1,4 @@ | |||
package requester | |||
package evm |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tip
Codebase Verification
Update leftover "requester" references and review TxPool
usage
The package change from requester
to evm
is mostly consistent, but there are some issues that need attention:
- Update the following occurrences of "requester" to reflect the new package name:
- Comments in
services/evm/client.go
- Error message in
bootstrap/bootstrap.go
- Comments in
Additionally, be aware that there's another TxPool
struct defined in the api
package. Ensure this doesn't cause any confusion with the TxPool
in the evm
package.
Analysis chain
Ensure consistency in package refactoring.
The package declaration change from requester
to evm
suggests a refactoring or reorganization of the codebase. This change should be consistent with the overall package structure and naming conventions of the project.
Please run the following script to verify the consistency of the package change across the codebase:
Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the consistency of the package change from `requester` to `evm`.
# Test 1: Search for import statements of the old package name. Expect: No occurrences.
rg --type go $'requester'
# Test 2: Search for references to the `TxPool` type. Expect: Only occurrences in the `evm` package.
rg --type go $'TxPool'
Length of output: 1096
if val, ok := l.slabs[id.String()]; ok { | ||
return val, nil | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Protect slabs
map access with synchronization.
In the AllocateSlabIndex
method, accessing the slabs
map without synchronization can lead to concurrency issues.
Use read and write locks when accessing and modifying the slabs
map:
func (l *remoteLedger) AllocateSlabIndex(owner []byte) (atree.SlabIndex, error) {
// ...
+ l.mu.RLock()
if val, ok := l.slabs[id.String()]; ok {
+ l.mu.RUnlock()
return val, nil
}
+ l.mu.RUnlock()
// Fetch the slab index if not in cache
// ...
+ l.mu.Lock()
slab := account.SlabIndex()
l.slabs[id.String()] = slab
+ l.mu.Unlock()
return slab, nil
}
Also applies to: 107-108
func (l *remoteLedger) SetValue(owner, key, value []byte) (err error) { | ||
id := flow.RegisterID{ | ||
Key: string(key), | ||
Owner: string(owner), | ||
} | ||
|
||
l.diffs[id.String()] = value | ||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Synchronize access when writing to cache maps.
Writing to the diffs
map in the SetValue
method without synchronization can cause data races.
Acquire a write lock when modifying the diffs
map:
func (l *remoteLedger) SetValue(owner, key, value []byte) error {
id := flow.RegisterID{
Key: string(key),
Owner: string(owner),
}
+ l.mu.Lock()
l.diffs[id.String()] = value
+ l.mu.Unlock()
return 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. Thoroughly test & benchmark the code to ensure it meets the requirements.
func (l *remoteLedger) SetValue(owner, key, value []byte) (err error) { | |
id := flow.RegisterID{ | |
Key: string(key), | |
Owner: string(owner), | |
} | |
l.diffs[id.String()] = value | |
return nil | |
} | |
func (l *remoteLedger) SetValue(owner, key, value []byte) (err error) { | |
id := flow.RegisterID{ | |
Key: string(key), | |
Owner: string(owner), | |
} | |
l.mu.Lock() | |
l.diffs[id.String()] = value | |
l.mu.Unlock() | |
return nil | |
} |
diffs map[string][]byte | ||
slabs map[string]atree.SlabIndex | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Address potential concurrency issues with unprotected maps.
The diffs
and slabs
maps in the remoteLedger
struct are not protected by any synchronization mechanisms. If remoteLedger
is accessed by multiple goroutines concurrently, this could lead to data races and undefined behavior.
Consider adding a sync.RWMutex
to the struct to protect access to these maps:
+import "sync"
type remoteLedger struct {
execution executiondata.ExecutionDataAPIClient
height uint64
+ mu sync.RWMutex
diffs map[string][]byte
slabs map[string]atree.SlabIndex
}
Then, use the mutex in methods that read or write to these maps to ensure thread safety.
Committable suggestion was skipped due to low confidence.
// first check local changes | ||
if val, ok := l.diffs[id.String()]; ok { | ||
return val, nil | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure thread safety when reading from cache maps.
In the GetValue
method, reading from the diffs
map without synchronization can lead to data races in a concurrent environment.
Use a read lock when accessing the diffs
map:
func (l *remoteLedger) GetValue(owner, key []byte) ([]byte, error) {
+ l.mu.RLock()
id := flow.RegisterID{
Key: string(key),
Owner: string(owner),
}
// first check local changes
if val, ok := l.diffs[id.String()]; ok {
+ l.mu.RUnlock()
return val, nil
}
+ l.mu.RUnlock()
// proceed to fetch register if not in cache
// ...
}
Committable suggestion was skipped due to low confidence.
services/evm/executor.go
Outdated
type BlockExecutor struct { | ||
types.StateDB // todo change to types.ReadOnlyView | ||
emulator types.Emulator | ||
chainID flowGo.ChainID | ||
block *models.Block | ||
blocks storage.BlockIndexer | ||
logger zerolog.Logger | ||
|
||
// block dynamic data | ||
txIndex uint | ||
gasUsed uint64 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assess thread safety of BlockExecutor
The BlockExecutor
struct maintains state in txIndex
and gasUsed
, which are modified during execution (lines 85-86). If instances of BlockExecutor
are used concurrently across goroutines, this could lead to race conditions.
If concurrency is expected, consider adding synchronization mechanisms, such as mutexes, to protect shared state.
import "sync"
type BlockExecutor struct {
// existing fields...
mutex sync.Mutex
}
// In methods that modify txIndex and gasUsed:
s.mutex.Lock()
defer s.mutex.Unlock()
// Perform modifications...
return nil, fmt.Errorf("invalid transaction %s: %w", tx.Hash(), res.ValidationError) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improve error wrapping for invalid transactions
The error message on line 81 uses fmt.Errorf
with %w
to wrap res.ValidationError
. Ensure that res.ValidationError
implements the error
interface so that the wrapping functions correctly.
Verify that res.ValidationError
is an error
. If not, you may need to convert it or adjust the error handling.
panic(err) | ||
} | ||
h, err := b.Hash() | ||
if err != nil { | ||
panic(err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid using panic
in production code
In the GetHashFunc
, errors are handled using panic(err)
on lines 126 and 130. Using panic
can cause the entire application to crash. It's recommended to handle errors gracefully to improve the robustness of the application.
Consider modifying the GetHashFunc
to handle errors without panicking. Here's a possible refactor:
GetHashFunc: func(n uint64) common.Hash {
b, err := s.blocks.GetByHeight(n)
if err != nil {
- panic(err)
+ s.logger.Error().Err(err).Uint64("height", n).Msg("failed to get block by height")
+ return common.Hash{}
}
h, err := b.Hash()
if err != nil {
- panic(err)
+ s.logger.Error().Err(err).Uint64("height", n).Msg("failed to compute block hash")
+ return common.Hash{}
}
return h
},
This approach logs the error and returns a zero common.Hash
, allowing the application to continue running.
Committable suggestion was skipped due to low confidence.
services/evm/client.go
Outdated
func (e *RemoteClient) EstimateGas(ctx context.Context, data []byte, from common.Address, evmHeight int64) (uint64, error) { | ||
executor, err := e.executorAt(evmHeight) | ||
if err != nil { | ||
return 0, err | ||
} | ||
|
||
height, err := e.evmToCadenceHeight(evmHeight) | ||
res, err := executor.Call(from, data) | ||
if err != nil { | ||
return 0, err | ||
} | ||
|
||
scriptResult, err := e.executeScriptAtHeight( | ||
ctx, | ||
dryRun, | ||
height, | ||
[]cadence.Value{hexEncodedTx, hexEncodedAddress}, | ||
) | ||
if err != nil { | ||
if !errors.Is(err, errs.ErrHeightOutOfRange) { | ||
e.logger.Error(). | ||
Err(err). | ||
Uint64("cadence-height", height). | ||
Int64("evm-height", evmHeight). | ||
Str("from", from.String()). | ||
Str("data", hex.EncodeToString(data)). | ||
Msg("failed to execute estimateGas") | ||
result := res.ResultSummary() | ||
if result.ErrorCode != 0 { | ||
if result.ErrorCode == evmTypes.ExecutionErrCodeExecutionReverted { | ||
return 0, errs.NewRevertError(result.ReturnedData) | ||
} | ||
return 0, fmt.Errorf("failed to execute script at height: %d, with: %w", height, err) | ||
} | ||
|
||
evmResult, err := parseResult(scriptResult) | ||
if err != nil { | ||
return 0, err | ||
return 0, errs.NewFailedTransactionError(result.ErrorMessage) | ||
} | ||
|
||
gasConsumed := evmResult.GasConsumed | ||
|
||
e.logger.Debug(). | ||
Uint64("gas", gasConsumed). | ||
Int64("evm-height", evmHeight). | ||
Uint64("cadence-height", height). | ||
Msg("estimateGas executed") | ||
|
||
return gasConsumed, nil | ||
return res.GasConsumed, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactor duplicate error handling in EstimateGas
and Call
methods
The error handling logic in both EstimateGas
(lines 355-374) and Call
(lines 377-406) methods is similar. Refactoring this repetitive code into a shared helper function can improve maintainability and reduce duplication.
Consider creating a helper function to process the ResultSummary
and handle errors:
func handleExecutionResult(result evmTypes.ResultSummary) error {
if result.ErrorCode != 0 {
if result.ErrorCode == evmTypes.ExecutionErrCodeExecutionReverted {
return errs.NewRevertError(result.ReturnedData)
}
return errs.NewFailedTransactionError(result.ErrorMessage)
}
return nil
}
Then update the EstimateGas
and Call
methods to use this helper:
// In EstimateGas
result := res.ResultSummary()
-if result.ErrorCode != 0 {
- if result.ErrorCode == evmTypes.ExecutionErrCodeExecutionReverted {
- return 0, errs.NewRevertError(result.ReturnedData)
- }
- return 0, errs.NewFailedTransactionError(result.ErrorMessage)
-}
+if err := handleExecutionResult(result); err != nil {
+ return 0, err
+}
// In Call
result := res.ResultSummary()
-if result.ErrorCode != 0 {
- if result.ErrorCode == evmTypes.ExecutionErrCodeExecutionReverted {
- return nil, errs.NewRevertError(result.ReturnedData)
- }
- return nil, errs.NewFailedTransactionError(result.ErrorMessage)
-}
+if err := handleExecutionResult(result); err != nil {
+ return nil, err
+}
Also applies to: 377-406
services/evm/client.go
Outdated
func (e *RemoteClient) stateAt(evmHeight int64) (evmTypes.StateDB, error) { | ||
ledger, err := e.ledgerAt(evmHeight) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to hex-decode string to byte array [%s]: %w", cdcString, err) | ||
return nil, err | ||
} | ||
|
||
return code, nil | ||
return state.NewStateDB(ledger, e.storageAccount) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle potential stateDB
errors after retrieval
In the stateAt
function, after retrieving stateDB
, errors from stateDB.Error()
might occur during subsequent calls. To prevent propagating a nil
error when the stateDB
is nil
, consider checking for errors immediately after retrieval.
Apply this diff to handle errors appropriately:
func (e *RemoteClient) stateAt(evmHeight int64) (evmTypes.StateDB, error) {
ledger, err := e.ledgerAt(evmHeight)
if err != nil {
return nil, err
}
stateDB, err := state.NewStateDB(ledger, e.storageAccount)
+ if err != nil {
+ return nil, err
+ }
return stateDB, nil
}
This ensures that any errors during the creation of stateDB
are correctly handled.
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. Thoroughly test & benchmark the code to ensure it meets the requirements.
func (e *RemoteClient) stateAt(evmHeight int64) (evmTypes.StateDB, error) { | |
ledger, err := e.ledgerAt(evmHeight) | |
if err != nil { | |
return nil, fmt.Errorf("failed to hex-decode string to byte array [%s]: %w", cdcString, err) | |
return nil, err | |
} | |
return code, nil | |
return state.NewStateDB(ledger, e.storageAccount) | |
func (e *RemoteClient) stateAt(evmHeight int64) (evmTypes.StateDB, error) { | |
ledger, err := e.ledgerAt(evmHeight) | |
if err != nil { | |
return nil, err | |
} | |
stateDB, err := state.NewStateDB(ledger, e.storageAccount) | |
if err != nil { | |
return nil, err | |
} | |
return stateDB, nil | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
Outside diff range and nitpick comments (9)
tests/e2e_web3js_test.go (2)
31-35
: Update the TODO comment and follow up on the progress.It's great to see a new test case being added for "cadence arch and environment calls". However, the TODO comment indicates that this test is currently failing due to an issue with the cadence arch replayer.
Consider updating the TODO comment with more details about the specific issue or converting it to a GitHub issue for better tracking and visibility.
Also, please check with Ramtin on the progress of the fix and update the codebase accordingly once it's available.
159-159
: Clarify the reason for increasing the gas limit.The gas limit for the contract deployment transaction has been increased from
1_250_000
to1_550_000
. While increasing the gas limit may be necessary to accommodate the complexity of the contract being deployed, it would be helpful to understand the specific reason behind this change.Please consider:
- Adding a comment explaining the need for the higher gas limit.
- Evaluating the trade-offs between allowing more computational work and the increased transaction costs.
- Adjusting the gas limit based on the contract complexity and transaction cost constraints.
go.mod (1)
91-91
: LGTM!The addition of the indirect dependency
github.com/hashicorp/golang-lru/v2 v2.0.7
should not cause any issues, as it is managed by the Go module system.As a best practice, consider reviewing the release notes or changelog of the added dependency to ensure there are no known issues or vulnerabilities.
services/evm/client.go (1)
53-57
: Address the TODO comment about extracting transaction submission to a separate type.Consider creating a new interface, such as
TransactionSubmitter
, to handle transaction submission responsibilities. This will help separate concerns and improve the cohesion of theEVMClient
interface.tests/fixtures/storage.sol (1)
11-11
: Nitpick: Explicitly specifyuint256
instead ofuint
for consistencyIn the event declaration for
BlockTime
, consider usinguint256
instead ofuint
to maintain consistency with the other event declarations and improve code clarity.Apply this diff:
-event BlockTime(address indexed caller, uint value); +event BlockTime(address indexed caller, uint256 value);tests/web3js/build_evm_state_test.js (1)
176-176
: Review the necessity of extending the test timeoutA timeout of
180*1000
milliseconds (180 seconds) has been added to the test case. Please confirm that this extended duration is necessary for the test to complete and consider optimizing the test to reduce execution time if possible.tests/web3js/cadence_arch_env_test.js (3)
7-13
: Improve the clarity and grammar of the introductory commentsThe comments in lines 7-13 contain grammatical errors and could be rephrased for better readability and understanding.
Consider updating the comments as follows:
-// this test calls different environment and cadenc arch functions. It uses view -// function to call and return the value which it compares with the block on the network, -// behind the scene these causes the local client to make such a call and return the value -// and this test makes sure the on-chain data is same as local-index data. Secondly, this -// test also submits a transaction that emits the result, which checks the local state -// re-execution of transaction, and makes sure both receipt matches (remote and local), -// this in turn tests the local state re-execution. +// This test calls different environment and Cadence architecture functions. It uses view +// functions to call and return values, which it compares with the blocks on the network. +// Behind the scenes, this causes the local client to make such calls and return the values, +// ensuring that the on-chain data is the same as the local index data. Secondly, this +// test also submits a transaction that emits the result, which checks the local state +// re-execution of the transaction, and makes sure both receipts (remote and local) match. +// This, in turn, tests the local state re-execution.
18-18
: Preferconst
overlet
for variables that are not reassignedIn lines 18, 32, and 51, the variables
res
,block
, anddeployed
are declared withlet
but are not reassigned. Usingconst
can prevent accidental reassignment and improve code clarity.Update the variable declarations:
- let res = await helpers.signAndSend({ + const res = await helpers.signAndSend({- let block = await web3.eth.getBlock('latest') + const block = await web3.eth.getBlock('latest')- let deployed = await helpers.deployContract('storage') + const deployed = await helpers.deployContract('storage')Also applies to: 32-32, 51-51
60-62
: Address the TODO regarding block environment functionsThe TODO comment indicates an issue where Ethereum calls are executed at the provided block height, but block environment functions (number, hash, etc.) point to the next block (the block proposal). This discrepancy may affect test accuracy.
Would you like assistance in investigating this issue or opening a GitHub issue to track and resolve this problem?
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files ignored due to path filters (2)
tests/go.sum
is excluded by!**/*.sum
tests/web3js/package-lock.json
is excluded by!**/package-lock.json
Files selected for processing (16)
- bootstrap/bootstrap.go (7 hunks)
- go.mod (1 hunks)
- services/evm/client.go (13 hunks)
- services/evm/executor.go (1 hunks)
- tests/e2e_web3js_test.go (2 hunks)
- tests/fixtures/storage.byte (1 hunks)
- tests/fixtures/storage.sol (4 hunks)
- tests/fixtures/storageABI.json (4 hunks)
- tests/go.mod (1 hunks)
- tests/helpers.go (3 hunks)
- tests/web3js/build_evm_state_test.js (2 hunks)
- tests/web3js/cadence_arch_env_test.js (1 hunks)
- tests/web3js/eth_deploy_contract_and_interact_test.js (2 hunks)
- tests/web3js/eth_filter_endpoints_test.js (2 hunks)
- tests/web3js/eth_revert_reason_test.js (2 hunks)
- tests/web3js/eth_transaction_type_fees_test.js (3 hunks)
Files skipped from review as they are similar to previous changes (2)
- bootstrap/bootstrap.go
- services/evm/executor.go
Additional comments not posted (53)
tests/web3js/eth_revert_reason_test.js (2)
44-44
: LGTM!The change simplifies the process of obtaining the reverted transaction by directly using the transaction hash, eliminating the need to fetch the latest block. This improves code efficiency.
74-74
: Duplicate change.This change is identical to the one at line 44. It simplifies the process of obtaining the reverted transaction by directly using the transaction hash, eliminating the need to fetch the latest block. This improves code efficiency.
tests/web3js/eth_transaction_type_fees_test.js (4)
24-24
: LGTM!The change updates the expected gas used value, which aligns with the AI-generated summary. The new value seems reasonable.
30-30
: LGTM!The change updates the expected sender balance, which aligns with the AI-generated summary. The new value seems reasonable.
75-75
: LGTM!The change updates the expected sender balance, which aligns with the AI-generated summary. The new value seems reasonable.
132-132
: LGTM!The change updates the expected sender balance, which aligns with the AI-generated summary. The new value seems reasonable.
tests/web3js/eth_deploy_contract_and_interact_test.js (2)
21-21
: LGTM!The change in the expected gas usage for the contract deployment process is valid and does not introduce any issues.
236-236
: LGTM!The change in the expected gas estimate for the contract interaction is valid and does not introduce any issues.
tests/fixtures/storageABI.json (16)
23-41
: LGTM!The
BlockHash
event is well-defined with clear input names and appropriate types. Indexing thecaller
input is a good practice for efficient event filtering.
42-60
: LGTM!The
BlockNumber
event is well-defined with clear input names and appropriate types. Indexing thecaller
input is a good practice for efficient event filtering.
61-79
: LGTM!The
BlockTime
event is well-defined with clear input names and appropriate types. Indexing thecaller
input is a good practice for efficient event filtering.
111-129
: LGTM!The
ChainID
event is well-defined with clear input names and appropriate types. Indexing thecaller
input is a good practice for efficient event filtering.
149-167
: LGTM!The
Random
event is well-defined with clear input names and appropriate types. Indexing thecaller
input is a good practice for efficient event filtering.
168-186
: LGTM!The
Retrieved
event is well-defined with clear input names and appropriate types. Indexing thecaller
input is a good practice for efficient event filtering.
187-205
: LGTM!The
VerifyArchCallToFlowBlockHeight
event is well-defined with clear input names and appropriate types. Indexing thecaller
input is a good practice for efficient event filtering.
206-224
: LGTM!The
VerifyArchCallToRandomSource
event is well-defined with clear input names and appropriate types. Indexing thecaller
input is a good practice for efficient event filtering.
225-243
: LGTM!The
VerifyArchCallToRevertibleRandom
event is well-defined with clear input names and appropriate types. Indexing thecaller
input is a good practice for efficient event filtering.
244-262
: LGTM!The
VerifyArchCallToVerifyCOAOwnershipProof
event is well-defined with clear input names and appropriate types. Indexing thecaller
input is a good practice for efficient event filtering.
355-367
: LGTM!The
emitBlockHash
function is well-defined with a clear parameter name and appropriate type. Thenonpayable
modifier is suitable for a function that emits an event without modifying the contract state.
368-374
: LGTM!The
emitBlockNumber
function is well-defined with a clear name. Thenonpayable
modifier is suitable for a function that emits an event without modifying the contract state.
375-381
: LGTM!The
emitBlockTime
function is well-defined with a clear name. Thenonpayable
modifier is suitable for a function that emits an event without modifying the contract state.
382-388
: LGTM!The
emitChainID
function is well-defined with a clear name. Thenonpayable
modifier is suitable for a function that emits an event without modifying the contract state.
389-395
: LGTM!The
emitRandom
function is well-defined with a clear name. Thenonpayable
modifier is suitable for a function that emits an event without modifying the contract state.
396-402
: LGTM!The
emitRetrieve
function is well-defined with a clear name. Thenonpayable
modifier is suitable for a function that emits an event without modifying the contract state.tests/helpers.go (2)
65-68
: LGTM!The changes to the
testLogWriter
function look good. The function now creates a newzerolog.ConsoleWriter
instance, sets the global time field format totime.RFC3339Nano
, and configures the writer's time format to "04:05.0000" before returning the writer.
338-339
: Looks good!The change to the
evmSign
function signature, moving thedata []byte
parameter to a new line, improves readability without altering the function's behavior.tests/go.mod (1)
156-156
: Verify compatibility of the dependency update.The
github.com/onflow/flow/protobuf/go/flow
dependency has been updated from versionv0.4.6
tov0.4.7
.While minor version updates are generally safe, it's important to ensure that this update is compatible with the rest of the project dependencies and doesn't introduce any breaking changes or issues.
Run the following script to check if the update causes any issues:
tests/web3js/eth_filter_endpoints_test.js (2)
364-364
: LGTM!The updated transaction hash looks good and matches the expected format.
417-417
: Looks good!The updated
hash
andvalue
fields in the expected transaction object are valid and match the Ethereum transaction format.Also applies to: 422-422
services/evm/client.go (10)
93-102
: LGTM!The
RemoteClient
struct has the appropriate dependencies and fields to implement theEVMClient
interface. The naming and organization of the fields are clear and follow Go conventions.
Line range hint
120-197
: LGTM!The
NewEVM
function properly initializes theRemoteClient
instance with the provided dependencies. The checks for the COA account balance and the creation of the COA resource based on the configuration flag are useful safeguards. The function logic is clear and follows best practices.
Line range hint
201-259
: LGTM!The
SendRawTransaction
method follows the expected steps for sending a raw transaction. The validation of the transaction, the check for the minimum gas price, and the building of the Flow transaction are all good practices. The method logic is clear and well-structured. The logging of the transaction details provides good visibility into the process.
Line range hint
260-308
: LGTM!The
buildTransaction
method follows the necessary steps to build a valid Flow transaction. Retrieving the latest block and signer information concurrently using an error group is an efficient approach. Setting the transaction fields with the appropriate values and signing the transaction envelope with the configured signer ensures a properly constructed and authorized transaction. The error handling and formatting of error messages are appropriate.
310-321
: LGTM!The
GetBalance
method retrieves the balance of an address at a given EVM height using thestateAt
method to get the state database. Retrieving the balance using theGetBalance
method of the state database is the correct approach. The method returns the balance as a*big.Int
, which is the expected type for balances in Go-Ethereum. The method logic is clear and follows best practices.
323-334
: LGTM!The
GetNonce
method retrieves the nonce of an address at a given EVM height using thestateAt
method to get the state database. Retrieving the nonce using theGetNonce
method of the state database is the correct approach. The method returns the nonce as auint64
, which is the expected type for nonces in Go-Ethereum. The method logic is clear and follows best practices.
Line range hint
336-348
: LGTM!The
GetStorageAt
method retrieves the storage value at a given address and hash at a specific EVM height using thestateAt
method to get the state database. Retrieving the storage value using theGetState
method of the state database is the correct approach. The method returns the storage value as acommon.Hash
, which is the expected type for storage values in Go-Ethereum. The method logic is clear and follows best practices.
350-357
: LGTM!The
GetCode
method retrieves the code at a given address at a specific EVM height using thestateAt
method to get the state database. Retrieving the code using theGetCode
method of the state database is the correct approach. The method returns the code as a byte slice, which is the expected type for code in Go-Ethereum. The method logic is clear and follows best practices.
359-379
: LGTM!The
EstimateGas
method estimates the gas required for a given transaction data at a specific EVM height using theexecutorAt
method to get the block executor. Calling theCall
method of the block executor to execute the transaction and get the gas consumed is the correct approach. The method handles the error cases and returns the appropriate error type based on the execution result, which is a good practice. The method logic is clear and follows best practices.
381-411
: LGTM!The
Call
method executes a given transaction data at a specific EVM height using theexecutorAt
method to get the block executor. Calling theCall
method of the block executor to execute the transaction and get the result is the correct approach. The method handles the error cases and returns the appropriate error type based on the execution result, which is a good practice. Ensuring that the returned data is an empty slice if it is nil is a good practice to match the behavior of the remote client. The method logic is clear and follows best practices.tests/fixtures/storage.sol (10)
46-48
: FunctionemitRetrieve
correctly emitsRetrieved
eventThe
emitRetrieve
function properly emits theRetrieved
event with the caller's address and the stored number.
60-62
: FunctionemitBlockNumber
correctly emitsBlockNumber
eventThe
emitBlockNumber
function properly emits theBlockNumber
event with the caller's address and the current block number.
68-70
: FunctionemitBlockTime
correctly emitsBlockTime
eventThe
emitBlockTime
function properly emits theBlockTime
event with the caller's address and the current block timestamp.
84-86
: FunctionemitRandom
correctly emitsRandom
eventThe
emitRandom
function properly emits theRandom
event with the caller's address and theblock.prevrandao
value.
92-94
: FunctionemitChainID
correctly emitsChainID
eventThe
emitChainID
function properly emits theChainID
event with the caller's address and the current chain ID.
104-105
: FunctioncustomError
correctly uses a custom errorThe
customError
function correctly demonstrates how to revert with the custom errorMyCustomError
.
115-118
: FunctionemitVerifyArchCallToRandomSource
correctly emits eventThe
emitVerifyArchCallToRandomSource
function correctly callsverifyArchCallToRandomSource
and emits theVerifyArchCallToRandomSource
event with the caller's address and the output.
127-130
: FunctionemitVerifyArchCallToRevertibleRandom
correctly emits eventThe
emitVerifyArchCallToRevertibleRandom
function correctly callsverifyArchCallToRevertibleRandom
and emits theVerifyArchCallToRevertibleRandom
event with the caller's address and the output.
139-142
: FunctionemitVerifyArchCallToFlowBlockHeight
correctly emits eventThe
emitVerifyArchCallToFlowBlockHeight
function correctly callsverifyArchCallToFlowBlockHeight
and emits theVerifyArchCallToFlowBlockHeight
event with the caller's address and the output.
151-154
: FunctionemitVerifyArchCallToVerifyCOAOwnershipProof
correctly emits eventThe
emitVerifyArchCallToVerifyCOAOwnershipProof
function correctly callsverifyArchCallToVerifyCOAOwnershipProof
and emits theVerifyArchCallToVerifyCOAOwnershipProof
event with the caller's address and the output.tests/web3js/build_evm_state_test.js (2)
158-158
: Confirm that the increased estimated gas value is expectedThe estimated gas value has been updated to
29338n
. Please verify that this increase is intentional and aligns with the expected changes in the contract or gas estimation logic.
165-165
: Confirm that the increased contract code length is expectedThe length of the contract code retrieved at the latest block has increased to
12180
. This significant change suggests alterations in the contract's bytecode. Please ensure that this is expected and corresponds to the updates made.tests/web3js/cadence_arch_env_test.js (2)
74-76
: Address the TODO regarding block environment functionsThe same issue regarding block environment functions pointing to the next block is mentioned here. It's important to resolve this to ensure test reliability.
90-92
: Address the TODO regarding block environment functionsThis TODO repeats the concern about block environment functions pointing to the next block instead of the provided block height. Resolving this will enhance the accuracy of your tests.
function emitBlockHash(uint num) public { | ||
emit BlockHash(msg.sender, blockhash(num)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add input validation for num
parameter in emitBlockHash
The blockhash
function only returns meaningful values for the 256 most recent blocks. To prevent unexpected results, consider adding input validation to ensure that num
is within the valid range (block.number - 256 <= num < block.number
).
Apply this diff:
function emitBlockHash(uint num) public {
+ require(num >= block.number - 256 && num < block.number, "Invalid block number");
emit BlockHash(msg.sender, blockhash(num));
}
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. Thoroughly test & benchmark the code to ensure it meets the requirements.
function emitBlockHash(uint num) public { | |
emit BlockHash(msg.sender, blockhash(num)); | |
} | |
function emitBlockHash(uint num) public { | |
require(num >= block.number - 256 && num < block.number, "Invalid block number"); | |
emit BlockHash(msg.sender, blockhash(num)); | |
} |
web3.eth.abi.decodeParameter('uint', res.value).toString(), | ||
(prev.timestamp+1n).toString(), // investigate why timestamp is increasing by 1 | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prevent TypeError due to mixing BigInt
and Number
types
The expression (prev.timestamp + 1n).toString()
may cause a TypeError because prev.timestamp
is a Number
, and 1n
is a BigInt
.
Convert prev.timestamp
to a BigInt
before the addition:
- (prev.timestamp+1n).toString(), // investigate why timestamp is increasing by 1
+ (BigInt(prev.timestamp) + 1n).toString(), // investigate why timestamp is increasing by 1
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. Thoroughly test & benchmark the code to ensure it meets the requirements.
web3.eth.abi.decodeParameter('uint', res.value).toString(), | |
(prev.timestamp+1n).toString(), // investigate why timestamp is increasing by 1 | |
) | |
web3.eth.abi.decodeParameter('uint', res.value).toString(), | |
(BigInt(prev.timestamp) + 1n).toString(), // investigate why timestamp is increasing by 1 | |
) |
assert.equal( | ||
web3.eth.abi.decodeParameter('uint256', res.value), | ||
res.block.number+1n, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prevent TypeError due to mixing BigInt
and Number
types
Adding a BigInt
(1n
) to a Number
(res.block.number
) can cause a TypeError in JavaScript. You cannot mix BigInt
and Number
types in arithmetic operations.
Convert res.block.number
to a BigInt
before performing the addition:
- res.block.number+1n,
+ BigInt(res.block.number) + 1n,
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. Thoroughly test & benchmark the code to ensure it meets the requirements.
assert.equal( | |
web3.eth.abi.decodeParameter('uint256', res.value), | |
res.block.number+1n, | |
) | |
assert.equal( | |
web3.eth.abi.decodeParameter('uint256', res.value), | |
BigInt(res.block.number) + 1n, | |
) |
await testEmitTx(methods.emitRandom()) | ||
|
||
let res = await testCall(methods.random()) | ||
assert.isNotEmpty(web3.eth.abi.decodeParameter('uint256', res.value).toString()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a valid assertion method
The assert.isNotEmpty
method may not exist in Chai's assert
interface. To verify that the value is not empty, consider checking the length of the string.
Update the assertion as follows:
- assert.isNotEmpty(web3.eth.abi.decodeParameter('uint256', res.value).toString())
+ assert.isAbove(web3.eth.abi.decodeParameter('uint256', res.value).toString().length, 0)
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. Thoroughly test & benchmark the code to ensure it meets the requirements.
assert.isNotEmpty(web3.eth.abi.decodeParameter('uint256', res.value).toString()) | |
assert.isAbove(web3.eth.abi.decodeParameter('uint256', res.value).toString().length, 0) |
60806040526105395f819055506117c9806100195f395ff3fe608060405234801561000f575f80fd5b50600436106101c2575f3560e01c80639075ef95116100f7578063bc31124b11610095578063d0d250bd1161006f578063d0d250bd14610420578063dda3a7bd1461043e578063ea8d8ccf14610448578063fe027d1114610478576101c2565b8063bc31124b146103dc578063c550f90f146103f8578063cbaff5f914610416576101c2565b8063adc879e9116100d1578063adc879e91461038c578063af32a363146103aa578063b2821c8f146103b4578063b7ec3e5f146103d2576101c2565b80639075ef9514610322578063911007b41461032c5780639967062d1461035c576101c2565b80635ec01e4d1161016457806364fc013a1161013e57806364fc013a146102b05780636babb224146102cc57806383197ef0146102e857806385df51fd146102f2576101c2565b80635ec01e4d1461025a5780635f0f73fb146102785780636057361d14610294576101c2565b80634cbefa6a116101a05780634cbefa6a1461020c57806357e871e7146102285780635b5764f4146102465780635e4268e614610250576101c2565b80632e64cec1146101c657806346c38ab0146101e457806348b15166146101ee575b5f80fd5b6101ce610482565b6040516101db9190610f06565b60405180910390f35b6101ec61048a565b005b6101f66104da565b6040516102039190610f06565b60405180910390f35b61022660048036038101906102219190610f5a565b6104e1565b005b6102306104ea565b60405161023d9190610f06565b60405180910390f35b61024e6104f1565b005b61025861054d565b005b61026261059d565b60405161026f9190610f06565b60405180910390f35b610292600480360381019061028d9190610f5a565b6105a4565b005b6102ae60048036038101906102a99190610f5a565b6105f6565b005b6102ca60048036038101906102c59190610fc2565b6105ff565b005b6102e660048036038101906102e19190610f5a565b61065d565b005b6102f06106aa565b005b61030c60048036038101906103079190610f5a565b6106c3565b6040516103199190611005565b60405180910390f35b61032a6106cd565b005b61034660048036038101906103419190610fc2565b61071d565b6040516103539190611005565b60405180910390f35b61037660048036038101906103719190611051565b61087f565b604051610383919061109e565b60405180910390f35b6103946108e9565b6040516103a19190610f06565b60405180910390f35b6103b26108f0565b005b6103bc61094c565b6040516103c991906110c6565b60405180910390f35b6103da610aa1565b005b6103f660048036038101906103f1919061129f565b610af1565b005b610400610b53565b60405161040d91906110c6565b60405180910390f35b61041e610ca8565b005b610428610cea565b604051610435919061131a565b60405180910390f35b610446610cf7565b005b610462600480360381019061045d919061129f565b610d35565b60405161046f919061134d565b60405180910390f35b610480610e9d565b005b5f8054905090565b3373ffffffffffffffffffffffffffffffffffffffff167fcdda07d20845760c8f1960f9992eb7b5253a2e6a68eb2340137c70a30e3af38b436040516104d09190610f06565b60405180910390a2565b5f42905090565b805f8190555f80fd5b5f43905090565b5f6104fa610b53565b90503373ffffffffffffffffffffffffffffffffffffffff167f226e31c8dfdcc17bec5aa64ce3cd9856d9bb4637e48450d27f62e0bda5bca6498260405161054291906110c6565b60405180910390a250565b3373ffffffffffffffffffffffffffffffffffffffff167fb8a2de765c79a4dd09c7a683c268e826303e1bbd5425c29706963329538a7534466040516105939190610f06565b60405180910390a2565b5f44905090565b3373ffffffffffffffffffffffffffffffffffffffff167f9c5f2f6f83b58de8294bc8af0de4c9e4fdd2c335eaf0d9a2461b5a5e4b014e8682406040516105eb9190611005565b60405180910390a250565b805f8190555050565b5f6106098261071d565b90503373ffffffffffffffffffffffffffffffffffffffff167f3c1e946213ca4a4f826f561e68d2e244c2db896d9612980bf786cd7da2c6ccdf826040516106519190611005565b60405180910390a25050565b803373ffffffffffffffffffffffffffffffffffffffff167f043cc306157a91d747b36aba0e235bbbc5771d75aba162f6e5540767d22673c660405160405180910390a3805f8190555050565b3373ffffffffffffffffffffffffffffffffffffffff16ff5b5f81409050919050565b3373ffffffffffffffffffffffffffffffffffffffff167f52481872d5402d9c11fcd282d57bfa9af8a0edcc9115a4ba1936f3bb45e286bb446040516107139190610f06565b60405180910390a2565b5f805f6801000000000000000173ffffffffffffffffffffffffffffffffffffffff168460405160240161075191906110c6565b6040516020818303038152906040527f78a75fbe000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516107db91906113b8565b5f60405180830381855afa9150503d805f8114610813576040519150601f19603f3d011682016040523d82523d5f602084013e610818565b606091505b50915091508161085d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161085490611428565b60405180910390fd5b5f81806020019051810190610872919061145a565b9050809350505050919050565b5f80828461088d91906114b2565b905082843373ffffffffffffffffffffffffffffffffffffffff167f76efea95e5da1fa661f235b2921ae1d89b99e457ec73fb88e34a1d150f95c64b846040516108d7919061109e565b60405180910390a48091505092915050565b5f46905090565b5f6108f961094c565b90503373ffffffffffffffffffffffffffffffffffffffff167f7f3eb80b1815b51402bef9f6393921916f5c7391ff4f5e82e2f5d7f866c65fb78260405161094191906110c6565b60405180910390a250565b5f805f6801000000000000000173ffffffffffffffffffffffffffffffffffffffff166040516024016040516020818303038152906040527f705fab20000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516109ff91906113b8565b5f60405180830381855afa9150503d805f8114610a37576040519150601f19603f3d011682016040523d82523d5f602084013e610a3c565b606091505b509150915081610a81576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a789061153d565b60405180910390fd5b5f81806020019051810190610a96919061156f565b905080935050505090565b3373ffffffffffffffffffffffffffffffffffffffff167f05a74f03de8d43b274ce924e4542bad549dea8f3572574a2b81d6ba62fc717b442604051610ae79190610f06565b60405180910390a2565b5f610afd848484610d35565b90503373ffffffffffffffffffffffffffffffffffffffff167f19481a9edff48c370d941b1f368fd2198a0f3117e18748a56d5e193b36dc569a82604051610b45919061134d565b60405180910390a250505050565b5f805f6801000000000000000173ffffffffffffffffffffffffffffffffffffffff166040516024016040516020818303038152906040527f53e87d66000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610c0691906113b8565b5f60405180830381855afa9150503d805f8114610c3e576040519150601f19603f3d011682016040523d82523d5f602084013e610c43565b606091505b509150915081610c88576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c7f90611428565b60405180910390fd5b5f81806020019051810190610c9d919061156f565b905080935050505090565b5f610ce8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cdf906115e4565b60405180910390fd5b565b6801000000000000000181565b60056040517f9195785a000000000000000000000000000000000000000000000000000000008152600401610d2c919061168e565b60405180910390fd5b5f805f6801000000000000000173ffffffffffffffffffffffffffffffffffffffff16868686604051602401610d6d93929190611702565b6040516020818303038152906040527f5ee837e7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610df791906113b8565b5f60405180830381855afa9150503d805f8114610e2f576040519150601f19603f3d011682016040523d82523d5f602084013e610e34565b606091505b509150915081610e79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e709061153d565b60405180910390fd5b5f81806020019051810190610e8e9190611768565b90508093505050509392505050565b3373ffffffffffffffffffffffffffffffffffffffff167f094703abe6f34e06c217139505bcc40e39f606853962e503a74d776a28f1148f5f54604051610ee49190610f06565b60405180910390a2565b5f819050919050565b610f0081610eee565b82525050565b5f602082019050610f195f830184610ef7565b92915050565b5f604051905090565b5f80fd5b5f80fd5b610f3981610eee565b8114610f43575f80fd5b50565b5f81359050610f5481610f30565b92915050565b5f60208284031215610f6f57610f6e610f28565b5b5f610f7c84828501610f46565b91505092915050565b5f67ffffffffffffffff82169050919050565b610fa181610f85565b8114610fab575f80fd5b50565b5f81359050610fbc81610f98565b92915050565b5f60208284031215610fd757610fd6610f28565b5b5f610fe484828501610fae565b91505092915050565b5f819050919050565b610fff81610fed565b82525050565b5f6020820190506110185f830184610ff6565b92915050565b5f819050919050565b6110308161101e565b811461103a575f80fd5b50565b5f8135905061104b81611027565b92915050565b5f806040838503121561106757611066610f28565b5b5f6110748582860161103d565b92505060206110858582860161103d565b9150509250929050565b6110988161101e565b82525050565b5f6020820190506110b15f83018461108f565b92915050565b6110c081610f85565b82525050565b5f6020820190506110d95f8301846110b7565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f611108826110df565b9050919050565b611118816110fe565b8114611122575f80fd5b50565b5f813590506111338161110f565b92915050565b61114281610fed565b811461114c575f80fd5b50565b5f8135905061115d81611139565b92915050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6111b18261116b565b810181811067ffffffffffffffff821117156111d0576111cf61117b565b5b80604052505050565b5f6111e2610f1f565b90506111ee82826111a8565b919050565b5f67ffffffffffffffff82111561120d5761120c61117b565b5b6112168261116b565b9050602081019050919050565b828183375f83830152505050565b5f61124361123e846111f3565b6111d9565b90508281526020810184848401111561125f5761125e611167565b5b61126a848285611223565b509392505050565b5f82601f83011261128657611285611163565b5b8135611296848260208601611231565b91505092915050565b5f805f606084860312156112b6576112b5610f28565b5b5f6112c386828701611125565b93505060206112d48682870161114f565b925050604084013567ffffffffffffffff8111156112f5576112f4610f2c565b5b61130186828701611272565b9150509250925092565b611314816110fe565b82525050565b5f60208201905061132d5f83018461130b565b92915050565b5f8115159050919050565b61134781611333565b82525050565b5f6020820190506113605f83018461133e565b92915050565b5f81519050919050565b5f81905092915050565b8281835e5f83830152505050565b5f61139282611366565b61139c8185611370565b93506113ac81856020860161137a565b80840191505092915050565b5f6113c38284611388565b915081905092915050565b5f82825260208201905092915050565b7f756e7375636365737366756c2063616c6c20746f2061726368200000000000005f82015250565b5f611412601a836113ce565b915061141d826113de565b602082019050919050565b5f6020820190508181035f83015261143f81611406565b9050919050565b5f8151905061145481611139565b92915050565b5f6020828403121561146f5761146e610f28565b5b5f61147c84828501611446565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6114bc8261101e565b91506114c78361101e565b92508282019050828112155f8312168382125f8412151617156114ed576114ec611485565b5b92915050565b7f756e7375636365737366756c2063616c6c20746f2061726368000000000000005f82015250565b5f6115276019836113ce565b9150611532826114f3565b602082019050919050565b5f6020820190508181035f8301526115548161151b565b9050919050565b5f8151905061156981610f98565b92915050565b5f6020828403121561158457611583610f28565b5b5f6115918482850161155b565b91505092915050565b7f417373657274204572726f72204d6573736167650000000000000000000000005f82015250565b5f6115ce6014836113ce565b91506115d98261159a565b602082019050919050565b5f6020820190508181035f8301526115fb816115c2565b9050919050565b5f819050919050565b5f819050919050565b5f61162e61162961162484611602565b61160b565b610eee565b9050919050565b61163e81611614565b82525050565b7f56616c756520697320746f6f206c6f77000000000000000000000000000000005f82015250565b5f6116786010836113ce565b915061168382611644565b602082019050919050565b5f6040820190506116a15f830184611635565b81810360208301526116b28161166c565b905092915050565b5f82825260208201905092915050565b5f6116d482611366565b6116de81856116ba565b93506116ee81856020860161137a565b6116f78161116b565b840191505092915050565b5f6060820190506117155f83018661130b565b6117226020830185610ff6565b818103604083015261173481846116ca565b9050949350505050565b61174781611333565b8114611751575f80fd5b50565b5f815190506117628161173e565b92915050565b5f6020828403121561177d5761177c610f28565b5b5f61178a84828501611754565b9150509291505056fea264697066735822122088b3fe8589df5bd1c9d7d46b543867f57d179028bd99eeec4aca768ba9581a3f64736f6c634300081a0033 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider excluding generated bytecode from version control
Including compiled bytecode (storage.byte
) in version control is generally discouraged. It can lead to larger repository sizes and potential merge conflicts when the bytecode changes. It's best practice to generate bytecode during the build or testing process.
Consider removing storage.byte
from the repository and adding it to .gitignore
to prevent future commits:
+ echo "tests/fixtures/storage.byte" >> .gitignore
Committable suggestion was skipped due to low confidence.
Description
This PR adds state read and execution using remote registers API from the AN.
For contributor use:
master
branchFiles changed
in the Github PR explorerSummary by CodeRabbit
Release Notes
New Features
BlockExecutor
for executing transactions in the EVM context on the Flow blockchain.Storage
contract for better state tracking.Refactor
requester
toevm
across multiple services.EVMClient
.Bug Fixes
evm
services.Chores
requester
package and updated test cases to reflect new client integrations.go.mod
files to ensure compatibility with the latest changes.