Skip to content

Commit

Permalink
Merge pull request #621 from najeal/configurable-max-gas
Browse files Browse the repository at this point in the history
Configurable teleporter-max-gas-limit
  • Loading branch information
geoff-vball authored Jan 17, 2025
2 parents bc0c871 + 3ab8bbd commit 1940014
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 20 deletions.
10 changes: 4 additions & 6 deletions messages/teleporter/message_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ import (
)

const (
// The maximum gas limit that can be specified for a Teleporter message
// Based on the C-Chain 15_000_000 gas limit per block, with other Warp message gas overhead conservatively estimated.
maxTeleporterGasLimit = 12_000_000
defaultBlockAcceptanceTimeout = 30 * time.Second
)

Expand Down Expand Up @@ -165,15 +162,16 @@ func (m *messageHandler) ShouldSendMessage(destinationClient vms.DestinationClie
if err != nil {
return false, fmt.Errorf("failed to calculate Teleporter message ID: %w", err)
}

requiredGasLimit := m.teleporterMessage.RequiredGasLimit.Uint64()
destBlockGasLimit := destinationClient.BlockGasLimit()
// Check if the specified gas limit is below the maximum threshold
if m.teleporterMessage.RequiredGasLimit.Uint64() > maxTeleporterGasLimit {
if requiredGasLimit > destBlockGasLimit {
m.logger.Info(
"Gas limit exceeds maximum threshold",
zap.String("destinationBlockchainID", destinationBlockchainID.String()),
zap.String("teleporterMessageID", teleporterMessageID.String()),
zap.Uint64("requiredGasLimit", m.teleporterMessage.RequiredGasLimit.Uint64()),
zap.Uint64("maxGasLimit", maxTeleporterGasLimit),
zap.Uint64("blockGasLimit", destBlockGasLimit),
)
return false, nil
}
Expand Down
4 changes: 3 additions & 1 deletion messages/teleporter/message_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ func TestShouldSendMessage(t *testing.T) {
)
require.NoError(t, err)

const blockGasLimit = 10_000
gasLimitExceededTeleporterMessage := validTeleporterMessage
gasLimitExceededTeleporterMessage.RequiredGasLimit = big.NewInt(maxTeleporterGasLimit + 1)
gasLimitExceededTeleporterMessage.RequiredGasLimit = big.NewInt(blockGasLimit + 1)
gasLimitExceededTeleporterMessageBytes, err := gasLimitExceededTeleporterMessage.Pack()
require.NoError(t, err)

Expand Down Expand Up @@ -233,6 +234,7 @@ func TestShouldSendMessage(t *testing.T) {
SenderAddress().
Return(test.senderAddressResult).
Times(test.senderAddressTimes)
mockClient.EXPECT().BlockGasLimit().Return(uint64(blockGasLimit)).AnyTimes()
mockClient.EXPECT().DestinationBlockchainID().Return(destinationBlockchainID).AnyTimes()
if test.messageReceivedCall != nil {
messageReceivedInput := interfaces.CallMsg{
Expand Down
15 changes: 15 additions & 0 deletions relayer/config/destination_blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ import (
"github.com/ethereum/go-ethereum/crypto"
)

const (
// The block gas limit that can be specified for a Teleporter message
// Based on the C-Chain 15_000_000 gas limit per block, with other Warp message gas overhead conservatively estimated.
defaultBlockGasLimit = 12_000_000
)

// Destination blockchain configuration. Specifies how to connect to and issue
// transactions on the destination blockchain.
type DestinationBlockchain struct {
Expand All @@ -23,6 +29,7 @@ type DestinationBlockchain struct {
KMSKeyID string `mapstructure:"kms-key-id" json:"kms-key-id"`
KMSAWSRegion string `mapstructure:"kms-aws-region" json:"kms-aws-region"`
AccountPrivateKey string `mapstructure:"account-private-key" json:"account-private-key"`
BlockGasLimit uint64 `mapstructure:"block-gas-limit" json:"block-gas-limit"`

// Fetched from the chain after startup
warpConfig WarpConfig
Expand All @@ -34,6 +41,9 @@ type DestinationBlockchain struct {

// Validates the destination subnet configuration
func (s *DestinationBlockchain) Validate() error {
if s.BlockGasLimit == 0 {
s.BlockGasLimit = defaultBlockGasLimit
}
if err := s.RPCEndpoint.Validate(); err != nil {
return fmt.Errorf("invalid rpc-endpoint in destination subnet configuration: %w", err)
}
Expand Down Expand Up @@ -68,6 +78,11 @@ func (s *DestinationBlockchain) Validate() error {
}
s.subnetID = subnetID

if s.subnetID == constants.PrimaryNetworkID &&
s.BlockGasLimit > defaultBlockGasLimit {
return fmt.Errorf("C-Chain block-gas-limit '%d' exceeded", s.BlockGasLimit)
}

return nil
}

Expand Down
7 changes: 6 additions & 1 deletion vms/destination_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@ type DestinationClient interface {

// DestinationBlockchainID returns the ID of the destination chain
DestinationBlockchainID() ids.ID

// BlockGasLimit returns destination blockchain block gas limit
BlockGasLimit() uint64
}

func NewDestinationClient(logger logging.Logger, subnetInfo *config.DestinationBlockchain) (DestinationClient, error) {
func NewDestinationClient(
logger logging.Logger, subnetInfo *config.DestinationBlockchain,
) (DestinationClient, error) {
switch config.ParseVM(subnetInfo.VM) {
case config.EVM:
return evm.NewDestinationClient(logger, subnetInfo)
Expand Down
30 changes: 18 additions & 12 deletions vms/evm/destination_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,41 +44,42 @@ type destinationClient struct {
signer signer.Signer
evmChainID *big.Int
currentNonce uint64
blockGasLimit uint64
logger logging.Logger
}

func NewDestinationClient(
logger logging.Logger,
destinationBlockchain *config.DestinationBlockchain,
) (*destinationClient, error) {
// Dial the destination RPC endpoint
client, err := utils.NewEthClientWithConfig(
context.Background(),
destinationBlockchain.RPCEndpoint.BaseURL,
destinationBlockchain.RPCEndpoint.HTTPHeaders,
destinationBlockchain.RPCEndpoint.QueryParams,
)
destinationID, err := ids.FromString(destinationBlockchain.BlockchainID)
if err != nil {
logger.Error(
"Failed to dial rpc endpoint",
"Could not decode destination chain ID from string",
zap.Error(err),
)
return nil, err
}

destinationID, err := ids.FromString(destinationBlockchain.BlockchainID)
sgnr, err := signer.NewSigner(destinationBlockchain)
if err != nil {
logger.Error(
"Could not decode destination chain ID from string",
"Failed to create signer",
zap.Error(err),
)
return nil, err
}

sgnr, err := signer.NewSigner(destinationBlockchain)
// Dial the destination RPC endpoint
client, err := utils.NewEthClientWithConfig(
context.Background(),
destinationBlockchain.RPCEndpoint.BaseURL,
destinationBlockchain.RPCEndpoint.HTTPHeaders,
destinationBlockchain.RPCEndpoint.QueryParams,
)
if err != nil {
logger.Error(
"Failed to create signer",
"Failed to dial rpc endpoint",
zap.Error(err),
)
return nil, err
Expand Down Expand Up @@ -117,6 +118,7 @@ func NewDestinationClient(
evmChainID: evmChainID,
currentNonce: nonce,
logger: logger,
blockGasLimit: destinationBlockchain.BlockGasLimit,
}, nil
}

Expand Down Expand Up @@ -210,3 +212,7 @@ func (c *destinationClient) SenderAddress() common.Address {
func (c *destinationClient) DestinationBlockchainID() ids.ID {
return c.destinationBlockchainID
}

func (c *destinationClient) BlockGasLimit() uint64 {
return c.blockGasLimit
}
14 changes: 14 additions & 0 deletions vms/mocks/mock_destination_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 1940014

Please sign in to comment.