diff --git a/cmd/algoh/blockWatcher.go b/cmd/algoh/blockWatcher.go index cc55b2d49f..43da894d02 100644 --- a/cmd/algoh/blockWatcher.go +++ b/cmd/algoh/blockWatcher.go @@ -20,15 +20,16 @@ import ( "sync" "time" - "github.com/algorand/go-algorand/daemon/algod/api/spec/v1" "github.com/algorand/go-algorand/logging" + "github.com/algorand/go-algorand/protocol" + "github.com/algorand/go-algorand/rpcs" ) var log = logging.Base() type blockListener interface { init(uint64) - onBlock(v1.Block) + onBlock(rpcs.EncodedBlockCert) } type blockWatcher struct { @@ -75,7 +76,8 @@ func (bw *blockWatcher) run(watchers []blockListener, stallDetect time.Duration, for { // Inner loop needed during catchup. for { - block, err := bw.client.Block(curBlock) + // Get the raw block from the client, then parse the block so we can get the bookkeeping block and certificate for proposer address. + resp, err := bw.client.RawBlock(curBlock) // Generally this error will be due to the new block not being ready. In the case of a stall we will // return, causing the loop to restart and handle any possible stall/catchup. @@ -89,6 +91,13 @@ func (bw *blockWatcher) run(watchers []blockListener, stallDetect time.Duration, break } + // Parse the raw block + var block rpcs.EncodedBlockCert + err = protocol.DecodeReflect(resp, &block) + if err != nil { + return false + } + curBlock++ for _, watcher := range watchers { watcher.onBlock(block) diff --git a/cmd/algoh/blockWatcher_test.go b/cmd/algoh/blockWatcher_test.go index f3efd1aaf5..1e4db05732 100644 --- a/cmd/algoh/blockWatcher_test.go +++ b/cmd/algoh/blockWatcher_test.go @@ -22,7 +22,7 @@ import ( "testing" "time" - "github.com/algorand/go-algorand/daemon/algod/api/spec/v1" + "github.com/algorand/go-algorand/rpcs" "github.com/algorand/go-algorand/test/partitiontest" "github.com/stretchr/testify/require" ) @@ -110,7 +110,7 @@ func (l *testlistener) init(block uint64) { atomic.AddUint32(&(l.initCount), 1) } -func (l *testlistener) onBlock(block v1.Block) { +func (l *testlistener) onBlock(rpcs.EncodedBlockCert) { atomic.AddUint32(&(l.blockCount), 1) } diff --git a/cmd/algoh/blockstats.go b/cmd/algoh/blockstats.go index 74a629d32d..590cfb4352 100644 --- a/cmd/algoh/blockstats.go +++ b/cmd/algoh/blockstats.go @@ -19,8 +19,8 @@ package main import ( "time" - "github.com/algorand/go-algorand/daemon/algod/api/spec/v1" "github.com/algorand/go-algorand/logging/telemetryspec" + "github.com/algorand/go-algorand/rpcs" ) const downtimeLimit time.Duration = 5 * time.Minute @@ -34,20 +34,21 @@ type blockstats struct { func (stats *blockstats) init(block uint64) { } -func (stats *blockstats) onBlock(block v1.Block) { +func (stats *blockstats) onBlock(block rpcs.EncodedBlockCert) { now := time.Now() + blockHeader := block.Block.BlockHeader // Ensure we only create stats from consecutive blocks. - if stats.lastBlock+1 != block.Round { - stats.lastBlock = block.Round + if stats.lastBlock+1 != uint64(blockHeader.Round) { + stats.lastBlock = uint64(blockHeader.Round) stats.lastBlockTime = now return } // Grab unique users. users := make(map[string]bool) - for _, tx := range block.Transactions.Transactions { - users[tx.From] = true + for _, tx := range block.Block.Payset { + users[tx.Txn.Sender.String()] = true } duration := now.Sub(stats.lastBlockTime) @@ -57,15 +58,15 @@ func (stats *blockstats) onBlock(block v1.Block) { } stats.log.EventWithDetails(telemetryspec.Agreement, telemetryspec.BlockStatsEvent, telemetryspec.BlockStatsEventDetails{ - Hash: block.Hash, - OriginalProposer: block.Proposer, - Round: block.Round, - Transactions: uint64(len(block.Transactions.Transactions)), + Hash: block.Block.Hash().String(), + OriginalProposer: block.Certificate.Proposal.OriginalProposer.String(), + Round: uint64(blockHeader.Round), + Transactions: uint64(len(block.Block.Payset)), ActiveUsers: uint64(len(users)), AgreementDurationMs: uint64(duration.Nanoseconds() / 1000 / 1000), NetworkDowntimeMs: uint64(downtime.Nanoseconds() / 1000 / 1000), }) - stats.lastBlock = block.Round + stats.lastBlock = uint64(blockHeader.Round) stats.lastBlockTime = now } diff --git a/cmd/algoh/blockstats_test.go b/cmd/algoh/blockstats_test.go index d0cafaf3f3..0398404dda 100644 --- a/cmd/algoh/blockstats_test.go +++ b/cmd/algoh/blockstats_test.go @@ -20,8 +20,11 @@ import ( "testing" "time" - "github.com/algorand/go-algorand/daemon/algod/api/spec/v1" + "github.com/algorand/go-algorand/data/basics" + "github.com/algorand/go-algorand/data/bookkeeping" + "github.com/algorand/go-algorand/data/transactions" "github.com/algorand/go-algorand/logging/telemetryspec" + "github.com/algorand/go-algorand/rpcs" "github.com/algorand/go-algorand/test/partitiontest" "github.com/stretchr/testify/require" ) @@ -31,7 +34,7 @@ type event struct { identifier telemetryspec.Event - details interface{} + details telemetryspec.BlockStatsEventDetails } type MockEventSender struct { @@ -39,7 +42,12 @@ type MockEventSender struct { } func (mes *MockEventSender) EventWithDetails(category telemetryspec.Category, identifier telemetryspec.Event, details interface{}) { - mes.events = append(mes.events, event{category: category, identifier: identifier, details: details}) + mes.events = append(mes.events, event{category: category, identifier: identifier, details: details.(telemetryspec.BlockStatsEventDetails)}) +} + +// Helper method to create an EncodedBlockCert for the block handler. +func makeTestBlock(round uint64) rpcs.EncodedBlockCert { + return rpcs.EncodedBlockCert{Block: bookkeeping.Block{BlockHeader: bookkeeping.BlockHeader{Round: basics.Round(round)}}} } func TestConsecutiveBlocks(t *testing.T) { @@ -47,17 +55,57 @@ func TestConsecutiveBlocks(t *testing.T) { sender := MockEventSender{} bs := blockstats{log: &sender} - bs.onBlock(v1.Block{Round: 300}) + bs.onBlock(makeTestBlock(300)) // first consecutive block - bs.onBlock(v1.Block{Round: 301}) + bs.onBlock(makeTestBlock(301)) // reset - bs.onBlock(v1.Block{Round: 303}) + bs.onBlock(makeTestBlock(303)) // second consecutive block - bs.onBlock(v1.Block{Round: 304}) + bs.onBlock(makeTestBlock(304)) require.Equal(t, 2, len(sender.events)) } +func TestEventWithDetails(t *testing.T) { + partitiontest.PartitionTest(t) + sender := MockEventSender{} + bs := blockstats{log: &sender} + + // Create blocks with some senders in the payload. + makeStxnWithAddr := func(addr basics.Address) transactions.SignedTxnInBlock { + return transactions.SignedTxnInBlock{SignedTxnWithAD: transactions.SignedTxnWithAD{SignedTxn: transactions.SignedTxn{Txn: transactions.Transaction{Header: transactions.Header{Sender: addr}}}}} + } + addr := basics.Address{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + otherAddr := basics.Address{0x7, 0xda, 0xcb, 0x4b, 0x6d, 0x9e, 0xd1, 0x41, 0xb1, 0x75, 0x76, 0xbd, 0x45, 0x9a, 0xe6, 0x42, 0x1d, 0x48, 0x6d, 0xa3, 0xd4, 0xef, 0x22, 0x47, 0xc4, 0x9, 0xa3, 0x96, 0xb8, 0x2e, 0xa2, 0x21} + // Check that only unique addrs are returned by ActiveUsers. + stxn1 := makeStxnWithAddr(addr) + stxn2 := makeStxnWithAddr(otherAddr) + stxn3 := makeStxnWithAddr(addr) + // Make block with some transactions. + testBlock := makeTestBlock(300) + testBlock.Block.Payset = transactions.Payset{stxn1, stxn2, stxn3} + + bs.onBlock(makeTestBlock(299)) + bs.onBlock(testBlock) + bs.onBlock(makeTestBlock(301)) + + testCases := []struct { + round uint64 + activeUsers uint64 + txns uint64 + }{ + {uint64(300), uint64(2), uint64(3)}, + {uint64(301), uint64(0), uint64(0)}, + } + + require.Equal(t, 2, len(sender.events)) + for i, event := range sender.events { + require.Equal(t, testCases[i].round, event.details.Round) + require.Equal(t, testCases[i].activeUsers, event.details.ActiveUsers) + require.Equal(t, testCases[i].txns, event.details.Transactions) + } +} + func TestAgreementTime(t *testing.T) { partitiontest.PartitionTest(t) sleepTime := 50 * time.Millisecond @@ -70,13 +118,13 @@ func TestAgreementTime(t *testing.T) { bs := blockstats{log: &sender} start := time.Now() - bs.onBlock(v1.Block{Round: 300}) + bs.onBlock(makeTestBlock(300)) time.Sleep(sleepTime) - bs.onBlock(v1.Block{Round: 301}) + bs.onBlock(makeTestBlock(301)) end := time.Now() require.Equal(t, 1, len(sender.events)) - details := sender.events[0].details.(telemetryspec.BlockStatsEventDetails) + details := sender.events[0].details // Test to see that the wait duration is at least the amount of time we slept require.True(t, int(details.AgreementDurationMs) >= int(sleepTime)/int(time.Millisecond)) diff --git a/cmd/algoh/client.go b/cmd/algoh/client.go index 89a7c27a3a..4a1b4c7ac1 100644 --- a/cmd/algoh/client.go +++ b/cmd/algoh/client.go @@ -20,13 +20,12 @@ import ( "context" generatedV2 "github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated" - "github.com/algorand/go-algorand/daemon/algod/api/spec/v1" ) // Client is a minimal interface for the RestClient type Client interface { Status() (generatedV2.NodeStatusResponse, error) - Block(round uint64) (v1.Block, error) + RawBlock(round uint64) ([]byte, error) GetGoRoutines(ctx context.Context) (string, error) HealthCheck() error } diff --git a/cmd/algoh/deadman.go b/cmd/algoh/deadman.go index 1c302e8802..a15046f077 100644 --- a/cmd/algoh/deadman.go +++ b/cmd/algoh/deadman.go @@ -23,8 +23,8 @@ import ( "time" "github.com/algorand/go-algorand/config" - "github.com/algorand/go-algorand/daemon/algod/api/spec/v1" "github.com/algorand/go-algorand/logging/telemetryspec" + "github.com/algorand/go-algorand/rpcs" ) type deadManWatcher struct { @@ -88,8 +88,8 @@ func (w deadManWatcher) run(initBlock uint64) { } } -func (w deadManWatcher) onBlock(block v1.Block) { - w.newBlockChan <- block.Round +func (w deadManWatcher) onBlock(block rpcs.EncodedBlockCert) { + w.newBlockChan <- uint64(block.Block.BlockHeader.Round) } func (w deadManWatcher) reportDeadManTimeout(curBlock uint64) (err error) { diff --git a/cmd/algoh/mockClient.go b/cmd/algoh/mockClient.go index d9d81387ef..550bf71150 100644 --- a/cmd/algoh/mockClient.go +++ b/cmd/algoh/mockClient.go @@ -21,7 +21,10 @@ import ( "fmt" generatedV2 "github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated" - "github.com/algorand/go-algorand/daemon/algod/api/spec/v1" + "github.com/algorand/go-algorand/data/basics" + "github.com/algorand/go-algorand/data/bookkeeping" + "github.com/algorand/go-algorand/protocol" + "github.com/algorand/go-algorand/rpcs" ) ////////////////////////////////////// @@ -36,10 +39,10 @@ func makeNodeStatuses(blocks ...uint64) (ret []generatedV2.NodeStatusResponse) { return ret } -func makeBlocks(blocks ...uint64) (ret map[uint64]v1.Block) { - ret = map[uint64]v1.Block{} +func makeBlocks(blocks ...uint64) (ret map[uint64]rpcs.EncodedBlockCert) { + ret = map[uint64]rpcs.EncodedBlockCert{} for _, block := range blocks { - ret[block] = v1.Block{Round: block} + ret[block] = rpcs.EncodedBlockCert{Block: bookkeeping.Block{BlockHeader: bookkeeping.BlockHeader{Round: basics.Round(block)}}} } return ret } @@ -54,10 +57,10 @@ type mockClient struct { error []error status []generatedV2.NodeStatusResponse routine []string - block map[uint64]v1.Block + block map[uint64]rpcs.EncodedBlockCert } -func makeMockClient(error []error, status []generatedV2.NodeStatusResponse, block map[uint64]v1.Block, routine []string) mockClient { +func makeMockClient(error []error, status []generatedV2.NodeStatusResponse, block map[uint64]rpcs.EncodedBlockCert, routine []string) mockClient { return mockClient{ BlockCalls: make(map[uint64]int), error: error, @@ -90,15 +93,16 @@ func (c *mockClient) Status() (s generatedV2.NodeStatusResponse, e error) { return } -func (c *mockClient) Block(block uint64) (b v1.Block, e error) { +func (c *mockClient) RawBlock(block uint64) (b []byte, e error) { c.BlockCalls[block]++ e = c.nextError() - b, ok := c.block[block] + bl, ok := c.block[block] if !ok { if e == nil { e = fmt.Errorf("test is missing block %d", block) } } + b = protocol.EncodeReflect(bl) return } diff --git a/cmd/goal/account.go b/cmd/goal/account.go index 62f1b08c80..d7943d7272 100644 --- a/cmd/goal/account.go +++ b/cmd/goal/account.go @@ -591,7 +591,7 @@ func printAccountInfo(client libgoal.Client, address string, onlyShowAssetIds bo _, units = unicodePrintable(*createdAsset.Params.UnitName) } - total := assetDecimalsFmt(createdAsset.Params.Total, uint32(createdAsset.Params.Decimals)) + total := assetDecimalsFmt(createdAsset.Params.Total, createdAsset.Params.Decimals) url := "" if createdAsset.Params.Url != nil { @@ -618,7 +618,7 @@ func printAccountInfo(client libgoal.Client, address string, onlyShowAssetIds bo fmt.Fprintf(report, "\tID %d, error\n", assetHolding.AssetId) } - amount := assetDecimalsFmt(assetHolding.Amount, uint32(assetParams.Params.Decimals)) + amount := assetDecimalsFmt(assetHolding.Amount, assetParams.Params.Decimals) assetName := "" if assetParams.Params.Name != nil { @@ -1137,15 +1137,15 @@ var listParticipationKeysCmd = &cobra.Command{ fmt.Printf(rowFormat, "Registered", "Account", "ParticipationID", "Last Used", "First round", "Last round") for _, part := range parts { onlineInfoStr := "unknown" - onlineAccountInfo, err := client.AccountInformation(part.Address) + onlineAccountInfo, err := client.AccountInformationV2(part.Address, false) if err == nil { votingBytes := part.Key.VoteParticipationKey vrfBytes := part.Key.SelectionParticipationKey if onlineAccountInfo.Participation != nil && - (string(onlineAccountInfo.Participation.ParticipationPK) == string(votingBytes[:])) && - (string(onlineAccountInfo.Participation.VRFPK) == string(vrfBytes[:])) && - (onlineAccountInfo.Participation.VoteFirst == part.Key.VoteFirstValid) && - (onlineAccountInfo.Participation.VoteLast == part.Key.VoteLastValid) && + (string(onlineAccountInfo.Participation.VoteParticipationKey) == string(votingBytes[:])) && + (string(onlineAccountInfo.Participation.SelectionParticipationKey) == string(vrfBytes[:])) && + (onlineAccountInfo.Participation.VoteFirstValid == part.Key.VoteFirstValid) && + (onlineAccountInfo.Participation.VoteLastValid == part.Key.VoteLastValid) && (onlineAccountInfo.Participation.VoteKeyDilution == part.Key.VoteKeyDilution) { onlineInfoStr = "yes" } else { diff --git a/cmd/goal/application.go b/cmd/goal/application.go index 58ac78f75c..aab4e02428 100644 --- a/cmd/goal/application.go +++ b/cmd/goal/application.go @@ -502,8 +502,8 @@ var createAppCmd = &cobra.Command{ if err != nil { reportErrorf(err.Error()) } - if txn.TransactionResults != nil && txn.TransactionResults.CreatedAppIndex != 0 { - reportInfof("Created app with app index %d", txn.TransactionResults.CreatedAppIndex) + if txn.ApplicationIndex != nil && *txn.ApplicationIndex != 0 { + reportInfof("Created app with app index %d", *txn.ApplicationIndex) } } } else { diff --git a/cmd/goal/asset.go b/cmd/goal/asset.go index 5826fd0837..8a814d906a 100644 --- a/cmd/goal/asset.go +++ b/cmd/goal/asset.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" + "github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated" "github.com/algorand/go-algorand/data/basics" "github.com/algorand/go-algorand/libgoal" ) @@ -175,21 +176,29 @@ func lookupAssetID(cmd *cobra.Command, creator string, client libgoal.Client) { "creator account is unknown.") } - response, err := client.AccountInformation(creator) + response, err := client.AccountInformationV2(creator, true) if err != nil { reportErrorf(errorRequestFail, err) } nmatch := 0 - for id, params := range response.AssetParams { - if params.UnitName == assetUnitName { - assetID = id - nmatch++ + if response.CreatedAssets != nil { + for _, asset := range *response.CreatedAssets { + params := asset.Params + if params.UnitName == nil && assetUnitName == "" { + // Since asset unit names can be left blank, try to match + // empty unit names in the user's account first. + assetID = asset.Index + nmatch++ + } else if params.UnitName != nil && *params.UnitName == assetUnitName { + assetID = asset.Index + nmatch++ + } } } if nmatch == 0 { - reportErrorf("No matches for asset unit name %s in creator %s", assetUnitName, creator) + reportErrorf("No matches for asset unit name %s in creator %s; assets %v", assetUnitName, creator, *response.CreatedAssets) } if nmatch > 1 { @@ -316,8 +325,8 @@ var createAssetCmd = &cobra.Command{ if err != nil { reportErrorf(err.Error()) } - if txn.TransactionResults != nil && txn.TransactionResults.CreatedAssetIndex != 0 { - reportInfof("Created asset with asset index %d", txn.TransactionResults.CreatedAssetIndex) + if txn.AssetIndex != nil && *txn.AssetIndex != 0 { + reportInfof("Created asset with asset index %d", *txn.AssetIndex) } } } else { @@ -654,7 +663,7 @@ var freezeAssetCmd = &cobra.Command{ }, } -func assetDecimalsFmt(amount uint64, decimals uint32) string { +func assetDecimalsFmt(amount uint64, decimals uint64) string { // Just return the raw amount with no decimal if decimals is 0 if decimals == 0 { return fmt.Sprintf("%d", amount) @@ -662,7 +671,7 @@ func assetDecimalsFmt(amount uint64, decimals uint32) string { // Otherwise, ensure there are decimals digits to the right of the decimal point pow := uint64(1) - for i := uint32(0); i < decimals; i++ { + for i := uint64(0); i < decimals; i++ { pow *= 10 } return fmt.Sprintf("%d.%0*d", amount/pow, decimals, amount%pow) @@ -754,42 +763,66 @@ var infoAssetCmd = &cobra.Command{ accountList := makeAccountsList(dataDir) creator := accountList.getAddressByName(assetCreator) + // Helper methods for dereferencing optional asset fields. + derefString := func(s *string) string { + if s == nil { + return "" + } + return *s + } + derefBool := func(b *bool) bool { + if b == nil { + return false + } + return *b + } + lookupAssetID(cmd, creator, client) - params, err := client.AssetInformation(assetID) + asset, err := client.AssetInformationV2(assetID) if err != nil { reportErrorf(errorRequestFail, err) } reserveEmpty := false - if params.ReserveAddr == "" { + if derefString(asset.Params.Reserve) == "" { reserveEmpty = true - params.ReserveAddr = params.Creator + asset.Params.Reserve = &asset.Params.Creator } - reserve, err := client.AccountInformation(params.ReserveAddr) + reserve, err := client.AccountInformationV2(*asset.Params.Reserve, true) if err != nil { reportErrorf(errorRequestFail, err) } - res := reserve.Assets[assetID] + var res generated.AssetHolding + if reserve.Assets != nil { + for _, reserveAsset := range *reserve.Assets { + if assetID == reserveAsset.AssetId { + res = reserveAsset + break + } + } + } else { + reportErrorf(errorRequestFail, "cannot find asset ID in account") + } fmt.Printf("Asset ID: %d\n", assetID) - fmt.Printf("Creator: %s\n", params.Creator) - reportInfof("Asset name: %s\n", params.AssetName) - reportInfof("Unit name: %s\n", params.UnitName) - fmt.Printf("Maximum issue: %s %s\n", assetDecimalsFmt(params.Total, params.Decimals), params.UnitName) - fmt.Printf("Reserve amount: %s %s\n", assetDecimalsFmt(res.Amount, params.Decimals), params.UnitName) - fmt.Printf("Issued: %s %s\n", assetDecimalsFmt(params.Total-res.Amount, params.Decimals), params.UnitName) - fmt.Printf("Decimals: %d\n", params.Decimals) - fmt.Printf("Default frozen: %v\n", params.DefaultFrozen) - fmt.Printf("Manager address: %s\n", params.ManagerAddr) + fmt.Printf("Creator: %s\n", asset.Params.Creator) + reportInfof("Asset name: %s\n", derefString(asset.Params.Name)) + reportInfof("Unit name: %s\n", derefString(asset.Params.UnitName)) + fmt.Printf("Maximum issue: %s %s\n", assetDecimalsFmt(asset.Params.Total, asset.Params.Decimals), derefString(asset.Params.UnitName)) + fmt.Printf("Reserve amount: %s %s\n", assetDecimalsFmt(res.Amount, asset.Params.Decimals), derefString(asset.Params.UnitName)) + fmt.Printf("Issued: %s %s\n", assetDecimalsFmt(asset.Params.Total-res.Amount, asset.Params.Decimals), derefString(asset.Params.UnitName)) + fmt.Printf("Decimals: %d\n", asset.Params.Decimals) + fmt.Printf("Default frozen: %v\n", derefBool(asset.Params.DefaultFrozen)) + fmt.Printf("Manager address: %s\n", derefString(asset.Params.Manager)) if reserveEmpty { - fmt.Printf("Reserve address: %s (Empty. Defaulting to creator)\n", params.ReserveAddr) + fmt.Printf("Reserve address: %s (Empty. Defaulting to creator)\n", derefString(asset.Params.Reserve)) } else { - fmt.Printf("Reserve address: %s\n", params.ReserveAddr) + fmt.Printf("Reserve address: %s\n", derefString(asset.Params.Reserve)) } - fmt.Printf("Freeze address: %s\n", params.FreezeAddr) - fmt.Printf("Clawback address: %s\n", params.ClawbackAddr) + fmt.Printf("Freeze address: %s\n", derefString(asset.Params.Freeze)) + fmt.Printf("Clawback address: %s\n", derefString(asset.Params.Clawback)) }, } diff --git a/cmd/goal/clerk.go b/cmd/goal/clerk.go index 8ab3293267..77f1408e50 100644 --- a/cmd/goal/clerk.go +++ b/cmd/goal/clerk.go @@ -30,7 +30,6 @@ import ( "github.com/algorand/go-algorand/config" "github.com/algorand/go-algorand/crypto" generatedV2 "github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated" - v1 "github.com/algorand/go-algorand/daemon/algod/api/spec/v1" "github.com/algorand/go-algorand/data/basics" "github.com/algorand/go-algorand/data/bookkeeping" "github.com/algorand/go-algorand/data/transactions" @@ -156,44 +155,43 @@ var clerkCmd = &cobra.Command{ }, } -func waitForCommit(client libgoal.Client, txid string, transactionLastValidRound uint64) (txn v1.Transaction, err error) { +func waitForCommit(client libgoal.Client, txid string, transactionLastValidRound uint64) (txn generatedV2.PendingTransactionResponse, err error) { // Get current round information stat, err := client.Status() if err != nil { - return v1.Transaction{}, fmt.Errorf(errorRequestFail, err) + return generatedV2.PendingTransactionResponse{}, fmt.Errorf(errorRequestFail, err) } for { // Check if we know about the transaction yet - txn, err = client.PendingTransactionInformation(txid) + txn, err = client.PendingTransactionInformationV2(txid) if err != nil { - return v1.Transaction{}, fmt.Errorf(errorRequestFail, err) + return generatedV2.PendingTransactionResponse{}, fmt.Errorf(errorRequestFail, err) } - if txn.ConfirmedRound > 0 { - reportInfof(infoTxCommitted, txid, txn.ConfirmedRound) + if txn.ConfirmedRound != nil && *txn.ConfirmedRound > 0 { + reportInfof(infoTxCommitted, txid, *txn.ConfirmedRound) break } if txn.PoolError != "" { - return v1.Transaction{}, fmt.Errorf(txPoolError, txid, txn.PoolError) + return generatedV2.PendingTransactionResponse{}, fmt.Errorf(txPoolError, txid, txn.PoolError) } // check if we've already committed to the block number equals to the transaction's last valid round. // if this is the case, the transaction would not be included in the blockchain, and we can exit right // here. if transactionLastValidRound > 0 && stat.LastRound >= transactionLastValidRound { - return v1.Transaction{}, fmt.Errorf(errorTransactionExpired, txid) + return generatedV2.PendingTransactionResponse{}, fmt.Errorf(errorTransactionExpired, txid) } reportInfof(infoTxPending, txid, stat.LastRound) // WaitForRound waits until round "stat.LastRound+1" is committed stat, err = client.WaitForRound(stat.LastRound) if err != nil { - return v1.Transaction{}, fmt.Errorf(errorRequestFail, err) + return generatedV2.PendingTransactionResponse{}, fmt.Errorf(errorRequestFail, err) } } - return } @@ -603,14 +601,14 @@ var rawsendCmd = &cobra.Command{ for txid, txidStr := range pendingTxns { for { // Check if we know about the transaction yet - txn, err := client.PendingTransactionInformation(txidStr) + txn, err := client.PendingTransactionInformationV2(txidStr) if err != nil { txnErrors[txid] = err.Error() reportWarnf(errorRequestFail, err) continue } - if txn.ConfirmedRound > 0 { + if txn.ConfirmedRound != nil && *txn.ConfirmedRound > 0 { reportInfof(infoTxCommitted, txidStr, txn.ConfirmedRound) break } diff --git a/cmd/goal/interact.go b/cmd/goal/interact.go index 45fb5bf8a9..938ce988c5 100644 --- a/cmd/goal/interact.go +++ b/cmd/goal/interact.go @@ -634,8 +634,8 @@ var appExecuteCmd = &cobra.Command{ if err != nil { reportErrorf(err.Error()) } - if txn.TransactionResults != nil && txn.TransactionResults.CreatedAppIndex != 0 { - reportInfof("Created app with app index %d", txn.TransactionResults.CreatedAppIndex) + if txn.ApplicationIndex != nil && *txn.ApplicationIndex != 0 { + reportInfof("Created app with app index %d", *txn.ApplicationIndex) } } } else { diff --git a/cmd/goal/ledger.go b/cmd/goal/ledger.go index fda139bd75..d06cf32379 100644 --- a/cmd/goal/ledger.go +++ b/cmd/goal/ledger.go @@ -65,7 +65,7 @@ var supplyCmd = &cobra.Command{ reportErrorf(errorRequestFail, err) } - fmt.Printf("Round: %v\nTotal Money: %v microAlgos\nOnline Money: %v microAlgos\n", response.Round, response.TotalMoney, response.OnlineMoney) + fmt.Printf("Round: %v\nTotal Money: %v microAlgos\nOnline Money: %v microAlgos\n", response.CurrentRound, response.TotalMoney, response.OnlineMoney) }, } diff --git a/cmd/goal/node.go b/cmd/goal/node.go index 68654055aa..80ca325143 100644 --- a/cmd/goal/node.go +++ b/cmd/goal/node.go @@ -525,23 +525,23 @@ var pendingTxnsCmd = &cobra.Command{ Run: func(cmd *cobra.Command, _ []string) { onDataDirs(func(dataDir string) { client := ensureAlgodClient(dataDir) - statusTxnPool, err := client.GetPendingTransactions(maxPendingTransactions) + statusTxnPool, err := client.GetParsedPendingTransactions(maxPendingTransactions) if err != nil { reportErrorf(errorNodeStatus, err) } - pendingTxns := statusTxnPool.TruncatedTxns + pendingTxns := statusTxnPool.TopTransactions // do this inline for now, break it out when we need to reuse a Txn->String function - reportInfof(infoNodePendingTxnsDescription, maxPendingTransactions, statusTxnPool.TotalTxns) - if pendingTxns.Transactions == nil || len(pendingTxns.Transactions) == 0 { + reportInfof(infoNodePendingTxnsDescription, maxPendingTransactions, statusTxnPool.TotalTransactions) + if len(statusTxnPool.TopTransactions) == 0 { reportInfof(infoNodeNoPendingTxnsDescription) } else { - for _, pendingTxn := range pendingTxns.Transactions { + for _, pendingTxn := range pendingTxns { pendingTxnStr, err := json.MarshalIndent(pendingTxn, "", " ") if err != nil { // json parsing of the txn failed, so let's just skip printing it - fmt.Printf("Unparseable Transaction %s\n", pendingTxn.TxID) + fmt.Printf("Unparseable Transaction %s\n", pendingTxn.Txn.ID().String()) continue } fmt.Printf("%s\n", string(pendingTxnStr)) diff --git a/cmd/loadgenerator/main.go b/cmd/loadgenerator/main.go index 37e1134719..598d837fac 100644 --- a/cmd/loadgenerator/main.go +++ b/cmd/loadgenerator/main.go @@ -272,7 +272,7 @@ func generateTransactions(restClient client.RestClient, cfg config, privateKeys go func(base int) { defer sendWaitGroup.Done() for x := base; x < sendSize; x += nroutines { - _, err2 := restClient.SendRawTransaction(txns[x]) + _, err2 := restClient.SendRawTransactionV2(txns[x]) if err2 != nil { if strings.Contains(err2.Error(), "txn dead") || strings.Contains(err2.Error(), "below threshold") { break diff --git a/daemon/algod/api/client/restClient.go b/daemon/algod/api/client/restClient.go index 2bece32a68..ed649db173 100644 --- a/daemon/algod/api/client/restClient.go +++ b/daemon/algod/api/client/restClient.go @@ -48,7 +48,8 @@ const ( // rawRequestPaths is a set of paths where the body should not be urlencoded var rawRequestPaths = map[string]bool{ - "/v1/transactions": true, + "/v1/transactions": true, // Deprecated path + "/v2/transactions": true, "/v2/teal/dryrun": true, "/v2/teal/compile": true, "/v2/participation": true, @@ -116,7 +117,33 @@ func extractError(resp *http.Response) error { } errorBuf, _ := io.ReadAll(resp.Body) // ignore returned error - errorString := filterASCII(string(errorBuf)) + var errorJSON generatedV2.ErrorResponse + decodeErr := json.Unmarshal(errorBuf, &errorJSON) + + var errorString string + if decodeErr == nil { + if errorJSON.Data == nil { + // There's no additional data, so let's just use the message + errorString = errorJSON.Message + } else { + // There's additional data, so let's re-encode the JSON response to show everything. + // We do this because the original response is likely encoded with escapeHTML=true, but + // since this isn't a webpage that extra encoding is not preferred. + var buffer strings.Builder + enc := json.NewEncoder(&buffer) + enc.SetEscapeHTML(false) + encErr := enc.Encode(errorJSON) + if encErr != nil { + // This really shouldn't happen, but if it does let's default to errorBuff + errorString = string(errorBuf) + } else { + errorString = buffer.String() + } + } + } else { + errorString = string(errorBuf) + } + errorString = filterASCII(errorString) if resp.StatusCode == http.StatusUnauthorized { apiToken := resp.Request.Header.Get(authHeader) @@ -134,6 +161,11 @@ func stripTransaction(tx string) string { return tx } +// RawResponse is fulfilled by responses that should not be decoded as json +type RawResponse interface { + SetBytes([]byte) +} + // submitForm is a helper used for submitting (ex.) GETs and POSTs to the server func (client RestClient) submitForm(response interface{}, path string, request interface{}, requestMethod string, encodeJSON bool, decodeJSON bool) error { var err error @@ -196,9 +228,9 @@ func (client RestClient) submitForm(response interface{}, path string, request i } // Response must implement RawResponse - raw, ok := response.(v1.RawResponse) + raw, ok := response.(RawResponse) if !ok { - return fmt.Errorf("can only decode raw response into type implementing v1.RawResponse") + return fmt.Errorf("can only decode raw response into type implementing RawResponse") } bodyBytes, err := io.ReadAll(resp.Body) @@ -216,8 +248,8 @@ func (client RestClient) get(response interface{}, path string, request interfac } // getRaw behaves identically to get but doesn't json decode the response, and -// the response must implement the v1.RawResponse interface -func (client RestClient) getRaw(response v1.RawResponse, path string, request interface{}) error { +// the response must implement the RawResponse interface +func (client RestClient) getRaw(response RawResponse, path string, request interface{}) error { return client.submitForm(response, path, request, "GET", false /* encodeJSON */, false /* decodeJSON */) } @@ -248,19 +280,6 @@ func (client RestClient) HealthCheck() error { return client.get(nil, "/health", nil) } -func fillNodeStatusResponse(nodeStatus v1.NodeStatus) generatedV2.NodeStatusResponse { - return generatedV2.NodeStatusResponse{ - LastRound: nodeStatus.LastRound, - LastVersion: nodeStatus.LastVersion, - NextVersion: nodeStatus.NextVersion, - NextVersionRound: nodeStatus.NextVersionRound, - NextVersionSupported: nodeStatus.NextVersionSupported, - TimeSinceLastRound: uint64(nodeStatus.TimeSinceLastRound), - CatchupTime: uint64(nodeStatus.CatchupTime), - StoppedAtUnsupportedRound: nodeStatus.StoppedAtUnsupportedRound, - } -} - // StatusAfterBlock waits for a block to occur then returns the StatusResponse after that block // blocks on the node end // Not supported @@ -270,13 +289,23 @@ func (client RestClient) StatusAfterBlock(blockNum uint64) (response generatedV2 } type pendingTransactionsParams struct { - Max uint64 `url:"max"` + Max uint64 `url:"max"` + Format string `url:"format"` } // GetPendingTransactions asks algod for a snapshot of current pending txns on the node, bounded by maxTxns. // If maxTxns = 0, fetches as many transactions as possible. -func (client RestClient) GetPendingTransactions(maxTxns uint64) (response v1.PendingTransactions, err error) { - err = client.get(&response, fmt.Sprintf("/v1/transactions/pending"), pendingTransactionsParams{maxTxns}) +func (client RestClient) GetPendingTransactions(maxTxns uint64) (response generatedV2.PendingTransactionsResponse, err error) { + err = client.get(&response, "/v2/transactions/pending", pendingTransactionsParams{Max: maxTxns, Format: "json"}) + return +} + +// GetRawPendingTransactions gets the raw encoded msgpack transactions. +// If maxTxns = 0, fetches as many transactions as possible. +func (client RestClient) GetRawPendingTransactions(maxTxns uint64) (response []byte, err error) { + var blob Blob + err = client.getRaw(&blob, "/v2/transactions/pending", pendingTransactionsParams{maxTxns, "msgpack"}) + response = blob return } @@ -288,8 +317,8 @@ func (client RestClient) Versions() (response common.Version, err error) { } // LedgerSupply gets the supply details for the specified node's Ledger -func (client RestClient) LedgerSupply() (response v1.Supply, err error) { - err = client.get(&response, "/v1/ledger/supply", nil) +func (client RestClient) LedgerSupply() (response generatedV2.SupplyResponse, err error) { + err = client.get(&response, "/v2/ledger/supply", nil) return } @@ -332,24 +361,42 @@ type accountInformationParams struct { // TransactionsByAddr returns all transactions for a PK [addr] in the [first, // last] rounds range. +// Deprecated: This function is only used in internal tests (restClient_test.go) func (client RestClient) TransactionsByAddr(addr string, first, last, max uint64) (response v1.TransactionList, err error) { err = client.get(&response, fmt.Sprintf("/v1/account/%s/transactions", addr), transactionsByAddrParams{first, last, max}) return } // PendingTransactionsByAddr returns all the pending transactions for a PK [addr]. +// Deprecated: Use v2 API func (client RestClient) PendingTransactionsByAddr(addr string, max uint64) (response v1.PendingTransactions, err error) { err = client.get(&response, fmt.Sprintf("/v1/account/%s/transactions/pending", addr), pendingTransactionsByAddrParams{max}) return } +// PendingTransactionsByAddrV2 returns all the pending transactions for an addr. +func (client RestClient) PendingTransactionsByAddrV2(addr string, max uint64) (response generatedV2.PendingTransactionsResponse, err error) { + err = client.get(&response, fmt.Sprintf("/v2/accounts/%s/transactions/pending", addr), pendingTransactionsByAddrParams{max}) + return +} + +// RawPendingTransactionsByAddrV2 returns all the pending transactions for an addr in raw msgpack format. +func (client RestClient) RawPendingTransactionsByAddrV2(addr string, max uint64) (response []byte, err error) { + var blob Blob + err = client.getRaw(&blob, fmt.Sprintf("/v2/accounts/%s/transactions/pending", addr), pendingTransactionsParams{max, "msgpack"}) + response = blob + return +} + // AssetInformation gets the AssetInformationResponse associated with the passed asset index +// Deprecated: Use v2 API func (client RestClient) AssetInformation(index uint64) (response v1.AssetParams, err error) { err = client.get(&response, fmt.Sprintf("/v1/asset/%d", index), nil) return } // Assets gets up to max assets with maximum asset index assetIdx +// Deprecated: Use v2 API func (client RestClient) Assets(assetIdx, max uint64) (response v1.AssetList, err error) { err = client.get(&response, "/v1/assets", assetsParams{assetIdx, max}) return @@ -369,6 +416,7 @@ func (client RestClient) ApplicationInformation(index uint64) (response generate } // AccountInformation also gets the AccountInformationResponse associated with the passed address +// Deprecated: Use v2 API func (client RestClient) AccountInformation(address string) (response v1.Account, err error) { err = client.get(&response, fmt.Sprintf("/v1/account/%s", address), nil) return @@ -386,7 +434,7 @@ func (client RestClient) AccountInformationV2(address string, includeCreatables return } -// Blob represents arbitrary blob of data satisfying v1.RawResponse interface +// Blob represents arbitrary blob of data satisfying RawResponse interface type Blob []byte // SetBytes fulfills the RawResponse interface on Blob @@ -403,6 +451,7 @@ func (client RestClient) RawAccountInformationV2(address string) (response []byt } // TransactionInformation gets information about a specific transaction involving a specific account +// Deprecated func (client RestClient) TransactionInformation(accountAddress, transactionID string) (response v1.Transaction, err error) { transactionID = stripTransaction(transactionID) err = client.get(&response, fmt.Sprintf("/v1/account/%s/transaction/%s", accountAddress, transactionID), nil) @@ -418,6 +467,7 @@ func (client RestClient) TransactionInformation(accountAddress, transactionID st // // Or the transaction may have happened sufficiently long ago that the // node no longer remembers it, and this will return an error. +// Deprecated func (client RestClient) PendingTransactionInformation(transactionID string) (response v1.Transaction, err error) { transactionID = stripTransaction(transactionID) err = client.get(&response, fmt.Sprintf("/v1/transactions/pending/%s", transactionID), nil) @@ -432,6 +482,15 @@ func (client RestClient) PendingTransactionInformationV2(transactionID string) ( return } +// RawPendingTransactionInformationV2 gets information about a recently issued transaction in msgpack encoded bytes. +func (client RestClient) RawPendingTransactionInformationV2(transactionID string) (response []byte, err error) { + transactionID = stripTransaction(transactionID) + var blob Blob + err = client.getRaw(&blob, fmt.Sprintf("/v2/transactions/pending/%s", transactionID), rawFormat{Format: "msgpack"}) + response = blob + return +} + // AccountApplicationInformation gets account information about a given app. func (client RestClient) AccountApplicationInformation(accountAddress string, applicationID uint64) (response generatedV2.AccountApplicationResponse, err error) { err = client.get(&response, fmt.Sprintf("/v2/accounts/%s/applications/%d", accountAddress, applicationID), nil) @@ -461,24 +520,40 @@ func (client RestClient) RawAccountAssetInformation(accountAddress string, asset } // SuggestedFee gets the recommended transaction fee from the node +// Deprecated func (client RestClient) SuggestedFee() (response v1.TransactionFee, err error) { err = client.get(&response, "/v1/transactions/fee", nil) return } // SuggestedParams gets the suggested transaction parameters +// Deprecated func (client RestClient) SuggestedParams() (response v1.TransactionParams, err error) { err = client.get(&response, "/v1/transactions/params", nil) return } +// SuggestedParamsV2 gets the suggested transaction parameters +func (client RestClient) SuggestedParamsV2() (response generatedV2.TransactionParametersResponse, err error) { + err = client.get(&response, "/v2/transactions/params", nil) + return +} + // SendRawTransaction gets a SignedTxn and broadcasts it to the network +// Deprecated func (client RestClient) SendRawTransaction(txn transactions.SignedTxn) (response v1.TransactionID, err error) { err = client.post(&response, "/v1/transactions", protocol.Encode(&txn)) return } +// SendRawTransactionV2 gets a SignedTxn and broadcasts it to the network +func (client RestClient) SendRawTransactionV2(txn transactions.SignedTxn) (response generatedV2.PostTransactionsResponse, err error) { + err = client.post(&response, "/v2/transactions", protocol.Encode(&txn)) + return +} + // SendRawTransactionGroup gets a SignedTxn group and broadcasts it to the network +// Deprecated func (client RestClient) SendRawTransactionGroup(txgroup []transactions.SignedTxn) error { // response is not terribly useful: it's the txid of the first transaction, // which can be computed by the client anyway.. @@ -491,9 +566,22 @@ func (client RestClient) SendRawTransactionGroup(txgroup []transactions.SignedTx return client.post(&response, "/v1/transactions", enc) } +// SendRawTransactionGroupV2 gets a SignedTxn group and broadcasts it to the network +func (client RestClient) SendRawTransactionGroupV2(txgroup []transactions.SignedTxn) error { + // response is not terribly useful: it's the txid of the first transaction, + // which can be computed by the client anyway.. + var enc []byte + for _, tx := range txgroup { + enc = append(enc, protocol.Encode(&tx)...) + } + + var response generatedV2.PostTransactionsResponse + return client.post(&response, "/v2/transactions", enc) +} + // Block gets the block info for the given round -func (client RestClient) Block(round uint64) (response v1.Block, err error) { - err = client.get(&response, fmt.Sprintf("/v1/block/%d", round), nil) +func (client RestClient) Block(round uint64) (response generatedV2.BlockResponse, err error) { + err = client.get(&response, fmt.Sprintf("/v2/blocks/%d", round), nil) return } @@ -599,6 +687,12 @@ func (client RestClient) RawDryrun(data []byte) (response []byte, err error) { return } +// StateProofs gets a state proof that covers a given round +func (client RestClient) StateProofs(round uint64) (response generatedV2.StateProofResponse, err error) { + err = client.get(&response, fmt.Sprintf("/v2/stateproofs/%d", round), nil) + return +} + // LightBlockHeaderProof gets a Merkle proof for the light block header of a given round. func (client RestClient) LightBlockHeaderProof(round uint64) (response generatedV2.LightBlockHeaderProofResponse, err error) { err = client.get(&response, fmt.Sprintf("/v2/blocks/%d/lightheader/proof", round), nil) diff --git a/daemon/algod/api/server/v2/handlers.go b/daemon/algod/api/server/v2/handlers.go index 9c82e0dca4..ef37a518ff 100644 --- a/daemon/algod/api/server/v2/handlers.go +++ b/daemon/algod/api/server/v2/handlers.go @@ -966,7 +966,9 @@ func (v2 *Handlers) TransactionParams(ctx echo.Context) error { return ctx.JSON(http.StatusOK, response) } -type preEncodedTxInfo struct { +// PreEncodedTxInfo represents the PendingTransaction response before it is +// encoded to a format. +type PreEncodedTxInfo struct { AssetIndex *uint64 `codec:"asset-index,omitempty"` AssetClosingAmount *uint64 `codec:"asset-closing-amount,omitempty"` ApplicationIndex *uint64 `codec:"application-index,omitempty"` @@ -980,7 +982,7 @@ type preEncodedTxInfo struct { SenderRewards *uint64 `codec:"sender-rewards,omitempty"` Txn transactions.SignedTxn `codec:"txn"` Logs *[][]byte `codec:"logs,omitempty"` - Inners *[]preEncodedTxInfo `codec:"inner-txns,omitempty"` + Inners *[]PreEncodedTxInfo `codec:"inner-txns,omitempty"` } // PendingTransactionInformation returns a transaction with the specified txID @@ -1012,7 +1014,7 @@ func (v2 *Handlers) PendingTransactionInformation(ctx echo.Context, txid string, } // Encoding wasn't working well without embedding "real" objects. - response := preEncodedTxInfo{ + response := PreEncodedTxInfo{ Txn: txn.Txn, } diff --git a/daemon/algod/api/server/v2/utils.go b/daemon/algod/api/server/v2/utils.go index fc9dbe2f4a..c34561d127 100644 --- a/daemon/algod/api/server/v2/utils.go +++ b/daemon/algod/api/server/v2/utils.go @@ -301,20 +301,20 @@ func convertLogs(txn node.TxnWithStatus) *[][]byte { return logItems } -func convertInners(txn *node.TxnWithStatus) *[]preEncodedTxInfo { - inner := make([]preEncodedTxInfo, len(txn.ApplyData.EvalDelta.InnerTxns)) +func convertInners(txn *node.TxnWithStatus) *[]PreEncodedTxInfo { + inner := make([]PreEncodedTxInfo, len(txn.ApplyData.EvalDelta.InnerTxns)) for i, itxn := range txn.ApplyData.EvalDelta.InnerTxns { inner[i] = convertInnerTxn(&itxn) } return &inner } -func convertInnerTxn(txn *transactions.SignedTxnWithAD) preEncodedTxInfo { +func convertInnerTxn(txn *transactions.SignedTxnWithAD) PreEncodedTxInfo { // This copies from handlers.PendingTransactionInformation, with // simplifications because we have a SignedTxnWithAD rather than // TxnWithStatus, and we know this txn has committed. - response := preEncodedTxInfo{Txn: txn.SignedTxn} + response := PreEncodedTxInfo{Txn: txn.SignedTxn} response.ClosingAmount = &txn.ApplyData.ClosingAmount.Raw response.AssetClosingAmount = &txn.ApplyData.AssetClosingAmount diff --git a/libgoal/libgoal.go b/libgoal/libgoal.go index a7cdde4ea1..72272fd2a4 100644 --- a/libgoal/libgoal.go +++ b/libgoal/libgoal.go @@ -61,7 +61,7 @@ type Client struct { cacheDir string consensus config.ConsensusProtocols - suggestedParamsCache v1.TransactionParams + suggestedParamsCache generatedV2.TransactionParametersResponse suggestedParamsExpire time.Time suggestedParamsMaxAge time.Duration } @@ -493,7 +493,7 @@ func (c *Client) signAndBroadcastTransactionWithWallet(walletHandle, pw []byte, return transactions.Transaction{}, err } - _, err = algod.SendRawTransaction(stx) + _, err = algod.SendRawTransactionV2(stx) if err != nil { return transactions.Transaction{}, err } @@ -617,7 +617,7 @@ func (c *Client) ConstructPayment(from, to string, fee, amount uint64, note []by tx.PaymentTxnFields.CloseRemainderTo = closeToAddr } - tx.Header.GenesisID = params.GenesisID + tx.Header.GenesisID = params.GenesisId // Check if the protocol supports genesis hash if cp.SupportGenesisHash { @@ -649,6 +649,7 @@ func (c *Client) Status() (resp generatedV2.NodeStatusResponse, err error) { } // AccountInformation takes an address and returns its information +// Deprecated func (c *Client) AccountInformation(account string) (resp v1.Account, err error) { algod, err := c.ensureAlgodClient() if err == nil { @@ -724,6 +725,7 @@ func (c *Client) AccountData(account string) (accountData basics.AccountData, er } // AssetInformation takes an asset's index and returns its information +// Deprecated: Use AssetInformationV2 func (c *Client) AssetInformation(index uint64) (resp v1.AssetParams, err error) { algod, err := c.ensureAlgodClient() if err == nil { @@ -776,6 +778,7 @@ func (c *Client) ApplicationInformation(index uint64) (resp generatedV2.Applicat } // TransactionInformation takes an address and associated txid and return its information +// Deprecated: Use PendingTransactionInformationV2 func (c *Client) TransactionInformation(addr, txid string) (resp v1.Transaction, err error) { algod, err := c.ensureAlgodClient() if err == nil { @@ -786,6 +789,7 @@ func (c *Client) TransactionInformation(addr, txid string) (resp v1.Transaction, // PendingTransactionInformation returns information about a recently issued // transaction based on its txid. +// Deprecated: Use PendingTransactionInformationV2 func (c *Client) PendingTransactionInformation(txid string) (resp v1.Transaction, err error) { algod, err := c.ensureAlgodClient() if err == nil { @@ -804,8 +808,24 @@ func (c *Client) PendingTransactionInformationV2(txid string) (resp generatedV2. return } +// ParsedPendingTransaction takes a txid and returns the parsed PendingTransaction response. +func (c *Client) ParsedPendingTransaction(txid string) (txn v2.PreEncodedTxInfo, err error) { + algod, err := c.ensureAlgodClient() + if err == nil { + var resp []byte + resp, err = algod.RawPendingTransactionInformationV2(txid) + if err == nil { + err = protocol.DecodeReflect(resp, &txn) + if err != nil { + return + } + } + } + return +} + // Block takes a round and returns its block -func (c *Client) Block(round uint64) (resp v1.Block, err error) { +func (c *Client) Block(round uint64) (resp generatedV2.BlockResponse, err error) { algod, err := c.ensureAlgodClient() if err == nil { resp, err = algod.Block(round) @@ -814,7 +834,7 @@ func (c *Client) Block(round uint64) (resp v1.Block, err error) { } // RawBlock takes a round and returns its block -func (c *Client) RawBlock(round uint64) (resp v1.RawBlock, err error) { +func (c *Client) RawBlock(round uint64) (resp []byte, err error) { algod, err := c.ensureAlgodClient() if err == nil { resp, err = algod.RawBlock(round) @@ -822,24 +842,31 @@ func (c *Client) RawBlock(round uint64) (resp v1.RawBlock, err error) { return } -// BookkeepingBlock takes a round and returns its block -func (c *Client) BookkeepingBlock(round uint64) (block bookkeeping.Block, err error) { +// EncodedBlockCert takes a round and returns its parsed block and certificate +func (c *Client) EncodedBlockCert(round uint64) (blockCert rpcs.EncodedBlockCert, err error) { algod, err := c.ensureAlgodClient() if err == nil { var resp []byte resp, err = algod.RawBlock(round) if err == nil { - var b rpcs.EncodedBlockCert - err = protocol.DecodeReflect(resp, &b) + err = protocol.DecodeReflect(resp, &blockCert) if err != nil { return } - block = b.Block } } return } +// BookkeepingBlock takes a round and returns its block +func (c *Client) BookkeepingBlock(round uint64) (block bookkeeping.Block, err error) { + blockCert, err := c.EncodedBlockCert(round) + if err == nil { + return blockCert.Block, nil + } + return +} + // HealthCheck returns an error if something is wrong func (c *Client) HealthCheck() error { algod, err := c.ensureAlgodClient() @@ -860,7 +887,7 @@ func (c *Client) WaitForRound(round uint64) (resp generatedV2.NodeStatusResponse // GetBalance takes an address and returns its total balance; if the address doesn't exist, it returns 0. func (c *Client) GetBalance(address string) (uint64, error) { - resp, err := c.AccountInformation(address) + resp, err := c.AccountInformationV2(address, false) if err != nil { return 0, err } @@ -877,7 +904,7 @@ func (c Client) AlgodVersions() (resp common.Version, err error) { } // LedgerSupply returns the total number of algos in the system -func (c Client) LedgerSupply() (resp v1.Supply, err error) { +func (c Client) LedgerSupply() (resp generatedV2.SupplyResponse, err error) { algod, err := c.ensureAlgodClient() if err == nil { resp, err = algod.LedgerSupply() @@ -902,19 +929,19 @@ func (c Client) CurrentRound() (lastRound uint64, err error) { func (c *Client) SuggestedFee() (fee uint64, err error) { algod, err := c.ensureAlgodClient() if err == nil { - resp, err := algod.SuggestedFee() + params, err := algod.SuggestedParamsV2() if err == nil { - fee = resp.Fee + fee = params.Fee } } return } // SuggestedParams returns the suggested parameters for a new transaction -func (c *Client) SuggestedParams() (params v1.TransactionParams, err error) { +func (c *Client) SuggestedParams() (params generatedV2.TransactionParametersResponse, err error) { algod, err := c.ensureAlgodClient() if err == nil { - params, err = algod.SuggestedParams() + params, err = algod.SuggestedParamsV2() } return } @@ -924,7 +951,7 @@ func (c *Client) SetSuggestedParamsCacheAge(maxAge time.Duration) { c.suggestedParamsMaxAge = maxAge } -func (c *Client) cachedSuggestedParams() (params v1.TransactionParams, err error) { +func (c *Client) cachedSuggestedParams() (params generatedV2.TransactionParametersResponse, err error) { if c.suggestedParamsMaxAge == 0 || time.Now().After(c.suggestedParamsExpire) { params, err = c.SuggestedParams() if err == nil && c.suggestedParamsMaxAge != 0 { @@ -938,7 +965,7 @@ func (c *Client) cachedSuggestedParams() (params v1.TransactionParams, err error // GetPendingTransactions gets a snapshot of current pending transactions on the node. // If maxTxns = 0, fetches as many transactions as possible. -func (c *Client) GetPendingTransactions(maxTxns uint64) (resp v1.PendingTransactions, err error) { +func (c *Client) GetPendingTransactions(maxTxns uint64) (resp generatedV2.PendingTransactionsResponse, err error) { algod, err := c.ensureAlgodClient() if err == nil { resp, err = algod.GetPendingTransactions(maxTxns) @@ -948,10 +975,48 @@ func (c *Client) GetPendingTransactions(maxTxns uint64) (resp v1.PendingTransact // GetPendingTransactionsByAddress gets a snapshot of current pending transactions on the node for the given address. // If maxTxns = 0, fetches as many transactions as possible. -func (c *Client) GetPendingTransactionsByAddress(addr string, maxTxns uint64) (resp v1.PendingTransactions, err error) { +func (c *Client) GetPendingTransactionsByAddress(addr string, maxTxns uint64) (resp generatedV2.PendingTransactionsResponse, err error) { algod, err := c.ensureAlgodClient() if err == nil { - resp, err = algod.PendingTransactionsByAddr(addr, maxTxns) + resp, err = algod.PendingTransactionsByAddrV2(addr, maxTxns) + } + return +} + +// PendingTransactions represents a parsed PendingTransactionsResponse struct. +type PendingTransactions struct { + TopTransactions []transactions.SignedTxn `json:"top-transactions"` + TotalTransactions uint64 `json:"total-transactions"` +} + +// GetParsedPendingTransactions returns the parsed response with pending transactions. +func (c *Client) GetParsedPendingTransactions(maxTxns uint64) (txns PendingTransactions, err error) { + algod, err := c.ensureAlgodClient() + if err == nil { + var resp []byte + resp, err = algod.GetRawPendingTransactions(maxTxns) + if err == nil { + err = protocol.DecodeReflect(resp, &txns) + if err != nil { + return + } + } + } + return +} + +// GetParsedPendingTransactionsByAddress returns the parsed response with pending transactions by address. +func (c *Client) GetParsedPendingTransactionsByAddress(addr string, maxTxns uint64) (txns PendingTransactions, err error) { + algod, err := c.ensureAlgodClient() + if err == nil { + var resp []byte + resp, err = algod.RawPendingTransactionsByAddrV2(addr, maxTxns) + if err == nil { + err = protocol.DecodeReflect(resp, &txns) + if err != nil { + return + } + } } return } @@ -1034,7 +1099,7 @@ func (c *Client) ExportKey(walletHandle []byte, password, account string) (resp // ConsensusParams returns the consensus parameters for the protocol active at the specified round func (c *Client) ConsensusParams(round uint64) (consensus config.ConsensusParams, err error) { - block, err := c.Block(round) + block, err := c.BookkeepingBlock(round) if err != nil { return } @@ -1196,11 +1261,11 @@ func MakeDryrunStateGenerated(client Client, txnOrStxnOrSlice interface{}, other if dr.Round, err = client.CurrentRound(); err != nil { return } - var b v1.Block - if b, err = client.Block(dr.Round); err != nil { + var b bookkeeping.Block + if b, err = client.BookkeepingBlock(dr.Round); err != nil { return } - dr.LatestTimestamp = uint64(b.Timestamp) + dr.LatestTimestamp = uint64(b.BlockHeader.TimeStamp) } } return diff --git a/libgoal/transactions.go b/libgoal/transactions.go index fb788f0249..2f1861b833 100644 --- a/libgoal/transactions.go +++ b/libgoal/transactions.go @@ -24,7 +24,6 @@ import ( "github.com/algorand/go-algorand/crypto" "github.com/algorand/go-algorand/crypto/merklesignature" "github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated" - v1 "github.com/algorand/go-algorand/daemon/algod/api/spec/v1" "github.com/algorand/go-algorand/data/account" "github.com/algorand/go-algorand/data/basics" "github.com/algorand/go-algorand/data/transactions" @@ -166,11 +165,11 @@ func (c *Client) BroadcastTransaction(stx transactions.SignedTxn) (txid string, if err != nil { return } - resp, err := algod.SendRawTransaction(stx) + resp, err := algod.SendRawTransactionV2(stx) if err != nil { return } - return resp.TxID, nil + return resp.TxId, nil } // BroadcastTransactionGroup broadcasts a signed transaction group to the network using algod @@ -179,7 +178,7 @@ func (c *Client) BroadcastTransactionGroup(txgroup []transactions.SignedTxn) err if err != nil { return err } - return algod.SendRawTransactionGroup(txgroup) + return algod.SendRawTransactionGroupV2(txgroup) } // SignAndBroadcastTransaction signs the unsigned transaction with keys from the default wallet, and broadcasts it @@ -274,7 +273,7 @@ func (c *Client) MakeRegistrationTransactionWithGenesisID(part account.Participa basics.Round(txnLastValid), leaseBytes, includeStateProofKeys) - goOnlineTx.Header.GenesisID = params.GenesisID + goOnlineTx.Header.GenesisID = params.GenesisId // Check if the protocol supports genesis hash if config.Consensus[protocol.ConsensusFuture].SupportGenesisHash { @@ -706,42 +705,54 @@ func (c *Client) MakeUnsignedAssetDestroyTx(index uint64) (transactions.Transact func (c *Client) MakeUnsignedAssetConfigTx(creator string, index uint64, newManager *string, newReserve *string, newFreeze *string, newClawback *string) (transactions.Transaction, error) { var tx transactions.Transaction var err error - var ok bool // If the creator was passed in blank, look up asset info by index - var params v1.AssetParams + var params generated.AssetParams if creator == "" { - params, err = c.AssetInformation(index) + asset, err := c.AssetInformationV2(index) if err != nil { return tx, err } + params = asset.Params } else { // Fetch the current state, to fill in as a template - current, err := c.AccountInformation(creator) + current, err := c.AccountInformationV2(creator, true) if err != nil { return tx, err } - params, ok = current.AssetParams[index] - if !ok { + // Search for the asset index in the CreatedAssets array + assetFound := false + if current.CreatedAssets != nil { + for _, asset := range *current.CreatedAssets { + if index == asset.Index { + params = asset.Params + assetFound = true + break + } + } + if !assetFound { + return tx, fmt.Errorf("asset ID %d not found in account %s", index, creator) + } + } else { return tx, fmt.Errorf("asset ID %d not found in account %s", index, creator) } } if newManager == nil { - newManager = ¶ms.ManagerAddr + newManager = params.Manager } if newReserve == nil { - newReserve = ¶ms.ReserveAddr + newReserve = params.Reserve } if newFreeze == nil { - newFreeze = ¶ms.FreezeAddr + newFreeze = params.Freeze } if newClawback == nil { - newClawback = ¶ms.ClawbackAddr + newClawback = params.Clawback } tx.Type = protocol.AssetConfigTx diff --git a/shared/pingpong/accounts.go b/shared/pingpong/accounts.go index 610a0e9b52..ad5543c2dc 100644 --- a/shared/pingpong/accounts.go +++ b/shared/pingpong/accounts.go @@ -30,7 +30,7 @@ import ( "github.com/algorand/go-algorand/config" "github.com/algorand/go-algorand/crypto" "github.com/algorand/go-algorand/crypto/passphrase" - v1 "github.com/algorand/go-algorand/daemon/algod/api/spec/v1" + "github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated" algodAcct "github.com/algorand/go-algorand/data/account" "github.com/algorand/go-algorand/data/basics" "github.com/algorand/go-algorand/data/transactions" @@ -163,10 +163,10 @@ func (pps *WorkerState) ensureAccounts(ac *libgoal.Client) (err error) { pps.cinfo.OptIns = make(map[uint64][]string, pps.cfg.NumAsset+pps.cfg.NumApp) } if pps.cinfo.AssetParams == nil { - pps.cinfo.AssetParams = make(map[uint64]v1.AssetParams, pps.cfg.NumAsset) + pps.cinfo.AssetParams = make(map[uint64]generated.AssetParams, pps.cfg.NumAsset) } if pps.cinfo.AppParams == nil { - pps.cinfo.AppParams = make(map[uint64]v1.AppParams, pps.cfg.NumApp) + pps.cinfo.AppParams = make(map[uint64]generated.ApplicationParams, pps.cfg.NumApp) } sources := make([]<-chan *crypto.SignatureSecrets, 0, 2) @@ -197,9 +197,7 @@ func (pps *WorkerState) ensureAccounts(ac *libgoal.Client) (err error) { srcAcctPresent = true } - // TODO: switch to v2 API - //ai, err := ac.AccountInformationV2(addr, false) - ai, err := ac.AccountInformation(addr) + ai, err := ac.AccountInformationV2(addr, true) if err != nil { return err } @@ -247,36 +245,48 @@ func (pps *WorkerState) ensureAccounts(ac *libgoal.Client) (err error) { return } -func (pps *WorkerState) integrateAccountInfo(addr string, ppa *pingPongAccount, ai v1.Account) { +func (pps *WorkerState) integrateAccountInfo(addr string, ppa *pingPongAccount, ai generated.Account) { ppa.balance = ai.Amount // assets this account has created - for assetID, ap := range ai.AssetParams { - pps.cinfo.OptIns[assetID] = uniqueAppend(pps.cinfo.OptIns[assetID], addr) - pps.cinfo.AssetParams[assetID] = ap + if ai.CreatedAssets != nil { + for _, ap := range *ai.CreatedAssets { + assetID := ap.Index + pps.cinfo.OptIns[assetID] = uniqueAppend(pps.cinfo.OptIns[assetID], addr) + pps.cinfo.AssetParams[assetID] = ap.Params + } } // assets held - for assetID, holding := range ai.Assets { - pps.cinfo.OptIns[assetID] = uniqueAppend(pps.cinfo.OptIns[assetID], addr) - if ppa.holdings == nil { - ppa.holdings = make(map[uint64]uint64) + if ai.Assets != nil { + for _, holding := range *ai.Assets { + assetID := holding.AssetId + pps.cinfo.OptIns[assetID] = uniqueAppend(pps.cinfo.OptIns[assetID], addr) + if ppa.holdings == nil { + ppa.holdings = make(map[uint64]uint64) + } + ppa.holdings[assetID] = holding.Amount } - ppa.holdings[assetID] = holding.Amount } // apps created by this account - for appID, ap := range ai.AppParams { - pps.cinfo.OptIns[appID] = uniqueAppend(pps.cinfo.OptIns[appID], addr) - pps.cinfo.AppParams[appID] = ap + if ai.CreatedApps != nil { + for _, ap := range *ai.CreatedApps { + appID := ap.Id + pps.cinfo.OptIns[appID] = uniqueAppend(pps.cinfo.OptIns[appID], addr) + pps.cinfo.AppParams[appID] = ap.Params + } } // apps opted into - for appID := range ai.AppLocalStates { - pps.cinfo.OptIns[appID] = uniqueAppend(pps.cinfo.OptIns[appID], addr) + if ai.AppsLocalState != nil { + for _, localState := range *ai.AppsLocalState { + appID := localState.Id + pps.cinfo.OptIns[appID] = uniqueAppend(pps.cinfo.OptIns[appID], addr) + } } } type assetopti struct { assetID uint64 - params v1.AssetParams // TODO: switch to v2 API - optins []string // addr strings + params generated.AssetParams + optins []string // addr strings } type assetSet []assetopti @@ -301,7 +311,7 @@ func (as *assetSet) Swap(a, b int) { func (pps *WorkerState) prepareAssets(client *libgoal.Client) (err error) { if pps.cinfo.AssetParams == nil { - pps.cinfo.AssetParams = make(map[uint64]v1.AssetParams) + pps.cinfo.AssetParams = make(map[uint64]generated.AssetParams) } if pps.cinfo.OptIns == nil { pps.cinfo.OptIns = make(map[uint64][]string) @@ -326,7 +336,7 @@ func (pps *WorkerState) prepareAssets(client *libgoal.Client) (err error) { sort.Sort(&ta) if len(assets) > int(pps.cfg.NumAsset) { assets = assets[:pps.cfg.NumAsset] - nap := make(map[uint64]v1.AssetParams, pps.cfg.NumAsset) + nap := make(map[uint64]generated.AssetParams, pps.cfg.NumAsset) for _, asset := range assets { nap[asset.assetID] = asset.params } @@ -407,30 +417,35 @@ func (pps *WorkerState) makeNewAssets(client *libgoal.Client) (err error) { newAssetAddrs[addr] = acct } // wait for new assets to be created, fetch account data for them - newAssets := make(map[uint64]v1.AssetParams, assetsNeeded) + newAssets := make(map[uint64]generated.AssetParams, assetsNeeded) timeout := time.Now().Add(10 * time.Second) for len(newAssets) < assetsNeeded { for addr, acct := range newAssetAddrs { - // TODO: switch to v2 API - ai, err := client.AccountInformation(addr) + ai, err := client.AccountInformationV2(addr, true) if err != nil { fmt.Printf("Warning: cannot lookup source account after assets creation") time.Sleep(1 * time.Second) continue } - for assetID, ap := range ai.AssetParams { - pps.cinfo.OptIns[assetID] = uniqueAppend(pps.cinfo.OptIns[assetID], addr) - _, has := pps.cinfo.AssetParams[assetID] - if !has { - newAssets[assetID] = ap + if ai.CreatedAssets != nil { + for _, ap := range *ai.CreatedAssets { + assetID := ap.Index + pps.cinfo.OptIns[assetID] = uniqueAppend(pps.cinfo.OptIns[assetID], addr) + _, has := pps.cinfo.AssetParams[assetID] + if !has { + newAssets[assetID] = ap.Params + } } } - for assetID, holding := range ai.Assets { - pps.cinfo.OptIns[assetID] = uniqueAppend(pps.cinfo.OptIns[assetID], addr) - if acct.holdings == nil { - acct.holdings = make(map[uint64]uint64) + if ai.Assets != nil { + for _, holding := range *ai.Assets { + assetID := holding.AssetId + pps.cinfo.OptIns[assetID] = uniqueAppend(pps.cinfo.OptIns[assetID], addr) + if acct.holdings == nil { + acct.holdings = make(map[uint64]uint64) + } + acct.holdings[assetID] = holding.Amount } - acct.holdings[assetID] = holding.Amount } } if time.Now().After(timeout) { @@ -677,7 +692,7 @@ func getProto(client *libgoal.Client) (config.ConsensusParams, error) { // ensure that cfg.NumPartAccounts have cfg.NumAppOptIn opted in selecting from cfg.NumApp func (pps *WorkerState) prepareApps(client *libgoal.Client) (err error) { if pps.cinfo.AppParams == nil { - pps.cinfo.AppParams = make(map[uint64]v1.AppParams) + pps.cinfo.AppParams = make(map[uint64]generated.ApplicationParams) } if pps.cinfo.OptIns == nil { @@ -732,27 +747,28 @@ func (pps *WorkerState) prepareApps(client *libgoal.Client) (err error) { // update pps.cinfo.AppParams to ensure newly created apps are present for _, addr := range newAppAddrs { - var ai v1.Account + var ai generated.Account for { - ai, err = client.AccountInformation(addr) + ai, err = client.AccountInformationV2(addr, true) if err != nil { fmt.Printf("Warning, cannot lookup source account") return } - if len(ai.AppParams) >= appsPerAddr[addr] { + if ai.CreatedApps != nil && len(*ai.CreatedApps) >= appsPerAddr[addr] { break } waitForNextRoundOrSleep(client, 500*time.Millisecond) // TODO : if we fail here for too long, we should re-create new accounts, etc. } - ai, err = client.AccountInformation(addr) + ai, err = client.AccountInformationV2(addr, true) if err != nil { return } - for appID, ap := range ai.AppParams { + for _, ap := range *ai.CreatedApps { + appID := ap.Id pps.cinfo.OptIns[appID] = uniqueAppend(pps.cinfo.OptIns[appID], addr) - pps.cinfo.AppParams[appID] = ap + pps.cinfo.AppParams[appID] = ap.Params } } diff --git a/shared/pingpong/pingpong.go b/shared/pingpong/pingpong.go index e0ee6812a7..6090b4a312 100644 --- a/shared/pingpong/pingpong.go +++ b/shared/pingpong/pingpong.go @@ -32,7 +32,7 @@ import ( "github.com/algorand/go-algorand/config" "github.com/algorand/go-algorand/crypto" - v1 "github.com/algorand/go-algorand/daemon/algod/api/spec/v1" + "github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated" "github.com/algorand/go-algorand/data/basics" "github.com/algorand/go-algorand/data/transactions" "github.com/algorand/go-algorand/data/transactions/logic" @@ -42,8 +42,8 @@ import ( // CreatablesInfo has information about created assets, apps and opting in type CreatablesInfo struct { - AssetParams map[uint64]v1.AssetParams - AppParams map[uint64]v1.AppParams + AssetParams map[uint64]generated.AssetParams + AppParams map[uint64]generated.ApplicationParams OptIns map[uint64][]string } @@ -267,7 +267,7 @@ func (pps *WorkerState) scheduleAction() bool { pps.refreshPos = 0 } addr := pps.refreshAddrs[pps.refreshPos] - ai, err := pps.client.AccountInformation(addr) + ai, err := pps.client.AccountInformationV2(addr, true) if err == nil { ppa := pps.accounts[addr] @@ -442,19 +442,19 @@ func (pps *WorkerState) sendPaymentFromSourceAccount(client *libgoal.Client, to } // waitPendingTransactions waits until all the pending transactions coming from the given -// accounts map have been cleared out of the transaction pool. A prerequesite for this is that +// accounts map have been cleared out of the transaction pool. A prerequisite for this is that // there is no other source who might be generating transactions that would come from these account // addresses. func waitPendingTransactions(accounts []string, client *libgoal.Client) error { for _, from := range accounts { repeat: - pendingTxns, err := client.GetPendingTransactionsByAddress(from, 0) + pendingTxns, err := client.GetParsedPendingTransactionsByAddress(from, 0) if err != nil { fmt.Printf("failed to check pending transaction pool status : %v\n", err) return err } - for _, txn := range pendingTxns.TruncatedTxns.Transactions { - if txn.From != from { + for _, txn := range pendingTxns.TopTransactions { + if txn.Txn.Sender.String() != from { // we found a transaction where the receiver was the given account. We don't // care about these. continue diff --git a/test/e2e-go/cli/goal/clerk_test.go b/test/e2e-go/cli/goal/clerk_test.go index 851eb19134..9f112fbeba 100644 --- a/test/e2e-go/cli/goal/clerk_test.go +++ b/test/e2e-go/cli/goal/clerk_test.go @@ -71,7 +71,7 @@ func TestClerkSendNoteEncoding(t *testing.T) { tx1, err := fixture.WaitForConfirmedTxn(status.LastRound+i, account, txID) if err == nil { foundTx1 = true - a.Equal(noteText, string(tx1.Note)) + a.Equal(noteText, string(tx1.Txn.Txn.Note)) } } if !foundTx2 { @@ -80,7 +80,7 @@ func TestClerkSendNoteEncoding(t *testing.T) { foundTx2 = true // If the note matches our original text, then goal is still expecting strings encoded // with StdEncoding.EncodeToString() when using --noteb64 parameter - a.Equal(originalNoteb64Text, string(tx2.Note), "goal should decode noteb64 with base64.StdEncoding") + a.Equal(originalNoteb64Text, string(tx2.Txn.Txn.Note), "goal should decode noteb64 with base64.StdEncoding") } } } diff --git a/test/e2e-go/features/accountPerf/sixMillion_test.go b/test/e2e-go/features/accountPerf/sixMillion_test.go index 679d2728a2..f41ae8b55a 100644 --- a/test/e2e-go/features/accountPerf/sixMillion_test.go +++ b/test/e2e-go/features/accountPerf/sixMillion_test.go @@ -85,7 +85,7 @@ func broadcastTransactions(queueWg *sync.WaitGroup, fixture *fixtures.RestClient if stxn == nil { break } - _, err := fixture.AlgodClient.SendRawTransaction(*stxn) + _, err := fixture.AlgodClient.SendRawTransactionV2(*stxn) if err != nil { handleError(err, "Error broadcastTransactions", errChan) } @@ -101,7 +101,7 @@ func broadcastTransactionGroups(queueWg *sync.WaitGroup, fixture *fixtures.RestC } var err error - err = fixture.AlgodClient.SendRawTransactionGroup(stxns) + err = fixture.AlgodClient.SendRawTransactionGroupV2(stxns) if err != nil { handleError(err, "Error broadcastTransactionGroups", errChan) } @@ -239,7 +239,7 @@ func test5MAssets(t *testing.T, scenario int) { // get the wallet account wAcct := accountList[0].Address - suggestedParams, err := fixture.AlgodClient.SuggestedParams() + suggestedParams, err := fixture.AlgodClient.SuggestedParamsV2() require.NoError(t, err) var genesisHash crypto.Digest copy(genesisHash[:], suggestedParams.GenesisHash) @@ -249,6 +249,7 @@ func test5MAssets(t *testing.T, scenario int) { ba := generateKeys(1) baseAcct := ba[0] sender, err := basics.UnmarshalChecksumAddress(wAcct) + require.NoError(t, err) satxn := sendAlgoTransaction(t, 0, sender, baseAcct.pk, 1000000000000000, 1, genesisHash) err = signAndBroadcastTransaction(0, &satxn, fixture.LibGoalClient, &fixture) require.NoError(t, err) @@ -1050,7 +1051,7 @@ func signAndBroadcastTransaction( return err } - _, err = fixture.AlgodClient.SendRawTransaction(stxn) + _, err = fixture.AlgodClient.SendRawTransactionV2(stxn) if err != nil { return err } diff --git a/test/e2e-go/features/devmode/devmode_test.go b/test/e2e-go/features/devmode/devmode_test.go index e5c9ab7ead..c356615e9b 100644 --- a/test/e2e-go/features/devmode/devmode_test.go +++ b/test/e2e-go/features/devmode/devmode_test.go @@ -48,13 +48,14 @@ func TestDevMode(t *testing.T) { key := crypto.GenerateSignatureSecrets(crypto.Seed{}) receiver := basics.Address(key.SignatureVerifier) txn := fixture.SendMoneyAndWait(0, 100000, 1000, sender.Address, receiver.String(), "") - firstRound := txn.ConfirmedRound + 1 + require.NotNil(t, txn.ConfirmedRound) + firstRound := *txn.ConfirmedRound + 1 start := time.Now() // 2 transactions should be sent within one normal confirmation time. for i := uint64(0); i < 2; i++ { txn = fixture.SendMoneyAndWait(firstRound+i, 100000, 1000, sender.Address, receiver.String(), "") - require.Equal(t, firstRound+i, txn.FirstRound) + require.Equal(t, firstRound+i, txn.Txn.Txn.FirstValid) } require.True(t, time.Since(start) < 8*time.Second, "Transactions should be quickly confirmed faster than usual.") diff --git a/test/e2e-go/features/participation/onlineOfflineParticipation_test.go b/test/e2e-go/features/participation/onlineOfflineParticipation_test.go index 97ac14e006..7be80c933d 100644 --- a/test/e2e-go/features/participation/onlineOfflineParticipation_test.go +++ b/test/e2e-go/features/participation/onlineOfflineParticipation_test.go @@ -199,14 +199,15 @@ func TestNewAccountCanGoOnlineAndParticipate(t *testing.T) { fixture.WaitForTxnConfirmation(seededRound+maxRoundsToWaitForTxnConfirm, newAccount, onlineTxID) nodeStatus, _ = client.Status() onlineRound := nodeStatus.LastRound - newAccountStatus, err := client.AccountInformation(newAccount) + newAccountStatus, err := client.AccountInformationV2(newAccount, false) a.NoError(err, "client should be able to get information about new account") a.Equal(basics.Online.String(), newAccountStatus.Status, "new account should be online") // transfer the funds and close to the new account amountToSend := richBalance - 3*transactionFee - amountToSendInitial - minAcctBalance txn := fixture.SendMoneyAndWait(onlineRound, amountToSend, transactionFee, richAccount, newAccount, newAccount) - fundedRound := txn.ConfirmedRound + a.NotNil(txn.ConfirmedRound) + fundedRound := *txn.ConfirmedRound nodeStatus, _ = client.Status() params, err := client.ConsensusParams(nodeStatus.LastRound) @@ -308,11 +309,12 @@ func TestAccountGoesOnlineForShortPeriod(t *testing.T) { fixture.AssertValidTxid(onlineTxID) maxRoundsToWaitForTxnConfirm := uint64(5) nodeStatus, err := client.Status() + a.NoError(err) seededRound := nodeStatus.LastRound fixture.WaitForTxnConfirmation(seededRound+maxRoundsToWaitForTxnConfirm, newAccount, onlineTxID) nodeStatus, _ = client.Status() - accountStatus, err := client.AccountInformation(newAccount) + accountStatus, err := client.AccountInformationV2(newAccount, false) a.NoError(err, "client should be able to get information about new account") a.Equal(basics.Online.String(), accountStatus.Status, "new account should be online") } diff --git a/test/e2e-go/features/participation/overlappingParticipationKeys_test.go b/test/e2e-go/features/participation/overlappingParticipationKeys_test.go index 45ac6c97c6..6deb6b14e7 100644 --- a/test/e2e-go/features/participation/overlappingParticipationKeys_test.go +++ b/test/e2e-go/features/participation/overlappingParticipationKeys_test.go @@ -181,7 +181,7 @@ func addParticipationKey(a *require.Assertions, fixture *fixtures.RestClientFixt signedTxn := regTransactions[int(startRound-2)] a.NotEmpty(signedTxn.Sig) - _, err := fixture.GetAlgodClientForController(nc).SendRawTransaction(signedTxn) + _, err := fixture.GetAlgodClientForController(nc).SendRawTransactionV2(signedTxn) a.NoError(err) return signedTxn.Txn.KeyregTxnFields.VotePK, err } diff --git a/test/e2e-go/features/participation/participationExpiration_test.go b/test/e2e-go/features/participation/participationExpiration_test.go index 06b392856f..b75ae1d935 100644 --- a/test/e2e-go/features/participation/participationExpiration_test.go +++ b/test/e2e-go/features/participation/participationExpiration_test.go @@ -64,7 +64,7 @@ func testExpirationAccounts(t *testing.T, fixture *fixtures.RestClientFixture, f a.GreaterOrEqual(newAmt, initialAmt) - newAccountStatus, err := pClient.AccountInformation(sAccount) + newAccountStatus, err := pClient.AccountInformationV2(sAccount, false) a.NoError(err) a.Equal(basics.Offline.String(), newAccountStatus.Status) @@ -114,7 +114,7 @@ func testExpirationAccounts(t *testing.T, fixture *fixtures.RestClientFixture, f txnConfirmed := fixture.WaitForTxnConfirmation(seededRound+maxRoundsToWaitForTxnConfirm, sAccount, onlineTxID) a.True(txnConfirmed) - newAccountStatus, err = pClient.AccountInformation(sAccount) + newAccountStatus, err = pClient.AccountInformationV2(sAccount, false) a.NoError(err) a.Equal(basics.Online.String(), newAccountStatus.Status) @@ -135,7 +135,7 @@ func testExpirationAccounts(t *testing.T, fixture *fixtures.RestClientFixture, f // We want to wait until we get to one round past the last valid round err = fixture.WaitForRoundWithTimeout(uint64(lastValidRound) + 1) - newAccountStatus, err = pClient.AccountInformation(sAccount) + newAccountStatus, err = pClient.AccountInformationV2(sAccount, false) a.NoError(err) // The account should be online still... @@ -150,16 +150,16 @@ func testExpirationAccounts(t *testing.T, fixture *fixtures.RestClientFixture, f _, err = sClient.WaitForRound(uint64(lastValidRound + 1)) a.NoError(err) - blk, err := sClient.Block(latestRound) + blk, err := sClient.BookkeepingBlock(latestRound) a.NoError(err) a.Equal(blk.CurrentProtocol, protocolCheck) sendMoneyTxn := fixture.SendMoneyAndWait(latestRound, amountToSendInitial, transactionFee, richAccount, sAccount, "") - txnConfirmed = fixture.WaitForTxnConfirmation(latestRound+maxRoundsToWaitForTxnConfirm, sAccount, sendMoneyTxn.TxID) + txnConfirmed = fixture.WaitForTxnConfirmation(latestRound+maxRoundsToWaitForTxnConfirm, sAccount, sendMoneyTxn.Txn.ID().String()) a.True(txnConfirmed) - newAccountStatus, err = pClient.AccountInformation(sAccount) + newAccountStatus, err = pClient.AccountInformationV2(sAccount, false) a.NoError(err) // The account should be equal to the target status now diff --git a/test/e2e-go/features/participation/participationRewards_test.go b/test/e2e-go/features/participation/participationRewards_test.go index 3c8a293714..db519c1697 100644 --- a/test/e2e-go/features/participation/participationRewards_test.go +++ b/test/e2e-go/features/participation/participationRewards_test.go @@ -42,15 +42,16 @@ func getFirstAccountFromNamedNode(fixture *fixtures.RestClientFixture, r *requir } func waitUntilRewards(t *testing.T, fixture *fixtures.RestClientFixture, round uint64) (uint64, error) { - block, err := fixture.AlgodClient.Block(round) a := require.New(fixtures.SynchronizedTest(t)) + + block, err := fixture.LibGoalClient.BookkeepingBlock(round) a.NoError(err) for { round++ err := fixture.WaitForRoundWithTimeout(round + 1) a.NoError(err) - nextBlock, err := fixture.AlgodClient.Block(round) + nextBlock, err := fixture.LibGoalClient.BookkeepingBlock(round) a.NoError(err) if nextBlock.RewardsLevel > block.RewardsLevel { @@ -126,7 +127,7 @@ func TestOnlineOfflineRewards(t *testing.T) { finalOnlineBalance, _ := onlineClient.GetBalance(onlineAccount) finalOfflineBalance, _ := offlineClient.GetBalance(offlineAccount) - blk, err := fixture.AlgodClient.Block(initialRound) + blk, err := fixture.LibGoalClient.BookkeepingBlock(initialRound) r.NoError(err) rewardUnit := config.Consensus[protocol.ConsensusVersion(blk.CurrentProtocol)].RewardUnit // online account should be rewarded at least the expected amount @@ -217,7 +218,7 @@ func TestRewardUnitThreshold(t *testing.T) { minFee, minBalance, err := fixture.MinFeeAndBalance(initialRound) r.NoError(err) - blk, err := client.Block(initialRound) + blk, err := client.BookkeepingBlock(initialRound) r.NoError(err) rewardUnit := config.Consensus[protocol.ConsensusVersion(blk.CurrentProtocol)].RewardUnit // accrue rewards by letting time pass @@ -254,8 +255,8 @@ func TestRewardUnitThreshold(t *testing.T) { r.NoError(err) // newAccount should NOT be rewarded // poorAccount should be rewarded - updatedBalancePoorAccount, _ := client.AccountInformation(poorAccount) - updatedBalanceNewAccount, _ := client.AccountInformation(newAccount) + updatedBalancePoorAccount, _ := client.AccountInformationV2(poorAccount, false) + updatedBalanceNewAccount, _ := client.AccountInformationV2(newAccount, false) poorAccountDelta := updatedBalancePoorAccount.Amount - initialBalancePoorAccount r.Truef(initialBalancePoorAccount/rewardUnit <= poorAccountDelta, "non-empty account with balance > rewardunit (%d) should accrue rewards. started with %d, given %d, now has %d. Expected %d", rewardUnit, initialBalancePoorAccount, amountRichAccountPokesWith, updatedBalancePoorAccount.Amount, amountRichAccountPokesWith+initialBalancePoorAccount/rewardUnit) r.Truef(initialBalancePoorAccount/rewardUnit <= updatedBalancePoorAccount.Rewards, "non-empty account with balance > rewardunit (%d) should accrue rewards. started with %d, given %d, now has %d, actual rewards %d", rewardUnit, initialBalancePoorAccount, amountRichAccountPokesWith, updatedBalancePoorAccount.Amount, updatedBalancePoorAccount.Rewards) @@ -288,7 +289,7 @@ func TestRewardUnitThreshold(t *testing.T) { client.WaitForRound(rewardRound2) // Ensure that a reward for newAccount's one reward unit is now pending - latestBalanceNewAccount, _ := client.AccountInformation(newAccount) + latestBalanceNewAccount, _ := client.AccountInformationV2(newAccount, false) r.Truef((initialBalanceNewAccount+amountRichAccountPokesWith)/rewardUnit >= 1, "new account needs at least one reward unit") r.Truef(latestBalanceNewAccount.Amount >= initialBalanceNewAccount+(initialBalanceNewAccount+amountRichAccountPokesWith)/rewardUnit, "account sent at least %d should have accrued rewards. started with %d, was bumped to %d, so increase should be more than the %d seen", @@ -298,7 +299,7 @@ func TestRewardUnitThreshold(t *testing.T) { r.Equal(initialBalanceNewAccount+amountRichAccountPokesWith, latestBalanceNewAccount.AmountWithoutPendingRewards, "rewards should be pending") // since we poked, previous rewards should no longer be pending for poor account - latestBalancePoorAccount, _ := client.AccountInformation(poorAccount) + latestBalancePoorAccount, _ := client.AccountInformationV2(poorAccount, false) r.Truef(latestBalancePoorAccount.AmountWithoutPendingRewards >= updatedBalancePoorAccount.Amount+amountRichAccountPokesWith, "rewards should have been applied") // Test e2e REST API convenience computations @@ -349,7 +350,7 @@ func TestRewardRateRecalculation(t *testing.T) { r.NoError(err) fixture.SendMoneyAndWait(curStatus.LastRound, amountToSend, minFee, richAccount.Address, rewardsAccount, "") - blk, err := client.Block(curStatus.LastRound) + blk, err := client.BookkeepingBlock(curStatus.LastRound) r.NoError(err) r.Equal(protocol.ConsensusVersion(blk.CurrentProtocol), consensusTestRapidRewardRecalculation) consensusParams := consensus[protocol.ConsensusVersion(blk.CurrentProtocol)] @@ -359,10 +360,10 @@ func TestRewardRateRecalculation(t *testing.T) { if roundQueried != rewardRecalcRound-1 { r.FailNow("", "got rewards pool balance on round %d but wanted the balance on round %d, failing out", rewardRecalcRound-1, roundQueried) } - lastRoundBeforeRewardRecals, err := client.Block(rewardRecalcRound - 1) + lastRoundBeforeRewardRecals, err := client.BookkeepingBlock(rewardRecalcRound - 1) r.NoError(err) r.NoError(fixture.WaitForRoundWithTimeout(rewardRecalcRound)) - blk, err = client.Block(rewardRecalcRound) + blk, err = client.BookkeepingBlock(rewardRecalcRound) r.NoError(err) if !consensusParams.PendingResidueRewards { lastRoundBeforeRewardRecals.RewardsResidue = 0 @@ -381,11 +382,11 @@ func TestRewardRateRecalculation(t *testing.T) { if roundQueried != rewardRecalcRound-1 { r.FailNow("", "got rewards pool balance on round %d but wanted the balance on round %d, failing out", rewardRecalcRound-1, roundQueried) } - lastRoundBeforeRewardRecals, err = client.Block(rewardRecalcRound - 1) + lastRoundBeforeRewardRecals, err = client.BookkeepingBlock(rewardRecalcRound - 1) r.NoError(err) consensusParams = consensus[protocol.ConsensusVersion(lastRoundBeforeRewardRecals.CurrentProtocol)] r.NoError(fixture.WaitForRoundWithTimeout(rewardRecalcRound)) - blk, err = client.Block(rewardRecalcRound) + blk, err = client.BookkeepingBlock(rewardRecalcRound) r.NoError(err) if !consensusParams.PendingResidueRewards { lastRoundBeforeRewardRecals.RewardsResidue = 0 diff --git a/test/e2e-go/features/stateproofs/stateproofs_test.go b/test/e2e-go/features/stateproofs/stateproofs_test.go index a3b72180f1..08f35a5fc2 100644 --- a/test/e2e-go/features/stateproofs/stateproofs_test.go +++ b/test/e2e-go/features/stateproofs/stateproofs_test.go @@ -37,7 +37,6 @@ import ( sp "github.com/algorand/go-algorand/crypto/stateproof" "github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated" generatedV2 "github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated" - v1 "github.com/algorand/go-algorand/daemon/algod/api/spec/v1" "github.com/algorand/go-algorand/data/account" "github.com/algorand/go-algorand/data/basics" "github.com/algorand/go-algorand/data/bookkeeping" @@ -200,7 +199,7 @@ func verifyStateProofsCreation(t *testing.T, fixture *fixtures.RestClientFixture t.Logf("found a state proof for round %d at round %d", nextStateProofRound, blk.Round()) // Find the state proof transaction - stateProofMessage, nextStateProofBlock := verifyStateProofForRound(r, fixture, nextStateProofRound, lastStateProofMessage, lastStateProofBlock, consensusParams, expectedNumberOfStateProofs) + stateProofMessage, nextStateProofBlock := verifyStateProofForRound(r, fixture, nextStateProofRound, lastStateProofMessage, lastStateProofBlock, consensusParams) lastStateProofMessage = stateProofMessage lastStateProofBlock = nextStateProofBlock } @@ -311,7 +310,7 @@ func TestStateProofOverlappingKeys(t *testing.T) { t.Logf("found a state proof for round %d at round %d", nextStateProofRound, blk.Round()) // Find the state proof transaction - stateProofMessage, nextStateProofBlock := verifyStateProofForRound(r, &fixture, nextStateProofRound, lastStateProofMessage, lastStateProofBlock, consensusParams, expectedNumberOfStateProofs) + stateProofMessage, nextStateProofBlock := verifyStateProofForRound(r, &fixture, nextStateProofRound, lastStateProofMessage, lastStateProofBlock, consensusParams) lastStateProofMessage = stateProofMessage lastStateProofBlock = nextStateProofBlock } @@ -362,7 +361,7 @@ func TestStateProofMessageCommitmentVerification(t *testing.T) { nextStateProofRound = uint64(blk.StateProofTracking[protocol.StateProofBasic].StateProofNextRound) } - _, stateProofMessage := getStateProofByLastRound(r, &fixture, firstStateProofRound, 1) + _, stateProofMessage := getStateProofByLastRound(r, &fixture, firstStateProofRound) t.Logf("found first stateproof, attesting to rounds %d - %d. Verifying.\n", stateProofMessage.FirstAttestedRound, stateProofMessage.LastAttestedRound) for rnd := stateProofMessage.FirstAttestedRound; rnd <= stateProofMessage.LastAttestedRound; rnd++ { @@ -396,39 +395,30 @@ func getDefaultStateProofConsensusParams() config.ConsensusParams { return consensusParams } -func getStateProofByLastRound(r *require.Assertions, fixture *fixtures.RestClientFixture, stateProofLatestRound uint64, expectedNumberOfStateProofs uint64) (sp.StateProof, stateproofmsg.Message) { +func getStateProofByLastRound(r *require.Assertions, fixture *fixtures.RestClientFixture, stateProofLatestRound uint64) (sp.StateProof, stateproofmsg.Message) { restClient, err := fixture.NC.AlgodClient() r.NoError(err) - curRound, err := fixture.LibGoalClient.CurrentRound() - r.NoError(err) - - res, err := restClient.TransactionsByAddr(transactions.StateProofSender.String(), 0, curRound, expectedNumberOfStateProofs+1) + res, err := restClient.StateProofs(stateProofLatestRound) r.NoError(err) + r.Equal(res.Message.LastAttestedRound, stateProofLatestRound) var stateProof sp.StateProof - var stateProofMessage stateproofmsg.Message - for _, txn := range res.Transactions { - r.Equal(txn.Type, string(protocol.StateProofTx)) - r.True(txn.StateProof != nil) - err = protocol.Decode(txn.StateProof.StateProofMessage, &stateProofMessage) - r.NoError(err) - if stateProofMessage.LastAttestedRound == stateProofLatestRound { - err = protocol.Decode(txn.StateProof.StateProof, &stateProof) - r.NoError(err) + err = protocol.Decode(res.StateProof, &stateProof) + r.NoError(err) - return stateProof, stateProofMessage - } + msg := stateproofmsg.Message{ + BlockHeadersCommitment: res.Message.BlockHeadersCommitment, + VotersCommitment: res.Message.VotersCommitment, + LnProvenWeight: res.Message.LnProvenWeight, + FirstAttestedRound: res.Message.FirstAttestedRound, + LastAttestedRound: res.Message.LastAttestedRound, } - - r.FailNow("no state proof with latest round %d found", stateProofLatestRound) - - // Should never get here - return sp.StateProof{}, stateproofmsg.Message{} + return stateProof, msg } -func verifyStateProofForRound(r *require.Assertions, fixture *fixtures.RestClientFixture, nextStateProofRound uint64, prevStateProofMessage stateproofmsg.Message, lastStateProofBlock bookkeeping.Block, consensusParams config.ConsensusParams, expectedNumberOfStateProofs uint64) (stateproofmsg.Message, bookkeeping.Block) { - stateProof, stateProofMessage := getStateProofByLastRound(r, fixture, nextStateProofRound, expectedNumberOfStateProofs) +func verifyStateProofForRound(r *require.Assertions, fixture *fixtures.RestClientFixture, nextStateProofRound uint64, prevStateProofMessage stateproofmsg.Message, lastStateProofBlock bookkeeping.Block, consensusParams config.ConsensusParams) (stateproofmsg.Message, bookkeeping.Block) { + stateProof, stateProofMessage := getStateProofByLastRound(r, fixture, nextStateProofRound) nextStateProofBlock, err := fixture.LibGoalClient.BookkeepingBlock(nextStateProofRound) @@ -545,7 +535,7 @@ func TestRecoverFromLaggingStateProofChain(t *testing.T) { t.Logf("found a state proof for round %d at round %d", nextStateProofRound, blk.Round()) // Find the state proof transaction - stateProofMessage, nextStateProofBlock := verifyStateProofForRound(r, &fixture, nextStateProofRound, lastStateProofMessage, lastStateProofBlock, consensusParams, expectedNumberOfStateProofs) + stateProofMessage, nextStateProofBlock := verifyStateProofForRound(r, &fixture, nextStateProofRound, lastStateProofMessage, lastStateProofBlock, consensusParams) lastStateProofMessage = stateProofMessage lastStateProofBlock = nextStateProofBlock } @@ -771,7 +761,7 @@ func TestAttestorsChange(t *testing.T) { t.Logf("found a state proof for round %d at round %d", nextStateProofRound, blk.Round()) // Find the state proof transaction - stateProofMessage, nextStateProofBlock := verifyStateProofForRound(a, &fixture, nextStateProofRound, lastStateProofMessage, lastStateProofBlock, consensusParams, expectedNumberOfStateProofs) + stateProofMessage, nextStateProofBlock := verifyStateProofForRound(a, &fixture, nextStateProofRound, lastStateProofMessage, lastStateProofBlock, consensusParams) lastStateProofMessage = stateProofMessage lastStateProofBlock = nextStateProofBlock } @@ -852,7 +842,7 @@ func TestTotalWeightChanges(t *testing.T) { t.Logf("found a state proof for round %d at round %d", nextStateProofRound, blk.Round()) // Find the state proof transaction - stateProofMessage, nextStateProofBlock := verifyStateProofForRound(a, &fixture, nextStateProofRound, lastStateProofMessage, lastStateProofBlock, consensusParams, expectedNumberOfStateProofs) + stateProofMessage, nextStateProofBlock := verifyStateProofForRound(a, &fixture, nextStateProofRound, lastStateProofMessage, lastStateProofBlock, consensusParams) lastStateProofMessage = stateProofMessage lastStateProofBlock = nextStateProofBlock } @@ -909,16 +899,13 @@ func TestSPWithTXPoolFull(t *testing.T) { err = fixture.WaitForRound(round+1, 6*time.Second) require.NoError(t, err) - b, err := relay.Block(round + 1) + b, err := relay.BookkeepingBlock(round + 1) require.NoError(t, err) - if len(b.Transactions.Transactions) == 0 { + if len(b.Payset) == 0 { continue } - require.Equal(t, string(protocol.StateProofTx), b.Transactions.Transactions[0].Type) - var msg stateproofmsg.Message - err = protocol.Decode(b.Transactions.Transactions[0].StateProof.StateProofMessage, &msg) - require.NoError(t, err) - require.Equal(t, uint64(8), msg.LastAttestedRound) + require.Equal(t, protocol.StateProofTx, b.Payset[0].Txn.Type) + require.Equal(t, uint64(8), b.Payset[0].Txn.StateProofTxnFields.Message.LastAttestedRound) break } require.Less(t, round, uint64(20)) @@ -968,12 +955,12 @@ func TestAtMostOneSPFullPool(t *testing.T) { err := fixture.WaitForRound(round+1, 6*time.Second) require.NoError(t, err) - b, err := relay.Block(round + 1) + b, err := relay.BookkeepingBlock(round + 1) require.NoError(t, err) params, err = relay.SuggestedParams() require.NoError(t, err) - if len(b.Transactions.Transactions) == 0 { + if len(b.Payset) == 0 { continue } tid := 0 @@ -981,14 +968,11 @@ func TestAtMostOneSPFullPool(t *testing.T) { // Since the pool is full, only one additional SP transaction is allowed in. So only one SP can be added to be block // break after finding it, and look for the next one in a subsequent block // In case two SP transactions get into the same block, the following loop will not find the second one, and fail the test - for ; tid < len(b.Transactions.Transactions); tid++ { - if b.Transactions.Transactions[tid].Type == string(protocol.StateProofTx) { - require.Equal(t, string(protocol.StateProofTx), b.Transactions.Transactions[tid].Type) + for ; tid < len(b.Payset); tid++ { + if string(b.Payset[tid].Txn.Type) == string(protocol.StateProofTx) { + require.Equal(t, protocol.StateProofTx, b.Payset[tid].Txn.Type) - var msg stateproofmsg.Message - err = protocol.Decode(b.Transactions.Transactions[tid].StateProof.StateProofMessage, &msg) - require.NoError(t, err) - require.Equal(t, int(expectedSPRound), int(msg.LastAttestedRound)) + require.Equal(t, int(expectedSPRound), int(b.Payset[tid].Txn.StateProofTxnFields.Message.LastAttestedRound)) expectedSPRound = expectedSPRound + consensusParams.StateProofInterval break @@ -1108,12 +1092,12 @@ func TestAtMostOneSPFullPoolWithLoad(t *testing.T) { err := fixture.WaitForRound(round+1, 6*time.Second) require.NoError(t, err) - b, err := relay.Block(round + 1) + b, err := relay.BookkeepingBlock(round + 1) require.NoError(t, err) params, err = relay.SuggestedParams() require.NoError(t, err) - if len(b.Transactions.Transactions) == 0 { + if len(b.Payset) == 0 { continue } tid := 0 @@ -1121,14 +1105,11 @@ func TestAtMostOneSPFullPoolWithLoad(t *testing.T) { // Since the pool is full, only one additional SP transaction is allowed in. So only one SP can be added to be block // break after finding it, and look for the next one in a subsequent block // In case two SP transactions get into the same block, the following loop will not find the second one, and fail the test - for ; tid < len(b.Transactions.Transactions); tid++ { - if b.Transactions.Transactions[tid].Type == string(protocol.StateProofTx) { - require.Equal(t, string(protocol.StateProofTx), b.Transactions.Transactions[tid].Type) + for ; tid < len(b.Payset); tid++ { + if string(b.Payset[tid].Txn.Type) == string(protocol.StateProofTx) { + require.Equal(t, protocol.StateProofTx, b.Payset[tid].Txn.Type) - var msg stateproofmsg.Message - err = protocol.Decode(b.Transactions.Transactions[tid].StateProof.StateProofMessage, &msg) - require.NoError(t, err) - require.Equal(t, int(expectedSPRound), int(msg.LastAttestedRound)) + require.Equal(t, int(expectedSPRound), int(b.Payset[tid].Txn.StateProofTxnFields.Message.LastAttestedRound)) expectedSPRound = expectedSPRound + consensusParams.StateProofInterval break @@ -1209,7 +1190,7 @@ func TestStateProofCheckTotalStake(t *testing.T) { var lastStateProofBlock bookkeeping.Block libgoalClient := fixture.LibGoalClient - var totalSupplyAtRound [100]v1.Supply + var totalSupplyAtRound [100]generatedV2.SupplyResponse var accountSnapshotAtRound [100][]generatedV2.Account for rnd := uint64(1); rnd <= consensusParams.StateProofInterval*(expectedNumberOfStateProofs+1); rnd++ { @@ -1237,7 +1218,7 @@ func TestStateProofCheckTotalStake(t *testing.T) { totalSupply, err := libgoalClient.LedgerSupply() r.NoError(err) - r.Equal(rnd, totalSupply.Round, "could not capture total stake at the target round. The machine might be too slow for this test") + r.Equal(rnd, totalSupply.CurrentRound, "could not capture total stake at the target round. The machine might be too slow for this test") totalSupplyAtRound[rnd] = totalSupply accountSnapshotAtRound[rnd] = make([]generatedV2.Account, pNodes, pNodes) @@ -1275,7 +1256,7 @@ func TestStateProofCheckTotalStake(t *testing.T) { t.Logf("found a state proof for round %d at round %d", nextStateProofRound, blk.Round()) - stateProof, stateProofMsg := getStateProofByLastRound(r, &fixture, nextStateProofRound, expectedNumberOfStateProofs) + stateProof, stateProofMsg := getStateProofByLastRound(r, &fixture, nextStateProofRound) accountSnapshot := accountSnapshotAtRound[stateProofMsg.LastAttestedRound-consensusParams.StateProofInterval-consensusParams.StateProofVotersLookback] diff --git a/test/e2e-go/features/transactions/accountv2_test.go b/test/e2e-go/features/transactions/accountv2_test.go index 52b39c9eed..2dd38e13a6 100644 --- a/test/e2e-go/features/transactions/accountv2_test.go +++ b/test/e2e-go/features/transactions/accountv2_test.go @@ -231,10 +231,11 @@ int 1 // Ensure the txn committed resp, err := client.GetPendingTransactions(2) a.NoError(err) - a.Equal(uint64(0), resp.TotalTxns) - txinfo, err := client.TransactionInformation(signedTxn.Txn.Sender.String(), txid) + a.Equal(uint64(0), resp.TotalTransactions) + txinfo, err := client.PendingTransactionInformationV2(txid) a.NoError(err) - a.True(txinfo.ConfirmedRound != 0) + a.NotNil(txinfo.ConfirmedRound) + a.True(*txinfo.ConfirmedRound != 0) // check creator's balance record for the app entry and the state changes ad, err = client.AccountData(creator) @@ -307,13 +308,14 @@ int 1 _, err = client.WaitForRound(round + 1) a.NoError(err) // Ensure the txn committed - resp, err = client.GetPendingTransactions(2) + resp, err := client.GetParsedPendingTransactions(2) a.NoError(err) - if resp.TotalTxns == 1 { - a.Equal(resp.TruncatedTxns.Transactions[0].TxID, txid) + if resp.TotalTransactions == 1 { + pendingTxn := resp.TopTransactions[0] + a.Equal(pendingTxn.Txn.ID().String(), txid) continue } - a.Equal(uint64(0), resp.TotalTxns) + a.Equal(uint64(0), resp.TotalTransactions) break } diff --git a/test/e2e-go/features/transactions/asset_test.go b/test/e2e-go/features/transactions/asset_test.go index 9616f3cb05..155564fedf 100644 --- a/test/e2e-go/features/transactions/asset_test.go +++ b/test/e2e-go/features/transactions/asset_test.go @@ -26,7 +26,7 @@ import ( "github.com/stretchr/testify/require" "github.com/algorand/go-algorand/config" - v1 "github.com/algorand/go-algorand/daemon/algod/api/spec/v1" + "github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated" "github.com/algorand/go-algorand/data/basics" "github.com/algorand/go-algorand/data/transactions" "github.com/algorand/go-algorand/libgoal" @@ -37,7 +37,7 @@ import ( type assetIDParams struct { idx uint64 - params v1.AssetParams + params generated.AssetParams } func helperFillSignBroadcast(client libgoal.Client, wh []byte, sender string, tx transactions.Transaction, err error) (string, error) { @@ -226,9 +226,10 @@ func TestAssetConfig(t *testing.T) { a.NoError(err) // There should be no assets to start with - info, err := client.AccountInformation(account0) + info, err := client.AccountInformationV2(account0, true) a.NoError(err) - a.Equal(len(info.AssetParams), 0) + a.NotNil(info.CreatedAssets) + a.Equal(len(*info.CreatedAssets), 0) // Create max number of assets, or 1000 if the number of assets are unlimitd. maxAssetsCount := config.Consensus[protocol.ConsensusFuture].MaxAssetsPerAccount @@ -268,21 +269,38 @@ func TestAssetConfig(t *testing.T) { a.True(strings.Contains(err.Error(), "too many assets in account:")) } + // Helper methods for dereferencing asset fields + derefString := func(sp *string) string { + if sp != nil { + return *sp + } + return "" + } + derefByteArray := func(ba *[]byte) []byte { + if ba != nil { + return *ba + } + return []byte{} + } + // Check that assets are visible - info, err = client.AccountInformation(account0) + info, err = client.AccountInformationV2(account0, true) a.NoError(err) - a.Equal(maxAssetsCount, len(info.AssetParams)) + a.NotNil(info.Assets) + a.Equal(maxAssetsCount, len(*info.CreatedAssets)) var assets []assetIDParams - for idx, cp := range info.AssetParams { + for _, asset := range *info.CreatedAssets { + idx := asset.Index + cp := asset.Params assets = append(assets, assetIDParams{idx, cp}) - a.Equal(cp.UnitName, fmt.Sprintf("test%d", cp.Total-1)) - a.Equal(cp.AssetName, fmt.Sprintf("testname%d", cp.Total-1)) - a.Equal(cp.ManagerAddr, manager) - a.Equal(cp.ReserveAddr, reserve) - a.Equal(cp.FreezeAddr, freeze) - a.Equal(cp.ClawbackAddr, clawback) - a.Equal(cp.MetadataHash, assetMetadataHash) - a.Equal(cp.URL, assetURL) + a.Equal(derefString(cp.UnitName), fmt.Sprintf("test%d", cp.Total-1)) + a.Equal(derefString(cp.Name), fmt.Sprintf("testname%d", cp.Total-1)) + a.Equal(derefString(cp.Manager), manager) + a.Equal(derefString(cp.Reserve), reserve) + a.Equal(derefString(cp.Freeze), freeze) + a.Equal(derefString(cp.Clawback), clawback) + a.Equal(derefByteArray(cp.MetadataHash), assetMetadataHash) + a.Equal(derefString(cp.Url), assetURL) } // re-generate wh, since this test takes a while and sometimes @@ -334,41 +352,44 @@ func TestAssetConfig(t *testing.T) { confirmed = fixture.WaitForAllTxnsToConfirm(status.LastRound+20, txids) a.True(confirmed, "changing keys") - info, err = client.AccountInformation(account0) + info, err = client.AccountInformationV2(account0, true) a.NoError(err) - a.Equal(maxAssetsCount, len(info.AssetParams)) - for idx, cp := range info.AssetParams { - a.Equal(cp.UnitName, fmt.Sprintf("test%d", cp.Total-1)) - a.Equal(cp.AssetName, fmt.Sprintf("testname%d", cp.Total-1)) + a.NotNil(info.CreatedAssets) + a.Equal(maxAssetsCount, len(*info.CreatedAssets)) + for _, asset := range *info.CreatedAssets { + idx := asset.Index + cp := asset.Params + a.Equal(derefString(cp.UnitName), fmt.Sprintf("test%d", cp.Total-1)) + a.Equal(derefString(cp.Name), fmt.Sprintf("testname%d", cp.Total-1)) if idx == assets[0].idx { - a.Equal(cp.ManagerAddr, account0) + a.Equal(derefString(cp.Manager), account0) } else { - a.Equal(cp.ManagerAddr, manager) + a.Equal(derefString(cp.Manager), manager) } if idx == assets[1].idx { - a.Equal(cp.ReserveAddr, account0) + a.Equal(derefString(cp.Reserve), account0) } else if idx == assets[4].idx { - a.Equal(cp.ReserveAddr, "") + a.Equal(derefString(cp.Reserve), "") } else { - a.Equal(cp.ReserveAddr, reserve) + a.Equal(derefString(cp.Reserve), reserve) } if idx == assets[2].idx { - a.Equal(cp.FreezeAddr, account0) + a.Equal(derefString(cp.Freeze), account0) } else if idx == assets[5].idx { - a.Equal(cp.FreezeAddr, "") + a.Equal(derefString(cp.Freeze), "") } else { - a.Equal(cp.FreezeAddr, freeze) + a.Equal(derefString(cp.Freeze), freeze) } if idx == assets[3].idx { - a.Equal(cp.ClawbackAddr, account0) + a.Equal(derefString(cp.Clawback), account0) } else if idx == assets[6].idx { - a.Equal(cp.ClawbackAddr, "") + a.Equal(derefString(cp.Clawback), "") } else { - a.Equal(cp.ClawbackAddr, clawback) + a.Equal(derefString(cp.Clawback), clawback) } } @@ -385,7 +406,8 @@ func TestAssetConfig(t *testing.T) { // Destroy assets txids = make(map[string]string) - for idx := range info.AssetParams { + for _, asset := range *info.CreatedAssets { + idx := asset.Index // re-generate wh, since this test takes a while and sometimes // the wallet handle expires. wh, err = client.GetUnencryptedWalletHandle() @@ -451,6 +473,7 @@ func TestAssetInformation(t *testing.T) { a.NoError(err) // There should be no assets to start with + // Note: This test uses a deprecated v1 API. The v2 API test is below. info, err := client.AccountInformation(account0) a.NoError(err) a.Equal(len(info.AssetParams), 0) @@ -475,6 +498,7 @@ func TestAssetInformation(t *testing.T) { a.True(confirmed, "creating assets") // Check that AssetInformation returns the correct AssetParams + // Note: This test uses a deprecated v1 API. The v2 API test is below. info, err = client.AccountInformation(account0) a.NoError(err) for idx, cp := range info.AssetParams { @@ -639,10 +663,13 @@ func TestAssetGroupCreateSendDestroy(t *testing.T) { txids = make(map[string]string) // asset 1 (create + send) exists and available - assetParams, err := client1.AssetInformation(assetID1) + asset, err := client1.AssetInformationV2(assetID1) + assetParams := asset.Params a.NoError(err) - a.Equal(assetName1, assetParams.AssetName) - a.Equal(assetUnitName1, assetParams.UnitName) + a.NotNil(assetParams.Name) + a.Equal(assetName1, *assetParams.Name) + a.NotNil(*assetParams.UnitName) + a.Equal(assetUnitName1, *assetParams.UnitName) a.Equal(account0, assetParams.Creator) a.Equal(assetTotal, assetParams.Total) // sending it should succeed @@ -664,7 +691,7 @@ func TestAssetGroupCreateSendDestroy(t *testing.T) { a.NoError(err) // asset 3 (create + destroy) not available - _, err = client1.AssetInformation(assetID3) + _, err = client1.AssetInformationV2(assetID3) a.Error(err) // sending it should fail txSend, err = client1.MakeUnsignedAssetSendTx(assetID3, 0, account1, "", "") @@ -730,16 +757,19 @@ func TestAssetSend(t *testing.T) { confirmed := fixture.WaitForAllTxnsToConfirm(curRound+20, txids) a.True(confirmed, "creating assets") - info, err := client.AccountInformation(account0) + info, err := client.AccountInformationV2(account0, true) a.NoError(err) - a.Equal(len(info.AssetParams), 2) + a.NotNil(info.CreatedAssets) + a.Equal(len(*info.CreatedAssets), 2) var frozenIdx, nonFrozenIdx uint64 - for idx, cp := range info.AssetParams { - if cp.UnitName == "frozen" { + for _, asset := range *info.CreatedAssets { + idx := asset.Index + cp := asset.Params + if cp.UnitName != nil && *cp.UnitName == "frozen" { frozenIdx = idx } - if cp.UnitName == "nofreeze" { + if cp.UnitName != nil && *cp.UnitName == "nofreeze" { nonFrozenIdx = idx } } @@ -820,13 +850,19 @@ func TestAssetSend(t *testing.T) { confirmed = fixture.WaitForAllTxnsToConfirm(curRound+20, txids) a.True(confirmed, "creating asset slots") - info, err = client.AccountInformation(extra) - a.NoError(err) - a.Equal(len(info.Assets), 2) - a.Equal(info.Assets[frozenIdx].Amount, uint64(0)) - a.Equal(info.Assets[frozenIdx].Frozen, true) - a.Equal(info.Assets[nonFrozenIdx].Amount, uint64(10)) - a.Equal(info.Assets[nonFrozenIdx].Frozen, false) + info, err = client.AccountInformationV2(extra, true) + a.NoError(err) + a.NotNil(info.Assets) + a.Equal(len(*info.Assets), 2) + for _, asset := range *info.Assets { + if asset.AssetId == frozenIdx { + a.Equal(asset.Amount, uint64(0)) + a.Equal(asset.IsFrozen, true) + } else if asset.AssetId == nonFrozenIdx { + a.Equal(asset.Amount, uint64(10)) + a.Equal(asset.IsFrozen, false) + } + } // Should not be able to send more than is available tx, err = client.MakeUnsignedAssetSendTx(nonFrozenIdx, 11, extra, "", "") @@ -893,17 +929,29 @@ func TestAssetSend(t *testing.T) { a.True(confirmed, "clawback") // Check that the asset balances are correct - info, err = client.AccountInformation(account0) - a.NoError(err) - a.Equal(len(info.Assets), 2) - a.Equal(info.Assets[frozenIdx].Amount, uint64(95)) - a.Equal(info.Assets[nonFrozenIdx].Amount, uint64(95)) + info, err = client.AccountInformationV2(account0, true) + a.NoError(err) + a.NotNil(info.Assets) + a.Equal(len(*info.Assets), 2) + for _, asset := range *info.Assets { + if asset.AssetId == frozenIdx { + a.Equal(asset.Amount, uint64(95)) + } else if asset.AssetId == nonFrozenIdx { + a.Equal(asset.Amount, uint64(95)) + } + } - info, err = client.AccountInformation(extra) + info, err = client.AccountInformationV2(extra, true) a.NoError(err) - a.Equal(len(info.Assets), 2) - a.Equal(info.Assets[frozenIdx].Amount, uint64(5)) - a.Equal(info.Assets[nonFrozenIdx].Amount, uint64(5)) + a.NotNil(info.Assets) + a.Equal(len(*info.Assets), 2) + for _, asset := range *info.Assets { + if asset.AssetId == frozenIdx { + a.Equal(asset.Amount, uint64(5)) + } else if asset.AssetId == nonFrozenIdx { + a.Equal(asset.Amount, uint64(5)) + } + } // Should be able to close out asset slots and close entire account. tx, err = client.MakeUnsignedAssetFreezeTx(nonFrozenIdx, extra, false) @@ -930,22 +978,24 @@ func TestAssetCreateWaitRestartDelete(t *testing.T) { defer fixture.Shutdown() // There should be no assets to start with - info, err := client.AccountInformation(account0) + info, err := client.AccountInformationV2(account0, true) a.NoError(err) - a.Equal(len(info.AssetParams), 0) + a.NotNil(info.CreatedAssets) + a.Equal(len(*info.CreatedAssets), 0) manager, reserve, freeze, clawback := setupActors(account0, client, a) createAsset("test", account0, manager, reserve, freeze, clawback, client, fixture, a) // Check that asset is visible - info, err = client.AccountInformation(account0) + info, err = client.AccountInformationV2(account0, true) a.NoError(err) - a.Equal(len(info.AssetParams), 1) - var asset v1.AssetParams + a.NotNil(info.CreatedAssets) + a.Equal(len(*info.CreatedAssets), 1) + var asset generated.AssetParams var assetIndex uint64 - for idx, cp := range info.AssetParams { - asset = cp - assetIndex = idx + for _, cp := range *info.CreatedAssets { + asset = cp.Params + assetIndex = cp.Index } assetURL := "foo://bar" @@ -961,12 +1011,13 @@ func TestAssetCreateWaitRestartDelete(t *testing.T) { client = &fixture.LibGoalClient // Check again that asset is visible - info, err = client.AccountInformation(account0) + info, err = client.AccountInformationV2(account0, true) a.NoError(err) - a.Equal(len(info.AssetParams), 1) - for idx, cp := range info.AssetParams { - asset = cp - assetIndex = idx + a.NotNil(info.CreatedAssets) + a.Equal(len(*info.CreatedAssets), 1) + for _, cp := range *info.CreatedAssets { + asset = cp.Params + assetIndex = cp.Index } verifyAssetParameters(asset, "test", "testunit", manager, reserve, freeze, clawback, assetMetadataHash, assetURL, a) @@ -984,9 +1035,11 @@ func TestAssetCreateWaitRestartDelete(t *testing.T) { submitAndWaitForTransaction(manager, tx, "destroying assets", client, fixture, a) // Check again that asset is destroyed - info, err = client.AccountInformation(account0) + info, err = client.AccountInformationV2(account0, true) a.NoError(err) - a.Equal(len(info.AssetParams), 0) + a.NoError(err) + a.NotNil(info.CreatedAssets) + a.Equal(len(*info.CreatedAssets), 0) // Should be able to close now wh, err := client.GetUnencryptedWalletHandle() @@ -1026,22 +1079,24 @@ func TestAssetCreateWaitBalLookbackDelete(t *testing.T) { defer fixture.Shutdown() // There should be no assets to start with - info, err := client.AccountInformation(account0) + info, err := client.AccountInformationV2(account0, true) a.NoError(err) - a.Equal(len(info.AssetParams), 0) + a.NotNil(info.CreatedAssets) + a.Equal(len(*info.CreatedAssets), 0) manager, reserve, freeze, clawback := setupActors(account0, client, a) createAsset("test", account0, manager, reserve, freeze, clawback, client, fixture, a) // Check that asset is visible - info, err = client.AccountInformation(account0) + info, err = client.AccountInformationV2(account0, true) a.NoError(err) - a.Equal(len(info.AssetParams), 1) - var asset v1.AssetParams + a.NotNil(info.CreatedAssets) + a.Equal(len(*info.CreatedAssets), 1) + var asset generated.AssetParams var assetIndex uint64 - for idx, cp := range info.AssetParams { - asset = cp - assetIndex = idx + for _, cp := range *info.CreatedAssets { + asset = cp.Params + assetIndex = cp.Index } assetURL := "foo://bar" @@ -1059,12 +1114,13 @@ func TestAssetCreateWaitBalLookbackDelete(t *testing.T) { a.NoError(err) // Check again that asset is visible - info, err = client.AccountInformation(account0) + info, err = client.AccountInformationV2(account0, true) a.NoError(err) - a.Equal(len(info.AssetParams), 1) - for idx, cp := range info.AssetParams { - asset = cp - assetIndex = idx + a.NotNil(info.CreatedAssets) + a.Equal(len(*info.CreatedAssets), 1) + for _, cp := range *info.CreatedAssets { + asset = cp.Params + assetIndex = cp.Index } verifyAssetParameters(asset, "test", "testunit", manager, reserve, freeze, clawback, assetMetadataHash, assetURL, a) @@ -1082,9 +1138,10 @@ func TestAssetCreateWaitBalLookbackDelete(t *testing.T) { submitAndWaitForTransaction(manager, tx, "destroying assets", client, fixture, a) // Check again that asset is destroyed - info, err = client.AccountInformation(account0) + info, err = client.AccountInformationV2(account0, true) a.NoError(err) - a.Equal(len(info.AssetParams), 0) + a.NotNil(info.CreatedAssets) + a.Equal(len(*info.CreatedAssets), 0) // Should be able to close now wh, err := client.GetUnencryptedWalletHandle() @@ -1182,16 +1239,16 @@ func submitAndWaitForTransaction(sender string, tx transactions.Transaction, mes asser.True(confirmed, message) } -func verifyAssetParameters(asset v1.AssetParams, +func verifyAssetParameters(asset generated.AssetParams, unitName, assetName, manager, reserve, freeze, clawback string, metadataHash []byte, assetURL string, asser *require.Assertions) { - asser.Equal(asset.UnitName, unitName) - asser.Equal(asset.AssetName, assetName) - asser.Equal(asset.ManagerAddr, manager) - asser.Equal(asset.ReserveAddr, reserve) - asser.Equal(asset.FreezeAddr, freeze) - asser.Equal(asset.ClawbackAddr, clawback) - asser.Equal(asset.MetadataHash, metadataHash) - asser.Equal(asset.URL, assetURL) + asser.Equal(*asset.UnitName, unitName) + asser.Equal(*asset.Name, assetName) + asser.Equal(*asset.Manager, manager) + asser.Equal(*asset.Reserve, reserve) + asser.Equal(*asset.Freeze, freeze) + asser.Equal(*asset.Clawback, clawback) + asser.Equal(*asset.MetadataHash, metadataHash) + asser.Equal(*asset.Url, assetURL) } diff --git a/test/e2e-go/features/transactions/onlineStatusChange_test.go b/test/e2e-go/features/transactions/onlineStatusChange_test.go index fdda7eea67..d61ffa212f 100644 --- a/test/e2e-go/features/transactions/onlineStatusChange_test.go +++ b/test/e2e-go/features/transactions/onlineStatusChange_test.go @@ -64,17 +64,17 @@ func testAccountsCanChangeOnlineState(t *testing.T, templatePath string) { becomesNonparticipating := accountList[2].Address // 10% stake // assert that initiallyOfflineAccount is offline - initiallyOfflineAccountStatus, err := client.AccountInformation(initiallyOffline) + initiallyOfflineAccountStatus, err := client.AccountInformationV2(initiallyOffline, false) a.NoError(err) a.Equal(initiallyOfflineAccountStatus.Status, basics.Offline.String()) // assert that initiallyOnlineAccount is online - initiallyOnlineAccountStatus, err := client.AccountInformation(initiallyOnline) + initiallyOnlineAccountStatus, err := client.AccountInformationV2(initiallyOnline, false) a.NoError(err) a.Equal(initiallyOnlineAccountStatus.Status, basics.Online.String()) // assert that the account that will become nonparticipating hasn't yet been marked as such - unmarkedAccountStatus, err := client.AccountInformation(becomesNonparticipating) + unmarkedAccountStatus, err := client.AccountInformationV2(becomesNonparticipating, false) a.NoError(err) a.NotEqual(unmarkedAccountStatus.Status, basics.NotParticipating.String()) @@ -132,18 +132,18 @@ func testAccountsCanChangeOnlineState(t *testing.T, templatePath string) { fixture.WaitForRoundWithTimeout(curRound + uint64(1)) // assert that initiallyOffline is now online - initiallyOfflineAccountStatus, err = client.AccountInformation(initiallyOffline) + initiallyOfflineAccountStatus, err = client.AccountInformationV2(initiallyOffline, false) a.NoError(err) a.Equal(initiallyOfflineAccountStatus.Status, basics.Online.String()) // assert that initiallyOnline is now offline - initiallyOnlineAccountStatus, err = client.AccountInformation(initiallyOnline) + initiallyOnlineAccountStatus, err = client.AccountInformationV2(initiallyOnline, false) a.NoError(err) a.Equal(initiallyOnlineAccountStatus.Status, basics.Offline.String()) if doNonparticipationTest { // assert that becomesNonparticipating is no longer participating - unmarkedAccountStatus, err = client.AccountInformation(becomesNonparticipating) + unmarkedAccountStatus, err = client.AccountInformationV2(becomesNonparticipating, false) a.NoError(err) a.Equal(unmarkedAccountStatus.Status, basics.NotParticipating.String()) } diff --git a/test/e2e-go/features/transactions/proof_test.go b/test/e2e-go/features/transactions/proof_test.go index 8de0dcb02c..bb5175c92b 100644 --- a/test/e2e-go/features/transactions/proof_test.go +++ b/test/e2e-go/features/transactions/proof_test.go @@ -94,14 +94,15 @@ func TestTxnMerkleProof(t *testing.T) { txidSHA256 := tx.IDSha256() // only used for verification confirmedTx, err := fixture.WaitForConfirmedTxn(status.LastRound+10, baseAcct, txid.String()) a.NoError(err) + a.NotNil(confirmedTx.ConfirmedRound) - blk, err := client.BookkeepingBlock(confirmedTx.ConfirmedRound) + blk, err := client.BookkeepingBlock(*confirmedTx.ConfirmedRound) a.NoError(err) - proofresp, proof, err := fixture.TransactionProof(txid.String(), confirmedTx.ConfirmedRound, crypto.Sha512_256) + proofresp, proof, err := fixture.TransactionProof(txid.String(), *confirmedTx.ConfirmedRound, crypto.Sha512_256) a.NoError(err) - proofrespSHA256, proofSHA256, err := fixture.TransactionProof(txid.String(), confirmedTx.ConfirmedRound, crypto.Sha256) + proofrespSHA256, proofSHA256, err := fixture.TransactionProof(txid.String(), *confirmedTx.ConfirmedRound, crypto.Sha256) a.NoError(err) element := TxnMerkleElemRaw{Txn: crypto.Digest(txid)} @@ -176,8 +177,9 @@ func TestTxnMerkleProofSHA256(t *testing.T) { txid := tx.ID() confirmedTx, err := fixture.WaitForConfirmedTxn(status.LastRound+10, baseAcct, txid.String()) a.NoError(err) + a.NotNil(confirmedTx.ConfirmedRound) - blk, err := client.BookkeepingBlock(confirmedTx.ConfirmedRound) + blk, err := client.BookkeepingBlock(*confirmedTx.ConfirmedRound) a.NoError(err) proto := config.Consensus[blk.CurrentProtocol] a.False(proto.EnableSHA256TxnCommitmentHeader) diff --git a/test/e2e-go/features/transactions/sendReceive_test.go b/test/e2e-go/features/transactions/sendReceive_test.go index d17bd7dd2b..817547e247 100644 --- a/test/e2e-go/features/transactions/sendReceive_test.go +++ b/test/e2e-go/features/transactions/sendReceive_test.go @@ -23,7 +23,8 @@ import ( "github.com/stretchr/testify/require" - v1 "github.com/algorand/go-algorand/daemon/algod/api/spec/v1" + generatedV2 "github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated" + "github.com/algorand/go-algorand/test/framework/fixtures" "github.com/algorand/go-algorand/test/partitiontest" ) @@ -125,12 +126,12 @@ func testAccountsCanSendMoney(t *testing.T, templatePath string, numberOfSends i expectedPingBalance = expectedPingBalance - transactionFee - amountPingSendsPong + amountPongSendsPing expectedPongBalance = expectedPongBalance - transactionFee - amountPongSendsPing + amountPingSendsPong - var pongTxInfo, pingTxInfo v1.Transaction - pongTxInfo, err = pongClient.PendingTransactionInformation(pongTx.ID().String()) + var pongTxInfo, pingTxInfo generatedV2.PendingTransactionResponse + pongTxInfo, err = pongClient.PendingTransactionInformationV2(pongTx.ID().String()) if err == nil { - pingTxInfo, err = pingClient.PendingTransactionInformation(pingTx.ID().String()) + pingTxInfo, err = pingClient.PendingTransactionInformationV2(pingTx.ID().String()) } - waitForTransaction = err != nil || pongTxInfo.ConfirmedRound == 0 || pingTxInfo.ConfirmedRound == 0 + waitForTransaction = err != nil || (pongTxInfo.ConfirmedRound != nil && *pongTxInfo.ConfirmedRound == 0) || (pingTxInfo.ConfirmedRound != nil && *pingTxInfo.ConfirmedRound == 0) if waitForTransaction { curStatus, _ := pongClient.Status() curRound := curStatus.LastRound diff --git a/test/e2e-go/perf/basic_test.go b/test/e2e-go/perf/basic_test.go index dd70d422d4..f7e6c90109 100644 --- a/test/e2e-go/perf/basic_test.go +++ b/test/e2e-go/perf/basic_test.go @@ -240,11 +240,11 @@ func doBenchTemplate(b *testing.B, template string, moneynode string) { fmt.Printf("Block size statistics:\n") for round := status.LastRound + 1; ; round++ { - blk, err := c.Block(round) + blk, err := c.BookkeepingBlock(round) if err != nil { break } - fmt.Printf(" %d: %d txns\n", round, len(blk.Transactions.Transactions)) + fmt.Printf(" %d: %d txns\n", round, len(blk.Payset)) } } diff --git a/test/e2e-go/restAPI/restClient_test.go b/test/e2e-go/restAPI/restClient_test.go index 1c9c942163..e45d584694 100644 --- a/test/e2e-go/restAPI/restClient_test.go +++ b/test/e2e-go/restAPI/restClient_test.go @@ -36,7 +36,7 @@ import ( "github.com/algorand/go-algorand/config" "github.com/algorand/go-algorand/crypto" "github.com/algorand/go-algorand/crypto/merklesignature" - v1 "github.com/algorand/go-algorand/daemon/algod/api/spec/v1" + v2 "github.com/algorand/go-algorand/daemon/algod/api/server/v2" "github.com/algorand/go-algorand/data/account" "github.com/algorand/go-algorand/data/basics" "github.com/algorand/go-algorand/data/transactions" @@ -161,7 +161,7 @@ func waitForRoundOne(t *testing.T, testClient libgoal.Client) { var errWaitForTransactionTimeout = errors.New("wait for transaction timed out") -func waitForTransaction(t *testing.T, testClient libgoal.Client, fromAddress, txID string, timeout time.Duration) (tx v1.Transaction, err error) { +func waitForTransaction(t *testing.T, testClient libgoal.Client, fromAddress, txID string, timeout time.Duration) (tx v2.PreEncodedTxInfo, err error) { a := require.New(fixtures.SynchronizedTest(t)) rnd, err := testClient.Status() a.NoError(err) @@ -170,14 +170,11 @@ func waitForTransaction(t *testing.T, testClient libgoal.Client, fromAddress, tx } timeoutTime := time.Now().Add(timeout) for { - tx, err = testClient.TransactionInformation(fromAddress, txID) - if err != nil && strings.HasPrefix(err.Error(), "HTTP 404") { - tx, err = testClient.PendingTransactionInformation(txID) - } + tx, err = testClient.ParsedPendingTransaction(txID) if err == nil { a.NotEmpty(tx) a.Empty(tx.PoolError) - if tx.ConfirmedRound > 0 { + if tx.ConfirmedRound != nil && *tx.ConfirmedRound > 0 { return } } @@ -220,6 +217,7 @@ func TestClientCanGetStatusAfterBlock(t *testing.T) { a.NotEmpty(statusResponse) } +// Deprecated: This test uses a v1 API feature that is no longer supported by v2. func TestTransactionsByAddr(t *testing.T) { partitiontest.PartitionTest(t) defer fixtures.ShutdownSynchronizedTest(t) @@ -302,7 +300,7 @@ func TestClientCanGetMinTxnFee(t *testing.T) { testClient := fixture.LibGoalClient suggestedParamsRes, err := testClient.SuggestedParams() a.NoError(err) - a.Truef(suggestedParamsRes.MinTxnFee > 0, "min txn fee not supplied") + a.Truef(suggestedParamsRes.MinFee > 0, "min txn fee not supplied") } func TestClientCanGetBlockInfo(t *testing.T) { @@ -466,7 +464,7 @@ func TestClientCanSendAndGetNote(t *testing.T) { a.NoError(err) txStatus, err := waitForTransaction(t, testClient, someAddress, tx.ID().String(), 30*time.Second) a.NoError(err) - a.Equal(note, txStatus.Note) + a.Equal(note, txStatus.Txn.Txn.Note) } func TestClientCanGetTransactionStatus(t *testing.T) { @@ -518,7 +516,7 @@ func TestAccountBalance(t *testing.T) { _, err = waitForTransaction(t, testClient, someAddress, tx.ID().String(), 30*time.Second) a.NoError(err) - account, err := testClient.AccountInformation(toAddress) + account, err := testClient.AccountInformationV2(toAddress, false) a.NoError(err) a.Equal(account.AmountWithoutPendingRewards, uint64(100000)) a.Truef(account.Amount >= 100000, "account must have received money, and account information endpoint must print it") @@ -584,12 +582,12 @@ func TestAccountParticipationInfo(t *testing.T) { _, err = waitForTransaction(t, testClient, someAddress, txID, 30*time.Second) a.NoError(err) - account, err := testClient.AccountInformation(someAddress) + account, err := testClient.AccountInformationV2(someAddress, false) a.NoError(err) - a.Equal(randomVotePKStr, string(account.Participation.ParticipationPK), "API must print correct root voting key") - a.Equal(randomSelPKStr, string(account.Participation.VRFPK), "API must print correct vrf key") - a.Equal(uint64(firstRound), account.Participation.VoteFirst, "API must print correct first participation round") - a.Equal(uint64(lastRound), account.Participation.VoteLast, "API must print correct last participation round") + a.Equal(randomVotePKStr, string(account.Participation.VoteParticipationKey), "API must print correct root voting key") + a.Equal(randomSelPKStr, string(account.Participation.SelectionParticipationKey), "API must print correct vrf key") + a.Equal(uint64(firstRound), account.Participation.VoteFirstValid, "API must print correct first participation round") + a.Equal(uint64(lastRound), account.Participation.VoteLastValid, "API must print correct last participation round") a.Equal(dilution, account.Participation.VoteKeyDilution, "API must print correct key dilution") // TODO: should we update the v1 API to support state proof? Currently it does not return this field. } @@ -846,13 +844,15 @@ func TestClientCanGetPendingTransactions(t *testing.T) { // Check that a single pending txn is corectly displayed tx, err := testClient.SendPaymentFromUnencryptedWallet(fromAddress, toAddress, minTxnFee, minAcctBalance, nil) a.NoError(err) - statusResponse, err := testClient.GetPendingTransactions(0) + statusResponse, err := testClient.GetParsedPendingTransactions(0) a.NoError(err) a.NotEmpty(statusResponse) - a.True(statusResponse.TotalTxns == 1) - a.True(len(statusResponse.TruncatedTxns.Transactions) == 1) - a.True(statusResponse.TruncatedTxns.Transactions[0].TxID == tx.ID().String()) + a.True(statusResponse.TotalTransactions == 1) + a.True(len(statusResponse.TopTransactions) == 1) + // Parse response into SignedTxn + pendingTxn := statusResponse.TopTransactions[0] + a.True(pendingTxn.Txn.ID().String() == tx.ID().String()) } func TestClientTruncatesPendingTransactions(t *testing.T) { @@ -884,14 +884,13 @@ func TestClientTruncatesPendingTransactions(t *testing.T) { a.NoError(err) txIDsSeen[tx2.ID().String()] = true } - statusResponse, err := testClient.GetPendingTransactions(uint64(MaxTxns)) + statusResponse, err := testClient.GetParsedPendingTransactions(uint64(MaxTxns)) a.NoError(err) - a.NotEmpty(statusResponse) - a.True(int(statusResponse.TotalTxns) == NumTxns) - a.True(len(statusResponse.TruncatedTxns.Transactions) == MaxTxns) - for _, tx := range statusResponse.TruncatedTxns.Transactions { - a.True(txIDsSeen[tx.TxID]) - delete(txIDsSeen, tx.TxID) + a.True(int(statusResponse.TotalTransactions) == NumTxns) + a.True(len(statusResponse.TopTransactions) == MaxTxns) + for _, tx := range statusResponse.TopTransactions { + a.True(txIDsSeen[tx.Txn.ID().String()]) + delete(txIDsSeen, tx.Txn.ID().String()) } a.True(len(txIDsSeen) == NumTxns-MaxTxns) } @@ -931,12 +930,14 @@ func TestClientPrioritizesPendingTransactions(t *testing.T) { txHigh, err := testClient.SendPaymentFromUnencryptedWallet(fromAddress, toAddress, minTxnFee*10, minAcctBalance, nil) a.NoError(err) - statusResponse, err := testClient.GetPendingTransactions(uint64(MaxTxns)) + statusResponse, err := testClient.GetParsedPendingTransactions(uint64(MaxTxns)) a.NoError(err) a.NotEmpty(statusResponse) - a.True(int(statusResponse.TotalTxns) == NumTxns+1) - a.True(len(statusResponse.TruncatedTxns.Transactions) == MaxTxns) - a.True(statusResponse.TruncatedTxns.Transactions[0].TxID == txHigh.ID().String()) + a.True(int(statusResponse.TotalTransactions) == NumTxns+1) + a.True(len(statusResponse.TopTransactions) == MaxTxns) + + pendingTxn := statusResponse.TopTransactions[0] + a.True(pendingTxn.Txn.ID().String() == txHigh.ID().String()) } func TestPendingTransactionInfoInnerTxnAssetCreate(t *testing.T) { diff --git a/test/e2e-go/stress/transactions/createManyAndGoOnline_test.go b/test/e2e-go/stress/transactions/createManyAndGoOnline_test.go index 064a615968..1924d87913 100644 --- a/test/e2e-go/stress/transactions/createManyAndGoOnline_test.go +++ b/test/e2e-go/stress/transactions/createManyAndGoOnline_test.go @@ -173,10 +173,12 @@ func TestManyAccountsCanGoOnline(t *testing.T) { i = 0 // for assert debug messages for txid, account := range txidsToAccountsGoOnline { - accountStatus, err := client.AccountInformation(account) + accountStatus, err := client.AccountInformationV2(account, false) + a.NoError(err) _, round := fixture.GetBalanceAndRound(account) - curTxStatus, err := client.TransactionInformation(account, txid) - a.True(curTxStatus.ConfirmedRound <= round, "go online transaction confirmed on round %d, current round is %d\n", curTxStatus.ConfirmedRound, round) + curTxStatus, err := client.PendingTransactionInformationV2(txid) + a.NotNil(curTxStatus.ConfirmedRound) + a.True(*curTxStatus.ConfirmedRound <= round, "go online transaction confirmed on round %d, current round is %d\n", curTxStatus.ConfirmedRound, round) a.NoError(err, "should be no error when querying account information (query number %v regarding account %v)", i, account) a.Equal(byte(basics.Online), accountStatus.Status, "account %v should be online by now", account) i++ diff --git a/test/e2e-go/upgrades/application_support_test.go b/test/e2e-go/upgrades/application_support_test.go index 3667cc3cef..f178dd0a6b 100644 --- a/test/e2e-go/upgrades/application_support_test.go +++ b/test/e2e-go/upgrades/application_support_test.go @@ -204,7 +204,7 @@ int 1 client.WaitForRound(round + 2) pendingTx, err := client.GetPendingTransactions(1) a.NoError(err) - a.Equal(uint64(0), pendingTx.TotalTxns) + a.Equal(uint64(0), pendingTx.TotalTransactions) // check creator's balance record for the app entry and the state changes ad, err = client.AccountData(creator) @@ -420,12 +420,12 @@ int 1 t.Skip("Test platform is too slow for this test") } - a.Equal(uint64(1), pendingTx.TotalTxns) + a.Equal(uint64(1), pendingTx.TotalTransactions) // check that the secondary node doesn't have that transaction in it's transaction pool. pendingTx, err = secondary.GetPendingTransactions(1) a.NoError(err) - a.Equal(uint64(0), pendingTx.TotalTxns) + a.Equal(uint64(0), pendingTx.TotalTransactions) curStatus, err := client.Status() a.NoError(err) @@ -459,7 +459,7 @@ int 1 client.WaitForRound(round + 2) pendingTx, err = client.GetPendingTransactions(1) a.NoError(err) - a.Equal(uint64(0), pendingTx.TotalTxns) + a.Equal(uint64(0), pendingTx.TotalTransactions) // check creator's balance record for the app entry and the state changes ad, err = client.AccountData(creator) diff --git a/test/e2e-go/upgrades/stateproof_participation_test.go b/test/e2e-go/upgrades/stateproof_participation_test.go index 6f9cf7f13d..75d3dad875 100644 --- a/test/e2e-go/upgrades/stateproof_participation_test.go +++ b/test/e2e-go/upgrades/stateproof_participation_test.go @@ -17,6 +17,11 @@ package upgrades import ( + "path/filepath" + "strings" + "testing" + "time" + "github.com/algorand/go-algorand/config" "github.com/algorand/go-algorand/crypto" "github.com/algorand/go-algorand/data/basics" @@ -25,10 +30,6 @@ import ( "github.com/algorand/go-algorand/test/framework/fixtures" "github.com/algorand/go-algorand/test/partitiontest" "github.com/stretchr/testify/require" - "path/filepath" - "strings" - "testing" - "time" ) func waitUntilProtocolUpgrades(a *require.Assertions, fixture *fixtures.RestClientFixture, nodeClient libgoal.Client) { @@ -36,19 +37,19 @@ func waitUntilProtocolUpgrades(a *require.Assertions, fixture *fixtures.RestClie curRound, err := nodeClient.CurrentRound() a.NoError(err) - blk, err := nodeClient.Block(curRound) + blk, err := nodeClient.BookkeepingBlock(curRound) a.NoError(err) curProtocol := blk.CurrentProtocol startTime := time.Now() // while consensus version has not upgraded - for strings.Compare(curProtocol, string(consensusTestFastUpgrade(protocol.ConsensusV30))) == 0 { + for strings.Compare(string(curProtocol), string(consensusTestFastUpgrade(protocol.ConsensusV30))) == 0 { curRound = curRound + 1 fixture.WaitForRoundWithTimeout(curRound + 1) // TODO: check node status instead of latest block? - blk, err := nodeClient.Block(curRound) + blk, err := nodeClient.BookkeepingBlock(curRound) a.NoError(err) curProtocol = blk.CurrentProtocol diff --git a/test/framework/fixtures/libgoalFixture.go b/test/framework/fixtures/libgoalFixture.go index 746a0c2f94..ab10942d5f 100644 --- a/test/framework/fixtures/libgoalFixture.go +++ b/test/framework/fixtures/libgoalFixture.go @@ -479,7 +479,7 @@ func (f *LibGoalFixture) CurrentConsensusParams() (consensus config.ConsensusPar // ConsensusParams returns the consensus parameters for the protocol from the specified round func (f *LibGoalFixture) ConsensusParams(round uint64) (consensus config.ConsensusParams, err error) { - block, err := f.LibGoalClient.Block(round) + block, err := f.LibGoalClient.BookkeepingBlock(round) if err != nil { return } diff --git a/test/framework/fixtures/restClientFixture.go b/test/framework/fixtures/restClientFixture.go index c9f3befa84..bc8a0fdc0e 100644 --- a/test/framework/fixtures/restClientFixture.go +++ b/test/framework/fixtures/restClientFixture.go @@ -18,15 +18,21 @@ package fixtures import ( "fmt" - "github.com/algorand/go-algorand/data/basics" "sort" "time" "unicode" + "github.com/algorand/go-algorand/data/basics" + "github.com/algorand/go-algorand/data/transactions" + "github.com/algorand/go-algorand/protocol" + "github.com/stretchr/testify/require" "github.com/algorand/go-algorand/daemon/algod/api/client" + v2 "github.com/algorand/go-algorand/daemon/algod/api/server/v2" + generatedV2 "github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated" v1 "github.com/algorand/go-algorand/daemon/algod/api/spec/v1" + "github.com/algorand/go-algorand/libgoal" "github.com/algorand/go-algorand/nodecontrol" "github.com/algorand/go-algorand/test/e2e-go/globals" @@ -166,7 +172,7 @@ func (f *RestClientFixture) GetFirstAccount() (account string, err error) { } // GetRichestAccount returns the first account when calling GetWalletsSortedByBalance, which should be the richest account -func (f *RestClientFixture) GetRichestAccount() (richest v1.Account, err error) { +func (f *RestClientFixture) GetRichestAccount() (richest generatedV2.Account, err error) { list, err := f.GetWalletsSortedByBalance() if len(list) > 0 { richest = list[0] @@ -191,17 +197,17 @@ func (f *RestClientFixture) GetBalanceAndRound(account string) (balance uint64, // GetWalletsSortedByBalance returns the Primary node's accounts sorted DESC by balance // the richest account will be at accounts[0] -func (f *RestClientFixture) GetWalletsSortedByBalance() (accounts []v1.Account, err error) { +func (f *RestClientFixture) GetWalletsSortedByBalance() (accounts []generatedV2.Account, err error) { return f.getNodeWalletsSortedByBalance(f.LibGoalClient) } // GetNodeWalletsSortedByBalance returns the specified node's accounts sorted DESC by balance // the richest account will be at accounts[0] -func (f *RestClientFixture) GetNodeWalletsSortedByBalance(nodeDataDir string) (accounts []v1.Account, err error) { +func (f *RestClientFixture) GetNodeWalletsSortedByBalance(nodeDataDir string) (accounts []generatedV2.Account, err error) { return f.getNodeWalletsSortedByBalance(f.GetLibGoalClientFromDataDir(nodeDataDir)) } -func (f *RestClientFixture) getNodeWalletsSortedByBalance(client libgoal.Client) (accounts []v1.Account, err error) { +func (f *RestClientFixture) getNodeWalletsSortedByBalance(client libgoal.Client) (accounts []generatedV2.Account, err error) { wh, err := client.GetUnencryptedWalletHandle() if err != nil { return nil, fmt.Errorf("unable to retrieve wallet handle : %v", err) @@ -211,7 +217,7 @@ func (f *RestClientFixture) getNodeWalletsSortedByBalance(client libgoal.Client) return nil, fmt.Errorf("unable to list wallet addresses : %v", err) } for _, addr := range addresses { - info, err := client.AccountInformation(addr) + info, err := client.AccountInformationV2(addr, true) f.failOnError(err, "failed to get account info: %v") accounts = append(accounts, info) } @@ -232,7 +238,7 @@ func (f *RestClientFixture) WaitForTxnConfirmation(roundTimeout uint64, accountA // WaitForConfirmedTxn waits until either the passed txid is confirmed // or until the passed roundTimeout passes // or until waiting for a round to pass times out -func (f *RestClientFixture) WaitForConfirmedTxn(roundTimeout uint64, accountAddress, txid string) (txn v1.Transaction, err error) { +func (f *RestClientFixture) WaitForConfirmedTxn(roundTimeout uint64, accountAddress, txid string) (txn v2.PreEncodedTxInfo, err error) { client := f.AlgodClient for { // Get current round information @@ -241,11 +247,17 @@ func (f *RestClientFixture) WaitForConfirmedTxn(roundTimeout uint64, accountAddr curRound := curStatus.LastRound // Check if we know about the transaction yet - txn, err = client.TransactionInformation(accountAddress, txid) + var resp []byte + resp, err = client.RawPendingTransactionInformationV2(txid) if err == nil { - return + err = protocol.DecodeReflect(resp, &txn) + require.NoError(f.t, err) } + // Check if transaction was confirmed + if txn.ConfirmedRound != nil && *txn.ConfirmedRound > 0 { + return + } // Check if we should wait a round if curRound > roundTimeout { err = fmt.Errorf("failed to see confirmed transaction by round %v", roundTimeout) @@ -267,11 +279,18 @@ func (f *RestClientFixture) WaitForAllTxnsToConfirm(roundTimeout uint64, txidsAn _, err := f.WaitForConfirmedTxn(roundTimeout, addr, txid) if err != nil { f.t.Logf("txn failed to confirm: ", addr, txid) - pendingTxns, err := f.AlgodClient.GetPendingTransactions(0) + response, err := f.AlgodClient.GetRawPendingTransactions(0) if err == nil { - pendingTxids := make([]string, 0, pendingTxns.TotalTxns) - for _, txn := range pendingTxns.TruncatedTxns.Transactions { - pendingTxids = append(pendingTxids, txn.TxID) + // Parse pending transaction response + var pendingTxns struct { + TopTransactions []transactions.SignedTxn + TotalTransactions uint64 + } + err = protocol.DecodeReflect(response, &pendingTxns) + require.NoError(f.t, err) + pendingTxids := make([]string, 0, pendingTxns.TotalTransactions) + for _, txn := range pendingTxns.TopTransactions { + pendingTxids = append(pendingTxids, txn.Txn.ID().String()) } f.t.Logf("pending txids: ", pendingTxids) } else { @@ -300,7 +319,7 @@ func (f *RestClientFixture) WaitForAccountFunded(roundTimeout uint64, accountAdd curRound := curStatus.LastRound // Check if we know about the transaction yet - acct, acctErr := client.AccountInformation(accountAddress) + acct, acctErr := client.AccountInformationV2(accountAddress, false) require.NoError(f.t, acctErr, "fixture should be able to get account info") if acct.Amount > 0 { return nil @@ -318,7 +337,7 @@ func (f *RestClientFixture) WaitForAccountFunded(roundTimeout uint64, accountAdd // SendMoneyAndWait uses the rest client to send money and WaitForTxnConfirmation to wait for the send to confirm // it adds some extra error checking as well -func (f *RestClientFixture) SendMoneyAndWait(curRound, amountToSend, transactionFee uint64, fromAccount, toAccount string, closeToAccount string) (txn v1.Transaction) { +func (f *RestClientFixture) SendMoneyAndWait(curRound, amountToSend, transactionFee uint64, fromAccount, toAccount string, closeToAccount string) (txn v2.PreEncodedTxInfo) { client := f.LibGoalClient wh, err := client.GetUnencryptedWalletHandle() require.NoError(f.t, err, "client should be able to get unencrypted wallet handle") @@ -327,7 +346,7 @@ func (f *RestClientFixture) SendMoneyAndWait(curRound, amountToSend, transaction } // SendMoneyAndWaitFromWallet is as above, but for a specific wallet -func (f *RestClientFixture) SendMoneyAndWaitFromWallet(walletHandle, walletPassword []byte, curRound, amountToSend, transactionFee uint64, fromAccount, toAccount string, closeToAccount string) (txn v1.Transaction) { +func (f *RestClientFixture) SendMoneyAndWaitFromWallet(walletHandle, walletPassword []byte, curRound, amountToSend, transactionFee uint64, fromAccount, toAccount string, closeToAccount string) (txn v2.PreEncodedTxInfo) { client := f.LibGoalClient // use one curRound - 1 in case other nodes are behind fundingTx, err := client.SendPaymentFromWallet(walletHandle, walletPassword, fromAccount, toAccount, transactionFee, amountToSend, nil, closeToAccount, basics.Round(curRound).SubSaturate(1), 0) @@ -344,9 +363,9 @@ func (f *RestClientFixture) SendMoneyAndWaitFromWallet(walletHandle, walletPassw func (f *RestClientFixture) VerifyBlockProposedRange(account string, fromRound, countDownNumRounds int) (blockWasProposed bool) { c := f.LibGoalClient for i := 0; i < countDownNumRounds; i++ { - block, err := c.Block(uint64(fromRound - i)) + cert, err := c.EncodedBlockCert(uint64(fromRound - i)) require.NoError(f.t, err, "client failed to get block %d", fromRound-i) - if block.Proposer == account { + if cert.Certificate.Proposal.OriginalProposer.GetUserAddress() == account { blockWasProposed = true break } diff --git a/test/scripts/e2e_subs/e2e-app-simple.sh b/test/scripts/e2e_subs/e2e-app-simple.sh index e770ee872e..e1f1458ce4 100755 --- a/test/scripts/e2e_subs/e2e-app-simple.sh +++ b/test/scripts/e2e_subs/e2e-app-simple.sh @@ -5,6 +5,7 @@ date '+app-simple-test start %Y%m%d_%H%M%S' set -e set -x set -o pipefail +set -o nounset export SHELLOPTS WALLET=$1