algorand / go-algorand

Algorand's official implementation in Go.
https://developer.algorand.org/
Other
1.35k stars 469 forks source link

Assert with reason code #3013

Open hernandp opened 3 years ago

hernandp commented 3 years ago

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.

algoanne commented 2 years ago

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

hernandp commented 2 years ago

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.

algoanne commented 2 years ago

thanks for the additional context!

fergalwalsh commented 2 years ago

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.

hernandp commented 2 years ago

@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)

algoanne commented 2 years ago

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

michaeldiamant commented 2 years ago

Summarizing a brainstormed idea during live discussion:

fergalwalsh commented 2 years ago

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.

jannotti commented 2 years ago

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.