diff --git a/cmd/goal/account.go b/cmd/goal/account.go index f4c36fcc5f..7eaa545d82 100644 --- a/cmd/goal/account.go +++ b/cmd/goal/account.go @@ -31,7 +31,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" + generatedV2 "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" @@ -476,7 +476,7 @@ var listCmd = &cobra.Command{ // For each address, request information about it from algod for _, addr := range addrs { - response, _ := client.AccountInformation(addr.Addr) + response, _ := client.AccountInformationV2(addr.Addr) // it's okay to proceed without algod info // Display this information to the user @@ -512,7 +512,7 @@ var infoCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { dataDir := ensureSingleDataDir() client := ensureAlgodClient(dataDir) - response, err := client.AccountInformation(accountAddress) + response, err := client.AccountInformationV2(accountAddress) if err != nil { reportErrorf(errorRequestFail, err) } @@ -524,36 +524,50 @@ var infoCmd = &cobra.Command{ }, } -func sortUint64Slice(slice []uint64) { - sort.Slice(slice, func(i, j int) bool { - return slice[i] < slice[j] - }) -} - -func printAccountInfo(client libgoal.Client, address string, account v1.Account) bool { - createdAssets := []uint64{} - for id := range account.AssetParams { - createdAssets = append(createdAssets, id) +func printAccountInfo(client libgoal.Client, address string, account generatedV2.Account) bool { + var createdAssets []generatedV2.Asset + if account.CreatedAssets != nil { + createdAssets = make([]generatedV2.Asset, len(*account.CreatedAssets)) + for i, asset := range *account.CreatedAssets { + createdAssets[i] = asset + } + sort.Slice(createdAssets, func(i, j int) bool { + return createdAssets[i].Index < createdAssets[j].Index + }) } - sortUint64Slice(createdAssets) - heldAssets := []uint64{} - for id := range account.Assets { - heldAssets = append(heldAssets, id) + var heldAssets []generatedV2.AssetHolding + if account.Assets != nil { + heldAssets = make([]generatedV2.AssetHolding, len(*account.Assets)) + for i, assetHolding := range *account.Assets { + heldAssets[i] = assetHolding + } + sort.Slice(heldAssets, func(i, j int) bool { + return heldAssets[i].AssetId < heldAssets[j].AssetId + }) } - sortUint64Slice(heldAssets) - createdApps := []uint64{} - for id := range account.AppParams { - createdApps = append(createdApps, id) + var createdApps []generatedV2.Application + if account.CreatedApps != nil { + createdApps = make([]generatedV2.Application, len(*account.CreatedApps)) + for i, app := range *account.CreatedApps { + createdApps[i] = app + } + sort.Slice(createdApps, func(i, j int) bool { + return createdApps[i].Id < createdApps[j].Id + }) } - sortUint64Slice(createdApps) - optedInApps := []uint64{} - for id := range account.AppLocalStates { - optedInApps = append(optedInApps, id) + var optedInApps []generatedV2.ApplicationLocalState + if account.AppsLocalState != nil { + optedInApps = make([]generatedV2.ApplicationLocalState, len(*account.AppsLocalState)) + for i, appLocalState := range *account.AppsLocalState { + optedInApps[i] = appLocalState + } + sort.Slice(optedInApps, func(i, j int) bool { + return optedInApps[i].Id < optedInApps[j].Id + }) } - sortUint64Slice(optedInApps) report := &strings.Builder{} errorReport := &strings.Builder{} @@ -563,103 +577,116 @@ func printAccountInfo(client libgoal.Client, address string, account v1.Account) if len(createdAssets) == 0 { fmt.Fprintln(report, "\t") } - for _, id := range createdAssets { - assetParams := account.AssetParams[id] - - name := assetParams.AssetName - if len(name) == 0 { - name = "" + for _, createdAsset := range createdAssets { + name := "" + if createdAsset.Params.Name != nil { + _, name = unicodePrintable(*createdAsset.Params.Name) } - _, name = unicodePrintable(name) - units := assetParams.UnitName - if len(units) == 0 { - units = "units" + + units := "units" + if createdAsset.Params.UnitName != nil { + _, units = unicodePrintable(*createdAsset.Params.UnitName) } - _, units = unicodePrintable(units) - total := assetDecimalsFmt(assetParams.Total, assetParams.Decimals) + + total := assetDecimalsFmt(createdAsset.Params.Total, uint32(createdAsset.Params.Decimals)) + url := "" - if len(assetParams.URL) != 0 { - url = fmt.Sprintf(", %s", assetParams.URL) + if createdAsset.Params.Url != nil { + _, safeURL := unicodePrintable(*createdAsset.Params.Url) + url = fmt.Sprintf(", %s", safeURL) } - fmt.Fprintf(report, "\tID %d, %s, supply %s %s%s\n", id, name, total, units, url) + fmt.Fprintf(report, "\tID %d, %s, supply %s %s%s\n", createdAsset.Index, name, total, units, url) } fmt.Fprintln(report, "Held Assets:") if len(heldAssets) == 0 { fmt.Fprintln(report, "\t") } - for _, id := range heldAssets { - assetHolding := account.Assets[id] - assetParams, err := client.AssetInformationV2(id) + for _, assetHolding := range heldAssets { + assetParams, err := client.AssetInformationV2(assetHolding.AssetId) if err != nil { hasError = true - fmt.Fprintf(errorReport, "Error: Unable to retrieve asset information for asset %d referred to by account %s: %v\n", id, address, err) - fmt.Fprintf(report, "\tID %d, error\n", id) + fmt.Fprintf(errorReport, "Error: Unable to retrieve asset information for asset %d referred to by account %s: %v\n", assetHolding.AssetId, address, err) + fmt.Fprintf(report, "\tID %d, error\n", assetHolding.AssetId) } amount := assetDecimalsFmt(assetHolding.Amount, uint32(assetParams.Params.Decimals)) - var assetName string + assetName := "" if assetParams.Params.Name != nil { - assetName = *assetParams.Params.Name - } - if len(assetName) == 0 { - assetName = "" + _, assetName = unicodePrintable(*assetParams.Params.Name) } - _, assetName = unicodePrintable(assetName) - var unitName string + unitName := "units" if assetParams.Params.UnitName != nil { - unitName = *assetParams.Params.UnitName + _, unitName = unicodePrintable(*assetParams.Params.UnitName) } - if len(unitName) == 0 { - unitName = "units" - } - _, unitName = unicodePrintable(unitName) frozen := "" - if assetHolding.Frozen { + if assetHolding.IsFrozen { frozen = " (frozen)" } - fmt.Fprintf(report, "\tID %d, %s, balance %s %s%s\n", id, assetName, amount, unitName, frozen) + fmt.Fprintf(report, "\tID %d, %s, balance %s %s%s\n", assetHolding.AssetId, assetName, amount, unitName, frozen) } fmt.Fprintln(report, "Created Apps:") if len(createdApps) == 0 { fmt.Fprintln(report, "\t") } - for _, id := range createdApps { - appParams := account.AppParams[id] - usedInts := 0 - usedBytes := 0 - for _, value := range appParams.GlobalState { - if value.Type == "u" { - usedInts++ - } else { - usedBytes++ + for _, app := range createdApps { + allocatedInts := uint64(0) + allocatedBytes := uint64(0) + if app.Params.GlobalStateSchema != nil { + allocatedInts = app.Params.GlobalStateSchema.NumUint + allocatedBytes = app.Params.GlobalStateSchema.NumByteSlice + } + + usedInts := uint64(0) + usedBytes := uint64(0) + if app.Params.GlobalState != nil { + for _, value := range *app.Params.GlobalState { + if basics.TealType(value.Value.Type) == basics.TealUintType { + usedInts++ + } else { + usedBytes++ + } } } - fmt.Fprintf(report, "\tID %d, global state used %d/%d uints, %d/%d byte slices\n", id, usedInts, appParams.GlobalStateSchema.NumUint, usedBytes, appParams.GlobalStateSchema.NumByteSlice) + + extraPages := "" + if app.Params.ExtraProgramPages != nil && *app.Params.ExtraProgramPages != 0 { + plural := "" + if *app.Params.ExtraProgramPages != 1 { + plural = "s" + } + extraPages = fmt.Sprintf(", %d extra page%s", *app.Params.ExtraProgramPages, plural) + } + + fmt.Fprintf(report, "\tID %d%s, global state used %d/%d uints, %d/%d byte slices\n", app.Id, extraPages, usedInts, allocatedInts, usedBytes, allocatedBytes) } fmt.Fprintln(report, "Opted In Apps:") if len(optedInApps) == 0 { fmt.Fprintln(report, "\t") } - for _, id := range optedInApps { - localState := account.AppLocalStates[id] - usedInts := 0 - usedBytes := 0 - for _, value := range localState.KeyValue { - if value.Type == "u" { - usedInts++ - } else { - usedBytes++ + for _, localState := range optedInApps { + allocatedInts := localState.Schema.NumUint + allocatedBytes := localState.Schema.NumByteSlice + + usedInts := uint64(0) + usedBytes := uint64(0) + if localState.KeyValue != nil { + for _, value := range *localState.KeyValue { + if basics.TealType(value.Value.Type) == basics.TealUintType { + usedInts++ + } else { + usedBytes++ + } } } - fmt.Fprintf(report, "\tID %d, local state used %d/%d uints, %d/%d byte slices\n", id, usedInts, localState.Schema.NumUint, usedBytes, localState.Schema.NumByteSlice) + fmt.Fprintf(report, "\tID %d, local state used %d/%d uints, %d/%d byte slices\n", localState.Id, usedInts, allocatedInts, usedBytes, allocatedBytes) } if hasError { diff --git a/cmd/goal/accountsList.go b/cmd/goal/accountsList.go index bf58c6f8e4..0fa2f4bffe 100644 --- a/cmd/goal/accountsList.go +++ b/cmd/goal/accountsList.go @@ -25,7 +25,7 @@ import ( "path/filepath" "strings" - "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/data/basics" "github.com/algorand/go-algorand/libgoal" ) @@ -205,7 +205,7 @@ func (accountList *AccountsList) loadList() { } } -func (accountList *AccountsList) outputAccount(addr string, acctInfo v1.Account, multisigInfo *libgoal.MultisigInfo) { +func (accountList *AccountsList) outputAccount(addr string, acctInfo generatedV2.Account, multisigInfo *libgoal.MultisigInfo) { if acctInfo.Address == "" { fmt.Printf("[n/a]\t%s\t%s\t[n/a] microAlgos", accountList.getNameByAddress(addr), addr) } else { @@ -225,25 +225,28 @@ func (accountList *AccountsList) outputAccount(addr string, acctInfo v1.Account, if multisigInfo != nil { fmt.Printf("\t[%d/%d multisig]", multisigInfo.Threshold, len(multisigInfo.PKs)) } - if len(acctInfo.AssetParams) > 0 { + if acctInfo.CreatedAssets != nil && len(*acctInfo.CreatedAssets) > 0 { var out []string - for curid, params := range acctInfo.AssetParams { - _, unitName := unicodePrintable(params.UnitName) - out = append(out, fmt.Sprintf("%d (%d %s)", curid, params.Total, unitName)) + for _, asset := range *acctInfo.CreatedAssets { + var unitName string + if asset.Params.UnitName != nil { + _, unitName = unicodePrintable(*asset.Params.UnitName) + } + out = append(out, fmt.Sprintf("%d (%d %s)", asset.Index, asset.Params.Total, unitName)) } fmt.Printf("\t[created asset IDs: %s]", strings.Join(out, ", ")) } - if len(acctInfo.AppParams) > 0 { + if acctInfo.CreatedApps != nil && len(*acctInfo.CreatedApps) > 0 { var out []string - for aid := range acctInfo.AppParams { - out = append(out, fmt.Sprintf("%d", aid)) + for _, app := range *acctInfo.CreatedApps { + out = append(out, fmt.Sprintf("%d", app.Id)) } fmt.Printf("\t[created app IDs: %s]", strings.Join(out, ", ")) } - if len(acctInfo.AppLocalStates) > 0 { + if acctInfo.AppsLocalState != nil && len(*acctInfo.AppsLocalState) > 0 { var out []string - for aid := range acctInfo.AppLocalStates { - out = append(out, fmt.Sprintf("%d", aid)) + for _, app := range *acctInfo.AppsLocalState { + out = append(out, fmt.Sprintf("%d", app.Id)) } fmt.Printf("\t[opted in app IDs: %s]", strings.Join(out, ", ")) } diff --git a/cmd/goal/application.go b/cmd/goal/application.go index a3204020ae..2c0e08fed8 100644 --- a/cmd/goal/application.go +++ b/cmd/goal/application.go @@ -1014,12 +1014,17 @@ var infoAppCmd = &cobra.Command{ gsch := params.GlobalStateSchema lsch := params.LocalStateSchema + epp := params.ExtraProgramPages fmt.Printf("Application ID: %d\n", appIdx) fmt.Printf("Creator: %v\n", params.Creator) fmt.Printf("Approval hash: %v\n", basics.Address(logic.HashProgram(params.ApprovalProgram))) fmt.Printf("Clear hash: %v\n", basics.Address(logic.HashProgram(params.ClearStateProgram))) + if epp != nil { + fmt.Printf("Extra program pages: %d\n", *epp) + } + if gsch != nil { fmt.Printf("Max global byteslices: %d\n", gsch.NumByteSlice) fmt.Printf("Max global integers: %d\n", gsch.NumUint) diff --git a/test/e2e-go/cli/goal/expect/goalAccountInfoTest.exp b/test/e2e-go/cli/goal/expect/goalAccountInfoTest.exp index 063651a9a9..4ba7ce1732 100644 --- a/test/e2e-go/cli/goal/expect/goalAccountInfoTest.exp +++ b/test/e2e-go/cli/goal/expect/goalAccountInfoTest.exp @@ -111,7 +111,8 @@ Opted In Apps: puts "Creating global state app" set GSTATE_GLOBAL_BYTE_SLICES 10 set GSTATE_LOCAL_BYTE_SLICES 0 - set GSTATE_APP_ID [::AlgorandGoal::AppCreate $PRIMARY_WALLET_NAME "" $PRIMARY_ACCOUNT_ADDRESS ${TEAL_PROGS_DIR}/globwrite.teal "str:value_to_write" $GSTATE_GLOBAL_BYTE_SLICES $GSTATE_LOCAL_BYTE_SLICES ${TEAL_PROGS_DIR}/clear_program_state.teal $TEST_PRIMARY_NODE_DIR] + set GSTATE_EXTRA_PAGES 2 + set GSTATE_APP_ID [::AlgorandGoal::AppCreateExPages $PRIMARY_WALLET_NAME "" $PRIMARY_ACCOUNT_ADDRESS ${TEAL_PROGS_DIR}/globwrite.teal "str:value_to_write" $GSTATE_GLOBAL_BYTE_SLICES $GSTATE_LOCAL_BYTE_SLICES ${TEAL_PROGS_DIR}/clear_program_state.teal $TEST_PRIMARY_NODE_DIR $GSTATE_EXTRA_PAGES] puts "Creating local state app" set LSTATE_GLOBAL_BYTE_SLICES 0 @@ -133,7 +134,7 @@ Held Assets: \tID $CCOIN_ASSET_ID, C-Coin, balance 1000 units \tID $DCOIN_ASSET_ID, D-Coin, balance 10.00 $DCOIN_UNIT_NAME (frozen) Created Apps: -\tID $GSTATE_APP_ID, global state used 0/0 uints, 1/$GSTATE_GLOBAL_BYTE_SLICES byte slices +\tID $GSTATE_APP_ID, $GSTATE_EXTRA_PAGES extra pages, global state used 0/0 uints, 1/$GSTATE_GLOBAL_BYTE_SLICES byte slices \tID $LSTATE_APP_ID, global state used 0/0 uints, 0/$LSTATE_GLOBAL_BYTE_SLICES byte slices Opted In Apps: \tID $LSTATE_APP_ID, local state used 0/1 uints, 1/$LSTATE_LOCAL_BYTE_SLICES byte slices" diff --git a/test/scripts/e2e_subs/e2e-app-extra-pages.sh b/test/scripts/e2e_subs/e2e-app-extra-pages.sh index c20b0eddb6..4852918c6a 100755 --- a/test/scripts/e2e_subs/e2e-app-extra-pages.sh +++ b/test/scripts/e2e_subs/e2e-app-extra-pages.sh @@ -84,9 +84,6 @@ if [[ $RES != *"${EXPERROR}"* ]]; then fi # App create with extra pages, succeeded -${gcmd} app create --creator ${ACCOUNT} --approval-prog "${SMALL_TEAL_FILE}" --clear-prog "${SMALL_TEAL_FILE}" --extra-pages 1 --global-byteslices 1 --global-ints 0 --local-byteslices 0 --local-ints 0 - -# App update RES=$(${gcmd} app create --creator ${ACCOUNT} --approval-prog "${SMALL_TEAL_FILE}" --clear-prog "${SMALL_TEAL_FILE}" --extra-pages 1 --global-byteslices 1 --global-ints 0 --local-byteslices 0 --local-ints 0 2>&1 || true) EXP="Created app" APPID=$(echo $RES | awk '{print $NF}') @@ -97,8 +94,13 @@ fi RES=$(${gcmd} app info --app-id ${APPID} 2>&1 || true) PROGHASH="Approval hash: 7356635AKR4FJOOKXXBWNN6HDJ5U3O2YWAOSK6NZBPMOGIQSWCL2N74VT4" +EXTRAPAGES="Extra program pages: 1" if [[ $RES != *"${PROGHASH}"* ]]; then - date '+app-extra-pages-test FAIL the application info should succeed %Y%m%d_%H%M%S' + date '+app-extra-pages-test FAIL the application approval program hash is incorrect %Y%m%d_%H%M%S' + false +fi +if [[ $RES != *"${EXTRAPAGES}"* ]]; then + date '+app-extra-pages-test FAIL the application extra pages value is incorrect %Y%m%d_%H%M%S' false fi @@ -114,3 +116,7 @@ if [[ $RES == *"${PROGHASH}"* ]]; then date '+app-extra-pages-test FAIL the application approval program should have been updated %Y%m%d_%H%M%S' false fi +if [[ $RES != *"${EXTRAPAGES}"* ]]; then + date '+app-extra-pages-test FAIL the application extra pages value is incorrect after update %Y%m%d_%H%M%S' + false +fi