Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extended logic eval error #2975

Merged
merged 2 commits into from
Sep 30, 2021
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
28 changes: 28 additions & 0 deletions data/transactions/logic/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -3938,3 +3938,31 @@ func opTxSubmit(cx *EvalContext) {
})
cx.subtxn = nil
}

// PcDetails return PC and disassembled instructions at PC up to 2 opcodes back
func (cx *EvalContext) PcDetails() (pc int, dis string) {
const maxNumAdditionalOpcodes = 2
text, ds, err := disassembleInstrumented(cx.program, nil)
if err != nil {
return cx.pc, dis
}

for i := 0; i < len(ds.pcOffset); i++ {
if ds.pcOffset[i].PC == cx.pc {
start := 0
if i >= maxNumAdditionalOpcodes {
start = i - maxNumAdditionalOpcodes
}

startTextPos := ds.pcOffset[start].Offset
endTextPos := len(text)
if i+1 < len(ds.pcOffset) {
endTextPos = ds.pcOffset[i+1].Offset
}

dis = text[startTextPos:endTextPos]
break
}
}
return cx.pc, dis
}
39 changes: 39 additions & 0 deletions data/transactions/logic/eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4842,3 +4842,42 @@ func TestLog(t *testing.T) {
require.False(t, pass)
}
}

func TestPcDetails(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()

var tests = []struct {
source string
pc int
det string
}{
{"int 1; int 2; -", 5, "pushint 1\npushint 2\n-\n"},
{"int 1; err", 3, "pushint 1\nerr\n"},
{"int 1; dup; int 2; -; +", 6, "dup\npushint 2\n-\n"},
{"b end; end:", 4, ""},
}
for i, test := range tests {
t.Run(fmt.Sprintf("i=%d", i), func(t *testing.T) {
ops := testProg(t, test.source, LogicVersion)
txn := makeSampleTxn()
txgroup := makeSampleTxnGroup(txn)
txn.Lsig.Logic = ops.Program
sb := strings.Builder{}
ep := defaultEvalParams(&sb, &txn)
ep.TxnGroup = txgroup

var cx EvalContext
cx.EvalParams = ep
cx.runModeFlags = runModeSignature

pass, err := eval(ops.Program, &cx)
require.Error(t, err)
require.False(t, pass)

pc, det := cx.PcDetails()
require.Equal(t, test.pc, pc)
require.Equal(t, test.det, det)
})
}
}
7 changes: 6 additions & 1 deletion ledger/appcow.go
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,12 @@ func (cb *roundCowState) StatefulEval(params logic.EvalParams, aidx basics.AppIn
var cx *logic.EvalContext
pass, cx, err = logic.EvalStatefulCx(program, params)
if err != nil {
return false, transactions.EvalDelta{}, ledgercore.LogicEvalError{Err: err}
var details string
if cx != nil {
pc, det := cx.PcDetails()
details = fmt.Sprintf("pc=%d, opcodes=%s", pc, det)
}
return false, transactions.EvalDelta{}, ledgercore.LogicEvalError{Err: err, Details: details}
}

// If program passed, build our eval delta, and commit to state changes
Expand Down
9 changes: 7 additions & 2 deletions ledger/ledgercore/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,17 @@ func (err ErrNoEntry) Error() string {

// LogicEvalError indicates TEAL evaluation failure
type LogicEvalError struct {
Err error
Err error
Details string
}

// Error satisfies builtin interface `error`
func (err LogicEvalError) Error() string {
return fmt.Sprintf("logic eval error: %v", err.Err)
msg := fmt.Sprintf("logic eval error: %v", err.Err)
if len(err.Details) > 0 {
msg = fmt.Sprintf("%s. Details: %s", msg, err.Details)
}
return msg
}

// ErrNonSequentialBlockEval provides feedback when the evaluator cannot be created for
Expand Down