Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion buildnumber.dat
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0
1
6 changes: 4 additions & 2 deletions cmd/tealdbg/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 := ""
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand Down
5 changes: 4 additions & 1 deletion cmd/tealdbg/localLedger.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
74 changes: 74 additions & 0 deletions cmd/tealdbg/local_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
2 changes: 1 addition & 1 deletion daemon/algod/api/server/v2/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down
43 changes: 6 additions & 37 deletions daemon/algod/api/server/v2/dryrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -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":
Expand All @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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 {
Expand Down
156 changes: 155 additions & 1 deletion daemon/algod/api/server/v2/dryrun_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
}
Loading