summaryrefslogtreecommitdiff
path: root/data/transactions/logic/evalStateful_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'data/transactions/logic/evalStateful_test.go')
-rw-r--r--data/transactions/logic/evalStateful_test.go930
1 files changed, 231 insertions, 699 deletions
diff --git a/data/transactions/logic/evalStateful_test.go b/data/transactions/logic/evalStateful_test.go
index f782fcce9..f270bd541 100644
--- a/data/transactions/logic/evalStateful_test.go
+++ b/data/transactions/logic/evalStateful_test.go
@@ -19,50 +19,18 @@ package logic
import (
"encoding/hex"
"fmt"
- "math/rand"
"strings"
"testing"
"github.com/stretchr/testify/require"
- "github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/data/transactions/logictest"
"github.com/algorand/go-algorand/protocol"
"github.com/algorand/go-algorand/test/partitiontest"
)
-type balanceRecord struct {
- addr basics.Address
- balance uint64
- locals map[basics.AppIndex]basics.TealKeyValue
- holdings map[basics.AssetIndex]basics.AssetHolding
- mods map[basics.AppIndex]map[string]basics.ValueDelta
-}
-
-// In our test ledger, we don't store the creatables with their
-// creators, so we need to carry the creator around with them.
-type appParams struct {
- basics.AppParams
- Creator basics.Address
-}
-
-type asaParams struct {
- basics.AssetParams
- Creator basics.Address
-}
-
-type testLedger struct {
- balances map[basics.Address]balanceRecord
- applications map[basics.AppIndex]appParams
- assets map[basics.AssetIndex]asaParams
- trackedCreatables map[int]basics.CreatableIndex
- appID basics.AppIndex
- creatorAddr basics.Address
- mods map[basics.AppIndex]map[string]basics.ValueDelta
- logs []basics.LogItem
-}
-
func makeApp(li uint64, lb uint64, gi uint64, gb uint64) basics.AppParams {
return basics.AppParams{
ApprovalProgram: []byte{},
@@ -76,412 +44,24 @@ func makeApp(li uint64, lb uint64, gi uint64, gb uint64) basics.AppParams {
}
}
-func makeBalanceRecord(addr basics.Address, balance uint64) balanceRecord {
- br := balanceRecord{
- addr: addr,
- balance: balance,
- locals: make(map[basics.AppIndex]basics.TealKeyValue),
- holdings: make(map[basics.AssetIndex]basics.AssetHolding),
- mods: make(map[basics.AppIndex]map[string]basics.ValueDelta),
- }
- return br
+func makeSampleEnv() (EvalParams, *logictest.Ledger) {
+ return makeSampleEnvWithVersion(LogicVersion)
}
-func makeSampleEnv() (EvalParams, *testLedger) {
+func makeSampleEnvWithVersion(version uint64) (EvalParams, *logictest.Ledger) {
txn := makeSampleTxn()
- ep := defaultEvalParams(nil, &txn)
+ ep := defaultEvalParamsWithVersion(nil, &txn, version)
ep.TxnGroup = makeSampleTxnGroup(txn)
- ledger := makeTestLedger(map[basics.Address]uint64{})
+ ledger := logictest.MakeLedger(map[basics.Address]uint64{})
ep.Ledger = ledger
return ep, ledger
}
-func makeTestLedger(balances map[basics.Address]uint64) *testLedger {
- l := new(testLedger)
- l.balances = make(map[basics.Address]balanceRecord)
- for addr, balance := range balances {
- l.newAccount(addr, balance)
- }
- l.applications = make(map[basics.AppIndex]appParams)
- l.assets = make(map[basics.AssetIndex]asaParams)
- l.trackedCreatables = make(map[int]basics.CreatableIndex)
- l.mods = make(map[basics.AppIndex]map[string]basics.ValueDelta)
- return l
-}
-
-func (l *testLedger) reset() {
- l.mods = make(map[basics.AppIndex]map[string]basics.ValueDelta)
- for addr, br := range l.balances {
- br.mods = make(map[basics.AppIndex]map[string]basics.ValueDelta)
- l.balances[addr] = br
- }
-}
-
-func (l *testLedger) newAccount(addr basics.Address, balance uint64) {
- l.balances[addr] = makeBalanceRecord(addr, balance)
-}
-
-func (l *testLedger) newApp(creator basics.Address, appID basics.AppIndex, params basics.AppParams) {
- l.appID = appID
- params = params.Clone()
- if params.GlobalState == nil {
- params.GlobalState = make(basics.TealKeyValue)
- }
- l.applications[appID] = appParams{
- Creator: creator,
- AppParams: params.Clone(),
- }
- br, ok := l.balances[creator]
- if !ok {
- br = makeBalanceRecord(creator, 0)
- }
- br.locals[appID] = make(map[string]basics.TealValue)
- l.balances[creator] = br
-}
-
-func (l *testLedger) newAsset(creator basics.Address, assetID basics.AssetIndex, params basics.AssetParams) {
- l.assets[assetID] = asaParams{
- Creator: creator,
- AssetParams: params,
- }
- br, ok := l.balances[creator]
- if !ok {
- br = makeBalanceRecord(creator, 0)
- }
- br.holdings[assetID] = basics.AssetHolding{Amount: params.Total, Frozen: params.DefaultFrozen}
- l.balances[creator] = br
-}
-
-func (l *testLedger) setHolding(addr basics.Address, assetID uint64, amount uint64, frozen bool) {
- br, ok := l.balances[addr]
- if !ok {
- br = makeBalanceRecord(addr, 0)
- }
- br.holdings[basics.AssetIndex(assetID)] = basics.AssetHolding{Amount: amount, Frozen: frozen}
- l.balances[addr] = br
-}
-
-func (l *testLedger) Round() basics.Round {
- return basics.Round(rand.Uint32() + 1)
-}
-
-func (l *testLedger) LatestTimestamp() int64 {
- return int64(rand.Uint32() + 1)
-}
-
-func (l *testLedger) Balance(addr basics.Address) (amount basics.MicroAlgos, err error) {
- if l.balances == nil {
- err = fmt.Errorf("empty ledger")
- return
- }
- br, ok := l.balances[addr]
- if !ok {
- err = fmt.Errorf("no such address")
- return
- }
- return basics.MicroAlgos{Raw: br.balance}, nil
-}
-
-func (l *testLedger) MinBalance(addr basics.Address, proto *config.ConsensusParams) (amount basics.MicroAlgos, err error) {
- if l.balances == nil {
- err = fmt.Errorf("empty ledger")
- return
- }
- br, ok := l.balances[addr]
- if !ok {
- err = fmt.Errorf("no such address")
- return
- }
-
- var min uint64
-
- // First, base MinBalance
- min = proto.MinBalance
-
- // MinBalance for each Asset
- assetCost := basics.MulSaturate(proto.MinBalance, uint64(len(br.holdings)))
- min = basics.AddSaturate(min, assetCost)
-
- // Base MinBalance + GlobalStateSchema.MinBalance + ExtraProgramPages MinBalance for each created application
- for _, params := range l.applications {
- if params.Creator == addr {
- min = basics.AddSaturate(min, proto.AppFlatParamsMinBalance)
- min = basics.AddSaturate(min, params.GlobalStateSchema.MinBalance(proto).Raw)
- min = basics.AddSaturate(min, basics.MulSaturate(proto.AppFlatParamsMinBalance, uint64(params.ExtraProgramPages)))
- }
- }
-
- // Base MinBalance + LocalStateSchema.MinBalance for each opted in application
- for idx := range br.locals {
- min = basics.AddSaturate(min, proto.AppFlatParamsMinBalance)
- min = basics.AddSaturate(min, l.applications[idx].LocalStateSchema.MinBalance(proto).Raw)
- }
-
- return basics.MicroAlgos{Raw: min}, nil
-}
-
-func (l *testLedger) GetGlobal(appIdx basics.AppIndex, key string) (basics.TealValue, bool, error) {
- if appIdx == basics.AppIndex(0) {
- appIdx = l.appID
- }
- params, ok := l.applications[appIdx]
- if !ok {
- return basics.TealValue{}, false, fmt.Errorf("no such app")
- }
-
- // return most recent value if available
- tkvm, ok := l.mods[appIdx]
- if ok {
- val, ok := tkvm[key]
- if ok {
- tv, ok := val.ToTealValue()
- return tv, ok, nil
- }
- }
-
- // otherwise return original one
- val, ok := params.GlobalState[key]
- return val, ok, nil
-}
-
-func (l *testLedger) SetGlobal(key string, value basics.TealValue) error {
- appIdx := l.appID
- params, ok := l.applications[appIdx]
- if !ok {
- return fmt.Errorf("no such app")
- }
-
- // if writing the same value, return
- // this simulates real ledger behavior for tests
- val, ok := params.GlobalState[key]
- if ok && val == value {
- return nil
- }
-
- // write to deltas
- _, ok = l.mods[appIdx]
- if !ok {
- l.mods[appIdx] = make(map[string]basics.ValueDelta)
- }
- l.mods[appIdx][key] = value.ToValueDelta()
- return nil
-}
-
-func (l *testLedger) DelGlobal(key string) error {
- appIdx := l.appID
- params, ok := l.applications[appIdx]
- if !ok {
- return fmt.Errorf("no such app")
- }
-
- exist := false
- if _, ok := params.GlobalState[key]; ok {
- exist = true
- }
-
- _, ok = l.mods[appIdx]
- if !ok && !exist {
- // nothing to delete
- return nil
- }
- if !ok {
- l.mods[appIdx] = make(map[string]basics.ValueDelta)
- }
- _, ok = l.mods[appIdx][key]
- if ok || exist {
- l.mods[appIdx][key] = basics.ValueDelta{Action: basics.DeleteAction}
- }
- return nil
-}
-
-func (l *testLedger) GetLocal(addr basics.Address, appIdx basics.AppIndex, key string, accountIdx uint64) (basics.TealValue, bool, error) {
- if appIdx == 0 {
- appIdx = l.appID
- }
- br, ok := l.balances[addr]
- if !ok {
- return basics.TealValue{}, false, fmt.Errorf("no such address")
- }
- tkvd, ok := br.locals[appIdx]
- if !ok {
- return basics.TealValue{}, false, fmt.Errorf("no app for account")
- }
-
- // check deltas first
- tkvm, ok := br.mods[appIdx]
- if ok {
- val, ok := tkvm[key]
- if ok {
- tv, ok := val.ToTealValue()
- return tv, ok, nil
- }
- }
-
- val, ok := tkvd[key]
- return val, ok, nil
-}
-
-func (l *testLedger) SetLocal(addr basics.Address, key string, value basics.TealValue, accountIdx uint64) error {
- appIdx := l.appID
-
- br, ok := l.balances[addr]
- if !ok {
- return fmt.Errorf("no such address")
- }
- tkv, ok := br.locals[appIdx]
- if !ok {
- return fmt.Errorf("no app for account")
- }
-
- // if writing the same value, return
- // this simulates real ledger behavior for tests
- val, ok := tkv[key]
- if ok && val == value {
- return nil
- }
-
- // write to deltas
- _, ok = br.mods[appIdx]
- if !ok {
- br.mods[appIdx] = make(map[string]basics.ValueDelta)
- }
- br.mods[appIdx][key] = value.ToValueDelta()
- return nil
-}
-
-func (l *testLedger) DelLocal(addr basics.Address, key string, accountIdx uint64) error {
- appIdx := l.appID
-
- br, ok := l.balances[addr]
- if !ok {
- return fmt.Errorf("no such address")
- }
- tkv, ok := br.locals[appIdx]
- if !ok {
- return fmt.Errorf("no app for account")
- }
- exist := false
- if _, ok := tkv[key]; ok {
- exist = true
- }
-
- _, ok = br.mods[appIdx]
- if !ok && !exist {
- // nothing to delete
- return nil
- }
- if !ok {
- br.mods[appIdx] = make(map[string]basics.ValueDelta)
- }
- _, ok = br.mods[appIdx][key]
- if ok || exist {
- br.mods[appIdx][key] = basics.ValueDelta{Action: basics.DeleteAction}
- }
- return nil
-}
-
-func (l *testLedger) OptedIn(addr basics.Address, appIdx basics.AppIndex) (bool, error) {
- if appIdx == 0 {
- appIdx = l.appID
- }
- br, ok := l.balances[addr]
- if !ok {
- return false, fmt.Errorf("no such address")
- }
- _, ok = br.locals[appIdx]
- return ok, nil
-}
-
-func (l *testLedger) setTrackedCreatable(groupIdx int, cl basics.CreatableLocator) {
- l.trackedCreatables[groupIdx] = cl.Index
-}
-
-func (l *testLedger) GetCreatableID(groupIdx int) basics.CreatableIndex {
- return l.trackedCreatables[groupIdx]
-}
-
-func (l *testLedger) AssetHolding(addr basics.Address, assetID basics.AssetIndex) (basics.AssetHolding, error) {
- if br, ok := l.balances[addr]; ok {
- if asset, ok := br.holdings[assetID]; ok {
- return asset, nil
- }
- return basics.AssetHolding{}, fmt.Errorf("No asset for account")
- }
- return basics.AssetHolding{}, fmt.Errorf("no such address")
-}
-
-func (l *testLedger) AssetParams(assetID basics.AssetIndex) (basics.AssetParams, basics.Address, error) {
- if asset, ok := l.assets[assetID]; ok {
- return asset.AssetParams, asset.Creator, nil
- }
- return basics.AssetParams{}, basics.Address{}, fmt.Errorf("no such asset")
-}
-
-func (l *testLedger) AppParams(appID basics.AppIndex) (basics.AppParams, basics.Address, error) {
- if app, ok := l.applications[appID]; ok {
- return app.AppParams, app.Creator, nil
- }
- return basics.AppParams{}, basics.Address{}, fmt.Errorf("no such app")
-}
-
-func (l *testLedger) ApplicationID() basics.AppIndex {
- return l.appID
-}
-
-func (l *testLedger) CreatorAddress() basics.Address {
- return l.creatorAddr
-}
-
-func (l *testLedger) LocalSchema() basics.StateSchema {
- return basics.StateSchema{
- NumUint: 100,
- NumByteSlice: 100,
- }
-}
-
-func (l *testLedger) GlobalSchema() basics.StateSchema {
- return basics.StateSchema{
- NumUint: 100,
- NumByteSlice: 100,
- }
-}
-
-func (l *testLedger) GetDelta(txn *transactions.Transaction) (evalDelta basics.EvalDelta, err error) {
- if tkv, ok := l.mods[l.appID]; ok {
- evalDelta.GlobalDelta = tkv
- }
- if len(txn.Accounts) > 0 {
- accounts := make(map[basics.Address]int)
- accounts[txn.Sender] = 0
- for idx, addr := range txn.Accounts {
- accounts[addr] = idx + 1
- }
- evalDelta.LocalDeltas = make(map[uint64]basics.StateDelta)
- for addr, br := range l.balances {
- if idx, ok := accounts[addr]; ok {
- if delta, ok := br.mods[l.appID]; ok {
- evalDelta.LocalDeltas[uint64(idx)] = delta
- }
- }
- }
- }
- evalDelta.Logs = l.logs
- return
-}
-
-func (l *testLedger) AppendLog(txn *transactions.Transaction, value string) error {
-
- appIdx, err := txn.IndexByAppID(l.appID)
- if err != nil {
- return err
- }
- _, ok := l.applications[l.appID]
- if !ok {
- return fmt.Errorf("no such app")
- }
-
- l.logs = append(l.logs, basics.LogItem{ID: appIdx, Message: value})
- return nil
+func makeOldAndNewEnv(version uint64) (EvalParams, EvalParams, *logictest.Ledger) {
+ new, sharedLedger := makeSampleEnv()
+ old, _ := makeSampleEnvWithVersion(version)
+ old.Ledger = sharedLedger
+ return old, new, sharedLedger
}
func TestEvalModes(t *testing.T) {
@@ -651,14 +231,14 @@ log
Clawback: txn.Txn.Receiver,
}
algoValue := basics.TealValue{Type: basics.TealUintType, Uint: 0x77}
- ledger := makeTestLedger(
+ ledger := logictest.MakeLedger(
map[basics.Address]uint64{
txn.Txn.Sender: 1,
},
)
- ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
- ledger.balances[txn.Txn.Sender].locals[100]["ALGO"] = algoValue
- ledger.newAsset(txn.Txn.Sender, 5, params)
+ ledger.NewApp(txn.Txn.Sender, 100, basics.AppParams{})
+ ledger.NewLocal(txn.Txn.Sender, 100, "ALGO", algoValue)
+ ledger.NewAsset(txn.Txn.Sender, 5, params)
for mode, test := range tests {
t.Run(fmt.Sprintf("opcodes_mode=%d", mode), func(t *testing.T) {
@@ -775,7 +355,7 @@ func TestBalance(t *testing.T) {
ep, ledger := makeSampleEnv()
text := "int 2; balance; int 177; =="
- ledger.newAccount(ep.Txn.Txn.Receiver, 177)
+ ledger.NewAccount(ep.Txn.Txn.Receiver, 177)
testApp(t, text, ep, "invalid Account reference")
text = `int 1; balance; int 177; ==`
@@ -787,17 +367,18 @@ func TestBalance(t *testing.T) {
// but legal after that
testApp(t, text, ep)
- text = "int 0; balance; int 13; =="
+ text = "int 0; balance; int 13; ==; assert; int 1"
var addr basics.Address
copy(addr[:], []byte("aoeuiaoeuiaoeuiaoeuiaoeuiaoeui02"))
- ledger.newAccount(addr, 13)
- testApp(t, text, ep, "failed to fetch balance")
+ ledger.NewAccount(addr, 13)
+ testApp(t, text, ep, "assert failed")
- ledger.newAccount(ep.Txn.Txn.Sender, 13)
+ ledger.NewAccount(ep.Txn.Txn.Sender, 13)
testApp(t, text, ep)
}
-func testApp(t *testing.T, program string, ep EvalParams, problems ...string) basics.EvalDelta {
+func testApp(t *testing.T, program string, ep EvalParams, problems ...string) transactions.EvalDelta {
+ t.Helper()
ops := testProg(t, program, ep.Proto.LogicSigVersion)
err := CheckStateful(ops.Program, ep)
require.NoError(t, err)
@@ -833,7 +414,7 @@ func testApp(t *testing.T, program string, ep EvalParams, problems ...string) ba
require.Empty(t, delta.Logs)
return delta
}
- return basics.EvalDelta{}
+ return transactions.EvalDelta{}
}
func TestMinBalance(t *testing.T) {
@@ -843,23 +424,23 @@ func TestMinBalance(t *testing.T) {
ep, ledger := makeSampleEnv()
- ledger.newAccount(ep.Txn.Txn.Sender, 234)
- ledger.newAccount(ep.Txn.Txn.Receiver, 123)
+ ledger.NewAccount(ep.Txn.Txn.Sender, 234)
+ ledger.NewAccount(ep.Txn.Txn.Receiver, 123)
testApp(t, "int 0; min_balance; int 1001; ==", ep)
// Sender makes an asset, min balance goes up
- ledger.newAsset(ep.Txn.Txn.Sender, 7, basics.AssetParams{Total: 1000})
+ ledger.NewAsset(ep.Txn.Txn.Sender, 7, basics.AssetParams{Total: 1000})
testApp(t, "int 0; min_balance; int 2002; ==", ep)
schemas := makeApp(1, 2, 3, 4)
- ledger.newApp(ep.Txn.Txn.Sender, 77, schemas)
+ ledger.NewApp(ep.Txn.Txn.Sender, 77, schemas)
// create + optin + 10 schema base + 4 ints + 6 bytes (local
- // and global count b/c newApp opts the creator in)
+ // and global count b/c NewApp opts the creator in)
minb := 2*1002 + 10*1003 + 4*1004 + 6*1005
testApp(t, fmt.Sprintf("int 0; min_balance; int %d; ==", 2002+minb), ep)
// request extra program pages, min balance increase
- app := ledger.applications[77]
- app.ExtraProgramPages = 2
- ledger.applications[77] = app
+ withepp := makeApp(1, 2, 3, 4)
+ withepp.ExtraProgramPages = 2
+ ledger.NewApp(ep.Txn.Txn.Sender, 77, withepp)
minb += 2 * 1002
testApp(t, fmt.Sprintf("int 0; min_balance; int %d; ==", 2002+minb), ep)
@@ -869,7 +450,7 @@ func TestMinBalance(t *testing.T) {
testProg(t, "txn Accounts 1; min_balance; int 1001; ==", directRefEnabledVersion)
testApp(t, "txn Accounts 1; min_balance; int 1001; ==", ep) // 1 == Accounts[0]
// Receiver opts in
- ledger.setHolding(ep.Txn.Txn.Receiver, 7, 1, true)
+ ledger.NewHolding(ep.Txn.Txn.Receiver, 7, 1, true)
testApp(t, "int 1; min_balance; int 2002; ==", ep) // 1 == Accounts[0]
testApp(t, "int 2; min_balance; int 1001; ==", ep, "invalid Account reference 2")
@@ -891,7 +472,7 @@ func TestAppCheckOptedIn(t *testing.T) {
pre.TxnGroup = txgroup
testApp(t, "int 2; int 100; app_opted_in; int 1; ==", now, "ledger not available")
- ledger := makeTestLedger(
+ ledger := logictest.MakeLedger(
map[basics.Address]uint64{
txn.Txn.Receiver: 1,
txn.Txn.Sender: 1,
@@ -910,7 +491,7 @@ func TestAppCheckOptedIn(t *testing.T) {
testApp(t, "int 0; int 100; app_opted_in; int 0; ==", now)
// Receiver opted in
- ledger.newApp(txn.Txn.Receiver, 100, basics.AppParams{})
+ ledger.NewApp(txn.Txn.Receiver, 100, basics.AppParams{})
testApp(t, "int 1; int 100; app_opted_in; int 1; ==", now)
testApp(t, "int 1; int 2; app_opted_in; int 1; ==", now)
testApp(t, "int 1; int 2; app_opted_in; int 0; ==", pre) // in pre, int 2 is an actual app id
@@ -919,7 +500,7 @@ func TestAppCheckOptedIn(t *testing.T) {
expect{3, "app_opted_in arg 0 wanted type uint64..."})
// Sender opted in
- ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
+ ledger.NewApp(txn.Txn.Sender, 100, basics.AppParams{})
testApp(t, "int 0; int 100; app_opted_in; int 1; ==", now)
}
@@ -942,24 +523,8 @@ exit:
int 1
==`
- txn := makeSampleTxn()
- txgroup := makeSampleTxnGroup(txn)
- now := defaultEvalParams(nil, nil)
- now.Txn = &txn
- now.TxnGroup = txgroup
- pre := defaultEvalParamsWithVersion(nil, nil, directRefEnabledVersion-1)
- pre.Txn = &txn
- pre.TxnGroup = txgroup
-
- testApp(t, text, now, "ledger not available")
-
- ledger := makeTestLedger(
- map[basics.Address]uint64{
- txn.Txn.Receiver: 1,
- },
- )
- now.Ledger = ledger
- pre.Ledger = ledger
+ pre, now, ledger := makeOldAndNewEnv(directRefEnabledVersion - 1)
+ ledger.NewAccount(now.Txn.Txn.Receiver, 1)
testApp(t, text, now, "invalid Account reference")
text = `int 1 // account idx
@@ -978,11 +543,11 @@ int 1`
testApp(t, text, now, "no app for account")
// Make a different app (not 100)
- ledger.newApp(txn.Txn.Receiver, 9999, basics.AppParams{})
+ ledger.NewApp(now.Txn.Txn.Receiver, 9999, basics.AppParams{})
testApp(t, text, now, "no app for account")
// create the app and check the value from ApplicationArgs[0] (protocol.PaymentTx) does not exist
- ledger.newApp(txn.Txn.Receiver, 100, basics.AppParams{})
+ ledger.NewApp(now.Txn.Txn.Receiver, 100, basics.AppParams{})
testApp(t, text, now)
text = `int 1 // account idx
@@ -994,7 +559,7 @@ err
exist:
byte 0x414c474f
==`
- ledger.balances[txn.Txn.Receiver].locals[100][string(protocol.PaymentTx)] = basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"}
+ ledger.NewLocal(now.Txn.Txn.Receiver, 100, string(protocol.PaymentTx), basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"})
testApp(t, text, now)
testApp(t, strings.Replace(text, "int 1 // account idx", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui01\"", -1), now)
@@ -1004,7 +569,7 @@ byte 0x414c474f
// Next we're testing if the use of the current app's id works
// as a direct reference. The error is because the sender
// account is not opted into 123.
- ledger.appID = basics.AppIndex(123)
+ ledger.NewApp(now.Txn.Txn.RekeyTo, 123, basics.AppParams{})
testApp(t, strings.Replace(text, "int 100 // app id", "int 123", -1), now, "no app for account")
testApp(t, strings.Replace(text, "int 100 // app id", "int 2", -1), pre, "no app for account")
testApp(t, strings.Replace(text, "int 100 // app id", "int 9", -1), now, "invalid App reference 9")
@@ -1012,7 +577,7 @@ byte 0x414c474f
"no such address")
// check special case account idx == 0 => sender
- ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
+ ledger.NewApp(now.Txn.Txn.Sender, 100, basics.AppParams{})
text = `int 0 // account idx
int 100 // app id
txn ApplicationArgs 0
@@ -1023,15 +588,15 @@ exist:
byte 0x414c474f
==`
- ledger.balances[txn.Txn.Sender].locals[100][string(protocol.PaymentTx)] = basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"}
+ ledger.NewLocal(now.Txn.Txn.Sender, 100, string(protocol.PaymentTx), basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"})
testApp(t, text, now)
testApp(t, strings.Replace(text, "int 0 // account idx", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00\"", -1), now)
testApp(t, strings.Replace(text, "int 0 // account idx", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui02\"", -1), now,
"invalid Account reference")
// check reading state of other app
- ledger.newApp(txn.Txn.Sender, 56, basics.AppParams{})
- ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
+ ledger.NewApp(now.Txn.Txn.Sender, 56, basics.AppParams{})
+ ledger.NewApp(now.Txn.Txn.Sender, 100, basics.AppParams{})
text = `int 0 // account idx
int 56 // app id
txn ApplicationArgs 0
@@ -1042,7 +607,7 @@ exist:
byte 0x414c474f
==`
- ledger.balances[txn.Txn.Sender].locals[56][string(protocol.PaymentTx)] = basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"}
+ ledger.NewLocal(now.Txn.Txn.Sender, 56, string(protocol.PaymentTx), basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"})
testApp(t, text, now)
// check app_local_get
@@ -1052,7 +617,7 @@ app_local_get
byte 0x414c474f
==`
- ledger.balances[txn.Txn.Sender].locals[100][string(protocol.PaymentTx)] = basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"}
+ ledger.NewLocal(now.Txn.Txn.Sender, 100, string(protocol.PaymentTx), basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"})
testApp(t, text, now)
testApp(t, strings.Replace(text, "int 0 // account idx", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00\"", -1), now)
testProg(t, strings.Replace(text, "int 0 // account idx", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00\"", -1), directRefEnabledVersion-1,
@@ -1068,7 +633,7 @@ app_local_get
int 0
==`
- ledger.balances[txn.Txn.Sender].locals[100][string(protocol.PaymentTx)] = basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"}
+ ledger.NewLocal(now.Txn.Txn.Sender, 100, string(protocol.PaymentTx), basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"})
testApp(t, text, now)
}
@@ -1100,35 +665,19 @@ byte 0x414c474f
==
&&
`
- txn := makeSampleTxn()
- txgroup := makeSampleTxnGroup(txn)
- now := defaultEvalParams(nil, nil)
- now.Txn = &txn
- now.TxnGroup = txgroup
- pre := defaultEvalParamsWithVersion(nil, nil, directRefEnabledVersion-1)
- pre.Txn = &txn
- pre.TxnGroup = txgroup
-
- testApp(t, text, now, "ledger not available")
-
- ledger := makeTestLedger(
- map[basics.Address]uint64{
- txn.Txn.Sender: 1,
- },
- )
- now.Ledger = ledger
- pre.Ledger = ledger
+ pre, now, ledger := makeOldAndNewEnv(directRefEnabledVersion - 1)
+ ledger.NewAccount(now.Txn.Txn.Sender, 1)
now.Txn.Txn.ApplicationID = 100
now.Txn.Txn.ForeignApps = []basics.AppIndex{now.Txn.Txn.ApplicationID}
testApp(t, text, now, "no such app")
// create the app and check the value from ApplicationArgs[0] (protocol.PaymentTx) does not exist
- ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
+ ledger.NewApp(now.Txn.Txn.Sender, 100, basics.AppParams{})
testApp(t, text, now, "err opcode")
- ledger.applications[100].GlobalState[string(protocol.PaymentTx)] = basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"}
+ ledger.NewGlobal(100, string(protocol.PaymentTx), basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"})
testApp(t, text, now)
@@ -1143,7 +692,7 @@ byte 0x414c474f
// check app_global_get default value
text = "byte 0x414c474f55; app_global_get; int 0; =="
- ledger.balances[txn.Txn.Sender].locals[100][string(protocol.PaymentTx)] = basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"}
+ ledger.NewLocal(now.Txn.Txn.Sender, 100, string(protocol.PaymentTx), basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"})
testApp(t, text, now)
text = `
@@ -1167,7 +716,7 @@ int 4141
testApp(t, text, now)
// Direct reference to the current app also works
- ledger.appID = basics.AppIndex(100)
+ ledger.NewApp(now.Txn.Txn.Receiver, 100, basics.AppParams{})
now.Txn.Txn.ForeignApps = []basics.AppIndex{}
testApp(t, strings.Replace(text, "int 1 // ForeignApps index", "int 100", -1), now)
testApp(t, strings.Replace(text, "int 1 // ForeignApps index", "global CurrentApplicationID", -1), now)
@@ -1315,7 +864,7 @@ func testAssetsByVersion(t *testing.T, assetsTestProgram string, version uint64)
pre := defaultEvalParamsWithVersion(nil, &txn, directRefEnabledVersion-1)
require.GreaterOrEqual(t, version, uint64(directRefEnabledVersion))
now := defaultEvalParamsWithVersion(nil, &txn, version)
- ledger := makeTestLedger(
+ ledger := logictest.MakeLedger(
map[basics.Address]uint64{
txn.Txn.Sender: 1,
},
@@ -1357,8 +906,8 @@ func testAssetsByVersion(t *testing.T, assetsTestProgram string, version uint64)
Clawback: txn.Txn.Receiver,
}
- ledger.newAsset(txn.Txn.Sender, 55, params)
- ledger.setHolding(txn.Txn.Sender, 55, 123, true)
+ ledger.NewAsset(txn.Txn.Sender, 55, params)
+ ledger.NewHolding(txn.Txn.Sender, 55, 123, true)
// For consistency you can now use an indirect ref in holding_get
// (recall ForeignAssets[0] = 55, which has balance 123)
testApp(t, "int 0; int 0; asset_holding_get AssetBalance; int 1; ==; assert; int 123; ==", now)
@@ -1398,7 +947,7 @@ err
ok:
intc_2 // 1
`
- ledger.setHolding(txn.Txn.Sender, 55, 123, false)
+ ledger.NewHolding(txn.Txn.Sender, 55, 123, false)
testApp(t, source, now)
// check holdings invalid offsets
@@ -1424,7 +973,7 @@ ok:
intc_1
`
params.DefaultFrozen = true
- ledger.newAsset(txn.Txn.Sender, 55, params)
+ ledger.NewAsset(txn.Txn.Sender, 55, params)
testApp(t, source, now)
// check holdings invalid offsets
ops = testProg(t, source, version)
@@ -1450,7 +999,7 @@ ok:
intc_1
`
params.URL = ""
- ledger.newAsset(txn.Txn.Sender, 55, params)
+ ledger.NewAsset(txn.Txn.Sender, 55, params)
testApp(t, source, now)
source = `intcblock 1 9
@@ -1468,7 +1017,7 @@ ok:
intc_0
`
params.URL = "foobarbaz"
- ledger.newAsset(txn.Txn.Sender, 77, params)
+ ledger.NewAsset(txn.Txn.Sender, 77, params)
testApp(t, source, now)
source = `intcblock 0 1
@@ -1485,15 +1034,16 @@ ok:
intc_1
`
params.URL = ""
- ledger.newAsset(txn.Txn.Sender, 55, params)
+ ledger.NewAsset(txn.Txn.Sender, 55, params)
testApp(t, source, now, "cannot compare ([]byte to uint64)")
}
func TestAppParams(t *testing.T) {
+ partitiontest.PartitionTest(t)
t.Parallel()
ep, ledger := makeSampleEnv()
- ledger.newAccount(ep.Txn.Txn.Sender, 1)
- ledger.newApp(ep.Txn.Txn.Sender, 100, basics.AppParams{})
+ ledger.NewAccount(ep.Txn.Txn.Sender, 1)
+ ledger.NewApp(ep.Txn.Txn.Sender, 100, basics.AppParams{})
/* app id is in ForeignApps, but does not exist */
source := "int 56; app_params_get AppExtraProgramPages; int 0; ==; assert; int 0; =="
@@ -1548,35 +1098,34 @@ bytec_0 // key "ALGO"
app_local_del
intc_1
`
- type test struct {
+ type cmdtest struct {
source string
accNumOffset int
}
- tests := map[string]test{
+ tests := map[string]cmdtest{
"read": {sourceRead, 20},
"write": {sourceWrite, 13},
"delete": {sourceDelete, 12},
}
- for name, test := range tests {
+ for name, cmdtest := range tests {
t.Run(fmt.Sprintf("test=%s", name), func(t *testing.T) {
- source := test.source
- firstCmdOffset := test.accNumOffset
+ source := cmdtest.source
+ firstCmdOffset := cmdtest.accNumOffset
- ops, err := AssembleStringWithVersion(source, AssemblerMaxVersion)
- require.NoError(t, err)
+ ops := testProg(t, source, AssemblerMaxVersion)
txn := makeSampleTxn()
ep := defaultEvalParams(nil, nil)
ep.Txn = &txn
ep.Txn.Txn.ApplicationID = 100
- err = CheckStateful(ops.Program, ep)
+ err := CheckStateful(ops.Program, ep)
require.NoError(t, err)
_, err = EvalStateful(ops.Program, ep)
require.Error(t, err)
require.Contains(t, err.Error(), "ledger not available")
- ledger := makeTestLedger(
+ ledger := logictest.MakeLedger(
map[basics.Address]uint64{
txn.Txn.Sender: 1,
},
@@ -1595,7 +1144,7 @@ intc_1
require.Error(t, err)
require.Contains(t, err.Error(), "no app for account")
- ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
+ ledger.NewApp(txn.Txn.Sender, 100, basics.AppParams{})
if name == "read" {
_, err = EvalStateful(ops.Program, ep)
@@ -1603,10 +1152,10 @@ intc_1
require.Contains(t, err.Error(), "err opcode") // no such key
}
- ledger.balances[txn.Txn.Sender].locals[100]["ALGO"] = basics.TealValue{Type: basics.TealUintType, Uint: 0x77}
- ledger.balances[txn.Txn.Sender].locals[100]["ALGOA"] = basics.TealValue{Type: basics.TealUintType, Uint: 1}
+ ledger.NewLocal(txn.Txn.Sender, 100, "ALGO", basics.TealValue{Type: basics.TealUintType, Uint: 0x77})
+ ledger.NewLocal(txn.Txn.Sender, 100, "ALGOA", basics.TealValue{Type: basics.TealUintType, Uint: 1})
- ledger.reset()
+ ledger.Reset()
pass, err := EvalStateful(ops.Program, ep)
require.NoError(t, err)
require.True(t, pass)
@@ -1631,13 +1180,13 @@ func TestAppLocalStateReadWrite(t *testing.T) {
txn := makeSampleTxn()
txn.Txn.ApplicationID = 100
ep.Txn = &txn
- ledger := makeTestLedger(
+ ledger := logictest.MakeLedger(
map[basics.Address]uint64{
txn.Txn.Sender: 1,
},
)
ep.Ledger = ledger
- ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
+ ledger.NewApp(txn.Txn.Sender, 100, basics.AppParams{})
// write int and bytes values
source := `int 0 // account
@@ -1704,15 +1253,14 @@ exist:
int 0x77
==
`
- ledger.reset()
- delete(ledger.balances[txn.Txn.Sender].locals[100], "ALGOA")
- delete(ledger.balances[txn.Txn.Sender].locals[100], "ALGO")
+ ledger.Reset()
+ ledger.NoLocal(txn.Txn.Sender, 100, "ALGOA")
+ ledger.NoLocal(txn.Txn.Sender, 100, "ALGO")
algoValue := basics.TealValue{Type: basics.TealUintType, Uint: 0x77}
- ledger.balances[txn.Txn.Sender].locals[100]["ALGO"] = algoValue
+ ledger.NewLocal(txn.Txn.Sender, 100, "ALGO", algoValue)
- ops, err = AssembleStringWithVersion(source, AssemblerMaxVersion)
- require.NoError(t, err)
+ ops = testProg(t, source, AssemblerMaxVersion)
err = CheckStateful(ops.Program, ep)
require.NoError(t, err)
pass, err = EvalStateful(ops.Program, ep)
@@ -1744,12 +1292,11 @@ err
exist2:
==
`
- ledger.reset()
- ledger.balances[txn.Txn.Sender].locals[100]["ALGO"] = algoValue
- delete(ledger.balances[txn.Txn.Sender].locals[100], "ALGOA")
+ ledger.Reset()
+ ledger.NewLocal(txn.Txn.Sender, 100, "ALGO", algoValue)
+ ledger.NoLocal(txn.Txn.Sender, 100, "ALGOA")
- ops, err = AssembleStringWithVersion(source, AssemblerMaxVersion)
- require.NoError(t, err)
+ ops = testProg(t, source, AssemblerMaxVersion)
pass, err = EvalStateful(ops.Program, ep)
require.NoError(t, err)
require.True(t, pass)
@@ -1765,12 +1312,11 @@ int 0x78 // value
app_local_put
int 1
`
- ledger.reset()
- ledger.balances[txn.Txn.Sender].locals[100]["ALGO"] = algoValue
- delete(ledger.balances[txn.Txn.Sender].locals[100], "ALGOA")
+ ledger.Reset()
+ ledger.NewLocal(txn.Txn.Sender, 100, "ALGO", algoValue)
+ ledger.NoLocal(txn.Txn.Sender, 100, "ALGOA")
- ops, err = AssembleStringWithVersion(source, AssemblerMaxVersion)
- require.NoError(t, err)
+ ops = testProg(t, source, AssemblerMaxVersion)
pass, err = EvalStateful(ops.Program, ep)
require.NoError(t, err)
require.True(t, pass)
@@ -1798,12 +1344,11 @@ exist:
int 0x78
==
`
- ledger.reset()
- ledger.balances[txn.Txn.Sender].locals[100]["ALGO"] = algoValue
- delete(ledger.balances[txn.Txn.Sender].locals[100], "ALGOA")
+ ledger.Reset()
+ ledger.NewLocal(txn.Txn.Sender, 100, "ALGO", algoValue)
+ ledger.NoLocal(txn.Txn.Sender, 100, "ALGOA")
- ops, err = AssembleStringWithVersion(source, AssemblerMaxVersion)
- require.NoError(t, err)
+ ops = testProg(t, source, AssemblerMaxVersion)
pass, err = EvalStateful(ops.Program, ep)
require.NoError(t, err)
require.True(t, pass)
@@ -1829,12 +1374,11 @@ byte 0x414c474f // key "ALGO"
int 0x78 // value
app_local_put
`
- ledger.reset()
- ledger.balances[txn.Txn.Sender].locals[100]["ALGO"] = algoValue
- delete(ledger.balances[txn.Txn.Sender].locals[100], "ALGOA")
+ ledger.Reset()
+ ledger.NewLocal(txn.Txn.Sender, 100, "ALGO", algoValue)
+ ledger.NoLocal(txn.Txn.Sender, 100, "ALGOA")
- ops, err = AssembleStringWithVersion(source, AssemblerMaxVersion)
- require.NoError(t, err)
+ ops = testProg(t, source, AssemblerMaxVersion)
pass, err = EvalStateful(ops.Program, ep)
require.NoError(t, err)
require.True(t, pass)
@@ -1866,15 +1410,14 @@ int 0x79 // value
app_local_put
int 1
`
- ledger.reset()
- ledger.balances[txn.Txn.Sender].locals[100]["ALGO"] = algoValue
- delete(ledger.balances[txn.Txn.Sender].locals[100], "ALGOA")
+ ledger.Reset()
+ ledger.NewLocal(txn.Txn.Sender, 100, "ALGO", algoValue)
+ ledger.NoLocal(txn.Txn.Sender, 100, "ALGOA")
- ledger.balances[txn.Txn.Receiver] = makeBalanceRecord(txn.Txn.Receiver, 500)
- ledger.balances[txn.Txn.Receiver].locals[100] = make(basics.TealKeyValue)
+ ledger.NewAccount(ep.Txn.Txn.Receiver, 500)
+ ledger.NewLocals(txn.Txn.Receiver, 100)
- ops, err = AssembleStringWithVersion(source, AssemblerMaxVersion)
- require.NoError(t, err)
+ ops = testProg(t, source, AssemblerMaxVersion)
err = CheckStateful(ops.Program, ep)
require.NoError(t, err)
pass, err = EvalStateful(ops.Program, ep)
@@ -1946,7 +1489,7 @@ int 1
require.Error(t, err)
require.Contains(t, err.Error(), "ledger not available")
- ledger := makeTestLedger(
+ ledger := logictest.MakeLedger(
map[basics.Address]uint64{
txn.Txn.Sender: 1,
},
@@ -1958,7 +1501,7 @@ int 1
require.Error(t, err)
require.Contains(t, err.Error(), "no such app")
- ledger.newApp(txn.Txn.Sender, 100, makeApp(0, 0, 1, 0))
+ ledger.NewApp(txn.Txn.Sender, 100, makeApp(0, 0, 1, 0))
// a special test for read
if name == "read" {
@@ -1966,9 +1509,9 @@ int 1
require.Error(t, err)
require.Contains(t, err.Error(), "err opcode") // no such key
}
- ledger.applications[100].GlobalState["ALGO"] = basics.TealValue{Type: basics.TealUintType, Uint: 0x77}
+ ledger.NewGlobal(100, "ALGO", basics.TealValue{Type: basics.TealUintType, Uint: 0x77})
- ledger.reset()
+ ledger.Reset()
pass, err := EvalStateful(ops.Program, ep)
require.NoError(t, err)
require.True(t, pass)
@@ -2049,13 +1592,13 @@ int 0x77
txn.Txn.ApplicationID = 100
txn.Txn.ForeignApps = []basics.AppIndex{txn.Txn.ApplicationID}
ep.Txn = &txn
- ledger := makeTestLedger(
+ ledger := logictest.MakeLedger(
map[basics.Address]uint64{
txn.Txn.Sender: 1,
},
)
ep.Ledger = ledger
- ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
+ ledger.NewApp(txn.Txn.Sender, 100, basics.AppParams{})
ops, err := AssembleStringWithVersion(source, AssemblerMaxVersion)
require.NoError(t, err)
@@ -2087,15 +1630,14 @@ app_global_get
int 0x77
==
`
- ledger.reset()
- delete(ledger.applications[100].GlobalState, "ALGOA")
- delete(ledger.applications[100].GlobalState, "ALGO")
+ ledger.Reset()
+ ledger.NoGlobal(100, "ALGOA")
+ ledger.NoGlobal(100, "ALGO")
algoValue := basics.TealValue{Type: basics.TealUintType, Uint: 0x77}
- ledger.applications[100].GlobalState["ALGO"] = algoValue
+ ledger.NewGlobal(100, "ALGO", algoValue)
- ops, err = AssembleStringWithVersion(source, AssemblerMaxVersion)
- require.NoError(t, err)
+ ops = testProg(t, source, AssemblerMaxVersion)
pass, err = EvalStateful(ops.Program, ep)
require.NoError(t, err)
require.True(t, pass)
@@ -2121,12 +1663,11 @@ app_global_get
int 0x77
==
`
- ledger.reset()
- delete(ledger.applications[100].GlobalState, "ALGOA")
- ledger.applications[100].GlobalState["ALGO"] = algoValue
+ ledger.Reset()
+ ledger.NoGlobal(100, "ALGOA")
+ ledger.NewGlobal(100, "ALGO", algoValue)
- ops, err = AssembleStringWithVersion(source, AssemblerMaxVersion)
- require.NoError(t, err)
+ ops = testProg(t, source, AssemblerMaxVersion)
pass, err = EvalStateful(ops.Program, ep)
require.NoError(t, err)
require.True(t, pass)
@@ -2167,12 +1708,11 @@ byte 0x414c474f
==
&&
`
- ledger.reset()
- delete(ledger.applications[100].GlobalState, "ALGOA")
- ledger.applications[100].GlobalState["ALGO"] = algoValue
+ ledger.Reset()
+ ledger.NoGlobal(100, "ALGOA")
+ ledger.NewGlobal(100, "ALGO", algoValue)
- ops, err = AssembleStringWithVersion(source, AssemblerMaxVersion)
- require.NoError(t, err)
+ ops = testProg(t, source, AssemblerMaxVersion)
sb := strings.Builder{}
ep.Trace = &sb
err = CheckStateful(ops.Program, ep)
@@ -2224,22 +1764,22 @@ byte "myval"
txn.Txn.ApplicationID = 100
txn.Txn.ForeignApps = []basics.AppIndex{txn.Txn.ApplicationID, 101}
ep.Txn = &txn
- ledger := makeTestLedger(
+ ledger := logictest.MakeLedger(
map[basics.Address]uint64{
txn.Txn.Sender: 1,
},
)
ep.Ledger = ledger
- ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
+ ledger.NewApp(txn.Txn.Sender, 100, basics.AppParams{})
delta := testApp(t, source, ep, "no such app")
require.Empty(t, delta.GlobalDelta)
require.Empty(t, delta.LocalDeltas)
- ledger.newApp(txn.Txn.Receiver, 101, basics.AppParams{})
- ledger.newApp(txn.Txn.Receiver, 100, basics.AppParams{}) // this keeps current app id = 100
+ ledger.NewApp(txn.Txn.Receiver, 101, basics.AppParams{})
+ ledger.NewApp(txn.Txn.Receiver, 100, basics.AppParams{}) // this keeps current app id = 100
algoValue := basics.TealValue{Type: basics.TealBytesType, Bytes: "myval"}
- ledger.applications[101].GlobalState["mykey"] = algoValue
+ ledger.NewGlobal(101, "mykey", algoValue)
delta = testApp(t, source, ep)
require.Empty(t, delta.GlobalDelta)
@@ -2270,13 +1810,13 @@ int 7
txn := makeSampleTxn()
txn.Txn.ApplicationID = 100
ep.Txn = &txn
- ledger := makeTestLedger(
+ ledger := logictest.MakeLedger(
map[basics.Address]uint64{
txn.Txn.Sender: 1,
},
)
ep.Ledger = ledger
- ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
+ ledger.NewApp(txn.Txn.Sender, 100, basics.AppParams{})
delta := testApp(t, source, ep)
require.Empty(t, delta.LocalDeltas)
@@ -2317,24 +1857,24 @@ int 1
txn := makeSampleTxn()
txn.Txn.ApplicationID = 100
ep.Txn = &txn
- ledger := makeTestLedger(
+ ledger := logictest.MakeLedger(
map[basics.Address]uint64{
txn.Txn.Sender: 1,
},
)
ep.Ledger = ledger
- ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
+ ledger.NewApp(txn.Txn.Sender, 100, basics.AppParams{})
delta := testApp(t, source, ep)
require.Len(t, delta.GlobalDelta, 2)
require.Empty(t, delta.LocalDeltas)
- ledger.reset()
- delete(ledger.applications[100].GlobalState, "ALGOA")
- delete(ledger.applications[100].GlobalState, "ALGO")
+ ledger.Reset()
+ ledger.NoGlobal(100, "ALGOA")
+ ledger.NoGlobal(100, "ALGO")
algoValue := basics.TealValue{Type: basics.TealUintType, Uint: 0x77}
- ledger.applications[100].GlobalState["ALGO"] = algoValue
+ ledger.NewGlobal(100, "ALGO", algoValue)
// check delete existing
source = `byte 0x414c474f // key "ALGO"
@@ -2353,11 +1893,11 @@ app_global_get_ex
require.Equal(t, "", vd.Bytes)
require.Equal(t, 0, len(delta.LocalDeltas))
- ledger.reset()
- delete(ledger.applications[100].GlobalState, "ALGOA")
- delete(ledger.applications[100].GlobalState, "ALGO")
+ ledger.Reset()
+ ledger.NoGlobal(100, "ALGOA")
+ ledger.NoGlobal(100, "ALGO")
- ledger.applications[100].GlobalState["ALGO"] = algoValue
+ ledger.NewGlobal(100, "ALGO", algoValue)
// check delete and write non-existing
source = `byte 0x414c474f41 // key "ALGOA"
@@ -2378,11 +1918,11 @@ app_global_put
require.Equal(t, "", vd.Bytes)
require.Empty(t, delta.LocalDeltas)
- ledger.reset()
- delete(ledger.applications[100].GlobalState, "ALGOA")
- delete(ledger.applications[100].GlobalState, "ALGO")
+ ledger.Reset()
+ ledger.NoGlobal(100, "ALGOA")
+ ledger.NoGlobal(100, "ALGO")
- ledger.applications[100].GlobalState["ALGO"] = algoValue
+ ledger.NewGlobal(100, "ALGO", algoValue)
// check delete and write existing
source = `byte 0x414c474f // key "ALGO"
@@ -2398,11 +1938,12 @@ int 1
require.Equal(t, basics.SetUintAction, vd.Action)
require.Empty(t, delta.LocalDeltas)
- ledger.reset()
- delete(ledger.applications[100].GlobalState, "ALGOA")
- delete(ledger.applications[100].GlobalState, "ALGO")
+ ledger.Reset()
+ ledger.Reset()
+ ledger.NoGlobal(100, "ALGOA")
+ ledger.NoGlobal(100, "ALGO")
- ledger.applications[100].GlobalState["ALGO"] = algoValue
+ ledger.NewGlobal(100, "ALGO", algoValue)
// check delete,write,delete existing
source = `byte 0x414c474f // key "ALGO"
@@ -2420,11 +1961,12 @@ int 1
require.Equal(t, basics.DeleteAction, vd.Action)
require.Empty(t, delta.LocalDeltas)
- ledger.reset()
- delete(ledger.applications[100].GlobalState, "ALGOA")
- delete(ledger.applications[100].GlobalState, "ALGO")
+ ledger.Reset()
+ ledger.Reset()
+ ledger.NoGlobal(100, "ALGOA")
+ ledger.NoGlobal(100, "ALGO")
- ledger.applications[100].GlobalState["ALGO"] = algoValue
+ ledger.NewGlobal(100, "ALGO", algoValue)
// check delete, write, delete non-existing
source = `byte 0x414c474f41 // key "ALGOA"
@@ -2482,15 +2024,15 @@ int 1
txn := makeSampleTxn()
txn.Txn.ApplicationID = 100
ep.Txn = &txn
- ledger := makeTestLedger(
+ ledger := logictest.MakeLedger(
map[basics.Address]uint64{
txn.Txn.Sender: 1,
},
)
ep.Ledger = ledger
- ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
- ledger.balances[txn.Txn.Receiver] = makeBalanceRecord(txn.Txn.Receiver, 1)
- ledger.balances[txn.Txn.Receiver].locals[100] = make(basics.TealKeyValue)
+ ledger.NewApp(txn.Txn.Sender, 100, basics.AppParams{})
+ ledger.NewAccount(txn.Txn.Receiver, 1)
+ ledger.NewLocals(txn.Txn.Receiver, 100)
sb := strings.Builder{}
ep.Trace = &sb
@@ -2501,7 +2043,7 @@ int 1
require.Equal(t, 0, len(delta.GlobalDelta))
require.Equal(t, 2, len(delta.LocalDeltas))
- ledger.reset()
+ ledger.Reset()
// test that app_local_put and _app_local_del can use byte addresses
testApp(t, strings.Replace(source, "int 0 // sender", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00\"", -1), ep)
// But won't compile in old teal
@@ -2513,14 +2055,14 @@ int 1
require.Equal(t, 0, len(delta.GlobalDelta))
require.Equal(t, 2, len(delta.LocalDeltas))
- ledger.reset()
- delete(ledger.balances[txn.Txn.Sender].locals[100], "ALGOA")
- delete(ledger.balances[txn.Txn.Sender].locals[100], "ALGO")
- delete(ledger.balances[txn.Txn.Receiver].locals[100], "ALGOA")
- delete(ledger.balances[txn.Txn.Receiver].locals[100], "ALGO")
+ ledger.Reset()
+ ledger.NoLocal(txn.Txn.Sender, 100, "ALGOA")
+ ledger.NoLocal(txn.Txn.Sender, 100, "ALGO")
+ ledger.NoLocal(txn.Txn.Receiver, 100, "ALGOA")
+ ledger.NoLocal(txn.Txn.Receiver, 100, "ALGO")
algoValue := basics.TealValue{Type: basics.TealUintType, Uint: 0x77}
- ledger.balances[txn.Txn.Sender].locals[100]["ALGO"] = algoValue
+ ledger.NewLocal(txn.Txn.Sender, 100, "ALGO", algoValue)
// check delete existing
source = `int 0 // account
@@ -2543,11 +2085,11 @@ app_local_get_ex
require.Equal(t, uint64(0), vd.Uint)
require.Equal(t, "", vd.Bytes)
- ledger.reset()
- delete(ledger.balances[txn.Txn.Sender].locals[100], "ALGOA")
- delete(ledger.balances[txn.Txn.Sender].locals[100], "ALGO")
+ ledger.Reset()
+ ledger.NoLocal(txn.Txn.Sender, 100, "ALGOA")
+ ledger.NoLocal(txn.Txn.Sender, 100, "ALGO")
- ledger.balances[txn.Txn.Sender].locals[100]["ALGO"] = algoValue
+ ledger.NewLocal(txn.Txn.Sender, 100, "ALGO", algoValue)
// check delete and write non-existing
source = `int 0 // account
@@ -2573,11 +2115,11 @@ app_local_put
require.Equal(t, uint64(0x78), vd.Uint)
require.Equal(t, "", vd.Bytes)
- ledger.reset()
- delete(ledger.balances[txn.Txn.Sender].locals[100], "ALGOA")
- delete(ledger.balances[txn.Txn.Sender].locals[100], "ALGO")
+ ledger.Reset()
+ ledger.NoLocal(txn.Txn.Sender, 100, "ALGOA")
+ ledger.NoLocal(txn.Txn.Sender, 100, "ALGO")
- ledger.balances[txn.Txn.Sender].locals[100]["ALGO"] = algoValue
+ ledger.NewLocal(txn.Txn.Sender, 100, "ALGO", algoValue)
// check delete and write existing
source = `int 0 // account
@@ -2599,11 +2141,11 @@ int 1
require.Equal(t, uint64(0x78), vd.Uint)
require.Equal(t, "", vd.Bytes)
- ledger.reset()
- delete(ledger.balances[txn.Txn.Sender].locals[100], "ALGOA")
- delete(ledger.balances[txn.Txn.Sender].locals[100], "ALGO")
+ ledger.Reset()
+ ledger.NoLocal(txn.Txn.Sender, 100, "ALGOA")
+ ledger.NoLocal(txn.Txn.Sender, 100, "ALGO")
- ledger.balances[txn.Txn.Sender].locals[100]["ALGO"] = algoValue
+ ledger.NewLocal(txn.Txn.Sender, 100, "ALGO", algoValue)
// check delete,write,delete existing
source = `int 0 // account
@@ -2628,11 +2170,11 @@ int 1
require.Equal(t, uint64(0), vd.Uint)
require.Equal(t, "", vd.Bytes)
- ledger.reset()
- delete(ledger.balances[txn.Txn.Sender].locals[100], "ALGOA")
- delete(ledger.balances[txn.Txn.Sender].locals[100], "ALGO")
+ ledger.Reset()
+ ledger.NoLocal(txn.Txn.Sender, 100, "ALGOA")
+ ledger.NoLocal(txn.Txn.Sender, 100, "ALGO")
- ledger.balances[txn.Txn.Sender].locals[100]["ALGO"] = algoValue
+ ledger.NewLocal(txn.Txn.Sender, 100, "ALGO", algoValue)
// check delete, write, delete non-existing
source = `int 0 // account
@@ -2694,7 +2236,7 @@ func TestEnumFieldErrors(t *testing.T) {
require.Contains(t, err.Error(), "MinTxnFee expected field type is []byte but got uint64")
txn := makeSampleTxn()
- ledger := makeTestLedger(
+ ledger := logictest.MakeLedger(
map[basics.Address]uint64{
txn.Txn.Sender: 1,
},
@@ -2711,7 +2253,7 @@ func TestEnumFieldErrors(t *testing.T) {
Freeze: txn.Txn.Receiver,
Clawback: txn.Txn.Receiver,
}
- ledger.newAsset(txn.Txn.Sender, 55, params)
+ ledger.NewAsset(txn.Txn.Sender, 55, params)
ep.Txn = &txn
ep.Ledger = ledger
@@ -2779,7 +2321,7 @@ func TestReturnTypes(t *testing.T) {
[]byte("aoeu2"),
[]byte("aoeu3"),
}
- ledger := makeTestLedger(
+ ledger := logictest.MakeLedger(
map[basics.Address]uint64{
txn.Txn.Sender: 1,
},
@@ -2796,15 +2338,16 @@ func TestReturnTypes(t *testing.T) {
Freeze: txn.Txn.Receiver,
Clawback: txn.Txn.Receiver,
}
- ledger.newAsset(txn.Txn.Sender, 1, params)
- ledger.newApp(txn.Txn.Sender, 1, basics.AppParams{})
- ledger.setTrackedCreatable(0, basics.CreatableLocator{Index: 1})
- ledger.balances[txn.Txn.Receiver] = makeBalanceRecord(txn.Txn.Receiver, 1)
- ledger.balances[txn.Txn.Receiver].locals[1] = make(basics.TealKeyValue)
+ ledger.NewAsset(txn.Txn.Sender, 1, params)
+ ledger.NewApp(txn.Txn.Sender, 1, basics.AppParams{})
+ ledger.SetTrackedCreatable(0, basics.CreatableLocator{Index: 1})
+ ledger.NewAccount(txn.Txn.Receiver, 1000000)
+ ledger.NewLocals(txn.Txn.Receiver, 1)
key, err := hex.DecodeString("33343536")
require.NoError(t, err)
algoValue := basics.TealValue{Type: basics.TealUintType, Uint: 0x77}
- ledger.balances[txn.Txn.Receiver].locals[1][string(key)] = algoValue
+ ledger.NewLocal(txn.Txn.Receiver, 1, string(key), algoValue)
+ ledger.NewAccount(basics.AppIndex(1).Address(), 1000000)
ep.Ledger = ledger
@@ -2834,7 +2377,6 @@ func TestReturnTypes(t *testing.T) {
"bytec_2": "bytecblock 0x32 0x33 0x34; bytec_2",
"bytec_3": "bytecblock 0x32 0x33 0x34 0x35; bytec_3",
"substring": "substring 0 2",
- "ed25519verify": "pop; pop; pop; int 1", // ignore
"asset_params_get": "asset_params_get AssetTotal",
"asset_holding_get": "asset_holding_get AssetBalance",
"gtxns": "gtxns Sender",
@@ -2843,13 +2385,28 @@ func TestReturnTypes(t *testing.T) {
"pushbytes": `pushbytes "jojogoodgorilla"`,
"app_params_get": "app_params_get AppGlobalNumUint",
"extract": "extract 0 2",
+ "txnas": "txnas ApplicationArgs",
+ "gtxnas": "gtxnas 0 ApplicationArgs",
+ "gtxnsas": "pop; pop; int 0; int 0; gtxnsas ApplicationArgs",
+ "args": "args",
+ "itxn": "itxn_begin; int pay; itxn_field TypeEnum; itxn_submit; itxn CreatedAssetID",
+ // This next one is a cop out. Can't use itxna Logs until we have inner appl
+ "itxna": "itxn_begin; int pay; itxn_field TypeEnum; itxn_submit; itxn NumLogs",
+ }
+
+ // these require special input data and tested separately
+ skipCmd := map[string]bool{
+ "ed25519verify": true,
+ "ecdsa_verify": true,
+ "ecdsa_pk_recover": true,
+ "ecdsa_pk_decompress": true,
}
byName := OpsByName[LogicVersion]
for _, m := range []runMode{runModeSignature, runModeApplication} {
t.Run(fmt.Sprintf("m=%s", m.String()), func(t *testing.T) {
for name, spec := range byName {
- if len(spec.Returns) == 0 || (m&spec.Modes) == 0 {
+ if len(spec.Returns) == 0 || (m&spec.Modes) == 0 || skipCmd[name] {
continue
}
var sb strings.Builder
@@ -2865,7 +2422,10 @@ func TestReturnTypes(t *testing.T) {
source := sb.String()
ops := testProg(t, source, AssemblerMaxVersion)
- var cx evalContext
+ var trace strings.Builder
+ ep.Trace = &trace
+
+ var cx EvalContext
cx.EvalParams = ep
cx.runModeFlags = m
@@ -2874,7 +2434,7 @@ func TestReturnTypes(t *testing.T) {
require.Equal(
t,
len(spec.Returns), len(cx.stack),
- fmt.Sprintf("%s expected to return %d values but stack has %d", spec.Name, len(spec.Returns), len(cx.stack)),
+ fmt.Sprintf("\n%s%s expected to return %d values but stack has %d", trace.String(), spec.Name, len(spec.Returns), len(cx.stack)),
)
for i := 0; i < len(spec.Returns); i++ {
sp := len(cx.stack) - 1 - i
@@ -2910,7 +2470,7 @@ func TestCurrentApplicationID(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
ep, ledger := makeSampleEnv()
- ledger.appID = basics.AppIndex(42)
+ ledger.NewApp(ep.Txn.Txn.Receiver, 42, basics.AppParams{})
source := "global CurrentApplicationID; int 42; =="
testApp(t, source, ep)
}
@@ -2925,54 +2485,10 @@ func TestAppLoop(t *testing.T) {
// Double until > 10. Should be 16
testApp(t, stateful+"int 1; loop: int 2; *; dup; int 10; <; bnz loop; int 16; ==", ep)
- testApp(t, stateful+"int 1; loop: int 2; *; dup; int 10; <; bnz loop; int 16; ==", ep)
-
// Infinite loop because multiply by one instead of two
testApp(t, stateful+"int 1; loop:; int 1; *; dup; int 10; <; bnz loop; int 16; ==", ep, "dynamic cost")
}
-func TestWriteLogs(t *testing.T) {
- partitiontest.PartitionTest(t)
-
- t.Parallel()
-
- ep := defaultEvalParams(nil, nil)
- txn := makeSampleTxn()
- txn.Txn.ApplicationID = 100
- ep.Txn = &txn
- ledger := makeTestLedger(
- map[basics.Address]uint64{
- txn.Txn.Sender: 1,
- },
- )
- ep.Ledger = ledger
- ledger.newApp(txn.Txn.Sender, 100, basics.AppParams{})
-
- // write int and bytes values
- source := `int 1
-loop: byte "a"
-log
-int 1
-+
-dup
-int 30
-<
-bnz loop
-`
- ops, err := AssembleStringWithVersion(source, AssemblerMaxVersion)
- require.NoError(t, err)
- err = CheckStateful(ops.Program, ep)
- require.NoError(t, err)
- pass, err := EvalStateful(ops.Program, ep)
- require.NoError(t, err)
- require.True(t, pass)
- delta, err := ledger.GetDelta(&ep.Txn.Txn)
- require.NoError(t, err)
- require.Empty(t, 0, delta.GlobalDelta)
- require.Empty(t, delta.LocalDeltas)
- require.Len(t, delta.Logs, 29)
-}
-
func TestPooledAppCallsVerifyOp(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
@@ -2998,3 +2514,19 @@ func TestPooledAppCallsVerifyOp(t *testing.T) {
*ep.PooledApplicationBudget = uint64(ep.Proto.MaxAppProgramCost * 3)
testApp(t, source, ep)
}
+
+func TestAppAddress(t *testing.T) {
+ ep, ledger := makeSampleEnv()
+ ledger.NewApp(ep.Txn.Txn.Receiver, 888, basics.AppParams{})
+ source := fmt.Sprintf("global CurrentApplicationAddress; addr %s; ==;", basics.AppIndex(888).Address())
+ testApp(t, source, ep)
+
+ source = fmt.Sprintf("int 0; app_params_get AppAddress; assert; addr %s; ==;", basics.AppIndex(888).Address())
+ testApp(t, source, ep)
+
+ // To document easy construction:
+ // python -c 'import algosdk.encoding as e; print(e.encode_address(e.checksum(b"appID"+(888).to_bytes(8, "big"))))'
+ a := "U7C5FUHZM5PL5EIS2KHHLL456GS66DZBEEKL2UBQLMKH2X5X5I643ZIM6U"
+ source = fmt.Sprintf("int 0; app_params_get AppAddress; assert; addr %s; ==;", a)
+ testApp(t, source, ep)
+}