Skip to content

Commit 0b8d9e0

Browse files
authored
Testing: Move WaitForConfirmedTxn down into clients (algorand#6218)
1 parent 45e94f5 commit 0b8d9e0

File tree

7 files changed

+81
-62
lines changed

7 files changed

+81
-62
lines changed

daemon/algod/api/client/restClient.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,45 @@ func (client RestClient) WaitForRoundWithTimeout(roundToWaitFor uint64) error {
336336
return nil
337337
}
338338

339+
// WaitForConfirmedTxn waits until either the passed txid is confirmed
340+
// or until the passed roundTimeout passes
341+
// or until waiting for a round to pass times out
342+
func (client RestClient) WaitForConfirmedTxn(roundTimeout uint64, txid string) (txn v2.PreEncodedTxInfo, err error) {
343+
for {
344+
// Get current round information
345+
curStatus, statusErr := client.Status()
346+
if err != nil {
347+
return txn, statusErr
348+
}
349+
curRound := curStatus.LastRound
350+
351+
// Check if we know about the transaction yet
352+
var resp []byte
353+
resp, err = client.RawPendingTransactionInformation(txid)
354+
if err == nil {
355+
err = protocol.DecodeReflect(resp, &txn)
356+
if err != nil {
357+
return txn, err
358+
}
359+
}
360+
361+
// Check if transaction was confirmed
362+
if txn.ConfirmedRound != nil && *txn.ConfirmedRound > 0 {
363+
return
364+
}
365+
// Check if we should wait a round
366+
if curRound > roundTimeout {
367+
err = fmt.Errorf("failed to see confirmed transaction by round %v", roundTimeout)
368+
return txn, err
369+
}
370+
// Wait a round
371+
err = client.WaitForRoundWithTimeout(curRound + 1)
372+
if err != nil {
373+
return txn, err
374+
}
375+
}
376+
}
377+
339378
// HealthCheck does a health check on the potentially running node,
340379
// returning an error if the API is down
341380
func (client RestClient) HealthCheck() error {

libgoal/transactions.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/algorand/go-algorand/config"
2424
"github.com/algorand/go-algorand/crypto"
2525
"github.com/algorand/go-algorand/crypto/merklesignature"
26+
v2 "github.com/algorand/go-algorand/daemon/algod/api/server/v2"
2627
"github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated/model"
2728
"github.com/algorand/go-algorand/data/account"
2829
"github.com/algorand/go-algorand/data/basics"
@@ -206,6 +207,15 @@ func (c *Client) SignAndBroadcastTransaction(walletHandle, pw []byte, utx transa
206207
return c.BroadcastTransaction(stx)
207208
}
208209

210+
// WaitForConfirmedTxn waits for a transaction to be confirmed, returing information about it.
211+
func (c *Client) WaitForConfirmedTxn(roundTimeout uint64, txid string) (txn v2.PreEncodedTxInfo, err error) {
212+
algod, err := c.ensureAlgodClient()
213+
if err != nil {
214+
return
215+
}
216+
return algod.WaitForConfirmedTxn(roundTimeout, txid)
217+
}
218+
209219
// generateRegistrationTransaction returns a transaction object for registering a Participation with its parent this is
210220
// similar to account.Participation.GenerateRegistrationTransaction.
211221
func generateRegistrationTransaction(part model.ParticipationKey, fee basics.MicroAlgos, txnFirstValid, txnLastValid basics.Round, leaseBytes [32]byte) (transactions.Transaction, error) {

test/e2e-go/features/incentives/challenge_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,11 @@ func testChallengesOnce(t *testing.T, a *require.Assertions) (retry bool) {
9797

9898
// eligible accounts1 will get challenged with node offline, and suspended
9999
for _, account := range accounts1 {
100-
rekeyreg(&fixture, a, c1, account.Address, eligible(account.Address))
100+
rekeyreg(a, c1, account.Address, eligible(account.Address))
101101
}
102102
// eligible accounts2 will get challenged, but node2 will heartbeat for them
103103
for _, account := range accounts2 {
104-
rekeyreg(&fixture, a, c2, account.Address, eligible(account.Address))
104+
rekeyreg(a, c2, account.Address, eligible(account.Address))
105105
}
106106

107107
// turn off node 1, so it can't heartbeat

test/e2e-go/features/incentives/payouts_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ func TestBasicPayouts(t *testing.T) {
7272
c01, account01 := clientAndAccount("Node01")
7373
relay, _ := clientAndAccount("Relay")
7474

75-
data01 := rekeyreg(&fixture, a, c01, account01.Address, true)
76-
data15 := rekeyreg(&fixture, a, c15, account15.Address, true)
75+
data01 := rekeyreg(a, c01, account01.Address, true)
76+
data15 := rekeyreg(a, c15, account15.Address, true)
7777

7878
// Wait a few rounds after rekeyreg, this means that `lookback` rounds after
7979
// those rekeyregs, the nodes will be IncentiveEligible, but both will have
@@ -296,7 +296,7 @@ func getblock(client libgoal.Client, round uint64) (bookkeeping.Block, error) {
296296
return client.BookkeepingBlock(round)
297297
}
298298

299-
func rekeyreg(f *fixtures.RestClientFixture, a *require.Assertions, client libgoal.Client, address string, becomeEligible bool) basics.AccountData {
299+
func rekeyreg(a *require.Assertions, client libgoal.Client, address string, becomeEligible bool) basics.AccountData {
300300
// we start by making an _offline_ tx here, because we want to populate the
301301
// key material ourself with a copy of the account's existing material. That
302302
// makes it an _online_ keyreg. That allows the running node to chug along
@@ -329,7 +329,7 @@ func rekeyreg(f *fixtures.RestClientFixture, a *require.Assertions, client libgo
329329
a.NoError(err)
330330
onlineTxID, err := client.SignAndBroadcastTransaction(wh, nil, reReg)
331331
a.NoError(err)
332-
txn, err := f.WaitForConfirmedTxn(uint64(reReg.LastValid), onlineTxID)
332+
txn, err := client.WaitForConfirmedTxn(uint64(reReg.LastValid), onlineTxID)
333333
a.NoError(err)
334334
// sync up with the network
335335
_, err = client.WaitForRound(*txn.ConfirmedRound)

test/e2e-go/features/incentives/suspension_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ func TestBasicSuspension(t *testing.T) {
7070
c10, account10 := clientAndAccount("Node10")
7171
c20, account20 := clientAndAccount("Node20")
7272

73-
rekeyreg(&fixture, a, c10, account10.Address, true)
74-
rekeyreg(&fixture, a, c20, account20.Address, true)
73+
rekeyreg(a, c10, account10.Address, true)
74+
rekeyreg(a, c20, account20.Address, true)
7575

7676
// Accounts are now suspendable whether they have proposed yet or not
7777
// because keyreg sets LastHeartbeat. Stop c20 which means account20 will be

test/e2e-go/features/incentives/whalejoin_test.go

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package suspension
1818

1919
import (
20-
"fmt"
2120
"path/filepath"
2221
"testing"
2322
"time"
@@ -65,15 +64,15 @@ func TestWhaleJoin(t *testing.T) {
6564
accounts, err := fixture.GetNodeWalletsSortedByBalance(c)
6665
a.NoError(err)
6766
a.Len(accounts, 1)
68-
fmt.Printf("Client %s is %v\n", name, accounts[0].Address)
67+
t.Logf("Client %s is %v\n", name, accounts[0].Address)
6968
return c, accounts[0]
7069
}
7170

7271
c15, account15 := clientAndAccount("Node15")
7372
c01, account01 := clientAndAccount("Node01")
7473

7574
// 1. take wallet15 offline
76-
keys := offline(&fixture, a, c15, account15.Address)
75+
keys := offline(a, c15, account15.Address)
7776

7877
// 2. c01 starts with 100M, so burn 99.9M to get total online stake down
7978
burn, err := c01.SendPaymentFromUnencryptedWallet(account01.Address, basics.Address{}.String(),
@@ -87,7 +86,7 @@ func TestWhaleJoin(t *testing.T) {
8786
a.NoError(err)
8887

8988
// 4. rejoin, with 1.5B against the paltry 100k that's currently online
90-
online(&fixture, a, c15, account15.Address, keys)
89+
online(a, c15, account15.Address, keys)
9190

9291
// 5. wait for agreement balances to kick in (another lookback's worth, plus some slack)
9392
_, err = c01.WaitForRound(*receipt.ConfirmedRound + 2*lookback + 5)
@@ -139,20 +138,20 @@ func TestBigJoin(t *testing.T) {
139138
accounts, err := fixture.GetNodeWalletsSortedByBalance(c)
140139
a.NoError(err)
141140
a.Len(accounts, 1)
142-
fmt.Printf("Client %s is %v\n", name, accounts[0].Address)
141+
t.Logf("Client %s is %v\n", name, accounts[0].Address)
143142
return c, accounts[0]
144143
}
145144

146145
c01, account01 := clientAndAccount("Node01")
147146

148147
// 1. take wallet01 offline
149-
keys := offline(&fixture, a, c01, account01.Address)
148+
keys := offline(a, c01, account01.Address)
150149

151150
// 2. Wait lookback rounds
152151
wait(&fixture, a, lookback)
153152

154153
// 4. rejoin, with 1/16 of total stake
155-
onRound := online(&fixture, a, c01, account01.Address, keys)
154+
onRound := online(a, c01, account01.Address, keys)
156155

157156
// 5. wait for enough rounds to pass, during which c01 can't vote, that is
158157
// could get knocked off.
@@ -162,7 +161,7 @@ func TestBigJoin(t *testing.T) {
162161
a.Equal(basics.Online, data.Status)
163162

164163
// 5a. just to be sure, do a zero pay to get it "noticed"
165-
zeroPay(&fixture, a, c01, account01.Address)
164+
zeroPay(a, c01, account01.Address)
166165
data, err = c01.AccountData(account01.Address)
167166
a.NoError(err)
168167
a.Equal(basics.Online, data.Status)
@@ -175,7 +174,7 @@ func TestBigJoin(t *testing.T) {
175174
a.NoError(err)
176175
a.Equal(basics.Online, data.Status)
177176

178-
zeroPay(&fixture, a, c01, account01.Address)
177+
zeroPay(a, c01, account01.Address)
179178
data, err = c01.AccountData(account01.Address)
180179
a.NoError(err)
181180
a.Equal(basics.Online, data.Status)
@@ -215,7 +214,7 @@ func TestBigIncrease(t *testing.T) {
215214
accounts, err := fixture.GetNodeWalletsSortedByBalance(c)
216215
a.NoError(err)
217216
a.Len(accounts, 1)
218-
fmt.Printf("Client %s is %v\n", name, accounts[0].Address)
217+
t.Logf("Client %s is %v\n", name, accounts[0].Address)
219218
return c, accounts[0]
220219
}
221220

@@ -226,14 +225,14 @@ func TestBigIncrease(t *testing.T) {
226225
// certainly will not have proposed by pure luck just before the critical
227226
// round. If we don't do that, 1/16 of stake is enough that it will probably
228227
// have a fairly recent proposal, and not get knocked off.
229-
pay(&fixture, a, c1, account01.Address, account15.Address, 99*account01.Amount/100)
228+
pay(a, c1, account01.Address, account15.Address, 99*account01.Amount/100)
230229

231-
rekeyreg(&fixture, a, c1, account01.Address, true)
230+
rekeyreg(a, c1, account01.Address, true)
232231

233232
// 2. Wait lookback rounds
234233
wait(&fixture, a, lookback)
235234

236-
tx := pay(&fixture, a, c15, account15.Address, account01.Address, 50*account15.Amount/100)
235+
tx := pay(a, c15, account15.Address, account01.Address, 50*account15.Amount/100)
237236
data, err := c15.AccountData(account01.Address)
238237
a.NoError(err)
239238
a.EqualValues(*tx.ConfirmedRound+lookback, data.LastHeartbeat)
@@ -252,22 +251,21 @@ func wait(f *fixtures.RestClientFixture, a *require.Assertions, count uint64) {
252251
a.NoError(f.WaitForRoundWithTimeout(round))
253252
}
254253

255-
func pay(f *fixtures.RestClientFixture, a *require.Assertions,
256-
c libgoal.Client, from string, to string, amount uint64) v2.PreEncodedTxInfo {
254+
func pay(a *require.Assertions, c libgoal.Client,
255+
from string, to string, amount uint64) v2.PreEncodedTxInfo {
257256
pay, err := c.SendPaymentFromUnencryptedWallet(from, to, 1000, amount, nil)
258257
a.NoError(err)
259-
tx, err := f.WaitForConfirmedTxn(uint64(pay.LastValid), pay.ID().String())
258+
tx, err := c.WaitForConfirmedTxn(uint64(pay.LastValid), pay.ID().String())
260259
a.NoError(err)
261260
return tx
262261
}
263262

264-
func zeroPay(f *fixtures.RestClientFixture, a *require.Assertions,
265-
c libgoal.Client, address string) {
266-
pay(f, a, c, address, address, 0)
263+
func zeroPay(a *require.Assertions, c libgoal.Client, address string) {
264+
pay(a, c, address, address, 0)
267265
}
268266

269267
// Go offline, but return the key material so it's easy to go back online
270-
func offline(f *fixtures.RestClientFixture, a *require.Assertions, client libgoal.Client, address string) transactions.KeyregTxnFields {
268+
func offline(a *require.Assertions, client libgoal.Client, address string) transactions.KeyregTxnFields {
271269
offTx, err := client.MakeUnsignedGoOfflineTx(address, 0, 0, 100_000, [32]byte{})
272270
a.NoError(err)
273271

@@ -286,7 +284,7 @@ func offline(f *fixtures.RestClientFixture, a *require.Assertions, client libgoa
286284
a.NoError(err)
287285
onlineTxID, err := client.SignAndBroadcastTransaction(wh, nil, offTx)
288286
a.NoError(err)
289-
txn, err := f.WaitForConfirmedTxn(uint64(offTx.LastValid), onlineTxID)
287+
txn, err := client.WaitForConfirmedTxn(uint64(offTx.LastValid), onlineTxID)
290288
a.NoError(err)
291289
// sync up with the network
292290
_, err = client.WaitForRound(*txn.ConfirmedRound)
@@ -298,7 +296,7 @@ func offline(f *fixtures.RestClientFixture, a *require.Assertions, client libgoa
298296
}
299297

300298
// Go online with the supplied key material
301-
func online(f *fixtures.RestClientFixture, a *require.Assertions, client libgoal.Client, address string, keys transactions.KeyregTxnFields) uint64 {
299+
func online(a *require.Assertions, client libgoal.Client, address string, keys transactions.KeyregTxnFields) uint64 {
302300
// sanity check that we start offline
303301
data, err := client.AccountData(address)
304302
a.NoError(err)
@@ -313,7 +311,7 @@ func online(f *fixtures.RestClientFixture, a *require.Assertions, client libgoal
313311
a.NoError(err)
314312
onlineTxID, err := client.SignAndBroadcastTransaction(wh, nil, onTx)
315313
a.NoError(err)
316-
receipt, err := f.WaitForConfirmedTxn(uint64(onTx.LastValid), onlineTxID)
314+
receipt, err := client.WaitForConfirmedTxn(uint64(onTx.LastValid), onlineTxID)
317315
a.NoError(err)
318316
data, err = client.AccountData(address)
319317
a.NoError(err)

test/framework/fixtures/restClientFixture.go

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import (
2727
"github.com/algorand/go-algorand/data/basics"
2828
"github.com/algorand/go-algorand/data/bookkeeping"
2929
"github.com/algorand/go-algorand/netdeploy"
30-
"github.com/algorand/go-algorand/protocol"
3130

3231
"github.com/algorand/go-algorand/daemon/algod/api/client"
3332
v2 "github.com/algorand/go-algorand/daemon/algod/api/server/v2"
@@ -192,34 +191,7 @@ func (f *RestClientFixture) WaitForTxnConfirmation(roundTimeout uint64, txid str
192191
// or until the passed roundTimeout passes
193192
// or until waiting for a round to pass times out
194193
func (f *RestClientFixture) WaitForConfirmedTxn(roundTimeout uint64, txid string) (txn v2.PreEncodedTxInfo, err error) {
195-
client := f.AlgodClient
196-
for {
197-
// Get current round information
198-
curStatus, statusErr := client.Status()
199-
require.NoError(f.t, statusErr, "fixture should be able to get node status")
200-
curRound := curStatus.LastRound
201-
202-
// Check if we know about the transaction yet
203-
var resp []byte
204-
resp, err = client.RawPendingTransactionInformation(txid)
205-
if err == nil {
206-
err = protocol.DecodeReflect(resp, &txn)
207-
require.NoError(f.t, err)
208-
}
209-
210-
// Check if transaction was confirmed
211-
if txn.ConfirmedRound != nil && *txn.ConfirmedRound > 0 {
212-
return
213-
}
214-
// Check if we should wait a round
215-
if curRound > roundTimeout {
216-
err = fmt.Errorf("failed to see confirmed transaction by round %v", roundTimeout)
217-
return
218-
}
219-
// Wait a round
220-
err = f.WaitForRoundWithTimeout(curRound + 1)
221-
require.NoError(f.t, err, "fixture should be able to wait for one round to pass")
222-
}
194+
return f.AlgodClient.WaitForConfirmedTxn(roundTimeout, txid)
223195
}
224196

225197
// WaitForAllTxnsToConfirm is as WaitForTxnConfirmation,
@@ -295,7 +267,7 @@ func (f *RestClientFixture) WaitForAccountFunded(roundTimeout uint64, accountAdd
295267
return fmt.Errorf("failed to see confirmed transaction by round %v", roundTimeout)
296268
}
297269
// Wait a round
298-
err = f.WaitForRoundWithTimeout(curRound + 1)
270+
err = client.WaitForRoundWithTimeout(curRound + 1)
299271
require.NoError(f.t, err, "fixture should be able to wait for one round to pass")
300272
}
301273
}
@@ -318,7 +290,7 @@ func (f *RestClientFixture) SendMoneyAndWaitFromWallet(walletHandle, walletPassw
318290
require.NoError(f.t, err, "client should be able to send money from rich to poor account")
319291
require.NotEmpty(f.t, fundingTx.ID().String(), "transaction ID should not be empty")
320292
waitingDeadline := curRound + uint64(5)
321-
txn, err = f.WaitForConfirmedTxn(waitingDeadline, fundingTx.ID().String())
293+
txn, err = client.WaitForConfirmedTxn(waitingDeadline, fundingTx.ID().String())
322294
require.NoError(f.t, err)
323295
return
324296
}

0 commit comments

Comments
 (0)