code.vegaprotocol.io/vega@v0.79.0/core/integration/stubs/topology_stub.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package stubs
    17  
    18  import (
    19  	"context"
    20  	"sort"
    21  
    22  	"code.vegaprotocol.io/vega/core/events"
    23  	"code.vegaprotocol.io/vega/core/types"
    24  	"code.vegaprotocol.io/vega/core/validators"
    25  	"code.vegaprotocol.io/vega/libs/num"
    26  )
    27  
    28  type TopologyStub struct {
    29  	validators    map[string]string
    30  	nodeID        string
    31  	broker        *BrokerStub
    32  	minDelegation num.Decimal
    33  }
    34  
    35  func NewTopologyStub(nodeID string, broker *BrokerStub) *TopologyStub {
    36  	return &TopologyStub{
    37  		validators: map[string]string{},
    38  		nodeID:     nodeID,
    39  		broker:     broker,
    40  	}
    41  }
    42  
    43  func (ts *TopologyStub) OnMinDelegationUpdated(_ context.Context, minDelegation num.Decimal) error {
    44  	ts.minDelegation = minDelegation
    45  	return nil
    46  }
    47  
    48  func (ts *TopologyStub) Len() int {
    49  	return len(ts.validators)
    50  }
    51  
    52  func (ts *TopologyStub) ValidatorPerformanceScore(nodeID string) num.Decimal {
    53  	return num.DecimalFromFloat(1)
    54  }
    55  
    56  func (ts *TopologyStub) SelfNodeID() string {
    57  	return ts.nodeID
    58  }
    59  
    60  func (ts *TopologyStub) SelfVegaPubKey() string {
    61  	return ts.nodeID
    62  }
    63  
    64  func (ts *TopologyStub) IsValidator() bool {
    65  	return true
    66  }
    67  
    68  func (ts *TopologyStub) IsValidatorVegaPubKey(pubKey string) bool {
    69  	return true
    70  }
    71  
    72  func (ts *TopologyStub) IsTendermintValidator(pubKey string) bool {
    73  	return true
    74  }
    75  
    76  func (ts *TopologyStub) IsValidatorNodeID(nodeID string) bool {
    77  	_, ok := ts.validators[nodeID]
    78  	return ok
    79  }
    80  
    81  func (ts *TopologyStub) RecalcValidatorSet(ctx context.Context, epochSeq string, delegationState []*types.ValidatorData, stakeScoreParams types.StakeScoreParams) []*types.PartyContributionScore {
    82  	return []*types.PartyContributionScore{}
    83  }
    84  
    85  func (ts *TopologyStub) AllNodeIDs() []string {
    86  	nodes := make([]string, 0, len(ts.validators))
    87  	for n := range ts.validators {
    88  		nodes = append(nodes, n)
    89  	}
    90  	sort.Strings(nodes)
    91  	return nodes
    92  }
    93  
    94  func (ts *TopologyStub) AllVegaPubKeys() []string {
    95  	nodes := make([]string, 0, len(ts.validators))
    96  	for _, pk := range ts.validators {
    97  		nodes = append(nodes, pk)
    98  	}
    99  	sort.Strings(nodes)
   100  	return nodes
   101  }
   102  
   103  func (ts *TopologyStub) Get(key string) *validators.ValidatorData {
   104  	if data, ok := ts.validators[key]; ok {
   105  		return &validators.ValidatorData{
   106  			ID:         key,
   107  			VegaPubKey: data,
   108  		}
   109  	}
   110  
   111  	return nil
   112  }
   113  
   114  func (ts *TopologyStub) AddValidator(node string, pubkey string) {
   115  	ts.validators[node] = pubkey
   116  }
   117  
   118  func (ts *TopologyStub) GetRewardsScores(ctx context.Context, epochSeq string, delegationState []*types.ValidatorData, stakeScoreParams types.StakeScoreParams) (*types.ScoreData, *types.ScoreData) {
   119  	tmScores := ts.calculateTMScores(delegationState, stakeScoreParams)
   120  	evts := make([]events.Event, 0, len(tmScores.NodeIDSlice))
   121  	for _, nodeID := range tmScores.NodeIDSlice {
   122  		evts = append(evts, events.NewValidatorScore(ctx, nodeID, epochSeq, tmScores.ValScores[nodeID], tmScores.NormalisedScores[nodeID], tmScores.RawValScores[nodeID], tmScores.PerformanceScores[nodeID], tmScores.MultisigScores[nodeID], "tendermint"))
   123  	}
   124  
   125  	ts.broker.SendBatch(evts)
   126  
   127  	return tmScores, &types.ScoreData{}
   128  }
   129  
   130  // calculateTMScores returns the reward validator scores for the tendermint validatore.
   131  func (ts *TopologyStub) calculateTMScores(delegationState []*types.ValidatorData, stakeScoreParams types.StakeScoreParams) *types.ScoreData {
   132  	tmScores := &types.ScoreData{}
   133  	validatorSet := make(map[string]struct{}, len(delegationState))
   134  	tmScores.PerformanceScores = make(map[string]num.Decimal, len(delegationState))
   135  	for _, ds := range delegationState {
   136  		validatorSet[ds.NodeID] = struct{}{}
   137  		if ds.SelfStake.ToDecimal().GreaterThanOrEqual(ts.minDelegation) {
   138  			tmScores.PerformanceScores[ds.NodeID] = num.DecimalFromFloat(1)
   139  		} else {
   140  			tmScores.PerformanceScores[ds.NodeID] = num.DecimalZero()
   141  		}
   142  	}
   143  
   144  	tmDelegation, tmTotalDelegation := validators.CalcDelegation(validatorSet, delegationState)
   145  	optStake := validators.GetOptimalStake(tmTotalDelegation, len(tmDelegation), stakeScoreParams)
   146  	tv := validators.CalcAntiWhalingScore(tmDelegation, tmTotalDelegation, optStake, stakeScoreParams)
   147  
   148  	tmScores.RawValScores = tv
   149  	tmScores.ValScores = make(map[string]num.Decimal, len(tv))
   150  	for k, d := range tv {
   151  		tmScores.ValScores[k] = d.Mul(tmScores.PerformanceScores[k])
   152  	}
   153  
   154  	// normalise the scores
   155  	tmScores.NormalisedScores = ts.normaliseScores(tmScores.ValScores)
   156  
   157  	// sort the list of tm validators
   158  	tmNodeIDs := make([]string, 0, len(tv))
   159  	for k := range tv {
   160  		tmNodeIDs = append(tmNodeIDs, k)
   161  	}
   162  
   163  	sort.Strings(tmNodeIDs)
   164  	tmScores.NodeIDSlice = tmNodeIDs
   165  	return tmScores
   166  }
   167  
   168  func (ts *TopologyStub) normaliseScores(scores map[string]num.Decimal) map[string]num.Decimal {
   169  	totalScore := num.DecimalZero()
   170  	for _, v := range scores {
   171  		totalScore = totalScore.Add(v)
   172  	}
   173  
   174  	normScores := make(map[string]num.Decimal, len(scores))
   175  	for n, s := range scores {
   176  		if totalScore.IsPositive() {
   177  			normScores[n] = s.Div(totalScore)
   178  		} else {
   179  			normScores[n] = num.DecimalZero()
   180  		}
   181  	}
   182  	return normScores
   183  }
   184  
   185  func (*TopologyStub) GetVotingPower(pubkey string) int64 {
   186  	return 1
   187  }
   188  
   189  func (*TopologyStub) GetTotalVotingPower() int64 {
   190  	return 1
   191  }