go-algorand icon indicating copy to clipboard operation
go-algorand copied to clipboard

Assert with reason code

Open hernandp opened this issue 4 years ago • 9 comments

I found the assertion opcode to be very useful to prematurely abort execution on failed checks, but how difficult would be to have an opcode like

assert i

where i is an integer representing reason code , that allows client code to identify where the program failed. I know there is a program counter information but that's very error prone for development purposes.

Thanks in advance.

hernandp avatar Oct 06 '21 19:10 hernandp

I believe this problem was resolved with #3082, but let me know if not.

algoanne avatar Nov 19 '21 17:11 algoanne

Hi @algoanne , it was not the same thing unfortunately.

What is needed from my point of view is to be able to trigger asserts from TEAL that can return a code to the caller, so automated tests for contracts can be built . With complex contracts, where multiple assertions maybe thrown, it is hard or nearly impossible to track execution. And using the "program counter" information for this purpose is not useful, since any modification would break down the entire test set.

hernandp avatar Nov 19 '21 17:11 hernandp

thanks for the additional context!

algoanne avatar Nov 19 '21 21:11 algoanne

Adding a comment here for extra support for this feature. I raised this issue in Discord and we had a discussion. No agreement reached but I still strongly believe something like this is required. Not just for testing/debugging but for end-user applications that need to display friendly/meaningful error messages depending on why the program failed. Raising an integer error code would make that possible and would be very developer friendly.

fergalwalsh avatar Feb 04 '22 17:02 fergalwalsh

@fergalwalsh I talked with @jannotti about this also. I'm interested -in particular- in deep testing features but error reporting in general is much needed in Algorand. Logging/state use is not feasible since any non-elemental solution in Algorand involves stateless contracts. At our team we are expectant on the possibility of the future integration of assembly-to-line-map feature to be able to track execution (e.g: https://github.com/algorand/go-algorand/pull/3322)

hernandp avatar Feb 04 '22 17:02 hernandp

Related to this, here's a little hack for assertions that gives the python line number that may be useful to you: https://github.com/certusone/wormhole/blob/cc72c2a644c65859eaae5103c925e6e95557e706/algorand/wormhole_core.py#L62 @hernandp @fergalwalsh

algoanne avatar May 05 '22 16:05 algoanne

Summarizing a brainstormed idea during live discussion:

  • Idea: Support referencing an assertion by associating an alias to each PyTeal source line containing an assert at source map creation time.
  • How it works:
    • In PyTeal, expose an API akin to NamedAssert(condition: Expr, name: str). name is an alias providing a convenient way to refer to a specific assertion.
      • It's possible name can take other data types.
    • Create a PyTeal-to-symbolic name source map alongside the TEAL-to-PyTeal source map (via https://github.com/algorand/pyteal/issues/449).
    • Compose source maps to make these jumps: PC -> TEAL -> PyTeal -> assert alias.
    • Given the association with an assert alias, it seems plausible to allow a Python assert comparing returned assert alias to expected alias.
  • Note - The approach does not modify TEAL source. So, it does not impact program size or evaluation cost.

michaeldiamant avatar Oct 13 '22 12:10 michaeldiamant

I went with something similar in the end. Since I last commented on this issue we have begun using a new higher level language that compiles to Teal rather than writing Teal directly. In the HLL we do something like this:

assert(output_amount >= min_amount, "Output below expected amount")

which compiles to a normal assert but the compiler also tracks the location of the assert so it can produce a mapping of pc to error messages. We plan to include this mapping as errors.json within our contracts repo so sdks/clients can read this and return useful errors to the user.

This would still be very painful to do though for the poor souls still handwriting Teal.

fergalwalsh avatar Oct 13 '22 13:10 fergalwalsh

I think the corresponding tool on Teal would take a label name in the unit test. You would add a label for the purpose of testing a particular assert.

txn Sender
addr HARD CODED
==
auth_check: assert

Your unit test would then want to be able to invoke the app and assert that the returned PC equals the auth_check label. That seems easy with the source maps.

jannotti avatar Oct 13 '22 16:10 jannotti