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

use warpRequirePrimaryNetworkSigners config #537

Merged
merged 8 commits into from
Nov 22, 2024
19 changes: 10 additions & 9 deletions relayer/application_relayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ type ApplicationRelayer struct {
signingSubnetID ids.ID
destinationClient vms.DestinationClient
relayerID database.RelayerID
warpQuorum config.WarpQuorum
warpConfig config.WarpConfig
checkpointManager CheckpointManager
sourceWarpSignatureClient *rpc.Client // nil if configured to fetch signatures via AppRequest for the source blockchain
signatureAggregator *aggregator.SignatureAggregator
Expand All @@ -79,19 +79,20 @@ func NewApplicationRelayer(
cfg *config.Config,
signatureAggregator *aggregator.SignatureAggregator,
) (*ApplicationRelayer, error) {
quorum, err := cfg.GetWarpQuorum(relayerID.DestinationBlockchainID)
warpConfig, err := cfg.GetWarpConfig(relayerID.DestinationBlockchainID)
if err != nil {
logger.Error(
"Failed to get warp quorum from config. Relayer may not be configured to deliver to the destination chain.",
"Failed to get warp config. Relayer may not be configured to deliver to the destination chain.",
zap.String("destinationBlockchainID", relayerID.DestinationBlockchainID.String()),
zap.Error(err),
)
return nil, err
}

var signingSubnet ids.ID
if sourceBlockchain.GetSubnetID() == constants.PrimaryNetworkID {
// If the message originates from the primary subnet, then we instead "self sign"
// the message using the validators of the destination subnet.
if sourceBlockchain.GetSubnetID() == constants.PrimaryNetworkID && !warpConfig.RequirePrimaryNetworkSigners {
// If the message originates from the primary network, and the primary network is validated by
// the destination subnet we can "self-sign" the message using the validators of the destination subnet.
signingSubnet = cfg.GetSubnetID(relayerID.DestinationBlockchainID)
} else {
// Otherwise, the source subnet signs the message.
Expand Down Expand Up @@ -128,7 +129,7 @@ func NewApplicationRelayer(
destinationClient: destinationClient,
relayerID: relayerID,
signingSubnetID: signingSubnet,
warpQuorum: quorum,
warpConfig: warpConfig,
checkpointManager: checkpointManager,
sourceWarpSignatureClient: warpClient,
signatureAggregator: signatureAggregator,
Expand Down Expand Up @@ -206,7 +207,7 @@ func (r *ApplicationRelayer) ProcessMessage(handler messages.MessageHandler) (co
unsignedMessage,
nil,
r.signingSubnetID,
r.warpQuorum.QuorumNumerator,
r.warpConfig.QuorumNumerator,
)
r.incFetchSignatureAppRequestCount()
if err != nil {
Expand Down Expand Up @@ -282,7 +283,7 @@ func (r *ApplicationRelayer) createSignedMessage(
&signedWarpMessageBytes,
"warp_getMessageAggregateSignature",
unsignedMessage.ID(),
r.warpQuorum.QuorumNumerator,
r.warpConfig.QuorumNumerator,
r.signingSubnetID.String(),
)
if err == nil {
Expand Down
64 changes: 24 additions & 40 deletions relayer/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"github.com/ava-labs/awm-relayer/peers"

"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/constants"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/utils/set"

Expand Down Expand Up @@ -50,8 +49,6 @@ awm-relayer --version Display awm-relayer vers
awm-relayer --help Display awm-relayer usage and exit.
`

var errFailedToGetWarpQuorum = errors.New("failed to get warp quorum")

// Top-level configuration
type Config struct {
LogLevel string `mapstructure:"log-level" json:"log-level"`
Expand Down Expand Up @@ -156,31 +153,24 @@ func (c *Config) GetSubnetID(blockchainID ids.ID) ids.ID {
}

// If the numerator in the Warp config is 0, use the default value
func calculateQuorumNumerator(cfgNumerator uint64) uint64 {
if cfgNumerator == 0 {
return warp.WarpDefaultQuorumNumerator
func warpConfigFromSubnetWarpConfig(inputConfig warp.Config) WarpConfig {
if inputConfig.QuorumNumerator == 0 {
return WarpConfig{
QuorumNumerator: warp.WarpDefaultQuorumNumerator,
RequirePrimaryNetworkSigners: inputConfig.RequirePrimaryNetworkSigners,
}
}
return cfgNumerator
}

// Helper to retrieve the Warp Quorum from the chain config.
// Differentiates between subnet-evm and coreth RPC internally
func getWarpQuorum(
subnetID ids.ID,
blockchainID ids.ID,
client ethclient.Client,
) (WarpQuorum, error) {
if subnetID == constants.PrimaryNetworkID {
return WarpQuorum{
QuorumNumerator: warp.WarpDefaultQuorumNumerator,
QuorumDenominator: warp.WarpQuorumDenominator,
}, nil
return WarpConfig{
QuorumNumerator: inputConfig.QuorumNumerator,
RequirePrimaryNetworkSigners: inputConfig.RequirePrimaryNetworkSigners,
}
}

func getWarpConfig(client ethclient.Client) (*warp.Config, error) {
// Fetch the subnet's chain config
chainConfig, err := client.ChainConfig(context.Background())
if err != nil {
return WarpQuorum{}, fmt.Errorf("failed to fetch chain config for blockchain %s: %w", blockchainID, err)
return nil, fmt.Errorf("failed to fetch chain config")
}

// First, check the list of precompile upgrades to get the most up to date Warp config
Expand All @@ -202,30 +192,24 @@ func getWarpQuorum(
}
}
if warpConfig != nil {
return WarpQuorum{
QuorumNumerator: calculateQuorumNumerator(warpConfig.QuorumNumerator),
QuorumDenominator: warp.WarpQuorumDenominator,
}, nil
return warpConfig, nil
}

// If we didn't find the Warp config in the upgrade precompile list, check the genesis config
warpConfig, ok := chainConfig.GenesisPrecompiles[warpConfigKey].(*warp.Config)
if ok {
return WarpQuorum{
QuorumNumerator: calculateQuorumNumerator(warpConfig.QuorumNumerator),
QuorumDenominator: warp.WarpQuorumDenominator,
}, nil
if !ok {
return nil, fmt.Errorf("no Warp config found in chain config")
}
return WarpQuorum{}, fmt.Errorf("failed to find warp config for blockchain %s", blockchainID)
return warpConfig, nil
}

func (c *Config) InitializeWarpQuorums() error {
// Fetch the Warp quorum values for each destination subnet.
// Initializes Warp configurations (quorum and self-signing settings) for each destination subnet
func (c *Config) InitializeWarpConfigs() error {
// Fetch the Warp config values for each destination subnet.
for _, destinationSubnet := range c.DestinationBlockchains {
err := destinationSubnet.initializeWarpQuorum()
err := destinationSubnet.initializeWarpConfigs()
if err != nil {
return fmt.Errorf(
"failed to initialize Warp quorum for destination subnet %s: %w",
"failed to initialize Warp config for destination subnet %s: %w",
destinationSubnet.SubnetID,
err,
)
Expand All @@ -247,13 +231,13 @@ func (c *Config) GetOverwrittenOptions() []string {
// Top-level config getters
//

func (c *Config) GetWarpQuorum(blockchainID ids.ID) (WarpQuorum, error) {
func (c *Config) GetWarpConfig(blockchainID ids.ID) (WarpConfig, error) {
for _, s := range c.DestinationBlockchains {
if blockchainID.String() == s.BlockchainID {
return s.warpQuorum, nil
return s.warpConfig, nil
}
}
return WarpQuorum{}, errFailedToGetWarpQuorum
return WarpConfig{}, fmt.Errorf("blockchain %s not configured as a destination", blockchainID)
}

var _ peers.Config = &Config{}
Expand Down
86 changes: 59 additions & 27 deletions relayer/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ func TestEitherKMSOrAccountPrivateKey(t *testing.T) {
}
}

func TestGetWarpQuorum(t *testing.T) {
func TestGetWarpConfig(t *testing.T) {
blockchainID, err := ids.FromString("p433wpuXyJiDhyazPYyZMJeaoPSW76CBZ2x7wrVPLgvokotXz")
require.NoError(t, err)
subnetID, err := ids.FromString("2PsShLjrFFwR51DMcAh8pyuwzLn1Ym3zRhuXLTmLCR1STk2mL6")
Expand All @@ -255,19 +255,8 @@ func TestGetWarpQuorum(t *testing.T) {
chainConfig params.ChainConfigWithUpgradesJSON
getChainConfigCalls int
expectedError error
expectedQuorum WarpQuorum
expectedWarpConfig WarpConfig
}{
{
name: "primary network",
blockchainID: blockchainID,
subnetID: ids.Empty,
getChainConfigCalls: 0,
expectedError: nil,
expectedQuorum: WarpQuorum{
QuorumNumerator: warp.WarpDefaultQuorumNumerator,
QuorumDenominator: warp.WarpQuorumDenominator,
},
},
{
name: "subnet genesis precompile",
blockchainID: blockchainID,
Expand All @@ -283,9 +272,9 @@ func TestGetWarpQuorum(t *testing.T) {
},
},
expectedError: nil,
expectedQuorum: WarpQuorum{
QuorumNumerator: warp.WarpDefaultQuorumNumerator,
QuorumDenominator: warp.WarpQuorumDenominator,
expectedWarpConfig: WarpConfig{
QuorumNumerator: warp.WarpDefaultQuorumNumerator,
RequirePrimaryNetworkSigners: false,
},
},
{
Expand All @@ -303,9 +292,9 @@ func TestGetWarpQuorum(t *testing.T) {
},
},
expectedError: nil,
expectedQuorum: WarpQuorum{
QuorumNumerator: 50,
QuorumDenominator: warp.WarpQuorumDenominator,
expectedWarpConfig: WarpConfig{
QuorumNumerator: 50,
RequirePrimaryNetworkSigners: false,
},
},
{
Expand All @@ -325,9 +314,9 @@ func TestGetWarpQuorum(t *testing.T) {
},
},
expectedError: nil,
expectedQuorum: WarpQuorum{
QuorumNumerator: warp.WarpDefaultQuorumNumerator,
QuorumDenominator: warp.WarpQuorumDenominator,
expectedWarpConfig: WarpConfig{
QuorumNumerator: warp.WarpDefaultQuorumNumerator,
RequirePrimaryNetworkSigners: false,
},
},
{
Expand All @@ -347,9 +336,51 @@ func TestGetWarpQuorum(t *testing.T) {
},
},
expectedError: nil,
expectedQuorum: WarpQuorum{
QuorumNumerator: 50,
QuorumDenominator: warp.WarpQuorumDenominator,
expectedWarpConfig: WarpConfig{
QuorumNumerator: 50,
RequirePrimaryNetworkSigners: false,
},
},
{
name: "require primary network signers",
blockchainID: blockchainID,
subnetID: subnetID,
getChainConfigCalls: 1,
chainConfig: params.ChainConfigWithUpgradesJSON{
ChainConfig: params.ChainConfig{
GenesisPrecompiles: params.Precompiles{
warpConfigKey: &warp.Config{
QuorumNumerator: 0,
RequirePrimaryNetworkSigners: true,
},
},
},
},
expectedError: nil,
expectedWarpConfig: WarpConfig{
QuorumNumerator: warp.WarpDefaultQuorumNumerator,
RequirePrimaryNetworkSigners: true,
},
},
{
name: "require primary network signers explicit false",
blockchainID: blockchainID,
subnetID: subnetID,
getChainConfigCalls: 1,
chainConfig: params.ChainConfigWithUpgradesJSON{
ChainConfig: params.ChainConfig{
GenesisPrecompiles: params.Precompiles{
warpConfigKey: &warp.Config{
QuorumNumerator: 0,
RequirePrimaryNetworkSigners: false,
},
},
},
},
expectedError: nil,
expectedWarpConfig: WarpConfig{
QuorumNumerator: warp.WarpDefaultQuorumNumerator,
RequirePrimaryNetworkSigners: false,
},
},
}
Expand All @@ -364,9 +395,10 @@ func TestGetWarpQuorum(t *testing.T) {
).Times(testCase.getChainConfigCalls),
)

quorum, err := getWarpQuorum(testCase.subnetID, testCase.blockchainID, client)
subnetWarpConfig, err := getWarpConfig(client)
require.Equal(t, testCase.expectedError, err)
require.Equal(t, testCase.expectedQuorum, quorum)
expectedWarpConfig := warpConfigFromSubnetWarpConfig(*subnetWarpConfig)
require.Equal(t, testCase.expectedWarpConfig, expectedWarpConfig)
})
}
}
Expand Down
31 changes: 20 additions & 11 deletions relayer/config/destination_blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import (
"fmt"

"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/constants"
basecfg "github.com/ava-labs/awm-relayer/config"
"github.com/ava-labs/awm-relayer/utils"
"github.com/ava-labs/subnet-evm/precompile/contracts/warp"
"github.com/ethereum/go-ethereum/crypto"
)

Expand All @@ -23,7 +25,7 @@ type DestinationBlockchain struct {
AccountPrivateKey string `mapstructure:"account-private-key" json:"account-private-key"`

// Fetched from the chain after startup
warpQuorum WarpQuorum
warpConfig WarpConfig

// convenience fields to access parsed data after initialization
subnetID ids.ID
Expand Down Expand Up @@ -77,7 +79,7 @@ func (s *DestinationBlockchain) GetBlockchainID() ids.ID {
return s.blockchainID
}

func (s *DestinationBlockchain) initializeWarpQuorum() error {
func (s *DestinationBlockchain) initializeWarpConfigs() error {
blockchainID, err := ids.FromString(s.BlockchainID)
if err != nil {
return fmt.Errorf("invalid blockchainID in configuration. error: %w", err)
Expand All @@ -86,28 +88,35 @@ func (s *DestinationBlockchain) initializeWarpQuorum() error {
if err != nil {
return fmt.Errorf("invalid subnetID in configuration. error: %w", err)
}
// If the destination blockchain is the primary network, use the default quorum
// primary network signers here are irrelevant and can be left at default value
if subnetID == constants.PrimaryNetworkID {
s.warpConfig = WarpConfig{
QuorumNumerator: warp.WarpDefaultQuorumNumerator,
}
return nil
}

client, err := utils.NewEthClientWithConfig(
context.Background(),
s.RPCEndpoint.BaseURL,
s.RPCEndpoint.HTTPHeaders,
s.RPCEndpoint.QueryParams,
)
defer client.Close()
if err != nil {
return fmt.Errorf("failed to dial destination blockchain %s: %w", blockchainID, err)
}
defer client.Close()
quorum, err := getWarpQuorum(subnetID, blockchainID, client)
subnetWarpConfig, err := getWarpConfig(client)
if err != nil {
return fmt.Errorf("failed to fetch warp quorum for subnet %s: %w", subnetID, err)
return fmt.Errorf("failed to fetch warp config for blockchain %s: %w", blockchainID, err)
}

s.warpQuorum = quorum
s.warpConfig = warpConfigFromSubnetWarpConfig(*subnetWarpConfig)
return nil
}

// Warp Quorum configuration, fetched from the chain config
type WarpQuorum struct {
QuorumNumerator uint64
QuorumDenominator uint64
// Warp Configuration, fetched from the chain config
type WarpConfig struct {
QuorumNumerator uint64
RequirePrimaryNetworkSigners bool
}
Loading