Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Configurable teleporter-max-gas-limit #621

Merged
merged 8 commits into from
Jan 17, 2025
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.

Loading