@@ -49,21 +49,22 @@ func TestBasicPayouts(t *testing.T) {
49
49
// Make the seed lookback shorter, otherwise we need to wait 320 rounds to become IncentiveEligible.
50
50
const lookback = 32
51
51
fixture .FasterConsensus (protocol .ConsensusFuture , time .Second , lookback )
52
- fmt . Printf ("lookback is %d\n " , lookback )
52
+ t . Logf ("lookback is %d\n " , lookback )
53
53
fixture .Setup (t , filepath .Join ("nettemplates" , "Payouts.json" ))
54
54
defer fixture .Shutdown ()
55
55
56
56
// Overview of this test:
57
57
// rereg to become eligible (must pay extra fee)
58
58
// show payouts are paid (from fees and bonuses)
59
59
// deplete feesink to ensure it's graceful
60
-
60
+ addressToNode := make ( map [ string ] string )
61
61
clientAndAccount := func (name string ) (libgoal.Client , model.Account ) {
62
62
c := fixture .GetLibGoalClientForNamedNode (name )
63
63
accounts , err := fixture .GetNodeWalletsSortedByBalance (c )
64
64
a .NoError (err )
65
65
a .Len (accounts , 1 )
66
- fmt .Printf ("Client %s is %v\n " , name , accounts [0 ].Address )
66
+ t .Logf ("Client %s is %v\n " , name , accounts [0 ].Address )
67
+ addressToNode [accounts [0 ].Address ] = name
67
68
return c , accounts [0 ]
68
69
}
69
70
@@ -74,31 +75,42 @@ func TestBasicPayouts(t *testing.T) {
74
75
data01 := rekeyreg (& fixture , a , c01 , account01 .Address , true )
75
76
data15 := rekeyreg (& fixture , a , c15 , account15 .Address , true )
76
77
78
+ // Wait a few rounds after rekeyreg, this means that `lookback` rounds after
79
+ // those rekeyregs, the nodes will be IncentiveEligible, but both will have
80
+ // too much stake to earn rewards. Then we'll burn from account01, so
81
+ // lookback rounds after _that_ account01 will start earning.
82
+ client := fixture .LibGoalClient
83
+ status , err := client .Status ()
84
+ a .NoError (err )
85
+ fixture .WaitForRoundWithTimeout (status .LastRound + 10 )
86
+
77
87
// have account01 burn some money to get below the eligibility cap
78
88
// Starts with 100M, so burn 60M and get under 70M cap.
79
89
txn , err := c01 .SendPaymentFromUnencryptedWallet (account01 .Address , basics.Address {}.String (),
80
90
1000 , 60_000_000_000_000 , nil )
81
91
a .NoError (err )
82
92
burn , err := fixture .WaitForConfirmedTxn (uint64 (txn .LastValid ), txn .ID ().String ())
83
93
a .NoError (err )
94
+ burnRound := * burn .ConfirmedRound
95
+ t .Logf ("burn round is %d" , burnRound )
84
96
// sync up with the network
85
- _ , err = c01 .WaitForRound (* burn . ConfirmedRound )
97
+ _ , err = c01 .WaitForRound (burnRound )
86
98
a .NoError (err )
87
99
data01 , err = c01 .AccountData (account01 .Address )
88
100
a .NoError (err )
89
101
90
- // Go 31 rounds after the burn happened. During this time, incentive
91
- // eligibility is not in effect yet, so regardless of who proposes, they
92
- // won't earn anything.
93
- client := fixture .LibGoalClient
94
- status , err := client .Status ()
102
+ // Start advancing. IncentiveEligibile will come into effect 32 rounds after
103
+ // the rekeregs but earning will only happen 32 rounds after burnRound, and
104
+ // only for account01 (the one that burned to get under the cap).
105
+ status , err = client .Status ()
95
106
a .NoError (err )
96
- for status .LastRound < * burn .ConfirmedRound + lookback - 1 {
107
+ account1earned := false
108
+ for ! account1earned {
97
109
block , err := client .BookkeepingBlock (status .LastRound )
98
110
a .NoError (err )
99
111
100
- fmt . Printf ("block %d proposed by %v\n " , status . LastRound , block . Proposer ())
101
- a . Zero ( block .ProposerPayout ()) // nobody is eligible yet (hasn't worked back to balance round )
112
+ t . Logf ("block %d proposed by %s % v\n " ,
113
+ status . LastRound , addressToNode [ block .Proposer (). String ()], block . Proposer () )
102
114
a .EqualValues (bonus1 , block .Bonus .Raw )
103
115
104
116
// all nodes agree the proposer proposed. The paranoia here is
@@ -109,7 +121,7 @@ func TestBasicPayouts(t *testing.T) {
109
121
// optimization, and it would cause failures here. Interface changes
110
122
// made since they should make such a problem impossible, but...
111
123
for i , c := range []libgoal.Client {c15 , c01 , relay } {
112
- fmt . Printf ("checking block %v\n " , block .Round ())
124
+ t . Logf ("checking block %v\n " , block .Round ())
113
125
bb , err := getblock (c , status .LastRound )
114
126
a .NoError (err )
115
127
a .Equal (block .Proposer (), bb .Proposer ())
@@ -125,12 +137,26 @@ func TestBasicPayouts(t *testing.T) {
125
137
next , err := client .AccountData (block .Proposer ().String ())
126
138
a .NoError (err )
127
139
a .LessOrEqual (int (status .LastRound ), int (next .LastProposed ))
128
- // regardless of proposer, nobody gets paid
129
140
switch block .Proposer ().String () {
130
141
case account01 .Address :
131
- a .Equal (data01 .MicroAlgos , next .MicroAlgos )
142
+ if uint64 (block .Round ()) < burnRound + lookback {
143
+ // until the burn is lookback rounds old, account01 can't earn
144
+ a .Zero (block .ProposerPayout ())
145
+ a .Equal (data01 .MicroAlgos , next .MicroAlgos )
146
+ } else {
147
+ a .EqualValues (bonus1 , block .ProposerPayout ().Raw )
148
+ // We'd like to do test if account one got paid the bonus:
149
+ // a.EqualValues(data01.MicroAlgos.Raw+bonus1, next.MicroAlgos.Raw)
150
+
151
+ // But we can't because it might have already proposed again. So
152
+ // let's check if it has received one OR two bonuses.
153
+ earned := int (next .MicroAlgos .Raw - data01 .MicroAlgos .Raw )
154
+ a .True (earned == bonus1 || earned == 2 * bonus1 , "earned %d" , earned )
155
+ account1earned = true
156
+ }
132
157
data01 = next
133
158
case account15 .Address :
159
+ a .Zero (block .ProposerPayout ())
134
160
a .Equal (data15 .MicroAlgos , next .MicroAlgos )
135
161
data15 = next
136
162
default :
@@ -141,54 +167,6 @@ func TestBasicPayouts(t *testing.T) {
141
167
a .NoError (err )
142
168
}
143
169
144
- // all nodes are in sync
145
- for _ , c := range []libgoal.Client {c15 , c01 , relay } {
146
- _ , err := c .WaitForRound (status .LastRound )
147
- a .NoError (err )
148
- }
149
-
150
- // Wait until each have proposed, so we can see that 01 gets paid and 15 does not (too much balance)
151
- proposed01 := false
152
- proposed15 := false
153
- for i := 0 ; ! proposed01 || ! proposed15 ; i ++ {
154
- status , err := client .Status ()
155
- a .NoError (err )
156
- block , err := client .BookkeepingBlock (status .LastRound )
157
- a .NoError (err )
158
- a .EqualValues (bonus1 , block .Bonus .Raw )
159
-
160
- next , err := client .AccountData (block .Proposer ().String ())
161
- a .NoError (err )
162
- fmt .Printf (" proposer %v has %d after proposing round %d\n " , block .Proposer (), next .MicroAlgos .Raw , status .LastRound )
163
-
164
- // all nodes agree the proposer proposed
165
- for i , c := range []libgoal.Client {c15 , c01 , relay } {
166
- _ , err := c .WaitForRound (status .LastRound )
167
- a .NoError (err )
168
- data , err := c .AccountData (block .Proposer ().String ())
169
- a .NoError (err )
170
- // <= in case one node is behind, and the others have already advanced
171
- a .LessOrEqual (block .Round (), data .LastProposed , i )
172
- }
173
-
174
- // 01 would get paid (because under balance cap) 15 would not
175
- switch block .Proposer ().String () {
176
- case account01 .Address :
177
- a .EqualValues (bonus1 , block .ProposerPayout ().Raw )
178
- a .EqualValues (data01 .MicroAlgos .Raw + bonus1 , next .MicroAlgos .Raw ) // 01 earns
179
- proposed01 = true
180
- data01 = next
181
- case account15 .Address :
182
- a .Zero (block .ProposerPayout ())
183
- a .Equal (data15 .MicroAlgos , next .MicroAlgos ) // didn't earn
184
- data15 = next
185
- proposed15 = true
186
- default :
187
- a .Fail ("bad proposer" , "%v proposed" , block .Proposer )
188
- }
189
- fixture .WaitForRoundWithTimeout (status .LastRound + 1 )
190
- }
191
-
192
170
// Now that we've proven incentives get paid, let's drain the FeeSink and
193
171
// ensure it happens gracefully. Have account15 go offline so that (after
194
172
// 32 rounds) only account01 (who is eligible) is proposing, so drainage
@@ -203,7 +181,8 @@ func TestBasicPayouts(t *testing.T) {
203
181
offTxn , err := fixture .WaitForConfirmedTxn (uint64 (offline .LastValid ), offlineTxID )
204
182
a .NoError (err )
205
183
206
- fmt .Printf (" c15 (%s) will be truly offline (not proposing) after round %d\n " , account15 .Address , * offTxn .ConfirmedRound + lookback )
184
+ t .Logf (" c15 (%s) will be truly offline (not proposing) after round %d\n " ,
185
+ account15 .Address , * offTxn .ConfirmedRound + lookback )
207
186
208
187
var feesink basics.Address
209
188
for i := 0 ; i < 100 ; i ++ {
0 commit comments