diff options
author | Zeph Grunschlag <tzaffi@users.noreply.github.com> | 2021-12-17 11:28:19 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-17 11:28:19 -0500 |
commit | 9cdcb39b87cebdb44452a3ca21914472783370bd (patch) | |
tree | 43a6d33d8ed0e5045f7808529dec44fa5a160901 | |
parent | b73265c952927a3adbd14015d5e388b1a2647ee1 (diff) |
Minimum Account Balance in Algod (#3287)
-rw-r--r-- | cmd/goal/account.go | 2 | ||||
-rw-r--r-- | cmd/tealdbg/local_test.go | 3 | ||||
-rw-r--r-- | daemon/algod/api/algod.oas2.json | 7 | ||||
-rw-r--r-- | daemon/algod/api/algod.oas3.yml | 5 | ||||
-rw-r--r-- | daemon/algod/api/server/v2/account.go | 7 | ||||
-rw-r--r-- | daemon/algod/api/server/v2/account_test.go | 4 | ||||
-rw-r--r-- | daemon/algod/api/server/v2/generated/private/routes.go | 153 | ||||
-rw-r--r-- | daemon/algod/api/server/v2/generated/private/types.go | 5 | ||||
-rw-r--r-- | daemon/algod/api/server/v2/generated/routes.go | 345 | ||||
-rw-r--r-- | daemon/algod/api/server/v2/generated/types.go | 5 | ||||
-rw-r--r-- | daemon/algod/api/server/v2/handlers.go | 7 | ||||
-rw-r--r-- | daemon/algod/api/server/v2/test/helpers.go | 1 | ||||
-rw-r--r-- | test/e2e-go/cli/goal/expect/README.md | 9 | ||||
-rw-r--r-- | test/e2e-go/cli/goal/expect/goalAccountInfoTest.exp | 9 | ||||
-rwxr-xr-x | test/scripts/e2e.sh | 9 | ||||
-rwxr-xr-x | test/scripts/e2e_subs/min_balance.py | 238 | ||||
-rwxr-xr-x | test/scripts/e2e_subs/min_balance.sh | 39 |
17 files changed, 590 insertions, 258 deletions
diff --git a/cmd/goal/account.go b/cmd/goal/account.go index bae3a73bb..b585a8801 100644 --- a/cmd/goal/account.go +++ b/cmd/goal/account.go @@ -696,6 +696,8 @@ func printAccountInfo(client libgoal.Client, address string, account generatedV2 fmt.Fprintf(report, "\tID %d, local state used %d/%d uints, %d/%d byte slices\n", localState.Id, usedInts, allocatedInts, usedBytes, allocatedBytes) } + fmt.Fprintf(report, "Minimum Balance:\t%v microAlgos\n", account.MinBalance) + if hasError { fmt.Fprint(os.Stderr, errorReport.String()) } diff --git a/cmd/tealdbg/local_test.go b/cmd/tealdbg/local_test.go index d78c402e8..0546835c5 100644 --- a/cmd/tealdbg/local_test.go +++ b/cmd/tealdbg/local_test.go @@ -26,6 +26,7 @@ import ( "strings" "testing" + "github.com/algorand/go-algorand/config" v2 "github.com/algorand/go-algorand/daemon/algod/api/server/v2" "github.com/algorand/go-algorand/data/basics" "github.com/algorand/go-algorand/data/transactions" @@ -984,7 +985,7 @@ func TestLocalBalanceAdapterIndexer(t *testing.T) { case strings.HasPrefix(r.URL.Path, accountPath): w.WriteHeader(200) if r.URL.Path[len(accountPath):] == brs.Addr.String() { - account, err := v2.AccountDataToAccount(brs.Addr.String(), &brs.AccountData, map[basics.AssetIndex]string{}, 100, basics.MicroAlgos{Raw: 0}) + account, err := v2.AccountDataToAccount(brs.Addr.String(), &brs.AccountData, map[basics.AssetIndex]string{}, 100, &config.ConsensusParams{MinBalance: 100000}, basics.MicroAlgos{Raw: 0}) a.NoError(err) accountResponse := AccountIndexerResponse{Account: account, CurrentRound: 100} response, err := json.Marshal(accountResponse) diff --git a/daemon/algod/api/algod.oas2.json b/daemon/algod/api/algod.oas2.json index 0eb127d8c..c6e2816d8 100644 --- a/daemon/algod/api/algod.oas2.json +++ b/daemon/algod/api/algod.oas2.json @@ -1354,7 +1354,8 @@ "pending-rewards", "amount-without-pending-rewards", "rewards", - "status" + "status", + "min-balance" ], "properties": { "address": { @@ -1365,6 +1366,10 @@ "description": "\\[algo\\] total number of MicroAlgos in the account", "type": "integer" }, + "min-balance": { + "description": "MicroAlgo balance required by the account.\n\nThe requirement grows based on asset and application usage.", + "type": "integer" + }, "amount-without-pending-rewards": { "description": "specifies the amount of MicroAlgos in the account, without the pending rewards.", "type": "integer" diff --git a/daemon/algod/api/algod.oas3.yml b/daemon/algod/api/algod.oas3.yml index b30282310..86ac76a5d 100644 --- a/daemon/algod/api/algod.oas3.yml +++ b/daemon/algod/api/algod.oas3.yml @@ -726,6 +726,10 @@ }, "type": "array" }, + "min-balance": { + "description": "MicroAlgo balance required by the account.\n\nThe requirement grows based on asset and application usage.", + "type": "integer" + }, "participation": { "$ref": "#/components/schemas/AccountParticipation" }, @@ -763,6 +767,7 @@ "address", "amount", "amount-without-pending-rewards", + "min-balance", "pending-rewards", "rewards", "round", diff --git a/daemon/algod/api/server/v2/account.go b/daemon/algod/api/server/v2/account.go index 2187a1068..a723db72f 100644 --- a/daemon/algod/api/server/v2/account.go +++ b/daemon/algod/api/server/v2/account.go @@ -22,6 +22,7 @@ import ( "math" "sort" + "github.com/algorand/go-algorand/config" "github.com/algorand/go-algorand/crypto" "github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated" "github.com/algorand/go-algorand/data/basics" @@ -30,7 +31,8 @@ import ( // AccountDataToAccount converts basics.AccountData to v2.generated.Account func AccountDataToAccount( address string, record *basics.AccountData, assetsCreators map[basics.AssetIndex]string, - lastRound basics.Round, amountWithoutPendingRewards basics.MicroAlgos, + lastRound basics.Round, consensus *config.ConsensusParams, + amountWithoutPendingRewards basics.MicroAlgos, ) (generated.Account, error) { assets := make([]generated.AssetHolding, 0, len(record.Assets)) @@ -108,6 +110,8 @@ func AccountDataToAccount( return generated.Account{}, errors.New("overflow on pending reward calculation") } + minBalance := record.MinBalance(consensus) + return generated.Account{ SigType: nil, Round: uint64(lastRound), @@ -126,6 +130,7 @@ func AccountDataToAccount( AppsLocalState: &appsLocalState, AppsTotalSchema: &totalAppSchema, AppsTotalExtraPages: numOrNil(totalExtraPages), + MinBalance: minBalance.Raw, }, nil } diff --git a/daemon/algod/api/server/v2/account_test.go b/daemon/algod/api/server/v2/account_test.go index f7dd96d80..61498fbe4 100644 --- a/daemon/algod/api/server/v2/account_test.go +++ b/daemon/algod/api/server/v2/account_test.go @@ -102,7 +102,7 @@ func TestAccount(t *testing.T) { b := a.WithUpdatedRewards(proto, 100) addr := basics.Address{}.String() - conv, err := AccountDataToAccount(addr, &b, map[basics.AssetIndex]string{}, round, a.MicroAlgos) + conv, err := AccountDataToAccount(addr, &b, map[basics.AssetIndex]string{}, round, &proto, a.MicroAlgos) require.NoError(t, err) require.Equal(t, addr, conv.Address) require.Equal(t, b.MicroAlgos.Raw, conv.Amount) @@ -196,7 +196,7 @@ func TestAccount(t *testing.T) { // convert the same account a few more times to make sure we always // produce the same generated.Account for i := 0; i < 10; i++ { - anotherConv, err := AccountDataToAccount(addr, &b, map[basics.AssetIndex]string{}, round, a.MicroAlgos) + anotherConv, err := AccountDataToAccount(addr, &b, map[basics.AssetIndex]string{}, round, &proto, a.MicroAlgos) require.NoError(t, err) require.Equal(t, protocol.EncodeJSON(conv), protocol.EncodeJSON(anotherConv)) diff --git a/daemon/algod/api/server/v2/generated/private/routes.go b/daemon/algod/api/server/v2/generated/private/routes.go index e294ea1e7..56baf1f2b 100644 --- a/daemon/algod/api/server/v2/generated/private/routes.go +++ b/daemon/algod/api/server/v2/generated/private/routes.go @@ -337,82 +337,83 @@ var swaggerSpec = []string{ "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", + "GUfr6/fX/xsAAP//tpthUSegAAA=", } // GetSwagger returns the Swagger specification corresponding to the generated code diff --git a/daemon/algod/api/server/v2/generated/private/types.go b/daemon/algod/api/server/v2/generated/private/types.go index 78137ac3e..9e6d5685b 100644 --- a/daemon/algod/api/server/v2/generated/private/types.go +++ b/daemon/algod/api/server/v2/generated/private/types.go @@ -49,6 +49,11 @@ type Account struct { // Note: the raw account uses `map[int] -> Asset` for this type. CreatedAssets *[]Asset `json:"created-assets,omitempty"` + // MicroAlgo balance required by the account. + // + // The requirement grows based on asset and application usage. + MinBalance uint64 `json:"min-balance"` + // AccountParticipation describes the parameters used by this account in consensus protocol. Participation *AccountParticipation `json:"participation,omitempty"` diff --git a/daemon/algod/api/server/v2/generated/routes.go b/daemon/algod/api/server/v2/generated/routes.go index 2962a328a..4d3d7bd11 100644 --- a/daemon/algod/api/server/v2/generated/routes.go +++ b/daemon/algod/api/server/v2/generated/routes.go @@ -617,178 +617,179 @@ func RegisterHandlers(router interface { var swaggerSpec = []string{ "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", - "HcEdLqVk55g78cPl/wsAAP//K7GmSonxAAA=", + "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", + "pZTsHHMnfrj8fwEAAP///pnN5DLyAAA=", } // GetSwagger returns the Swagger specification corresponding to the generated code diff --git a/daemon/algod/api/server/v2/generated/types.go b/daemon/algod/api/server/v2/generated/types.go index b9066ba0e..41d33126d 100644 --- a/daemon/algod/api/server/v2/generated/types.go +++ b/daemon/algod/api/server/v2/generated/types.go @@ -49,6 +49,11 @@ type Account struct { // Note: the raw account uses `map[int] -> Asset` for this type. CreatedAssets *[]Asset `json:"created-assets,omitempty"` + // MicroAlgo balance required by the account. + // + // The requirement grows based on asset and application usage. + MinBalance uint64 `json:"min-balance"` + // AccountParticipation describes the parameters used by this account in consensus protocol. Participation *AccountParticipation `json:"participation,omitempty"` diff --git a/daemon/algod/api/server/v2/handlers.go b/daemon/algod/api/server/v2/handlers.go index da47ce350..6541311a3 100644 --- a/daemon/algod/api/server/v2/handlers.go +++ b/daemon/algod/api/server/v2/handlers.go @@ -239,6 +239,11 @@ func (v2 *Handlers) AccountInformation(ctx echo.Context, address string, params return internalError(ctx, err, errFailedLookingUpLedger, v2.Log) } + consensus, err := myLedger.ConsensusParams(lastRound) + if err != nil { + return internalError(ctx, err, fmt.Sprintf("could not retrieve consensus information for last round (%d)", lastRound), v2.Log) + } + if handle == protocol.CodecHandle { data, err := encode(handle, record) if err != nil { @@ -270,7 +275,7 @@ func (v2 *Handlers) AccountInformation(ctx echo.Context, address string, params } } - account, err := AccountDataToAccount(address, &record, assetsCreators, lastRound, amountWithoutPendingRewards) + account, err := AccountDataToAccount(address, &record, assetsCreators, lastRound, &consensus, amountWithoutPendingRewards) if err != nil { return internalError(ctx, err, errInternalFailure, v2.Log) } diff --git a/daemon/algod/api/server/v2/test/helpers.go b/daemon/algod/api/server/v2/test/helpers.go index 31e6053a6..dda735783 100644 --- a/daemon/algod/api/server/v2/test/helpers.go +++ b/daemon/algod/api/server/v2/test/helpers.go @@ -73,6 +73,7 @@ var poolAddrResponseGolden = generatedV2.AccountResponse{ AppsLocalState: &appLocalStates, AppsTotalSchema: &appsTotalSchema, CreatedApps: &appCreatedApps, + MinBalance: 100000, } var txnPoolGolden = make([]transactions.SignedTxn, 2) diff --git a/test/e2e-go/cli/goal/expect/README.md b/test/e2e-go/cli/goal/expect/README.md index ea3dd026d..cde94390f 100644 --- a/test/e2e-go/cli/goal/expect/README.md +++ b/test/e2e-go/cli/goal/expect/README.md @@ -77,6 +77,15 @@ go test -v test/e2e-go/cli/goal/expect/goal_expect_test.go TESTFILTER=foobar[0-9]Test TESTDIR=baz go test -v test/e2e-go/cli/goal/expect/goal_expect_test.go ``` +In particular, if you want to run `goalAccountInfoTest.exp` you'll need to create a temporary directory such as `deletemeTemp` with +``` +mkdir test/e2e-go/cli/goal/expect/deletemeTemp +``` +and then run the following command: +``` +TESTFILTER=goalAccountInfoTest TESTDIR=deletemeTemp go test -v test/e2e-go/cli/goal/expect/goal_expect_test.go +``` +If you're running **exactly the same command again**, make sure to _delete_ and _re-create_ the temp directory first. > Of course, a test can always be run directly by `expect`, i.e. `expect rekeyTest.exp $TESTDIR $TESTDATADIR`. diff --git a/test/e2e-go/cli/goal/expect/goalAccountInfoTest.exp b/test/e2e-go/cli/goal/expect/goalAccountInfoTest.exp index 4ba7ce173..a7e9ad1e3 100644 --- a/test/e2e-go/cli/goal/expect/goalAccountInfoTest.exp +++ b/test/e2e-go/cli/goal/expect/goalAccountInfoTest.exp @@ -40,7 +40,8 @@ Held Assets: Created Apps: \t<none> Opted In Apps: -\t<none>" +\t<none> +Minimum Balance:\t100000 microAlgos" # Check info with no assets puts "goal account info -w $PRIMARY_WALLET_NAME -a $PRIMARY_ACCOUNT_ADDRESS -d $TEST_PRIMARY_NODE_DIR" @@ -97,7 +98,8 @@ Held Assets: Created Apps: \t<none> Opted In Apps: -\t<none>" +\t<none> +Minimum Balance:\t500000 microAlgos" # Check info with assets puts "goal account info -w $PRIMARY_WALLET_NAME -a $PRIMARY_ACCOUNT_ADDRESS -d $TEST_PRIMARY_NODE_DIR" @@ -137,7 +139,8 @@ Created Apps: \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" +\tID $LSTATE_APP_ID, local state used 0/1 uints, 1/$LSTATE_LOCAL_BYTE_SLICES byte slices +Minimum Balance:\t1578500 microAlgos" # Check info with assets and apps puts "goal account info -w $PRIMARY_WALLET_NAME -a $PRIMARY_ACCOUNT_ADDRESS -d $TEST_PRIMARY_NODE_DIR" diff --git a/test/scripts/e2e.sh b/test/scripts/e2e.sh index 05754825e..a587bc201 100755 --- a/test/scripts/e2e.sh +++ b/test/scripts/e2e.sh @@ -121,7 +121,14 @@ if [ -z "$E2E_TEST_FILTER" ] || [ "$E2E_TEST_FILTER" == "SCRIPTS" ]; then python3 -m venv "${TEMPDIR}/ve" . "${TEMPDIR}/ve/bin/activate" "${TEMPDIR}/ve/bin/pip3" install --upgrade pip - "${TEMPDIR}/ve/bin/pip3" install --upgrade py-algorand-sdk cryptography + "${TEMPDIR}/ve/bin/pip3" install --upgrade cryptograpy + + # Pin a version of our python SDK's so that breaking changes don't spuriously break our tests. + # Please update as necessary. + "${TEMPDIR}/ve/bin/pip3" install py-algorand-sdk==1.9.0b1 + + # Enable remote debugging: + "${TEMPDIR}/ve/bin/pip3" install --upgrade debugpy duration "e2e client setup" if [ $INTERACTIVE ]; then diff --git a/test/scripts/e2e_subs/min_balance.py b/test/scripts/e2e_subs/min_balance.py new file mode 100755 index 000000000..b7376fd37 --- /dev/null +++ b/test/scripts/e2e_subs/min_balance.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python + +from base64 import b64decode +from datetime import datetime +from pathlib import PurePath +import sys + +import algosdk.future.transaction as txn + +from goal import Goal + +# Set INTERACTIVE True if you want to run a remote debugger interactively on the given PORT +INTERACTIVE, DEBUGPORT = False, 4312 + + +def initialize_debugger(): + import multiprocessing + + if multiprocessing.current_process().pid > 1: + import debugpy + + debugpy.listen(("0.0.0.0", DEBUGPORT)) + print("Debugger is ready to be attached, press F5", flush=True) + debugpy.wait_for_client() + print("Visual Studio Code debugger is now attached", flush=True) + + +if INTERACTIVE: + initialize_debugger() + + +CONSENSUS_MIN_BALANCE = 100_000 +ASSET_MIN_BALANCE = 100_000 +APP_MIN_BALANCE = 100_000 +OPTIN_MIN_BALANCE = 100_000 +# app schemas: +APP_KV_MIN_BALANCE = 25_000 +APP_INTS_MIN_BALANCE = 3_500 +APP_BYTES_MIN_BALANCE = 25_000 + +# per userBalance.go::MinBalance() as of Dec 2021: +EXTRA_PAGE_MIN_BALANCE = APP_MIN_BALANCE + +TEAL = f"""#pragma version 5 +byte "Hello Min Balance!" +log + +// even when creating the app, calc the min balance: +byte "min_balance=" +log + +txn Accounts 0 +min_balance +itob +log + +int 1""" + + +def get_endpoint_info(goal) -> dict: + return { + "algod": { + "url": goal.algod.algod_address, + "auth": goal.algod.algod_token, + }, + "kmd": { + "url": goal.kmd.kmd_address, + "auth": goal.kmd.kmd_token, + }, + } + + +def get_pysdk_min_balance(goal, account): + return goal.algod.account_info(account)["min-balance"] + + +def create_sender_min_balance_app(goal): + txinfo, err = goal.app_create(goal.account, goal.assemble(TEAL)) + assert not err, f"err: {err}" + + appid = txinfo["application-index"] + creator_min_balance = int.from_bytes(b64decode(txinfo["logs"][2]), byteorder="big") + return appid, creator_min_balance + + +def assert_teal_min_balance( + goal, account, expected_account_mb, expected_goal_mb, goal_only=False +): + appid, goal_mb = create_sender_min_balance_app(goal) + assert ( + goal_mb == expected_goal_mb + ), f"GOAL teal v. expected: {goal_mb} != {expected_goal_mb}" + + txinfo, err = goal.app_call(account, appid) + assert not err, f"err = {err}" + + if goal_only: + return + + min_balance = int.from_bytes(b64decode(txinfo["logs"][2]), byteorder="big") + assert ( + min_balance == expected_account_mb + ), f"SENDER teal v. expected: {min_balance} != {expected_account_mb}" + + +def assert_min_balance( + goal, account, expected_sender_mb, expected_goal_mb, goal_only=False +): + algod_mb = get_pysdk_min_balance(goal, account) + assert ( + algod_mb == expected_sender_mb + ), f"SENDER algod v. expected: {algod_mb} != {expected_sender_mb}" + assert_teal_min_balance( + goal, account, expected_sender_mb, expected_goal_mb, goal_only=goal_only + ) + + +script_path, WALLET = sys.argv +ppath = PurePath(script_path) + +CWD, SCRIPT = ppath.parent, ppath.name +TEAL_DIR = CWD / "tealprogs" + +stamp = datetime.now().strftime("%Y%m%d_%H%M%S") +print(f"Running {SCRIPT} inside {CWD} @ {stamp}") + +# Initialize goal +goal = Goal(WALLET, autosend=True) +rest_endpoints = get_endpoint_info(goal) +print(f"Python Goal cennected to {rest_endpoints}") + + +joe = goal.new_account() +flo = goal.new_account() + +print(f"Joe & Flo: {joe}, {flo}") + +txinfo, err = goal.pay(goal.account, joe, amt=50_000_000, send=True) +txinfo, err = goal.pay(goal.account, flo, amt=100_000_000, send=True) + +expected_goal_mb = CONSENSUS_MIN_BALANCE + APP_MIN_BALANCE + +# starting out, should be at global min +assert_min_balance(goal, flo, CONSENSUS_MIN_BALANCE, expected_goal_mb) + +expected_goal_mb += APP_MIN_BALANCE +assert_min_balance(goal, joe, CONSENSUS_MIN_BALANCE, expected_goal_mb) + + +# flo creates an asset +txinfo, err = goal.asset_create( + flo, total=10_000, unit_name="oz", asset_name="Gold", manager=flo, send=True +) +assert not err, err +assets = {"Gold": txinfo["asset-index"]} + +expected_mb = CONSENSUS_MIN_BALANCE + ASSET_MIN_BALANCE +expected_goal_mb += APP_MIN_BALANCE +assert_min_balance(goal, flo, expected_mb, expected_goal_mb) + + +# goal creates 2 assets +for total, unit, asset in [(1000, "oz", "Silver"), (100, "oz", "Platinum")]: + txinfo, err = goal.asset_create( + goal.account, + total=total, + unit_name=unit, + asset_name=asset, + manager=goal.account, + send=True, + ) + assets[asset] = txinfo["asset-index"] + assert not err, err + +expected_goal_mb += 2 * ASSET_MIN_BALANCE +assert_min_balance( + goal, + goal.account, + expected_goal_mb, + expected_goal_mb + APP_MIN_BALANCE, + goal_only=True, +) +expected_goal_mb += APP_MIN_BALANCE + +# joe opts into Gold and Silver: +txinfo, err = goal.axfer(joe, joe, 0, assets["Gold"], send=True) +txinfo, err = goal.axfer(joe, joe, 0, assets["Silver"], send=True) +assert not err, err + +expected_mb = CONSENSUS_MIN_BALANCE + 2 * ASSET_MIN_BALANCE +expected_goal_mb += APP_MIN_BALANCE +assert_min_balance(goal, joe, expected_mb, expected_goal_mb) + +# next, destroy Gold and Silver +txinfo, err = goal.acfg(flo, index=assets["Gold"], send=True) +assert not err, err +expected_mb = CONSENSUS_MIN_BALANCE +expected_goal_mb += APP_MIN_BALANCE +assert_min_balance(goal, flo, expected_mb, expected_goal_mb) + +txinfo, err = goal.acfg(goal.account, index=assets["Silver"], send=True) +assert not err, err +expected_goal_mb -= ASSET_MIN_BALANCE +assert_min_balance( + goal, + goal.account, + expected_goal_mb, + expected_goal_mb + APP_MIN_BALANCE, + goal_only=True, +) +expected_goal_mb += APP_MIN_BALANCE + + +# flo creates an app with 2 global schema ints, 10 global schema bytes, 1 extra page +txinfo, err = goal.app_create( + flo, + goal.assemble(TEAL), + local_schema=(2, 0), + global_schema=(0, 10), + extra_pages=1, + send=True, +) +assert not err, err +expected_mb = ( + CONSENSUS_MIN_BALANCE + + APP_MIN_BALANCE + # Not these local var requirements because not opting in + # + 2 * APP_KV_MIN_BALANCE + # + 2 * APP_INTS_MIN_BALANCE + + 10 * APP_KV_MIN_BALANCE + + 10 * APP_BYTES_MIN_BALANCE + + EXTRA_PAGE_MIN_BALANCE +) +expected_goal_mb += APP_MIN_BALANCE +assert_min_balance(goal, flo, expected_mb, expected_goal_mb) + +stamp = datetime.now().strftime("%Y%m%d_%H%M%S") +print(f"Running {SCRIPT} inside {CWD} @ {stamp}") diff --git a/test/scripts/e2e_subs/min_balance.sh b/test/scripts/e2e_subs/min_balance.sh new file mode 100755 index 000000000..94a961a81 --- /dev/null +++ b/test/scripts/e2e_subs/min_balance.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +set -e +set -x +set -o pipefail +export SHELLOPTS + +WALLET=$1 + +echo "NETDIR=$NETDIR" + +# Directory of this bash program +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +echo "DIR=$DIR" + + +gcmd="goal -w ${WALLET}" + +ACCOUNT=$(${gcmd} account list|awk '{ print $3 }') + +echo `$gcmd account list` +echo $ACCOUNT + +echo `$gcmd account balance -a $ACCOUNT` + +echo `$gcmd account info -a $ACCOUNT` + +MINBAL=$(${gcmd} account info -a ${ACCOUNT}|grep 'Minimum Balance:'| awk '{ print $3 }') + +echo "Minimum Balance --> $MINBAL" + +EXPECTED="100000" +if [[ ${MINBAL} != ${EXPECTED} ]]; then + date '+min_balance FAIL goal account info should return expected Minimum Ballance %Y%m%d_%H%M%S' + false +fi + +# see ./min_balance.py for more complicated scenarios |