@@ -18,12 +18,16 @@ package participation
1818
1919import (
2020 "path/filepath"
21+ "runtime"
2122 "testing"
23+ "time"
2224
2325 "github.com/stretchr/testify/require"
2426
2527 "github.com/algorand/go-algorand/config"
2628 "github.com/algorand/go-algorand/data/basics"
29+ "github.com/algorand/go-algorand/protocol"
30+ "github.com/algorand/go-algorand/test/e2e-go/globals"
2731 "github.com/algorand/go-algorand/test/framework/fixtures"
2832)
2933
@@ -95,20 +99,45 @@ func waitForAccountToProposeBlock(a *require.Assertions, fixture *fixtures.RestC
9599 return false
96100}
97101
102+ // TestNewAccountCanGoOnlineAndParticipate tests two behaviors:
103+ // - When the account does not have enough stake, or after receivning algos, but before the lookback rounds,
104+ // it should not be proposing blocks
105+ // - When the account balance receives enough stake, it should be proposing after lookback rounds
98106func TestNewAccountCanGoOnlineAndParticipate (t * testing.T ) {
99- /*if runtime.GOOS == "darwin" {
100- t.Skip()
101- }
102107 if testing .Short () {
103108 t .Skip ()
104- }*/
105- t .Skip () // temporary disable the test since it's failing.
109+ }
106110
107111 t .Parallel ()
108112 a := require .New (fixtures .SynchronizedTest (t ))
109113
114+ // Make the seed lookback shorter, otherwise will wait for 320 rounds
115+ consensus := make (config.ConsensusProtocols )
116+ shortPartKeysProtocol := config .Consensus [protocol .ConsensusCurrentVersion ]
117+ shortPartKeysProtocol .ApprovedUpgrades = map [protocol.ConsensusVersion ]uint64 {}
118+ shortPartKeysProtocol .SeedLookback = 2
119+ shortPartKeysProtocol .SeedRefreshInterval = 8
120+ if runtime .GOARCH == "amd64" {
121+ // amd64 platforms are generally quite capable, so accelerate the round times to make the test run faster.
122+ shortPartKeysProtocol .AgreementFilterTimeoutPeriod0 = 1 * time .Second
123+ shortPartKeysProtocol .AgreementFilterTimeout = 1 * time .Second
124+ }
125+ consensus [protocol .ConsensusVersion ("shortpartkeysprotocol" )] = shortPartKeysProtocol
126+
110127 var fixture fixtures.RestClientFixture
111- fixture .Setup (t , filepath .Join ("nettemplates" , "TwoNodesOneOnline.json" ))
128+ fixture .SetConsensus (consensus )
129+ fixture .SetupNoStart (t , filepath .Join ("nettemplates" , "OneNode.json" ))
130+
131+ // update the config file by setting the ParticipationKeysRefreshInterval to 5 second.
132+ nodeDirectory , err := fixture .GetNodeDir ("Primary" )
133+ a .NoError (err )
134+ cfg , err := config .LoadConfigFromDisk (nodeDirectory )
135+ a .NoError (err )
136+ cfg .ParticipationKeysRefreshInterval = 5 * time .Second
137+ cfg .SaveToDisk (nodeDirectory )
138+
139+ fixture .Start ()
140+
112141 defer fixture .Shutdown ()
113142 client := fixture .LibGoalClient
114143
@@ -129,7 +158,7 @@ func TestNewAccountCanGoOnlineAndParticipate(t *testing.T) {
129158
130159 transactionFee := minTxnFee
131160 amountToSendInitial := 5 * minAcctBalance
132- fixture .SendMoneyAndWait (initialRound , amountToSendInitial , transactionFee , richAccount , newAccount )
161+ fixture .SendMoneyAndWait (initialRound , amountToSendInitial , transactionFee , richAccount , newAccount , "" )
133162 amt , err := client .GetBalance (newAccount )
134163 a .NoError (err )
135164 nodeStatus , err := client .Status ()
@@ -145,7 +174,7 @@ func TestNewAccountCanGoOnlineAndParticipate(t *testing.T) {
145174 a .NoError (err , "rest client should be able to add participation key to new account" )
146175 a .Equal (newAccount , partkeyResponse .Parent .String (), "partkey response should echo queried account" )
147176 // account uses part key to go online
148- goOnlineTx , err := client .MakeUnsignedGoOnlineTx (newAccount , nil , 0 , 0 , transactionFee , [32 ]byte {})
177+ goOnlineTx , err := client .MakeUnsignedGoOnlineTx (newAccount , & partkeyResponse , 0 , 0 , transactionFee , [32 ]byte {})
149178 a .NoError (err , "should be able to make go online tx" )
150179 a .Equal (newAccount , goOnlineTx .Src ().String (), "go online response should echo queried account" )
151180 onlineTxID , err := client .SignAndBroadcastTransaction (wh , nil , goOnlineTx )
@@ -159,35 +188,37 @@ func TestNewAccountCanGoOnlineAndParticipate(t *testing.T) {
159188 newAccountStatus , err := client .AccountInformation (newAccount )
160189 a .NoError (err , "client should be able to get information about new account" )
161190 a .Equal (basics .Online .String (), newAccountStatus .Status , "new account should be online" )
162- // account receives almost all of rich account's stake (minus enough to
163- // keep it over MinBalance), so it will be selected for participation
191+
192+ // transfer the funds and close to the new account
164193 amountToSend := richBalance - 3 * transactionFee - amountToSendInitial - minAcctBalance
165- fixture .SendMoneyAndWait (onlineRound , amountToSend , transactionFee , richAccount , newAccount )
194+ txn := fixture .SendMoneyAndWait (onlineRound , amountToSend , transactionFee , richAccount , newAccount , newAccount )
195+ fundedRound := txn .ConfirmedRound
166196
167197 nodeStatus , _ = client .Status ()
168- fundedRound := nodeStatus .LastRound
169-
170198 params , err := client .ConsensusParams (nodeStatus .LastRound )
171199 a .NoError (err )
172- lookbackRound := balanceRound (basics .Round (nodeStatus .LastRound ), params )
173- delta := int64 (nodeStatus .LastRound ) - int64 (lookbackRound )
174- a .True (delta > 0 )
200+ accountProposesStarting := balanceRoundOf (basics .Round (fundedRound ), params )
175201
176202 // Need to wait for funding to take effect on selection, then we can see if we're participating
177203 // Stop before the account should become eligible for selection so we can ensure it wasn't
178- err = fixture .WaitForRoundWithTimeout (fundedRound + uint64 (delta ) - 1 )
204+ err = fixture .ClientWaitForRound (fixture .AlgodClient , uint64 (accountProposesStarting - 1 ),
205+ time .Duration (uint64 (globals .MaxTimePerRound )* uint64 (accountProposesStarting - 1 )))
179206 a .NoError (err )
180207
181- blockWasProposed := fixture .VerifyBlockProposed (newAccount , int (delta )- 1 )
182- a .False (blockWasProposed , "account should not be selected until BalLookback (round %d) passes" , int (delta )- 1 )
208+ // Check if the account did not propose any blocks up to this round
209+ blockWasProposed := fixture .VerifyBlockProposedRange (newAccount , int (accountProposesStarting )- 1 ,
210+ int (accountProposesStarting )- 1 )
211+ a .False (blockWasProposed , "account should not be selected until BalLookback (round %d) passes" , int (accountProposesStarting - 1 ))
212+
213+ // Now wait until the round where the funded account will be used.
214+ err = fixture .ClientWaitForRound (fixture .AlgodClient , uint64 (accountProposesStarting ), 10 * globals .MaxTimePerRound )
215+ a .NoError (err )
183216
184- // check that account starts participating after a while
185- proposalWindow := 20 // arbitrary
186- blockWasProposedByNewAccountRecently := waitForAccountToProposeBlock (a , & fixture , newAccount , proposalWindow )
217+ blockWasProposedByNewAccountRecently := fixture .VerifyBlockProposedRange (newAccount , int (accountProposesStarting ), 1 )
187218 a .True (blockWasProposedByNewAccountRecently , "newly online account should be proposing blocks" )
188219}
189220
190- // helper copied from agreement/selector.go
191- func balanceRound (r basics.Round , cparams config.ConsensusParams ) basics.Round {
192- return r . SubSaturate ( basics .Round (2 * cparams .SeedRefreshInterval * cparams .SeedLookback ))
221+ // Returns the earliest round which will have the balanceRound equal to r
222+ func balanceRoundOf (r basics.Round , cparams config.ConsensusParams ) basics.Round {
223+ return basics .Round (2 * cparams .SeedRefreshInterval * cparams .SeedLookback ) + r
193224}
0 commit comments