From 16e661bedc4425a71a6d60676825feedf9531382 Mon Sep 17 00:00:00 2001 From: Ian Suvak Date: Thu, 31 Oct 2024 10:16:54 -0400 Subject: [PATCH 1/4] use warpRequirePrimaryNetworkSigners config --- relayer/application_relayer.go | 17 +++++-- relayer/config/config.go | 56 +++++++++++------------- relayer/config/config_test.go | 14 +----- relayer/config/destination_blockchain.go | 26 ++++++++--- relayer/main/main.go | 2 +- 5 files changed, 62 insertions(+), 53 deletions(-) diff --git a/relayer/application_relayer.go b/relayer/application_relayer.go index c1c93910..76e3c6f3 100644 --- a/relayer/application_relayer.go +++ b/relayer/application_relayer.go @@ -88,10 +88,21 @@ func NewApplicationRelayer( ) return nil, err } + requirePrimaryNetworkSigners, err := cfg.GetWarpRequirePrimaryNetworkSigners(relayerID.DestinationBlockchainID) + // this shouldn't be reachable since if we found a quorum, we should also find the requirePrimaryNetworkSigners + // but leaving the check for completeness + if err != nil { + logger.Error( + "Failed to get warp primary network configuration from config.", + 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 && !requirePrimaryNetworkSigners { + // If the message originates from the primary subnet, and the primary network is validated by + // the destination change 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. diff --git a/relayer/config/config.go b/relayer/config/config.go index 3f643dd2..0158e149 100644 --- a/relayer/config/config.go +++ b/relayer/config/config.go @@ -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" @@ -156,31 +155,25 @@ 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 { +func calculateQuorum(cfgNumerator uint64) WarpQuorum { if cfgNumerator == 0 { - return warp.WarpDefaultQuorumNumerator - } - 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 + } + } else { + return WarpQuorum{ + QuorumNumerator: cfgNumerator, + QuorumDenominator: warp.WarpQuorumDenominator, + } } +} +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 @@ -202,27 +195,21 @@ 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 { +// Initializes Warp configurations (quorum and self-signing settings) for each destination subnet +func (c *Config) InitializeWarpConfigs() error { // Fetch the Warp quorum 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", @@ -256,6 +243,15 @@ func (c *Config) GetWarpQuorum(blockchainID ids.ID) (WarpQuorum, error) { return WarpQuorum{}, errFailedToGetWarpQuorum } +func (c *Config) GetWarpRequirePrimaryNetworkSigners(blockchainID ids.ID) (bool, error) { + for _, s := range c.DestinationBlockchains { + if blockchainID.String() == s.BlockchainID { + return s.warpRequirePrimaryNetworkSigners, nil + } + } + return false, errFailedToGetWarpQuorum +} + var _ peers.Config = &Config{} func (c *Config) GetPChainAPI() *basecfg.APIConfig { diff --git a/relayer/config/config_test.go b/relayer/config/config_test.go index 06f54248..2f0c6156 100644 --- a/relayer/config/config_test.go +++ b/relayer/config/config_test.go @@ -257,17 +257,6 @@ func TestGetWarpQuorum(t *testing.T) { expectedError error expectedQuorum WarpQuorum }{ - { - 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, @@ -364,8 +353,9 @@ func TestGetWarpQuorum(t *testing.T) { ).Times(testCase.getChainConfigCalls), ) - quorum, err := getWarpQuorum(testCase.subnetID, testCase.blockchainID, client) + warpConfig, err := getWarpConfig(client) require.Equal(t, testCase.expectedError, err) + quorum := calculateQuorum(warpConfig.QuorumNumerator) require.Equal(t, testCase.expectedQuorum, quorum) }) } diff --git a/relayer/config/destination_blockchain.go b/relayer/config/destination_blockchain.go index 2e0c9eb1..89c3b1b5 100644 --- a/relayer/config/destination_blockchain.go +++ b/relayer/config/destination_blockchain.go @@ -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" ) @@ -23,7 +25,8 @@ type DestinationBlockchain struct { AccountPrivateKey string `mapstructure:"account-private-key" json:"account-private-key"` // Fetched from the chain after startup - warpQuorum WarpQuorum + warpQuorum WarpQuorum + warpRequirePrimaryNetworkSigners bool // convenience fields to access parsed data after initialization subnetID ids.ID @@ -77,7 +80,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) @@ -86,6 +89,15 @@ 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.warpQuorum = WarpQuorum{ + QuorumNumerator: warp.WarpDefaultQuorumNumerator, + QuorumDenominator: warp.WarpQuorumDenominator, + } + return nil + } client, err := utils.NewEthClientWithConfig( context.Background(), @@ -93,16 +105,16 @@ func (s *DestinationBlockchain) initializeWarpQuorum() error { 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) + warpConfig, 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.warpQuorum = calculateQuorum(warpConfig.QuorumNumerator) + s.warpRequirePrimaryNetworkSigners = warpConfig.RequirePrimaryNetworkSigners return nil } diff --git a/relayer/main/main.go b/relayer/main/main.go index 06e4c6e5..b785444f 100644 --- a/relayer/main/main.go +++ b/relayer/main/main.go @@ -80,7 +80,7 @@ func main() { } // Initialize the Warp Quorum values by fetching via RPC // We do this here so that BuildConfig doesn't need to make RPC calls - if err = cfg.InitializeWarpQuorums(); err != nil { + if err = cfg.InitializeWarpConfigs(); err != nil { panic(fmt.Errorf("couldn't initialize warp quorums: %w", err)) } From 8dfb1940821d4e8cb457907daf6273548621da59 Mon Sep 17 00:00:00 2001 From: Ian Suvak Date: Wed, 20 Nov 2024 06:56:27 -0500 Subject: [PATCH 2/4] test requirePrimaryNetworkSigners explicitly --- relayer/config/config_test.go | 66 ++++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/relayer/config/config_test.go b/relayer/config/config_test.go index 2f0c6156..18835150 100644 --- a/relayer/config/config_test.go +++ b/relayer/config/config_test.go @@ -242,20 +242,21 @@ 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") require.NoError(t, err) testCases := []struct { - name string - blockchainID ids.ID - subnetID ids.ID - chainConfig params.ChainConfigWithUpgradesJSON - getChainConfigCalls int - expectedError error - expectedQuorum WarpQuorum + name string + blockchainID ids.ID + subnetID ids.ID + chainConfig params.ChainConfigWithUpgradesJSON + getChainConfigCalls int + expectedError error + expectedQuorum WarpQuorum + expectedRequirePrimaryNeworkSigners bool }{ { name: "subnet genesis precompile", @@ -276,6 +277,7 @@ func TestGetWarpQuorum(t *testing.T) { QuorumNumerator: warp.WarpDefaultQuorumNumerator, QuorumDenominator: warp.WarpQuorumDenominator, }, + expectedRequirePrimaryNeworkSigners: false, }, { name: "subnet genesis precompile non-default", @@ -296,6 +298,7 @@ func TestGetWarpQuorum(t *testing.T) { QuorumNumerator: 50, QuorumDenominator: warp.WarpQuorumDenominator, }, + expectedRequirePrimaryNeworkSigners: false, }, { name: "subnet upgrade precompile", @@ -318,6 +321,7 @@ func TestGetWarpQuorum(t *testing.T) { QuorumNumerator: warp.WarpDefaultQuorumNumerator, QuorumDenominator: warp.WarpQuorumDenominator, }, + expectedRequirePrimaryNeworkSigners: false, }, { name: "subnet upgrade precompile non-default", @@ -340,6 +344,51 @@ func TestGetWarpQuorum(t *testing.T) { QuorumNumerator: 50, QuorumDenominator: warp.WarpQuorumDenominator, }, + expectedRequirePrimaryNeworkSigners: 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, + expectedQuorum: WarpQuorum{ + QuorumNumerator: warp.WarpDefaultQuorumNumerator, + QuorumDenominator: warp.WarpQuorumDenominator, + }, + expectedRequirePrimaryNeworkSigners: 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, + expectedQuorum: WarpQuorum{ + QuorumNumerator: warp.WarpDefaultQuorumNumerator, + QuorumDenominator: warp.WarpQuorumDenominator, + }, + expectedRequirePrimaryNeworkSigners: false, }, } @@ -357,6 +406,7 @@ func TestGetWarpQuorum(t *testing.T) { require.Equal(t, testCase.expectedError, err) quorum := calculateQuorum(warpConfig.QuorumNumerator) require.Equal(t, testCase.expectedQuorum, quorum) + require.Equal(t, testCase.expectedRequirePrimaryNeworkSigners, warpConfig.RequirePrimaryNetworkSigners) }) } } From 7a8573467197b0973478f3767e343ffdff042a76 Mon Sep 17 00:00:00 2001 From: Ian Suvak Date: Fri, 22 Nov 2024 13:33:55 -0500 Subject: [PATCH 3/4] rename WarpQuorum to WarpConfig and move RequirePrimaryNetworKSigners into it --- relayer/application_relayer.go | 30 +++------ relayer/config/config.go | 40 +++++------- relayer/config/config_test.go | 64 ++++++++----------- relayer/config/destination_blockchain.go | 21 +++--- relayer/main/main.go | 2 +- relayer/network_utils.go | 21 +++--- signature-aggregator/aggregator/aggregator.go | 4 +- utils/utils.go | 13 +--- utils/utils_test.go | 7 -- 9 files changed, 77 insertions(+), 125 deletions(-) diff --git a/relayer/application_relayer.go b/relayer/application_relayer.go index 76e3c6f3..a0aff4a7 100644 --- a/relayer/application_relayer.go +++ b/relayer/application_relayer.go @@ -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 @@ -79,30 +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.", - zap.String("destinationBlockchainID", relayerID.DestinationBlockchainID.String()), - zap.Error(err), - ) - return nil, err - } - requirePrimaryNetworkSigners, err := cfg.GetWarpRequirePrimaryNetworkSigners(relayerID.DestinationBlockchainID) - // this shouldn't be reachable since if we found a quorum, we should also find the requirePrimaryNetworkSigners - // but leaving the check for completeness - if err != nil { - logger.Error( - "Failed to get warp primary network configuration from config.", + "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 && !requirePrimaryNetworkSigners { - // If the message originates from the primary subnet, and the primary network is validated by - // the destination change we can "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. @@ -139,7 +129,7 @@ func NewApplicationRelayer( destinationClient: destinationClient, relayerID: relayerID, signingSubnetID: signingSubnet, - warpQuorum: quorum, + warpConfig: warpConfig, checkpointManager: checkpointManager, sourceWarpSignatureClient: warpClient, signatureAggregator: signatureAggregator, @@ -217,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 { @@ -293,7 +283,7 @@ func (r *ApplicationRelayer) createSignedMessage( &signedWarpMessageBytes, "warp_getMessageAggregateSignature", unsignedMessage.ID(), - r.warpQuorum.QuorumNumerator, + r.warpConfig.QuorumNumerator, r.signingSubnetID.String(), ) if err == nil { diff --git a/relayer/config/config.go b/relayer/config/config.go index 0158e149..b42b174b 100644 --- a/relayer/config/config.go +++ b/relayer/config/config.go @@ -49,7 +49,7 @@ 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") +var errFailedToGetWarpConfig = errors.New("failed to get warp config") // Top-level configuration type Config struct { @@ -155,18 +155,17 @@ func (c *Config) GetSubnetID(blockchainID ids.ID) ids.ID { } // If the numerator in the Warp config is 0, use the default value -func calculateQuorum(cfgNumerator uint64) WarpQuorum { - if cfgNumerator == 0 { - return WarpQuorum{ - QuorumNumerator: warp.WarpDefaultQuorumNumerator, - QuorumDenominator: warp.WarpQuorumDenominator, - } - } else { - return WarpQuorum{ - QuorumNumerator: cfgNumerator, - QuorumDenominator: warp.WarpQuorumDenominator, +func warpConfigFromSubnetWarpConfig(inputConfig warp.Config) WarpConfig { + if inputConfig.QuorumNumerator == 0 { + return WarpConfig{ + QuorumNumerator: warp.WarpDefaultQuorumNumerator, + RequirePrimaryNetworkSigners: inputConfig.RequirePrimaryNetworkSigners, } } + return WarpConfig{ + QuorumNumerator: inputConfig.QuorumNumerator, + RequirePrimaryNetworkSigners: inputConfig.RequirePrimaryNetworkSigners, + } } func getWarpConfig(client ethclient.Client) (*warp.Config, error) { @@ -207,12 +206,12 @@ func getWarpConfig(client ethclient.Client) (*warp.Config, error) { // Initializes Warp configurations (quorum and self-signing settings) for each destination subnet func (c *Config) InitializeWarpConfigs() error { - // Fetch the Warp quorum values for each destination subnet. + // Fetch the Warp config values for each destination subnet. for _, destinationSubnet := range c.DestinationBlockchains { 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, ) @@ -234,22 +233,13 @@ func (c *Config) GetOverwrittenOptions() []string { // Top-level config getters // -func (c *Config) GetWarpQuorum(blockchainID ids.ID) (WarpQuorum, error) { - for _, s := range c.DestinationBlockchains { - if blockchainID.String() == s.BlockchainID { - return s.warpQuorum, nil - } - } - return WarpQuorum{}, errFailedToGetWarpQuorum -} - -func (c *Config) GetWarpRequirePrimaryNetworkSigners(blockchainID ids.ID) (bool, error) { +func (c *Config) GetWarpConfig(blockchainID ids.ID) (WarpConfig, error) { for _, s := range c.DestinationBlockchains { if blockchainID.String() == s.BlockchainID { - return s.warpRequirePrimaryNetworkSigners, nil + return s.warpConfig, nil } } - return false, errFailedToGetWarpQuorum + return WarpConfig{}, errFailedToGetWarpConfig } var _ peers.Config = &Config{} diff --git a/relayer/config/config_test.go b/relayer/config/config_test.go index 18835150..710f1f67 100644 --- a/relayer/config/config_test.go +++ b/relayer/config/config_test.go @@ -249,14 +249,13 @@ func TestGetWarpConfig(t *testing.T) { require.NoError(t, err) testCases := []struct { - name string - blockchainID ids.ID - subnetID ids.ID - chainConfig params.ChainConfigWithUpgradesJSON - getChainConfigCalls int - expectedError error - expectedQuorum WarpQuorum - expectedRequirePrimaryNeworkSigners bool + name string + blockchainID ids.ID + subnetID ids.ID + chainConfig params.ChainConfigWithUpgradesJSON + getChainConfigCalls int + expectedError error + expectedWarpConfig WarpConfig }{ { name: "subnet genesis precompile", @@ -273,11 +272,10 @@ func TestGetWarpConfig(t *testing.T) { }, }, expectedError: nil, - expectedQuorum: WarpQuorum{ - QuorumNumerator: warp.WarpDefaultQuorumNumerator, - QuorumDenominator: warp.WarpQuorumDenominator, + expectedWarpConfig: WarpConfig{ + QuorumNumerator: warp.WarpDefaultQuorumNumerator, + RequirePrimaryNetworkSigners: false, }, - expectedRequirePrimaryNeworkSigners: false, }, { name: "subnet genesis precompile non-default", @@ -294,11 +292,10 @@ func TestGetWarpConfig(t *testing.T) { }, }, expectedError: nil, - expectedQuorum: WarpQuorum{ - QuorumNumerator: 50, - QuorumDenominator: warp.WarpQuorumDenominator, + expectedWarpConfig: WarpConfig{ + QuorumNumerator: 50, + RequirePrimaryNetworkSigners: false, }, - expectedRequirePrimaryNeworkSigners: false, }, { name: "subnet upgrade precompile", @@ -317,11 +314,10 @@ func TestGetWarpConfig(t *testing.T) { }, }, expectedError: nil, - expectedQuorum: WarpQuorum{ - QuorumNumerator: warp.WarpDefaultQuorumNumerator, - QuorumDenominator: warp.WarpQuorumDenominator, + expectedWarpConfig: WarpConfig{ + QuorumNumerator: warp.WarpDefaultQuorumNumerator, + RequirePrimaryNetworkSigners: false, }, - expectedRequirePrimaryNeworkSigners: false, }, { name: "subnet upgrade precompile non-default", @@ -340,11 +336,10 @@ func TestGetWarpConfig(t *testing.T) { }, }, expectedError: nil, - expectedQuorum: WarpQuorum{ - QuorumNumerator: 50, - QuorumDenominator: warp.WarpQuorumDenominator, + expectedWarpConfig: WarpConfig{ + QuorumNumerator: 50, + RequirePrimaryNetworkSigners: false, }, - expectedRequirePrimaryNeworkSigners: false, }, { name: "require primary network signers", @@ -362,11 +357,10 @@ func TestGetWarpConfig(t *testing.T) { }, }, expectedError: nil, - expectedQuorum: WarpQuorum{ - QuorumNumerator: warp.WarpDefaultQuorumNumerator, - QuorumDenominator: warp.WarpQuorumDenominator, + expectedWarpConfig: WarpConfig{ + QuorumNumerator: warp.WarpDefaultQuorumNumerator, + RequirePrimaryNetworkSigners: true, }, - expectedRequirePrimaryNeworkSigners: true, }, { name: "require primary network signers explicit false", @@ -384,11 +378,10 @@ func TestGetWarpConfig(t *testing.T) { }, }, expectedError: nil, - expectedQuorum: WarpQuorum{ - QuorumNumerator: warp.WarpDefaultQuorumNumerator, - QuorumDenominator: warp.WarpQuorumDenominator, + expectedWarpConfig: WarpConfig{ + QuorumNumerator: warp.WarpDefaultQuorumNumerator, + RequirePrimaryNetworkSigners: false, }, - expectedRequirePrimaryNeworkSigners: false, }, } @@ -402,11 +395,10 @@ func TestGetWarpConfig(t *testing.T) { ).Times(testCase.getChainConfigCalls), ) - warpConfig, err := getWarpConfig(client) + subnetWarpConfig, err := getWarpConfig(client) require.Equal(t, testCase.expectedError, err) - quorum := calculateQuorum(warpConfig.QuorumNumerator) - require.Equal(t, testCase.expectedQuorum, quorum) - require.Equal(t, testCase.expectedRequirePrimaryNeworkSigners, warpConfig.RequirePrimaryNetworkSigners) + expectedWarpConfig := warpConfigFromSubnetWarpConfig(*subnetWarpConfig) + require.Equal(t, testCase.expectedWarpConfig, expectedWarpConfig) }) } } diff --git a/relayer/config/destination_blockchain.go b/relayer/config/destination_blockchain.go index 89c3b1b5..044439e1 100644 --- a/relayer/config/destination_blockchain.go +++ b/relayer/config/destination_blockchain.go @@ -25,8 +25,7 @@ type DestinationBlockchain struct { AccountPrivateKey string `mapstructure:"account-private-key" json:"account-private-key"` // Fetched from the chain after startup - warpQuorum WarpQuorum - warpRequirePrimaryNetworkSigners bool + warpConfig WarpConfig // convenience fields to access parsed data after initialization subnetID ids.ID @@ -92,9 +91,8 @@ func (s *DestinationBlockchain) initializeWarpConfigs() error { // 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.warpQuorum = WarpQuorum{ - QuorumNumerator: warp.WarpDefaultQuorumNumerator, - QuorumDenominator: warp.WarpQuorumDenominator, + s.warpConfig = WarpConfig{ + QuorumNumerator: warp.WarpDefaultQuorumNumerator, } return nil } @@ -109,17 +107,16 @@ func (s *DestinationBlockchain) initializeWarpConfigs() error { if err != nil { return fmt.Errorf("failed to dial destination blockchain %s: %w", blockchainID, err) } - warpConfig, err := getWarpConfig(client) + subnetWarpConfig, err := getWarpConfig(client) if err != nil { return fmt.Errorf("failed to fetch warp config for blockchain %s: %w", blockchainID, err) } - s.warpQuorum = calculateQuorum(warpConfig.QuorumNumerator) - s.warpRequirePrimaryNetworkSigners = warpConfig.RequirePrimaryNetworkSigners + 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 } diff --git a/relayer/main/main.go b/relayer/main/main.go index 351d75bf..177bb82e 100644 --- a/relayer/main/main.go +++ b/relayer/main/main.go @@ -78,7 +78,7 @@ func main() { if err != nil { panic(fmt.Errorf("couldn't build config: %w", err)) } - // Initialize the Warp Quorum values by fetching via RPC + // Initialize the Warp Config values by fetching via RPC // We do this here so that BuildConfig doesn't need to make RPC calls if err = cfg.InitializeWarpConfigs(); err != nil { panic(fmt.Errorf("couldn't initialize warp quorums: %w", err)) diff --git a/relayer/network_utils.go b/relayer/network_utils.go index fc1e925a..4cea04d7 100644 --- a/relayer/network_utils.go +++ b/relayer/network_utils.go @@ -69,13 +69,13 @@ func connectToNonPrimaryNetworkPeers( } for _, destination := range sourceBlockchain.SupportedDestinations { blockchainID := destination.GetBlockchainID() - if ok, quorum, err := checkForSufficientConnectedStake(logger, cfg, connectedValidators, blockchainID); !ok { + if ok, warpConfig, err := checkForSufficientConnectedStake(logger, cfg, connectedValidators, blockchainID); !ok { logger.Warn( "Failed to connect to a threshold of stake", zap.String("destinationBlockchainID", blockchainID.String()), zap.Uint64("connectedWeight", connectedValidators.ConnectedWeight), zap.Uint64("totalValidatorWeight", connectedValidators.TotalValidatorWeight), - zap.Any("warpQuorum", quorum), + zap.Any("WarpConfig", warpConfig), ) return err } @@ -104,13 +104,13 @@ func connectToPrimaryNetworkPeers( return err } - if ok, quorum, err := checkForSufficientConnectedStake(logger, cfg, connectedValidators, blockchainID); !ok { + if ok, warpConfig, err := checkForSufficientConnectedStake(logger, cfg, connectedValidators, blockchainID); !ok { logger.Warn( "Failed to connect to a threshold of stake", zap.String("destinationBlockchainID", blockchainID.String()), zap.Uint64("connectedWeight", connectedValidators.ConnectedWeight), zap.Uint64("totalValidatorWeight", connectedValidators.TotalValidatorWeight), - zap.Any("warpQuorum", quorum), + zap.Any("WarpConfig", warpConfig), ) return err } @@ -118,17 +118,17 @@ func connectToPrimaryNetworkPeers( return nil } -// Fetch the warp quorum from the config and check if the connected stake exceeds the threshold +// Fetch the warp config from the destination chain config and check if the connected stake exceeds the threshold func checkForSufficientConnectedStake( logger logging.Logger, cfg *config.Config, connectedValidators *peers.ConnectedCanonicalValidators, destinationBlockchainID ids.ID, -) (bool, *config.WarpQuorum, error) { - quorum, err := cfg.GetWarpQuorum(destinationBlockchainID) +) (bool, *config.WarpConfig, error) { + warpConfig, err := cfg.GetWarpConfig(destinationBlockchainID) if err != nil { logger.Error( - "Failed to get warp quorum from config", + "Failed to get warp config from chain config", zap.String("destinationBlockchainID", destinationBlockchainID.String()), zap.Error(err), ) @@ -137,7 +137,6 @@ func checkForSufficientConnectedStake( return utils.CheckStakeWeightExceedsThreshold( big.NewInt(0).SetUint64(connectedValidators.ConnectedWeight), connectedValidators.TotalValidatorWeight, - quorum.QuorumNumerator, - quorum.QuorumDenominator, - ), &quorum, nil + warpConfig.QuorumNumerator, + ), &warpConfig, nil } diff --git a/signature-aggregator/aggregator/aggregator.go b/signature-aggregator/aggregator/aggregator.go index 7d2b9b01..cd38ca87 100644 --- a/signature-aggregator/aggregator/aggregator.go +++ b/signature-aggregator/aggregator/aggregator.go @@ -136,7 +136,7 @@ func (s *SignatureAggregator) CreateSignedMessage( float64(connectedValidators.TotalValidatorWeight) * 100, ) - if !utils.CheckStakeWeightPercentageExceedsThreshold( + if !utils.CheckStakeWeightExceedsThreshold( big.NewInt(0).SetUint64(connectedValidators.ConnectedWeight), connectedValidators.TotalValidatorWeight, quorumPercentage, @@ -453,7 +453,7 @@ func (s *SignatureAggregator) aggregateIfSufficientWeight( quorumPercentage uint64, ) (*avalancheWarp.Message, error) { // As soon as the signatures exceed the stake weight threshold we try to aggregate and send the transaction. - if !utils.CheckStakeWeightPercentageExceedsThreshold( + if !utils.CheckStakeWeightExceedsThreshold( accumulatedSignatureWeight, connectedValidators.TotalValidatorWeight, quorumPercentage, diff --git a/utils/utils.go b/utils/utils.go index 7aa51fbc..581f92e4 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -13,6 +13,7 @@ import ( "time" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/subnet-evm/precompile/contracts/warp" "github.com/ethereum/go-ethereum/common" ) @@ -40,7 +41,6 @@ func CheckStakeWeightExceedsThreshold( accumulatedSignatureWeight *big.Int, totalWeight uint64, quorumNumerator uint64, - quorumDenominator uint64, ) bool { if accumulatedSignatureWeight == nil { return false @@ -49,20 +49,11 @@ func CheckStakeWeightExceedsThreshold( // Verifies that quorumNum * totalWeight <= quorumDen * sigWeight totalWeightBI := new(big.Int).SetUint64(totalWeight) scaledTotalWeight := new(big.Int).Mul(totalWeightBI, new(big.Int).SetUint64(quorumNumerator)) - scaledSigWeight := new(big.Int).Mul(accumulatedSignatureWeight, new(big.Int).SetUint64(quorumDenominator)) + scaledSigWeight := new(big.Int).Mul(accumulatedSignatureWeight, new(big.Int).SetUint64(warp.WarpQuorumDenominator)) return scaledTotalWeight.Cmp(scaledSigWeight) != 1 } -// Wrapper for CheckStakeWeightExceedThreshold with a quorumDen of 100. -func CheckStakeWeightPercentageExceedsThreshold( - accumulatedSignatureWeight *big.Int, - totalWeight uint64, - stakeWeightPercentage uint64, -) bool { - return CheckStakeWeightExceedsThreshold(accumulatedSignatureWeight, totalWeight, stakeWeightPercentage, 100) -} - // // Chain Utils // diff --git a/utils/utils_test.go b/utils/utils_test.go index 4fa21908..65aed4ad 100644 --- a/utils/utils_test.go +++ b/utils/utils_test.go @@ -79,7 +79,6 @@ func TestCheckStakeWeightExceedsThreshold(t *testing.T) { accumulatedSignatureWeight uint64 totalWeight uint64 quorumNumerator uint64 - quorumDenominator uint64 expectedResult bool }{ { @@ -87,7 +86,6 @@ func TestCheckStakeWeightExceedsThreshold(t *testing.T) { accumulatedSignatureWeight: 0, totalWeight: 0, quorumNumerator: 0, - quorumDenominator: 0, expectedResult: true, }, { @@ -95,7 +93,6 @@ func TestCheckStakeWeightExceedsThreshold(t *testing.T) { accumulatedSignatureWeight: 67_000_000, totalWeight: 100_000_000, quorumNumerator: 67, - quorumDenominator: 100, expectedResult: true, }, { @@ -103,7 +100,6 @@ func TestCheckStakeWeightExceedsThreshold(t *testing.T) { accumulatedSignatureWeight: 66_999_999, totalWeight: 100_000_000, quorumNumerator: 67, - quorumDenominator: 100, expectedResult: false, }, { @@ -111,7 +107,6 @@ func TestCheckStakeWeightExceedsThreshold(t *testing.T) { accumulatedSignatureWeight: 67_000_000, totalWeight: 67_000_000, quorumNumerator: 100, - quorumDenominator: 100, expectedResult: true, }, { @@ -119,7 +114,6 @@ func TestCheckStakeWeightExceedsThreshold(t *testing.T) { accumulatedSignatureWeight: 66_999_999, totalWeight: 67_000_000, quorumNumerator: 100, - quorumDenominator: 100, expectedResult: false, }, } @@ -129,7 +123,6 @@ func TestCheckStakeWeightExceedsThreshold(t *testing.T) { new(big.Int).SetUint64(testCase.accumulatedSignatureWeight), testCase.totalWeight, testCase.quorumNumerator, - testCase.quorumDenominator, ) require.Equal(t, testCase.expectedResult, actualResult) }) From b4c7a099cef32184a1fb47d4b7c954b72b9ae55c Mon Sep 17 00:00:00 2001 From: Ian Suvak Date: Fri, 22 Nov 2024 14:00:11 -0500 Subject: [PATCH 4/4] fix error wording --- relayer/config/config.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/relayer/config/config.go b/relayer/config/config.go index b42b174b..747ceec3 100644 --- a/relayer/config/config.go +++ b/relayer/config/config.go @@ -49,8 +49,6 @@ awm-relayer --version Display awm-relayer vers awm-relayer --help Display awm-relayer usage and exit. ` -var errFailedToGetWarpConfig = errors.New("failed to get warp config") - // Top-level configuration type Config struct { LogLevel string `mapstructure:"log-level" json:"log-level"` @@ -239,7 +237,7 @@ func (c *Config) GetWarpConfig(blockchainID ids.ID) (WarpConfig, error) { return s.warpConfig, nil } } - return WarpConfig{}, errFailedToGetWarpConfig + return WarpConfig{}, fmt.Errorf("blockchain %s not configured as a destination", blockchainID) } var _ peers.Config = &Config{}