summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralgobarb <78746954+algobarb@users.noreply.github.com>2021-09-17 13:58:19 -0400
committerGitHub <noreply@github.com>2021-09-17 13:58:19 -0400
commitd2790079630e316e4ae881c896744e26a1d0c263 (patch)
treee10b8c8450ec3d548ac2547233d9a218135d78b3
parent13edc2acfce8eef71a94c28be45628ae5b58b6d1 (diff)
Rel/beta 3.0.1 (#2905)v3.0.1-betarelbeta3.0.1
![GitHub Logo](https://raw.githubusercontent.com/algorand/go-algorand/master/release/release-banner.jpg) # Highlights This version adds debugging for itxn programs and includes a bugfix for dryrun crashes. **This release does not contain a protocol upgrade.** # Changes 1. TEAL * Added * Enable debugging itxn programs (#2900) * Fixed * Fix dryrun crash on rewards calculation (#2894) ## Additional Resources * [Algorand Forum](https://forum.algorand.org) * [Developer Documentation](https://developer.algorand.org)
-rw-r--r--buildnumber.dat2
-rw-r--r--cmd/tealdbg/local.go6
-rw-r--r--cmd/tealdbg/localLedger.go5
-rw-r--r--cmd/tealdbg/local_test.go74
-rw-r--r--daemon/algod/api/server/v2/account.go2
-rw-r--r--daemon/algod/api/server/v2/dryrun.go43
-rw-r--r--daemon/algod/api/server/v2/dryrun_test.go156
-rw-r--r--test/e2e-go/cli/tealdbg/expect/tealdbgTest.exp2
8 files changed, 246 insertions, 44 deletions
diff --git a/buildnumber.dat b/buildnumber.dat
index 573541ac9..d00491fd7 100644
--- a/buildnumber.dat
+++ b/buildnumber.dat
@@ -1 +1 @@
-0
+1
diff --git a/cmd/tealdbg/local.go b/cmd/tealdbg/local.go
index 814afae3e..6fe2d006a 100644
--- a/cmd/tealdbg/local.go
+++ b/cmd/tealdbg/local.go
@@ -38,7 +38,7 @@ func protoFromString(protoString string) (name string, proto config.ConsensusPar
var ok bool
proto, ok = config.Consensus[protocol.ConsensusVersion(protoString)]
if !ok {
- err = fmt.Errorf("Unknown protocol %s", protoString)
+ err = fmt.Errorf("unknown protocol %s", protoString)
return
}
name = protoString
@@ -369,7 +369,7 @@ func (r *LocalRunner) Setup(dp *DebugParams) (err error) {
source := string(data)
ops, err := logic.AssembleString(source)
if ops.Version > r.proto.LogicSigVersion {
- return fmt.Errorf("Program version (%d) is beyond the maximum supported protocol version (%d)", ops.Version, r.proto.LogicSigVersion)
+ return fmt.Errorf("program version (%d) is beyond the maximum supported protocol version (%d)", ops.Version, r.proto.LogicSigVersion)
}
if err != nil {
errorLines := ""
@@ -534,6 +534,7 @@ func (r *LocalRunner) RunAll() error {
TxnGroup: r.txnGroup,
GroupIndex: run.groupIndex,
PastSideEffects: run.pastSideEffects,
+ Specials: &transactions.SpecialAddresses{},
}
run.result.pass, run.result.err = run.eval(ep)
@@ -562,6 +563,7 @@ func (r *LocalRunner) Run() (bool, error) {
TxnGroup: r.txnGroup,
GroupIndex: run.groupIndex,
PastSideEffects: run.pastSideEffects,
+ Specials: &transactions.SpecialAddresses{},
}
// Workaround for Go's nil/empty interfaces nil check after nil assignment, i.e.
diff --git a/cmd/tealdbg/localLedger.go b/cmd/tealdbg/localLedger.go
index 6f4dcfeaa..23e58e3f3 100644
--- a/cmd/tealdbg/localLedger.go
+++ b/cmd/tealdbg/localLedger.go
@@ -285,7 +285,10 @@ func (l *localLedger) CheckDup(config.ConsensusParams, basics.Round, basics.Roun
}
func (l *localLedger) LookupWithoutRewards(rnd basics.Round, addr basics.Address) (basics.AccountData, basics.Round, error) {
- return l.balances[addr], rnd, nil
+ ad := l.balances[addr]
+ // Clear RewardsBase since tealdbg has no idea about rewards level so the underlying calculation with reward will fail.
+ ad.RewardsBase = 0
+ return ad, rnd, nil
}
func (l *localLedger) GetCreatorForRound(rnd basics.Round, cidx basics.CreatableIndex, ctype basics.CreatableType) (basics.Address, bool, error) {
diff --git a/cmd/tealdbg/local_test.go b/cmd/tealdbg/local_test.go
index c0b26b145..d4d917a40 100644
--- a/cmd/tealdbg/local_test.go
+++ b/cmd/tealdbg/local_test.go
@@ -1064,3 +1064,77 @@ func TestLocalBalanceAdapterIndexer(t *testing.T) {
ba := l.runs[0].ba
checkBalanceAdapter(a, ba, sender, payTxn.Txn.Receiver, assetIdx, appIdx)
}
+
+func TestDebugTxSubmit(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ a := require.New(t)
+
+ sender, err := basics.UnmarshalChecksumAddress("47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU")
+ a.NoError(err)
+ app, err := basics.UnmarshalChecksumAddress("6BPQU5WNZMTO4X72A2THZCGNJNTTE7YL6AWCYSUUTZEIYMJSEPJCQQ6DQI")
+ a.NoError(err)
+
+ // make balance records
+ assetIdx := basics.AssetIndex(50)
+ appIdx := basics.AppIndex(100)
+ brs := makeSampleBalanceRecord(sender, assetIdx, appIdx)
+ bra := makeSampleBalanceRecord(app, assetIdx, appIdx)
+ balanceBlob := protocol.EncodeMsgp(&brs)
+ balanceBlob = append(balanceBlob, protocol.EncodeMsgp(&bra)...)
+
+ txn := transactions.SignedTxn{
+ Txn: transactions.Transaction{
+ Type: protocol.ApplicationCallTx,
+ Header: transactions.Header{
+ Sender: sender,
+ Fee: basics.MicroAlgos{Raw: 100},
+ Note: []byte{1, 2, 3},
+ },
+ ApplicationCallTxnFields: transactions.ApplicationCallTxnFields{
+ ApplicationID: appIdx,
+ },
+ },
+ }
+
+ txnEnc := protocol.EncodeJSON(&txn)
+ txnBlob := []byte("[" + strings.Join([]string{string(txnEnc), txnSample}, ",") + "]")
+
+ source := `#pragma version 5
+itxn_begin
+int acfg
+itxn_field TypeEnum
+int 1000000
+itxn_field ConfigAssetTotal
+int 3
+itxn_field ConfigAssetDecimals
+byte "oz"
+itxn_field ConfigAssetUnitName
+byte "Gold"
+itxn_field ConfigAssetName
+byte "https://gold.rush/"
+itxn_field ConfigAssetURL
+byte 0x67f0cd61653bd34316160bc3f5cd3763c85b114d50d38e1f4e72c3b994411e7b
+itxn_field ConfigAssetMetadataHash
+itxn_submit
+int 1`
+
+ ds := DebugParams{
+ ProgramNames: []string{"test"},
+ ProgramBlobs: [][]byte{[]byte(source)},
+ BalanceBlob: balanceBlob,
+ TxnBlob: txnBlob,
+ Proto: string(protocol.ConsensusCurrentVersion),
+ Round: 222,
+ LatestTimestamp: 333,
+ GroupIndex: 0,
+ RunMode: "application",
+ }
+
+ local := MakeLocalRunner(nil) // no debugger
+ err = local.Setup(&ds)
+ a.NoError(err)
+
+ pass, err := local.Run()
+ a.NoError(err)
+ a.True(pass)
+}
diff --git a/daemon/algod/api/server/v2/account.go b/daemon/algod/api/server/v2/account.go
index 018618265..2187a1068 100644
--- a/daemon/algod/api/server/v2/account.go
+++ b/daemon/algod/api/server/v2/account.go
@@ -105,7 +105,7 @@ func AccountDataToAccount(
amount := record.MicroAlgos
pendingRewards, overflowed := basics.OSubA(amount, amountWithoutPendingRewards)
if overflowed {
- return generated.Account{}, errors.New("overflow on pending reward calcuation")
+ return generated.Account{}, errors.New("overflow on pending reward calculation")
}
return generated.Account{
diff --git a/daemon/algod/api/server/v2/dryrun.go b/daemon/algod/api/server/v2/dryrun.go
index fed86ce62..3677c4b28 100644
--- a/daemon/algod/api/server/v2/dryrun.go
+++ b/daemon/algod/api/server/v2/dryrun.go
@@ -87,7 +87,7 @@ func (dr *DryrunRequest) ExpandSources() error {
for i, s := range dr.Sources {
ops, err := logic.AssembleString(s.Source)
if err != nil {
- return fmt.Errorf("Dryrun Source[%d]: %v", i, err)
+ return fmt.Errorf("dryrun Source[%d]: %v", i, err)
}
switch s.FieldName {
case "lsig":
@@ -104,7 +104,7 @@ func (dr *DryrunRequest) ExpandSources() error {
}
}
default:
- return fmt.Errorf("Dryrun Source[%d]: bad field name %#v", i, s.FieldName)
+ return fmt.Errorf("dryrun Source[%d]: bad field name %#v", i, s.FieldName)
}
}
return nil
@@ -273,6 +273,9 @@ func (dl *dryrunLedger) LookupWithoutRewards(rnd basics.Round, addr basics.Addre
return basics.AccountData{}, 0, err
}
out.MicroAlgos.Raw = acct.AmountWithoutPendingRewards
+ // Clear RewardsBase since dryrun has no idea about rewards level so the underlying calculation with reward will fail.
+ // The amount needed is known as acct.Amount but this method must return AmountWithoutPendingRewards
+ out.RewardsBase = 0
}
appi, ok := dl.accountApps[addr]
if ok {
@@ -335,41 +338,6 @@ func (dl *dryrunLedger) GetCreatorForRound(rnd basics.Round, cidx basics.Creatab
return basics.Address{}, false, fmt.Errorf("unknown creatable type %d", ctype)
}
-func (dl *dryrunLedger) getAppParams(addr basics.Address, aidx basics.AppIndex) (params basics.AppParams, err error) {
- idx, ok := dl.accountApps[addr]
- if !ok {
- err = fmt.Errorf("addr %s is not know to dryrun", addr.String())
- return
- }
- if aidx != basics.AppIndex(dl.dr.Apps[idx].Id) {
- err = fmt.Errorf("creator addr %s does not match to app id %d", addr.String(), aidx)
- return
- }
- if params, err = ApplicationParamsToAppParams(&dl.dr.Apps[idx].Params); err != nil {
- return
- }
- return
-}
-
-func (dl *dryrunLedger) getLocalKV(addr basics.Address, aidx basics.AppIndex) (kv basics.TealKeyValue, err error) {
- idx, ok := dl.accountsIn[addr]
- if !ok {
- err = fmt.Errorf("addr %s is not know to dryrun", addr.String())
- return
- }
- var ad basics.AccountData
- if ad, err = AccountToAccountData(&dl.dr.Accounts[idx]); err != nil {
- return
- }
- loc, ok := ad.AppLocalStates[aidx]
- if !ok {
- err = fmt.Errorf("addr %s not opted in to app %d, cannot fetch state", addr.String(), aidx)
- return
- }
- kv = loc.KeyValue
- return
-}
-
func makeBalancesAdapter(dl *dryrunLedger, txn *transactions.Transaction, appIdx basics.AppIndex) (ba apply.Balances, err error) {
ba = ledger.MakeDebugBalances(dl, basics.Round(dl.dr.Round), protocol.ConsensusVersion(dl.dr.ProtocolVersion), dl.dr.LatestTimestamp)
@@ -423,6 +391,7 @@ func doDryrunRequest(dr *DryrunRequest, response *generated.DryrunResponse) {
GroupIndex: uint64(ti),
PastSideEffects: pse,
PooledApplicationBudget: &pooledAppBudget,
+ Specials: &transactions.SpecialAddresses{},
}
var result generated.DryrunTxnResult
if len(stxn.Lsig.Logic) > 0 {
diff --git a/daemon/algod/api/server/v2/dryrun_test.go b/daemon/algod/api/server/v2/dryrun_test.go
index 10c758d4e..abb28143d 100644
--- a/daemon/algod/api/server/v2/dryrun_test.go
+++ b/daemon/algod/api/server/v2/dryrun_test.go
@@ -830,6 +830,7 @@ func TestDryrunEncodeDecode(t *testing.T) {
dr1, err := DryrunRequestFromGenerated(&gdr)
require.NoError(t, err)
encoded, err = encode(protocol.CodecHandle, &dr)
+ require.NoError(t, err)
encoded2 := protocol.EncodeReflect(&dr)
require.Equal(t, encoded, encoded2)
@@ -840,7 +841,6 @@ func TestDryrunEncodeDecode(t *testing.T) {
require.NoError(t, err)
require.Equal(t, dr1, dr2)
- dec = protocol.NewDecoder(buf)
dr2 = DryrunRequest{}
err = decode(protocol.CodecHandle, encoded, &dr2)
require.NoError(t, err)
@@ -1136,6 +1136,7 @@ return
require.NoError(t, err)
approval := ops.Program
ops, err = logic.AssembleString("int 1")
+ require.NoError(t, err)
clst := ops.Program
ops, err = logic.AssembleString("#pragma version 5 \nint 1")
approv := ops.Program
@@ -1331,3 +1332,156 @@ func TestDryrunCost(t *testing.T) {
})
}
}
+
+func TestDebugTxSubmit(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ a := require.New(t)
+ source := `#pragma version 5
+itxn_begin
+int acfg
+itxn_field TypeEnum
+int 1000000
+itxn_field ConfigAssetTotal
+int 3
+itxn_field ConfigAssetDecimals
+byte "oz"
+itxn_field ConfigAssetUnitName
+byte "Gold"
+itxn_field ConfigAssetName
+byte "https://gold.rush/"
+itxn_field ConfigAssetURL
+byte 0x67f0cd61653bd34316160bc3f5cd3763c85b114d50d38e1f4e72c3b994411e7b
+itxn_field ConfigAssetMetadataHash
+itxn_submit
+int 1`
+
+ ops, err := logic.AssembleString(source)
+ require.NoError(t, err)
+ approval := ops.Program
+
+ ops, err = logic.AssembleString("int 1")
+ clst := ops.Program
+ require.NoError(t, err)
+
+ sender, err := basics.UnmarshalChecksumAddress("47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU")
+ a.NoError(err)
+ app, err := basics.UnmarshalChecksumAddress("6BPQU5WNZMTO4X72A2THZCGNJNTTE7YL6AWCYSUUTZEIYMJSEPJCQQ6DQI")
+ a.NoError(err)
+
+ // make balance records
+ appIdx := basics.AppIndex(100)
+ dr := DryrunRequest{
+ Txns: []transactions.SignedTxn{{
+ Txn: transactions.Transaction{
+ Type: protocol.ApplicationCallTx,
+ Header: transactions.Header{
+ Sender: sender,
+ Fee: basics.MicroAlgos{Raw: 100},
+ Note: []byte{1, 2, 3},
+ },
+ ApplicationCallTxnFields: transactions.ApplicationCallTxnFields{
+ ApplicationID: appIdx,
+ },
+ },
+ }},
+ Apps: []generated.Application{
+ {
+ Id: uint64(appIdx),
+ Params: generated.ApplicationParams{
+ Creator: sender.String(),
+ ApprovalProgram: approval,
+ ClearStateProgram: clst,
+ },
+ },
+ },
+ Accounts: []generated.Account{
+ {
+ Address: sender.String(),
+ Status: "Online",
+ Amount: 10000000,
+ AmountWithoutPendingRewards: 10000000,
+ },
+ {
+ Address: app.String(),
+ Status: "Offline",
+ Amount: 10000000,
+ AmountWithoutPendingRewards: 10000000,
+ },
+ {
+ Address: basics.Address{}.String(),
+ Status: "Offline",
+ },
+ },
+ }
+
+ dr.ProtocolVersion = string(dryrunProtoVersion)
+
+ var response generated.DryrunResponse
+ doDryrunRequest(&dr, &response)
+ require.NoError(t, err)
+ checkAppCallPass(t, &response)
+ if t.Failed() {
+ logResponse(t, &response)
+ }
+}
+
+func TestDryrunBalanceWithReward(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ ops, err := logic.AssembleString(`#pragma version 5
+int 0
+balance
+int 0
+>`)
+ require.NoError(t, err)
+ approval := ops.Program
+ ops, err = logic.AssembleString("int 1")
+ clst := ops.Program
+ require.NoError(t, err)
+ var appIdx basics.AppIndex = 1
+ creator := randomAddress()
+ rewardBase := uint64(10000000)
+ dr := DryrunRequest{
+ Txns: []transactions.SignedTxn{
+ {
+ Txn: transactions.Transaction{
+ Header: transactions.Header{Sender: creator},
+ Type: protocol.ApplicationCallTx,
+ ApplicationCallTxnFields: transactions.ApplicationCallTxnFields{
+ ApplicationID: appIdx,
+ },
+ },
+ },
+ },
+ Apps: []generated.Application{
+ {
+ Id: uint64(appIdx),
+ Params: generated.ApplicationParams{
+ Creator: creator.String(),
+ ApprovalProgram: approval,
+ ClearStateProgram: clst,
+ LocalStateSchema: &generated.ApplicationStateSchema{NumByteSlice: 1},
+ },
+ },
+ },
+ Accounts: []generated.Account{
+ {
+ Address: creator.String(),
+ Status: "Online",
+ Amount: 10000000,
+ AmountWithoutPendingRewards: 10000000,
+ RewardBase: &rewardBase,
+ },
+ },
+ }
+ dr.ProtocolVersion = string(dryrunProtoVersion)
+
+ var response generated.DryrunResponse
+ doDryrunRequest(&dr, &response)
+ require.NoError(t, err)
+ checkAppCallPass(t, &response)
+ if t.Failed() {
+ logResponse(t, &response)
+ }
+}
diff --git a/test/e2e-go/cli/tealdbg/expect/tealdbgTest.exp b/test/e2e-go/cli/tealdbg/expect/tealdbgTest.exp
index a4fc773eb..7d7b84ab4 100644
--- a/test/e2e-go/cli/tealdbg/expect/tealdbgTest.exp
+++ b/test/e2e-go/cli/tealdbg/expect/tealdbgTest.exp
@@ -81,7 +81,7 @@ if { [catch {
spawn tealdbg debug -v $TEAL_PROG_FILE -p $PROTOCOL_VERSION_2 --remote-debugging-port 9392 --listen 127.0.0.1
expect {
timeout { puts "tealdbg debug timed out"; exit 1 }
- -re {Debug error: Program version \([0-9]+\) is beyond the maximum supported protocol version \([0-9]+\)} { set FAILED 1; close }
+ -re {Debug error: program version \([0-9]+\) is beyond the maximum supported protocol version \([0-9]+\)} { set FAILED 1; close }
}
if { $FAILED == 0 } {
puts "ERROR: the command should have failed"