code.vegaprotocol.io/vega@v0.79.0/core/rewards/staking_reward_calculator_test.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 rewards
    17  
    18  import (
    19  	"math/rand"
    20  	"testing"
    21  	"time"
    22  
    23  	bmocks "code.vegaprotocol.io/vega/core/broker/mocks"
    24  	"code.vegaprotocol.io/vega/core/types"
    25  	vmock "code.vegaprotocol.io/vega/core/validators/mocks"
    26  	"code.vegaprotocol.io/vega/libs/num"
    27  	"code.vegaprotocol.io/vega/logging"
    28  
    29  	"github.com/golang/mock/gomock"
    30  	"github.com/stretchr/testify/require"
    31  )
    32  
    33  var rng *rand.Rand
    34  
    35  func init() {
    36  	rng = rand.New(rand.NewSource(time.Now().Unix()))
    37  }
    38  
    39  func TestStakingRewards(t *testing.T) {
    40  	t.Run("Calculate the reward when the balance of the reward account is 0", testCalcRewardNoBalance)
    41  	t.Run("Calculate the reward when the validator scores are 0", testCalcRewardsZeroScores)
    42  	t.Run("Reward is calculated correctly when max reward per participant is zero (i.e. unrestricted)", testCalcRewardsNoMaxPayout)
    43  	t.Run("Reward is calculated correctly when max reward per participant restricted but not breached", testCalcRewardsMaxPayoutNotBreached)
    44  	t.Run("Reward is calculated correctly when max reward per participant restricted and breached - no participant can be topped up", testCalcRewardSmallMaxPayoutBreached)
    45  	t.Run("Reward is calculated correctly when max reward per participant restricted and breached - participant can be topped up", testCalcRewardsMaxPayoutBreachedPartyCanTakeMore)
    46  	t.Run("Stop distributing leftover to delegation when remaining is less than 0.1% of max per participant", testEarlyStopCalcRewardsMaxPayoutBreachedPartyCanTakeMore)
    47  }
    48  
    49  func testCalcRewardNoBalance(t *testing.T) {
    50  	delegatorShare, _ := num.DecimalFromString("0.3")
    51  	res := calculateRewardsByStake("1", "asset", "rewardsAccountID", num.UintZero(), map[string]num.Decimal{}, []*types.ValidatorData{}, delegatorShare, num.UintZero(), logging.NewTestLogger())
    52  	require.Equal(t, num.UintZero(), res.totalReward)
    53  	require.Equal(t, 0, len(res.partyToAmount))
    54  }
    55  
    56  func testCalcRewardsZeroScores(t *testing.T) {
    57  	delegatorShare, _ := num.DecimalFromString("0.3")
    58  	scores := map[string]num.Decimal{}
    59  	scores["node1"] = num.DecimalZero()
    60  	scores["node2"] = num.DecimalZero()
    61  	scores["node3"] = num.DecimalZero()
    62  	scores["node4"] = num.DecimalZero()
    63  
    64  	res := calculateRewardsByStake("1", "asset", "rewardsAccountID", num.NewUint(100000), scores, []*types.ValidatorData{}, delegatorShare, num.UintZero(), logging.NewTestLogger())
    65  	require.Equal(t, num.UintZero(), res.totalReward)
    66  	require.Equal(t, 0, len(res.partyToAmount))
    67  }
    68  
    69  func TestFilterZeros(t *testing.T) {
    70  	delegatorShare, _ := num.DecimalFromString("0.3")
    71  	scores := map[string]num.Decimal{}
    72  	scores["node1"] = num.NewDecimalFromFloat(1)
    73  	scores["node2"] = num.DecimalZero()
    74  	scores["node3"] = num.DecimalZero()
    75  	scores["node4"] = num.DecimalZero()
    76  
    77  	res := calculateRewardsByStake("1", "asset", "rewardsAccountID", num.NewUint(100000), scores, []*types.ValidatorData{{NodeID: "node1", PubKey: "node1", StakeByDelegators: num.NewUint(500), SelfStake: num.NewUint(1000), Delegators: map[string]*num.Uint{"zohar": num.UintZero(), "jeremy": num.NewUint(500)}}}, delegatorShare, num.UintZero(), logging.NewTestLogger())
    78  	require.Equal(t, num.NewUint(100000), res.totalReward)
    79  	require.Equal(t, 2, len(res.partyToAmount))
    80  	_, ok := res.partyToAmount["zohar"]
    81  	require.False(t, ok)
    82  
    83  	_, ok = res.partyToAmount["jeremy"]
    84  	require.True(t, ok)
    85  
    86  	_, ok = res.partyToAmount["node1"]
    87  	require.True(t, ok)
    88  }
    89  
    90  // nolint
    91  func testCalcRewardsMaxPayoutRepsected(t *testing.T, maxPayout *num.Uint) {
    92  	delegatorShare, _ := num.DecimalFromString("0.3")
    93  	ctrl := gomock.NewController(t)
    94  	broker := bmocks.NewMockBroker(ctrl)
    95  	broker.EXPECT().SendBatch(gomock.Any()).AnyTimes()
    96  	valPerformance := vmock.NewMockValidatorPerformance(ctrl)
    97  	valPerformance.EXPECT().ValidatorPerformanceScore(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(num.DecimalFromFloat(1)).AnyTimes()
    98  
    99  	delegatorForVal1 := map[string]*num.Uint{}
   100  	delegatorForVal1["party1"] = num.NewUint(6000)
   101  	delegatorForVal1["party2"] = num.NewUint(4000)
   102  	validator1 := &types.ValidatorData{
   103  		NodeID:            "node1",
   104  		PubKey:            "node1",
   105  		SelfStake:         num.UintZero(),
   106  		StakeByDelegators: num.NewUint(10000),
   107  		Delegators:        delegatorForVal1,
   108  	}
   109  	validator2 := &types.ValidatorData{
   110  		NodeID:            "node2",
   111  		PubKey:            "node2",
   112  		SelfStake:         num.NewUint(20000),
   113  		StakeByDelegators: num.UintZero(),
   114  		Delegators:        map[string]*num.Uint{},
   115  	}
   116  
   117  	delegatorForVal3 := map[string]*num.Uint{}
   118  	delegatorForVal3["party1"] = num.NewUint(40000)
   119  	validator3 := &types.ValidatorData{
   120  		NodeID:            "node3",
   121  		PubKey:            "node3",
   122  		SelfStake:         num.NewUint(30000),
   123  		StakeByDelegators: num.NewUint(40000),
   124  		Delegators:        delegatorForVal3,
   125  	}
   126  
   127  	validator4 := &types.ValidatorData{
   128  		NodeID:            "node4",
   129  		PubKey:            "node4",
   130  		SelfStake:         num.UintZero(),
   131  		StakeByDelegators: num.UintZero(),
   132  		Delegators:        map[string]*num.Uint{},
   133  	}
   134  
   135  	validatorData := []*types.ValidatorData{validator1, validator2, validator3, validator4}
   136  	valScores := map[string]num.Decimal{"node1": num.DecimalFromFloat(0.25), "node2": num.DecimalFromFloat(0.5), "node3": num.DecimalFromFloat(0.25), "node4": num.DecimalZero()}
   137  	res := calculateRewardsByStake("1", "asset", "rewardsAccountID", num.NewUint(1000000), valScores, validatorData, delegatorShare, maxPayout, logging.NewTestLogger())
   138  
   139  	// the normalised scores are as follows (from the test above)
   140  	// node1 - 0.25
   141  	// node2 - 0.5
   142  	// node3 - 0.25
   143  	// node4 - 0
   144  	// as node3 and node4 has 0 score they get nothing.
   145  	// given a reward of 1000000,
   146  	//
   147  	// node1 and its delegators get 250,000
   148  	// node2 and its delegators get 500,000
   149  	// node3 and its delegators get 250,000
   150  	// with a delegator share of 0.3,
   151  	// delegators to node1 get 0.3 * 250000 = 75000
   152  	// party1 gets 0.6 * 75000 = 45000
   153  	// party2 gets 0.4 * 75000 = 30000
   154  	// node1 gets 175000
   155  	// node2 gets 1 * 500000 = 500000
   156  	// delegators to node3 get 0.3 * 4/7 * 250000 = 68571
   157  	// party1 gets 42857
   158  	// node3 gets 1 - (0.3*4/7) = 207142
   159  
   160  	// node1, node2, node3, party1, party2
   161  	require.Equal(t, 5, len(res.partyToAmount))
   162  
   163  	require.Equal(t, num.NewUint(87857), res.partyToAmount["party1"])
   164  	require.Equal(t, num.NewUint(30000), res.partyToAmount["party2"])
   165  	require.Equal(t, num.NewUint(175000), res.partyToAmount["node1"])
   166  	require.Equal(t, num.NewUint(500000), res.partyToAmount["node2"])
   167  	require.Equal(t, num.NewUint(207142), res.partyToAmount["node3"])
   168  
   169  	require.Equal(t, num.NewUint(999999), res.totalReward)
   170  }
   171  
   172  func testCalcRewardsNoMaxPayout(t *testing.T) {
   173  	testCalcRewardsMaxPayoutRepsected(t, num.UintZero())
   174  }
   175  
   176  func testCalcRewardsMaxPayoutNotBreached(t *testing.T) {
   177  	testCalcRewardsMaxPayoutRepsected(t, num.NewUint(1000000))
   178  }
   179  
   180  func testCalcRewardSmallMaxPayoutBreached(t *testing.T) {
   181  	delegatorShare, _ := num.DecimalFromString("0.3")
   182  	delegatorForVal1 := map[string]*num.Uint{}
   183  	delegatorForVal1["party1"] = num.NewUint(6000)
   184  	delegatorForVal1["party2"] = num.NewUint(4000)
   185  	validator1 := &types.ValidatorData{
   186  		NodeID:            "node1",
   187  		PubKey:            "node1",
   188  		SelfStake:         num.UintZero(),
   189  		StakeByDelegators: num.NewUint(10000),
   190  		Delegators:        delegatorForVal1,
   191  	}
   192  	validator2 := &types.ValidatorData{
   193  		NodeID:            "node2",
   194  		PubKey:            "node2",
   195  		SelfStake:         num.NewUint(20000),
   196  		StakeByDelegators: num.UintZero(),
   197  		Delegators:        map[string]*num.Uint{},
   198  	}
   199  
   200  	delegatorForVal3 := map[string]*num.Uint{}
   201  	delegatorForVal3["party1"] = num.NewUint(40000)
   202  	validator3 := &types.ValidatorData{
   203  		NodeID:            "node3",
   204  		PubKey:            "node3",
   205  		SelfStake:         num.NewUint(30000),
   206  		StakeByDelegators: num.NewUint(40000),
   207  		Delegators:        delegatorForVal3,
   208  	}
   209  
   210  	validator4 := &types.ValidatorData{
   211  		NodeID:            "node4",
   212  		PubKey:            "node4",
   213  		SelfStake:         num.UintZero(),
   214  		StakeByDelegators: num.UintZero(),
   215  		Delegators:        map[string]*num.Uint{},
   216  	}
   217  
   218  	ctrl := gomock.NewController(t)
   219  	broker := bmocks.NewMockBroker(ctrl)
   220  	broker.EXPECT().SendBatch(gomock.Any()).AnyTimes()
   221  	valPerformance := vmock.NewMockValidatorPerformance(ctrl)
   222  	valPerformance.EXPECT().ValidatorPerformanceScore(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(num.DecimalFromFloat(1)).AnyTimes()
   223  
   224  	validatorData := []*types.ValidatorData{validator1, validator2, validator3, validator4}
   225  	valScores := map[string]num.Decimal{"node1": num.DecimalFromFloat(0.2), "node2": num.DecimalFromFloat(0.4), "node3": num.DecimalFromFloat(0.4), "node4": num.DecimalZero()}
   226  	res := calculateRewardsByStake("1", "asset", "rewardsAccountID", num.NewUint(1000000), valScores, validatorData, delegatorShare, num.NewUint(20000), logging.NewTestLogger())
   227  
   228  	// the normalised scores are as follows (from the test above)
   229  	// node1 - 0.2
   230  	// node2 - 0.4
   231  	// node3 - 0.4
   232  	// node4 - 0
   233  	// as node3 and node4 has 0 score they get nothing.
   234  	// given a reward of 1000000,
   235  	//
   236  	// node1 and its delegators get 200,000
   237  	// node2 and its delegators get 400,000
   238  	// node3 and its delegators get 400,000
   239  	// with a delegator share of 0.3,
   240  	// delegators to node1 get 0.3 * 200000 = 60000
   241  	// party1 gets 0.6 * 60000 = 36000 -> 20000
   242  	// party2 gets 0.4 * 60000 = 24000 -> 20000
   243  	// node1 gets 140000 -> -> 20000
   244  	// node2 gets 1 * 400000 = 400000 -> -> 20000
   245  	// delegators to node3 get 0.3 * 4/7 * 400000 = 68571
   246  	// party1 gets 68571 -> -> 20000
   247  	// node3 gets 1 - (0.3*4/7) = 331428 -> -> 20000
   248  
   249  	// node1, node2, node3, party1, party2
   250  	require.Equal(t, 5, len(res.partyToAmount))
   251  
   252  	require.Equal(t, num.NewUint(20000), res.partyToAmount["party1"])
   253  	require.Equal(t, num.NewUint(20000), res.partyToAmount["party2"])
   254  	require.Equal(t, num.NewUint(20000), res.partyToAmount["node1"])
   255  	require.Equal(t, num.NewUint(20000), res.partyToAmount["node2"])
   256  	require.Equal(t, num.NewUint(20000), res.partyToAmount["node3"])
   257  	require.Equal(t, num.NewUint(100000), res.totalReward)
   258  }
   259  
   260  func testCalcRewardsMaxPayoutBreachedPartyCanTakeMore(t *testing.T) {
   261  	delegatorShare, _ := num.DecimalFromString("0.3")
   262  	delegatorForVal1 := map[string]*num.Uint{}
   263  	delegatorForVal1["party1"] = num.NewUint(6000)
   264  	delegatorForVal1["party2"] = num.NewUint(4000)
   265  	validator1 := &types.ValidatorData{
   266  		NodeID:            "node1",
   267  		PubKey:            "node1",
   268  		SelfStake:         num.UintZero(),
   269  		StakeByDelegators: num.NewUint(10000),
   270  		Delegators:        delegatorForVal1,
   271  	}
   272  	validator2 := &types.ValidatorData{
   273  		NodeID:            "node2",
   274  		PubKey:            "node2",
   275  		SelfStake:         num.NewUint(20000),
   276  		StakeByDelegators: num.UintZero(),
   277  		Delegators:        map[string]*num.Uint{},
   278  	}
   279  
   280  	delegatorForVal3 := map[string]*num.Uint{}
   281  	delegatorForVal3["party1"] = num.NewUint(40000)
   282  	validator3 := &types.ValidatorData{
   283  		NodeID:            "node3",
   284  		PubKey:            "node3",
   285  		SelfStake:         num.NewUint(30000),
   286  		StakeByDelegators: num.NewUint(40000),
   287  		Delegators:        delegatorForVal3,
   288  	}
   289  
   290  	validator4 := &types.ValidatorData{
   291  		NodeID:            "node4",
   292  		PubKey:            "node4",
   293  		SelfStake:         num.UintZero(),
   294  		StakeByDelegators: num.UintZero(),
   295  		Delegators:        map[string]*num.Uint{},
   296  	}
   297  
   298  	ctrl := gomock.NewController(t)
   299  	broker := bmocks.NewMockBroker(ctrl)
   300  	broker.EXPECT().SendBatch(gomock.Any()).AnyTimes()
   301  	valPerformance := vmock.NewMockValidatorPerformance(ctrl)
   302  	valPerformance.EXPECT().ValidatorPerformanceScore(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(num.DecimalFromFloat(1)).AnyTimes()
   303  
   304  	validatorData := []*types.ValidatorData{validator1, validator2, validator3, validator4}
   305  
   306  	valScores := map[string]num.Decimal{"node1": num.DecimalFromFloat(0.25), "node2": num.DecimalFromFloat(0.5), "node3": num.DecimalFromFloat(0.25), "node4": num.DecimalZero()}
   307  	res := calculateRewardsByStake("1", "asset", "rewardsAccountID", num.NewUint(1000000), valScores, validatorData, delegatorShare, num.NewUint(40000), logging.NewTestLogger())
   308  
   309  	// the normalised scores are as follows (from the test above)
   310  	// node1 - 0.25
   311  	// node2 - 0.5
   312  	// node3 - 0.25
   313  	// node4 - 0
   314  	// as node3 and node4 has 0 score they get nothing.
   315  	// given a reward of 1000000,
   316  	//
   317  	// node1 and its delegators get 250,000
   318  	// node2 and its delegators get 500,000
   319  	// node3 and its delegators get 250,000
   320  	// with a delegator share of 0.3,
   321  	// delegators to node1 get 0.3 * 250000 = 75000
   322  	// party1 gets 0.6 * 75000 = 45000 -> 40000
   323  	// party2 gets 0.4 * 75000 = 30000 -> party can take 5k more from what's left =>
   324  	// when distributing the 5k leftover:
   325  	// iteration 0: party2 gets 0.4 * 75000 = 30000 = 2000
   326  	// iteration 1: party2 gets 0.4*5000 = 2000
   327  	// iteration 2: party2 gets 0.4*3000 = 1200
   328  	// iteration 3: party2 gets 0.4*1800 = 720
   329  	// iteration 4: party2 gets 0.4*1080 = 432
   330  	// iteration 5: party2 gets 0.4*648 = 259
   331  	// iteration 6: party2 gets 0.4*388 = 155
   332  	// iteration 7: party2 gets 0.4*233 = 93
   333  	// iteration 8: party2 gets 0.4*140 = 56
   334  	// iteration 9: party2 gets 0.4*84 = 34
   335  	// this runs for 10 iteration and stops therefore:
   336  	// and party 2 gets: 30000 + 2000 + 1200 + 720 +432 + 259 + 155 + 93 + 56 + 34 = 34949
   337  	// node1 gets 175000 -> 40000
   338  	// node2 gets 1 * 500000 = 500000 -> 40000
   339  	// delegators to node3 get 0.3 * 4/7 * 250000 = 42857
   340  	// party1 gets 42857 -> 40000
   341  	// node3 gets 1 - (0.3*4/7) = 207142 -> 40000
   342  	// node1, node2, party1, party2
   343  	require.Equal(t, 5, len(res.partyToAmount))
   344  
   345  	require.Equal(t, num.NewUint(40000), res.partyToAmount["party1"])
   346  	require.Equal(t, num.NewUint(34949), res.partyToAmount["party2"])
   347  	require.Equal(t, num.NewUint(40000), res.partyToAmount["node1"])
   348  	require.Equal(t, num.NewUint(40000), res.partyToAmount["node2"])
   349  	require.Equal(t, num.NewUint(40000), res.partyToAmount["node3"])
   350  	require.Equal(t, num.NewUint(194949), res.totalReward)
   351  }
   352  
   353  func testEarlyStopCalcRewardsMaxPayoutBreachedPartyCanTakeMore(t *testing.T) {
   354  	delegatorShare, _ := num.DecimalFromString("0.3")
   355  	delegatorForVal1 := map[string]*num.Uint{}
   356  	delegatorForVal1["party1"] = num.NewUint(6000)
   357  	delegatorForVal1["party2"] = num.NewUint(4000)
   358  	validator1 := &types.ValidatorData{
   359  		NodeID:            "node1",
   360  		PubKey:            "node1",
   361  		SelfStake:         num.UintZero(),
   362  		StakeByDelegators: num.NewUint(10000),
   363  		Delegators:        delegatorForVal1,
   364  	}
   365  	validator2 := &types.ValidatorData{
   366  		NodeID:            "node2",
   367  		PubKey:            "node2",
   368  		SelfStake:         num.NewUint(20000),
   369  		StakeByDelegators: num.UintZero(),
   370  		Delegators:        map[string]*num.Uint{},
   371  	}
   372  
   373  	delegatorForVal3 := map[string]*num.Uint{}
   374  	delegatorForVal3["party1"] = num.NewUint(40000)
   375  	validator3 := &types.ValidatorData{
   376  		NodeID:            "node3",
   377  		PubKey:            "node3",
   378  		SelfStake:         num.NewUint(30000),
   379  		StakeByDelegators: num.NewUint(40000),
   380  		Delegators:        delegatorForVal3,
   381  	}
   382  
   383  	validator4 := &types.ValidatorData{
   384  		NodeID:            "node4",
   385  		PubKey:            "node4",
   386  		SelfStake:         num.UintZero(),
   387  		StakeByDelegators: num.UintZero(),
   388  		Delegators:        map[string]*num.Uint{},
   389  	}
   390  
   391  	ctrl := gomock.NewController(t)
   392  	broker := bmocks.NewMockBroker(ctrl)
   393  	broker.EXPECT().SendBatch(gomock.Any()).AnyTimes()
   394  	valPerformance := vmock.NewMockValidatorPerformance(ctrl)
   395  	valPerformance.EXPECT().ValidatorPerformanceScore(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(num.DecimalFromFloat(1)).AnyTimes()
   396  
   397  	validatorData := []*types.ValidatorData{validator1, validator2, validator3, validator4}
   398  	valScores := map[string]num.Decimal{"node1": num.DecimalFromFloat(0.25), "node2": num.DecimalFromFloat(0.5), "node3": num.DecimalFromFloat(0.25), "node4": num.DecimalZero()}
   399  	res := calculateRewardsByStake("1", "asset", "rewardsAccountID", num.NewUint(1000000), valScores, validatorData, delegatorShare, num.NewUint(1000000000), logging.NewTestLogger())
   400  
   401  	// 0.1% of 1000000000 = 1000000 - this test is demonstrating that regardless of the remaining balance to give to delegators is less than 0.1% of the max
   402  	// payout per participant, we still run one round and then stop.
   403  
   404  	// the normalised scores are as follows (from the test above)
   405  	// node1 - 0.25
   406  	// node2 - 0.5
   407  	// node3 - 0.25
   408  	// node4 - 0
   409  	// as node3 and node4 has 0 score they get nothing.
   410  	// given a reward of 1000000,
   411  	//
   412  	// node1 and its delegators get 250,000
   413  	// node2 and its delegators get 500,000
   414  	// node3 and its delegators get 250,000
   415  	// with a delegator share of 0.3,
   416  	// delegators to node1 get 0.3 * 250000 = 75000
   417  	// party1 gets 0.6 * 75000 = 45000
   418  	// party2 gets 0.4 * 75000 = 30000
   419  	// node1 gets 175000
   420  	// node2 gets 1 * 500000 = 500000
   421  	// delegators to node3 get 0.3 * 4/7 * 250000 = 42857
   422  	// party1 gets 42857
   423  	// node3 gets 1 - (0.3*4/7) = 207142 -> 207142
   424  	// node1, node2, party1, party2
   425  	require.Equal(t, 5, len(res.partyToAmount))
   426  
   427  	require.Equal(t, num.NewUint(87857), res.partyToAmount["party1"])
   428  	require.Equal(t, num.NewUint(30000), res.partyToAmount["party2"])
   429  	require.Equal(t, num.NewUint(175000), res.partyToAmount["node1"])
   430  	require.Equal(t, num.NewUint(500000), res.partyToAmount["node2"])
   431  	require.Equal(t, num.NewUint(207142), res.partyToAmount["node3"])
   432  	require.Equal(t, num.NewUint(999999), res.totalReward)
   433  }
   434  
   435  func TestValidatorIsNotBeingStarved(t *testing.T) {
   436  	delegatorShare, _ := num.DecimalFromString("0.3")
   437  	delegatorForVal1 := map[string]*num.Uint{}
   438  	delegatorForVal1["party1"] = num.NewUint(6000)
   439  	delegatorForVal1["party2"] = num.NewUint(3000)
   440  	delegatorForVal1["n2"] = num.NewUint(1000)
   441  	validator1 := &types.ValidatorData{
   442  		NodeID:            "node1",
   443  		PubKey:            "n1",
   444  		SelfStake:         num.UintZero(),
   445  		StakeByDelegators: num.NewUint(10000),
   446  		Delegators:        delegatorForVal1,
   447  	}
   448  	validator2 := &types.ValidatorData{
   449  		NodeID:            "node2",
   450  		PubKey:            "n2",
   451  		SelfStake:         num.NewUint(20000),
   452  		StakeByDelegators: num.UintZero(),
   453  		Delegators:        map[string]*num.Uint{},
   454  	}
   455  
   456  	delegatorForVal3 := map[string]*num.Uint{}
   457  	delegatorForVal3["party1"] = num.NewUint(40000)
   458  	validator3 := &types.ValidatorData{
   459  		NodeID:            "node3",
   460  		PubKey:            "n3",
   461  		SelfStake:         num.NewUint(30000),
   462  		StakeByDelegators: num.NewUint(40000),
   463  		Delegators:        delegatorForVal3,
   464  	}
   465  
   466  	validator4 := &types.ValidatorData{
   467  		NodeID:            "node4",
   468  		PubKey:            "n4",
   469  		SelfStake:         num.UintZero(),
   470  		StakeByDelegators: num.UintZero(),
   471  		Delegators:        map[string]*num.Uint{},
   472  	}
   473  	ctrl := gomock.NewController(t)
   474  	broker := bmocks.NewMockBroker(ctrl)
   475  	broker.EXPECT().SendBatch(gomock.Any()).AnyTimes()
   476  	valPerformance := vmock.NewMockValidatorPerformance(ctrl)
   477  	valPerformance.EXPECT().ValidatorPerformanceScore(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(num.DecimalFromFloat(1)).AnyTimes()
   478  
   479  	validatorData := []*types.ValidatorData{validator1, validator2, validator3, validator4}
   480  	valScores := map[string]num.Decimal{"node1": num.DecimalFromFloat(0.25), "node2": num.DecimalFromFloat(0.5), "node3": num.DecimalFromFloat(0.25), "node4": num.DecimalZero()}
   481  	res := calculateRewardsByStake("1", "asset", "rewardsAccountID", num.NewUint(1000000), valScores, validatorData, delegatorShare, num.NewUint(1000000000), logging.NewTestLogger())
   482  
   483  	// 0.1% of 1000000000 = 1000000 - this test is demonstrating that regardless of the remaining balance to give to delegators is less than 0.1% of the max
   484  	// payout per participant, we still run one round and then stop.
   485  
   486  	// the normalised scores are as follows (from the test above)
   487  	// node1 - 0.25
   488  	// node2 - 0.5
   489  	// node3 - 0.25
   490  	// node4 - 0
   491  	// as node4 has 0 score they get nothing.
   492  	// given a reward of 1000000,
   493  	//
   494  	// node1 and its delegators get 250,000
   495  	// node2 and its delegators get 500,000
   496  	// node3 and its delegators get 250,000
   497  	// with a delegator share of 0.3,
   498  	// delegators to node1 get 0.3 * 250000 = 75000
   499  	// party1 gets 0.6 * 75000 = 45000
   500  	// party2 gets 0.3 * 75000 = 22500
   501  	// n2 gets 0.1 * 75000 = 7500
   502  	// node1 gets 175000
   503  	// node2 gets 1 * 500000 = 500000 + 7500 (from the delegation to node1) = 507500
   504  	// delegators to node3 get 0.3 * 4/7 * 250000 = 42857
   505  	// party1 gets 42857
   506  	// node3 gets 1 - (0.3*4/7) = 207142 -> 207142
   507  	// node1, node2, party1, party2
   508  	require.Equal(t, 5, len(res.partyToAmount))
   509  
   510  	require.Equal(t, num.NewUint(87857), res.partyToAmount["party1"])
   511  	require.Equal(t, num.NewUint(22500), res.partyToAmount["party2"])
   512  	require.Equal(t, num.NewUint(175000), res.partyToAmount["n1"])
   513  	require.Equal(t, num.NewUint(507500), res.partyToAmount["n2"])
   514  	require.Equal(t, num.NewUint(207142), res.partyToAmount["n3"])
   515  	require.Equal(t, num.NewUint(999999), res.totalReward)
   516  }