diff --git a/network/p2p/gossip/gossip.go b/network/p2p/gossip/gossip.go index c6950f9871f6..66080535b1a4 100644 --- a/network/p2p/gossip/gossip.go +++ b/network/p2p/gossip/gossip.go @@ -21,6 +21,7 @@ import ( "github.com/ava-labs/avalanchego/utils/bloom" "github.com/ava-labs/avalanchego/utils/buffer" "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/avalanchego/utils/set" ) const ( @@ -262,6 +263,7 @@ func (p *PullGossiper[_]) handleResponse( func NewPushGossiper[T Gossipable]( marshaller Marshaller[T], mempool Set[T], + validators p2p.ValidatorPortion, client *p2p.Client, metrics Metrics, gossipParams BranchingFactor, @@ -288,6 +290,7 @@ func NewPushGossiper[T Gossipable]( return &PushGossiper[T]{ marshaller: marshaller, set: mempool, + validators: validators, client: client, metrics: metrics, gossipParams: gossipParams, @@ -306,6 +309,7 @@ func NewPushGossiper[T Gossipable]( type PushGossiper[T Gossipable] struct { marshaller Marshaller[T] set Set[T] + validators p2p.ValidatorPortion client *p2p.Client metrics Metrics @@ -323,9 +327,10 @@ type PushGossiper[T Gossipable] struct { } type BranchingFactor struct { - Validators int - NonValidators int - Peers int + StakePercentage float64 + Validators int + NonValidators int + Peers int } func (b *BranchingFactor) Verify() error { @@ -461,9 +466,11 @@ func (p *PushGossiper[T]) gossip( sentCountMetric.Add(float64(len(gossip))) sentBytesMetric.Add(float64(sentBytes)) + validatorsByStake := p.validators.Top(ctx, gossipParams.StakePercentage) return p.client.AppGossip( ctx, common.SendConfig{ + NodeIDs: set.Of(validatorsByStake...), Validators: gossipParams.Validators, NonValidators: gossipParams.NonValidators, Peers: gossipParams.Peers, diff --git a/network/p2p/gossip/gossip_test.go b/network/p2p/gossip/gossip_test.go index 47a05ceb5330..a1eed80bed3b 100644 --- a/network/p2p/gossip/gossip_test.go +++ b/network/p2p/gossip/gossip_test.go @@ -18,6 +18,8 @@ import ( "github.com/ava-labs/avalanchego/network/p2p" "github.com/ava-labs/avalanchego/proto/pb/sdk" "github.com/ava-labs/avalanchego/snow/engine/common" + "github.com/ava-labs/avalanchego/snow/validators" + "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/utils/units" @@ -359,6 +361,7 @@ func TestPushGossiperNew(t *testing.T) { nil, nil, nil, + nil, Metrics{}, tt.gossipParams, tt.regossipParams, @@ -517,6 +520,20 @@ func TestPushGossiper(t *testing.T) { ) require.NoError(err) client := network.NewClient(0) + validators := p2p.NewValidators( + &p2p.Peers{}, + logging.NoLog{}, + constants.PrimaryNetworkID, + &validators.TestState{ + GetCurrentHeightF: func(context.Context) (uint64, error) { + return 1, nil + }, + GetValidatorSetF: func(context.Context, uint64, ids.ID) (map[ids.NodeID]*validators.GetValidatorOutput, error) { + return nil, nil + }, + }, + time.Hour, + ) metrics, err := NewMetrics(prometheus.NewRegistry(), "") require.NoError(err) marshaller := testMarshaller{} @@ -529,6 +546,7 @@ func TestPushGossiper(t *testing.T) { gossiper, err := NewPushGossiper[*testTx]( marshaller, FullSet[*testTx]{}, + validators, client, metrics, BranchingFactor{ diff --git a/vms/avm/config_test.go b/vms/avm/config_test.go index f372335b80d8..4f04833c77b8 100644 --- a/vms/avm/config_test.go +++ b/vms/avm/config_test.go @@ -40,6 +40,7 @@ func TestParseConfig(t *testing.T) { Network: network.Config{ MaxValidatorSetStaleness: time.Nanosecond, TargetGossipSize: network.DefaultConfig.TargetGossipSize, + PushGossipPercentStake: network.DefaultConfig.PushGossipPercentStake, PushGossipNumValidators: network.DefaultConfig.PushGossipNumValidators, PushGossipNumPeers: network.DefaultConfig.PushGossipNumPeers, PushRegossipNumValidators: network.DefaultConfig.PushRegossipNumValidators, diff --git a/vms/avm/network/config.go b/vms/avm/network/config.go index 8c3975653dfa..797138ab93f9 100644 --- a/vms/avm/network/config.go +++ b/vms/avm/network/config.go @@ -12,6 +12,7 @@ import ( var DefaultConfig = Config{ MaxValidatorSetStaleness: time.Minute, TargetGossipSize: 20 * units.KiB, + PushGossipPercentStake: .9, PushGossipNumValidators: 100, PushGossipNumPeers: 0, PushRegossipNumValidators: 10, @@ -36,6 +37,11 @@ type Config struct { // sent when pushing transactions and when responded to transaction pull // requests. TargetGossipSize int `json:"target-gossip-size"` + // PushGossipPercentStake is the percentage of total stake to push + // transactions to in the first round of gossip. Nodes with higher stake are + // preferred over nodes with less stake to minimize the number of messages + // sent over the p2p network. + PushGossipPercentStake float64 `json:"push-gossip-percent-stake"` // PushGossipNumValidators is the number of validators to push transactions // to in the first round of gossip. PushGossipNumValidators int `json:"push-gossip-num-validators"` diff --git a/vms/avm/network/network.go b/vms/avm/network/network.go index 5cc17b03cec0..7673334f84ea 100644 --- a/vms/avm/network/network.go +++ b/vms/avm/network/network.go @@ -92,11 +92,13 @@ func New( txPushGossiper, err := gossip.NewPushGossiper[*txs.Tx]( marshaller, gossipMempool, + validators, txGossipClient, txGossipMetrics, gossip.BranchingFactor{ - Validators: config.PushGossipNumValidators, - Peers: config.PushGossipNumPeers, + StakePercentage: config.PushGossipPercentStake, + Validators: config.PushGossipNumValidators, + Peers: config.PushGossipNumPeers, }, gossip.BranchingFactor{ Validators: config.PushRegossipNumValidators, diff --git a/vms/avm/network/network_test.go b/vms/avm/network/network_test.go index f107b8b389cb..53256888ef4e 100644 --- a/vms/avm/network/network_test.go +++ b/vms/avm/network/network_test.go @@ -16,6 +16,7 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/engine/common" + "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/vms/avm/block/executor" "github.com/ava-labs/avalanchego/vms/avm/fxs" @@ -353,6 +354,14 @@ func TestNetworkIssueTxFromRPC(t *testing.T) { n, err := New( &snow.Context{ Log: logging.NoLog{}, + ValidatorState: &validators.TestState{ + GetCurrentHeightF: func(context.Context) (uint64, error) { + return 0, nil + }, + GetValidatorSetF: func(context.Context, uint64, ids.ID) (map[ids.NodeID]*validators.GetValidatorOutput, error) { + return nil, nil + }, + }, }, parser, txVerifierFunc(ctrl), @@ -440,6 +449,14 @@ func TestNetworkIssueTxFromRPCWithoutVerification(t *testing.T) { n, err := New( &snow.Context{ Log: logging.NoLog{}, + ValidatorState: &validators.TestState{ + GetCurrentHeightF: func(context.Context) (uint64, error) { + return 0, nil + }, + GetValidatorSetF: func(context.Context, uint64, ids.ID) (map[ids.NodeID]*validators.GetValidatorOutput, error) { + return nil, nil + }, + }, }, parser, executor.NewMockManager(ctrl), // Should never verify a tx diff --git a/vms/platformvm/config/execution_config_test.go b/vms/platformvm/config/execution_config_test.go index 66b43e800198..4c4f4ba9dc96 100644 --- a/vms/platformvm/config/execution_config_test.go +++ b/vms/platformvm/config/execution_config_test.go @@ -45,20 +45,21 @@ func TestExecutionConfigUnmarshal(t *testing.T) { "network": { "max-validator-set-staleness": 1, "target-gossip-size": 2, - "push-gossip-num-validators": 3, - "push-gossip-num-peers": 4, - "push-regossip-num-validators": 5, - "push-regossip-num-peers": 6, - "push-gossip-discarded-cache-size": 7, - "push-gossip-max-regossip-frequency": 8, - "push-gossip-frequency": 9, - "pull-gossip-poll-size": 10, - "pull-gossip-frequency": 11, - "pull-gossip-throttling-period": 12, - "pull-gossip-throttling-limit": 13, - "expected-bloom-filter-elements": 14, - "expected-bloom-filter-false-positive-probability": 15, - "max-bloom-filter-false-positive-probability": 16 + "push-gossip-percent-stake": 0.3, + "push-gossip-num-validators": 4, + "push-gossip-num-peers": 5, + "push-regossip-num-validators": 6, + "push-regossip-num-peers": 7, + "push-gossip-discarded-cache-size": 8, + "push-gossip-max-regossip-frequency": 9, + "push-gossip-frequency": 10, + "pull-gossip-poll-size": 11, + "pull-gossip-frequency": 12, + "pull-gossip-throttling-period": 13, + "pull-gossip-throttling-limit": 14, + "expected-bloom-filter-elements": 15, + "expected-bloom-filter-false-positive-probability": 16, + "max-bloom-filter-false-positive-probability": 17 }, "block-cache-size": 1, "tx-cache-size": 2, @@ -77,20 +78,21 @@ func TestExecutionConfigUnmarshal(t *testing.T) { Network: network.Config{ MaxValidatorSetStaleness: 1, TargetGossipSize: 2, - PushGossipNumValidators: 3, - PushGossipNumPeers: 4, - PushRegossipNumValidators: 5, - PushRegossipNumPeers: 6, - PushGossipDiscardedCacheSize: 7, - PushGossipMaxRegossipFrequency: 8, - PushGossipFrequency: 9, - PullGossipPollSize: 10, - PullGossipFrequency: 11, - PullGossipThrottlingPeriod: 12, - PullGossipThrottlingLimit: 13, - ExpectedBloomFilterElements: 14, - ExpectedBloomFilterFalsePositiveProbability: 15, - MaxBloomFilterFalsePositiveProbability: 16, + PushGossipPercentStake: .3, + PushGossipNumValidators: 4, + PushGossipNumPeers: 5, + PushRegossipNumValidators: 6, + PushRegossipNumPeers: 7, + PushGossipDiscardedCacheSize: 8, + PushGossipMaxRegossipFrequency: 9, + PushGossipFrequency: 10, + PullGossipPollSize: 11, + PullGossipFrequency: 12, + PullGossipThrottlingPeriod: 13, + PullGossipThrottlingLimit: 14, + ExpectedBloomFilterElements: 15, + ExpectedBloomFilterFalsePositiveProbability: 16, + MaxBloomFilterFalsePositiveProbability: 17, }, BlockCacheSize: 1, TxCacheSize: 2, @@ -134,6 +136,7 @@ func TestExecutionConfigUnmarshal(t *testing.T) { Network: network.Config{ MaxValidatorSetStaleness: 1, TargetGossipSize: 2, + PushGossipPercentStake: DefaultExecutionConfig.Network.PushGossipPercentStake, PushGossipNumValidators: DefaultExecutionConfig.Network.PushGossipNumValidators, PushGossipNumPeers: DefaultExecutionConfig.Network.PushGossipNumPeers, PushRegossipNumValidators: DefaultExecutionConfig.Network.PushRegossipNumValidators, diff --git a/vms/platformvm/network/config.go b/vms/platformvm/network/config.go index 8c3975653dfa..797138ab93f9 100644 --- a/vms/platformvm/network/config.go +++ b/vms/platformvm/network/config.go @@ -12,6 +12,7 @@ import ( var DefaultConfig = Config{ MaxValidatorSetStaleness: time.Minute, TargetGossipSize: 20 * units.KiB, + PushGossipPercentStake: .9, PushGossipNumValidators: 100, PushGossipNumPeers: 0, PushRegossipNumValidators: 10, @@ -36,6 +37,11 @@ type Config struct { // sent when pushing transactions and when responded to transaction pull // requests. TargetGossipSize int `json:"target-gossip-size"` + // PushGossipPercentStake is the percentage of total stake to push + // transactions to in the first round of gossip. Nodes with higher stake are + // preferred over nodes with less stake to minimize the number of messages + // sent over the p2p network. + PushGossipPercentStake float64 `json:"push-gossip-percent-stake"` // PushGossipNumValidators is the number of validators to push transactions // to in the first round of gossip. PushGossipNumValidators int `json:"push-gossip-num-validators"` diff --git a/vms/platformvm/network/network.go b/vms/platformvm/network/network.go index 0c78f9a84081..3d92cb0c98a3 100644 --- a/vms/platformvm/network/network.go +++ b/vms/platformvm/network/network.go @@ -91,11 +91,13 @@ func New( txPushGossiper, err := gossip.NewPushGossiper[*txs.Tx]( marshaller, gossipMempool, + validators, txGossipClient, txGossipMetrics, gossip.BranchingFactor{ - Validators: config.PushGossipNumValidators, - Peers: config.PushGossipNumPeers, + StakePercentage: config.PushGossipPercentStake, + Validators: config.PushGossipNumValidators, + Peers: config.PushGossipNumPeers, }, gossip.BranchingFactor{ Validators: config.PushRegossipNumValidators,