-
Notifications
You must be signed in to change notification settings - Fork 240
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
Problem: no required gas log in precompiles #1223
Changes from all commits
5e07a2b
df59ecf
707a600
a9d070e
41f3ebc
74860a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -1,6 +1,7 @@ | ||||||||||
package precompiles | ||||||||||
|
||||||||||
import ( | ||||||||||
"github.com/cometbft/cometbft/libs/log" | ||||||||||
"github.com/ethereum/go-ethereum/common" | ||||||||||
) | ||||||||||
|
||||||||||
|
@@ -10,18 +11,56 @@ | |||||||||
|
||||||||||
type BaseContract interface { | ||||||||||
Registrable | ||||||||||
RequiredGas(input []byte) uint64 | ||||||||||
} | ||||||||||
|
||||||||||
type baseContract struct { | ||||||||||
address common.Address | ||||||||||
address common.Address | ||||||||||
writeCostPerByte uint64 | ||||||||||
nameByMethod map[[4]byte]string | ||||||||||
gasByMethod map[[4]byte]uint64 | ||||||||||
emptyGasIfInputLessThanPrefix bool | ||||||||||
logger log.Logger | ||||||||||
} | ||||||||||
|
||||||||||
func NewBaseContract(address common.Address) BaseContract { | ||||||||||
func NewBaseContract( | ||||||||||
address common.Address, | ||||||||||
writeCostPerByte uint64, | ||||||||||
nameByMethod map[[4]byte]string, | ||||||||||
gasByMethod map[[4]byte]uint64, | ||||||||||
emptyGasIfInputLessThanPrefix bool, | ||||||||||
logger log.Logger, | ||||||||||
) BaseContract { | ||||||||||
return &baseContract{ | ||||||||||
address: address, | ||||||||||
address, | ||||||||||
writeCostPerByte, | ||||||||||
nameByMethod, | ||||||||||
gasByMethod, | ||||||||||
emptyGasIfInputLessThanPrefix, | ||||||||||
logger, | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
func (c *baseContract) RegistryKey() common.Address { | ||||||||||
return c.address | ||||||||||
} | ||||||||||
|
||||||||||
// RequiredGas calculates the contract gas use | ||||||||||
func (c *baseContract) RequiredGas(input []byte) (gas uint64) { | ||||||||||
var methodID [4]byte | ||||||||||
copy(methodID[:], input[:4]) | ||||||||||
inputLen := len(input) | ||||||||||
defer func() { | ||||||||||
method := c.nameByMethod[methodID] | ||||||||||
c.logger.Debug("required", "gas", gas, "method", method, "len", inputLen) | ||||||||||
}() | ||||||||||
if c.emptyGasIfInputLessThanPrefix && inputLen < 4 { | ||||||||||
return | ||||||||||
} | ||||||||||
// base cost to prevent large input size | ||||||||||
gas = uint64(inputLen) * c.writeCostPerByte | ||||||||||
Check failure Code scanning / gosec Potential integer overflow by integer type conversion Error
Potential integer overflow by integer type conversion
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Potential integer overflow by integer type conversion. Consider adding a check to prevent overflow. + if inputLen > math.MaxUint64/c.writeCostPerByte {
+ // handle the error, possibly return an error
+ }
gas = uint64(inputLen) * c.writeCostPerByte Commitable suggestion
Suggested change
|
||||||||||
if requiredGas, ok := c.gasByMethod[methodID]; ok { | ||||||||||
gas += requiredGas | ||||||||||
} | ||||||||||
return | ||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
import ( | ||
"encoding/binary" | ||
"errors" | ||
"fmt" | ||
|
||
"github.com/cometbft/cometbft/libs/log" | ||
|
||
|
@@ -12,34 +13,45 @@ | |
"github.com/ethereum/go-ethereum/core/vm" | ||
|
||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" | ||
ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper" | ||
cronosevents "github.com/crypto-org-chain/cronos/v2/x/cronos/events" | ||
"github.com/crypto-org-chain/cronos/v2/x/cronos/types" | ||
) | ||
|
||
var ( | ||
relayerContractAddress = common.BytesToAddress([]byte{101}) | ||
relayerGasRequiredByMethod = map[int]uint64{} | ||
relayerGasRequiredByMethod = map[[4]byte]uint64{} | ||
relayerMethodMap = map[[4]byte]string{} | ||
) | ||
|
||
func assignMethodGas(prefix int, gas uint64) { | ||
data := make([]byte, 4) | ||
binary.LittleEndian.PutUint32(data, uint32(prefix)) | ||
Check failure Code scanning / gosec Potential integer overflow by integer type conversion Error
Potential integer overflow by integer type conversion
|
||
var id [4]byte | ||
copy(id[:], data[:4]) | ||
relayerMethodMap[id] = fmt.Sprintf("%d", prefix) | ||
relayerGasRequiredByMethod[id] = gas | ||
} | ||
Comment on lines
+27
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The binary.LittleEndian.PutUint32(data, uint32(prefix)) |
||
|
||
func init() { | ||
relayerGasRequiredByMethod[prefixCreateClient] = 117462 | ||
relayerGasRequiredByMethod[prefixUpdateClient] = 111894 | ||
relayerGasRequiredByMethod[prefixUpgradeClient] = 400000 | ||
relayerGasRequiredByMethod[prefixSubmitMisbehaviour] = 100000 | ||
relayerGasRequiredByMethod[prefixConnectionOpenInit] = 19755 | ||
relayerGasRequiredByMethod[prefixConnectionOpenTry] = 38468 | ||
relayerGasRequiredByMethod[prefixConnectionOpenAck] = 29603 | ||
relayerGasRequiredByMethod[prefixConnectionOpenConfirm] = 12865 | ||
relayerGasRequiredByMethod[prefixChannelOpenInit] = 68701 | ||
relayerGasRequiredByMethod[prefixChannelOpenTry] = 70562 | ||
relayerGasRequiredByMethod[prefixChannelOpenAck] = 22127 | ||
relayerGasRequiredByMethod[prefixChannelOpenConfirm] = 21190 | ||
relayerGasRequiredByMethod[prefixChannelCloseInit] = 100000 | ||
relayerGasRequiredByMethod[prefixChannelCloseConfirm] = 31199 | ||
relayerGasRequiredByMethod[prefixRecvPacket] = 144025 | ||
relayerGasRequiredByMethod[prefixAcknowledgement] = 61781 | ||
relayerGasRequiredByMethod[prefixTimeout] = 104283 | ||
relayerGasRequiredByMethod[prefixTimeoutOnClose] = 100000 | ||
assignMethodGas(prefixCreateClient, 117462) | ||
assignMethodGas(prefixUpdateClient, 111894) | ||
assignMethodGas(prefixUpgradeClient, 400000) | ||
assignMethodGas(prefixSubmitMisbehaviour, 100000) | ||
assignMethodGas(prefixConnectionOpenInit, 19755) | ||
assignMethodGas(prefixConnectionOpenTry, 38468) | ||
assignMethodGas(prefixConnectionOpenAck, 29603) | ||
assignMethodGas(prefixConnectionOpenConfirm, 12865) | ||
assignMethodGas(prefixChannelOpenInit, 68701) | ||
assignMethodGas(prefixChannelOpenTry, 70562) | ||
assignMethodGas(prefixChannelOpenAck, 22127) | ||
assignMethodGas(prefixChannelOpenConfirm, 21190) | ||
assignMethodGas(prefixChannelCloseInit, 100000) | ||
assignMethodGas(prefixChannelCloseConfirm, 31199) | ||
assignMethodGas(prefixRecvPacket, 144025) | ||
assignMethodGas(prefixAcknowledgement, 61781) | ||
assignMethodGas(prefixTimeout, 104283) | ||
assignMethodGas(prefixTimeoutOnClose, 100000) | ||
} | ||
|
||
type RelayerContract struct { | ||
|
@@ -50,12 +62,24 @@ | |
logger log.Logger | ||
} | ||
|
||
func NewRelayerContract(ibcKeeper types.IbcKeeper, cdc codec.Codec, logger log.Logger) vm.PrecompiledContract { | ||
func NewRelayerContract( | ||
ibcKeeper *ibckeeper.Keeper, | ||
cdc codec.Codec, | ||
logger log.Logger, | ||
) vm.PrecompiledContract { | ||
bcLogger := logger.With("precompiles", "relayer") | ||
return &RelayerContract{ | ||
BaseContract: NewBaseContract(relayerContractAddress), | ||
ibcKeeper: ibcKeeper, | ||
cdc: cdc, | ||
logger: logger.With("precompiles", "relayer"), | ||
BaseContract: NewBaseContract( | ||
relayerContractAddress, | ||
authtypes.DefaultTxSizeCostPerByte, | ||
relayerMethodMap, | ||
relayerGasRequiredByMethod, | ||
true, | ||
bcLogger, | ||
), | ||
ibcKeeper: ibcKeeper, | ||
cdc: cdc, | ||
logger: bcLogger, | ||
} | ||
} | ||
|
||
|
@@ -66,24 +90,16 @@ | |
// RequiredGas calculates the contract gas use | ||
// `max(0, len(input) * DefaultTxSizeCostPerByte + requiredGasTable[methodPrefix] - intrinsicGas)` | ||
func (bc *RelayerContract) RequiredGas(input []byte) (gas uint64) { | ||
if len(input) < prefixSize4Bytes { | ||
return 0 | ||
} | ||
intrinsicGas, err := core.IntrinsicGas(input, nil, false, true, true) | ||
if err != nil { | ||
return 0 | ||
} | ||
prefix := int(binary.LittleEndian.Uint32(input[:prefixSize4Bytes])) | ||
requiredGas, ok := relayerGasRequiredByMethod[prefix] | ||
if !ok { | ||
requiredGas = 0 | ||
} | ||
// base cost to prevent large input size | ||
baseCost := uint64(len(input)) * authtypes.DefaultTxSizeCostPerByte | ||
|
||
total := bc.BaseContract.RequiredGas(input) | ||
defer func() { | ||
bc.logger.Debug("required", "gas", gas, "method", prefix, "len", len(input), "intrinsic", intrinsicGas) | ||
bc.logger.Debug("required", "gas", gas, "intrinsic", intrinsicGas, "total", total) | ||
}() | ||
total := requiredGas + baseCost | ||
|
||
if total < intrinsicGas { | ||
return 0 | ||
} | ||
|
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.
The
RequiredGas
method is removed from theBankContract
struct. This is likely because the method is now part of theBaseContract
and can be accessed through it. This change reduces code duplication and enhances maintainability.