-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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(store/v2): gaskv store #18240
feat(store/v2): gaskv store #18240
Conversation
WalkthroughThis pull request introduces a comprehensive gas metering system for store operations. It includes the creation of a new Changes
TipsChat with CodeRabbit Bot (
|
applicable issue: #13961 |
@tac0turtle thanks for raising that to my attention. I recall seeing that issue a while ago. I'm trying to understand what should really come out of that. It seems there are two core ideas:
cc @ValarDragon |
@alexanderbez your pull request is missing a changelog! |
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.
Review Status
Actionable comments generated: 3
Configuration used: CodeRabbit UI
Files selected for processing (6)
- store/gas.go (1 hunks)
- store/kv/gas/iterator.go (1 hunks)
- store/kv/gas/store.go (1 hunks)
- store/kv/gas/store_test.go (1 hunks)
- store/kv/mem/store.go (1 hunks)
- store/kv/trace/store.go (2 hunks)
Files skipped from review due to trivial changes (2)
- store/kv/gas/store_test.go
- store/kv/mem/store.go
Additional comments: 24
store/kv/trace/store.go (3)
6-6: The
fmt
package has been added to the import list. Ensure that it is being used in the code and is not an unnecessary import.94-95: The panic message in the
Branch()
method has been updated to use the type of theStore
struct. This change provides more specific information in the panic message, which can be helpful for debugging.- panic("cannot call Branch() on tracekv.Store") + panic(fmt.Sprintf("cannot call Branch() on %T", s))
- 97-98: The panic message in the
BranchWithTrace()
method has been updated in the same way as theBranch()
method.- panic("cannot call BranchWithTrace() on tracekv.Store") + panic(fmt.Sprintf("cannot call BranchWithTrace() on %T", s))store/kv/gas/iterator.go (5)
7-11: The
iterator
struct is well defined with all necessary fields for gas metering and parent store operations. It's good to see that the parent store'sIterator
is being used, which ensures that the underlying store's functionality is not being altered, only extended with gas metering.13-19: The
newIterator
function is correctly initializing theiterator
struct. It's good to see that the function is not exported, which means it's only intended for use within thegas
package. This is a good practice for encapsulation.21-48: The methods
Domain
,Valid
,Key
,Value
,Next
,Close
, andError
are correctly delegating their operations to the parent iterator. This ensures that the underlying store's functionality is preserved.37-40: The
Next
method correctly callsconsumeGasSeek
before delegating to the parent iterator'sNext
method. This ensures that gas is consumed for each iteration step.50-63: The
consumeGasSeek
method correctly consumes gas based on the length of the current key and value if the iterator is valid. It also consumes a fixed amount of gas for each iteration step. This is a good implementation of gas metering for store operations.store/gas.go (8)
1-6: The import section looks clean and only includes necessary packages.
8-24: The
Gas
type and constants for gas consumption descriptors are well defined.45-70: The
GasMeter
interface is well defined and covers all necessary methods for gas consumption tracking.72-81: The
GasConfig
struct is well defined and covers all necessary fields for gas cost configuration.83-98: The
DefaultGasConfig
function returns a default configuration for gas costs. The comment explains that these values are arbitrary and mainly reflect relative costs.100-171: The
defaultGasMeter
struct and its methods are well implemented. TheConsumeGas
andRefundGas
methods correctly handle gas consumption and refunding, including error handling for overflow and negative gas consumption.173-228: The
infiniteGasMeter
struct and its methods are well implemented. TheConsumeGas
andRefundGas
methods correctly handle gas consumption and refunding, including error handling for overflow and negative gas consumption.230-238: The
addGasOverflow
function correctly handles the addition of twoGas
values and returns a boolean indicating whether an overflow occurred.store/kv/gas/store.go (8)
12-16: The
Store
struct is well defined with all necessary fields for a gas metered KVStore. It embeds the parent KVStore, a gas meter, and a gas configuration. This is a good example of composition in Go, where theStore
struct "has a"KVStore
,GasMeter
, andGasConfig
, rather than "is a"KVStore
,GasMeter
, orGasConfig
.18-24: The
New
function is a constructor for theStore
struct. It takes aKVStore
,GasMeter
, andGasConfig
as arguments and returns aBranchedKVStore
. This is a good use of dependency injection, as it allows the caller to provide the specific implementations ofKVStore
,GasMeter
, andGasConfig
that should be used.34-42: The
Get
method consumes gas for the read operation. It consumes a flat cost for the read operation and additional costs per byte for the key and value. This is a good way to account for the computational resources used by the operation.44-47: The
Has
method consumes a flat cost for the operation. This is a good way to account for the computational resources used by the operation.49-54: The
Set
method consumes gas for the write operation. It consumes a flat cost for the write operation and additional costs per byte for the key and value. This is a good way to account for the computational resources used by the operation.56-59: The
Delete
method consumes a flat cost for the operation. This is a good way to account for the computational resources used by the operation.83-85: The
Iterator
method returns a new iterator that consumes gas for each iteration step. This is a good way to account for the computational resources used by the operation.87-89: The
ReverseIterator
method returns a new reverse iterator that consumes gas for each iteration step. This is a good way to account for the computational resources used by the operation.
…smos-sdk into bez/18225-store-v2-gaskv-store
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.
Review Status
Actionable comments generated: 2
Configuration used: CodeRabbit UI
Files selected for processing (2)
- store/gas.go (1 hunks)
- store/kv/gas/store_test.go (1 hunks)
Additional comments: 15
store/kv/gas/store_test.go (13)
1-12: The import statements are well organized and only necessary packages are imported. The constants defined are also appropriate for the test suite.
19-25: The
StoreTestSuite
struct is well defined with all necessary fields for the test suite.27-29: The
TestStorageTestSuite
function correctly runs the test suite.31-35: The
SetupTest
function correctly initializes the parent store, gas meter, and gasKVStore for each test.37-40: The
TearDownTest
function correctly resets the gasKVStore after each test and checks for errors.42-44: The
TestGetStoreKey
function correctly tests theGetStoreKey
method of the gasKVStore.46-48: The
TestGetStoreType
function correctly tests theGetStoreType
method of the gasKVStore.50-56: The
TestGet
function correctly tests theGet
method of the gasKVStore and checks the gas consumed.58-64: The
TestHas
function correctly tests theHas
method of the gasKVStore and checks the gas consumed.66-69: The
TestSet
function correctly tests theSet
method of the gasKVStore and checks the gas consumed.71-77: The
TestDelete
function correctly tests theDelete
method of the gasKVStore and checks the gas consumed.79-94: The
TestIterator
function correctly tests theIterator
method of the gasKVStore and checks the gas consumed.96-111: The
TestReverseIterator
function correctly tests theReverseIterator
method of the gasKVStore and checks the gas consumed.store/gas.go (2)
202-208: The
ConsumeGas
method ofinfiniteGasMeter
also checks for overflow and sets the consumed gas to the new value only if there is no overflow. This is a good practice as it prevents incorrect gas consumption values in case of overflow.230-238: The
addGasOverflow
function correctly checks for overflow before performing the addition operation. This is a good practice as it prevents integer overflow errors.
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.
Review Status
Actionable comments generated: 2
Configuration used: CodeRabbit UI
Files selected for processing (1)
- store/gas.go (1 hunks)
Additional comments: 4
store/gas.go (4)
26-43: The error types
ErrorNegativeGasConsumed
,ErrorOutOfGas
, andErrorGasOverflow
now have theError
method implementation, making them compliant with theerror
interface. This allows these types to be used wherevererror
is expected. Good job on addressing the previous comment.112-183: The
defaultGasMeter
struct and its methods provide a good implementation of theGasMeter
interface. The methods are well-defined and handle edge cases such as gas overflow and exceeding the gas limit. The use of custom error types improves the readability of the code and allows for better error handling.185-240: The
infiniteGasMeter
struct and its methods provide an implementation of theGasMeter
interface where the gas limit is infinite. This could be useful in scenarios where gas consumption is not a concern. The methods are well-defined and handle edge cases such as gas overflow.242-250: The
addGasOverflow
function is a utility function that adds twoGas
values and checks for overflow. This is a good practice as it prevents potential integer overflow bugs.
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.
Review Status
Actionable comments generated: 2
Configuration used: CodeRabbit UI
Files selected for processing (2)
- store/gas.go (1 hunks)
- store/storage/storage_bench_test.go (1 hunks)
Files skipped from review due to trivial changes (1)
- store/storage/storage_bench_test.go
Additional comments: 2
store/gas.go (2)
26-43: The error types
ErrorNegativeGasConsumed
,ErrorOutOfGas
, andErrorGasOverflow
now have theError
method implementation, making them compliant with theerror
interface. This allows these types to be used wherevererror
is expected. Good job on addressing the previous comment.112-250: The
defaultGasMeter
andinfiniteGasMeter
implementations of theGasMeter
interface are well-structured and follow the interface's contract. The panic behavior in case of gas overflow or out-of-gas situations is appropriate, as these are critical errors that should halt execution. TheaddGasOverflow
helper function is a good way to handle potential overflow situations.
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.
LGTM code wise, and thank you @alexanderbez! Also nice and simple test for overflow: one day we should centralize that check in the cosmos-sdk helper libraries.
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.
Review Status
Actionable comments generated: 1
Configuration used: CodeRabbit UI
Files selected for processing (1)
- store/gas.go (1} hunks)
Additional comments: 4
store/gas.go (4)
26-55: The error types
ErrorNegativeGasConsumed
,ErrorOutOfGas
, andErrorGasOverflow
now implement theError
method, making them compliant with theerror
interface. This allows these types to be used wherevererror
is expected. Good job on addressing the previous comment.57-82: The
GasMeter
interface is well defined with clear method signatures and comments explaining their purpose. This makes it easy for other developers to implement their own versions ofGasMeter
if needed.84-104: The
GasConfig
struct provides a clear and flexible way to configure the gas cost for each operation on a KVStore. This allows for easy adjustments of gas costs in the future.123-261: The
defaultGasMeter
andinfiniteGasMeter
structs provide concrete implementations of theGasMeter
interface. The methods are well implemented with clear error handling and panic conditions. TheaddGasOverflow
function is a good utility function to handle potential overflow conditions when adding gas amounts.
Description
closes: #18225
NOTE: This increases fixed gas cost for deletes from 1000 to 1500
Author Checklist
All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.
I have...
!
to the type prefix if API or client breaking changeCHANGELOG.md
make lint
andmake test
Reviewers Checklist
All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.
I have...
!
in the type prefix if API or client breaking changeSummary by CodeRabbit
Store
struct methods for better debugging and user experience.