From d0f9d8d68a32ae28d6d09d91a92ca61013b6ab11 Mon Sep 17 00:00:00 2001 From: Ben Guidarelli Date: Fri, 24 Jun 2022 10:05:29 -0400 Subject: [PATCH 001/157] upping max teal version --- pyteal/compiler/compiler.py | 2 +- pyteal/compiler/compiler_test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyteal/compiler/compiler.py b/pyteal/compiler/compiler.py index 5a6709efe..2a68be57a 100644 --- a/pyteal/compiler/compiler.py +++ b/pyteal/compiler/compiler.py @@ -25,7 +25,7 @@ ) from pyteal.compiler.constants import createConstantBlocks -MAX_TEAL_VERSION = 6 +MAX_TEAL_VERSION = 7 MIN_TEAL_VERSION = 2 DEFAULT_TEAL_VERSION = MIN_TEAL_VERSION diff --git a/pyteal/compiler/compiler_test.py b/pyteal/compiler/compiler_test.py index 0d6fdbe09..b3e528506 100644 --- a/pyteal/compiler/compiler_test.py +++ b/pyteal/compiler/compiler_test.py @@ -139,7 +139,7 @@ def test_compile_version_invalid(): pt.compileTeal(expr, pt.Mode.Signature, version=1) # too small with pytest.raises(pt.TealInputError): - pt.compileTeal(expr, pt.Mode.Signature, version=7) # too large + pt.compileTeal(expr, pt.Mode.Signature, version=8) # too large with pytest.raises(pt.TealInputError): pt.compileTeal(expr, pt.Mode.Signature, version=2.0) # decimal From 749fb8c8e4cd956d5cd855f2288f5ba1c09eb160 Mon Sep 17 00:00:00 2001 From: Ben Guidarelli Date: Thu, 30 Jun 2022 11:02:28 -0400 Subject: [PATCH 002/157] adding program page related ops (#412) * adding program page related ops --- docs/accessing_transaction_field.rst | 44 ++++++++++++---------- pyteal/ast/txn.py | 56 ++++++++++++++++++++++++++++ pyteal/ast/txn_test.py | 6 +++ 3 files changed, 86 insertions(+), 20 deletions(-) diff --git a/docs/accessing_transaction_field.rst b/docs/accessing_transaction_field.rst index adb8125e8..ea37663e5 100644 --- a/docs/accessing_transaction_field.rst +++ b/docs/accessing_transaction_field.rst @@ -37,26 +37,30 @@ Operator Application Call ....................................................... -================================================================================ ========================= ================ ============================================================================ -Operator Type Min TEAL Version Notes -================================================================================ ========================= ================ ============================================================================ -:any:`Txn.application_id() ` :code:`TealType.uint64` 2 -:any:`Txn.on_completion() ` :code:`TealType.uint64` 2 -:any:`Txn.approval_program() ` :code:`TealType.bytes` 2 -:any:`Txn.global_num_uints() ` :code:`TealType.uint64` 3 Maximum global integers in app schema -:any:`Txn.global_num_byte_slices() ` :code:`TealType.uint64` 3 Maximum global byte strings in app schema -:any:`Txn.local_num_uints() ` :code:`TealType.uint64` 3 Maximum local integers in app schema -:any:`Txn.local_num_byte_slices() ` :code:`TealType.uint64` 3 Maximum local byte strings in app schema -:any:`Txn.accounts ` :code:`TealType.bytes[]` 2 Array of accounts available to the application -:any:`Txn.assets ` :code:`TealType.uint64[]` 3 Array of assets available to the application -:any:`Txn.applications ` :code:`TealType.uint64[]` 3 Array of applications -:any:`Txn.clear_state_program() ` :code:`TealType.bytes` 2 -:any:`Txn.extra_program_pages() ` :code:`TealType.uint64` 4 Number of extra program pages for app -:any:`Txn.application_args ` :code:`TealType.bytes[]` 2 Array of application arguments -:any:`Txn.created_application_id() ` :code:`TealType.uint64` 5 The ID of the newly created application in this transaction. In v5, only valid on inner transactions. >= v6 works with top-level and inner transactions. -:any:`Txn.logs ` :code:`TealType.bytes[]` 5 Array of application logged items. In v5, only valid on inner transactions. >= v6 works with top-level and inner transactions. -:any:`Txn.last_log() ` :code:`TealType.bytes[]` 6 The last message emitted. Empty bytes if none were emitted. Application mode only. -================================================================================ ========================= ================ ============================================================================ +==================================================================================== ========================= ================ ============================================================================ +Operator Type Min TEAL Version Notes +==================================================================================== ========================= ================ ============================================================================ +:any:`Txn.application_id() ` :code:`TealType.uint64` 2 +:any:`Txn.on_completion() ` :code:`TealType.uint64` 2 +:any:`Txn.approval_program() ` :code:`TealType.bytes` 2 +:any:`Txn.global_num_uints() ` :code:`TealType.uint64` 3 Maximum global integers in app schema +:any:`Txn.global_num_byte_slices() ` :code:`TealType.uint64` 3 Maximum global byte strings in app schema +:any:`Txn.local_num_uints() ` :code:`TealType.uint64` 3 Maximum local integers in app schema +:any:`Txn.local_num_byte_slices() ` :code:`TealType.uint64` 3 Maximum local byte strings in app schema +:any:`Txn.accounts ` :code:`TealType.bytes[]` 2 Array of accounts available to the application +:any:`Txn.assets ` :code:`TealType.uint64[]` 3 Array of assets available to the application +:any:`Txn.applications ` :code:`TealType.uint64[]` 3 Array of applications +:any:`Txn.clear_state_program() ` :code:`TealType.bytes` 2 +:any:`Txn.extra_program_pages() ` :code:`TealType.uint64` 4 Number of extra program pages for app +:any:`Txn.application_args ` :code:`TealType.bytes[]` 2 Array of application arguments +:any:`Txn.created_application_id() ` :code:`TealType.uint64` 5 The ID of the newly created application in this transaction. In v5, only valid on inner transactions. >= v6 works with top-level and inner transactions. +:any:`Txn.logs ` :code:`TealType.bytes[]` 5 Array of application logged items. In v5, only valid on inner transactions. >= v6 works with top-level and inner transactions. +:any:`Txn.last_log() ` :code:`TealType.bytes[]` 6 The last message emitted. Empty bytes if none were emitted. Application mode only. +:any:`Txn.approval_program_pages() ` :code:`TealType.bytes[]` 7 The pages of the approval program as an array +:any:`Txn.num_approval_program_pages() ` :code:`TealType.uint64` 7 The number of approval program pages +:any:`Txn.clear_state_program_pages() ` :code:`TealType.bytes[]` 7 The pages of a clear state program as an array +:any:`Txn.num_clear_state_program_pages() ` :code:`TealType.uint64` 7 The number of clear state program pages +==================================================================================== ========================= ================ ============================================================================ Asset Config ....................................................... diff --git a/pyteal/ast/txn.py b/pyteal/ast/txn.py index e9182b74f..3c0fc0f4e 100644 --- a/pyteal/ast/txn.py +++ b/pyteal/ast/txn.py @@ -110,6 +110,22 @@ class TxnField(Enum): created_application_id = (61, "CreatedApplicationID", TealType.uint64, False, 5) last_log = (62, "LastLog", TealType.bytes, False, 6) state_proof_pk = (63, "StateProofPK", TealType.bytes, False, 6) + approval_program_pages = (64, "ApprovalProgramPages", TealType.bytes, True, 7) + num_approval_program_pages = ( + 65, + "NumApprovalProgramPages", + TealType.uint64, + False, + 7, + ) + clear_state_program_pages = (66, "ClearStateProgramPages", TealType.bytes, True, 7) + num_clear_state_program_pages = ( + 67, + "NumClearStateProgramPages", + TealType.uint64, + False, + 7, + ) def __init__( self, id: int, name: str, type: TealType, is_array: bool, min_version: int @@ -728,6 +744,20 @@ def state_proof_pk(self) -> TxnExpr: """ return self.makeTxnExpr(TxnField.state_proof_pk) + def num_approval_program_pages(self) -> TxnExpr: + """Get the number of pages in the approval program. + + Requires TEAL version 7 or higher. + """ + return self.makeTxnExpr(TxnField.num_approval_program_pages) + + def num_clear_state_program_pages(self) -> TxnExpr: + """Get the number of pages in the clear state program. + + Requires TEAL version 7 or higher. + """ + return self.makeTxnExpr(TxnField.num_clear_state_program_pages) + @property def application_args(self) -> TxnArray: """Application call arguments array. @@ -777,6 +807,32 @@ def logs(self) -> TxnArray: """ return TxnArray(self, TxnField.logs, TxnField.num_logs) + @property + def approval_program_pages(self) -> TxnArray: + """The approval program pages. + + :type: TxnArray + + Requires TEAL version 7 or higher. + """ + return TxnArray( + self, TxnField.approval_program_pages, TxnField.num_approval_program_pages + ) + + @property + def clear_state_program_pages(self) -> TxnArray: + """The clear state program pages. + + :type: TxnArray + + Requires TEAL version 7 or higher. + """ + return TxnArray( + self, + TxnField.clear_state_program_pages, + TxnField.num_clear_state_program_pages, + ) + TxnObject.__module__ = "pyteal" diff --git a/pyteal/ast/txn_test.py b/pyteal/ast/txn_test.py index eaaf01464..c0477fd23 100644 --- a/pyteal/ast/txn_test.py +++ b/pyteal/ast/txn_test.py @@ -58,6 +58,8 @@ pt.TxnField.created_application_id: lambda txn: txn.created_application_id(), pt.TxnField.last_log: lambda txn: txn.last_log(), pt.TxnField.state_proof_pk: lambda txn: txn.state_proof_pk(), + pt.TxnField.num_approval_program_pages: lambda txn: txn.num_approval_program_pages(), + pt.TxnField.num_clear_state_program_pages: lambda txn: txn.num_clear_state_program_pages(), } arrayFieldToProperty: Dict[pt.TxnField, Callable[[pt.TxnObject], pt.TxnArray]] = { @@ -66,6 +68,8 @@ pt.TxnField.assets: lambda txn: txn.assets, pt.TxnField.applications: lambda txn: txn.applications, pt.TxnField.logs: lambda txn: txn.logs, + pt.TxnField.approval_program_pages: lambda txn: txn.approval_program_pages, + pt.TxnField.clear_state_program_pages: lambda txn: txn.clear_state_program_pages, } arrayFieldToLengthField: Dict[pt.TxnField, pt.TxnField] = { @@ -74,6 +78,8 @@ pt.TxnField.assets: pt.TxnField.num_assets, pt.TxnField.applications: pt.TxnField.num_applications, pt.TxnField.logs: pt.TxnField.num_logs, + pt.TxnField.approval_program_pages: pt.TxnField.num_approval_program_pages, + pt.TxnField.clear_state_program_pages: pt.TxnField.num_clear_state_program_pages, } From 39a11c283eaa101d8188811ce22bc1e583baf151 Mon Sep 17 00:00:00 2001 From: Jacob Daitzman Date: Thu, 30 Jun 2022 11:50:44 -0400 Subject: [PATCH 003/157] Add Replace (#413) * Add Replace * Remove replace auto-import * Use scripts/generate_init.py * Add more tests to replace, substring, and extract (#1) Co-authored-by: Michael Diamant --- pyteal/__init__.pyi | 1 + pyteal/ast/__init__.py | 2 + pyteal/ast/replace.py | 86 ++++++++++++++++++++++++++++++++ pyteal/ast/replace_test.py | 97 ++++++++++++++++++++++++++++++++++++ pyteal/ast/substring.py | 12 ++--- pyteal/ast/substring_test.py | 82 ++++++++++++++++++++++++++++++ pyteal/ir/ops.py | 2 + 7 files changed, 276 insertions(+), 6 deletions(-) create mode 100644 pyteal/ast/replace.py create mode 100644 pyteal/ast/replace_test.py diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 4fa32d071..20bc15dd4 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -138,6 +138,7 @@ __all__ = [ "Or", "Pop", "Reject", + "Replace", "Return", "ScratchIndex", "ScratchLoad", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 613a39480..a72c064fc 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -102,6 +102,7 @@ # ternary ops from pyteal.ast.ternaryexpr import Divw, Ed25519Verify, SetBit, SetByte from pyteal.ast.substring import Substring, Extract, Suffix +from pyteal.ast.replace import Replace # more ops from pyteal.ast.naryexpr import NaryExpr, And, Or, Concat @@ -272,6 +273,7 @@ "ExtractUint16", "ExtractUint32", "ExtractUint64", + "Replace", "Log", "While", "For", diff --git a/pyteal/ast/replace.py b/pyteal/ast/replace.py new file mode 100644 index 000000000..2b7968978 --- /dev/null +++ b/pyteal/ast/replace.py @@ -0,0 +1,86 @@ +from typing import cast, TYPE_CHECKING + +from pyteal.types import TealType, require_type +from pyteal.errors import verifyTealVersion +from pyteal.ir import TealOp, Op, TealBlock +from pyteal.ast.expr import Expr +from pyteal.ast.int import Int +from pyteal.ast.ternaryexpr import TernaryExpr + +if TYPE_CHECKING: + from pyteal.compiler import CompileOptions + + +class ReplaceExpr(Expr): + """An expression for replacing a section of a byte string at a given start index""" + + def __init__(self, original: Expr, start: Expr, replacement: Expr) -> None: + super().__init__() + + require_type(original, TealType.bytes) + require_type(start, TealType.uint64) + require_type(replacement, TealType.bytes) + + self.original = original + self.start = start + self.replacement = replacement + + # helper method for correctly populating op + def __get_op(self, options: "CompileOptions"): + s = cast(Int, self.start).value + if s < 2**8: + return Op.replace2 + else: + return Op.replace3 + + def __teal__(self, options: "CompileOptions"): + if not isinstance(self.start, Int): + return TernaryExpr( + Op.replace3, + (TealType.bytes, TealType.uint64, TealType.bytes), + TealType.bytes, + self.original, + self.start, + self.replacement, + ).__teal__(options) + + op = self.__get_op(options) + + verifyTealVersion( + op.min_version, + options.version, + "TEAL version too low to use op {}".format(op), + ) + + s = cast(Int, self.start).value + if op == Op.replace2: + return TealBlock.FromOp( + options, TealOp(self, op, s), self.original, self.replacement + ) + elif op == Op.replace3: + return TealBlock.FromOp( + options, TealOp(self, op), self.original, self.start, self.replacement + ) + + def __str__(self): + return "(Replace {} {} {})".format(self.original, self.start, self.replacement) + + def type_of(self): + return TealType.bytes + + def has_return(self): + return False + + +def Replace(original: Expr, start: Expr, replacement: Expr) -> Expr: + """ + Replace a portion of original bytes with new bytes at a given starting point. + + Requires TEAL version 7 or higher. + + Args: + original: The value containing the original bytes. Must evaluate to bytes. + start: The index of the byte where replacement starts. Must evaluate to an integer less than Len(original). + replacement: The value containing the replacement bytes. Must evaluate to bytes with length at most Len(original) - start. + """ + return ReplaceExpr(original, start, replacement) diff --git a/pyteal/ast/replace_test.py b/pyteal/ast/replace_test.py new file mode 100644 index 000000000..b72a5d879 --- /dev/null +++ b/pyteal/ast/replace_test.py @@ -0,0 +1,97 @@ +import pytest + +import pyteal as pt + +teal6Options = pt.CompileOptions(version=6) +teal7Options = pt.CompileOptions(version=7) + + +def test_replace_immediate(): + args = [pt.Bytes("my string"), pt.Int(0), pt.Bytes("abcdefghi")] + expr = pt.Replace(args[0], args[1], args[2]) + assert expr.type_of() == pt.TealType.bytes + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(args[0], pt.Op.byte, '"my string"'), + pt.TealOp(args[2], pt.Op.byte, '"abcdefghi"'), + pt.TealOp(expr, pt.Op.replace2, 0), + ] + ) + + actual, _ = expr.__teal__(teal7Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + with pytest.raises(pt.TealInputError): + expr.__teal__(teal6Options) + + +def test_replace_stack_int(): + my_string = "*" * 257 + args = [pt.Bytes(my_string), pt.Int(256), pt.Bytes("ab")] + expr = pt.Replace(args[0], args[1], args[2]) + assert expr.type_of() == pt.TealType.bytes + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(args[0], pt.Op.byte, '"{my_string}"'.format(my_string=my_string)), + pt.TealOp(args[1], pt.Op.int, 256), + pt.TealOp(args[2], pt.Op.byte, '"ab"'), + pt.TealOp(expr, pt.Op.replace3), + ] + ) + + actual, _ = expr.__teal__(teal7Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + with pytest.raises(pt.TealInputError): + expr.__teal__(teal6Options) + + +# Mirrors `test_replace_stack_int`, but attempts replacement with start != pt.Int. +def test_replace_stack_not_int(): + my_string = "*" * 257 + add = pt.Add(pt.Int(254), pt.Int(2)) + args = [pt.Bytes(my_string), add, pt.Bytes("ab")] + expr = pt.Replace(args[0], args[1], args[2]) + assert expr.type_of() == pt.TealType.bytes + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(args[0], pt.Op.byte, '"{my_string}"'.format(my_string=my_string)), + pt.TealOp(pt.Int(254), pt.Op.int, 254), + pt.TealOp(pt.Int(2), pt.Op.int, 2), + pt.TealOp(add, pt.Op.add), + pt.TealOp(args[2], pt.Op.byte, '"ab"'), + pt.TealOp(expr, pt.Op.replace3), + ] + ) + + actual, _ = expr.__teal__(teal7Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + with pt.TealComponent.Context.ignoreExprEquality(): + assert actual == expected + + with pytest.raises(pt.TealInputError): + expr.__teal__(teal6Options) + + +def test_replace_invalid(): + with pytest.raises(pt.TealTypeError): + pt.Replace(pt.Bytes("my string"), pt.Int(0), pt.Int(1)) + + with pytest.raises(pt.TealTypeError): + pt.Replace( + pt.Bytes("my string"), pt.Bytes("should be int"), pt.Bytes("abcdefghi") + ) + + with pytest.raises(pt.TealTypeError): + pt.Replace(pt.Bytes("my string"), pt.Txn.sender(), pt.Bytes("abcdefghi")) diff --git a/pyteal/ast/substring.py b/pyteal/ast/substring.py index 438b40933..6febf69dc 100644 --- a/pyteal/ast/substring.py +++ b/pyteal/ast/substring.py @@ -26,7 +26,7 @@ def __init__(self, stringArg: Expr, startArg: Expr, endArg: Expr) -> None: self.endArg = endArg # helper method for correctly populating op - def __getOp(self, options: "CompileOptions"): + def __get_op(self, options: "CompileOptions"): s, e = cast(Int, self.startArg).value, cast(Int, self.endArg).value l = e - s @@ -58,7 +58,7 @@ def __teal__(self, options: "CompileOptions"): self.endArg, ).__teal__(options) - op = self.__getOp(options) + op = self.__get_op(options) verifyTealVersion( op.min_version, @@ -121,7 +121,7 @@ def __init__(self, stringArg: Expr, startArg: Expr, lenArg: Expr) -> None: self.lenArg = lenArg # helper method for correctly populating op - def __getOp(self, options: "CompileOptions"): + def __get_op(self, options: "CompileOptions"): s, l = cast(Int, self.startArg).value, cast(Int, self.lenArg).value if s < 2**8 and l > 0 and l < 2**8: return Op.extract @@ -139,7 +139,7 @@ def __teal__(self, options: "CompileOptions"): self.lenArg, ).__teal__(options) - op = self.__getOp(options) + op = self.__get_op(options) verifyTealVersion( op.min_version, @@ -186,7 +186,7 @@ def __init__( self.startArg = startArg # helper method for correctly populating op - def __getOp(self, options: "CompileOptions"): + def __get_op(self, options: "CompileOptions"): if not isinstance(self.startArg, Int): return Op.substring3 @@ -197,7 +197,7 @@ def __getOp(self, options: "CompileOptions"): return Op.substring3 def __teal__(self, options: "CompileOptions"): - op = self.__getOp(options) + op = self.__get_op(options) verifyTealVersion( op.min_version, diff --git a/pyteal/ast/substring_test.py b/pyteal/ast/substring_test.py index 2aafeabfd..ae5bcace2 100644 --- a/pyteal/ast/substring_test.py +++ b/pyteal/ast/substring_test.py @@ -272,6 +272,88 @@ def test_suffix_stack(): assert actual == expected +@pytest.mark.parametrize("op", [pt.Op.extract3, pt.Op.substring3]) +def test_startArg_not_int(op: pt.Op): + my_string = "*" * 257 + add = pt.Add(pt.Int(254), pt.Int(2)) + args = [pt.Bytes(my_string), add, pt.Int(257)] + + def generate_expr() -> pt.Expr: + match op: + case pt.Op.extract3: + return pt.Extract(args[0], args[1], args[2]) + case pt.Op.substring3: + return pt.Substring(args[0], args[1], args[2]) + case _: + raise Exception(f"Unsupported {op=}") + + expr = generate_expr() + assert expr.type_of() == pt.TealType.bytes + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(args[0], pt.Op.byte, '"{my_string}"'.format(my_string=my_string)), + pt.TealOp(pt.Int(254), pt.Op.int, 254), + pt.TealOp(pt.Int(2), pt.Op.int, 2), + pt.TealOp(add, pt.Op.add), + pt.TealOp(args[2], pt.Op.int, 257), + pt.TealOp(None, op), + ] + ) + + actual, _ = expr.__teal__(teal5Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + with pt.TealComponent.Context.ignoreExprEquality(): + assert actual == expected + + if op == pt.Op.extract3: + with pytest.raises(pt.TealInputError): + expr.__teal__(teal4Options) + + +@pytest.mark.parametrize("op", [pt.Op.extract3, pt.Op.substring3]) +def test_endArg_not_int(op: pt.Op): + my_string = "*" * 257 + add = pt.Add(pt.Int(254), pt.Int(3)) + args = [pt.Bytes(my_string), pt.Int(256), add] + + def generate_expr() -> pt.Expr: + match op: + case pt.Op.extract3: + return pt.Extract(args[0], args[1], args[2]) + case pt.Op.substring3: + return pt.Substring(args[0], args[1], args[2]) + case _: + raise Exception(f"Unsupported {op=}") + + expr = generate_expr() + assert expr.type_of() == pt.TealType.bytes + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(args[0], pt.Op.byte, '"{my_string}"'.format(my_string=my_string)), + pt.TealOp(args[1], pt.Op.int, 256), + pt.TealOp(pt.Int(254), pt.Op.int, 254), + pt.TealOp(pt.Int(3), pt.Op.int, 3), + pt.TealOp(add, pt.Op.add), + pt.TealOp(None, op), + ] + ) + + actual, _ = expr.__teal__(teal5Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + with pt.TealComponent.Context.ignoreExprEquality(): + assert actual == expected + + if op == pt.Op.extract3: + with pytest.raises(pt.TealInputError): + expr.__teal__(teal4Options) + + def test_suffix_invalid(): with pytest.raises(pt.TealTypeError): pt.Suffix(pt.Int(0), pt.Int(0)) diff --git a/pyteal/ir/ops.py b/pyteal/ir/ops.py index 7d91dab42..f9a8f731e 100644 --- a/pyteal/ir/ops.py +++ b/pyteal/ir/ops.py @@ -179,6 +179,8 @@ def min_version(self) -> int: gitxnas = OpType("gitxnas", Mode.Application, 6) gloadss = OpType("gloadss", Mode.Application, 6) acct_params_get = OpType("acct_params_get", Mode.Application, 6) + replace2 = OpType("replace2", Mode.Signature | Mode.Application, 7) + replace3 = OpType("replace3", Mode.Signature | Mode.Application, 7) # fmt: on From dd2c7ecc0617137411951e87452a58fde2887a8e Mon Sep 17 00:00:00 2001 From: Jacob Daitzman Date: Thu, 30 Jun 2022 12:09:30 -0400 Subject: [PATCH 004/157] Add Block (#415) * Add Block # Conflicts: # pyteal/ir/ops.py * Disable flake8 errors on formatted lines * Add past version failure check * Remove unnecessary ignore Expr equality context --- pyteal/__init__.pyi | 1 + pyteal/ast/__init__.py | 2 + pyteal/ast/block.py | 80 ++++++++++++++++++++++++++++++++++++++++ pyteal/ast/block_test.py | 60 ++++++++++++++++++++++++++++++ pyteal/ir/ops.py | 1 + 5 files changed, 144 insertions(+) create mode 100644 pyteal/ast/block.py create mode 100644 pyteal/ast/block_test.py diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 20bc15dd4..85f89147a 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -43,6 +43,7 @@ __all__ = [ "BitwiseNot", "BitwiseOr", "BitwiseXor", + "Block", "Break", "Btoi", "Bytes", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index a72c064fc..de22eb659 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -20,6 +20,7 @@ Txn, ) from pyteal.ast.gtxn import GtxnExpr, GtxnaExpr, TxnGroup, Gtxn +from pyteal.ast.block import Block from pyteal.ast.gaid import GeneratedID from pyteal.ast.gitxn import Gitxn, GitxnExpr, GitxnaExpr, InnerTxnGroup from pyteal.ast.gload import ImportScratchValue @@ -162,6 +163,7 @@ "GtxnaExpr", "TxnGroup", "Gtxn", + "Block", "GeneratedID", "ImportScratchValue", "Global", diff --git a/pyteal/ast/block.py b/pyteal/ast/block.py new file mode 100644 index 000000000..041483aae --- /dev/null +++ b/pyteal/ast/block.py @@ -0,0 +1,80 @@ +from typing import TYPE_CHECKING +from enum import Enum + +from pyteal.types import TealType, require_type +from pyteal.errors import verifyFieldVersion +from pyteal.ir import TealOp, Op, TealBlock +from pyteal.ast.expr import Expr +from pyteal.ast.leafexpr import LeafExpr + +if TYPE_CHECKING: + from pyteal.compiler import CompileOptions + + +class BlockField(Enum): + # fmt: off + # id | name | type | min version + block_seed = (0, "BlkSeed", TealType.bytes, 7) # noqa: E222 + block_timestamp = (1, "BlkTimestamp", TealType.uint64, 7) # noqa: E222 + + # fmt: on + + def __init__(self, id: int, name: str, type: TealType, min_version: int) -> None: + self.id = id + self.arg_name = name + self.ret_type = type + self.min_version = min_version + + def type_of(self) -> TealType: + return self.ret_type + + +BlockField.__module__ = "pyteal" + + +class Block(LeafExpr): + """An expression that accesses a block property.""" + + def __init__(self, field: BlockField, block: Expr) -> None: + super().__init__() + self.field = field + + require_type(block, TealType.uint64) + self.block = block + + def __teal__(self, options: "CompileOptions"): + verifyFieldVersion(self.field.arg_name, self.field.min_version, options.version) + + op = TealOp(self, Op.block, self.field.arg_name) + return TealBlock.FromOp(options, op, self.block) + + def __str__(self): + return "(Block {})".format(self.field.arg_name) + + def type_of(self): + return self.field.type_of() + + @classmethod + def seed(cls, block: Expr) -> "Block": + """Get the seed of a block. + + Args: + block: A block index that corresponds to the block to check, + must be evaluated to uint64. Fails if the block index is not less than the + current round or more than 1001 rounds before txn.LastValid. + """ + return cls(BlockField.block_seed, block) + + @classmethod + def timestamp(cls, block: Expr) -> "Block": + """Get the timestamp of a block. + + Args: + block: A block index that corresponds to the block to check, + must be evaluated to uint64. Fails if the block index is not less than the + current round or more than 1001 rounds before txn.LastValid. + """ + return cls(BlockField.block_timestamp, block) + + +Block.__module__ = "pyteal" diff --git a/pyteal/ast/block_test.py b/pyteal/ast/block_test.py new file mode 100644 index 000000000..0cd571063 --- /dev/null +++ b/pyteal/ast/block_test.py @@ -0,0 +1,60 @@ +import pytest + +import pyteal as pt + +teal6Options = pt.CompileOptions(version=6) +teal7Options = pt.CompileOptions(version=7) + + +def test_block_seed(): + arg = pt.Int(0) + expr = pt.Block.seed(arg) + assert expr.type_of() == pt.TealType.bytes + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(arg, pt.Op.int, 0), + pt.TealOp(expr, pt.Op.block, "BlkSeed"), + ] + ) + + actual, _ = expr.__teal__(teal7Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + with pytest.raises(pt.TealInputError): + expr.__teal__(teal6Options) + + +def test_block_seed_invalid(): + with pytest.raises(pt.TealTypeError): + pt.Block.seed(pt.Bytes("")) + + +def test_block_timestamp(): + arg = pt.Int(0) + expr = pt.Block.timestamp(arg) + assert expr.type_of() == pt.TealType.uint64 + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(arg, pt.Op.int, 0), + pt.TealOp(expr, pt.Op.block, "BlkTimestamp"), + ] + ) + + actual, _ = expr.__teal__(teal7Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + with pytest.raises(pt.TealInputError): + expr.__teal__(teal6Options) + + +def test_block_timestamp_invalid(): + with pytest.raises(pt.TealTypeError): + pt.Block.timestamp(pt.Txn.sender()) diff --git a/pyteal/ir/ops.py b/pyteal/ir/ops.py index f9a8f731e..3a2c49f37 100644 --- a/pyteal/ir/ops.py +++ b/pyteal/ir/ops.py @@ -181,6 +181,7 @@ def min_version(self) -> int: acct_params_get = OpType("acct_params_get", Mode.Application, 6) replace2 = OpType("replace2", Mode.Signature | Mode.Application, 7) replace3 = OpType("replace3", Mode.Signature | Mode.Application, 7) + block = OpType("block", Mode.Signature | Mode.Application, 7) # fmt: on From 8c3d2a03200e29694329e6102993b0460e6ea587 Mon Sep 17 00:00:00 2001 From: Jacob Daitzman Date: Thu, 30 Jun 2022 12:25:30 -0400 Subject: [PATCH 005/157] Add JsonRef (#417) * Add JsonRef * Use named class methods to specify value type * Remove unnecessary ignore Expr equality context * Fix docstring link --- pyteal/__init__.pyi | 1 + pyteal/ast/__init__.py | 2 + pyteal/ast/jsonref.py | 107 +++++++++++++++++++++++++++++++++++++ pyteal/ast/jsonref_test.py | 83 ++++++++++++++++++++++++++++ pyteal/ir/ops.py | 1 + 5 files changed, 194 insertions(+) create mode 100644 pyteal/ast/jsonref.py create mode 100644 pyteal/ast/jsonref_test.py diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 85f89147a..ec4af54a0 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -108,6 +108,7 @@ __all__ = [ "InnerTxnGroup", "Int", "Itob", + "JsonRef", "Keccak256", "LabelReference", "Le", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index de22eb659..919e8b6d6 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -104,6 +104,7 @@ from pyteal.ast.ternaryexpr import Divw, Ed25519Verify, SetBit, SetByte from pyteal.ast.substring import Substring, Extract, Suffix from pyteal.ast.replace import Replace +from pyteal.ast.jsonref import JsonRef # more ops from pyteal.ast.naryexpr import NaryExpr, And, Or, Concat @@ -285,4 +286,5 @@ "EcdsaVerify", "EcdsaDecompress", "EcdsaRecover", + "JsonRef", ] diff --git a/pyteal/ast/jsonref.py b/pyteal/ast/jsonref.py new file mode 100644 index 000000000..91018d714 --- /dev/null +++ b/pyteal/ast/jsonref.py @@ -0,0 +1,107 @@ +from typing import TYPE_CHECKING +from enum import Enum + +from pyteal.types import TealType, require_type +from pyteal.errors import verifyFieldVersion, verifyTealVersion +from pyteal.ir import TealOp, Op, TealBlock +from pyteal.ast.expr import Expr +from pyteal.ast.leafexpr import LeafExpr + +if TYPE_CHECKING: + from pyteal.compiler import CompileOptions + + +class JsonRefType(Enum): + # fmt: off + # id | name | type | min version + string = (0, "JSONString", TealType.bytes, 7) + uint64 = (1, "JSONUint64", TealType.uint64, 7) + object = (2, "JSONObject", TealType.bytes, 7) + # fmt: on + + def __init__(self, id: int, name: str, type: TealType, min_version: int) -> None: + self.id = id + self.arg_name = name + self.ret_type = type + self.min_version = min_version + + def type_of(self) -> TealType: + return self.ret_type + + +JsonRefType.__module__ = "pyteal" + + +class JsonRef(LeafExpr): + """An expression that accesses the value associated with a given key from a supported utf-8 encoded json object. + + The json object must satisfy a `particular specification `_. + """ + + def __init__(self, type: JsonRefType, json_obj: Expr, key: Expr) -> None: + super().__init__() + + self.type = type + + require_type(json_obj, TealType.bytes) + self.json_obj = json_obj + + require_type(key, TealType.bytes) + self.key = key + + def __teal__(self, options: "CompileOptions"): + verifyTealVersion( + Op.json_ref.min_version, + options.version, + "TEAL version too low to use op json_ref", + ) + + verifyFieldVersion(self.type.arg_name, self.type.min_version, options.version) + + op = TealOp(self, Op.json_ref, self.type.arg_name) + return TealBlock.FromOp(options, op, self.json_obj, self.key) + + def __str__(self): + return "(JsonRef {})".format(self.type.arg_name) + + def type_of(self): + return self.type.type_of() + + @classmethod + def as_string(cls, json_obj: Expr, key: Expr) -> "JsonRef": + """Access the value of a given key as a string. + + Refer to the `JsonRef` class documentation for valid json specification. + + Args: + json_obj: The utf-8 encoded json object. + key: The key to access in the json object. + """ + return cls(JsonRefType.string, json_obj, key) + + @classmethod + def as_uint64(cls, json_obj: Expr, key: Expr) -> "JsonRef": + """Access the value of a given key as a uint64. + + Refer to the `JsonRef` class documentation for valid json specification. + + Args: + json_obj: The utf-8 encoded json object. + key: The key to access in the json object. + """ + return cls(JsonRefType.uint64, json_obj, key) + + @classmethod + def as_object(cls, json_obj: Expr, key: Expr) -> "JsonRef": + """Access the value of a given key as a json object. + + Refer to the `JsonRef` class documentation for valid json specification. + + Args: + json_obj: The utf-8 encoded json object. + key: The key to access in the json object. + """ + return cls(JsonRefType.object, json_obj, key) + + +JsonRef.__module__ = "pyteal" diff --git a/pyteal/ast/jsonref_test.py b/pyteal/ast/jsonref_test.py new file mode 100644 index 000000000..356c74591 --- /dev/null +++ b/pyteal/ast/jsonref_test.py @@ -0,0 +1,83 @@ +import pytest + +import pyteal as pt + +teal6Options = pt.CompileOptions(version=6) +teal7Options = pt.CompileOptions(version=7) + + +def test_json_string(): + args = [pt.Bytes('{"foo":"bar"}'), pt.Bytes("foo")] + expr = pt.JsonRef.as_string(*args) + assert expr.type_of() == pt.TealType.bytes + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(args[0], pt.Op.byte, '"{\\"foo\\":\\"bar\\"}"'), + pt.TealOp(args[1], pt.Op.byte, '"foo"'), + pt.TealOp(expr, pt.Op.json_ref, "JSONString"), + ] + ) + + actual, _ = expr.__teal__(teal7Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + with pytest.raises(pt.TealInputError): + expr.__teal__(teal6Options) + + +def test_json_uint64(): + args = [pt.Bytes('{"foo":123456789}'), pt.Bytes("foo")] + expr = pt.JsonRef.as_uint64(*args) + assert expr.type_of() == pt.TealType.uint64 + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(args[0], pt.Op.byte, '"{\\"foo\\":123456789}"'), + pt.TealOp(args[1], pt.Op.byte, '"foo"'), + pt.TealOp(expr, pt.Op.json_ref, "JSONUint64"), + ] + ) + + actual, _ = expr.__teal__(teal7Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + with pytest.raises(pt.TealInputError): + expr.__teal__(teal6Options) + + +def test_json_object(): + args = [pt.Bytes('{"foo":{"key": "value"}}'), pt.Bytes("foo")] + expr = pt.JsonRef.as_object(*args) + assert expr.type_of() == pt.TealType.bytes + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(args[0], pt.Op.byte, '"{\\"foo\\":{\\"key\\": \\"value\\"}}"'), + pt.TealOp(args[1], pt.Op.byte, '"foo"'), + pt.TealOp(expr, pt.Op.json_ref, "JSONObject"), + ] + ) + + actual, _ = expr.__teal__(teal7Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + with pytest.raises(pt.TealInputError): + expr.__teal__(teal6Options) + + +def test_json_ref_invalid(): + with pytest.raises(pt.TealTypeError): + pt.JsonRef.as_object(pt.Int(0), pt.Bytes("a")) + + with pytest.raises(pt.TealTypeError): + pt.JsonRef.as_string(pt.Bytes("a"), pt.Int(0)) diff --git a/pyteal/ir/ops.py b/pyteal/ir/ops.py index 3a2c49f37..f3ffc1a44 100644 --- a/pyteal/ir/ops.py +++ b/pyteal/ir/ops.py @@ -181,6 +181,7 @@ def min_version(self) -> int: acct_params_get = OpType("acct_params_get", Mode.Application, 6) replace2 = OpType("replace2", Mode.Signature | Mode.Application, 7) replace3 = OpType("replace3", Mode.Signature | Mode.Application, 7) + json_ref = OpType("json_ref", Mode.Signature | Mode.Application, 7) block = OpType("block", Mode.Signature | Mode.Application, 7) # fmt: on From 839b9852521479a7a8be3e12de832c1ba4980258 Mon Sep 17 00:00:00 2001 From: Jacob Daitzman Date: Thu, 30 Jun 2022 13:47:58 -0400 Subject: [PATCH 006/157] Add Base64Decode (#418) * Add Base64Decode * Remove unnecessary ignore Expr equality context --- pyteal/__init__.pyi | 1 + pyteal/ast/__init__.py | 2 + pyteal/ast/base64decode.py | 85 +++++++++++++++++++++++++++++++++ pyteal/ast/base64decode_test.py | 57 ++++++++++++++++++++++ pyteal/ir/ops.py | 1 + 5 files changed, 146 insertions(+) create mode 100644 pyteal/ast/base64decode.py create mode 100644 pyteal/ast/base64decode_test.py diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index ec4af54a0..c4f1dd670 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -37,6 +37,7 @@ __all__ = [ "AssetHolding", "AssetParam", "Balance", + "Base64Decode", "BinaryExpr", "BitLen", "BitwiseAnd", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 919e8b6d6..f42ee4ec0 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -99,6 +99,7 @@ ExtractUint32, ExtractUint64, ) +from pyteal.ast.base64decode import Base64Decode # ternary ops from pyteal.ast.ternaryexpr import Divw, Ed25519Verify, SetBit, SetByte @@ -277,6 +278,7 @@ "ExtractUint32", "ExtractUint64", "Replace", + "Base64Decode", "Log", "While", "For", diff --git a/pyteal/ast/base64decode.py b/pyteal/ast/base64decode.py new file mode 100644 index 000000000..7dcf47c18 --- /dev/null +++ b/pyteal/ast/base64decode.py @@ -0,0 +1,85 @@ +from typing import TYPE_CHECKING +from enum import Enum + +from pyteal.types import TealType, require_type +from pyteal.errors import verifyFieldVersion +from pyteal.ir import TealOp, Op, TealBlock +from pyteal.ast.expr import Expr +from pyteal.ast.leafexpr import LeafExpr + +if TYPE_CHECKING: + from pyteal.compiler import CompileOptions + + +class Base64Encoding(Enum): + # fmt: off + # id | name | min version + url = (0, "URLEncoding", 7) + std = (1, "StdEncoding", 7) + # fmt: on + + def __init__(self, id: int, name: str, min_version: int) -> None: + self.id = id + self.arg_name = name + self.min_version = min_version + + +Base64Encoding.__module__ = "pyteal" + + +class Base64Decode(LeafExpr): + """An expression that decodes a base64-encoded byte string according to a specific encoding. + + See [RFC 4648](https://rfc-editor.org/rfc/rfc4648.html#section-4) (sections 4 and 5) for information on specifications. + + It is assumed that the encoding ends with the exact number of = padding characters as required by the RFC. + When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. + The special cases of \\n and \\r are allowed but completely ignored. An error will result when attempting + to decode a string with a character that is not in the encoding alphabet or not one of =, \\r, or \\n. + """ + + def __init__(self, encoding: Base64Encoding, base64: Expr) -> None: + super().__init__() + self.encoding = encoding + + require_type(base64, TealType.bytes) + self.base64 = base64 + + def __teal__(self, options: "CompileOptions"): + verifyFieldVersion( + self.encoding.arg_name, self.encoding.min_version, options.version + ) + + op = TealOp(self, Op.base64_decode, self.encoding.arg_name) + return TealBlock.FromOp(options, op, self.base64) + + def __str__(self): + return "(Base64Decode {})".format(self.encoding.arg_name) + + def type_of(self): + return TealType.bytes + + @classmethod + def url(cls, base64: Expr) -> "Base64Decode": + """Decode a base64-encoded byte string according to the URL encoding. + + Refer to the `Base64Decode` class documentation for more information. + + Args: + base64: A base64-encoded byte string. + """ + return cls(Base64Encoding.url, base64) + + @classmethod + def std(cls, base64: Expr) -> "Base64Decode": + """Decode a base64-encoded byte string according to the Standard encoding. + + Refer to the `Base64Decode` class documentation for more information. + + Args: + base64: A base64-encoded byte string. + """ + return cls(Base64Encoding.std, base64) + + +Base64Decode.__module__ = "pyteal" diff --git a/pyteal/ast/base64decode_test.py b/pyteal/ast/base64decode_test.py new file mode 100644 index 000000000..14eb48799 --- /dev/null +++ b/pyteal/ast/base64decode_test.py @@ -0,0 +1,57 @@ +import pytest + +import pyteal as pt + +teal6Options = pt.CompileOptions(version=6) +teal7Options = pt.CompileOptions(version=7) + + +def test_base64decode_std(): + arg = pt.Bytes("aGVsbG8gd29ybGQ=") + expr = pt.Base64Decode.std(arg) + assert expr.type_of() == pt.TealType.bytes + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(arg, pt.Op.byte, '"aGVsbG8gd29ybGQ="'), + pt.TealOp(expr, pt.Op.base64_decode, "StdEncoding"), + ] + ) + + actual, _ = expr.__teal__(teal7Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + with pytest.raises(pt.TealInputError): + expr.__teal__(teal6Options) + + +def test_base64decode_url(): + arg = pt.Bytes("aGVsbG8gd29ybGQ") + expr = pt.Base64Decode.url(arg) + assert expr.type_of() == pt.TealType.bytes + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(arg, pt.Op.byte, '"aGVsbG8gd29ybGQ"'), + pt.TealOp(expr, pt.Op.base64_decode, "URLEncoding"), + ] + ) + + actual, _ = expr.__teal__(teal7Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + with pytest.raises(pt.TealInputError): + expr.__teal__(teal6Options) + + +def test_base64decode_invalid(): + with pytest.raises(pt.TealTypeError): + pt.Base64Decode.std(pt.Int(0)) + with pytest.raises(pt.TealTypeError): + pt.Base64Decode.url(pt.Int(0)) diff --git a/pyteal/ir/ops.py b/pyteal/ir/ops.py index f3ffc1a44..a21e34bc4 100644 --- a/pyteal/ir/ops.py +++ b/pyteal/ir/ops.py @@ -181,6 +181,7 @@ def min_version(self) -> int: acct_params_get = OpType("acct_params_get", Mode.Application, 6) replace2 = OpType("replace2", Mode.Signature | Mode.Application, 7) replace3 = OpType("replace3", Mode.Signature | Mode.Application, 7) + base64_decode = OpType("base64_decode", Mode.Application | Mode.Signature, 7) json_ref = OpType("json_ref", Mode.Signature | Mode.Application, 7) block = OpType("block", Mode.Signature | Mode.Application, 7) # fmt: on From 7cccdcb9b9ab14b7539e349e1fa3b2ba9ea18ab0 Mon Sep 17 00:00:00 2001 From: Jacob Daitzman Date: Thu, 30 Jun 2022 14:00:06 -0400 Subject: [PATCH 007/157] Support Secp256r1 curve (#423) * Support Secp256r1 curve * Fix type errors in ecdsa tests * Fix typo * Test Secp256k1 curve against TEAL 5 instead * Add compile check to `MultiValue` class * Use `MultiValue` compile checks instead of inheritance --- pyteal/ast/ecdsa.py | 18 +++-- pyteal/ast/ecdsa_test.py | 162 +++++++++++++++++++++++++++------------ pyteal/ast/multi.py | 6 +- pyteal/ast/multi_test.py | 102 ++++++++++++++---------- 4 files changed, 191 insertions(+), 97 deletions(-) diff --git a/pyteal/ast/ecdsa.py b/pyteal/ast/ecdsa.py index b85acf2c1..06e4e49db 100644 --- a/pyteal/ast/ecdsa.py +++ b/pyteal/ast/ecdsa.py @@ -2,7 +2,7 @@ from typing import Tuple, TYPE_CHECKING from pyteal.ast import Expr, MultiValue -from pyteal.errors import TealTypeError, verifyTealVersion +from pyteal.errors import TealTypeError, verifyFieldVersion, verifyTealVersion from pyteal.ir import Op, TealBlock, TealOp from pyteal.types import TealType, require_type @@ -17,6 +17,7 @@ class EcdsaCurve(Enum): """Enum representing an elliptic curve specification used in ECDSA.""" Secp256k1 = (0, "Secp256k1", 5) + Secp256r1 = (1, "Secp256r1", 7) def __init__(self, id: int, name: str, min_version: int) -> None: self.id = id @@ -52,11 +53,13 @@ def __init__( def __teal__(self, options: "CompileOptions"): verifyTealVersion( - max(self.op.min_version, self.curve.min_version), + self.op.min_version, options.version, "TEAL version too low to use op {}".format(self.op), ) + verifyFieldVersion(self.curve.arg_name, self.curve.min_version, options.version) + return TealBlock.FromOp( options, TealOp(self, self.op, self.curve.arg_name), *self.args ) @@ -113,11 +116,9 @@ def EcdsaVerify( def EcdsaDecompress(curve: EcdsaCurve, compressed_pk: Expr) -> MultiValue: """Decompress an ECDSA public key. - Args: curve: Enum representing the ECDSA curve used for the public key compressed_pk: The compressed public key. Must be 33 bytes long and big endian encoded. - Returns: A MultiValue expression representing the two components of the public key, big endian encoded. @@ -132,6 +133,9 @@ def EcdsaDecompress(curve: EcdsaCurve, compressed_pk: Expr) -> MultiValue: EcdsaPubkey, immediate_args=[curve.arg_name], args=[compressed_pk], + compile_check=lambda options: verifyFieldVersion( + curve.arg_name, curve.min_version, options.version + ), ) @@ -139,16 +143,13 @@ def EcdsaRecover( curve: EcdsaCurve, data: Expr, recovery_id: Expr, sigA: Expr, sigB: Expr ) -> MultiValue: """Reover an ECDSA public key from a signature. - All byte arguments must be big endian encoded. - Args: curve: Enum representing the ECDSA curve used for the public key data: Hash value of the signed data. Must be 32 bytes long. recovery_id: value used to extract public key from signature. Must evaluate to uint. sigA: First component of the signature. Must evaluate to bytes. sigB: Second component of the signature. Must evaluate to bytes. - Returns: A MultiValue expression representing the two components of the public key, big endian encoded. @@ -166,4 +167,7 @@ def EcdsaRecover( EcdsaPubkey, immediate_args=[curve.arg_name], args=[data, recovery_id, sigA, sigB], + compile_check=lambda options: verifyFieldVersion( + curve.arg_name, curve.min_version, options.version + ), ) diff --git a/pyteal/ast/ecdsa_test.py b/pyteal/ast/ecdsa_test.py index 681755a65..03cec2207 100644 --- a/pyteal/ast/ecdsa_test.py +++ b/pyteal/ast/ecdsa_test.py @@ -1,22 +1,28 @@ import pytest +from typing import Union, List, cast import pyteal as pt teal4Options = pt.CompileOptions(version=4) teal5Options = pt.CompileOptions(version=5) +teal7Options = pt.CompileOptions(version=7) +curve_options_map = { + pt.EcdsaCurve.Secp256k1: teal5Options, + pt.EcdsaCurve.Secp256r1: teal7Options, +} -def test_ecdsa_decompress(): + +@pytest.mark.parametrize("curve", [pt.EcdsaCurve.Secp256k1, pt.EcdsaCurve.Secp256r1]) +def test_ecdsa_decompress(curve: pt.EcdsaCurve): compressed_pubkey = pt.Bytes("XY") - pubkey = pt.EcdsaDecompress(pt.EcdsaCurve.Secp256k1, compressed_pubkey) + pubkey = pt.EcdsaDecompress(curve, compressed_pubkey) assert pubkey.type_of() == pt.TealType.none expected = pt.TealSimpleBlock( [ pt.TealOp(compressed_pubkey, pt.Op.byte, '"XY"'), - pt.TealOp( - pubkey, pt.Op.ecdsa_pk_decompress, pt.EcdsaCurve.Secp256k1.arg_name - ), + pt.TealOp(pubkey, pt.Op.ecdsa_pk_decompress, curve.arg_name), pt.TealOp( pubkey.output_slots[1].store(), pt.Op.store, pubkey.output_slots[1] ), @@ -26,7 +32,7 @@ def test_ecdsa_decompress(): ] ) - actual, _ = pubkey.__teal__(teal5Options) + actual, _ = pubkey.__teal__(curve_options_map[curve]) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -34,14 +40,22 @@ def test_ecdsa_decompress(): assert actual == expected # compile without errors this is necessary so assembly is also tested - pt.compileTeal(pt.Seq(pubkey, pt.Approve()), pt.Mode.Application, version=5) + pt.compileTeal( + pt.Seq(pubkey, pt.Approve()), pt.Mode.Application, version=curve.min_version + ) + with pytest.raises(pt.TealInputError): + pt.compileTeal( + pt.Seq(pubkey, pt.Approve()), + pt.Mode.Application, + version=curve.min_version - 1, + ) -def test_ecdsa_recover(): + +@pytest.mark.parametrize("curve", [pt.EcdsaCurve.Secp256k1, pt.EcdsaCurve.Secp256r1]) +def test_ecdsa_recover(curve: pt.EcdsaCurve): args = [pt.Bytes("data"), pt.Int(1), pt.Bytes("sigA"), pt.Bytes("sigB")] - pubkey = pt.EcdsaRecover( - pt.EcdsaCurve.Secp256k1, args[0], args[1], args[2], args[3] - ) + pubkey = pt.EcdsaRecover(curve, args[0], args[1], args[2], args[3]) assert pubkey.type_of() == pt.TealType.none expected = pt.TealSimpleBlock( @@ -50,7 +64,7 @@ def test_ecdsa_recover(): pt.TealOp(args[1], pt.Op.int, 1), pt.TealOp(args[2], pt.Op.byte, '"sigA"'), pt.TealOp(args[3], pt.Op.byte, '"sigB"'), - pt.TealOp(pubkey, pt.Op.ecdsa_pk_recover, pt.EcdsaCurve.Secp256k1.arg_name), + pt.TealOp(pubkey, pt.Op.ecdsa_pk_recover, curve.arg_name), pt.TealOp( pubkey.output_slots[1].store(), pt.Op.store, pubkey.output_slots[1] ), @@ -60,7 +74,7 @@ def test_ecdsa_recover(): ] ) - actual, _ = pubkey.__teal__(teal5Options) + actual, _ = pubkey.__teal__(curve_options_map[curve]) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -68,13 +82,23 @@ def test_ecdsa_recover(): assert actual == expected # compile without errors this is necessary so assembly is also tested - pt.compileTeal(pt.Seq(pubkey, pt.Approve()), pt.Mode.Application, version=5) + pt.compileTeal( + pt.Seq(pubkey, pt.Approve()), pt.Mode.Application, version=curve.min_version + ) + + with pytest.raises(pt.TealInputError): + pt.compileTeal( + pt.Seq(pubkey, pt.Approve()), + pt.Mode.Application, + version=curve.min_version - 1, + ) -def test_ecdsa_verify_basic(): +@pytest.mark.parametrize("curve", [pt.EcdsaCurve.Secp256k1, pt.EcdsaCurve.Secp256r1]) +def test_ecdsa_verify_basic(curve: pt.EcdsaCurve): args = [pt.Bytes("data"), pt.Bytes("sigA"), pt.Bytes("sigB")] pubkey = (pt.Bytes("X"), pt.Bytes("Y")) - expr = pt.EcdsaVerify(pt.EcdsaCurve.Secp256k1, args[0], args[1], args[2], pubkey) + expr = pt.EcdsaVerify(curve, args[0], args[1], args[2], pubkey) assert expr.type_of() == pt.TealType.uint64 expected = pt.TealSimpleBlock( @@ -84,33 +108,43 @@ def test_ecdsa_verify_basic(): pt.TealOp(args[2], pt.Op.byte, '"sigB"'), pt.TealOp(pubkey[0], pt.Op.byte, '"X"'), pt.TealOp(pubkey[1], pt.Op.byte, '"Y"'), - pt.TealOp(expr, pt.Op.ecdsa_verify, pt.EcdsaCurve.Secp256k1.arg_name), + pt.TealOp(expr, pt.Op.ecdsa_verify, curve.arg_name), ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(curve_options_map[curve]) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected # compile without errors this is necessary so assembly is also tested - pt.compileTeal(pt.Seq(pt.Pop(expr), pt.Approve()), pt.Mode.Application, version=5) + pt.compileTeal( + pt.Seq(pt.Pop(expr), pt.Approve()), + pt.Mode.Application, + version=curve.min_version, + ) + + with pytest.raises(pt.TealInputError): + pt.compileTeal( + pt.Seq(pt.Pop(expr), pt.Approve()), + pt.Mode.Application, + version=curve.min_version - 1, + ) -def test_ecdsa_verify_compressed_pk(): +@pytest.mark.parametrize("curve", [pt.EcdsaCurve.Secp256k1, pt.EcdsaCurve.Secp256r1]) +def test_ecdsa_verify_compressed_pk(curve: pt.EcdsaCurve): args = [pt.Bytes("data"), pt.Bytes("sigA"), pt.Bytes("sigB")] compressed_pubkey = pt.Bytes("XY") - pubkey = pt.EcdsaDecompress(pt.EcdsaCurve.Secp256k1, compressed_pubkey) - expr = pt.EcdsaVerify(pt.EcdsaCurve.Secp256k1, args[0], args[1], args[2], pubkey) + pubkey = pt.EcdsaDecompress(curve, compressed_pubkey) + expr = pt.EcdsaVerify(curve, args[0], args[1], args[2], pubkey) assert expr.type_of() == pt.TealType.uint64 expected = pt.TealSimpleBlock( [ pt.TealOp(compressed_pubkey, pt.Op.byte, '"XY"'), - pt.TealOp( - pubkey, pt.Op.ecdsa_pk_decompress, pt.EcdsaCurve.Secp256k1.arg_name - ), + pt.TealOp(pubkey, pt.Op.ecdsa_pk_decompress, curve.arg_name), pt.TealOp( pubkey.output_slots[1].store(), pt.Op.store, pubkey.output_slots[1] ), @@ -126,11 +160,11 @@ def test_ecdsa_verify_compressed_pk(): pt.TealOp( pubkey.output_slots[1].load(), pt.Op.load, pubkey.output_slots[1] ), - pt.TealOp(expr, pt.Op.ecdsa_verify, pt.EcdsaCurve.Secp256k1.arg_name), + pt.TealOp(expr, pt.Op.ecdsa_verify, curve.arg_name), ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(curve_options_map[curve]) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -138,15 +172,25 @@ def test_ecdsa_verify_compressed_pk(): assert actual == expected # compile without errors this is necessary so assembly is also tested - pt.compileTeal(pt.Seq(pt.Pop(expr), pt.Approve()), pt.Mode.Application, version=5) + pt.compileTeal( + pt.Seq(pt.Pop(expr), pt.Approve()), + pt.Mode.Application, + version=curve.min_version, + ) + with pytest.raises(pt.TealInputError): + pt.compileTeal( + pt.Seq(pt.Pop(expr), pt.Approve()), + pt.Mode.Application, + version=curve.min_version - 1, + ) -def test_ecdsa_verify_recovered_pk(): + +@pytest.mark.parametrize("curve", [pt.EcdsaCurve.Secp256k1, pt.EcdsaCurve.Secp256r1]) +def test_ecdsa_verify_recovered_pk(curve: pt.EcdsaCurve): args = [pt.Bytes("data"), pt.Int(1), pt.Bytes("sigA"), pt.Bytes("sigB")] - pubkey = pt.EcdsaRecover( - pt.EcdsaCurve.Secp256k1, args[0], args[1], args[2], args[3] - ) - expr = pt.EcdsaVerify(pt.EcdsaCurve.Secp256k1, args[0], args[2], args[3], pubkey) + pubkey = pt.EcdsaRecover(curve, args[0], args[1], args[2], args[3]) + expr = pt.EcdsaVerify(curve, args[0], args[2], args[3], pubkey) assert expr.type_of() == pt.TealType.uint64 expected = pt.TealSimpleBlock( @@ -155,7 +199,7 @@ def test_ecdsa_verify_recovered_pk(): pt.TealOp(args[1], pt.Op.int, 1), pt.TealOp(args[2], pt.Op.byte, '"sigA"'), pt.TealOp(args[3], pt.Op.byte, '"sigB"'), - pt.TealOp(pubkey, pt.Op.ecdsa_pk_recover, pt.EcdsaCurve.Secp256k1.arg_name), + pt.TealOp(pubkey, pt.Op.ecdsa_pk_recover, curve.arg_name), pt.TealOp( pubkey.output_slots[1].store(), pt.Op.store, pubkey.output_slots[1] ), @@ -171,11 +215,11 @@ def test_ecdsa_verify_recovered_pk(): pt.TealOp( pubkey.output_slots[1].load(), pt.Op.load, pubkey.output_slots[1] ), - pt.TealOp(expr, pt.Op.ecdsa_verify, pt.EcdsaCurve.Secp256k1.arg_name), + pt.TealOp(expr, pt.Op.ecdsa_verify, curve.arg_name), ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(curve_options_map[curve]) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -183,26 +227,46 @@ def test_ecdsa_verify_recovered_pk(): assert actual == expected # compile without errors this is necessary so assembly is also tested - pt.compileTeal(pt.Seq(pt.Pop(expr), pt.Approve()), pt.Mode.Application, version=5) + pt.compileTeal( + pt.Seq(pt.Pop(expr), pt.Approve()), + pt.Mode.Application, + version=curve.min_version, + ) + + with pytest.raises(pt.TealInputError): + pt.compileTeal( + pt.Seq(pt.Pop(expr), pt.Approve()), + pt.Mode.Application, + version=curve.min_version - 1, + ) -def test_ecdsa_invalid(): +@pytest.mark.parametrize("curve", [pt.EcdsaCurve.Secp256k1, pt.EcdsaCurve.Secp256r1]) +def test_ecdsa_invalid(curve: pt.EcdsaCurve): with pytest.raises(pt.TealTypeError): - args = [pt.Bytes("data"), pt.Bytes("1"), pt.Bytes("sigA"), pt.Bytes("sigB")] - pt.EcdsaRecover(pt.EcdsaCurve.Secp256k1, args[0], args[1], args[2], args[3]) + args: List[Union[pt.Bytes, pt.Int]] = [ + pt.Bytes("data"), + pt.Bytes("1"), + pt.Bytes("sigA"), + pt.Bytes("sigB"), + ] + pt.EcdsaRecover(curve, args[0], args[1], args[2], args[3]) with pytest.raises(pt.TealTypeError): - pt.EcdsaDecompress(pt.EcdsaCurve.Secp256k1, pt.Int(1)) + pt.EcdsaDecompress(curve, pt.Int(1)) with pytest.raises(pt.TealTypeError): args = [pt.Bytes("data"), pt.Bytes("sigA"), pt.Bytes("sigB")] - pubkey = (pt.Bytes("X"), pt.Int(1)) - pt.EcdsaVerify(pt.EcdsaCurve.Secp256k1, args[0], args[1], args[2], pubkey) + pubkey: Union[tuple[pt.Bytes, Union[pt.Int, pt.Bytes]], pt.MultiValue] = ( + pt.Bytes("X"), + pt.Int(1), + ) + pt.EcdsaVerify(curve, args[0], args[1], args[2], pubkey) with pytest.raises(pt.TealTypeError): args = [pt.Bytes("data"), pt.Int(1), pt.Bytes("sigB")] pubkey = (pt.Bytes("X"), pt.Bytes("Y")) - pt.EcdsaVerify(pt.EcdsaCurve.Secp256k1, args[0], args[1], args[2], pubkey) + pt.EcdsaVerify(curve, args[0], args[1], args[2], pubkey) with pytest.raises(pt.TealTypeError): args = [pt.Bytes("data"), pt.Bytes("sigA"), pt.Bytes("sigB")] @@ -210,21 +274,19 @@ def test_ecdsa_invalid(): pubkey = pt.MultiValue( pt.Op.ecdsa_pk_decompress, [pt.TealType.uint64, pt.TealType.bytes], - immediate_args=[pt.EcdsaCurve.Secp256k1], + immediate_args=[curve.__str__()], args=[compressed_pk], ) - pt.EcdsaVerify(pt.EcdsaCurve.Secp256k1, args[0], args[1], args[2], pubkey) + pt.EcdsaVerify(curve, args[0], args[1], args[2], pubkey) with pytest.raises(pt.TealInputError): args = [pt.Bytes("data"), pt.Bytes("sigA"), pt.Bytes("sigB")] pubkey = (pt.Bytes("X"), pt.Bytes("Y")) - expr = pt.EcdsaVerify( - pt.EcdsaCurve.Secp256k1, args[0], args[1], args[2], pubkey - ) + expr = pt.EcdsaVerify(curve, args[0], args[1], args[2], pubkey) expr.__teal__(teal4Options) with pytest.raises(pt.TealTypeError): args = [pt.Bytes("data"), pt.Bytes("sigA"), pt.Bytes("sigB")] pubkey = (pt.Bytes("X"), pt.Bytes("Y")) - expr = pt.EcdsaVerify(5, args[0], args[1], args[2], pubkey) + expr = pt.EcdsaVerify(cast(pt.EcdsaCurve, 5), args[0], args[1], args[2], pubkey) diff --git a/pyteal/ast/multi.py b/pyteal/ast/multi.py index 63a4dec11..e61af4b4a 100644 --- a/pyteal/ast/multi.py +++ b/pyteal/ast/multi.py @@ -20,7 +20,8 @@ def __init__( types: List[TealType], *, immediate_args: List[Union[int, str]] = None, - args: List[Expr] = None + args: List[Expr] = None, + compile_check: Callable[["CompileOptions"], None] = lambda _: None, ): """Create a new MultiValue. @@ -35,6 +36,7 @@ def __init__( self.types = types self.immediate_args = immediate_args if immediate_args is not None else [] self.args = args if args is not None else [] + self.compile_check = compile_check self.output_slots = [ScratchSlot() for _ in self.types] @@ -57,6 +59,8 @@ def __str__(self): return ret_str def __teal__(self, options: "CompileOptions"): + self.compile_check(options) + tealOp = TealOp(self, self.op, *self.immediate_args) callStart, callEnd = TealBlock.FromOp(options, tealOp, *self.args) diff --git a/pyteal/ast/multi_test.py b/pyteal/ast/multi_test.py index e0fe3d58c..a85cebed7 100644 --- a/pyteal/ast/multi_test.py +++ b/pyteal/ast/multi_test.py @@ -1,3 +1,4 @@ +import pytest from typing import List import pyteal as pt @@ -147,47 +148,70 @@ def __test_single_with_vars( assert actual == expected -def test_multi_value(): - ops = ( +@pytest.mark.parametrize( + "op", + [ pt.Op.app_global_get_ex, pt.Op.app_local_get_ex, pt.Op.asset_holding_get, pt.Op.asset_params_get, + ], +) +@pytest.mark.parametrize( + "type", [pt.TealType.uint64, pt.TealType.bytes, pt.TealType.anytype] +) +@pytest.mark.parametrize("iargs", [[], ["AssetFrozen"]]) +@pytest.mark.parametrize("args", [[], [pt.Int(0)], [pt.Int(1), pt.Int(2)]]) +def test_multi_value(op, type, iargs, args): + reducer = ( + lambda value, hasValue: pt.If(hasValue) + .Then(value) + .Else(pt.App.globalGet(pt.Bytes("None"))) + ) + expr = pt.MultiValue( + op, [type, pt.TealType.uint64], immediate_args=iargs, args=args + ) + __test_single_conditional(expr, op, args, iargs, reducer) + + reducer = lambda value, hasValue: pt.Seq(pt.Assert(hasValue), value) # noqa: E731 + expr = pt.MultiValue( + op, [type, pt.TealType.uint64], immediate_args=iargs, args=args + ) + __test_single_assert(expr, op, args, iargs, reducer) + + hasValueVar = pt.ScratchVar(pt.TealType.uint64) + valueVar = pt.ScratchVar(type) + reducer = lambda value, hasValue: pt.Seq( # noqa: E731 + hasValueVar.store(hasValue), valueVar.store(value) + ) + expr = pt.MultiValue( + op, [type, pt.TealType.uint64], immediate_args=iargs, args=args + ) + __test_single_with_vars(expr, op, args, iargs, hasValueVar, valueVar, reducer) + + +def test_multi_compile_check(): + def never_fails(options): + return + + program_never_fails = pt.MultiValue( + pt.Op.app_global_get_ex, + [pt.TealType.uint64, pt.TealType.uint64], + compile_check=never_fails, ) - types = (pt.TealType.uint64, pt.TealType.bytes, pt.TealType.anytype) - immedate_argv = ([], ["AssetFrozen"]) - argv = ([], [pt.Int(0)], [pt.Int(1), pt.Int(2)]) - - for op in ops: - for type in types: - for iargs in immedate_argv: - for args in argv: - reducer = ( - lambda value, hasValue: pt.If(hasValue) - .Then(value) - .Else(pt.App.globalGet(pt.Bytes("None"))) - ) - expr = pt.MultiValue( - op, [type, pt.TealType.uint64], immediate_args=iargs, args=args - ) - __test_single_conditional(expr, op, args, iargs, reducer) - - reducer = lambda value, hasValue: pt.Seq( # noqa: E731 - pt.Assert(hasValue), value - ) - expr = pt.MultiValue( - op, [type, pt.TealType.uint64], immediate_args=iargs, args=args - ) - __test_single_assert(expr, op, args, iargs, reducer) - - hasValueVar = pt.ScratchVar(pt.TealType.uint64) - valueVar = pt.ScratchVar(type) - reducer = lambda value, hasValue: pt.Seq( # noqa: E731 - hasValueVar.store(hasValue), valueVar.store(value) - ) - expr = pt.MultiValue( - op, [type, pt.TealType.uint64], immediate_args=iargs, args=args - ) - __test_single_with_vars( - expr, op, args, iargs, hasValueVar, valueVar, reducer - ) + program_never_fails.__teal__(options) + + class TestException(Exception): + pass + + def always_fails(options): + raise TestException() + + program_always_fails = pt.MultiValue( + pt.Op.app_global_get_ex, + [pt.TealType.uint64, pt.TealType.uint64], + compile_check=always_fails, + ) + + with pytest.raises(TestException): + program_always_fails.__teal__(options) From 9a26fec4602d8f7ac1c9309ac148e6d43aa363e8 Mon Sep 17 00:00:00 2001 From: Jacob Daitzman Date: Thu, 30 Jun 2022 14:12:21 -0400 Subject: [PATCH 008/157] Add VrfVerify (#419) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add VrfVerify # Conflicts: # pyteal/ast/__init__.py # pyteal/ir/ops.py * Tidy with `MultiValue`’s compile check --- pyteal/__init__.pyi | 1 + pyteal/ast/__init__.py | 4 ++ pyteal/ast/vrfverify.py | 80 ++++++++++++++++++++++++++++++++++++ pyteal/ast/vrfverify_test.py | 71 ++++++++++++++++++++++++++++++++ pyteal/ir/ops.py | 1 + 5 files changed, 157 insertions(+) create mode 100644 pyteal/ast/vrfverify.py create mode 100644 pyteal/ast/vrfverify_test.py diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index c4f1dd670..4008461a8 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -185,6 +185,7 @@ __all__ = [ "TxnType", "TxnaExpr", "UnaryExpr", + "VrfVerify", "While", "WideRatio", "compileTeal", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index f42ee4ec0..6cce690a2 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -107,6 +107,9 @@ from pyteal.ast.replace import Replace from pyteal.ast.jsonref import JsonRef +# quaternary ops +from pyteal.ast.vrfverify import VrfVerify + # more ops from pyteal.ast.naryexpr import NaryExpr, And, Or, Concat from pyteal.ast.widemath import WideRatio @@ -289,4 +292,5 @@ "EcdsaDecompress", "EcdsaRecover", "JsonRef", + "VrfVerify", ] diff --git a/pyteal/ast/vrfverify.py b/pyteal/ast/vrfverify.py new file mode 100644 index 000000000..110671c7f --- /dev/null +++ b/pyteal/ast/vrfverify.py @@ -0,0 +1,80 @@ +from enum import Enum + +from pyteal.types import TealType, require_type +from pyteal.errors import verifyFieldVersion +from pyteal.ir import Op +from pyteal.ast.multi import MultiValue +from pyteal.ast.expr import Expr + + +class VrfVerifyStandard(Enum): + # fmt: off + # id | name | min version + algorand = (0, "VrfAlgorand", 7) # noqa: E222 + chainlink = (1, "VrfChainlink", 7) + # fmt: on + + def __init__(self, id: int, name: str, min_version: int) -> None: + self.id = id + self.arg_name = name + self.min_version = min_version + + +VrfVerifyStandard.__module__ = "pyteal" + + +class VrfVerify(MultiValue): + """An expression that verifies the proof of a message against a public key.""" + + def __init__( + self, standard: VrfVerifyStandard, message: Expr, proof: Expr, public_key: Expr + ) -> None: + require_type(message, TealType.bytes) + require_type(proof, TealType.bytes) + require_type(public_key, TealType.bytes) + + self.standard = standard + + super().__init__( + Op.vrf_verify, + [TealType.bytes, TealType.uint64], + immediate_args=[standard.arg_name], + args=[message, proof, public_key], + compile_check=lambda options: verifyFieldVersion( + standard.arg_name, standard.min_version, options.version + ), + ) + + def __str__(self): + return "(VrfVerify {})".format(self.standard.arg_name) + + @classmethod + def algorand(cls, message: Expr, proof: Expr, public_key: Expr) -> "VrfVerify": + """Verifies the proof of a message against a public key using the Algorand VRF standard. + + Args: + message: The message to verify. + proof: The proof of the message. + public_key: The public key to use to verify the proof. + + Returns: + A MultiValue expression representing the VRF output and a verification flag. + """ + return cls(VrfVerifyStandard.algorand, message, proof, public_key) + + @classmethod + def chainlink(cls, message: Expr, proof: Expr, public_key: Expr) -> "VrfVerify": + """Verifies the proof of a message against a public key using the Chainlink VRF standard. + + Args: + message: The message to verify. + proof: The proof of the message. + public_key: The public key to use to verify the proof. + + Returns: + A MultiValue expression representing the VRF output and a verification flag. + """ + return cls(VrfVerifyStandard.chainlink, message, proof, public_key) + + +VrfVerify.__module__ = "pyteal" diff --git a/pyteal/ast/vrfverify_test.py b/pyteal/ast/vrfverify_test.py new file mode 100644 index 000000000..8380d053c --- /dev/null +++ b/pyteal/ast/vrfverify_test.py @@ -0,0 +1,71 @@ +import pytest + +import pyteal as pt + +teal6Options = pt.CompileOptions(version=6) +teal7Options = pt.CompileOptions(version=7) + + +def test_vrf_verify_algorand(): + args = [pt.Bytes("a"), pt.Bytes("b"), pt.Bytes("c")] + expr = pt.VrfVerify.algorand(*args) + assert expr.type_of() == pt.TealType.none + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(args[0], pt.Op.byte, '"a"'), + pt.TealOp(args[1], pt.Op.byte, '"b"'), + pt.TealOp(args[2], pt.Op.byte, '"c"'), + pt.TealOp(expr, pt.Op.vrf_verify, "VrfAlgorand"), + pt.TealOp(expr.output_slots[1], pt.Op.store, expr.output_slots[1]), + pt.TealOp(expr.output_slots[0], pt.Op.store, expr.output_slots[0]), + ] + ) + + actual, _ = expr.__teal__(teal7Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + with pt.TealComponent.Context.ignoreExprEquality(): + assert actual == expected + + with pytest.raises(pt.TealInputError): + expr.__teal__(teal6Options) + + +def test_vrf_verify_chainlink(): + args = [pt.Bytes("a"), pt.Bytes("b"), pt.Bytes("c")] + expr = pt.VrfVerify.chainlink(*args) + assert expr.type_of() == pt.TealType.none + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(args[0], pt.Op.byte, '"a"'), + pt.TealOp(args[1], pt.Op.byte, '"b"'), + pt.TealOp(args[2], pt.Op.byte, '"c"'), + pt.TealOp(expr, pt.Op.vrf_verify, "VrfChainlink"), + pt.TealOp(expr.output_slots[1], pt.Op.store, expr.output_slots[1]), + pt.TealOp(expr.output_slots[0], pt.Op.store, expr.output_slots[0]), + ] + ) + + actual, _ = expr.__teal__(teal7Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + with pt.TealComponent.Context.ignoreExprEquality(): + assert actual == expected + + with pytest.raises(pt.TealInputError): + expr.__teal__(teal6Options) + + +def test_vrf_verify_invalid(): + with pytest.raises(pt.TealTypeError): + pt.VrfVerify.algorand(pt.Int(0), pt.Bytes("b"), pt.Bytes("c")) + + with pytest.raises(pt.TealTypeError): + pt.VrfVerify.chainlink(pt.Bytes("a"), pt.Int(0), pt.Bytes("c")) + + with pytest.raises(pt.TealTypeError): + pt.VrfVerify.chainlink(pt.Bytes("a"), pt.Bytes("b"), pt.Int(0)) diff --git a/pyteal/ir/ops.py b/pyteal/ir/ops.py index a21e34bc4..50563da94 100644 --- a/pyteal/ir/ops.py +++ b/pyteal/ir/ops.py @@ -183,6 +183,7 @@ def min_version(self) -> int: replace3 = OpType("replace3", Mode.Signature | Mode.Application, 7) base64_decode = OpType("base64_decode", Mode.Application | Mode.Signature, 7) json_ref = OpType("json_ref", Mode.Signature | Mode.Application, 7) + vrf_verify = OpType("vrf_verify", Mode.Signature | Mode.Application, 7) block = OpType("block", Mode.Signature | Mode.Application, 7) # fmt: on From cc544aae783b466450dae5aed5456920bba2526b Mon Sep 17 00:00:00 2001 From: Jacob Daitzman Date: Thu, 30 Jun 2022 14:23:33 -0400 Subject: [PATCH 009/157] Add `Sha3_256` (#425) * Add sha3_256 * Add crypto docs --- docs/crypto.rst | 1 + pyteal/__init__.pyi | 1 + pyteal/ast/__init__.py | 2 ++ pyteal/ast/unaryexpr.py | 5 +++++ pyteal/ast/unaryexpr_test.py | 22 ++++++++++++++++++++++ pyteal/ir/ops.py | 1 + 6 files changed, 32 insertions(+) diff --git a/docs/crypto.rst b/docs/crypto.rst index d062eb671..2ae4055b1 100644 --- a/docs/crypto.rst +++ b/docs/crypto.rst @@ -14,6 +14,7 @@ Below is how you express cryptographic primitives in PyTeal: Operator Cost Description ==================================== ========= ================================================================================================================== :code:`Sha256(e)` `35` `SHA-256` hash function, produces 32 bytes +:code:`Sha3_256(e)` `130` `SHA3-256` hash function, produces 32 bytes :code:`Keccak256(e)` `130` `Keccak-256` hash funciton, produces 32 bytes :code:`Sha512_256(e)` `45` `SHA-512/256` hash function, produces 32 bytes :code:`Ed25519Verify(d, s, p)` `1900`\* `1` if :code:`s` is the signature of :code:`d` signed by the private key corresponding to the public key :code:`p`, else `0` diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 4008461a8..79545ec99 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -153,6 +153,7 @@ __all__ = [ "SetBit", "SetByte", "Sha256", + "Sha3_256", "Sha512_256", "ShiftLeft", "ShiftRight", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 6cce690a2..61d3254d3 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -46,6 +46,7 @@ BitLen, Sha256, Sha512_256, + Sha3_256, Keccak256, Not, BitwiseNot, @@ -197,6 +198,7 @@ "BitLen", "Sha256", "Sha512_256", + "Sha3_256", "Keccak256", "Not", "BitwiseNot", diff --git a/pyteal/ast/unaryexpr.py b/pyteal/ast/unaryexpr.py index 619bfab46..1fad9903b 100644 --- a/pyteal/ast/unaryexpr.py +++ b/pyteal/ast/unaryexpr.py @@ -80,6 +80,11 @@ def Sha512_256(arg: Expr) -> UnaryExpr: return UnaryExpr(Op.sha512_256, TealType.bytes, TealType.bytes, arg) +def Sha3_256(arg: Expr) -> UnaryExpr: + """Get the SHA3-256 hash of a byte string.""" + return UnaryExpr(Op.sha3_256, TealType.bytes, TealType.bytes, arg) + + def Keccak256(arg: Expr) -> UnaryExpr: """Get the KECCAK-256 hash of a byte string.""" return UnaryExpr(Op.keccak256, TealType.bytes, TealType.bytes, arg) diff --git a/pyteal/ast/unaryexpr_test.py b/pyteal/ast/unaryexpr_test.py index 50a6e2f15..5a096fcbd 100644 --- a/pyteal/ast/unaryexpr_test.py +++ b/pyteal/ast/unaryexpr_test.py @@ -7,6 +7,7 @@ teal4Options = pt.CompileOptions(version=4) teal5Options = pt.CompileOptions(version=5) teal6Options = pt.CompileOptions(version=6) +teal7Options = pt.CompileOptions(version=7) def test_btoi(): @@ -146,6 +147,27 @@ def test_sha512_256_invalid(): pt.Sha512_256(pt.Int(1)) +def test_sha3_256(): + arg = pt.Arg(0) + expr = pt.Sha3_256(arg) + assert expr.type_of() == pt.TealType.bytes + + expected = pt.TealSimpleBlock( + [pt.TealOp(arg, pt.Op.arg, 0), pt.TealOp(expr, pt.Op.sha3_256)] + ) + + actual, _ = expr.__teal__(teal7Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + +def test_sha3_256_invalid(): + with pytest.raises(pt.TealTypeError): + pt.Sha3_256(pt.Int(1)) + + def test_keccak256(): arg = pt.Arg(0) expr = pt.Keccak256(arg) diff --git a/pyteal/ir/ops.py b/pyteal/ir/ops.py index 50563da94..4a040cac0 100644 --- a/pyteal/ir/ops.py +++ b/pyteal/ir/ops.py @@ -183,6 +183,7 @@ def min_version(self) -> int: replace3 = OpType("replace3", Mode.Signature | Mode.Application, 7) base64_decode = OpType("base64_decode", Mode.Application | Mode.Signature, 7) json_ref = OpType("json_ref", Mode.Signature | Mode.Application, 7) + sha3_256 = OpType("sha3_256", Mode.Signature | Mode.Application, 7) vrf_verify = OpType("vrf_verify", Mode.Signature | Mode.Application, 7) block = OpType("block", Mode.Signature | Mode.Application, 7) # fmt: on From 6e83ae65261dd3d33ea0d11a1c3d6876aaf58a1e Mon Sep 17 00:00:00 2001 From: Jacob Daitzman Date: Thu, 30 Jun 2022 14:24:11 -0400 Subject: [PATCH 010/157] Support `FirstValidTime` transaction field (#424) * Add first valid time factory and update min version * Include FirstValidTime in txn tests * Add transaction field docs --- docs/accessing_transaction_field.rst | 1 + pyteal/ast/txn.py | 9 ++++++++- pyteal/ast/txn_test.py | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/accessing_transaction_field.rst b/docs/accessing_transaction_field.rst index ea37663e5..64c5f0b65 100644 --- a/docs/accessing_transaction_field.rst +++ b/docs/accessing_transaction_field.rst @@ -27,6 +27,7 @@ Operator :any:`Txn.sender() ` :code:`TealType.bytes` 2 32 byte address :any:`Txn.fee() ` :code:`TealType.uint64` 2 in microAlgos :any:`Txn.first_valid() ` :code:`TealType.uint64` 2 round number +:any:`Txn.first_valid_time() ` :code:`TealType.uint64` 7 UNIX timestamp of block before :code:`Txn.first_valid()`. Fails if negative :any:`Txn.last_valid() ` :code:`TealType.uint64` 2 round number :any:`Txn.note() ` :code:`TealType.bytes` 2 transaction note in bytes :any:`Txn.lease() ` :code:`TealType.bytes` 2 transaction lease in bytes diff --git a/pyteal/ast/txn.py b/pyteal/ast/txn.py index 3c0fc0f4e..a4d011ddf 100644 --- a/pyteal/ast/txn.py +++ b/pyteal/ast/txn.py @@ -37,7 +37,7 @@ class TxnField(Enum): sender = (0, "Sender", TealType.bytes, False, 2) fee = (1, "Fee", TealType.uint64, False, 2) first_valid = (2, "FirstValid", TealType.uint64, False, 2) - first_valid_time = (3, "FirstValidTime", TealType.uint64, False, 2) + first_valid_time = (3, "FirstValidTime", TealType.uint64, False, 7) last_valid = (4, "LastValid", TealType.uint64, False, 2) note = (5, "Note", TealType.bytes, False, 2) lease = (6, "Lease", TealType.bytes, False, 2) @@ -319,6 +319,13 @@ def first_valid(self) -> TxnExpr: """ return self.makeTxnExpr(TxnField.first_valid) + def first_valid_time(self) -> TxnExpr: + """Get the UNIX timestamp of block before txn.FirstValid. Fails if negative. + + For more information, see https://developer.algorand.org/docs/reference/transactions/#firstvalidtime + """ + return self.makeTxnExpr(TxnField.first_valid_time) + def last_valid(self) -> TxnExpr: """Get the last valid round number. diff --git a/pyteal/ast/txn_test.py b/pyteal/ast/txn_test.py index c0477fd23..d169b459b 100644 --- a/pyteal/ast/txn_test.py +++ b/pyteal/ast/txn_test.py @@ -8,6 +8,7 @@ pt.TxnField.sender: lambda txn: txn.sender(), pt.TxnField.fee: lambda txn: txn.fee(), pt.TxnField.first_valid: lambda txn: txn.first_valid(), + pt.TxnField.first_valid_time: lambda txn: txn.first_valid_time(), pt.TxnField.last_valid: lambda txn: txn.last_valid(), pt.TxnField.note: lambda txn: txn.note(), pt.TxnField.lease: lambda txn: txn.lease(), From 594e8e42349219f70d6804bbed7f31fbf267802c Mon Sep 17 00:00:00 2001 From: Jacob Daitzman Date: Thu, 30 Jun 2022 14:41:49 -0400 Subject: [PATCH 011/157] Add `Ed25519Verify_Bare` (#426) * Add ed25519verify_bare * Fix typos in Ed25519 docstrings (#2) * Add crypto doc for Ed25519Verify_Bare Co-authored-by: Michael Diamant --- docs/crypto.rst | 3 ++- pyteal/__init__.pyi | 1 + pyteal/ast/__init__.py | 9 ++++++++- pyteal/ast/ternaryexpr.py | 22 +++++++++++++++++++-- pyteal/ast/ternaryexpr_test.py | 36 ++++++++++++++++++++++++++++++++++ pyteal/ir/ops.py | 1 + 6 files changed, 68 insertions(+), 4 deletions(-) diff --git a/docs/crypto.rst b/docs/crypto.rst index 2ae4055b1..6a80b2567 100644 --- a/docs/crypto.rst +++ b/docs/crypto.rst @@ -17,7 +17,8 @@ Operator Cost Description :code:`Sha3_256(e)` `130` `SHA3-256` hash function, produces 32 bytes :code:`Keccak256(e)` `130` `Keccak-256` hash funciton, produces 32 bytes :code:`Sha512_256(e)` `45` `SHA-512/256` hash function, produces 32 bytes -:code:`Ed25519Verify(d, s, p)` `1900`\* `1` if :code:`s` is the signature of :code:`d` signed by the private key corresponding to the public key :code:`p`, else `0` +:code:`Ed25519Verify(d, s, p)` `1900`\* `1` if :code:`s` is the signature of the concatenation :code:`("ProgData" + hash_of_current_program + d)` signed by the private key corresponding to the public key :code:`p`, else `0` +:code:`Ed25519Verify_Bare(d, s, p)` `1900` `1` if :code:`s` is the signature of :code:`d` signed by the private key corresponding to the public key :code:`p`, else `0` :code:`EcdsaVerify(c, d, r, s, pk)` `1700` `1` if :code:`(r, s)` is the signature of :code:`d` by private key corresponding to public key :code:`pk`, else 0 :code:`EcdsaDecompress(c, short_pk)` `650` produces the decompressed public key associated with the compressed public key :code:`short_pk` :code:`EcdsaRecover(c, d, id, r, s)` `2000` produces the public key associated with the signature :code:`(r, s)` and recovery id :code:`id` diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 79545ec99..4e2e3b65b 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -78,6 +78,7 @@ __all__ = [ "EcdsaRecover", "EcdsaVerify", "Ed25519Verify", + "Ed25519Verify_Bare", "EnumInt", "Eq", "Err", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 61d3254d3..145e7f2f3 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -103,7 +103,13 @@ from pyteal.ast.base64decode import Base64Decode # ternary ops -from pyteal.ast.ternaryexpr import Divw, Ed25519Verify, SetBit, SetByte +from pyteal.ast.ternaryexpr import ( + Divw, + Ed25519Verify, + Ed25519Verify_Bare, + SetBit, + SetByte, +) from pyteal.ast.substring import Substring, Extract, Suffix from pyteal.ast.replace import Replace from pyteal.ast.jsonref import JsonRef @@ -228,6 +234,7 @@ "GetBit", "GetByte", "Ed25519Verify", + "Ed25519Verify_Bare", "Substring", "Extract", "Suffix", diff --git a/pyteal/ast/ternaryexpr.py b/pyteal/ast/ternaryexpr.py index b329165de..ad2c36bd6 100644 --- a/pyteal/ast/ternaryexpr.py +++ b/pyteal/ast/ternaryexpr.py @@ -62,9 +62,9 @@ def Ed25519Verify(data: Expr, sig: Expr, key: Expr) -> TernaryExpr: """Verify the ed25519 signature of the concatenation ("ProgData" + hash_of_current_program + data). Args: - data: The data signed by the public key. Must evalutes to bytes. + data: The data signed by the public key. Must evaluate to bytes. sig: The proposed 64-byte signature of the concatenation ("ProgData" + hash_of_current_program + data). - Must evalute to bytes. + Must evaluate to bytes. key: The 32 byte public key that produced the signature. Must evaluate to bytes. """ return TernaryExpr( @@ -77,6 +77,24 @@ def Ed25519Verify(data: Expr, sig: Expr, key: Expr) -> TernaryExpr: ) +def Ed25519Verify_Bare(data: Expr, sig: Expr, key: Expr) -> TernaryExpr: + """Verify the ed25519 signature of the data against the public key. + + Args: + data: The data signed by the public key. Must evaluate to bytes. + sig: The proposed 64-byte signature of the data. Must evaluate to bytes. + key: The 32 byte public key that produced the signature. Must evaluate to bytes. + """ + return TernaryExpr( + Op.ed25519verify_bare, + (TealType.bytes, TealType.bytes, TealType.bytes), + TealType.uint64, + data, + sig, + key, + ) + + def SetBit(value: Expr, index: Expr, newBitValue: Expr) -> TernaryExpr: """Set the bit value of an expression at a specific index. diff --git a/pyteal/ast/ternaryexpr_test.py b/pyteal/ast/ternaryexpr_test.py index 996c58635..51a01958a 100644 --- a/pyteal/ast/ternaryexpr_test.py +++ b/pyteal/ast/ternaryexpr_test.py @@ -7,6 +7,7 @@ teal4Options = pt.CompileOptions(version=4) teal5Options = pt.CompileOptions(version=5) teal6Options = pt.CompileOptions(version=6) +teal7Options = pt.CompileOptions(version=7) def test_ed25519verify(): @@ -41,6 +42,41 @@ def test_ed25519verify_invalid(): pt.Ed25519Verify(pt.Bytes("data"), pt.Bytes("sig"), pt.Int(0)) +def test_ed25519verify_bare(): + args = [pt.Bytes("data"), pt.Bytes("sig"), pt.Bytes("key")] + expr = pt.Ed25519Verify_Bare(args[0], args[1], args[2]) + assert expr.type_of() == pt.TealType.uint64 + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(args[0], pt.Op.byte, '"data"'), + pt.TealOp(args[1], pt.Op.byte, '"sig"'), + pt.TealOp(args[2], pt.Op.byte, '"key"'), + pt.TealOp(expr, pt.Op.ed25519verify_bare), + ] + ) + + actual, _ = expr.__teal__(teal7Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + with pytest.raises(pt.TealInputError): + expr.__teal__(teal6Options) + + +def test_ed25519verify_bare_invalid(): + with pytest.raises(pt.TealTypeError): + pt.Ed25519Verify_Bare(pt.Int(0), pt.Bytes("sig"), pt.Bytes("key")) + + with pytest.raises(pt.TealTypeError): + pt.Ed25519Verify_Bare(pt.Bytes("data"), pt.Int(0), pt.Bytes("key")) + + with pytest.raises(pt.TealTypeError): + pt.Ed25519Verify_Bare(pt.Bytes("data"), pt.Bytes("sig"), pt.Int(0)) + + def test_set_bit_int(): args = [pt.Int(0), pt.Int(2), pt.Int(1)] expr = pt.SetBit(args[0], args[1], args[2]) diff --git a/pyteal/ir/ops.py b/pyteal/ir/ops.py index 4a040cac0..f0e217a63 100644 --- a/pyteal/ir/ops.py +++ b/pyteal/ir/ops.py @@ -183,6 +183,7 @@ def min_version(self) -> int: replace3 = OpType("replace3", Mode.Signature | Mode.Application, 7) base64_decode = OpType("base64_decode", Mode.Application | Mode.Signature, 7) json_ref = OpType("json_ref", Mode.Signature | Mode.Application, 7) + ed25519verify_bare = OpType("ed25519verify_bare", Mode.Signature | Mode.Application, 7) sha3_256 = OpType("sha3_256", Mode.Signature | Mode.Application, 7) vrf_verify = OpType("vrf_verify", Mode.Signature | Mode.Application, 7) block = OpType("block", Mode.Signature | Mode.Application, 7) From 7c24013f60150851994af29e89a0f79f054edeb5 Mon Sep 17 00:00:00 2001 From: Hang Su <87964331+ahangsu@users.noreply.github.com> Date: Wed, 20 Jul 2022 13:25:28 -0400 Subject: [PATCH 012/157] AVM Boxes Ops in Pyteal (#438) * add box ops * full support on ops * first set of test, add versioning in multi * remove some seemingly not necessary code? * update testcase * check invalid arguments * finish testcase * move stuffs to app * version check trick * verifyTealVersion apply * error message * update docs structures * period * update doc * update doc * update doc * per pr review on implementation * Update docs/state.rst Co-authored-by: Zeph Grunschlag * Update docs/state.rst Co-authored-by: Zeph Grunschlag * Update docs/state.rst Co-authored-by: Zeph Grunschlag * Update docs/state.rst Co-authored-by: Zeph Grunschlag * Update docs/state.rst Co-authored-by: Zeph Grunschlag * Update docs/state.rst Co-authored-by: Zeph Grunschlag * Update docs/state.rst Co-authored-by: Zeph Grunschlag * Update docs/state.rst Co-authored-by: Zeph Grunschlag * Update docs/state.rst Co-authored-by: Zeph Grunschlag * hex box size goes wild * Update docs/state.rst Co-authored-by: Zeph Grunschlag * warning about MBR * wording * Update docs/state.rst Co-authored-by: Zeph Grunschlag * emphasize * Update docs/state.rst Co-authored-by: Zeph Grunschlag * Update docs/state.rst Co-authored-by: Zeph Grunschlag * polishing * remove redundant box_put doc segment * per zeph pr review * use note and warning * per zeph's pr review * Update docs/state.rst Co-authored-by: Michael Diamant * creating boxes * Update docs/state.rst Co-authored-by: Michael Diamant * per pr review * table for state types Co-authored-by: Ben Guidarelli Co-authored-by: Zeph Grunschlag Co-authored-by: Michael Diamant --- docs/state.rst | 165 ++++++++++++++++++++-- pyteal/__init__.pyi | 7 + pyteal/ast/__init__.py | 17 +++ pyteal/ast/app.py | 87 +++++++++++- pyteal/ast/box.py | 226 +++++++++++++++++++++++++++++++ pyteal/ast/box_test.py | 184 +++++++++++++++++++++++++ pyteal/ast/maybe.py | 28 +++- pyteal/compiler/compiler.py | 2 +- pyteal/compiler/compiler_test.py | 2 +- pyteal/ir/ops.py | 7 + 10 files changed, 707 insertions(+), 18 deletions(-) create mode 100644 pyteal/ast/box.py create mode 100644 pyteal/ast/box_test.py diff --git a/docs/state.rst b/docs/state.rst index 71f1c638f..adb585b26 100644 --- a/docs/state.rst +++ b/docs/state.rst @@ -7,20 +7,30 @@ PyTeal can be used to write `Stateful Algorand Smart Contracts "App": Args: key: The key to write in the global application state. Must evaluate to bytes. - value: THe value to write in the global application state. Can evaluate to any type. + value: The value to write in the global application state. Can evaluate to any type. """ require_type(key, TealType.bytes) require_type(value, TealType.anytype) @@ -211,6 +220,82 @@ def globalDel(cls, key: Expr) -> "App": require_type(key, TealType.bytes) return cls(AppField.globalDel, [key]) + @classmethod + def box_create(cls, name: Expr, size: Expr) -> BoxCreate: + """ + Create a box with a given name and size. + + Args: + name: The key used to reference this box. Must evaluate to a bytes. + size: The number of bytes to reserve for this box. Must evaluate to a uint64. + """ + return BoxCreate(name, size) + + @classmethod + def box_delete(cls, name: Expr) -> BoxDelete: + """ + Deletes a box given it's name. + + Args: + name: The key the box was created with. Must evaluate to bytes. + """ + return BoxDelete(name) + + @classmethod + def box_extract(cls, name: Expr, start: Expr, length: Expr) -> BoxExtract: + """ + Extracts bytes in a box given its name, start index and stop index. + + Args: + name: The key the box was created with. Must evaluate to bytes. + start: The byte index into the box to start reading. Must evaluate to uint64. + length: The byte length into the box from start to stop reading. Must evaluate to uint64. + """ + return BoxExtract(name, start, length) + + @classmethod + def box_replace(cls, name: Expr, start: Expr, value: Expr) -> BoxReplace: + """ + Replaces bytes in a box given its name, start index, and value. + + Args: + name: The key the box was created with. Must evaluate to bytes. + start: The byte index into the box to start writing. Must evaluate to uint64. + value: The value to start writing at start index. Must evaluate to bytes. + """ + return BoxReplace(name, start, value) + + @classmethod + def box_length(cls, name: Expr) -> MaybeValue: + """ + Get the byte length of the box specified by its name. + + Args: + name: The key the box was created with. Must evaluate to bytes. + """ + return BoxLen(name) + + @classmethod + def box_get(cls, name: Expr) -> MaybeValue: + """ + Get the full contents of a box given its name. + + Args: + name: The key the box was created with. Must evaluate to bytes. + """ + return BoxGet(name) + + @classmethod + def box_put(cls, name: Expr, value: Expr) -> BoxPut: + """ + Write all contents to a box given its name. + + Args: + name: The key the box was created with. Must evaluate to bytes. + value: The value to write to the box. Must evaluate to bytes. + """ + return BoxPut(name, value) + App.__module__ = "pyteal" diff --git a/pyteal/ast/box.py b/pyteal/ast/box.py new file mode 100644 index 000000000..33b9712e3 --- /dev/null +++ b/pyteal/ast/box.py @@ -0,0 +1,226 @@ +from typing import TYPE_CHECKING +from pyteal.ast.maybe import MaybeValue +from pyteal.errors import verifyTealVersion + +from pyteal.types import TealType, require_type +from pyteal.ir import TealOp, Op, TealBlock +from pyteal.ast.expr import Expr + +if TYPE_CHECKING: + from pyteal.compiler import CompileOptions + + +class BoxCreate(Expr): + """Create a box with a given name and size.""" + + def __init__(self, name: Expr, size: Expr) -> None: + """ + Args: + name: The key used to reference this box. Must evaluate to a bytes. + size: The number of bytes to reserve for this box. Must evaluate to a uint64. + """ + + super().__init__() + require_type(name, TealType.bytes) + require_type(size, TealType.uint64) + self.name = name + self.size = size + + def __teal__(self, options: "CompileOptions"): + verifyTealVersion( + minVersion=Op.box_create.min_version, + version=options.version, + msg=f"{Op.box_create} unavailable", + ) + return TealBlock.FromOp( + options, TealOp(self, Op.box_create), self.size, self.name + ) + + def __str__(self): + return f"(box_create {self.name} {self.size})" + + def type_of(self): + return TealType.none + + def has_return(self): + return False + + +BoxCreate.__module__ = "pyteal" + + +class BoxDelete(Expr): + """Deletes a box given its name.""" + + def __init__(self, name: Expr) -> None: + """ + Args: + name: The key the box was created with. Must evaluate to bytes. + """ + super().__init__() + require_type(name, TealType.bytes) + self.name = name + + def __teal__(self, options: "CompileOptions"): + verifyTealVersion( + minVersion=Op.box_del.min_version, + version=options.version, + msg=f"{Op.box_del} unavailable", + ) + return TealBlock.FromOp(options, TealOp(self, Op.box_del), self.name) + + def __str__(self): + return f"(box_del {self.name})" + + def type_of(self): + return TealType.none + + def has_return(self): + return False + + +BoxDelete.__module__ = "pyteal" + + +class BoxReplace(Expr): + """Replaces bytes in a box given its name, start index, and value.""" + + def __init__(self, name: Expr, start: Expr, value: Expr) -> None: + """ + Args: + name: The key the box was created with. Must evaluate to bytes. + start: The byte index into the box to start writing. Must evaluate to uint64. + value: The value to start writing at start index. Must evaluate to bytes. + """ + super().__init__() + require_type(name, TealType.bytes) + require_type(start, TealType.uint64) + require_type(value, TealType.bytes) + self.name = name + self.start = start + self.value = value + + def __teal__(self, options: "CompileOptions"): + verifyTealVersion( + minVersion=Op.box_replace.min_version, + version=options.version, + msg=f"{Op.box_replace} unavailable", + ) + return TealBlock.FromOp( + options, TealOp(self, Op.box_replace), self.name, self.start, self.value + ) + + def __str__(self): + return f"(box_replace {self.name} {self.start} {self.value})" + + def type_of(self): + return TealType.none + + def has_return(self): + return False + + +BoxReplace.__module__ = "pyteal" + + +class BoxExtract(Expr): + """Extracts bytes in a box given its name, start index and stop index.""" + + def __init__(self, name: Expr, start: Expr, length: Expr) -> None: + """ + Args: + name: The key the box was created with. Must evaluate to bytes. + start: The byte index into the box to start reading. Must evaluate to uint64. + length: The byte length into the box from start to stop reading. Must evaluate to uint64. + """ + + super().__init__() + require_type(name, TealType.bytes) + require_type(start, TealType.uint64) + require_type(length, TealType.uint64) + self.name = name + self.start = start + self.length = length + + def __teal__(self, options: "CompileOptions"): + verifyTealVersion( + minVersion=Op.box_extract.min_version, + version=options.version, + msg=f"{Op.box_extract} unavailable", + ) + return TealBlock.FromOp( + options, TealOp(self, Op.box_extract), self.name, self.start, self.length + ) + + def __str__(self): + return f"(box_extract {self.name} {self.start} {self.length})" + + def type_of(self): + return TealType.bytes + + def has_return(self): + return False + + +BoxExtract.__module__ = "pyteal" + + +def BoxLen(name: Expr) -> MaybeValue: + """ + Get the byte length of the box specified by its name. + + Args: + name: The key the box was created with. Must evaluate to bytes. + """ + require_type(name, TealType.bytes) + return MaybeValue(Op.box_len, TealType.uint64, args=[name]) + + +def BoxGet(name: Expr) -> MaybeValue: + """ + Get the full contents of a box given its name. + + Args: + name: The key the box was created with. Must evaluate to bytes. + """ + require_type(name, TealType.bytes) + return MaybeValue(Op.box_get, TealType.bytes, args=[name]) + + +class BoxPut(Expr): + """Write all contents to a box given its name.""" + + def __init__(self, name: Expr, value: Expr) -> None: + """ + Args: + name: The key the box was created with. Must evaluate to bytes. + value: The value to write to the box. Must evaluate to bytes. + """ + + super().__init__() + require_type(name, TealType.bytes) + require_type(value, TealType.bytes) + self.name = name + self.value = value + + def __teal__(self, options: "CompileOptions"): + verifyTealVersion( + minVersion=Op.box_put.min_version, + version=options.version, + msg=f"{Op.box_put} unavailable", + ) + return TealBlock.FromOp( + options, TealOp(self, Op.box_put), self.name, self.value + ) + + def __str__(self): + return f"(box_put {self.name})" + + def type_of(self): + return TealType.none + + def has_return(self): + return False + + +BoxPut.__module__ = "pyteal" diff --git a/pyteal/ast/box_test.py b/pyteal/ast/box_test.py new file mode 100644 index 000000000..87968ce2f --- /dev/null +++ b/pyteal/ast/box_test.py @@ -0,0 +1,184 @@ +from typing import Callable, Tuple + +import pytest +import pyteal as pt + +teal7Options = pt.CompileOptions(version=7) +teal8Options = pt.CompileOptions(version=8) + +POSITIVE_TEST_CASES: list[Tuple[pt.Expr, pt.TealType]] = [ + (pt.BoxCreate(pt.Bytes("box"), pt.Int(10)), pt.TealType.none), + (pt.BoxDelete(pt.Bytes("box")), pt.TealType.none), + (pt.BoxExtract(pt.Bytes("box"), pt.Int(2), pt.Int(4)), pt.TealType.bytes), + ( + pt.BoxReplace(pt.Bytes("box"), pt.Int(3), pt.Bytes("replace")), + pt.TealType.none, + ), + (pt.BoxLen(pt.Bytes("box")), pt.TealType.none), + (pt.BoxGet(pt.Bytes("box")), pt.TealType.none), + (pt.BoxPut(pt.Bytes("box"), pt.Bytes("goonery")), pt.TealType.none), +] + + +@pytest.mark.parametrize("test_case, test_case_type", POSITIVE_TEST_CASES) +def test_compile_version_and_type(test_case, test_case_type): + with pytest.raises(pt.TealInputError): + test_case.__teal__(teal7Options) + + test_case.__teal__(teal8Options) + assert test_case.type_of() == test_case_type + assert not test_case.has_return() + + return + + +INVALID_TEST_CASES: list[Tuple[list[pt.Expr], type | Callable[..., pt.MaybeValue]]] = [ + ([pt.Bytes("box"), pt.Bytes("ten")], pt.BoxCreate), + ([pt.Int(0xB0B), pt.Int(10)], pt.BoxCreate), + ([pt.Int(0xA11CE)], pt.BoxDelete), + ([pt.Bytes("box"), pt.Int(2), pt.Bytes("three")], pt.BoxExtract), + ([pt.Bytes("box"), pt.Int(2), pt.Int(0x570FF)], pt.BoxReplace), + ([pt.Int(12)], pt.BoxLen), + ([pt.Int(45)], pt.BoxGet), + ([pt.Bytes("box"), pt.Int(123)], pt.BoxPut), +] + + +@pytest.mark.parametrize("test_args, test_expr", INVALID_TEST_CASES) +def test_box_invalid_args(test_args, test_expr): + with pytest.raises(pt.TealTypeError): + test_expr(*test_args) + + +def test_box_create_compile(): + name_arg: pt.Expr = pt.Bytes("eineName") + size_arg: pt.Expr = pt.Int(10) + expr: pt.Expr = pt.BoxCreate(name_arg, size_arg) + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(size_arg, pt.Op.int, 10), + pt.TealOp(name_arg, pt.Op.byte, '"eineName"'), + pt.TealOp(expr, pt.Op.box_create), + ] + ) + actual, _ = expr.__teal__(teal8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert expected == actual + + +def test_box_delete_compile(): + name_arg: pt.Expr = pt.Bytes("eineName") + expr: pt.Expr = pt.BoxDelete(name_arg) + + expected = pt.TealSimpleBlock( + [pt.TealOp(name_arg, pt.Op.byte, '"eineName"'), pt.TealOp(expr, pt.Op.box_del)] + ) + actual, _ = expr.__teal__(teal8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert expected == actual + + +def test_box_extract(): + name_arg: pt.Expr = pt.Bytes("eineName") + srt_arg: pt.Expr = pt.Int(10) + end_arg: pt.Expr = pt.Int(15) + expr: pt.Expr = pt.BoxExtract(name_arg, srt_arg, end_arg) + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(name_arg, pt.Op.byte, '"eineName"'), + pt.TealOp(srt_arg, pt.Op.int, 10), + pt.TealOp(end_arg, pt.Op.int, 15), + pt.TealOp(expr, pt.Op.box_extract), + ] + ) + actual, _ = expr.__teal__(teal8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert expected == actual + + +def test_box_replace(): + name_arg: pt.Expr = pt.Bytes("eineName") + srt_arg: pt.Expr = pt.Int(10) + replace_arg: pt.Expr = pt.Bytes("replace-str") + expr: pt.Expr = pt.BoxReplace(name_arg, srt_arg, replace_arg) + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(name_arg, pt.Op.byte, '"eineName"'), + pt.TealOp(srt_arg, pt.Op.int, 10), + pt.TealOp(replace_arg, pt.Op.byte, '"replace-str"'), + pt.TealOp(expr, pt.Op.box_replace), + ] + ) + actual, _ = expr.__teal__(teal8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert expected == actual + + +def test_box_length(): + name_arg: pt.Expr = pt.Bytes("eineName") + expr: pt.MaybeValue = pt.BoxLen(name_arg) + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(name_arg, pt.Op.byte, '"eineName"'), + pt.TealOp(expr, pt.Op.box_len), + pt.TealOp(expr.output_slots[1].store(), pt.Op.store, expr.output_slots[1]), + pt.TealOp(expr.output_slots[0].store(), pt.Op.store, expr.output_slots[0]), + ] + ) + actual, _ = expr.__teal__(teal8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + with pt.TealComponent.Context.ignoreExprEquality(): + assert expected == actual + + +def test_box_get(): + name_arg: pt.Expr = pt.Bytes("eineName") + expr: pt.MaybeValue = pt.BoxGet(name_arg) + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(name_arg, pt.Op.byte, '"eineName"'), + pt.TealOp(expr, pt.Op.box_get), + pt.TealOp(expr.output_slots[1].store(), pt.Op.store, expr.output_slots[1]), + pt.TealOp(expr.output_slots[0].store(), pt.Op.store, expr.output_slots[0]), + ] + ) + actual, _ = expr.__teal__(teal8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + with pt.TealComponent.Context.ignoreExprEquality(): + assert expected == actual + + +def test_box_put(): + name_arg: pt.Expr = pt.Bytes("eineName") + put_arg: pt.Expr = pt.Bytes("put-str") + expr: pt.Expr = pt.BoxPut(name_arg, put_arg) + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(name_arg, pt.Op.byte, '"eineName"'), + pt.TealOp(put_arg, pt.Op.byte, '"put-str"'), + pt.TealOp(expr, pt.Op.box_put), + ] + ) + actual, _ = expr.__teal__(teal8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert expected == actual diff --git a/pyteal/ast/maybe.py b/pyteal/ast/maybe.py index 43846384d..ebe3d03e7 100644 --- a/pyteal/ast/maybe.py +++ b/pyteal/ast/maybe.py @@ -1,11 +1,15 @@ -from typing import List, Union - -from pyteal.ast.multi import MultiValue +from typing import List, Union, TYPE_CHECKING +from pyteal.errors import verifyTealVersion from pyteal.types import TealType from pyteal.ir import Op + from pyteal.ast.expr import Expr from pyteal.ast.scratch import ScratchLoad, ScratchSlot +from pyteal.ast.multi import MultiValue + +if TYPE_CHECKING: + from pyteal.compiler import CompileOptions class MaybeValue(MultiValue): @@ -17,7 +21,7 @@ def __init__( type: TealType, *, immediate_args: List[Union[int, str]] = None, - args: List[Expr] = None + args: List[Expr] = None, ): """Create a new MaybeValue. @@ -27,8 +31,22 @@ def __init__( immediate_args (optional): Immediate arguments for the op. Defaults to None. args (optional): Stack arguments for the op. Defaults to None. """ + + def local_version_check(option: "CompileOptions"): + verifyTealVersion( + minVersion=op.min_version, + version=option.version, + msg=f"{op.value} unavailable", + ) + types = [type, TealType.uint64] - super().__init__(op, types, immediate_args=immediate_args, args=args) + super().__init__( + op, + types, + immediate_args=immediate_args, + args=args, + compile_check=local_version_check, + ) def hasValue(self) -> ScratchLoad: """Check if the value exists. diff --git a/pyteal/compiler/compiler.py b/pyteal/compiler/compiler.py index 2a68be57a..faf8717bd 100644 --- a/pyteal/compiler/compiler.py +++ b/pyteal/compiler/compiler.py @@ -25,7 +25,7 @@ ) from pyteal.compiler.constants import createConstantBlocks -MAX_TEAL_VERSION = 7 +MAX_TEAL_VERSION = 8 MIN_TEAL_VERSION = 2 DEFAULT_TEAL_VERSION = MIN_TEAL_VERSION diff --git a/pyteal/compiler/compiler_test.py b/pyteal/compiler/compiler_test.py index b3e528506..014607465 100644 --- a/pyteal/compiler/compiler_test.py +++ b/pyteal/compiler/compiler_test.py @@ -139,7 +139,7 @@ def test_compile_version_invalid(): pt.compileTeal(expr, pt.Mode.Signature, version=1) # too small with pytest.raises(pt.TealInputError): - pt.compileTeal(expr, pt.Mode.Signature, version=8) # too large + pt.compileTeal(expr, pt.Mode.Signature, version=9) # too large with pytest.raises(pt.TealInputError): pt.compileTeal(expr, pt.Mode.Signature, version=2.0) # decimal diff --git a/pyteal/ir/ops.py b/pyteal/ir/ops.py index f0e217a63..d87c76250 100644 --- a/pyteal/ir/ops.py +++ b/pyteal/ir/ops.py @@ -187,6 +187,13 @@ def min_version(self) -> int: sha3_256 = OpType("sha3_256", Mode.Signature | Mode.Application, 7) vrf_verify = OpType("vrf_verify", Mode.Signature | Mode.Application, 7) block = OpType("block", Mode.Signature | Mode.Application, 7) + box_create = OpType("box_create", Mode.Application, 8) + box_extract = OpType("box_extract", Mode.Application, 8) + box_replace = OpType("box_replace", Mode.Application, 8) + box_del = OpType("box_del", Mode.Application, 8) + box_len = OpType("box_len", Mode.Application, 8) + box_get = OpType("box_get", Mode.Application, 8) + box_put = OpType("box_put", Mode.Application, 8) # fmt: on From ba260e6c337933b017a708b952eaf2f7842b1e03 Mon Sep 17 00:00:00 2001 From: Hang Su <87964331+ahangsu@users.noreply.github.com> Date: Fri, 22 Jul 2022 13:33:24 -0400 Subject: [PATCH 013/157] Merge Teal7 to AVM8, and consolidate Teal to AVM versioning (#470) * swapping base64 modes to match the rest (#446) * Merge master into teal7 (#450) * AVM 7: Address integration branch feedback (#452) * Add Execute Method (#444) * adding execute method to allow omission of begin/submit for common use case * exec docstring * update testcase Co-authored-by: Hang Su * Merge branch 'master' into teal7 (#463) * fix misspelling of uint (#431) * fix misspelling of uint * Clarify minimum Python version management docs (#435) * Foreign prefix on App and Asset arrays (#440) * replacing foreignapps with applications * fix assets as well * Add Execute Method (#444) * adding execute method to allow omission of begin/submit for common use case * exec docstring * update testcase Co-authored-by: Hang Su Co-authored-by: Ben Guidarelli Co-authored-by: Hang Su * Consolidate TEAL and AVM versioning (#441) * fix misspelling of uint (#431) * fix misspelling of uint * Clarify minimum Python version management docs (#435) * Convert TEAL version references to program version by hand * Replace `teal#Options` with `avm#Options` * Deprecate `*_TEAL_VERSION` in favor of `*_PROGRAM_VERSION` * Fix docs typo Co-authored-by: Michael Diamant * Minor `versions.rst` changes * Fix `verifyTealVersion` in new opcode files * Fix linter errors * Fix language discrepencies introduced by the merge * Remove incorrect avm replacement * Fix inconsistent language introduced by merge Co-authored-by: Ben Guidarelli Co-authored-by: Michael Diamant * max program version Co-authored-by: Ben Guidarelli Co-authored-by: Michael Diamant Co-authored-by: Jacob Daitzman --- docs/accessing_transaction_field.rst | 184 +++++++++++++------------- docs/arithmetic_expression.rst | 2 +- docs/byte_expression.rst | 2 +- docs/control_structures.rst | 8 +- docs/crypto.rst | 4 +- docs/loading_group_transaction.rst | 2 +- docs/versions.rst | 19 +-- examples/signature/factorizer_game.py | 2 +- pyteal/__init__.py | 6 + pyteal/__init__.pyi | 6 + pyteal/ast/acct_test.py | 12 +- pyteal/ast/app_test.py | 24 ++-- pyteal/ast/arg.py | 8 +- pyteal/ast/arg_test.py | 12 +- pyteal/ast/assert_test.py | 12 +- pyteal/ast/asset_test.py | 60 ++++----- pyteal/ast/base64decode.py | 12 +- pyteal/ast/base64decode_test.py | 12 +- pyteal/ast/binaryexpr.py | 50 +++---- pyteal/ast/binaryexpr_test.py | 170 ++++++++++++------------ pyteal/ast/block.py | 4 +- pyteal/ast/block_test.py | 12 +- pyteal/ast/box.py | 12 +- pyteal/ast/box_test.py | 22 +-- pyteal/ast/ecdsa.py | 16 ++- pyteal/ast/ecdsa_test.py | 105 ++++++++------- pyteal/ast/gaid.py | 8 +- pyteal/ast/gaid_test.py | 12 +- pyteal/ast/gitxn.py | 10 +- pyteal/ast/gitxn_test.py | 12 +- pyteal/ast/gload.py | 8 +- pyteal/ast/gload_test.py | 20 +-- pyteal/ast/global_.py | 14 +- pyteal/ast/global_test.py | 50 +++---- pyteal/ast/gtxn.py | 16 ++- pyteal/ast/gtxn_test.py | 6 +- pyteal/ast/itxn.py | 43 ++++-- pyteal/ast/itxn_test.py | 94 ++++++++----- pyteal/ast/jsonref.py | 18 +-- pyteal/ast/jsonref_test.py | 16 +-- pyteal/ast/maybe.py | 4 +- pyteal/ast/opup.py | 4 +- pyteal/ast/replace.py | 8 +- pyteal/ast/replace_test.py | 16 +-- pyteal/ast/return_.py | 6 +- pyteal/ast/subroutine.py | 6 +- pyteal/ast/substring.py | 20 +-- pyteal/ast/substring_test.py | 46 +++---- pyteal/ast/ternaryexpr.py | 12 +- pyteal/ast/ternaryexpr_test.py | 32 ++--- pyteal/ast/txn.py | 54 +++----- pyteal/ast/txn_test.py | 2 - pyteal/ast/unaryexpr.py | 22 +-- pyteal/ast/unaryexpr_test.py | 60 ++++----- pyteal/ast/widemath.py | 4 +- pyteal/compiler/__init__.py | 6 + pyteal/compiler/compiler.py | 32 +++-- pyteal/compiler/subroutines.py | 4 +- pyteal/errors.py | 6 +- pyteal/ir/ops.py | 2 +- 60 files changed, 764 insertions(+), 687 deletions(-) diff --git a/docs/accessing_transaction_field.rst b/docs/accessing_transaction_field.rst index 64c5f0b65..cf13f99a6 100644 --- a/docs/accessing_transaction_field.rst +++ b/docs/accessing_transaction_field.rst @@ -19,56 +19,54 @@ Fields by Transaction Type Common Fields ....................................................... -================================================================================ ========================= ================ ============================================================================ -Operator Type Min TEAL Version Notes -================================================================================ ========================= ================ ============================================================================ +================================================================================ ========================= ==================== ============================================================================ +Operator Type Min Program Version Notes +================================================================================ ========================= ==================== ============================================================================ :any:`Txn.type() ` :code:`TealType.bytes` 2 -:any:`Txn.type_enum() ` :code:`TealType.uint64` 2 see table below -:any:`Txn.sender() ` :code:`TealType.bytes` 2 32 byte address -:any:`Txn.fee() ` :code:`TealType.uint64` 2 in microAlgos -:any:`Txn.first_valid() ` :code:`TealType.uint64` 2 round number -:any:`Txn.first_valid_time() ` :code:`TealType.uint64` 7 UNIX timestamp of block before :code:`Txn.first_valid()`. Fails if negative -:any:`Txn.last_valid() ` :code:`TealType.uint64` 2 round number -:any:`Txn.note() ` :code:`TealType.bytes` 2 transaction note in bytes -:any:`Txn.lease() ` :code:`TealType.bytes` 2 transaction lease in bytes -:any:`Txn.group_index() ` :code:`TealType.uint64` 2 position of this transaction within a transaction group, starting at 0 -:any:`Txn.tx_id() ` :code:`TealType.bytes` 2 the computed ID for this transaction, 32 bytes -:any:`Txn.rekey_to() ` :code:`TealType.bytes` 2 32 byte address -================================================================================ ========================= ================ ============================================================================ +:any:`Txn.type_enum() ` :code:`TealType.uint64` 2 see table below +:any:`Txn.sender() ` :code:`TealType.bytes` 2 32 byte address +:any:`Txn.fee() ` :code:`TealType.uint64` 2 in microAlgos +:any:`Txn.first_valid() ` :code:`TealType.uint64` 2 round number +:any:`Txn.first_valid_time() ` :code:`TealType.uint64` 7 UNIX timestamp of block before :code:`Txn.first_valid()`. Fails if negative +:any:`Txn.last_valid() ` :code:`TealType.uint64` 2 round number +:any:`Txn.note() ` :code:`TealType.bytes` 2 transaction note in bytes +:any:`Txn.lease() ` :code:`TealType.bytes` 2 transaction lease in bytes +:any:`Txn.group_index() ` :code:`TealType.uint64` 2 position of this transaction within a transaction group, starting at 0 +:any:`Txn.tx_id() ` :code:`TealType.bytes` 2 the computed ID for this transaction, 32 bytes +:any:`Txn.rekey_to() ` :code:`TealType.bytes` 2 32 byte address +================================================================================ ========================= ==================== ============================================================================ Application Call ....................................................... -==================================================================================== ========================= ================ ============================================================================ -Operator Type Min TEAL Version Notes -==================================================================================== ========================= ================ ============================================================================ +==================================================================================== ========================= ==================== ============================================================================ +Operator Type Min Program Version Notes +==================================================================================== ========================= ==================== ============================================================================ :any:`Txn.application_id() ` :code:`TealType.uint64` 2 :any:`Txn.on_completion() ` :code:`TealType.uint64` 2 :any:`Txn.approval_program() ` :code:`TealType.bytes` 2 -:any:`Txn.global_num_uints() ` :code:`TealType.uint64` 3 Maximum global integers in app schema -:any:`Txn.global_num_byte_slices() ` :code:`TealType.uint64` 3 Maximum global byte strings in app schema -:any:`Txn.local_num_uints() ` :code:`TealType.uint64` 3 Maximum local integers in app schema -:any:`Txn.local_num_byte_slices() ` :code:`TealType.uint64` 3 Maximum local byte strings in app schema -:any:`Txn.accounts ` :code:`TealType.bytes[]` 2 Array of accounts available to the application -:any:`Txn.assets ` :code:`TealType.uint64[]` 3 Array of assets available to the application -:any:`Txn.applications ` :code:`TealType.uint64[]` 3 Array of applications +:any:`Txn.global_num_uints() ` :code:`TealType.uint64` 3 Maximum global integers in app schema +:any:`Txn.global_num_byte_slices() ` :code:`TealType.uint64` 3 Maximum global byte strings in app schema +:any:`Txn.local_num_uints() ` :code:`TealType.uint64` 3 Maximum local integers in app schema +:any:`Txn.local_num_byte_slices() ` :code:`TealType.uint64` 3 Maximum local byte strings in app schema +:any:`Txn.accounts ` :code:`TealType.bytes[]` 2 Array of accounts available to the application +:any:`Txn.assets ` :code:`TealType.uint64[]` 3 Array of assets available to the application +:any:`Txn.applications ` :code:`TealType.uint64[]` 3 Array of applications :any:`Txn.clear_state_program() ` :code:`TealType.bytes` 2 -:any:`Txn.extra_program_pages() ` :code:`TealType.uint64` 4 Number of extra program pages for app -:any:`Txn.application_args ` :code:`TealType.bytes[]` 2 Array of application arguments -:any:`Txn.created_application_id() ` :code:`TealType.uint64` 5 The ID of the newly created application in this transaction. In v5, only valid on inner transactions. >= v6 works with top-level and inner transactions. -:any:`Txn.logs ` :code:`TealType.bytes[]` 5 Array of application logged items. In v5, only valid on inner transactions. >= v6 works with top-level and inner transactions. -:any:`Txn.last_log() ` :code:`TealType.bytes[]` 6 The last message emitted. Empty bytes if none were emitted. Application mode only. -:any:`Txn.approval_program_pages() ` :code:`TealType.bytes[]` 7 The pages of the approval program as an array -:any:`Txn.num_approval_program_pages() ` :code:`TealType.uint64` 7 The number of approval program pages -:any:`Txn.clear_state_program_pages() ` :code:`TealType.bytes[]` 7 The pages of a clear state program as an array -:any:`Txn.num_clear_state_program_pages() ` :code:`TealType.uint64` 7 The number of clear state program pages -==================================================================================== ========================= ================ ============================================================================ +:any:`Txn.extra_program_pages() ` :code:`TealType.uint64` 4 Number of extra program pages for app +:any:`Txn.application_args ` :code:`TealType.bytes[]` 2 Array of application arguments +:any:`Txn.created_application_id() ` :code:`TealType.uint64` 5 The ID of the newly created application in this transaction. In v5, only valid on inner transactions. >= v6 works with top-level and inner transactions. +:any:`Txn.logs ` :code:`TealType.bytes[]` 5 Array of application logged items. In v5, only valid on inner transactions. >= v6 works with top-level and inner transactions. +:any:`Txn.last_log() ` :code:`TealType.bytes` 6 The last message emitted. Empty bytes if none were emitted. Application mode only. +:any:`Txn.approval_program_pages() ` :code:`TealType.bytes[]` 7 The pages of the approval program as an array +:any:`Txn.clear_state_program_pages() ` :code:`TealType.bytes[]` 7 The pages of a clear state program as an array +==================================================================================== ========================= ==================== ============================================================================ Asset Config ....................................................... -================================================================================ ========================= ================ ============================================================================ -Operator Type Min TEAL Version Notes -================================================================================ ========================= ================ ============================================================================ -:any:`Txn.config_asset() ` :code:`TealType.uint64` 2 ID of asset being configured +================================================================================ ========================= ==================== ============================================================================ +Operator Type Min Program Version Notes +================================================================================ ========================= ==================== ============================================================================ +:any:`Txn.config_asset() ` :code:`TealType.uint64` 2 ID of asset being configured :any:`Txn.config_asset_total() ` :code:`TealType.uint64` 2 :any:`Txn.config_asset_decimals() ` :code:`TealType.uint64` 2 :any:`Txn.config_asset_default_frozen() ` :code:`TealType.uint64` 2 @@ -76,58 +74,58 @@ Operator :any:`Txn.config_asset_name() ` :code:`TealType.bytes` 2 :any:`Txn.config_asset_url() ` :code:`TealType.bytes` 2 :any:`Txn.config_asset_metadata_hash() ` :code:`TealType.bytes` 2 -:any:`Txn.config_asset_manager() ` :code:`TealType.bytes` 2 32 byte address -:any:`Txn.config_asset_reserve() ` :code:`TealType.bytes` 2 32 byte address -:any:`Txn.config_asset_freeze() ` :code:`TealType.bytes` 2 32 byte address -:any:`Txn.config_asset_clawback() ` :code:`TealType.bytes` 2 32 byte address -:any:`Txn.created_asset_id() ` :code:`TealType.uint64` 5 The ID of the newly created asset in this transaction. In v5, only valid on inner transactions. >= v6 works with top-level and inner transactions. -================================================================================ ========================= ================ ============================================================================ +:any:`Txn.config_asset_manager() ` :code:`TealType.bytes` 2 32 byte address +:any:`Txn.config_asset_reserve() ` :code:`TealType.bytes` 2 32 byte address +:any:`Txn.config_asset_freeze() ` :code:`TealType.bytes` 2 32 byte address +:any:`Txn.config_asset_clawback() ` :code:`TealType.bytes` 2 32 byte address +:any:`Txn.created_asset_id() ` :code:`TealType.uint64` 5 The ID of the newly created asset in this transaction. In v5, only valid on inner transactions. >= v6 works with top-level and inner transactions. +================================================================================ ========================= ==================== ============================================================================ Asset Freeze ....................................................... -================================================================================ ========================= ================ ============================================================================ -Operator Type Min TEAL Version Notes -================================================================================ ========================= ================ ============================================================================ +================================================================================ ========================= ==================== ============================================================================ +Operator Type Min Program Version Notes +================================================================================ ========================= ==================== ============================================================================ :any:`Txn.freeze_asset() ` :code:`TealType.uint64` 2 -:any:`Txn.freeze_asset_account() ` :code:`TealType.bytes` 2 32 byte address +:any:`Txn.freeze_asset_account() ` :code:`TealType.bytes` 2 32 byte address :any:`Txn.freeze_asset_frozen() ` :code:`TealType.uint64` 2 -================================================================================ ========================= ================ ============================================================================ +================================================================================ ========================= ==================== ============================================================================ Asset Transfer ....................................................... -================================================================================ ========================= ================ ============================================================================ -Operator Type Min TEAL Version Notes -================================================================================ ========================= ================ ============================================================================ -:any:`Txn.xfer_asset() ` :code:`TealType.uint64` 2 ID of asset being transferred -:any:`Txn.asset_amount() ` :code:`TealType.uint64` 2 value in Asset's units -:any:`Txn.asset_sender() ` :code:`TealType.bytes` 2 32 byte address, causes clawback of all value if sender is the clawback -:any:`Txn.asset_receiver() ` :code:`TealType.bytes` 2 32 byte address -:any:`Txn.asset_close_to() ` :code:`TealType.bytes` 2 32 byte address -================================================================================ ========================= ================ ============================================================================ +================================================================================ ========================= ==================== ============================================================================ +Operator Type Min Program Version Notes +================================================================================ ========================= ==================== ============================================================================ +:any:`Txn.xfer_asset() ` :code:`TealType.uint64` 2 ID of asset being transferred +:any:`Txn.asset_amount() ` :code:`TealType.uint64` 2 value in Asset's units +:any:`Txn.asset_sender() ` :code:`TealType.bytes` 2 32 byte address, causes clawback of all value if sender is the clawback +:any:`Txn.asset_receiver() ` :code:`TealType.bytes` 2 32 byte address +:any:`Txn.asset_close_to() ` :code:`TealType.bytes` 2 32 byte address +================================================================================ ========================= ==================== ============================================================================ Key Registration ....................................................... -================================================================================ ========================= ================ ============================================================================ -Operator Type Min TEAL Version Notes -================================================================================ ========================= ================ ============================================================================ -:any:`Txn.vote_pk() ` :code:`TealType.bytes` 2 32 byte address -:any:`Txn.selection_pk() ` :code:`TealType.bytes` 2 32 byte address -:any:`Txn.state_proof_pk ` :code:`TealType.bytes` 6 64 byte state proof public key commitment. +================================================================================ ========================= ==================== ============================================================================ +Operator Type Min Program Version Notes +================================================================================ ========================= ==================== ============================================================================ +:any:`Txn.vote_pk() ` :code:`TealType.bytes` 2 32 byte address +:any:`Txn.selection_pk() ` :code:`TealType.bytes` 2 32 byte address +:any:`Txn.state_proof_pk ` :code:`TealType.bytes` 6 64 byte state proof public key commitment. :any:`Txn.vote_first() ` :code:`TealType.uint64` 2 :any:`Txn.vote_last() ` :code:`TealType.uint64` 2 :any:`Txn.vote_key_dilution() ` :code:`TealType.uint64` 2 -:any:`Txn.nonparticipation() ` :code:`TealType.uint64` 5 Marks an account nonparticipating for rewards -================================================================================ ========================= ================ ============================================================================ +:any:`Txn.nonparticipation() ` :code:`TealType.uint64` 5 Marks an account nonparticipating for rewards +================================================================================ ========================= ==================== ============================================================================ Payment ....................................................... -================================================================================ ========================= ================ ============================================================================ -Operator Type Min TEAL Version Notes -================================================================================ ========================= ================ ============================================================================ -:any:`Txn.receiver() ` :code:`TealType.bytes` 2 32 byte address -:any:`Txn.amount() ` :code:`TealType.uint64` 2 in microAlgos -:any:`Txn.close_remainder_to() ` :code:`TealType.bytes` 2 32 byte address -================================================================================ ========================= ================ ============================================================================ +================================================================================ ========================= ==================== ============================================================================ +Operator Type Min Program Version Notes +================================================================================ ========================= ==================== ============================================================================ +:any:`Txn.receiver() ` :code:`TealType.bytes` 2 32 byte address +:any:`Txn.amount() ` :code:`TealType.uint64` 2 in microAlgos +:any:`Txn.close_remainder_to() ` :code:`TealType.bytes` 2 32 byte address +================================================================================ ========================= ==================== ============================================================================ Transaction Types ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -162,7 +160,7 @@ items can be accessed using bracket notation. For example: Txn.application_args[0] # get the first application argument Txn.application_args[1] # get the second application argument - # as of TEAL v5, PyTeal expressions can be used to dynamically index into array properties as well + # as of AVM v5, PyTeal expressions can be used to dynamically index into array properties as well Txn.application_args[Txn.application_args.length() - Int(1)] # get the last application argument .. _txn_special_case_arrays: @@ -197,7 +195,7 @@ available on the elements of :code:`Gtxn`. For example: Gtxn[0].sender() # get the sender of the first transaction in the atomic transfer group Gtxn[1].receiver() # get the receiver of the second transaction in the atomic transfer group - # as of TEAL v3, PyTeal expressions can be used to dynamically index into Gtxn as well + # as of AVM v3, PyTeal expressions can be used to dynamically index into Gtxn as well Gtxn[Txn.group_index() - Int(1)].sender() # get the sender of the previous transaction in the atomic transfer group :code:`Gtxn` is zero-indexed and the maximum size of an atomic transfer group is 16. The size of the @@ -211,7 +209,7 @@ Inner Transactions ------------------ .. note:: - Inner transactions are only available in TEAL version 5 or higher. + Inner transactions are only available in AVM version 5 or higher. Inner transactions can be created and submitted with expressions from the :any:`InnerTxnBuilder` class. The properties of the most recently submitted inner transaction can be accessed using the :any:`InnerTxn` @@ -224,19 +222,19 @@ Global Parameters Information about the current state of the blockchain can be obtained using the following :any:`Global` expressions: -=========================================== ======================= ================ ============================================================= -Operator Type Min TEAL Version Notes -=========================================== ======================= ================ ============================================================= -:any:`Global.min_txn_fee()` :code:`TealType.uint64` 2 in microAlgos -:any:`Global.min_balance()` :code:`TealType.uint64` 2 in microAlgos -:any:`Global.max_txn_life()` :code:`TealType.uint64` 2 number of rounds -:any:`Global.zero_address()` :code:`TealType.bytes` 2 32 byte address of all zero bytes -:any:`Global.group_size()` :code:`TealType.uint64` 2 number of txns in this atomic transaction group, at least 1 -:any:`Global.logic_sig_version()` :code:`TealType.uint64` 2 the maximum supported TEAL version -:any:`Global.round()` :code:`TealType.uint64` 2 the current round number -:any:`Global.latest_timestamp()` :code:`TealType.uint64` 2 the latest confirmed block UNIX timestamp -:any:`Global.current_application_id()` :code:`TealType.uint64` 2 the ID of the current application executing -:any:`Global.creator_address()` :code:`TealType.bytes` 3 32 byte address of the creator of the current application -:any:`Global.current_application_address()` :code:`TealType.bytes` 5 32 byte address of the current application controlled account -:any:`Global.group_id()` :code:`TealType.bytes` 5 32 byte ID of the current transaction group -=========================================== ======================= ================ ============================================================= +=========================================== ======================= ==================== ============================================================= +Operator Type Min Program Version Notes +=========================================== ======================= ==================== ============================================================= +:any:`Global.min_txn_fee()` :code:`TealType.uint64` 2 in microAlgos +:any:`Global.min_balance()` :code:`TealType.uint64` 2 in microAlgos +:any:`Global.max_txn_life()` :code:`TealType.uint64` 2 number of rounds +:any:`Global.zero_address()` :code:`TealType.bytes` 2 32 byte address of all zero bytes +:any:`Global.group_size()` :code:`TealType.uint64` 2 number of txns in this atomic transaction group, at least 1 +:any:`Global.logic_sig_version()` :code:`TealType.uint64` 2 the maximum supported program version +:any:`Global.round()` :code:`TealType.uint64` 2 the current round number +:any:`Global.latest_timestamp()` :code:`TealType.uint64` 2 the latest confirmed block UNIX timestamp +:any:`Global.current_application_id()` :code:`TealType.uint64` 2 the ID of the current application executing +:any:`Global.creator_address()` :code:`TealType.bytes` 3 32 byte address of the creator of the current application +:any:`Global.current_application_address()` :code:`TealType.bytes` 5 32 byte address of the current application controlled account +:any:`Global.group_id()` :code:`TealType.bytes` 5 32 byte ID of the current transaction group +=========================================== ======================= ==================== ============================================================= diff --git a/docs/arithmetic_expression.rst b/docs/arithmetic_expression.rst index daa4619c6..a9d0f75aa 100644 --- a/docs/arithmetic_expression.rst +++ b/docs/arithmetic_expression.rst @@ -49,7 +49,7 @@ The associativity and precedence of the overloaded Python arithmetic operators a Byteslice Arithmetic -------------------- -Byteslice arithemetic is available for Teal V4 and above. +Byteslice arithmetic is available for AVM V4 and above. Byteslice arithmetic operators allow up to 512-bit arithmetic. In PyTeal, byteslice arithmetic expressions include :code:`TealType.Bytes` values as arguments (with the exception of :code:`BytesZero`) diff --git a/docs/byte_expression.rst b/docs/byte_expression.rst index acc535576..b457e756b 100644 --- a/docs/byte_expression.rst +++ b/docs/byte_expression.rst @@ -48,7 +48,7 @@ Extract ~~~~~~~ .. note:: - :code:`Extract` is only available in TEAL version 5 or higher. + :code:`Extract` is only available in program version 5 or higher. The :any:`Extract` expression can extract part of a byte slice given the start index and length. For example: diff --git a/docs/control_structures.rst b/docs/control_structures.rst index a62bfec2c..b464b1535 100644 --- a/docs/control_structures.rst +++ b/docs/control_structures.rst @@ -11,7 +11,7 @@ Exiting the Program: :code:`Approve` and :code:`Reject` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. note:: - The :code:`Approve` and :code:`Reject` expressions are only available in TEAL version 4 or higher. + The :code:`Approve` and :code:`Reject` expressions are only available in program version 4 or higher. Prior to this, :code:`Return(Int(1))` is equivalent to :code:`Approve()` and :code:`Return(Int(0))` is equivalent to :code:`Reject()`. @@ -166,7 +166,7 @@ Looping: :code:`While` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. note:: - This expression is only available in TEAL version 4 or higher. + This expression is only available in program version 4 or higher. The :any:`While` expression can be used to create simple loops in PyTeal. The syntax of :code:`While` is: @@ -203,7 +203,7 @@ Looping: :code:`For` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. note:: - This expression is only available in TEAL version 4 or higher. + This expression is only available in program version 4 or higher. Similar to :code:`While`, the :any:`For` expression can also be used to create loops in PyTeal. The syntax of :code:`For` is: @@ -294,7 +294,7 @@ Subroutines ~~~~~~~~~~~ .. note:: - Subroutines are only available in TEAL version 4 or higher. + Subroutines are only available in program version 4 or higher. A subroutine is section of code that can be called multiple times from within a program. Subroutines are PyTeal's equivalent to functions. Subroutine constraints include: diff --git a/docs/crypto.rst b/docs/crypto.rst index 6a80b2567..7f9a0ef75 100644 --- a/docs/crypto.rst +++ b/docs/crypto.rst @@ -24,9 +24,9 @@ Operator Cost Description :code:`EcdsaRecover(c, d, id, r, s)` `2000` produces the public key associated with the signature :code:`(r, s)` and recovery id :code:`id` ==================================== ========= ================================================================================================================== -\* :code:`Ed25519Verify` is only available in signature mode up to version 4 of TEAL. From version 5 upwards, `Ed25519Verify` can be used in any mode. +\* :code:`Ed25519Verify` is only available in signature mode up to version 4 of AVM. From version 5 upwards, `Ed25519Verify` can be used in any mode. -Note the cost amount is accurate for version 2 of TEAL and higher. The parameter :code:`c` in the ECDSA expressions defined above represents the elliptic curve +Note the cost amount is accurate for version 2 of AVM and higher. The parameter :code:`c` in the ECDSA expressions defined above represents the elliptic curve specification to be used (for example, :code:`Secp256k1`). These cryptographic primitives cover the most used ones in blockchains and cryptocurrencies. For example, Bitcoin uses `SHA-256` for creating Bitcoin addresses; diff --git a/docs/loading_group_transaction.rst b/docs/loading_group_transaction.rst index 90ada05d5..be2753a7d 100644 --- a/docs/loading_group_transaction.rst +++ b/docs/loading_group_transaction.rst @@ -3,7 +3,7 @@ Loading Values from Group Transactions ====================================== -Since TEAL version 4 and above, programs can load values from transactions within an atomic +Since program version 4 and above, programs can load values from transactions within an atomic group transaction. For instance, you can import values from the scratch space of another application call, and you can access the generated ID of a new application or asset. These operations are only permitted in application mode. diff --git a/docs/versions.rst b/docs/versions.rst index b64910451..15a9bfad0 100644 --- a/docs/versions.rst +++ b/docs/versions.rst @@ -1,14 +1,14 @@ .. _versions: -TEAL Versions +AVM Versions ============= -Each version of PyTeal compiles contracts for a specific version of TEAL. Newer versions of TEAL +Each version of PyTeal compiles contracts for a specific AVM version. Newer versions of the AVM introduce new opcodes and transaction fields, so PyTeal must be updated to support these new -features. Below is a table which shows the relationship between TEAL and PyTeal versions. +features. Below is a table which shows the relationship between AVM and PyTeal versions. ============ ============== -TEAL Version PyTeal Version +AVM Version PyTeal Version ============ ============== 1 <= 0.5.4 2 >= 0.6.0 @@ -16,16 +16,17 @@ TEAL Version PyTeal Version 4 >= 0.8.0 5 >= 0.9.0 6 >= 0.10.0 +7 >= 0.14.0 ============ ============== -In order to support TEAL v2, PyTeal v0.6.0 breaks backward compatibility with v0.5.4. PyTeal +In order to support AVM v2, PyTeal v0.6.0 breaks backward compatibility with v0.5.4. PyTeal programs written for PyTeal version 0.5.4 and below will not compile properly and most likely will display an error of the form :code:`AttributeError: * object has no attribute 'teal'`. -**WARNING:** before updating PyTeal to a version with generates TEAL v2 contracts and fixing the +**WARNING:** before updating PyTeal to a version with generates AVM v2 contracts and fixing the programs to use the global function :any:`compileTeal` rather the class method :code:`.teal()`, make -sure your program abides by the TEAL safety guidelines ``_. -Changing a v1 TEAL program to a v2 TEAL program without any code changes is insecure because v2 -TEAL programs allow rekeying. Specifically, you must add a check that the :code:`RekeyTo` property +sure your program abides by the AVM safety guidelines ``_. +Changing a v1 AVM program to a v2 AVM program without any code changes is insecure because v2 +AVM programs allow rekeying. Specifically, you must add a check that the :code:`RekeyTo` property of any transaction is set to the zero address when updating an older PyTeal program from v0.5.4 and below. diff --git a/examples/signature/factorizer_game.py b/examples/signature/factorizer_game.py index ad8ffe3b7..6f4ba48c7 100644 --- a/examples/signature/factorizer_game.py +++ b/examples/signature/factorizer_game.py @@ -47,7 +47,7 @@ def logicsig(a: int, p: int, q: int) -> Expr: """ Choices * (a, p, q) = (1, 5, 7) - * compiling on TEAL version 5 and + * compiling on program version 5 and * with assembleConstants = True results in Logic-Sig Contract Account Address: WO3TQD3WBSDKB6WEHUMSEBFH53GZVVXYGPWYDWKUZCKEXTVCDNDHJGG6II diff --git a/pyteal/__init__.py b/pyteal/__init__.py index ae30dd312..1d8d92f3d 100644 --- a/pyteal/__init__.py +++ b/pyteal/__init__.py @@ -6,6 +6,9 @@ MAX_TEAL_VERSION, MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, + MAX_PROGRAM_VERSION, + MIN_PROGRAM_VERSION, + DEFAULT_PROGRAM_VERSION, CompileOptions, compileTeal, OptimizeOptions, @@ -27,6 +30,9 @@ "MAX_TEAL_VERSION", "MIN_TEAL_VERSION", "DEFAULT_TEAL_VERSION", + "MAX_PROGRAM_VERSION", + "MIN_PROGRAM_VERSION", + "DEFAULT_PROGRAM_VERSION", "CompileOptions", "compileTeal", "OptimizeOptions", diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index a94633317..1ea51a5a1 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -9,6 +9,9 @@ from pyteal.compiler import ( MAX_TEAL_VERSION, MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, + MAX_PROGRAM_VERSION, + MIN_PROGRAM_VERSION, + DEFAULT_PROGRAM_VERSION, CompileOptions, compileTeal, OptimizeOptions, @@ -76,6 +79,7 @@ __all__ = [ "Concat", "Cond", "Continue", + "DEFAULT_PROGRAM_VERSION", "DEFAULT_TEAL_VERSION", "Div", "Divw", @@ -126,7 +130,9 @@ __all__ = [ "Log", "Lt", "MAX_GROUP_SIZE", + "MAX_PROGRAM_VERSION", "MAX_TEAL_VERSION", + "MIN_PROGRAM_VERSION", "MIN_TEAL_VERSION", "MaybeValue", "MethodSignature", diff --git a/pyteal/ast/acct_test.py b/pyteal/ast/acct_test.py index 52fc89132..ee60690d8 100644 --- a/pyteal/ast/acct_test.py +++ b/pyteal/ast/acct_test.py @@ -1,9 +1,9 @@ import pyteal as pt options = pt.CompileOptions() -teal4Options = pt.CompileOptions(version=4) -teal5Options = pt.CompileOptions(version=5) -teal6Options = pt.CompileOptions(version=6) +avm4Options = pt.CompileOptions(version=4) +avm5Options = pt.CompileOptions(version=5) +avm6Options = pt.CompileOptions(version=6) def test_acct_param_balance_valid(): @@ -21,7 +21,7 @@ def test_acct_param_balance_valid(): ] ) - actual, _ = expr.__teal__(teal6Options) + actual, _ = expr.__teal__(avm6Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -44,7 +44,7 @@ def test_acct_param_min_balance_valid(): ] ) - actual, _ = expr.__teal__(teal6Options) + actual, _ = expr.__teal__(avm6Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -67,7 +67,7 @@ def test_acct_param_auth_addr_valid(): ] ) - actual, _ = expr.__teal__(teal6Options) + actual, _ = expr.__teal__(avm6Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) diff --git a/pyteal/ast/app_test.py b/pyteal/ast/app_test.py index 79a6c1491..a74e66332 100644 --- a/pyteal/ast/app_test.py +++ b/pyteal/ast/app_test.py @@ -3,8 +3,8 @@ import pyteal as pt options = pt.CompileOptions() -teal4Options = pt.CompileOptions(version=4) -teal5Options = pt.CompileOptions(version=5) +avm4Options = pt.CompileOptions(version=4) +avm5Options = pt.CompileOptions(version=5) def test_on_complete(): @@ -258,7 +258,7 @@ def test_global_get_ex_direct_ref(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -439,7 +439,7 @@ def test_app_param_approval_program_valid(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -467,7 +467,7 @@ def test_app_param_clear_state_program_valid(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -495,7 +495,7 @@ def test_app_param_global_num_uint_valid(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -523,7 +523,7 @@ def test_app_param_global_num_byte_slice_valid(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -551,7 +551,7 @@ def test_app_param_local_num_uint_valid(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -579,7 +579,7 @@ def test_app_param_local_num_byte_slice_valid(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -607,7 +607,7 @@ def test_app_param_extra_programs_page_valid(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -635,7 +635,7 @@ def test_app_param_creator_valid(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -663,7 +663,7 @@ def test_app_param_address_valid(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) diff --git a/pyteal/ast/arg.py b/pyteal/ast/arg.py index 4c5697eda..25f7cb45c 100644 --- a/pyteal/ast/arg.py +++ b/pyteal/ast/arg.py @@ -2,7 +2,7 @@ from pyteal.types import TealType, require_type from pyteal.ir import TealOp, Op, TealBlock -from pyteal.errors import TealInputError, verifyTealVersion +from pyteal.errors import TealInputError, verifyProgramVersion from pyteal.ast.expr import Expr from pyteal.ast.leafexpr import LeafExpr @@ -21,7 +21,7 @@ def __init__(self, index: Union[int, Expr]) -> None: Args: index: The index of the argument to get. The index must be between 0 and 255 inclusive. - Starting in TEAL v5, the index may be a PyTeal expression that evaluates to uint64. + Starting in AVM v5, the index may be a PyTeal expression that evaluates to uint64. """ super().__init__() @@ -38,10 +38,10 @@ def __teal__(self, options: "CompileOptions"): op = TealOp(self, Op.arg, self.index) return TealBlock.FromOp(options, op) - verifyTealVersion( + verifyProgramVersion( Op.args.min_version, options.version, - "TEAL version too low to use dynamic indexes with Arg", + "Program version too low to use dynamic indexes with Arg", ) op = TealOp(self, Op.args) diff --git a/pyteal/ast/arg_test.py b/pyteal/ast/arg_test.py index 90cfc8929..b4feca2ad 100644 --- a/pyteal/ast/arg_test.py +++ b/pyteal/ast/arg_test.py @@ -2,9 +2,9 @@ import pyteal as pt -teal2Options = pt.CompileOptions(version=2) -teal4Options = pt.CompileOptions(version=4) -teal5Options = pt.CompileOptions(version=5) +avm2Options = pt.CompileOptions(version=2) +avm4Options = pt.CompileOptions(version=4) +avm5Options = pt.CompileOptions(version=5) def test_arg_static(): @@ -15,7 +15,7 @@ def test_arg_static(): expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.arg, i)]) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) assert actual == expected @@ -29,14 +29,14 @@ def test_arg_dynamic(): [pt.TealOp(i, pt.Op.int, 7), pt.TealOp(expr, pt.Op.args)] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal4Options) + expr.__teal__(avm4Options) def test_arg_invalid(): diff --git a/pyteal/ast/assert_test.py b/pyteal/ast/assert_test.py index fd6b756ab..1291a799c 100644 --- a/pyteal/ast/assert_test.py +++ b/pyteal/ast/assert_test.py @@ -2,8 +2,8 @@ import pyteal as pt -teal2Options = pt.CompileOptions(version=2) -teal3Options = pt.CompileOptions(version=3) +avm2Options = pt.CompileOptions(version=2) +avm3Options = pt.CompileOptions(version=3) def test_teal_2_assert(): @@ -11,13 +11,13 @@ def test_teal_2_assert(): expr = pt.Assert(arg) assert expr.type_of() == pt.TealType.none - expected, _ = arg.__teal__(teal2Options) + expected, _ = arg.__teal__(avm2Options) expectedBranch = pt.TealConditionalBlock([]) expectedBranch.setTrueBlock(pt.TealSimpleBlock([])) - expectedBranch.setFalseBlock(pt.Err().__teal__(teal2Options)[0]) + expectedBranch.setFalseBlock(pt.Err().__teal__(avm2Options)[0]) expected.setNextBlock(expectedBranch) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected @@ -32,7 +32,7 @@ def test_teal_3_assert(): [pt.TealOp(arg, pt.Op.int, 1), pt.TealOp(expr, pt.Op.assert_)] ) - actual, _ = expr.__teal__(teal3Options) + actual, _ = expr.__teal__(avm3Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) diff --git a/pyteal/ast/asset_test.py b/pyteal/ast/asset_test.py index 6ac9cf0e1..8bdaf57b1 100644 --- a/pyteal/ast/asset_test.py +++ b/pyteal/ast/asset_test.py @@ -2,9 +2,9 @@ import pyteal as pt -teal2Options = pt.CompileOptions() -teal4Options = pt.CompileOptions(version=4) -teal5Options = pt.CompileOptions(version=5) +avm2Options = pt.CompileOptions() +avm4Options = pt.CompileOptions(version=4) +avm5Options = pt.CompileOptions(version=5) def test_asset_holding_balance(): @@ -23,7 +23,7 @@ def test_asset_holding_balance(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -47,7 +47,7 @@ def test_asset_holding_balance_direct_ref(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -79,7 +79,7 @@ def test_asset_holding_frozen(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -103,7 +103,7 @@ def test_asset_holding_frozen_direct_ref(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -134,7 +134,7 @@ def test_asset_param_total(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -157,7 +157,7 @@ def test_asset_param_total_direct_ref(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -185,7 +185,7 @@ def test_asset_param_decimals(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -208,7 +208,7 @@ def test_asset_param_decimals_direct_ref(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -236,7 +236,7 @@ def test_asset_param_default_frozen(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -259,7 +259,7 @@ def test_asset_param_default_frozen_direct_ref(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -287,7 +287,7 @@ def test_asset_param_unit_name(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -310,7 +310,7 @@ def test_asset_param_unit_name_direct_ref(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -338,7 +338,7 @@ def test_asset_param_name(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -361,7 +361,7 @@ def test_asset_param_name_direct_ref(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -389,7 +389,7 @@ def test_asset_param_url(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -412,7 +412,7 @@ def test_asset_param_url_direct_ref(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -440,7 +440,7 @@ def test_asset_param_metadata_hash(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -463,7 +463,7 @@ def test_asset_param_metadata_hash_direct_ref(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -491,7 +491,7 @@ def test_asset_param_manager(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -514,7 +514,7 @@ def test_asset_param_manager_direct_ref(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -542,7 +542,7 @@ def test_asset_param_reserve(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -565,7 +565,7 @@ def test_asset_param_reserve_direct_ref(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -593,7 +593,7 @@ def test_asset_param_freeze(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -616,7 +616,7 @@ def test_asset_param_freeze_direct_ref(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -644,7 +644,7 @@ def test_asset_param_clawback(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -667,7 +667,7 @@ def test_asset_param_clawback_direct_ref(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -695,7 +695,7 @@ def test_asset_param_creator_valid(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) diff --git a/pyteal/ast/base64decode.py b/pyteal/ast/base64decode.py index 7dcf47c18..be850a001 100644 --- a/pyteal/ast/base64decode.py +++ b/pyteal/ast/base64decode.py @@ -5,7 +5,6 @@ from pyteal.errors import verifyFieldVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.ast.expr import Expr -from pyteal.ast.leafexpr import LeafExpr if TYPE_CHECKING: from pyteal.compiler import CompileOptions @@ -27,7 +26,7 @@ def __init__(self, id: int, name: str, min_version: int) -> None: Base64Encoding.__module__ = "pyteal" -class Base64Decode(LeafExpr): +class Base64Decode(Expr): """An expression that decodes a base64-encoded byte string according to a specific encoding. See [RFC 4648](https://rfc-editor.org/rfc/rfc4648.html#section-4) (sections 4 and 5) for information on specifications. @@ -36,6 +35,8 @@ class Base64Decode(LeafExpr): When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of \\n and \\r are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of =, \\r, or \\n. + + NOTE: Base64Decode usage is not intended for introducing constants. Instead, use :any:`Bytes`. """ def __init__(self, encoding: Base64Encoding, base64: Expr) -> None: @@ -59,8 +60,11 @@ def __str__(self): def type_of(self): return TealType.bytes + def has_return(self): + return False + @classmethod - def url(cls, base64: Expr) -> "Base64Decode": + def url(cls, base64: Expr) -> Expr: """Decode a base64-encoded byte string according to the URL encoding. Refer to the `Base64Decode` class documentation for more information. @@ -71,7 +75,7 @@ def url(cls, base64: Expr) -> "Base64Decode": return cls(Base64Encoding.url, base64) @classmethod - def std(cls, base64: Expr) -> "Base64Decode": + def std(cls, base64: Expr) -> Expr: """Decode a base64-encoded byte string according to the Standard encoding. Refer to the `Base64Decode` class documentation for more information. diff --git a/pyteal/ast/base64decode_test.py b/pyteal/ast/base64decode_test.py index 14eb48799..724dbc4aa 100644 --- a/pyteal/ast/base64decode_test.py +++ b/pyteal/ast/base64decode_test.py @@ -2,8 +2,8 @@ import pyteal as pt -teal6Options = pt.CompileOptions(version=6) -teal7Options = pt.CompileOptions(version=7) +avm6Options = pt.CompileOptions(version=6) +avm7Options = pt.CompileOptions(version=7) def test_base64decode_std(): @@ -18,14 +18,14 @@ def test_base64decode_std(): ] ) - actual, _ = expr.__teal__(teal7Options) + actual, _ = expr.__teal__(avm7Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal6Options) + expr.__teal__(avm6Options) def test_base64decode_url(): @@ -40,14 +40,14 @@ def test_base64decode_url(): ] ) - actual, _ = expr.__teal__(teal7Options) + actual, _ = expr.__teal__(avm7Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal6Options) + expr.__teal__(avm6Options) def test_base64decode_invalid(): diff --git a/pyteal/ast/binaryexpr.py b/pyteal/ast/binaryexpr.py index c6f879f7c..7b2ebebe2 100644 --- a/pyteal/ast/binaryexpr.py +++ b/pyteal/ast/binaryexpr.py @@ -1,7 +1,7 @@ from typing import Union, Tuple, cast, TYPE_CHECKING from pyteal.types import TealType, require_type -from pyteal.errors import verifyTealVersion +from pyteal.errors import verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.ast.expr import Expr @@ -35,10 +35,10 @@ def __init__( self.argRight = argRight def __teal__(self, options: "CompileOptions"): - verifyTealVersion( + verifyProgramVersion( self.op.min_version, options.version, - "TEAL version too low to use op {}".format(self.op), + "Program version too low to use op {}".format(self.op), ) return TealBlock.FromOp( @@ -123,7 +123,7 @@ def Exp(a: Expr, b: Expr) -> BinaryExpr: Produces a ** b. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. Args: a: Must evaluate to uint64. @@ -173,7 +173,7 @@ def ShiftLeft(a: Expr, b: Expr) -> BinaryExpr: Produces a << b. This is equivalent to a times 2^b, modulo 2^64. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. Args: a: Must evaluate to uint64. @@ -187,7 +187,7 @@ def ShiftRight(a: Expr, b: Expr) -> BinaryExpr: Produces a >> b. This is equivalent to a divided by 2^b. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. Args: a: Must evaluate to uint64. @@ -281,7 +281,7 @@ def GetBit(value: Expr, index: Expr) -> BinaryExpr: yields 1. Any index less than 4 would yield 1, and any valid index 4 or greater would yield 0. Any integer less than 8*Len(value) is a valid index. - Requires TEAL version 3 or higher. + Requires program version 3 or higher. Args: value: The value containing bits. Can evaluate to any type. @@ -298,7 +298,7 @@ def GetByte(value: Expr, index: Expr) -> BinaryExpr: Similar to GetBit, indexing begins at the first byte. For example, :code:`GetByte(Bytes("base16", "0xff0000"), Int(0))` yields 255. Any other valid index would yield 0. - Requires TEAL version 3 or higher. + Requires program version 3 or higher. Args: value: The value containing the bytes. Must evaluate to bytes. @@ -315,7 +315,7 @@ def BytesAdd(left: Expr, right: Expr) -> BinaryExpr: Produces left + right, where left and right are interpreted as big-endian unsigned integers. Arguments must not exceed 64 bytes. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. Args: left: Must evaluate to bytes. @@ -330,7 +330,7 @@ def BytesMinus(left: Expr, right: Expr) -> BinaryExpr: Produces left - right, where left and right are interpreted as big-endian unsigned integers. Arguments must not exceed 64 bytes. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. Args: left: Must evaluate to bytes. @@ -347,7 +347,7 @@ def BytesDiv(left: Expr, right: Expr) -> BinaryExpr: Panics if right is 0. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. Args: left: Must evaluate to bytes. @@ -362,7 +362,7 @@ def BytesMul(left: Expr, right: Expr) -> BinaryExpr: Produces left * right, where left and right are interpreted as big-endian unsigned integers. Arguments must not exceed 64 bytes. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. Args: left: Must evaluate to bytes. @@ -379,7 +379,7 @@ def BytesMod(left: Expr, right: Expr) -> BinaryExpr: Panics if right is 0. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. Args: left: Must evaluate to bytes. @@ -395,7 +395,7 @@ def BytesAnd(left: Expr, right: Expr) -> BinaryExpr: Left and right are zero-left extended to the greater of their lengths. Arguments must not exceed 64 bytes. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. Args: left: Must evaluate to bytes. @@ -411,7 +411,7 @@ def BytesOr(left: Expr, right: Expr) -> BinaryExpr: Left and right are zero-left extended to the greater of their lengths. Arguments must not exceed 64 bytes. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. Args: left: Must evaluate to bytes. @@ -427,7 +427,7 @@ def BytesXor(left: Expr, right: Expr) -> BinaryExpr: Left and right are zero-left extended to the greater of their lengths. Arguments must not exceed 64 bytes. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. Args: left: Must evaluate to bytes. @@ -442,7 +442,7 @@ def BytesEq(left: Expr, right: Expr) -> BinaryExpr: Checks if left == right, where left and right are interpreted as big-endian unsigned integers. Arguments must not exceed 64 bytes. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. Args: left: Must evaluate to bytes. @@ -457,7 +457,7 @@ def BytesNeq(left: Expr, right: Expr) -> BinaryExpr: Checks if left != right, where left and right are interpreted as big-endian unsigned integers. Arguments must not exceed 64 bytes. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. Args: left: Must evaluate to bytes. @@ -472,7 +472,7 @@ def BytesLt(left: Expr, right: Expr) -> BinaryExpr: Checks if left < right, where left and right are interpreted as big-endian unsigned integers. Arguments must not exceed 64 bytes. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. Args: left: Must evaluate to bytes. @@ -487,7 +487,7 @@ def BytesLe(left: Expr, right: Expr) -> BinaryExpr: Checks if left <= right, where left and right are interpreted as big-endian unsigned integers. Arguments must not exceed 64 bytes. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. Args: left: Must evaluate to bytes. @@ -502,7 +502,7 @@ def BytesGt(left: Expr, right: Expr) -> BinaryExpr: Checks if left > right, where left and right are interpreted as big-endian unsigned integers. Arguments must not exceed 64 bytes. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. Args: left: Must evaluate to bytes. @@ -517,7 +517,7 @@ def BytesGe(left: Expr, right: Expr) -> BinaryExpr: Checks if left >= right, where left and right are interpreted as big-endian unsigned integers. Arguments must not exceed 64 bytes. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. Args: left: Must evaluate to bytes. @@ -534,7 +534,7 @@ def ExtractUint16(string: Expr, offset: Expr) -> BinaryExpr: If :code:`offset + 2` exceeds :code:`Len(string)`, the program fails. - Requires TEAL version 5 or higher. + Requires program version 5 or higher. Args: string: The bytestring to extract from. Must evaluate to bytes. @@ -557,7 +557,7 @@ def ExtractUint32(string: Expr, offset: Expr) -> BinaryExpr: If :code:`offset + 4` exceeds :code:`Len(string)`, the program fails. - Requires TEAL version 5 or higher. + Requires program version 5 or higher. Args: string: The bytestring to extract from. Must evaluate to bytes. @@ -580,7 +580,7 @@ def ExtractUint64(string: Expr, offset: Expr) -> BinaryExpr: If :code:`offset + 8` exceeds :code:`Len(string)`, the program fails. - Requires TEAL version 5 or higher. + Requires program version 5 or higher. Args: string: The bytestring to extract from. Must evaluate to bytes. diff --git a/pyteal/ast/binaryexpr_test.py b/pyteal/ast/binaryexpr_test.py index a1b493365..1d050fd1e 100644 --- a/pyteal/ast/binaryexpr_test.py +++ b/pyteal/ast/binaryexpr_test.py @@ -2,10 +2,10 @@ import pyteal as pt -teal2Options = pt.CompileOptions(version=2) -teal3Options = pt.CompileOptions(version=3) -teal4Options = pt.CompileOptions(version=4) -teal5Options = pt.CompileOptions(version=5) +avm2Options = pt.CompileOptions(version=2) +avm3Options = pt.CompileOptions(version=3) +avm4Options = pt.CompileOptions(version=4) +avm5Options = pt.CompileOptions(version=5) def test_add(): @@ -21,7 +21,7 @@ def test_add(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -43,7 +43,7 @@ def test_add_overload(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -72,7 +72,7 @@ def test_minus(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -94,7 +94,7 @@ def test_minus_overload(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -123,7 +123,7 @@ def test_mul(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -145,7 +145,7 @@ def test_mul_overload(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -174,7 +174,7 @@ def test_div(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -196,7 +196,7 @@ def test_div_overload(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -225,7 +225,7 @@ def test_mod(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -247,7 +247,7 @@ def test_mod_overload(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -276,14 +276,14 @@ def test_exp(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_exp_overload(): @@ -302,7 +302,7 @@ def test_exp_overload(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -310,7 +310,7 @@ def test_exp_overload(): assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_exp_invalid(): @@ -342,7 +342,7 @@ def test_arithmetic(): ] ) - actual, _ = v.__teal__(teal2Options) + actual, _ = v.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -363,7 +363,7 @@ def test_bitwise_and(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -385,7 +385,7 @@ def test_bitwise_and_overload(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -414,7 +414,7 @@ def test_bitwise_or(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -436,7 +436,7 @@ def test_bitwise_or_overload(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -465,7 +465,7 @@ def test_bitwise_xor(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -487,7 +487,7 @@ def test_bitwise_xor_overload(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -516,14 +516,14 @@ def test_shift_left(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_shift_left_overload(): @@ -541,7 +541,7 @@ def test_shift_left_overload(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -549,7 +549,7 @@ def test_shift_left_overload(): assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_shift_left_invalid(): @@ -573,14 +573,14 @@ def test_shift_right(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_shift_right_overload(): @@ -598,7 +598,7 @@ def test_shift_right_overload(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -606,7 +606,7 @@ def test_shift_right_overload(): assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_shift_right_invalid(): @@ -630,7 +630,7 @@ def test_eq(): ] ) - actual_int, _ = expr_int.__teal__(teal2Options) + actual_int, _ = expr_int.__teal__(avm2Options) actual_int.addIncoming() actual_int = pt.TealBlock.NormalizeBlocks(actual_int) @@ -648,7 +648,7 @@ def test_eq(): ] ) - actual_bytes, _ = expr_bytes.__teal__(teal2Options) + actual_bytes, _ = expr_bytes.__teal__(avm2Options) actual_bytes.addIncoming() actual_bytes = pt.TealBlock.NormalizeBlocks(actual_bytes) @@ -668,7 +668,7 @@ def test_eq_overload(): ] ) - actual_int, _ = expr_int.__teal__(teal2Options) + actual_int, _ = expr_int.__teal__(avm2Options) actual_int.addIncoming() actual_int = pt.TealBlock.NormalizeBlocks(actual_int) @@ -686,7 +686,7 @@ def test_eq_overload(): ] ) - actual_bytes, _ = expr_bytes.__teal__(teal2Options) + actual_bytes, _ = expr_bytes.__teal__(avm2Options) actual_bytes.addIncoming() actual_bytes = pt.TealBlock.NormalizeBlocks(actual_bytes) @@ -714,7 +714,7 @@ def test_neq(): ] ) - actual_int, _ = expr_int.__teal__(teal2Options) + actual_int, _ = expr_int.__teal__(avm2Options) actual_int.addIncoming() actual_int = pt.TealBlock.NormalizeBlocks(actual_int) @@ -732,7 +732,7 @@ def test_neq(): ] ) - actual_bytes, _ = expr_bytes.__teal__(teal2Options) + actual_bytes, _ = expr_bytes.__teal__(avm2Options) actual_bytes.addIncoming() actual_bytes = pt.TealBlock.NormalizeBlocks(actual_bytes) @@ -752,7 +752,7 @@ def test_neq_overload(): ] ) - actual_int, _ = expr_int.__teal__(teal2Options) + actual_int, _ = expr_int.__teal__(avm2Options) actual_int.addIncoming() actual_int = pt.TealBlock.NormalizeBlocks(actual_int) @@ -770,7 +770,7 @@ def test_neq_overload(): ] ) - actual_bytes, _ = expr_bytes.__teal__(teal2Options) + actual_bytes, _ = expr_bytes.__teal__(avm2Options) actual_bytes.addIncoming() actual_bytes = pt.TealBlock.NormalizeBlocks(actual_bytes) @@ -798,7 +798,7 @@ def test_lt(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -818,7 +818,7 @@ def test_lt_overload(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -846,7 +846,7 @@ def test_le(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -866,7 +866,7 @@ def test_le_overload(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -894,7 +894,7 @@ def test_gt(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -914,7 +914,7 @@ def test_gt_overload(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -942,7 +942,7 @@ def test_ge(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -962,7 +962,7 @@ def test_ge_overload(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -990,14 +990,14 @@ def test_get_bit_int(): ] ) - actual, _ = expr.__teal__(teal3Options) + actual, _ = expr.__teal__(avm3Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal2Options) + expr.__teal__(avm2Options) def test_get_bit_bytes(): @@ -1013,14 +1013,14 @@ def test_get_bit_bytes(): ] ) - actual, _ = expr.__teal__(teal3Options) + actual, _ = expr.__teal__(avm3Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal2Options) + expr.__teal__(avm2Options) def test_get_bit_invalid(): @@ -1044,14 +1044,14 @@ def test_get_byte(): ] ) - actual, _ = expr.__teal__(teal3Options) + actual, _ = expr.__teal__(avm3Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal2Options) + expr.__teal__(avm2Options) def test_get_byte_invalid(): @@ -1078,14 +1078,14 @@ def test_b_add(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_b_add_invalid(): @@ -1112,14 +1112,14 @@ def test_b_minus(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_b_minus_invalid(): @@ -1143,14 +1143,14 @@ def test_b_div(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_b_div_invalid(): @@ -1174,14 +1174,14 @@ def test_b_mul(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_b_mul_invalid(): @@ -1205,14 +1205,14 @@ def test_b_mod(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_b_mod_invalid(): @@ -1236,14 +1236,14 @@ def test_b_and(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_b_and_invalid(): @@ -1267,14 +1267,14 @@ def test_b_or(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_b_or_invalid(): @@ -1298,14 +1298,14 @@ def test_b_xor(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_b_xor_invalid(): @@ -1332,14 +1332,14 @@ def test_b_eq(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_b_eq_invalid(): @@ -1366,14 +1366,14 @@ def test_b_neq(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_b_neq_invalid(): @@ -1400,14 +1400,14 @@ def test_b_lt(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_b_lt_invalid(): @@ -1434,14 +1434,14 @@ def test_b_le(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_b_le_invalid(): @@ -1468,14 +1468,14 @@ def test_b_gt(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_b_gt_invalid(): @@ -1502,14 +1502,14 @@ def test_b_ge(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_b_ge_invalid(): @@ -1541,14 +1541,14 @@ def test_extract_uint(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal4Options) + expr.__teal__(avm4Options) def test_extract_uint_invalid(): diff --git a/pyteal/ast/block.py b/pyteal/ast/block.py index 041483aae..775f1593c 100644 --- a/pyteal/ast/block.py +++ b/pyteal/ast/block.py @@ -55,7 +55,7 @@ def type_of(self): return self.field.type_of() @classmethod - def seed(cls, block: Expr) -> "Block": + def seed(cls, block: Expr) -> Expr: """Get the seed of a block. Args: @@ -66,7 +66,7 @@ def seed(cls, block: Expr) -> "Block": return cls(BlockField.block_seed, block) @classmethod - def timestamp(cls, block: Expr) -> "Block": + def timestamp(cls, block: Expr) -> Expr: """Get the timestamp of a block. Args: diff --git a/pyteal/ast/block_test.py b/pyteal/ast/block_test.py index 0cd571063..e55ddf319 100644 --- a/pyteal/ast/block_test.py +++ b/pyteal/ast/block_test.py @@ -2,8 +2,8 @@ import pyteal as pt -teal6Options = pt.CompileOptions(version=6) -teal7Options = pt.CompileOptions(version=7) +avm6Options = pt.CompileOptions(version=6) +avm7Options = pt.CompileOptions(version=7) def test_block_seed(): @@ -18,14 +18,14 @@ def test_block_seed(): ] ) - actual, _ = expr.__teal__(teal7Options) + actual, _ = expr.__teal__(avm7Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal6Options) + expr.__teal__(avm6Options) def test_block_seed_invalid(): @@ -45,14 +45,14 @@ def test_block_timestamp(): ] ) - actual, _ = expr.__teal__(teal7Options) + actual, _ = expr.__teal__(avm7Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal6Options) + expr.__teal__(avm6Options) def test_block_timestamp_invalid(): diff --git a/pyteal/ast/box.py b/pyteal/ast/box.py index 33b9712e3..368c001e0 100644 --- a/pyteal/ast/box.py +++ b/pyteal/ast/box.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING from pyteal.ast.maybe import MaybeValue -from pyteal.errors import verifyTealVersion +from pyteal.errors import verifyProgramVersion from pyteal.types import TealType, require_type from pyteal.ir import TealOp, Op, TealBlock @@ -27,7 +27,7 @@ def __init__(self, name: Expr, size: Expr) -> None: self.size = size def __teal__(self, options: "CompileOptions"): - verifyTealVersion( + verifyProgramVersion( minVersion=Op.box_create.min_version, version=options.version, msg=f"{Op.box_create} unavailable", @@ -62,7 +62,7 @@ def __init__(self, name: Expr) -> None: self.name = name def __teal__(self, options: "CompileOptions"): - verifyTealVersion( + verifyProgramVersion( minVersion=Op.box_del.min_version, version=options.version, msg=f"{Op.box_del} unavailable", @@ -101,7 +101,7 @@ def __init__(self, name: Expr, start: Expr, value: Expr) -> None: self.value = value def __teal__(self, options: "CompileOptions"): - verifyTealVersion( + verifyProgramVersion( minVersion=Op.box_replace.min_version, version=options.version, msg=f"{Op.box_replace} unavailable", @@ -143,7 +143,7 @@ def __init__(self, name: Expr, start: Expr, length: Expr) -> None: self.length = length def __teal__(self, options: "CompileOptions"): - verifyTealVersion( + verifyProgramVersion( minVersion=Op.box_extract.min_version, version=options.version, msg=f"{Op.box_extract} unavailable", @@ -204,7 +204,7 @@ def __init__(self, name: Expr, value: Expr) -> None: self.value = value def __teal__(self, options: "CompileOptions"): - verifyTealVersion( + verifyProgramVersion( minVersion=Op.box_put.min_version, version=options.version, msg=f"{Op.box_put} unavailable", diff --git a/pyteal/ast/box_test.py b/pyteal/ast/box_test.py index 87968ce2f..4000b3974 100644 --- a/pyteal/ast/box_test.py +++ b/pyteal/ast/box_test.py @@ -3,8 +3,8 @@ import pytest import pyteal as pt -teal7Options = pt.CompileOptions(version=7) -teal8Options = pt.CompileOptions(version=8) +avm7Options = pt.CompileOptions(version=7) +avm8Options = pt.CompileOptions(version=8) POSITIVE_TEST_CASES: list[Tuple[pt.Expr, pt.TealType]] = [ (pt.BoxCreate(pt.Bytes("box"), pt.Int(10)), pt.TealType.none), @@ -23,9 +23,9 @@ @pytest.mark.parametrize("test_case, test_case_type", POSITIVE_TEST_CASES) def test_compile_version_and_type(test_case, test_case_type): with pytest.raises(pt.TealInputError): - test_case.__teal__(teal7Options) + test_case.__teal__(avm7Options) - test_case.__teal__(teal8Options) + test_case.__teal__(avm8Options) assert test_case.type_of() == test_case_type assert not test_case.has_return() @@ -62,7 +62,7 @@ def test_box_create_compile(): pt.TealOp(expr, pt.Op.box_create), ] ) - actual, _ = expr.__teal__(teal8Options) + actual, _ = expr.__teal__(avm8Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -76,7 +76,7 @@ def test_box_delete_compile(): expected = pt.TealSimpleBlock( [pt.TealOp(name_arg, pt.Op.byte, '"eineName"'), pt.TealOp(expr, pt.Op.box_del)] ) - actual, _ = expr.__teal__(teal8Options) + actual, _ = expr.__teal__(avm8Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -97,7 +97,7 @@ def test_box_extract(): pt.TealOp(expr, pt.Op.box_extract), ] ) - actual, _ = expr.__teal__(teal8Options) + actual, _ = expr.__teal__(avm8Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -118,7 +118,7 @@ def test_box_replace(): pt.TealOp(expr, pt.Op.box_replace), ] ) - actual, _ = expr.__teal__(teal8Options) + actual, _ = expr.__teal__(avm8Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -137,7 +137,7 @@ def test_box_length(): pt.TealOp(expr.output_slots[0].store(), pt.Op.store, expr.output_slots[0]), ] ) - actual, _ = expr.__teal__(teal8Options) + actual, _ = expr.__teal__(avm8Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -157,7 +157,7 @@ def test_box_get(): pt.TealOp(expr.output_slots[0].store(), pt.Op.store, expr.output_slots[0]), ] ) - actual, _ = expr.__teal__(teal8Options) + actual, _ = expr.__teal__(avm8Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -177,7 +177,7 @@ def test_box_put(): pt.TealOp(expr, pt.Op.box_put), ] ) - actual, _ = expr.__teal__(teal8Options) + actual, _ = expr.__teal__(avm8Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) diff --git a/pyteal/ast/ecdsa.py b/pyteal/ast/ecdsa.py index 06e4e49db..b71e7ae46 100644 --- a/pyteal/ast/ecdsa.py +++ b/pyteal/ast/ecdsa.py @@ -2,7 +2,12 @@ from typing import Tuple, TYPE_CHECKING from pyteal.ast import Expr, MultiValue -from pyteal.errors import TealTypeError, verifyFieldVersion, verifyTealVersion +from pyteal.errors import ( + TealTypeError, + verifyFieldVersion, + verifyProgramVersion, + TealInputError, +) from pyteal.ir import Op, TealBlock, TealOp from pyteal.types import TealType, require_type @@ -52,10 +57,10 @@ def __init__( self.args = [data, sigA, sigB, pkX, pkY] def __teal__(self, options: "CompileOptions"): - verifyTealVersion( + verifyProgramVersion( self.op.min_version, options.version, - "TEAL version too low to use op {}".format(self.op), + "Program version too low to use op {}".format(self.op), ) verifyFieldVersion(self.curve.arg_name, self.curve.min_version, options.version) @@ -142,7 +147,7 @@ def EcdsaDecompress(curve: EcdsaCurve, compressed_pk: Expr) -> MultiValue: def EcdsaRecover( curve: EcdsaCurve, data: Expr, recovery_id: Expr, sigA: Expr, sigB: Expr ) -> MultiValue: - """Reover an ECDSA public key from a signature. + """Recover an ECDSA public key from a signature. All byte arguments must be big endian encoded. Args: curve: Enum representing the ECDSA curve used for the public key @@ -158,6 +163,9 @@ def EcdsaRecover( if not isinstance(curve, EcdsaCurve): raise TealTypeError(curve, EcdsaCurve) + if curve != EcdsaCurve.Secp256k1: + raise TealInputError("Recover only supports Secp256k1") + require_type(data, TealType.bytes) require_type(recovery_id, TealType.uint64) require_type(sigA, TealType.bytes) diff --git a/pyteal/ast/ecdsa_test.py b/pyteal/ast/ecdsa_test.py index 03cec2207..c6dc1bdb1 100644 --- a/pyteal/ast/ecdsa_test.py +++ b/pyteal/ast/ecdsa_test.py @@ -3,13 +3,13 @@ import pyteal as pt -teal4Options = pt.CompileOptions(version=4) -teal5Options = pt.CompileOptions(version=5) -teal7Options = pt.CompileOptions(version=7) +avm4Options = pt.CompileOptions(version=4) +avm5Options = pt.CompileOptions(version=5) +avm7Options = pt.CompileOptions(version=7) curve_options_map = { - pt.EcdsaCurve.Secp256k1: teal5Options, - pt.EcdsaCurve.Secp256r1: teal7Options, + pt.EcdsaCurve.Secp256k1: avm5Options, + pt.EcdsaCurve.Secp256r1: avm7Options, } @@ -54,45 +54,51 @@ def test_ecdsa_decompress(curve: pt.EcdsaCurve): @pytest.mark.parametrize("curve", [pt.EcdsaCurve.Secp256k1, pt.EcdsaCurve.Secp256r1]) def test_ecdsa_recover(curve: pt.EcdsaCurve): - args = [pt.Bytes("data"), pt.Int(1), pt.Bytes("sigA"), pt.Bytes("sigB")] - pubkey = pt.EcdsaRecover(curve, args[0], args[1], args[2], args[3]) - assert pubkey.type_of() == pt.TealType.none - - expected = pt.TealSimpleBlock( - [ - pt.TealOp(args[0], pt.Op.byte, '"data"'), - pt.TealOp(args[1], pt.Op.int, 1), - pt.TealOp(args[2], pt.Op.byte, '"sigA"'), - pt.TealOp(args[3], pt.Op.byte, '"sigB"'), - pt.TealOp(pubkey, pt.Op.ecdsa_pk_recover, curve.arg_name), - pt.TealOp( - pubkey.output_slots[1].store(), pt.Op.store, pubkey.output_slots[1] - ), - pt.TealOp( - pubkey.output_slots[0].store(), pt.Op.store, pubkey.output_slots[0] - ), - ] - ) + if curve != pt.EcdsaCurve.Secp256k1: + with pytest.raises(pt.TealInputError): + pt.EcdsaRecover( + curve, pt.Bytes("data"), pt.Int(1), pt.Bytes("sigA"), pt.Bytes("sigB") + ) + else: + args = [pt.Bytes("data"), pt.Int(1), pt.Bytes("sigA"), pt.Bytes("sigB")] + pubkey = pt.EcdsaRecover(curve, args[0], args[1], args[2], args[3]) + assert pubkey.type_of() == pt.TealType.none + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(args[0], pt.Op.byte, '"data"'), + pt.TealOp(args[1], pt.Op.int, 1), + pt.TealOp(args[2], pt.Op.byte, '"sigA"'), + pt.TealOp(args[3], pt.Op.byte, '"sigB"'), + pt.TealOp(pubkey, pt.Op.ecdsa_pk_recover, curve.arg_name), + pt.TealOp( + pubkey.output_slots[1].store(), pt.Op.store, pubkey.output_slots[1] + ), + pt.TealOp( + pubkey.output_slots[0].store(), pt.Op.store, pubkey.output_slots[0] + ), + ] + ) - actual, _ = pubkey.__teal__(curve_options_map[curve]) - actual.addIncoming() - actual = pt.TealBlock.NormalizeBlocks(actual) + actual, _ = pubkey.__teal__(curve_options_map[curve]) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) - with pt.TealComponent.Context.ignoreExprEquality(): - assert actual == expected + with pt.TealComponent.Context.ignoreExprEquality(): + assert actual == expected - # compile without errors this is necessary so assembly is also tested - pt.compileTeal( - pt.Seq(pubkey, pt.Approve()), pt.Mode.Application, version=curve.min_version - ) - - with pytest.raises(pt.TealInputError): + # compile without errors this is necessary so assembly is also tested pt.compileTeal( - pt.Seq(pubkey, pt.Approve()), - pt.Mode.Application, - version=curve.min_version - 1, + pt.Seq(pubkey, pt.Approve()), pt.Mode.Application, version=curve.min_version ) + with pytest.raises(pt.TealInputError): + pt.compileTeal( + pt.Seq(pubkey, pt.Approve()), + pt.Mode.Application, + version=curve.min_version - 1, + ) + @pytest.mark.parametrize("curve", [pt.EcdsaCurve.Secp256k1, pt.EcdsaCurve.Secp256r1]) def test_ecdsa_verify_basic(curve: pt.EcdsaCurve): @@ -186,8 +192,8 @@ def test_ecdsa_verify_compressed_pk(curve: pt.EcdsaCurve): ) -@pytest.mark.parametrize("curve", [pt.EcdsaCurve.Secp256k1, pt.EcdsaCurve.Secp256r1]) -def test_ecdsa_verify_recovered_pk(curve: pt.EcdsaCurve): +def test_ecdsa_verify_recovered_pk(): + curve = pt.EcdsaCurve.Secp256k1 args = [pt.Bytes("data"), pt.Int(1), pt.Bytes("sigA"), pt.Bytes("sigB")] pubkey = pt.EcdsaRecover(curve, args[0], args[1], args[2], args[3]) expr = pt.EcdsaVerify(curve, args[0], args[2], args[3], pubkey) @@ -243,14 +249,15 @@ def test_ecdsa_verify_recovered_pk(curve: pt.EcdsaCurve): @pytest.mark.parametrize("curve", [pt.EcdsaCurve.Secp256k1, pt.EcdsaCurve.Secp256r1]) def test_ecdsa_invalid(curve: pt.EcdsaCurve): - with pytest.raises(pt.TealTypeError): - args: List[Union[pt.Bytes, pt.Int]] = [ - pt.Bytes("data"), - pt.Bytes("1"), - pt.Bytes("sigA"), - pt.Bytes("sigB"), - ] - pt.EcdsaRecover(curve, args[0], args[1], args[2], args[3]) + if curve == pt.EcdsaCurve.Secp256k1: + with pytest.raises(pt.TealTypeError): + args: List[Union[pt.Bytes, pt.Int]] = [ + pt.Bytes("data"), + pt.Bytes("1"), + pt.Bytes("sigA"), + pt.Bytes("sigB"), + ] + pt.EcdsaRecover(curve, args[0], args[1], args[2], args[3]) with pytest.raises(pt.TealTypeError): pt.EcdsaDecompress(curve, pt.Int(1)) @@ -284,7 +291,7 @@ def test_ecdsa_invalid(curve: pt.EcdsaCurve): pubkey = (pt.Bytes("X"), pt.Bytes("Y")) expr = pt.EcdsaVerify(curve, args[0], args[1], args[2], pubkey) - expr.__teal__(teal4Options) + expr.__teal__(avm4Options) with pytest.raises(pt.TealTypeError): args = [pt.Bytes("data"), pt.Bytes("sigA"), pt.Bytes("sigB")] diff --git a/pyteal/ast/gaid.py b/pyteal/ast/gaid.py index d9faa6128..371aa86ac 100644 --- a/pyteal/ast/gaid.py +++ b/pyteal/ast/gaid.py @@ -2,7 +2,7 @@ from pyteal.types import TealType, require_type from pyteal.ir import TealOp, Op, TealBlock -from pyteal.errors import TealInputError, verifyTealVersion +from pyteal.errors import TealInputError, verifyProgramVersion from pyteal.config import MAX_GROUP_SIZE from pyteal.ast.expr import Expr from pyteal.ast.leafexpr import LeafExpr @@ -17,7 +17,7 @@ class GeneratedID(LeafExpr): def __init__(self, txnIndex: Union[int, Expr]) -> None: """Create an expression to extract the created ID from a transaction in the current group. - Requires TEAL version 4 or higher. This operation is only permitted in application mode. + Requires program version 4 or higher. This operation is only permitted in application mode. Args: txnIndex: The index of the transaction from which the created ID should be obtained. @@ -41,10 +41,10 @@ def __str__(self): return "(Gaid {})".format(self.txnIndex) def __teal__(self, options: "CompileOptions"): - verifyTealVersion( + verifyProgramVersion( Op.gaid.min_version, options.version, - "TEAL version too low to use Gaid expression", + "Program version too low to use Gaid expression", ) if type(self.txnIndex) is int: diff --git a/pyteal/ast/gaid_test.py b/pyteal/ast/gaid_test.py index 9da4fe254..51e896200 100644 --- a/pyteal/ast/gaid_test.py +++ b/pyteal/ast/gaid_test.py @@ -2,13 +2,13 @@ import pyteal as pt -teal3Options = pt.CompileOptions(version=3) -teal4Options = pt.CompileOptions(version=4) +avm3Options = pt.CompileOptions(version=3) +avm4Options = pt.CompileOptions(version=4) def test_gaid_teal_3(): with pytest.raises(pt.TealInputError): - pt.GeneratedID(0).__teal__(teal3Options) + pt.GeneratedID(0).__teal__(avm3Options) def test_gaid(): @@ -17,7 +17,7 @@ def test_gaid(): expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.gaid, 0)]) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) assert actual == expected @@ -32,7 +32,7 @@ def test_gaid_invalid(): def test_gaid_dynamic_teal_3(): with pytest.raises(pt.TealInputError): - pt.GeneratedID(pt.Int(0)).__teal__(teal3Options) + pt.GeneratedID(pt.Int(0)).__teal__(avm3Options) def test_gaid_dynamic(): @@ -44,7 +44,7 @@ def test_gaid_dynamic(): [pt.TealOp(arg, pt.Op.int, 0), pt.TealOp(expr, pt.Op.gaids)] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) diff --git a/pyteal/ast/gitxn.py b/pyteal/ast/gitxn.py index 486120e07..ad6c5aa06 100644 --- a/pyteal/ast/gitxn.py +++ b/pyteal/ast/gitxn.py @@ -2,7 +2,7 @@ from pyteal.config import MAX_GROUP_SIZE -from pyteal.errors import TealInputError, verifyFieldVersion, verifyTealVersion +from pyteal.errors import TealInputError, verifyFieldVersion, verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.ast.expr import Expr from pyteal.ast.txn import TxnExpr, TxnField, TxnObject, TxnaExpr @@ -33,10 +33,10 @@ def __str__(self): def __teal__(self, options: "CompileOptions"): verifyFieldVersion(self.field.arg_name, self.field.min_version, options.version) - verifyTealVersion( + verifyProgramVersion( Op.gitxn.min_version, options.version, - "TEAL version too low to use gitxn", + "Program version too low to use gitxn", ) op = TealOp(self, Op.gitxn, self.txnIndex, self.field.arg_name) return TealBlock.FromOp(options, op) @@ -71,10 +71,10 @@ def __teal__(self, options: "CompileOptions"): else: opToUse = Op.gitxnas - verifyTealVersion( + verifyProgramVersion( opToUse.min_version, options.version, - "TEAL version too low to use op {}".format(opToUse), + "Program version too low to use op {}".format(opToUse), ) if type(self.index) is int: diff --git a/pyteal/ast/gitxn_test.py b/pyteal/ast/gitxn_test.py index 44415df83..8501cc4e7 100644 --- a/pyteal/ast/gitxn_test.py +++ b/pyteal/ast/gitxn_test.py @@ -2,8 +2,8 @@ import pyteal as pt -teal5Options = pt.CompileOptions(version=5) -teal6Options = pt.CompileOptions(version=6) +avm5Options = pt.CompileOptions(version=5) +avm6Options = pt.CompileOptions(version=6) def test_gitxn_invalid(): @@ -33,7 +33,7 @@ def test_gitxn_expr_invalid(): pt.TealInputError, ), ( - lambda: pt.GitxnExpr(1, pt.TxnField.sender).__teal__(teal5Options), + lambda: pt.GitxnExpr(1, pt.TxnField.sender).__teal__(avm5Options), pt.TealInputError, ), ]: @@ -42,7 +42,7 @@ def test_gitxn_expr_invalid(): def test_gitxn_expr_valid(): - pt.GitxnExpr(1, pt.TxnField.sender).__teal__(teal6Options) + pt.GitxnExpr(1, pt.TxnField.sender).__teal__(avm6Options) def test_gitxna_expr_invalid(): @@ -63,7 +63,7 @@ def test_gitxna_expr_invalid(): ), ( lambda: pt.GitxnaExpr(0, pt.TxnField.application_args, 0).__teal__( - teal5Options + avm5Options ), pt.TealInputError, ), @@ -74,7 +74,7 @@ def test_gitxna_expr_invalid(): def test_gitxna_valid(): [ - e.__teal__(teal6Options) + e.__teal__(avm6Options) for e in [ pt.GitxnaExpr(0, pt.TxnField.application_args, 1), pt.GitxnaExpr(0, pt.TxnField.application_args, pt.Int(1)), diff --git a/pyteal/ast/gload.py b/pyteal/ast/gload.py index 0c4b86c55..6b85a4725 100644 --- a/pyteal/ast/gload.py +++ b/pyteal/ast/gload.py @@ -2,7 +2,7 @@ from pyteal.types import TealType, require_type from pyteal.ir import TealOp, Op, TealBlock -from pyteal.errors import TealInputError, verifyTealVersion +from pyteal.errors import TealInputError, verifyProgramVersion from pyteal.config import MAX_GROUP_SIZE, NUM_SLOTS from pyteal.ast.expr import Expr from pyteal.ast.leafexpr import LeafExpr @@ -17,7 +17,7 @@ class ImportScratchValue(LeafExpr): def __init__(self, txnIndex: Union[int, Expr], slotId: Union[int, Expr]) -> None: """Create an expression to load a scratch space slot from a transaction in the current group. - Requires TEAL version 4 or higher. This operation is only permitted in application mode. + Requires program version 4 or higher. This operation is only permitted in application mode. Args: txnIndex: The index of the transaction from which the created ID should be obtained. @@ -62,10 +62,10 @@ def __str__(self) -> str: def __teal__(self, options: "CompileOptions"): def local_version_check(opcode: TealOp): - verifyTealVersion( + verifyProgramVersion( opcode.op.min_version, options.version, - "TEAL version too low to use {} experssion".format(opcode.op.name), + "Program version too low to use {} experssion".format(opcode.op.name), ) # For txnIndex and slotId, there are only three scenario as following diff --git a/pyteal/ast/gload_test.py b/pyteal/ast/gload_test.py index fe182af6a..3be3390ea 100644 --- a/pyteal/ast/gload_test.py +++ b/pyteal/ast/gload_test.py @@ -2,25 +2,25 @@ import pyteal as pt -teal3Options = pt.CompileOptions(version=3) -teal4Options = pt.CompileOptions(version=4) -teal6Options = pt.CompileOptions(version=6) +avm3Options = pt.CompileOptions(version=3) +avm4Options = pt.CompileOptions(version=4) +avm6Options = pt.CompileOptions(version=6) def test_gload_teal_3(): with pytest.raises(pt.TealInputError): - pt.ImportScratchValue(0, 1).__teal__(teal3Options) + pt.ImportScratchValue(0, 1).__teal__(avm3Options) with pytest.raises(pt.TealInputError): - pt.ImportScratchValue(pt.Int(0), 1).__teal__(teal3Options) + pt.ImportScratchValue(pt.Int(0), 1).__teal__(avm3Options) with pytest.raises(pt.TealInputError): - pt.ImportScratchValue(pt.Int(0), pt.Int(1)).__teal__(teal3Options) + pt.ImportScratchValue(pt.Int(0), pt.Int(1)).__teal__(avm3Options) def test_gload_teal_4(): with pytest.raises(pt.TealInputError): - pt.ImportScratchValue(pt.Int(0), pt.Int(2)).__teal__(teal4Options) + pt.ImportScratchValue(pt.Int(0), pt.Int(2)).__teal__(avm4Options) def test_gload(): @@ -29,7 +29,7 @@ def test_gload(): expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.gload, 0, 1)]) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) assert actual == expected @@ -43,7 +43,7 @@ def test_gloads(): [pt.TealOp(arg, pt.Op.int, 1), pt.TealOp(expr, pt.Op.gloads, 0)] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -64,7 +64,7 @@ def test_gloadss(): ] ) - actual, _ = expr.__teal__(teal6Options) + actual, _ = expr.__teal__(avm6Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) diff --git a/pyteal/ast/global_.py b/pyteal/ast/global_.py index 9c311e84e..1ed4c313a 100644 --- a/pyteal/ast/global_.py +++ b/pyteal/ast/global_.py @@ -89,7 +89,7 @@ def group_size(cls) -> "Global": @classmethod def logic_sig_version(cls) -> "Global": - """Get the maximum supported TEAL version.""" + """Get the maximum supported program version.""" return cls(GlobalField.logic_sig_version) @classmethod @@ -115,14 +115,14 @@ def current_application_id(cls) -> "Global": def creator_address(cls) -> "Global": """Address of the creator of the current application. - Fails during Signature mode. Requires TEAL version 3 or higher.""" + Fails during Signature mode. Requires program version 3 or higher.""" return cls(GlobalField.creator_address) @classmethod def current_application_address(cls) -> "Global": """Get the address of that the current application controls. - Fails during Signature mode. Requires TEAL version 5 or higher.""" + Fails during Signature mode. Requires program version 5 or higher.""" return cls(GlobalField.current_app_address) @classmethod @@ -131,14 +131,14 @@ def group_id(cls) -> "Global": If the current transaction is not part of a group, this will return 32 zero bytes. - Requires TEAL version 5 or higher.""" + Requires program version 5 or higher.""" return cls(GlobalField.group_id) @classmethod def opcode_budget(cls) -> "Global": """Get the remaining opcode execution budget - Requires TEAL version 6 or higher.""" + Requires program version 6 or higher.""" return cls(GlobalField.opcode_budget) @classmethod @@ -147,7 +147,7 @@ def caller_app_id(cls) -> "Global": If not called from another app, this will return 0 - Requires TEAL version 6 or higher.""" + Requires program version 6 or higher.""" return cls(GlobalField.caller_app_id) @classmethod @@ -156,7 +156,7 @@ def caller_app_address(cls) -> "Global": If not called from another app, this will return the ZeroAddress - Requires TEAL version 6 or higher.""" + Requires program version 6 or higher.""" return cls(GlobalField.caller_app_address) diff --git a/pyteal/ast/global_test.py b/pyteal/ast/global_test.py index 4e72b3bd1..b06addefb 100644 --- a/pyteal/ast/global_test.py +++ b/pyteal/ast/global_test.py @@ -2,10 +2,10 @@ import pyteal as pt -teal2Options = pt.CompileOptions(version=2) -teal3Options = pt.CompileOptions(version=3) -teal5Options = pt.CompileOptions(version=5) -teal6Options = pt.CompileOptions(version=6) +avm2Options = pt.CompileOptions(version=2) +avm3Options = pt.CompileOptions(version=3) +avm5Options = pt.CompileOptions(version=5) +avm6Options = pt.CompileOptions(version=6) def test_global_min_txn_fee(): @@ -14,7 +14,7 @@ def test_global_min_txn_fee(): expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.global_, "MinTxnFee")]) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) assert actual == expected @@ -25,7 +25,7 @@ def test_global_min_balance(): expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.global_, "MinBalance")]) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) assert actual == expected @@ -36,7 +36,7 @@ def test_global_max_txn_life(): expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.global_, "MaxTxnLife")]) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) assert actual == expected @@ -47,7 +47,7 @@ def test_global_zero_address(): expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.global_, "ZeroAddress")]) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) assert actual == expected @@ -58,7 +58,7 @@ def test_global_group_size(): expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.global_, "GroupSize")]) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) assert actual == expected @@ -69,7 +69,7 @@ def test_global_logic_sig_version(): expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.global_, "LogicSigVersion")]) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) assert actual == expected @@ -80,7 +80,7 @@ def test_global_round(): expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.global_, "Round")]) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) assert actual == expected @@ -91,7 +91,7 @@ def test_global_latest_timestamp(): expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.global_, "LatestTimestamp")]) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) assert actual == expected @@ -104,7 +104,7 @@ def test_global_current_application_id(): [pt.TealOp(expr, pt.Op.global_, "CurrentApplicationID")] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) assert actual == expected @@ -115,12 +115,12 @@ def test_global_creator_address(): expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.global_, "CreatorAddress")]) - actual, _ = expr.__teal__(teal3Options) + actual, _ = expr.__teal__(avm3Options) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal2Options) + expr.__teal__(avm2Options) def test_global_current_application_address(): @@ -131,12 +131,12 @@ def test_global_current_application_address(): [pt.TealOp(expr, pt.Op.global_, "CurrentApplicationAddress")] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_global_group_id(): @@ -145,12 +145,12 @@ def test_global_group_id(): expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.global_, "GroupID")]) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal3Options) + expr.__teal__(avm3Options) def test_global_opcode_budget(): @@ -159,12 +159,12 @@ def test_global_opcode_budget(): expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.global_, "OpcodeBudget")]) - actual, _ = expr.__teal__(teal6Options) + actual, _ = expr.__teal__(avm6Options) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal5Options) + expr.__teal__(avm5Options) def test_global_caller_application_id(): @@ -175,12 +175,12 @@ def test_global_caller_application_id(): [pt.TealOp(expr, pt.Op.global_, "CallerApplicationID")] ) - actual, _ = expr.__teal__(teal6Options) + actual, _ = expr.__teal__(avm6Options) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal5Options) + expr.__teal__(avm5Options) def test_global_caller_app_address(): @@ -191,9 +191,9 @@ def test_global_caller_app_address(): [pt.TealOp(expr, pt.Op.global_, "CallerApplicationAddress")] ) - actual, _ = expr.__teal__(teal6Options) + actual, _ = expr.__teal__(avm6Options) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal5Options) + expr.__teal__(avm5Options) diff --git a/pyteal/ast/gtxn.py b/pyteal/ast/gtxn.py index 640f0605d..f1f59a95d 100644 --- a/pyteal/ast/gtxn.py +++ b/pyteal/ast/gtxn.py @@ -2,7 +2,7 @@ from pyteal.types import TealType, require_type from pyteal.ir import TealOp, Op, TealBlock -from pyteal.errors import TealInputError, verifyFieldVersion, verifyTealVersion +from pyteal.errors import TealInputError, verifyFieldVersion, verifyProgramVersion from pyteal.config import MAX_GROUP_SIZE from pyteal.ast.expr import Expr from pyteal.ast.txn import TxnField, TxnExpr, TxnaExpr, TxnObject @@ -35,16 +35,18 @@ def __teal__(self, options: "CompileOptions"): verifyFieldVersion(self.field.arg_name, self.field.min_version, options.version) if type(self.txnIndex) is int: - verifyTealVersion( - Op.gtxn.min_version, options.version, "TEAL version too low to use gtxn" + verifyProgramVersion( + Op.gtxn.min_version, + options.version, + "Program version too low to use gtxn", ) op = TealOp(self, Op.gtxn, self.txnIndex, self.field.arg_name) return TealBlock.FromOp(options, op) - verifyTealVersion( + verifyProgramVersion( Op.gtxns.min_version, options.version, - "TEAL version too low to index Gtxn with dynamic values", + "Program version too low to index Gtxn with dynamic values", ) op = TealOp(self, Op.gtxns, self.field.arg_name) @@ -83,10 +85,10 @@ def __teal__(self, options: "CompileOptions"): else: opToUse = Op.gtxnsas - verifyTealVersion( + verifyProgramVersion( opToUse.min_version, options.version, - "TEAL version too low to use op {}".format(opToUse), + "Program version too low to use op {}".format(opToUse), ) if type(self.txnIndex) is int: diff --git a/pyteal/ast/gtxn_test.py b/pyteal/ast/gtxn_test.py index 9f48e5317..a42135bec 100644 --- a/pyteal/ast/gtxn_test.py +++ b/pyteal/ast/gtxn_test.py @@ -2,7 +2,7 @@ import pyteal as pt -teal6Options = pt.CompileOptions(version=6) +avm6Options = pt.CompileOptions(version=6) def test_gtxn_invalid(): @@ -29,7 +29,7 @@ def test_gtxn_expr_invalid(): def test_gtxn_expr_valid(): [ - e.__teal__(teal6Options) + e.__teal__(avm6Options) for e in [ pt.GtxnExpr(1, pt.TxnField.sender), pt.GtxnExpr(pt.Int(1), pt.TxnField.sender), @@ -62,7 +62,7 @@ def test_gtxna_expr_invalid(): def test_gtxna_expr_valid(): [ - e.__teal__(teal6Options) + e.__teal__(avm6Options) for e in [ pt.GtxnaExpr(1, pt.TxnField.assets, 1), pt.GtxnaExpr(pt.Int(1), pt.TxnField.assets, pt.Int(1)), diff --git a/pyteal/ast/itxn.py b/pyteal/ast/itxn.py index af7704198..b2cfae2ad 100644 --- a/pyteal/ast/itxn.py +++ b/pyteal/ast/itxn.py @@ -2,7 +2,7 @@ from typing import Dict, TYPE_CHECKING, List, Union, cast from pyteal.types import TealType, require_type -from pyteal.errors import TealInputError, verifyTealVersion +from pyteal.errors import TealInputError, verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.ast.expr import Expr from pyteal.ast.txn import TxnField, TxnExprBuilder, TxnaExprBuilder, TxnObject @@ -32,10 +32,10 @@ def __str__(self): def __teal__(self, options: "CompileOptions"): op = self.action.value - verifyTealVersion( + verifyProgramVersion( op.min_version, options.version, - "TEAL version too low to create inner transactions", + "Program version too low to create inner transactions", ) return TealBlock.FromOp(options, TealOp(self, op)) @@ -58,10 +58,10 @@ def __str__(self): return "(InnerTxnSetField {} {})".format(self.field.arg_name, self.value) def __teal__(self, options: "CompileOptions"): - verifyTealVersion( + verifyProgramVersion( Op.itxn_field.min_version, options.version, - "TEAL version too low to create inner transactions", + "Program version too low to create inner transactions", ) return TealBlock.FromOp( @@ -81,7 +81,7 @@ class InnerTxnBuilder: Inner transactions are transactions which applications can dynamically create. Each inner transaction will appear as a transaction inside of the current transaction being executed. - As of TEAL version 5, only the transaction types :any:`TxnType.Payment`, :any:`TxnType.AssetTransfer`, + As of program version 5, only the transaction types :any:`TxnType.Payment`, :any:`TxnType.AssetTransfer`, :any:`TxnType.AssetConfig`, and :any:`TxnType.AssetFreeze` are allowed. Additionally, not all fields are allowed to be set. For example, it is not currently allowed to set the rekeyTo field of an inner transaction. @@ -96,7 +96,7 @@ def Begin(cls) -> Expr: overpaying in earlier transactions; :code:`FirstValid`/:code:`LastValid` to the values in the top-level transaction, and all other fields to zero values. - Requires TEAL version 5 or higher. This operation is only permitted in application mode. + Requires program version 5 or higher. This operation is only permitted in application mode. """ return InnerTxnActionExpr(InnerTxnAction.Begin) @@ -109,7 +109,7 @@ def Next(cls) -> Expr: overpaying in earlier transactions; :code:`FirstValid`/:code:`LastValid` to the values in the top-level transaction, and all other fields to zero values. - Requires TEAL version 6 or higher. This operation is only permitted in application mode. + Requires program version 6 or higher. This operation is only permitted in application mode. """ return InnerTxnActionExpr(InnerTxnAction.Next) @@ -130,7 +130,7 @@ def Submit(cls) -> Expr: If the inner transaction creates an asset, the new asset ID can be found by looking at :any:`InnerTxn.created_asset_id() `. - Requires TEAL version 5 or higher. This operation is only permitted in application mode. + Requires program version 5 or higher. This operation is only permitted in application mode. """ return InnerTxnActionExpr(InnerTxnAction.Submit) @@ -144,7 +144,7 @@ def SetField(cls, field: TxnField, value: Union[Expr, List[Expr]]) -> Expr: Note: For non-array field (e.g., note), setting it twice will overwrite the original value. While for array field (e.g., accounts), setting it multiple times will append the values. - Requires TEAL version 5 or higher. This operation is only permitted in application mode. + Requires program version 5 or higher. This operation is only permitted in application mode. Args: field: The field to set on the inner transaction. @@ -180,6 +180,27 @@ def SetField(cls, field: TxnField, value: Union[Expr, List[Expr]]) -> Expr: ] ) + @classmethod + def Execute(cls, fields: Dict[TxnField, Union[Expr, List[Expr]]]) -> Expr: + """Performs a single transaction given fields passed in. + + A convenience method that accepts fields to submit a single inner transaction, which is equivalent to: + + .. code-block:: python + + InnerTxnBuilder.Begin() + InnerTxnBuilder.SetFields(fields) + InnerTxnBuilder.End() + + Requires program version 5 or higher. This operation is only permitted in application mode. + + Args: + fields: A dictionary whose keys are fields to set and whose values are the value each + field should take. Each value must evaluate to a type that is compatible with the + field being set. + """ + return Seq(cls.Begin(), cls.SetFields(fields), cls.Submit()) + @classmethod def SetFields(cls, fields: Dict[TxnField, Union[Expr, List[Expr]]]) -> Expr: """Set multiple fields of the current inner transaction. @@ -190,7 +211,7 @@ def SetFields(cls, fields: Dict[TxnField, Union[Expr, List[Expr]]]) -> Expr: Note: For non-array field (e.g., note), setting it twice will overwrite the original value. While for array field (e.g., accounts), setting it multiple times will append the values. - Requires TEAL version 5 or higher. This operation is only permitted in application mode. + Requires program version 5 or higher. This operation is only permitted in application mode. Args: fields: A dictionary whose keys are fields to set and whose values are the value each diff --git a/pyteal/ast/itxn_test.py b/pyteal/ast/itxn_test.py index af9c3a79c..b4da1b7dc 100644 --- a/pyteal/ast/itxn_test.py +++ b/pyteal/ast/itxn_test.py @@ -3,9 +3,9 @@ import pyteal as pt from pyteal.types import types_match -teal4Options = pt.CompileOptions(version=4) -teal5Options = pt.CompileOptions(version=5) -teal6Options = pt.CompileOptions(version=6) +avm4Options = pt.CompileOptions(version=4) +avm5Options = pt.CompileOptions(version=5) +avm6Options = pt.CompileOptions(version=6) def test_InnerTxnBuilder_Begin(): @@ -15,12 +15,12 @@ def test_InnerTxnBuilder_Begin(): expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.itxn_begin)]) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal4Options) + expr.__teal__(avm4Options) def test_InnerTxnBuilder_Submit(): @@ -30,12 +30,12 @@ def test_InnerTxnBuilder_Submit(): expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.itxn_submit)]) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal4Options) + expr.__teal__(avm4Options) def test_InnerTxnBuilder_Next(): @@ -45,12 +45,12 @@ def test_InnerTxnBuilder_Next(): expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.itxn_next)]) - actual, _ = expr.__teal__(teal6Options) + actual, _ = expr.__teal__(avm6Options) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal5Options) + expr.__teal__(avm5Options) def test_InnerTxnBuilder_SetField(): @@ -82,47 +82,48 @@ def test_InnerTxnBuilder_SetField(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal4Options) - - -def test_InnerTxnBuilder_SetFields(): - cases = ( - ({}, pt.Seq()), - ( - {pt.TxnField.amount: pt.Int(5)}, - pt.InnerTxnBuilder.SetField(pt.TxnField.amount, pt.Int(5)), - ), - ( - { - pt.TxnField.type_enum: pt.TxnType.Payment, - pt.TxnField.close_remainder_to: pt.Txn.sender(), - }, - pt.Seq( - pt.InnerTxnBuilder.SetField(pt.TxnField.type_enum, pt.TxnType.Payment), - pt.InnerTxnBuilder.SetField( - pt.TxnField.close_remainder_to, pt.Txn.sender() - ), + expr.__teal__(avm4Options) + + +ITXN_FIELDS_CASES = [ + ({}, pt.Seq()), + ( + {pt.TxnField.amount: pt.Int(5)}, + pt.InnerTxnBuilder.SetField(pt.TxnField.amount, pt.Int(5)), + ), + ( + { + pt.TxnField.type_enum: pt.TxnType.Payment, + pt.TxnField.close_remainder_to: pt.Txn.sender(), + }, + pt.Seq( + pt.InnerTxnBuilder.SetField(pt.TxnField.type_enum, pt.TxnType.Payment), + pt.InnerTxnBuilder.SetField( + pt.TxnField.close_remainder_to, pt.Txn.sender() ), ), - ) + ), +] + - for fields, expectedExpr in cases: +def test_InnerTxnBuilder_SetFields(): + for fields, expectedExpr in ITXN_FIELDS_CASES: expr = pt.InnerTxnBuilder.SetFields(fields) assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expected, _ = expectedExpr.__teal__(teal5Options) + expected, _ = expectedExpr.__teal__(avm5Options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -131,7 +132,30 @@ def test_InnerTxnBuilder_SetFields(): if len(fields) != 0: with pytest.raises(pt.TealInputError): - expr.__teal__(teal4Options) + expr.__teal__(avm4Options) + + +def test_InnerTxnBuilder_Execute(): + for fields, expectedExpr in ITXN_FIELDS_CASES: + expr = pt.InnerTxnBuilder.Execute(fields) + + expected, _ = pt.Seq( + pt.InnerTxnBuilder.Begin(), + expectedExpr, + pt.InnerTxnBuilder.Submit(), + ).__teal__(avm5Options) + expected.addIncoming() + expected = pt.TealBlock.NormalizeBlocks(expected) + + actual, _ = expr.__teal__(avm5Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + with pt.TealComponent.Context.ignoreExprEquality(): + assert actual == expected + + with pytest.raises(pt.TealInputError): + expr.__teal__(avm4Options) # txn_test.py performs additional testing diff --git a/pyteal/ast/jsonref.py b/pyteal/ast/jsonref.py index 91018d714..5173218c4 100644 --- a/pyteal/ast/jsonref.py +++ b/pyteal/ast/jsonref.py @@ -2,10 +2,9 @@ from enum import Enum from pyteal.types import TealType, require_type -from pyteal.errors import verifyFieldVersion, verifyTealVersion +from pyteal.errors import verifyFieldVersion, verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.ast.expr import Expr -from pyteal.ast.leafexpr import LeafExpr if TYPE_CHECKING: from pyteal.compiler import CompileOptions @@ -32,7 +31,7 @@ def type_of(self) -> TealType: JsonRefType.__module__ = "pyteal" -class JsonRef(LeafExpr): +class JsonRef(Expr): """An expression that accesses the value associated with a given key from a supported utf-8 encoded json object. The json object must satisfy a `particular specification `_. @@ -50,10 +49,10 @@ def __init__(self, type: JsonRefType, json_obj: Expr, key: Expr) -> None: self.key = key def __teal__(self, options: "CompileOptions"): - verifyTealVersion( + verifyProgramVersion( Op.json_ref.min_version, options.version, - "TEAL version too low to use op json_ref", + "Program version too low to use op json_ref", ) verifyFieldVersion(self.type.arg_name, self.type.min_version, options.version) @@ -62,13 +61,16 @@ def __teal__(self, options: "CompileOptions"): return TealBlock.FromOp(options, op, self.json_obj, self.key) def __str__(self): - return "(JsonRef {})".format(self.type.arg_name) + return "(JsonRef {} {} {})".format(self.type.arg_name, self.json_obj, self.key) def type_of(self): return self.type.type_of() + def has_return(self): + return False + @classmethod - def as_string(cls, json_obj: Expr, key: Expr) -> "JsonRef": + def as_string(cls, json_obj: Expr, key: Expr) -> Expr: """Access the value of a given key as a string. Refer to the `JsonRef` class documentation for valid json specification. @@ -80,7 +82,7 @@ def as_string(cls, json_obj: Expr, key: Expr) -> "JsonRef": return cls(JsonRefType.string, json_obj, key) @classmethod - def as_uint64(cls, json_obj: Expr, key: Expr) -> "JsonRef": + def as_uint64(cls, json_obj: Expr, key: Expr) -> Expr: """Access the value of a given key as a uint64. Refer to the `JsonRef` class documentation for valid json specification. diff --git a/pyteal/ast/jsonref_test.py b/pyteal/ast/jsonref_test.py index 356c74591..10733952f 100644 --- a/pyteal/ast/jsonref_test.py +++ b/pyteal/ast/jsonref_test.py @@ -2,8 +2,8 @@ import pyteal as pt -teal6Options = pt.CompileOptions(version=6) -teal7Options = pt.CompileOptions(version=7) +avm6Options = pt.CompileOptions(version=6) +avm7Options = pt.CompileOptions(version=7) def test_json_string(): @@ -19,14 +19,14 @@ def test_json_string(): ] ) - actual, _ = expr.__teal__(teal7Options) + actual, _ = expr.__teal__(avm7Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal6Options) + expr.__teal__(avm6Options) def test_json_uint64(): @@ -42,14 +42,14 @@ def test_json_uint64(): ] ) - actual, _ = expr.__teal__(teal7Options) + actual, _ = expr.__teal__(avm7Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal6Options) + expr.__teal__(avm6Options) def test_json_object(): @@ -65,14 +65,14 @@ def test_json_object(): ] ) - actual, _ = expr.__teal__(teal7Options) + actual, _ = expr.__teal__(avm7Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal6Options) + expr.__teal__(avm6Options) def test_json_ref_invalid(): diff --git a/pyteal/ast/maybe.py b/pyteal/ast/maybe.py index ebe3d03e7..4d863e6ff 100644 --- a/pyteal/ast/maybe.py +++ b/pyteal/ast/maybe.py @@ -1,6 +1,6 @@ from typing import List, Union, TYPE_CHECKING -from pyteal.errors import verifyTealVersion +from pyteal.errors import verifyProgramVersion from pyteal.types import TealType from pyteal.ir import Op @@ -33,7 +33,7 @@ def __init__( """ def local_version_check(option: "CompileOptions"): - verifyTealVersion( + verifyProgramVersion( minVersion=op.min_version, version=option.version, msg=f"{op.value} unavailable", diff --git a/pyteal/ast/opup.py b/pyteal/ast/opup.py index 45a84d37d..af862b10b 100644 --- a/pyteal/ast/opup.py +++ b/pyteal/ast/opup.py @@ -29,14 +29,14 @@ class OpUpMode(Enum): OnCall = 1 -ON_CALL_APP = Bytes("base16", "068101") # v6 teal program "int 1" +ON_CALL_APP = Bytes("base16", "068101") # v6 program "int 1" MIN_TXN_FEE = Int(1000) class OpUp: """Utility for increasing opcode budget during app execution. - Requires TEAL version 6 or higher. + Requires program version 6 or higher. Example: .. code-block:: python diff --git a/pyteal/ast/replace.py b/pyteal/ast/replace.py index 2b7968978..fa625df8a 100644 --- a/pyteal/ast/replace.py +++ b/pyteal/ast/replace.py @@ -1,7 +1,7 @@ from typing import cast, TYPE_CHECKING from pyteal.types import TealType, require_type -from pyteal.errors import verifyTealVersion +from pyteal.errors import verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.ast.expr import Expr from pyteal.ast.int import Int @@ -46,10 +46,10 @@ def __teal__(self, options: "CompileOptions"): op = self.__get_op(options) - verifyTealVersion( + verifyProgramVersion( op.min_version, options.version, - "TEAL version too low to use op {}".format(op), + "Program version too low to use op {}".format(op), ) s = cast(Int, self.start).value @@ -76,7 +76,7 @@ def Replace(original: Expr, start: Expr, replacement: Expr) -> Expr: """ Replace a portion of original bytes with new bytes at a given starting point. - Requires TEAL version 7 or higher. + Requires program version 7 or higher. Args: original: The value containing the original bytes. Must evaluate to bytes. diff --git a/pyteal/ast/replace_test.py b/pyteal/ast/replace_test.py index b72a5d879..5f7076ed0 100644 --- a/pyteal/ast/replace_test.py +++ b/pyteal/ast/replace_test.py @@ -2,8 +2,8 @@ import pyteal as pt -teal6Options = pt.CompileOptions(version=6) -teal7Options = pt.CompileOptions(version=7) +avm6Options = pt.CompileOptions(version=6) +avm7Options = pt.CompileOptions(version=7) def test_replace_immediate(): @@ -19,14 +19,14 @@ def test_replace_immediate(): ] ) - actual, _ = expr.__teal__(teal7Options) + actual, _ = expr.__teal__(avm7Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal6Options) + expr.__teal__(avm6Options) def test_replace_stack_int(): @@ -44,14 +44,14 @@ def test_replace_stack_int(): ] ) - actual, _ = expr.__teal__(teal7Options) + actual, _ = expr.__teal__(avm7Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal6Options) + expr.__teal__(avm6Options) # Mirrors `test_replace_stack_int`, but attempts replacement with start != pt.Int. @@ -73,7 +73,7 @@ def test_replace_stack_not_int(): ] ) - actual, _ = expr.__teal__(teal7Options) + actual, _ = expr.__teal__(avm7Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -81,7 +81,7 @@ def test_replace_stack_not_int(): assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal6Options) + expr.__teal__(avm6Options) def test_replace_invalid(): diff --git a/pyteal/ast/return_.py b/pyteal/ast/return_.py index be27155fe..0540a4ff2 100644 --- a/pyteal/ast/return_.py +++ b/pyteal/ast/return_.py @@ -1,7 +1,7 @@ from typing import TYPE_CHECKING from pyteal.types import TealType, require_type, types_match -from pyteal.errors import verifyTealVersion, TealCompileError +from pyteal.errors import verifyProgramVersion, TealCompileError from pyteal.ir import TealOp, Op, TealBlock from pyteal.ast.expr import Expr from pyteal.ast.int import Int @@ -31,10 +31,10 @@ def __init__(self, value: Expr = None) -> None: def __teal__(self, options: "CompileOptions"): if options.currentSubroutine is not None: - verifyTealVersion( + verifyProgramVersion( Op.retsub.min_version, options.version, - "TEAL version too low to use subroutines", + "Program version too low to use subroutines", ) returnType = options.currentSubroutine.returnType if returnType == TealType.none: diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 657134bee..026f1c27d 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -2,7 +2,7 @@ from types import MappingProxyType from typing import Callable, List, Optional, Type, Union, TYPE_CHECKING -from pyteal.errors import TealInputError, verifyTealVersion +from pyteal.errors import TealInputError, verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.types import TealType @@ -263,10 +263,10 @@ def __teal__(self, options: "CompileOptions"): 2. (by-reference) In the case of a by-reference argument of type ScratchVar, its SLOT INDEX is put on the stack and will be stored in a local DynamicScratchVar for subroutine evaluation """ - verifyTealVersion( + verifyProgramVersion( Op.callsub.min_version, options.version, - "TEAL version too low to use SubroutineCall expression", + "Program version too low to use SubroutineCall expression", ) def handle_arg(arg): diff --git a/pyteal/ast/substring.py b/pyteal/ast/substring.py index 6febf69dc..fe4ce4809 100644 --- a/pyteal/ast/substring.py +++ b/pyteal/ast/substring.py @@ -1,7 +1,7 @@ from typing import cast, TYPE_CHECKING from pyteal.types import TealType, require_type -from pyteal.errors import TealCompileError, verifyTealVersion +from pyteal.errors import TealCompileError, verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock, TealSimpleBlock from pyteal.ast.expr import Expr from pyteal.ast.int import Int @@ -60,10 +60,10 @@ def __teal__(self, options: "CompileOptions"): op = self.__get_op(options) - verifyTealVersion( + verifyProgramVersion( op.min_version, options.version, - "TEAL version too low to use op {}".format(op), + "Program version too low to use op {}".format(op), ) start, end = cast(Int, self.startArg).value, cast(Int, self.endArg).value @@ -141,10 +141,10 @@ def __teal__(self, options: "CompileOptions"): op = self.__get_op(options) - verifyTealVersion( + verifyProgramVersion( op.min_version, options.version, - "TEAL version too low to use op {}".format(op), + "Program version too low to use op {}".format(op), ) s, l = cast(Int, self.startArg).value, cast(Int, self.lenArg).value @@ -199,10 +199,10 @@ def __get_op(self, options: "CompileOptions"): def __teal__(self, options: "CompileOptions"): op = self.__get_op(options) - verifyTealVersion( + verifyProgramVersion( op.min_version, options.version, - "TEAL version too low to use op {}".format(op), + "Program version too low to use op {}".format(op), ) if op == Op.extract: @@ -248,7 +248,7 @@ def Substring(string: Expr, start: Expr, end: Expr) -> Expr: This expression is similar to :any:`Extract`, except this expression uses start and end indexes, while :code:`Extract` uses a start index and length. - Requires TEAL version 2 or higher. + Requires program version 2 or higher. Args: string: The byte string. @@ -273,7 +273,7 @@ def Extract(string: Expr, start: Expr, length: Expr) -> Expr: This expression is similar to :any:`Substring`, except this expression uses a start index and length, while :code:`Substring` uses start and end indexes. - Requires TEAL version 5 or higher. + Requires program version 5 or higher. Args: string: The byte string. @@ -296,7 +296,7 @@ def Suffix(string: Expr, start: Expr) -> Expr: This expression is similar to :any:`Substring` and :any:`Extract`, except this expression only uses a start index. - Requires TEAL version 5 or higher. + Requires program version 5 or higher. Args: string: The byte string. diff --git a/pyteal/ast/substring_test.py b/pyteal/ast/substring_test.py index ae5bcace2..3e10c5f51 100644 --- a/pyteal/ast/substring_test.py +++ b/pyteal/ast/substring_test.py @@ -2,10 +2,10 @@ import pyteal as pt -teal2Options = pt.CompileOptions(version=2) -teal3Options = pt.CompileOptions(version=3) -teal4Options = pt.CompileOptions(version=4) -teal5Options = pt.CompileOptions(version=5) +avm2Options = pt.CompileOptions(version=2) +avm3Options = pt.CompileOptions(version=3) +avm4Options = pt.CompileOptions(version=4) +avm5Options = pt.CompileOptions(version=5) def test_substring_immediate_v2(): @@ -20,7 +20,7 @@ def test_substring_immediate_v2(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -39,7 +39,7 @@ def test_substring_immediate_v5(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -59,7 +59,7 @@ def test_substring_to_extract(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -82,7 +82,7 @@ def test_substring_stack_v2(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -105,7 +105,7 @@ def test_substring_stack_v5(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -126,7 +126,7 @@ def test_zero_length_substring_immediate(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -145,7 +145,7 @@ def test_substring_invalid(): pt.Substring(pt.Bytes("my string"), pt.Int(0), pt.Txn.sender()) with pytest.raises(Exception): - pt.Substring(pt.Bytes("my string"), pt.Int(1), pt.Int(0)).__teal__(teal5Options) + pt.Substring(pt.Bytes("my string"), pt.Int(1), pt.Int(0)).__teal__(avm5Options) def test_extract_immediate(): @@ -160,14 +160,14 @@ def test_extract_immediate(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal4Options) + expr.__teal__(avm4Options) def test_extract_zero(): @@ -184,14 +184,14 @@ def test_extract_zero(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal4Options) + expr.__teal__(avm4Options) def test_extract_stack(): @@ -209,14 +209,14 @@ def test_extract_stack(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal4Options) + expr.__teal__(avm4Options) def test_extract_invalid(): @@ -242,7 +242,7 @@ def test_suffix_immediate(): ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -265,7 +265,7 @@ def test_suffix_stack(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -301,7 +301,7 @@ def generate_expr() -> pt.Expr: ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -310,7 +310,7 @@ def generate_expr() -> pt.Expr: if op == pt.Op.extract3: with pytest.raises(pt.TealInputError): - expr.__teal__(teal4Options) + expr.__teal__(avm4Options) @pytest.mark.parametrize("op", [pt.Op.extract3, pt.Op.substring3]) @@ -342,7 +342,7 @@ def generate_expr() -> pt.Expr: ] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -351,7 +351,7 @@ def generate_expr() -> pt.Expr: if op == pt.Op.extract3: with pytest.raises(pt.TealInputError): - expr.__teal__(teal4Options) + expr.__teal__(avm4Options) def test_suffix_invalid(): diff --git a/pyteal/ast/ternaryexpr.py b/pyteal/ast/ternaryexpr.py index ad2c36bd6..a8a526cff 100644 --- a/pyteal/ast/ternaryexpr.py +++ b/pyteal/ast/ternaryexpr.py @@ -1,7 +1,7 @@ from typing import Tuple, TYPE_CHECKING from pyteal.types import TealType, require_type -from pyteal.errors import verifyTealVersion +from pyteal.errors import verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.ast.expr import Expr @@ -33,10 +33,10 @@ def __init__( self.thirdArg = thirdArg def __teal__(self, options: "CompileOptions"): - verifyTealVersion( + verifyProgramVersion( self.op.min_version, options.version, - "TEAL version too low to use op {}".format(self.op), + "Program version too low to use op {}".format(self.op), ) return TealBlock.FromOp( @@ -106,7 +106,7 @@ def SetBit(value: Expr, index: Expr, newBitValue: Expr) -> TernaryExpr: * For byte strings, bit indexing begins at the first byte. For example, :code:`SetBit(Bytes("base16", "0x00"), Int(7), Int(1))` yields the byte string 0x01. Any integer less than 8*Len(value) is a valid index. - Requires TEAL version 3 or higher. + Requires program version 3 or higher. Args: value: The value containing bits. Can evaluate to any type. @@ -129,7 +129,7 @@ def SetByte(value: Expr, index: Expr, newByteValue: Expr) -> TernaryExpr: Similar to SetBit, indexing begins at the first byte. For example, :code:`SetByte(Bytes("base16", "0x000000"), Int(0), Int(255))` yields the byte string 0xff0000. - Requires TEAL version 3 or higher. + Requires program version 3 or higher. Args: value: The value containing the bytes. Must evaluate to bytes. @@ -150,7 +150,7 @@ def Divw(hi: Expr, lo: Expr, y: Expr) -> TernaryExpr: """ Performs wide division by interpreting `hi` and `lo` as a uint128 value. - Requires TEAL version 6 or higher. + Requires program version 6 or higher. Args: hi: Quotient's high 64 bits. Must evaluate to uint64. diff --git a/pyteal/ast/ternaryexpr_test.py b/pyteal/ast/ternaryexpr_test.py index 51a01958a..0530ec6b6 100644 --- a/pyteal/ast/ternaryexpr_test.py +++ b/pyteal/ast/ternaryexpr_test.py @@ -2,12 +2,12 @@ import pyteal as pt -teal2Options = pt.CompileOptions(version=2) -teal3Options = pt.CompileOptions(version=3) -teal4Options = pt.CompileOptions(version=4) -teal5Options = pt.CompileOptions(version=5) -teal6Options = pt.CompileOptions(version=6) -teal7Options = pt.CompileOptions(version=7) +avm2Options = pt.CompileOptions(version=2) +avm3Options = pt.CompileOptions(version=3) +avm4Options = pt.CompileOptions(version=4) +avm5Options = pt.CompileOptions(version=5) +avm6Options = pt.CompileOptions(version=6) +avm7Options = pt.CompileOptions(version=7) def test_ed25519verify(): @@ -24,7 +24,7 @@ def test_ed25519verify(): ] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -56,14 +56,14 @@ def test_ed25519verify_bare(): ] ) - actual, _ = expr.__teal__(teal7Options) + actual, _ = expr.__teal__(avm7Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal6Options) + expr.__teal__(avm6Options) def test_ed25519verify_bare_invalid(): @@ -91,14 +91,14 @@ def test_set_bit_int(): ] ) - actual, _ = expr.__teal__(teal3Options) + actual, _ = expr.__teal__(avm3Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal2Options) + expr.__teal__(avm2Options) def test_set_bit_bytes(): @@ -115,14 +115,14 @@ def test_set_bit_bytes(): ] ) - actual, _ = expr.__teal__(teal3Options) + actual, _ = expr.__teal__(avm3Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal2Options) + expr.__teal__(avm2Options) def test_set_bit_invalid(): @@ -153,14 +153,14 @@ def test_set_byte(): ] ) - actual, _ = expr.__teal__(teal3Options) + actual, _ = expr.__teal__(avm3Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal2Options) + expr.__teal__(avm2Options) def test_set_byte_invalid(): @@ -188,7 +188,7 @@ def test_divw(): ] ) - actual, _ = expr.__teal__(teal6Options) + actual, _ = expr.__teal__(avm6Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) diff --git a/pyteal/ast/txn.py b/pyteal/ast/txn.py index a4d011ddf..d8de1bd84 100644 --- a/pyteal/ast/txn.py +++ b/pyteal/ast/txn.py @@ -6,7 +6,7 @@ TealInputError, TealCompileError, verifyFieldVersion, - verifyTealVersion, + verifyProgramVersion, ) from pyteal.ir import TealOp, Op, TealBlock from pyteal.ast.leafexpr import LeafExpr @@ -159,10 +159,10 @@ def __str__(self): def __teal__(self, options: "CompileOptions"): verifyFieldVersion(self.field.arg_name, self.field.min_version, options.version) - verifyTealVersion( + verifyProgramVersion( self.op.min_version, options.version, - "TEAL version too low to use op {}".format(self.op), + "Program version too low to use op {}".format(self.op), ) op = TealOp(self, self.op, self.field.arg_name) @@ -216,10 +216,10 @@ def __teal__(self, options: "CompileOptions"): if opToUse is None: raise TealCompileError("Dynamic array indexing not supported", self) - verifyTealVersion( + verifyProgramVersion( opToUse.min_version, options.version, - "TEAL version too low to use op {}".format(opToUse), + "Program version too low to use op {}".format(opToUse), ) if type(self.index) is int: @@ -426,7 +426,7 @@ def nonparticipation(self) -> TxnExpr: For more information, see https://developer.algorand.org/docs/reference/transactions/#nonparticipation - Requires TEAL version 5 or higher. + Requires program version 5 or higher. """ return self.makeTxnExpr(TxnField.nonparticipation) @@ -643,7 +643,7 @@ def created_asset_id(self) -> TxnExpr: Only set when :any:`type_enum()` is :any:`TxnType.AssetConfig` and this is an asset creation transaction. - Requires TEAL version 5 or higher. + Requires program version 5 or higher. * v5 - Only works on inner transactions. * >= v6 - Works on top-level and inner transactions. @@ -679,7 +679,7 @@ def global_num_uints(self) -> TxnExpr: Only set when :any:`type_enum()` is :any:`TxnType.ApplicationCall` and this is an app creation call. - Requires TEAL version 3 or higher. + Requires program version 3 or higher. """ return self.makeTxnExpr(TxnField.global_num_uints) @@ -688,7 +688,7 @@ def global_num_byte_slices(self) -> TxnExpr: Only set when :any:`type_enum()` is :any:`TxnType.ApplicationCall` and this is an app creation call. - Requires TEAL version 3 or higher. + Requires program version 3 or higher. """ return self.makeTxnExpr(TxnField.global_num_byte_slices) @@ -697,7 +697,7 @@ def local_num_uints(self) -> TxnExpr: Only set when :any:`type_enum()` is :any:`TxnType.ApplicationCall` and this is an app creation call. - Requires TEAL version 3 or higher. + Requires program version 3 or higher. """ return self.makeTxnExpr(TxnField.local_num_uints) @@ -706,7 +706,7 @@ def local_num_byte_slices(self) -> TxnExpr: Only set when :any:`type_enum()` is :any:`TxnType.ApplicationCall` and this is an app creation call. - Requires TEAL version 3 or higher. + Requires program version 3 or higher. """ return self.makeTxnExpr(TxnField.local_num_byte_slices) @@ -717,7 +717,7 @@ def extra_program_pages(self) -> TxnExpr: Only set when :any:`type_enum()` is :any:`TxnType.ApplicationCall` and this is an app creation call. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. """ return self.makeTxnExpr(TxnField.extra_program_pages) @@ -726,7 +726,7 @@ def created_application_id(self) -> TxnExpr: Only set when :any:`type_enum()` is :any:`TxnType.ApplicationCall` and this is an app creation call. - Requires TEAL version 5 or higher. + Requires program version 5 or higher. * v5 - Only works on inner transactions. * >= v6 - Works on top-level and inner transactions. @@ -740,31 +740,17 @@ def last_log(self) -> TxnExpr: Only set when :any:`type_enum()` is :any:`TxnType.ApplicationCall`. - Requires TEAL version 6 or higher. + Requires program version 6 or higher. """ return self.makeTxnExpr(TxnField.last_log) def state_proof_pk(self) -> TxnExpr: """Get the state proof public key commitment from a transaction. - Requires TEAL version 6 or higher. + Requires program version 6 or higher. """ return self.makeTxnExpr(TxnField.state_proof_pk) - def num_approval_program_pages(self) -> TxnExpr: - """Get the number of pages in the approval program. - - Requires TEAL version 7 or higher. - """ - return self.makeTxnExpr(TxnField.num_approval_program_pages) - - def num_clear_state_program_pages(self) -> TxnExpr: - """Get the number of pages in the clear state program. - - Requires TEAL version 7 or higher. - """ - return self.makeTxnExpr(TxnField.num_clear_state_program_pages) - @property def application_args(self) -> TxnArray: """Application call arguments array. @@ -787,7 +773,7 @@ def assets(self) -> TxnArray: :type: TxnArray - Requires TEAL version 3 or higher. + Requires program version 3 or higher. """ return TxnArray(self, TxnField.assets, TxnField.num_assets) @@ -797,7 +783,7 @@ def applications(self) -> TxnArray: :type: TxnArray - Requires TEAL version 3 or higher. + Requires program version 3 or higher. """ return TxnArray(self, TxnField.applications, TxnField.num_applications) @@ -807,7 +793,7 @@ def logs(self) -> TxnArray: :type: TxnArray - Requires TEAL version 5 or higher. + Requires program version 5 or higher. * v5 - Only works on inner transactions. * >= v6 - Works on top-level and inner transactions. @@ -820,7 +806,7 @@ def approval_program_pages(self) -> TxnArray: :type: TxnArray - Requires TEAL version 7 or higher. + Requires program version 7 or higher. """ return TxnArray( self, TxnField.approval_program_pages, TxnField.num_approval_program_pages @@ -832,7 +818,7 @@ def clear_state_program_pages(self) -> TxnArray: :type: TxnArray - Requires TEAL version 7 or higher. + Requires program version 7 or higher. """ return TxnArray( self, diff --git a/pyteal/ast/txn_test.py b/pyteal/ast/txn_test.py index d169b459b..a53273376 100644 --- a/pyteal/ast/txn_test.py +++ b/pyteal/ast/txn_test.py @@ -59,8 +59,6 @@ pt.TxnField.created_application_id: lambda txn: txn.created_application_id(), pt.TxnField.last_log: lambda txn: txn.last_log(), pt.TxnField.state_proof_pk: lambda txn: txn.state_proof_pk(), - pt.TxnField.num_approval_program_pages: lambda txn: txn.num_approval_program_pages(), - pt.TxnField.num_clear_state_program_pages: lambda txn: txn.num_clear_state_program_pages(), } arrayFieldToProperty: Dict[pt.TxnField, Callable[[pt.TxnObject], pt.TxnArray]] = { diff --git a/pyteal/ast/unaryexpr.py b/pyteal/ast/unaryexpr.py index 1fad9903b..9d532a2b1 100644 --- a/pyteal/ast/unaryexpr.py +++ b/pyteal/ast/unaryexpr.py @@ -1,7 +1,7 @@ from typing import TYPE_CHECKING from pyteal.types import TealType, require_type -from pyteal.errors import verifyTealVersion +from pyteal.errors import verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.ast.expr import Expr @@ -22,10 +22,10 @@ def __init__( self.arg = arg def __teal__(self, options: "CompileOptions"): - verifyTealVersion( + verifyProgramVersion( self.op.min_version, options.version, - "TEAL version too low to use op {}".format(self.op), + "Program version too low to use op {}".format(self.op), ) return TealBlock.FromOp(options, TealOp(self, self.op), self.arg) @@ -65,7 +65,7 @@ def BitLen(arg: Expr) -> UnaryExpr: If the argument is a byte array, it is interpreted as a big-endian unsigned integer. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. """ return UnaryExpr(Op.bitlen, TealType.anytype, TealType.uint64, arg) @@ -111,7 +111,7 @@ def Sqrt(arg: Expr) -> UnaryExpr: This will return the largest integer X such that X^2 <= arg. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. """ return UnaryExpr(Op.sqrt, TealType.uint64, TealType.uint64, arg) @@ -142,7 +142,7 @@ def MinBalance(account: Expr) -> UnaryExpr: must be evaluated to uint64 (or, since v4, an account address that appears in Txn.Accounts or is Txn.Sender). - Requires TEAL version 3 or higher. This operation is only permitted in application mode. + Requires program version 3 or higher. This operation is only permitted in application mode. """ return UnaryExpr(Op.min_balance, TealType.anytype, TealType.uint64, account) @@ -153,7 +153,7 @@ def BytesNot(arg: Expr) -> UnaryExpr: Produces ~arg. Argument must not exceed 64 bytes. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. """ return UnaryExpr(Op.b_not, TealType.bytes, TealType.bytes, arg) @@ -163,7 +163,7 @@ def BytesSqrt(arg: Expr) -> UnaryExpr: This will return the largest integer X such that X^2 <= arg. - Requires TEAL version 6 or higher. + Requires program version 6 or higher. """ return UnaryExpr(Op.bsqrt, TealType.bytes, TealType.bytes, arg) @@ -173,7 +173,7 @@ def BytesZero(arg: Expr) -> UnaryExpr: Argument must evaluate to uint64. - Requires TEAL version 4 or higher. + Requires program version 4 or higher. """ return UnaryExpr(Op.bzero, TealType.uint64, TealType.bytes, arg) @@ -181,12 +181,12 @@ def BytesZero(arg: Expr) -> UnaryExpr: def Log(message: Expr) -> UnaryExpr: """Write a message to log state of the current application. - This will fail if called more than :code:`MaxLogCalls` times in a program (32 as of TEAL v5), or + This will fail if called more than :code:`MaxLogCalls` times in a program (32 as of AVM v5), or if the sum of the lengths of all logged messages in a program exceeds 1024 bytes. Args: message: The message to write. Must evaluate to bytes. - Requires TEAL version 5 or higher. + Requires program version 5 or higher. """ return UnaryExpr(Op.log, TealType.bytes, TealType.none, message) diff --git a/pyteal/ast/unaryexpr_test.py b/pyteal/ast/unaryexpr_test.py index 5a096fcbd..589286b75 100644 --- a/pyteal/ast/unaryexpr_test.py +++ b/pyteal/ast/unaryexpr_test.py @@ -2,12 +2,12 @@ import pyteal as pt -teal2Options = pt.CompileOptions(version=2) -teal3Options = pt.CompileOptions(version=3) -teal4Options = pt.CompileOptions(version=4) -teal5Options = pt.CompileOptions(version=5) -teal6Options = pt.CompileOptions(version=6) -teal7Options = pt.CompileOptions(version=7) +avm2Options = pt.CompileOptions(version=2) +avm3Options = pt.CompileOptions(version=3) +avm4Options = pt.CompileOptions(version=4) +avm5Options = pt.CompileOptions(version=5) +avm6Options = pt.CompileOptions(version=6) +avm7Options = pt.CompileOptions(version=7) def test_btoi(): @@ -19,7 +19,7 @@ def test_btoi(): [pt.TealOp(arg, pt.Op.arg, 1), pt.TealOp(expr, pt.Op.btoi)] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -40,7 +40,7 @@ def test_itob(): [pt.TealOp(arg, pt.Op.int, 1), pt.TealOp(expr, pt.Op.itob)] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -61,7 +61,7 @@ def test_len(): [pt.TealOp(arg, pt.Op.txn, "Receiver"), pt.TealOp(expr, pt.Op.len)] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -82,7 +82,7 @@ def test_bitlen_int(): [pt.TealOp(arg, pt.Op.int, 7), pt.TealOp(expr, pt.Op.bitlen)] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -98,7 +98,7 @@ def test_bitlen_bytes(): [pt.TealOp(arg, pt.Op.txn, "Receiver"), pt.TealOp(expr, pt.Op.bitlen)] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -114,7 +114,7 @@ def test_sha256(): [pt.TealOp(arg, pt.Op.arg, 0), pt.TealOp(expr, pt.Op.sha256)] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -135,7 +135,7 @@ def test_sha512_256(): [pt.TealOp(arg, pt.Op.arg, 0), pt.TealOp(expr, pt.Op.sha512_256)] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -156,7 +156,7 @@ def test_sha3_256(): [pt.TealOp(arg, pt.Op.arg, 0), pt.TealOp(expr, pt.Op.sha3_256)] ) - actual, _ = expr.__teal__(teal7Options) + actual, _ = expr.__teal__(avm7Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -177,7 +177,7 @@ def test_keccak256(): [pt.TealOp(arg, pt.Op.arg, 0), pt.TealOp(expr, pt.Op.keccak256)] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -198,7 +198,7 @@ def test_not(): [pt.TealOp(arg, pt.Op.int, 1), pt.TealOp(expr, pt.Op.logic_not)] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -219,7 +219,7 @@ def test_bitwise_not(): [pt.TealOp(arg, pt.Op.int, 2), pt.TealOp(expr, pt.Op.bitwise_not)] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -235,7 +235,7 @@ def test_bitwise_not_overload(): [pt.TealOp(arg, pt.Op.int, 10), pt.TealOp(expr, pt.Op.bitwise_not)] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -256,7 +256,7 @@ def test_sqrt(): [pt.TealOp(arg, pt.Op.int, 4), pt.TealOp(expr, pt.Op.sqrt)] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -277,7 +277,7 @@ def test_pop(): [pt.TealOp(arg_int, pt.Op.int, 3), pt.TealOp(expr_int, pt.Op.pop)] ) - actual_int, _ = expr_int.__teal__(teal2Options) + actual_int, _ = expr_int.__teal__(avm2Options) actual_int.addIncoming() actual_int = pt.TealBlock.NormalizeBlocks(actual_int) @@ -291,7 +291,7 @@ def test_pop(): [pt.TealOp(arg_bytes, pt.Op.txn, "Receiver"), pt.TealOp(expr_bytes, pt.Op.pop)] ) - actual_bytes, _ = expr_bytes.__teal__(teal2Options) + actual_bytes, _ = expr_bytes.__teal__(avm2Options) actual_bytes.addIncoming() actual_bytes = pt.TealBlock.NormalizeBlocks(actual_bytes) @@ -313,7 +313,7 @@ def test_balance(): [pt.TealOp(arg, pt.Op.int, 0), pt.TealOp(expr, pt.Op.balance)] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -329,7 +329,7 @@ def test_balance_direct_ref(): [pt.TealOp(arg, pt.Op.txn, "Sender"), pt.TealOp(expr, pt.Op.balance)] ) - actual, _ = expr.__teal__(teal2Options) + actual, _ = expr.__teal__(avm2Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -352,7 +352,7 @@ def test_min_balance(): [pt.TealOp(arg, pt.Op.int, 0), pt.TealOp(expr, pt.Op.min_balance)] ) - actual, _ = expr.__teal__(teal3Options) + actual, _ = expr.__teal__(avm3Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -368,7 +368,7 @@ def test_min_balance_direct_ref(): [pt.TealOp(arg, pt.Op.txn, "Sender"), pt.TealOp(expr, pt.Op.min_balance)] ) - actual, _ = expr.__teal__(teal3Options) + actual, _ = expr.__teal__(avm3Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -394,7 +394,7 @@ def test_b_not(): ] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -415,7 +415,7 @@ def test_bsqrt(): [pt.TealOp(arg, pt.Op.byte, "0xFEDCBA9876543210"), pt.TealOp(expr, pt.Op.bsqrt)] ) - actual, _ = expr.__teal__(teal6Options) + actual, _ = expr.__teal__(avm6Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -436,7 +436,7 @@ def test_b_zero(): [pt.TealOp(arg, pt.Op.int, 8), pt.TealOp(expr, pt.Op.bzero)] ) - actual, _ = expr.__teal__(teal4Options) + actual, _ = expr.__teal__(avm4Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) @@ -458,14 +458,14 @@ def test_log(): [pt.TealOp(arg, pt.Op.byte, '"message"'), pt.TealOp(expr, pt.Op.log)] ) - actual, _ = expr.__teal__(teal5Options) + actual, _ = expr.__teal__(avm5Options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) assert actual == expected with pytest.raises(pt.TealInputError): - expr.__teal__(teal4Options) + expr.__teal__(avm4Options) def test_log_invalid(): diff --git a/pyteal/ast/widemath.py b/pyteal/ast/widemath.py index 3098a7d3a..b70c4c2e8 100644 --- a/pyteal/ast/widemath.py +++ b/pyteal/ast/widemath.py @@ -90,7 +90,7 @@ def __init__( :code:`N_i` represents an element in :code:`numeratorFactors` and each :code:`D_i` represents an element in :code:`denominatorFactors`. - Requires TEAL version 5 or higher. + Requires program version 5 or higher. Args: numeratorFactors: The factors in the numerator of the ratio. This list must have at @@ -114,7 +114,7 @@ def __init__( def __teal__(self, options: "CompileOptions"): if options.version < Op.cover.min_version: raise TealCompileError( - "WideRatio requires TEAL version {} or higher".format( + "WideRatio requires program version {} or higher".format( Op.cover.min_version ), self, diff --git a/pyteal/compiler/__init__.py b/pyteal/compiler/__init__.py index 13a3e6e92..e0d29450d 100644 --- a/pyteal/compiler/__init__.py +++ b/pyteal/compiler/__init__.py @@ -2,6 +2,9 @@ MAX_TEAL_VERSION, MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, + MAX_PROGRAM_VERSION, + MIN_PROGRAM_VERSION, + DEFAULT_PROGRAM_VERSION, CompileOptions, compileTeal, ) @@ -12,6 +15,9 @@ "MAX_TEAL_VERSION", "MIN_TEAL_VERSION", "DEFAULT_TEAL_VERSION", + "MAX_PROGRAM_VERSION", + "MIN_PROGRAM_VERSION", + "DEFAULT_PROGRAM_VERSION", "CompileOptions", "compileTeal", "OptimizeOptions", diff --git a/pyteal/compiler/compiler.py b/pyteal/compiler/compiler.py index faf8717bd..f98396e36 100644 --- a/pyteal/compiler/compiler.py +++ b/pyteal/compiler/compiler.py @@ -25,9 +25,17 @@ ) from pyteal.compiler.constants import createConstantBlocks -MAX_TEAL_VERSION = 8 -MIN_TEAL_VERSION = 2 -DEFAULT_TEAL_VERSION = MIN_TEAL_VERSION +MAX_PROGRAM_VERSION = 8 +MIN_PROGRAM_VERSION = 2 +DEFAULT_PROGRAM_VERSION = MIN_PROGRAM_VERSION + + +"""Deprecated. Use MAX_PROGRAM_VERSION instead.""" +MAX_TEAL_VERSION = MAX_PROGRAM_VERSION +"""Deprecated. Use MIN_PROGRAM_VERSION instead.""" +MIN_TEAL_VERSION = MIN_PROGRAM_VERSION +"""Deprecated. Use DEFAULT_PROGRAM_VERSION instead.""" +DEFAULT_TEAL_VERSION = DEFAULT_PROGRAM_VERSION class CompileOptions: @@ -35,7 +43,7 @@ def __init__( self, *, mode: Mode = Mode.Signature, - version: int = DEFAULT_TEAL_VERSION, + version: int = DEFAULT_PROGRAM_VERSION, optimize: OptimizeOptions = None, ) -> None: self.mode = mode @@ -88,7 +96,7 @@ def verifyOpsForVersion(teal: List[TealComponent], version: int): op = stmt.getOp() if op.min_version > version: raise TealInputError( - "Op not supported in TEAL version {}: {}. Minimum required version is {}".format( + "Op not supported in program version {}: {}. Minimum required version is {}".format( version, op, op.min_version ) ) @@ -192,7 +200,7 @@ def compileTeal( ast: Expr, mode: Mode, *, - version: int = DEFAULT_TEAL_VERSION, + version: int = DEFAULT_PROGRAM_VERSION, assembleConstants: bool = False, optimize: OptimizeOptions = None, ) -> str: @@ -201,13 +209,13 @@ def compileTeal( Args: ast: The PyTeal expression to assemble. mode: The mode of the program to assemble. Must be Signature or Application. - version (optional): The TEAL version used to assemble the program. This will determine which + version (optional): The program version used to assemble the program. This will determine which expressions and fields are able to be used in the program and how expressions compile to TEAL opcodes. Defaults to 2 if not included. assembleConstants (optional): When true, the compiler will produce a program with fully assembled constants, rather than using the pseudo-ops `int`, `byte`, and `addr`. These constants will be assembled in the most space-efficient way, so enabling this may reduce - the compiled program's size. Enabling this option requires a minimum TEAL version of 3. + the compiled program's size. Enabling this option requires a minimum program version of 3. Defaults to false. optimize (optional): OptimizeOptions that determine which optimizations will be applied. @@ -219,12 +227,12 @@ def compileTeal( TealInternalError: if an internal error is encounter during compilation. """ if ( - not (MIN_TEAL_VERSION <= version <= MAX_TEAL_VERSION) + not (MIN_PROGRAM_VERSION <= version <= MAX_PROGRAM_VERSION) or type(version) is not int ): raise TealInputError( - "Unsupported TEAL version: {}. Excepted an integer in the range [{}, {}]".format( - version, MIN_TEAL_VERSION, MAX_TEAL_VERSION + "Unsupported program version: {}. Excepted an integer in the range [{}, {}]".format( + version, MIN_PROGRAM_VERSION, MAX_PROGRAM_VERSION ) ) @@ -265,7 +273,7 @@ def compileTeal( if assembleConstants: if version < 3: raise TealInternalError( - "The minimum TEAL version required to enable assembleConstants is 3. The current version is {}".format( + "The minimum program version required to enable assembleConstants is 3. The current version is {}".format( version ) ) diff --git a/pyteal/compiler/subroutines.py b/pyteal/compiler/subroutines.py index 6335b82b3..bcde38b1b 100644 --- a/pyteal/compiler/subroutines.py +++ b/pyteal/compiler/subroutines.py @@ -103,7 +103,7 @@ def spillLocalSlotsDuringRecursion( slots from being modifying by a new recursive invocation of the current subroutine. Args: - version: The current TEAL version being assembled. + version: The current program version being assembled. subroutineMapping: A dictionary containing a list of TealComponents for every subroutine in a program. The key None is taken to indicate the main program routine. This input may be modified by this function in order to spill subroutine slots. @@ -209,7 +209,7 @@ def spillLocalSlotsDuringRecursion( stackDistance, ) ) - # because we are stuck using dig instead of uncover in TEAL 4, we'll need to + # because we are stuck using dig instead of uncover in AVM 4, we'll need to # pop all of the dug up arguments after the function returns hideReturnValueInFirstSlot = False diff --git a/pyteal/errors.py b/pyteal/errors.py index 03e597e2f..f5b4d34ef 100644 --- a/pyteal/errors.py +++ b/pyteal/errors.py @@ -64,7 +64,7 @@ def __eq__(self, other) -> bool: TealCompileError.__module__ = "pyteal" -def verifyTealVersion(minVersion: int, version: int, msg: str): +def verifyProgramVersion(minVersion: int, version: int, msg: str): if minVersion > version: msg = "{}. Minimum version needed is {}, but current version being compiled is {}".format( msg, minVersion, version @@ -73,8 +73,8 @@ def verifyTealVersion(minVersion: int, version: int, msg: str): def verifyFieldVersion(fieldName: str, fieldMinVersion: int, version: int): - verifyTealVersion( + verifyProgramVersion( fieldMinVersion, version, - "TEAL version too low to use field {}".format(fieldName), + "Program version too low to use field {}".format(fieldName), ) diff --git a/pyteal/ir/ops.py b/pyteal/ir/ops.py index d87c76250..c0be2e59c 100644 --- a/pyteal/ir/ops.py +++ b/pyteal/ir/ops.py @@ -181,7 +181,7 @@ def min_version(self) -> int: acct_params_get = OpType("acct_params_get", Mode.Application, 6) replace2 = OpType("replace2", Mode.Signature | Mode.Application, 7) replace3 = OpType("replace3", Mode.Signature | Mode.Application, 7) - base64_decode = OpType("base64_decode", Mode.Application | Mode.Signature, 7) + base64_decode = OpType("base64_decode", Mode.Signature | Mode.Application, 7) json_ref = OpType("json_ref", Mode.Signature | Mode.Application, 7) ed25519verify_bare = OpType("ed25519verify_bare", Mode.Signature | Mode.Application, 7) sha3_256 = OpType("sha3_256", Mode.Signature | Mode.Application, 7) From 055c981619904f0a4cb979ff48dad05eccf1e432 Mon Sep 17 00:00:00 2001 From: Hang Su <87964331+ahangsu@users.noreply.github.com> Date: Wed, 3 Aug 2022 18:46:21 -0400 Subject: [PATCH 014/157] change according to https://github.com/algorand/go-algorand/pull/4323/files (#488) --- pyteal/ast/box.py | 6 +++--- pyteal/ast/box_test.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pyteal/ast/box.py b/pyteal/ast/box.py index 368c001e0..119f7f24e 100644 --- a/pyteal/ast/box.py +++ b/pyteal/ast/box.py @@ -33,14 +33,14 @@ def __teal__(self, options: "CompileOptions"): msg=f"{Op.box_create} unavailable", ) return TealBlock.FromOp( - options, TealOp(self, Op.box_create), self.size, self.name + options, TealOp(self, Op.box_create), self.name, self.size ) def __str__(self): return f"(box_create {self.name} {self.size})" def type_of(self): - return TealType.none + return TealType.uint64 def has_return(self): return False @@ -73,7 +73,7 @@ def __str__(self): return f"(box_del {self.name})" def type_of(self): - return TealType.none + return TealType.uint64 def has_return(self): return False diff --git a/pyteal/ast/box_test.py b/pyteal/ast/box_test.py index 4000b3974..c3ec419f3 100644 --- a/pyteal/ast/box_test.py +++ b/pyteal/ast/box_test.py @@ -7,8 +7,8 @@ avm8Options = pt.CompileOptions(version=8) POSITIVE_TEST_CASES: list[Tuple[pt.Expr, pt.TealType]] = [ - (pt.BoxCreate(pt.Bytes("box"), pt.Int(10)), pt.TealType.none), - (pt.BoxDelete(pt.Bytes("box")), pt.TealType.none), + (pt.BoxCreate(pt.Bytes("box"), pt.Int(10)), pt.TealType.uint64), + (pt.BoxDelete(pt.Bytes("box")), pt.TealType.uint64), (pt.BoxExtract(pt.Bytes("box"), pt.Int(2), pt.Int(4)), pt.TealType.bytes), ( pt.BoxReplace(pt.Bytes("box"), pt.Int(3), pt.Bytes("replace")), @@ -57,8 +57,8 @@ def test_box_create_compile(): expected = pt.TealSimpleBlock( [ - pt.TealOp(size_arg, pt.Op.int, 10), pt.TealOp(name_arg, pt.Op.byte, '"eineName"'), + pt.TealOp(size_arg, pt.Op.int, 10), pt.TealOp(expr, pt.Op.box_create), ] ) From 76010b27c81e0b52fba33814f3124c7ee982e921 Mon Sep 17 00:00:00 2001 From: Jason Paulos Date: Thu, 29 Sep 2022 12:31:21 -0700 Subject: [PATCH 015/157] Changes to avm8 docs (#546) --- docs/state.rst | 63 +++++++++++++++++++++++++----------------- pyteal/ast/app.py | 42 +++++++++++++++------------- pyteal/ast/box_test.py | 16 +++++------ pyteal/ast/maybe.py | 4 +-- 4 files changed, 70 insertions(+), 55 deletions(-) diff --git a/docs/state.rst b/docs/state.rst index adb585b26..b45a5a0c6 100644 --- a/docs/state.rst +++ b/docs/state.rst @@ -28,8 +28,8 @@ Current App Global :any:`App.globalPut` :any:`App.gl Current App Local :any:`App.localPut` :any:`App.localGet` :any:`App.localDel` :any:`App.localGetEx` Other App Global :any:`App.globalGetEx` :any:`App.globalGetEx` Other App Local :any:`App.localGetEx` :any:`App.localGetEx` -Current App Boxes | :any:`App.box_create` | :any:`App.box_put` | :any:`App.box_extract` :any:`App.box_delete` | :any:`App.box_length` - | :any:`App.box_put` | :any:`App.box_replace` | :any:`App.box_get` | :any:`App.box_get` +Current App Boxes :any:`App.box_create` :any:`App.box_put` :any:`App.box_extract` :any:`App.box_delete` :any:`App.box_length` + :any:`App.box_put` :any:`App.box_replace` :any:`App.box_get` :any:`App.box_get` ================== ======================= ======================== ======================== ===================== ======================= Global State @@ -279,30 +279,35 @@ Creating Boxes To create a box, use :any:`App.box_create`, or :any:`App.box_put` method. -:any:`App.box_create` makes a box with a specified name and byte length. -The first argument is the box name, and the second argument is the byte size to be allocated. +For :any:`App.box_create`, the first argument is the box name, and the second argument is the byte size to be allocated. + +:any:`App.box_create` creates a new box with the specified name and byte length. New boxes will contain a byte string of all zeros. Performing this operation on a box that already exists will not change its contents. + +If successful, :any:`App.box_create` will return :code:`0` if the box already existed, otherwise it will return :code:`1`. A failure will occur if you attempt to create a box that already exists with a different size. For example: .. code-block:: python - # Allocate a box called "BoxA" of byte size 100 - App.box_create(Bytes("BoxA"), Int(100)) - # Allocate a box called "BoxB" of byte size 90 - App.box_create(Bytes("BoxB"), Int(90) + # Allocate a box called "BoxA" of byte size 100 and ignore the return value + Pop(App.box_create(Bytes("BoxA"), Int(100))) + + # Allocate a box called "BoxB" of byte size 90, asserting that it didn't exist before. + Assert(App.box_create(Bytes("BoxB"), Int(90)) For :any:`App.box_put`, the first argument is the box name to create or to write to, and the second argument is the bytes to write. .. note:: If the box exists, then :any:`App.box_put` will write the contents to the box - (fails when the replacement length is **not identical** to the box's byte size); + (fails when the content length is **not identical** to the existing box's byte size); otherwise, it will create a box containing exactly the same input bytes. .. code-block:: python # create a 42 bytes length box called `poemLine` with content App.box_put(Bytes("poemLine"), Bytes("Of that colossal wreck, boundless and bare")) + # write to box `poemLine` with new value App.box_put(Bytes("poemLine"), Bytes("The lone and level sands stretch far away.")) @@ -335,7 +340,7 @@ and the third argument is the length of bytes to extract. For example: .. code-block:: python - # extract a segment of length 10 starting at the 5'th byte in a box named `NoteBook` + # extract a segment of length 10 starting at the 5th byte in a box named `NoteBook` App.box_extract(Bytes("NoteBook"), Int(5), Int(10)) :any:`App.box_get` gets the full contents of a box. @@ -348,27 +353,29 @@ For example: .. code-block:: python - # get the full contents from a box named `NoteBook` - App.box_get(Bytes("NoteBook")).value() - - -.. note:: - - :any:`App.box_get` can also be used to check the existence of a box. For example: - - .. code-block:: python - - # check existence of a box named `NoteBook` - App.box_get(Bytes("NoteBook")).hasValue() + # get the full contents from a box named `NoteBook`, asserting that it exists + Seq( + contents := App.box_get(Bytes("NoteBook")), + Assert(contents.hasValue()), + contents.value() + ) Deleting a Box ~~~~~~~~~~~~~~ -To delete a box, use :any:`App.box_delete` method. The only argument is the box name. For example: +To delete a box, use :any:`App.box_delete` method. The only argument is the box name. + +:any:`App.box_delete` will return :code:`1` if the box already existed, otherwise it will return :code:`0`. Deleting a nonexistent box is allowed, but has no effect. + +For example: .. code-block:: python - App.box_delete(Bytes("boxToRemove")) + # delete the box `boxToRemove`, asserting that it existed prior to this + Assert(App.box_delete(Bytes("boxToRemove"))) + + # delete the box `mightExist` and ignore the return value + Pop(App.box_delete(Bytes("mightExist"))) Checking if a Box Exists and Reads its Length ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -383,8 +390,12 @@ For example: .. code-block:: python - # search for the box length for box `someBox`, and get the bool value for box existence - App.box_length(Bytes("someBox")).hasValue() + # get the length of the box `someBox`, and assert that the box exists + Seq( + length := App.box_length(Bytes("someBox")), + Assert(length.hasValue()), + length.value() + ) .. note:: diff --git a/pyteal/ast/app.py b/pyteal/ast/app.py index cf9993d46..e6f9d0de9 100644 --- a/pyteal/ast/app.py +++ b/pyteal/ast/app.py @@ -221,9 +221,15 @@ def globalDel(cls, key: Expr) -> "App": return cls(AppField.globalDel, [key]) @classmethod - def box_create(cls, name: Expr, size: Expr) -> BoxCreate: - """ - Create a box with a given name and size. + def box_create(cls, name: Expr, size: Expr) -> Expr: + """Create a box with a given name and size. + + New boxes will contain a byte string of all zeros. Performing this operation on a box that + already exists will not change its contents. + + If successful, this expression returns 0 if the box already existed, otherwise it returns 1. + + A failure will occur if you attempt to create a box that already exists with a different size. Args: name: The key used to reference this box. Must evaluate to a bytes. @@ -232,9 +238,12 @@ def box_create(cls, name: Expr, size: Expr) -> BoxCreate: return BoxCreate(name, size) @classmethod - def box_delete(cls, name: Expr) -> BoxDelete: - """ - Deletes a box given it's name. + def box_delete(cls, name: Expr) -> Expr: + """Deletes a box given it's name. + + This expression returns 1 if the box existed, otherwise it returns 0. + + Deleting a nonexistent box is allowed, but has no effect. Args: name: The key the box was created with. Must evaluate to bytes. @@ -242,9 +251,8 @@ def box_delete(cls, name: Expr) -> BoxDelete: return BoxDelete(name) @classmethod - def box_extract(cls, name: Expr, start: Expr, length: Expr) -> BoxExtract: - """ - Extracts bytes in a box given its name, start index and stop index. + def box_extract(cls, name: Expr, start: Expr, length: Expr) -> Expr: + """Extracts bytes in a box given its name, start index and stop index. Args: name: The key the box was created with. Must evaluate to bytes. @@ -254,9 +262,8 @@ def box_extract(cls, name: Expr, start: Expr, length: Expr) -> BoxExtract: return BoxExtract(name, start, length) @classmethod - def box_replace(cls, name: Expr, start: Expr, value: Expr) -> BoxReplace: - """ - Replaces bytes in a box given its name, start index, and value. + def box_replace(cls, name: Expr, start: Expr, value: Expr) -> Expr: + """Replaces bytes in a box given its name, start index, and value. Args: name: The key the box was created with. Must evaluate to bytes. @@ -267,8 +274,7 @@ def box_replace(cls, name: Expr, start: Expr, value: Expr) -> BoxReplace: @classmethod def box_length(cls, name: Expr) -> MaybeValue: - """ - Get the byte length of the box specified by its name. + """Get the byte length of the box specified by its name. Args: name: The key the box was created with. Must evaluate to bytes. @@ -277,8 +283,7 @@ def box_length(cls, name: Expr) -> MaybeValue: @classmethod def box_get(cls, name: Expr) -> MaybeValue: - """ - Get the full contents of a box given its name. + """Get the full contents of a box given its name. Args: name: The key the box was created with. Must evaluate to bytes. @@ -286,9 +291,8 @@ def box_get(cls, name: Expr) -> MaybeValue: return BoxGet(name) @classmethod - def box_put(cls, name: Expr, value: Expr) -> BoxPut: - """ - Write all contents to a box given its name. + def box_put(cls, name: Expr, value: Expr) -> Expr: + """Write all contents to a box given its name. Args: name: The key the box was created with. Must evaluate to bytes. diff --git a/pyteal/ast/box_test.py b/pyteal/ast/box_test.py index c3ec419f3..008ffb580 100644 --- a/pyteal/ast/box_test.py +++ b/pyteal/ast/box_test.py @@ -131,10 +131,10 @@ def test_box_length(): expected = pt.TealSimpleBlock( [ - pt.TealOp(name_arg, pt.Op.byte, '"eineName"'), - pt.TealOp(expr, pt.Op.box_len), - pt.TealOp(expr.output_slots[1].store(), pt.Op.store, expr.output_slots[1]), - pt.TealOp(expr.output_slots[0].store(), pt.Op.store, expr.output_slots[0]), + pt.TealOp(None, pt.Op.byte, '"eineName"'), + pt.TealOp(None, pt.Op.box_len), + pt.TealOp(None, pt.Op.store, expr.output_slots[1]), + pt.TealOp(None, pt.Op.store, expr.output_slots[0]), ] ) actual, _ = expr.__teal__(avm8Options) @@ -151,10 +151,10 @@ def test_box_get(): expected = pt.TealSimpleBlock( [ - pt.TealOp(name_arg, pt.Op.byte, '"eineName"'), - pt.TealOp(expr, pt.Op.box_get), - pt.TealOp(expr.output_slots[1].store(), pt.Op.store, expr.output_slots[1]), - pt.TealOp(expr.output_slots[0].store(), pt.Op.store, expr.output_slots[0]), + pt.TealOp(None, pt.Op.byte, '"eineName"'), + pt.TealOp(None, pt.Op.box_get), + pt.TealOp(None, pt.Op.store, expr.output_slots[1]), + pt.TealOp(None, pt.Op.store, expr.output_slots[0]), ] ) actual, _ = expr.__teal__(avm8Options) diff --git a/pyteal/ast/maybe.py b/pyteal/ast/maybe.py index 4d863e6ff..4c6091953 100644 --- a/pyteal/ast/maybe.py +++ b/pyteal/ast/maybe.py @@ -67,7 +67,7 @@ def value(self) -> ScratchLoad: def slotOk(self) -> ScratchSlot: """Get the scratch slot that stores hasValue. - Note: This is mainly added for backwards compatability and normally shouldn't be used + Note: This is mainly added for backwards compatibility and normally shouldn't be used directly in pyteal code. """ return self.output_slots[1] @@ -77,7 +77,7 @@ def slotValue(self) -> ScratchSlot: """Get the scratch slot that stores the value or the zero value for the type if the value doesn't exist. - Note: This is mainly added for backwards compatability and normally shouldn't be used + Note: This is mainly added for backwards compatibility and normally shouldn't be used directly in pyteal code. """ return self.output_slots[0] From cc49a55b96356108068b1771a785451438b68e11 Mon Sep 17 00:00:00 2001 From: Jacob Daitzman Date: Wed, 26 Oct 2022 07:50:23 -0400 Subject: [PATCH 016/157] Support new AVM 8 account parameters (#555) --- pyteal/ast/acct.py | 225 ++++++++++++++++++++++++++++++++++++---- pyteal/ast/acct_test.py | 190 ++++++++++++++++++++------------- pyteal/ast/maybe.py | 14 ++- 3 files changed, 332 insertions(+), 97 deletions(-) diff --git a/pyteal/ast/acct.py b/pyteal/ast/acct.py index 7f61e10ee..7bc19ec78 100644 --- a/pyteal/ast/acct.py +++ b/pyteal/ast/acct.py @@ -1,12 +1,67 @@ -from typing import Final +from enum import Enum +from typing import Final, TYPE_CHECKING +from pyteal.errors import verifyFieldVersion, verifyProgramVersion from pyteal.types import TealType, require_type from pyteal.ir import Op from pyteal.ast.expr import Expr from pyteal.ast.maybe import MaybeValue +if TYPE_CHECKING: + from pyteal.compiler import CompileOptions + + +class AccountParamField(Enum): + # fmt: off + # id | name | type | min version + balance = (0, "AcctBalance", TealType.uint64, 6) # noqa: E221 + min_balance = (1, "AcctMinBalance", TealType.uint64, 6) # noqa: E221 + auth_addr = (2, "AcctAuthAddr", TealType.bytes, 6) # noqa: E221 + total_num_uint = (3, "AcctTotalNumUint", TealType.uint64, 8) # noqa: E221 + total_num_byte_slice = (4, "AcctTotalNumByteSlice", TealType.uint64, 8) # noqa: E221 + total_extra_app_pages = (5, "AcctTotalExtraAppPages", TealType.uint64, 8) # noqa: E221 + total_apps_created = (6, "AcctTotalAppsCreated", TealType.uint64, 8) # noqa: E221 + total_apps_opted_in = (7, "AcctTotalAppsOptedIn", TealType.uint64, 8) # noqa: E221 + total_assets_created = (8, "AcctTotalAssetsCreated", TealType.uint64, 8) # noqa: E221 + total_assets = (9, "AcctTotalAssets", TealType.uint64, 8) # noqa: E221 + total_boxes = (10, "AcctTotalBoxes", TealType.uint64, 8) # noqa: E221 + total_box_bytes = (11, "AcctTotalBoxBytes", TealType.uint64, 8) # noqa: E221 + # fmt: on + + def __init__(self, id: int, name: str, type: TealType, min_version: int) -> None: + self.id = id + self.arg_name = name + self.type = type + self.min_version = min_version + + def type_of(self) -> TealType: + return self.type + + +AccountParamField.__module__ = "pyteal" + class AccountParam: + @staticmethod + def __makeAccountParamExpr(field: AccountParamField, acct: Expr) -> MaybeValue: + require_type(acct, TealType.anytype) + + def field_and_program_version_check(options: "CompileOptions"): + verifyProgramVersion( + minVersion=Op.acct_params_get.min_version, + version=options.version, + msg=f"{Op.acct_params_get.value} unavailable", + ) + verifyFieldVersion(field.arg_name, field.min_version, options.version) + + return MaybeValue( + Op.acct_params_get, + field.type_of(), + immediate_args=[field.arg_name], + args=[acct], + compile_check=field_and_program_version_check, + ) + @classmethod def balance(cls, acct: Expr) -> MaybeValue: """Get the current balance in microalgos an account. @@ -15,13 +70,7 @@ def balance(cls, acct: Expr) -> MaybeValue: acct: An index into Txn.accounts that corresponds to the application to check or an address available at runtime. May evaluate to uint64 or an address. """ - require_type(acct, TealType.anytype) - return MaybeValue( - Op.acct_params_get, - TealType.uint64, - immediate_args=["AcctBalance"], - args=[acct], - ) + return cls.__makeAccountParamExpr(AccountParamField.balance, acct) @classmethod def minBalance(cls, acct: Expr) -> MaybeValue: @@ -31,13 +80,7 @@ def minBalance(cls, acct: Expr) -> MaybeValue: acct: An index into Txn.accounts that corresponds to the application to check or an address available at runtime. May evaluate to uint64 or an address. """ - require_type(acct, TealType.anytype) - return MaybeValue( - Op.acct_params_get, - TealType.uint64, - immediate_args=["AcctMinBalance"], - args=[acct], - ) + return cls.__makeAccountParamExpr(AccountParamField.min_balance, acct) @classmethod def authAddr(cls, acct: Expr) -> MaybeValue: @@ -47,13 +90,115 @@ def authAddr(cls, acct: Expr) -> MaybeValue: acct: An index into Txn.accounts that corresponds to the application to check or an address available at runtime. May evaluate to uint64 or an address. """ - require_type(acct, TealType.anytype) - return MaybeValue( - Op.acct_params_get, - TealType.bytes, - immediate_args=["AcctAuthAddr"], - args=[acct], - ) + return cls.__makeAccountParamExpr(AccountParamField.auth_addr, acct) + + @classmethod + def totalNumUint(cls, acct: Expr) -> MaybeValue: + """Get the total number of uint64 values allocated by the account in Global and Local States. + + Requires program version 8 or higher. + + Args: + acct: An index into Txn.accounts that corresponds to the application to check or an address available at runtime. + May evaluate to uint64 or an address. + """ + return cls.__makeAccountParamExpr(AccountParamField.total_num_uint, acct) + + @classmethod + def totalNumByteSlice(cls, acct: Expr) -> MaybeValue: + """Get the total number of byte array values allocated by the account in Global and Local States. + + Requires program version 8 or higher. + + Args: + acct: An index into Txn.accounts that corresponds to the application to check or an address available at runtime. + May evaluate to uint64 or an address. + """ + return cls.__makeAccountParamExpr(AccountParamField.total_num_byte_slice, acct) + + @classmethod + def totalExtraAppPages(cls, acct: Expr) -> MaybeValue: + """Get the number of extra app code pages used by the account. + + Requires program version 8 or higher. + + Args: + acct: An index into Txn.accounts that corresponds to the application to check or an address available at runtime. + May evaluate to uint64 or an address. + """ + return cls.__makeAccountParamExpr(AccountParamField.total_extra_app_pages, acct) + + @classmethod + def totalAppsCreated(cls, acct: Expr) -> MaybeValue: + """Get the number of existing apps created by the account. + + Requires program version 8 or higher. + + Args: + acct: An index into Txn.accounts that corresponds to the application to check or an address available at runtime. + May evaluate to uint64 or an address. + """ + return cls.__makeAccountParamExpr(AccountParamField.total_apps_created, acct) + + @classmethod + def totalAppsOptedIn(cls, acct: Expr) -> MaybeValue: + """Get the number of apps the account is opted into. + + Requires program version 8 or higher. + + Args: + acct: An index into Txn.accounts that corresponds to the application to check or an address available at runtime. + May evaluate to uint64 or an address. + """ + return cls.__makeAccountParamExpr(AccountParamField.total_apps_opted_in, acct) + + @classmethod + def totalAssetsCreated(cls, acct: Expr) -> MaybeValue: + """Get the number of existing ASAs created by the account. + + Requires program version 8 or higher. + + Args: + acct: An index into Txn.accounts that corresponds to the application to check or an address available at runtime. + May evaluate to uint64 or an address. + """ + return cls.__makeAccountParamExpr(AccountParamField.total_assets_created, acct) + + @classmethod + def totalAssets(cls, acct: Expr) -> MaybeValue: + """Get the number of ASAs held by the account (including ASAs the account created). + + Requires program version 8 or higher. + + Args: + acct: An index into Txn.accounts that corresponds to the application to check or an address available at runtime. + May evaluate to uint64 or an address. + """ + return cls.__makeAccountParamExpr(AccountParamField.total_assets, acct) + + @classmethod + def totalBoxes(cls, acct: Expr) -> MaybeValue: + """Get the number of existing boxes created by the account's app. + + Requires program version 8 or higher. + + Args: + acct: An index into Txn.accounts that corresponds to the application to check or an address available at runtime. + May evaluate to uint64 or an address. + """ + return cls.__makeAccountParamExpr(AccountParamField.total_boxes, acct) + + @classmethod + def totalBoxBytes(cls, acct: Expr) -> MaybeValue: + """Get the total number of bytes used by the account's app's box keys and values. + + Requires program version 8 or higher. + + Args: + acct: An index into Txn.accounts that corresponds to the application to check or an address available at runtime. + May evaluate to uint64 or an address. + """ + return cls.__makeAccountParamExpr(AccountParamField.total_box_bytes, acct) AccountParam.__module__ = "pyteal" @@ -85,5 +230,41 @@ def auth_address(self) -> MaybeValue: If the account is not rekeyed, the empty address is returned.""" return AccountParam.authAddr(self._account) + def total_num_uint(self) -> MaybeValue: + """Get the total number of uint64 values allocated by the account in Global and Local States.""" + return AccountParam.totalNumUint(self._account) + + def total_num_byte_slice(self) -> MaybeValue: + """Get the total number of byte array values allocated by the account in Global and Local States.""" + return AccountParam.totalNumByteSlice(self._account) + + def total_extra_app_pages(self) -> MaybeValue: + """Get the number of extra app code pages used by the account.""" + return AccountParam.totalExtraAppPages(self._account) + + def total_apps_created(self) -> MaybeValue: + """Get the number of existing apps created by the account.""" + return AccountParam.totalAppsCreated(self._account) + + def total_apps_opted_in(self) -> MaybeValue: + """Get the number of apps the account is opted into.""" + return AccountParam.totalAppsOptedIn(self._account) + + def total_assets_created(self) -> MaybeValue: + """Get the number of existing ASAs created by the account.""" + return AccountParam.totalAssetsCreated(self._account) + + def total_assets(self) -> MaybeValue: + """Get the number of ASAs held by the account (including ASAs the account created).""" + return AccountParam.totalAssets(self._account) + + def total_boxes(self) -> MaybeValue: + """Get the number of existing boxes created by the account's app.""" + return AccountParam.totalBoxes(self._account) + + def total_box_bytes(self) -> MaybeValue: + """Get the total number of bytes used by the account's app's box keys and values.""" + return AccountParam.totalBoxBytes(self._account) + AccountParamObject.__module__ = "pyteal" diff --git a/pyteal/ast/acct_test.py b/pyteal/ast/acct_test.py index e4f12f958..8259f8ac6 100644 --- a/pyteal/ast/acct_test.py +++ b/pyteal/ast/acct_test.py @@ -1,79 +1,89 @@ +import pytest + import pyteal as pt +from pyteal.ast.acct import AccountParamField from pyteal.ast.maybe_test import assert_MaybeValue_equality -options = pt.CompileOptions() -avm4Options = pt.CompileOptions(version=4) -avm5Options = pt.CompileOptions(version=5) avm6Options = pt.CompileOptions(version=6) +avm8Options = pt.CompileOptions(version=8) + + +@pytest.mark.parametrize( + "method_name,field_name", + [ + ("balance", "balance"), + ("minBalance", "min_balance"), + ("authAddr", "auth_addr"), + ("totalNumUint", "total_num_uint"), + ("totalNumByteSlice", "total_num_byte_slice"), + ("totalExtraAppPages", "total_extra_app_pages"), + ("totalAppsCreated", "total_apps_created"), + ("totalAppsOptedIn", "total_apps_opted_in"), + ("totalAssetsCreated", "total_assets_created"), + ("totalAssets", "total_assets"), + ("totalBoxes", "total_boxes"), + ("totalBoxBytes", "total_box_bytes"), + ], +) +class TestAcctParam: + @staticmethod + def test_acct_param_fields_valid(method_name, field_name): + arg = pt.Int(1) + account_param_method = getattr(pt.AccountParam, method_name) + expr = account_param_method(arg) + assert expr.type_of() == pt.TealType.none + + account_param_field = AccountParamField[field_name] + assert expr.value().type_of() == account_param_field.type_of() + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(arg, pt.Op.int, 1), + pt.TealOp(expr, pt.Op.acct_params_get, account_param_field.arg_name), + pt.TealOp(None, pt.Op.store, expr.slotOk), + pt.TealOp(None, pt.Op.store, expr.slotValue), + ] + ) - -def test_acct_param_balance_valid(): - arg = pt.Int(1) - expr = pt.AccountParam.balance(arg) - assert expr.type_of() == pt.TealType.none - assert expr.value().type_of() == pt.TealType.uint64 - - expected = pt.TealSimpleBlock( - [ - pt.TealOp(arg, pt.Op.int, 1), - pt.TealOp(expr, pt.Op.acct_params_get, "AcctBalance"), - pt.TealOp(None, pt.Op.store, expr.slotOk), - pt.TealOp(None, pt.Op.store, expr.slotValue), - ] - ) - - actual, _ = expr.__teal__(avm6Options) - actual.addIncoming() - actual = pt.TealBlock.NormalizeBlocks(actual) - - with pt.TealComponent.Context.ignoreExprEquality(): - assert actual == expected - - -def test_acct_param_min_balance_valid(): - arg = pt.Int(0) - expr = pt.AccountParam.minBalance(arg) - assert expr.type_of() == pt.TealType.none - assert expr.value().type_of() == pt.TealType.uint64 - - expected = pt.TealSimpleBlock( - [ - pt.TealOp(arg, pt.Op.int, 0), - pt.TealOp(expr, pt.Op.acct_params_get, "AcctMinBalance"), - pt.TealOp(None, pt.Op.store, expr.slotOk), - pt.TealOp(None, pt.Op.store, expr.slotValue), - ] - ) - - actual, _ = expr.__teal__(avm6Options) - actual.addIncoming() - actual = pt.TealBlock.NormalizeBlocks(actual) - - with pt.TealComponent.Context.ignoreExprEquality(): - assert actual == expected - - -def test_acct_param_auth_addr_valid(): - arg = pt.Int(1) - expr = pt.AccountParam.authAddr(arg) - assert expr.type_of() == pt.TealType.none - assert expr.value().type_of() == pt.TealType.bytes - - expected = pt.TealSimpleBlock( - [ - pt.TealOp(arg, pt.Op.int, 1), - pt.TealOp(expr, pt.Op.acct_params_get, "AcctAuthAddr"), - pt.TealOp(None, pt.Op.store, expr.slotOk), - pt.TealOp(None, pt.Op.store, expr.slotValue), - ] - ) - - actual, _ = expr.__teal__(avm6Options) - actual.addIncoming() - actual = pt.TealBlock.NormalizeBlocks(actual) - - with pt.TealComponent.Context.ignoreExprEquality(): - assert actual == expected + supported_options_version = pt.CompileOptions( + version=account_param_field.min_version + ) + actual, _ = expr.__teal__(supported_options_version) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + with pt.TealComponent.Context.ignoreExprEquality(): + assert actual == expected + + @staticmethod + def test_acct_param_version_checks(method_name, field_name): + arg = pt.Int(1) + account_param_method = getattr(pt.AccountParam, method_name) + expr = account_param_method(arg) + + account_param_field = AccountParamField[field_name] + + def test_unsupported_version(version: int, match: str = None): + with pytest.raises(pt.TealInputError, match=match): + unsupported_options_version = pt.CompileOptions(version=version) + expr.__teal__(unsupported_options_version) + + # Test program and field version checks + program_unsupported_version = pt.ir.Op.acct_params_get.min_version - 1 + program_error_match = "unavailable" + test_unsupported_version(program_unsupported_version, program_error_match) + + field_unsupported_version = account_param_field.min_version - 1 + + # Since program version dominates, we conditionally check field error message or program error message + # depending on whether the unsupported field version is less than or equal to the program unsupported + # version. + field_error_match = ( + "Program version too low to use field" + if field_unsupported_version > program_unsupported_version + else program_error_match + ) + test_unsupported_version(field_unsupported_version, field_error_match) def test_AccountParamObject(): @@ -94,3 +104,41 @@ def test_AccountParamObject(): assert_MaybeValue_equality( obj.auth_address(), pt.AccountParam.authAddr(account), avm6Options ) + + assert_MaybeValue_equality( + obj.total_num_uint(), pt.AccountParam.totalNumUint(account), avm8Options + ) + assert_MaybeValue_equality( + obj.total_num_byte_slice(), + pt.AccountParam.totalNumByteSlice(account), + avm8Options, + ) + assert_MaybeValue_equality( + obj.total_extra_app_pages(), + pt.AccountParam.totalExtraAppPages(account), + avm8Options, + ) + assert_MaybeValue_equality( + obj.total_apps_created(), + pt.AccountParam.totalAppsCreated(account), + avm8Options, + ) + assert_MaybeValue_equality( + obj.total_apps_opted_in(), + pt.AccountParam.totalAppsOptedIn(account), + avm8Options, + ) + assert_MaybeValue_equality( + obj.total_assets_created(), + pt.AccountParam.totalAssetsCreated(account), + avm8Options, + ) + assert_MaybeValue_equality( + obj.total_assets(), pt.AccountParam.totalAssets(account), avm8Options + ) + assert_MaybeValue_equality( + obj.total_boxes(), pt.AccountParam.totalBoxes(account), avm8Options + ) + assert_MaybeValue_equality( + obj.total_box_bytes(), pt.AccountParam.totalBoxBytes(account), avm8Options + ) diff --git a/pyteal/ast/maybe.py b/pyteal/ast/maybe.py index 4c6091953..9ae1f0245 100644 --- a/pyteal/ast/maybe.py +++ b/pyteal/ast/maybe.py @@ -1,4 +1,4 @@ -from typing import List, Union, TYPE_CHECKING +from typing import Callable, List, Union, TYPE_CHECKING from pyteal.errors import verifyProgramVersion from pyteal.types import TealType @@ -22,6 +22,7 @@ def __init__( *, immediate_args: List[Union[int, str]] = None, args: List[Expr] = None, + compile_check: Callable[["CompileOptions"], None] = None, ): """Create a new MaybeValue. @@ -30,12 +31,15 @@ def __init__( type: The type of the returned value. immediate_args (optional): Immediate arguments for the op. Defaults to None. args (optional): Stack arguments for the op. Defaults to None. + compile_check (optional): Callable compile check. Defaults to program version check. + This parameter overwrites the default program version check. """ - def local_version_check(option: "CompileOptions"): + # Default compile check if one is not given + def local_version_check(options: "CompileOptions"): verifyProgramVersion( minVersion=op.min_version, - version=option.version, + version=options.version, msg=f"{op.value} unavailable", ) @@ -45,7 +49,9 @@ def local_version_check(option: "CompileOptions"): types, immediate_args=immediate_args, args=args, - compile_check=local_version_check, + compile_check=( + local_version_check if compile_check is None else compile_check + ), ) def hasValue(self) -> ScratchLoad: From 1d7cd6ad0b5b01eec9a9e3fa428020eb42493b4b Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 26 Oct 2022 09:56:48 -0400 Subject: [PATCH 017/157] add frame ops to avm8 branch --- pyteal/__init__.pyi | 6 ++ pyteal/ast/__init__.py | 7 ++ pyteal/ast/frame.py | 188 +++++++++++++++++++++++++++++++++++++++ pyteal/ast/frame_test.py | 159 +++++++++++++++++++++++++++++++++ pyteal/ir/ops.py | 8 +- 5 files changed, 367 insertions(+), 1 deletion(-) create mode 100644 pyteal/ast/frame.py create mode 100644 pyteal/ast/frame_test.py diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index ce347b0eb..69e3c55eb 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -70,6 +70,7 @@ __all__ = [ "BoxReplace", "Break", "Btoi", + "Bury", "Bytes", "BytesAdd", "BytesAnd", @@ -98,6 +99,7 @@ __all__ = [ "DEFAULT_TEAL_VERSION", "Div", "Divw", + "DupN", "DynamicScratchVar", "EcdsaCurve", "EcdsaDecompress", @@ -115,6 +117,8 @@ __all__ = [ "ExtractUint32", "ExtractUint64", "For", + "FrameBury", + "FrameDig", "Ge", "GeneratedID", "GetBit", @@ -173,7 +177,9 @@ __all__ = [ "OptimizeOptions", "Or", "Pop", + "PopN", "Pragma", + "Proto", "RETURN_HASH_PREFIX", "Reject", "Replace", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 9efe807c5..1ca49a2e5 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -155,6 +155,7 @@ from pyteal.ast.for_ import For from pyteal.ast.break_ import Break from pyteal.ast.continue_ import Continue +from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN, Bury # misc from pyteal.ast.scratch import ( @@ -336,6 +337,12 @@ "For", "Break", "Continue", + "Proto", + "FrameDig", + "FrameBury", + "Bury", + "DupN", + "PopN", "Router", "CallConfig", "MethodConfig", diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py new file mode 100644 index 000000000..8b1cb6080 --- /dev/null +++ b/pyteal/ast/frame.py @@ -0,0 +1,188 @@ +from typing import TYPE_CHECKING + +from pyteal.ast.expr import Expr +from pyteal.types import TealType, require_type +from pyteal.errors import TealInputError, verifyProgramVersion +from pyteal.ir import TealBlock, TealSimpleBlock, TealOp, Op + +if TYPE_CHECKING: + from pyteal.compiler import CompileOptions + + +class Proto(Expr): + def __init__(self, arg_num: int, ret_num: int): + super().__init__() + if arg_num < 0: + raise TealInputError(f"subroutine arg number {arg_num} must be >= 0") + if ret_num < 0: + raise TealInputError(f"return value number {ret_num} must be >= 0") + self.arg_num = arg_num + self.ret_num = ret_num + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + verifyProgramVersion( + Op.proto.min_version, + options.version, + "Program version too low to use op proto", + ) + op = TealOp(self, Op.proto, self.arg_num, self.ret_num) + return TealBlock.FromOp(options, op) + + def __str__(self) -> str: + return f"(proto: arg_num = {self.arg_num}, ret_num = {self.ret_num})" + + def type_of(self) -> TealType: + return TealType.none + + def has_return(self) -> bool: + return False + + +Proto.__module__ = "pyteal" + + +class FrameDig(Expr): + def __init__(self, depth: int): + super().__init__() + self.depth = depth + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + verifyProgramVersion( + Op.frame_dig.min_version, + options.version, + "Program version too low to use op frame_dig", + ) + op = TealOp(self, Op.frame_dig, self.depth) + return TealBlock.FromOp(options, op) + + def __str__(self) -> str: + return f"(frame_dig: dig_depth = {self.depth})" + + def type_of(self) -> TealType: + return TealType.anytype + + def has_return(self) -> bool: + return False + + +FrameDig.__module__ = "pyteal" + + +class FrameBury(Expr): + def __init__(self, what: Expr, depth: int): + super().__init__() + require_type(what, TealType.anytype) + self.what = what + self.depth = depth + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + verifyProgramVersion( + Op.frame_bury.min_version, + options.version, + "Program version too low to use op frame_bury", + ) + op = TealOp(self, Op.frame_bury, self.depth) + return TealBlock.FromOp(options, op, self.what) + + def __str__(self) -> str: + return f"(frame_bury (bury_depth = {self.depth}) ({self.what}))" + + def type_of(self) -> TealType: + return TealType.none + + def has_return(self) -> bool: + return False + + +FrameBury.__module__ = "pyteal" + + +class Bury(Expr): + def __init__(self, what: Expr, depth: int): + super().__init__() + require_type(what, TealType.anytype) + if depth <= 0: + raise TealInputError("bury depth should be strictly positive") + self.what = what + self.depth = depth + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + verifyProgramVersion( + Op.bury.min_version, + options.version, + "Program version too low to use op bury", + ) + op = TealOp(self, Op.bury, self.depth) + return TealBlock.FromOp(options, op, self.what) + + def __str__(self) -> str: + return f"(bury (depth = {self.depth}) ({self.what}))" + + def type_of(self) -> TealType: + return TealType.none + + def has_return(self) -> bool: + return False + + +Bury.__module__ = "pyteal" + + +class DupN(Expr): + def __init__(self, what: Expr, repetition: int): + super().__init__() + require_type(what, TealType.anytype) + if repetition < 0: + raise TealInputError("dupn repetition should be non negative") + self.what = what + self.repetition = repetition + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + verifyProgramVersion( + Op.dupn.min_version, + options.version, + "Program version too low to use op dupn", + ) + op = TealOp(self, Op.dupn, self.repetition) + return TealBlock.FromOp(options, op, self.what) + + def __str__(self) -> str: + return f"(dupn (repetition = {self.repetition}) ({self.what}))" + + def type_of(self) -> TealType: + return self.what.type_of() + + def has_return(self) -> bool: + return False + + +DupN.__module__ = "pyteal" + + +class PopN(Expr): + def __init__(self, repetition: int): + super().__init__() + if repetition < 0: + raise TealInputError("popn repetition should be non negative") + self.repetition = repetition + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + verifyProgramVersion( + Op.popn.min_version, + options.version, + "Program version too low to use op popn", + ) + op = TealOp(self, Op.popn, self.repetition) + return TealBlock.FromOp(options, op) + + def __str__(self) -> str: + return f"(popn {self.repetition})" + + def type_of(self) -> TealType: + return TealType.none + + def has_return(self) -> bool: + return False + + +PopN.__module__ = "pyteal" diff --git a/pyteal/ast/frame_test.py b/pyteal/ast/frame_test.py new file mode 100644 index 000000000..b21b47d0e --- /dev/null +++ b/pyteal/ast/frame_test.py @@ -0,0 +1,159 @@ +import pytest +import pyteal as pt +from pyteal.types import TealType + +avm7Options = pt.CompileOptions(version=7) +avm8Options = pt.CompileOptions(version=8) + + +@pytest.mark.parametrize("input_num, output_num", [(1, 1), (1, 0), (5, 5)]) +def test_proto(input_num: int, output_num: int): + expr = pt.Proto(input_num, output_num) + assert not expr.has_return() + assert expr.type_of() == pt.TealType.none + + expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.proto, input_num, output_num)]) + actual, _ = expr.__teal__(avm8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + +def test_proto_invalid(): + with pytest.raises(pt.TealInputError): + pt.Proto(-1, 1) + + with pytest.raises(pt.TealInputError): + pt.Proto(1, -1) + + with pytest.raises(pt.TealInputError): + pt.Proto(1, 1).__teal__(avm7Options) + + +@pytest.mark.parametrize("depth", [-1, 0, 1, 2]) +def test_frame_dig(depth: int): + expr = pt.FrameDig(depth) + assert not expr.has_return() + assert expr.type_of() == pt.TealType.anytype + + expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.frame_dig, depth)]) + actual, _ = expr.__teal__(avm8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + +def test_frame_dig_invalid(): + with pytest.raises(pt.TealInputError): + pt.FrameDig(1).__teal__(avm7Options) + + +def test_frame_bury(): + byte_expr = pt.Bytes("Astartes") + expr = pt.FrameBury(byte_expr, 4) + assert not expr.has_return() + assert expr.type_of() == TealType.none + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(byte_expr, pt.Op.byte, '"Astartes"'), + pt.TealOp(expr, pt.Op.frame_bury, 4), + ] + ) + actual, _ = expr.__teal__(avm8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + +def test_frame_bury_invalid(): + with pytest.raises(pt.TealTypeError): + pt.FrameBury(pt.Seq(), 1) + + with pytest.raises(pt.TealInputError): + pt.FrameBury(pt.Int(1), 1).__teal__(avm7Options) + + +def test_bury(): + byte_expr = pt.Bytes("Astartes") + expr = pt.Bury(byte_expr, 4) + assert not expr.has_return() + assert expr.type_of() == TealType.none + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(byte_expr, pt.Op.byte, '"Astartes"'), + pt.TealOp(expr, pt.Op.bury, 4), + ] + ) + actual, _ = expr.__teal__(avm8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + +def test_bury_invalid(): + with pytest.raises(pt.TealTypeError): + pt.Bury(pt.Seq(), 1) + + with pytest.raises(pt.TealInputError): + pt.Bury(pt.Int(1), 0) + + with pytest.raises(pt.TealInputError): + pt.Bury(pt.Int(1), 1).__teal__(avm7Options) + + +@pytest.mark.parametrize("repetition", [0, 1, 2, 3, 4, 5]) +def test_popn(repetition: int): + expr = pt.PopN(repetition) + assert not expr.has_return() + assert expr.type_of() == pt.TealType.none + + expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.popn, repetition)]) + actual, _ = expr.__teal__(avm8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + +def test_popn_invalid(): + with pytest.raises(pt.TealInputError): + pt.PopN(-1) + + with pytest.raises(pt.TealInputError): + pt.PopN(5).__teal__(avm7Options) + + +def test_dupn(): + byte_expr = pt.Bytes("Astartes") + expr = pt.DupN(byte_expr, 4) + assert not expr.has_return() + assert expr.type_of() == byte_expr.type_of() + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(byte_expr, pt.Op.byte, '"Astartes"'), + pt.TealOp(expr, pt.Op.dupn, 4), + ] + ) + actual, _ = expr.__teal__(avm8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + +def test_dupn_invalid(): + with pytest.raises(pt.TealTypeError): + pt.DupN(pt.Seq(), 1) + + with pytest.raises(pt.TealInputError): + pt.DupN(pt.Int(1), -1) + + with pytest.raises(pt.TealInputError): + pt.DupN(pt.Int(1), 1).__teal__(avm7Options) diff --git a/pyteal/ir/ops.py b/pyteal/ir/ops.py index 43a62b5d4..9ec496288 100644 --- a/pyteal/ir/ops.py +++ b/pyteal/ir/ops.py @@ -33,7 +33,7 @@ def min_version(self) -> int: # fmt: off # meta comment = OpType("//", Mode.Signature | Mode.Application, 0) - # avm + # avm err = OpType("err", Mode.Signature | Mode.Application, 2) sha256 = OpType("sha256", Mode.Signature | Mode.Application, 2) keccak256 = OpType("keccak256", Mode.Signature | Mode.Application, 2) @@ -197,6 +197,12 @@ def min_version(self) -> int: box_len = OpType("box_len", Mode.Application, 8) box_get = OpType("box_get", Mode.Application, 8) box_put = OpType("box_put", Mode.Application, 8) + popn = OpType("popn", Mode.Signature | Mode.Application, 8) + dupn = OpType("dupn", Mode.Signature | Mode.Application, 8) + bury = OpType("bury", Mode.Signature | Mode.Application, 8) + frame_dig = OpType("frame_dig", Mode.Signature | Mode.Application, 8) + frame_bury = OpType("frame_bury", Mode.Signature | Mode.Application, 8) + proto = OpType("proto", Mode.Signature | Mode.Application, 8) # fmt: on From 49d169ed4e7dd4bbd7ea1cedcdc5a5d70718d33d Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 26 Oct 2022 13:52:43 -0400 Subject: [PATCH 018/157] specify FRAME_POINTER_VERSION in frame-op branch --- pyteal/__init__.py | 2 ++ pyteal/__init__.pyi | 2 ++ pyteal/compiler/__init__.py | 2 ++ pyteal/compiler/compiler.py | 1 + 4 files changed, 7 insertions(+) diff --git a/pyteal/__init__.py b/pyteal/__init__.py index ac28dd641..ba6e8eead 100644 --- a/pyteal/__init__.py +++ b/pyteal/__init__.py @@ -8,6 +8,7 @@ MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, + FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -38,6 +39,7 @@ "MIN_TEAL_VERSION", "DEFAULT_TEAL_VERSION", "MAX_PROGRAM_VERSION", + "FRAME_POINTER_VERSION", "MIN_PROGRAM_VERSION", "DEFAULT_PROGRAM_VERSION", "CompileOptions", diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 69e3c55eb..40600d561 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -11,6 +11,7 @@ from pyteal.compiler import ( MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, + FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -116,6 +117,7 @@ __all__ = [ "ExtractUint16", "ExtractUint32", "ExtractUint64", + "FRAME_POINTER_VERSION", "For", "FrameBury", "FrameDig", diff --git a/pyteal/compiler/__init__.py b/pyteal/compiler/__init__.py index e0d29450d..9755ead4f 100644 --- a/pyteal/compiler/__init__.py +++ b/pyteal/compiler/__init__.py @@ -3,6 +3,7 @@ MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, + FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -16,6 +17,7 @@ "MIN_TEAL_VERSION", "DEFAULT_TEAL_VERSION", "MAX_PROGRAM_VERSION", + "FRAME_POINTER_VERSION", "MIN_PROGRAM_VERSION", "DEFAULT_PROGRAM_VERSION", "CompileOptions", diff --git a/pyteal/compiler/compiler.py b/pyteal/compiler/compiler.py index 1955d0430..f2b25b489 100644 --- a/pyteal/compiler/compiler.py +++ b/pyteal/compiler/compiler.py @@ -26,6 +26,7 @@ from pyteal.compiler.constants import createConstantBlocks MAX_PROGRAM_VERSION = 8 +FRAME_POINTER_VERSION = 8 MIN_PROGRAM_VERSION = 2 DEFAULT_PROGRAM_VERSION = MIN_PROGRAM_VERSION From 02f3775fa62d351ee9af27b884656ec5984d38c3 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 26 Oct 2022 17:12:46 -0400 Subject: [PATCH 019/157] just the work of abi data schema --- pyteal/ast/abi/__init__.py | 13 ++++- pyteal/ast/abi/address.py | 15 +++--- pyteal/ast/abi/address_test.py | 73 ++++++++++++++++++++++----- pyteal/ast/abi/array_base.py | 6 +-- pyteal/ast/abi/array_dynamic.py | 8 +-- pyteal/ast/abi/array_dynamic_test.py | 68 ++++++++++++++++++++----- pyteal/ast/abi/array_static.py | 10 ++-- pyteal/ast/abi/array_static_test.py | 49 ++++++++++++++---- pyteal/ast/abi/bool.py | 8 +-- pyteal/ast/abi/bool_test.py | 66 ++++++++++++++++++++---- pyteal/ast/abi/reference_type.py | 8 +-- pyteal/ast/abi/reference_type_test.py | 27 ++++++++-- pyteal/ast/abi/string.py | 29 +++++++---- pyteal/ast/abi/string_test.py | 65 ++++++++++++++++++++---- pyteal/ast/abi/transaction.py | 8 +-- pyteal/ast/abi/transaction_test.py | 8 ++- pyteal/ast/abi/tuple.py | 6 +-- pyteal/ast/abi/tuple_test.py | 22 ++++++-- pyteal/ast/abi/type.py | 64 ++++++++++++++++++++++- pyteal/ast/abi/type_test.py | 2 +- pyteal/ast/abi/uint.py | 39 +++++++------- pyteal/ast/abi/uint_test.py | 64 +++++++++++++++++++---- pyteal/ast/comment.py | 4 +- pyteal/ast/expr.py | 6 +-- pyteal/ast/router.py | 2 +- pyteal/ast/subroutine.py | 18 ++++--- 26 files changed, 529 insertions(+), 159 deletions(-) diff --git a/pyteal/ast/abi/__init__.py b/pyteal/ast/abi/__init__.py index f1cb3a58c..3113b8d72 100644 --- a/pyteal/ast/abi/__init__.py +++ b/pyteal/ast/abi/__init__.py @@ -4,7 +4,15 @@ Address, AddressLength, ) -from pyteal.ast.abi.type import TypeSpec, BaseType, ComputedValue, ReturnedValue +from pyteal.ast.abi.type import ( + TypeSpec, + BaseType, + ComputedValue, + ReturnedValue, + DataStorageSchema, + FrameStorage, + ScratchVarStorage, +) from pyteal.ast.abi.bool import BoolTypeSpec, Bool from pyteal.ast.abi.uint import ( UintTypeSpec, @@ -166,6 +174,9 @@ "type_specs_from_signature", "make", "size_of", + "DataStorageSchema", + "FrameStorage", + "ScratchVarStorage", "algosdk_from_annotation", "algosdk_from_type_spec", "contains_type_spec", diff --git a/pyteal/ast/abi/address.py b/pyteal/ast/abi/address.py index d0413cf6c..3165fcd9a 100644 --- a/pyteal/ast/abi/address.py +++ b/pyteal/ast/abi/address.py @@ -56,7 +56,7 @@ def get(self) -> Expr: The expression will have the type TealType.bytes. """ - return self.stored_value.load() + return self._data_storage.load_value() def set( self, @@ -108,25 +108,28 @@ def set( or value.type_spec() == StaticArrayTypeSpec(ByteTypeSpec(), AddressLength.Bytes) ): - return self.stored_value.store(value.stored_value.load()) + return self._data_storage.store_value( + value._data_storage.load_value() + ) raise TealInputError( f"Got {value} with type spec {value.type_spec()}, expected AddressTypeSpec" ) case str(): # Addr throws if value is invalid address - return self.stored_value.store(Addr(value)) + return self._data_storage.store_value(Addr(value)) case bytes(): if len(value) == AddressLength.Bytes: - return self.stored_value.store(Bytes(value)) + return self._data_storage.store_value(Bytes(value)) raise TealInputError( f"Got bytes with length {len(value)}, expected {AddressLength.Bytes}" ) case Expr(): return Seq( - self.stored_value.store(value), + self._data_storage.store_value(value), Assert( - Len(self.stored_value.load()) == Int(AddressLength.Bytes.value) + Len(self._data_storage.load_value()) + == Int(AddressLength.Bytes.value) ), ) case CollectionSequence(): diff --git a/pyteal/ast/abi/address_test.py b/pyteal/ast/abi/address_test.py index 7cc9cd449..305046619 100644 --- a/pyteal/ast/abi/address_test.py +++ b/pyteal/ast/abi/address_test.py @@ -1,4 +1,5 @@ import pytest +from typing import cast import pyteal as pt from pyteal import abi @@ -48,7 +49,13 @@ def test_Address_encode(): assert expr.has_return() is False expected = pt.TealSimpleBlock( - [pt.TealOp(expr, pt.Op.load, value.stored_value.slot)] + [ + pt.TealOp( + expr, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + ] ) actual, _ = expr.__teal__(options) assert actual == expected @@ -79,7 +86,7 @@ def test_Address_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expectedExpr = value.stored_value.store( + expectedExpr = value._data_storage.store_value( substring_for_decoding( encoded, start_index=start_index, @@ -106,7 +113,13 @@ def test_Address_get(): assert expr.has_return() is False expected = pt.TealSimpleBlock( - [pt.TealOp(expr, pt.Op.load, value.stored_value.slot)] + [ + pt.TealOp( + expr, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + ] ) actual, _ = expr.__teal__(options) assert actual == expected @@ -123,8 +136,16 @@ def test_Address_set_StaticArray(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, value_to_set.stored_value.slot), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value_to_set._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -150,7 +171,11 @@ def test_Address_set_str(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.addr, value_to_set), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -175,7 +200,11 @@ def test_Address_set_bytes(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.byte, f"0x{value_to_set.hex()}"), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -204,8 +233,16 @@ def test_Address_set_expr(): expected = pt.TealSimpleBlock( [ vts.ops[0], - pt.TealOp(None, pt.Op.store, value.stored_value.slot), - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.int, AddressLength.Bytes.value), pt.TealOp(None, pt.Op.eq), @@ -230,8 +267,16 @@ def test_Address_set_copy(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, other.stored_value.slot), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -259,7 +304,11 @@ def test_Address_set_computed(): expected = pt.TealSimpleBlock( [ byte_ops.ops[0], - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) diff --git a/pyteal/ast/abi/array_base.py b/pyteal/ast/abi/array_base.py index aea164c81..4674f1d90 100644 --- a/pyteal/ast/abi/array_base.py +++ b/pyteal/ast/abi/array_base.py @@ -104,7 +104,7 @@ def decode( extracted = substring_for_decoding( encoded, start_index=start_index, end_index=end_index, length=length ) - return self.stored_value.store(extracted) + return self._data_storage.store_value(extracted) def set(self, values: Sequence[T]) -> Expr: """Set the ABI array with a sequence of ABI type variables. @@ -142,7 +142,7 @@ def set(self, values: Sequence[T]) -> Expr: length_prefix = Seq(length_tmp.set(len(values)), length_tmp.encode()) encoded = Concat(length_prefix, encoded) - return self.stored_value.store(encoded) + return self._data_storage.store_value(encoded) def encode(self) -> Expr: """Encode the ABI array to be a byte string. @@ -150,7 +150,7 @@ def encode(self) -> Expr: Returns: A PyTeal expression that encodes this ABI array to a byte string. """ - return self.stored_value.load() + return self._data_storage.load_value() @abstractmethod def length(self) -> Expr: diff --git a/pyteal/ast/abi/array_dynamic.py b/pyteal/ast/abi/array_dynamic.py index 9d53e0559..2a5f7367d 100644 --- a/pyteal/ast/abi/array_dynamic.py +++ b/pyteal/ast/abi/array_dynamic.py @@ -79,7 +79,7 @@ def set( raise TealInputError( f"Cannot assign type {values.type_spec()} to {self.type_spec()}" ) - return self.stored_value.store(values.encode()) + return self._data_storage.store_value(values.encode()) return super().set(values) def length(self) -> Expr: @@ -165,10 +165,10 @@ def set( match values: case bytes() | bytearray(): - return self.stored_value.store(_encoded_byte_string(values)) + return self._data_storage.store_value(_encoded_byte_string(values)) case Expr(): return _store_encoded_expr_byte_string_into_var( - values, self.stored_value + values, self._data_storage ) return super().set(values) @@ -181,7 +181,7 @@ def get(self) -> Expr: Returns: A Pyteal expression that loads byte encoding of this DynamicBytes, and drop the first uint16 DynamicArray length encoding. """ - return Suffix(self.stored_value.load(), Int(2)) + return Suffix(self._data_storage.load_value(), Int(2)) DynamicBytes.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/array_dynamic_test.py b/pyteal/ast/abi/array_dynamic_test.py index 326f72294..fa0e122e1 100644 --- a/pyteal/ast/abi/array_dynamic_test.py +++ b/pyteal/ast/abi/array_dynamic_test.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, cast import pytest import pyteal as pt @@ -106,7 +106,7 @@ def test_DynamicArray_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value.stored_value.store( + expectedExpr = value._data_storage.store_value( substring_for_decoding( encoded, start_index=start_index, @@ -141,7 +141,7 @@ def test_DynamicArray_set_values(): assert not expr.has_return() length_tmp = abi.Uint16() - expectedExpr = value.stored_value.store( + expectedExpr = value._data_storage.store_value( pt.Concat( pt.Seq(length_tmp.set(len(values)), length_tmp.encode()), _encode_tuple(values), @@ -182,8 +182,16 @@ def test_DynamicArray_set_copy(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, otherArray.stored_value.slot), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, otherArray._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -207,7 +215,11 @@ def test_DynamicArray_set_computed(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.byte, '"this should be a dynamic array"'), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) actual, _ = expr.__teal__(options) @@ -253,7 +265,11 @@ def test_DynamicBytes_set_py_bytes(test_case: bytes | bytearray): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.byte, "0x" + length_encoding + BYTE_HEX_TEST_CASE), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -280,14 +296,30 @@ def test_DynamicBytes_set_expr(test_case: bytes | bytearray): pt.TealOp(None, pt.Op.byte, "0x" + BYTE_HEX_TEST_CASE), pt.TealOp(None, pt.Op.byte, "0x" + BYTE_HEX_TEST_CASE), pt.TealOp(None, pt.Op.concat), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.itob), pt.TealOp(None, pt.Op.extract, 6, 0), - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.concat), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -308,7 +340,11 @@ def test_DynamicBytes_get(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.extract, 2, 0), ] ) @@ -325,7 +361,13 @@ def test_DynamicArray_encode(): assert not expr.has_return() expected = pt.TealSimpleBlock( - [pt.TealOp(None, pt.Op.load, value.stored_value.slot)] + [ + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + ] ) actual, _ = expr.__teal__(options) diff --git a/pyteal/ast/abi/array_static.py b/pyteal/ast/abi/array_static.py index 7744a6edb..caf2dcc88 100644 --- a/pyteal/ast/abi/array_static.py +++ b/pyteal/ast/abi/array_static.py @@ -109,7 +109,7 @@ def set( raise TealInputError( f"Cannot assign type {values.type_spec()} to {self.type_spec()}" ) - return self.stored_value.store(values.encode()) + return self._data_storage.store_value(values.encode()) if self.type_spec().length_static() != len(values): raise TealInputError( @@ -207,11 +207,11 @@ def set( raise TealInputError( f"Got bytes with length {len(values)}, expect {self.type_spec().length_static()}" ) - return self.stored_value.store(Bytes(values)) + return self._data_storage.store_value(Bytes(values)) case Expr(): return Seq( - self.stored_value.store(values), - Assert(self.length() == Len(self.stored_value.load())), + self._data_storage.store_value(values), + Assert(self.length() == Len(self._data_storage.load_value())), ) return super().set(values) @@ -222,7 +222,7 @@ def get(self) -> Expr: Returns: A Pyteal expression that loads byte encoding of this StaticBytes. """ - return self.stored_value.load() + return self._data_storage.load_value() StaticBytes.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/array_static_test.py b/pyteal/ast/abi/array_static_test.py index 91781a682..236e2591e 100644 --- a/pyteal/ast/abi/array_static_test.py +++ b/pyteal/ast/abi/array_static_test.py @@ -1,4 +1,5 @@ import pytest +from typing import cast import pyteal as pt from pyteal import abi @@ -158,7 +159,7 @@ def test_StaticArray_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value.stored_value.store( + expectedExpr = value._data_storage.store_value( substring_for_decoding( encoded, start_index=start_index, @@ -201,7 +202,7 @@ def test_StaticArray_set_values(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value.stored_value.store(_encode_tuple(values)) + expectedExpr = value._data_storage.store_value(_encode_tuple(values)) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) @@ -233,8 +234,16 @@ def test_StaticArray_set_copy(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, otherArray.stored_value.slot), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, otherArray._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -258,7 +267,11 @@ def test_StaticArray_set_computed(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.byte, '"indeed this is hard to simulate"'), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) actual, _ = expr.__teal__(options) @@ -301,7 +314,11 @@ def test_StaticBytes_set_py_bytes(test_case: bytes | bytearray): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.byte, "0x" + BYTE_HEX_TEST_CASE), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -332,9 +349,17 @@ def test_StaticBytes_expr(test_case: bytes | bytearray): pt.TealOp(None, pt.Op.byte, "0x" + BYTE_HEX_TEST_CASE), pt.TealOp(None, pt.Op.byte, "0x" + BYTE_HEX_TEST_CASE), pt.TealOp(None, pt.Op.concat), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.int, 32), - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.eq), pt.TealOp(None, pt.Op.assert_), @@ -352,7 +377,13 @@ def test_StaticArray_encode(): assert not expr.has_return() expected = pt.TealSimpleBlock( - [pt.TealOp(None, pt.Op.load, value.stored_value.slot)] + [ + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + ] ) actual, _ = expr.__teal__(options) diff --git a/pyteal/ast/abi/bool.py b/pyteal/ast/abi/bool.py index 13552b6db..2bfbd3aca 100644 --- a/pyteal/ast/abi/bool.py +++ b/pyteal/ast/abi/bool.py @@ -50,7 +50,7 @@ def get(self) -> Expr: expression that evaluates to 0 will be returned. In either case, the expression will have the type TealType.uint64. """ - return self.stored_value.load() + return self._data_storage.load_value() def set(self, value: Union[bool, Expr, "Bool", ComputedValue["Bool"]]) -> Expr: """Set the value of this Bool to the input value. @@ -85,10 +85,10 @@ def set(self, value: Union[bool, Expr, "Bool", ComputedValue["Bool"]]) -> Expr: checked = True if checked: - return self.stored_value.store(value) + return self._data_storage.store_value(value) # Not(Not(value)) coerces all values greater than 0 to 1 - return self.stored_value.store(Not(Not(value))) + return self._data_storage.store_value(Not(Not(value))) def decode( self, @@ -103,7 +103,7 @@ def decode( return self.decode_bit(encoded, start_index * Int(NUM_BITS_IN_BYTE)) def decode_bit(self, encoded, bit_index: Expr) -> Expr: - return self.stored_value.store(GetBit(encoded, bit_index)) + return self._data_storage.store_value(GetBit(encoded, bit_index)) def encode(self) -> Expr: return SetBit(Bytes(b"\x00"), Int(0), self.get()) diff --git a/pyteal/ast/abi/bool_test.py b/pyteal/ast/abi/bool_test.py index 45ffa7e30..411bdf376 100644 --- a/pyteal/ast/abi/bool_test.py +++ b/pyteal/ast/abi/bool_test.py @@ -1,4 +1,4 @@ -from typing import NamedTuple, List +from typing import NamedTuple, List, cast import pytest import pyteal as pt @@ -53,7 +53,11 @@ def test_Bool_set_static(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.int, 1 if value_to_set else 0), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -78,7 +82,11 @@ def test_Bool_set_expr(): pt.TealOp(None, pt.Op.logic_or), pt.TealOp(None, pt.Op.logic_not), pt.TealOp(None, pt.Op.logic_not), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -99,8 +107,16 @@ def test_Bool_set_copy(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, other.stored_value.slot), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -125,7 +141,11 @@ def test_Bool_set_computed(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.int, 0x80), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -147,7 +167,13 @@ def test_Bool_get(): assert not expr.has_return() expected = pt.TealSimpleBlock( - [pt.TealOp(expr, pt.Op.load, value.stored_value.slot)] + [ + pt.TealOp( + expr, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + ] ) actual, _ = expr.__teal__(options) @@ -174,7 +200,13 @@ def test_Bool_decode(): pt.TealOp(None, pt.Op.int, 8), pt.TealOp(None, pt.Op.mul), pt.TealOp(None, pt.Op.getbit), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast( + abi.ScratchVarStorage, value._data_storage + ).scratchvar.slot, + ), ] ) @@ -199,7 +231,11 @@ def test_Bool_decode_bit(): pt.TealOp(None, pt.Op.byte, '"encoded"'), pt.TealOp(None, pt.Op.int, 17), pt.TealOp(None, pt.Op.getbit), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -221,7 +257,11 @@ def test_Bool_encode(): [ pt.TealOp(None, pt.Op.byte, "0x00"), pt.TealOp(None, pt.Op.int, 0), - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.setbit), ] ) @@ -401,7 +441,11 @@ class EncodeSeqTest(NamedTuple): setBits = [ [ pt.TealOp(None, pt.Op.int, j), - pt.TealOp(None, pt.Op.load, testType.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, testType._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.setbit), ] for j, testType in enumerate(test.types) diff --git a/pyteal/ast/abi/reference_type.py b/pyteal/ast/abi/reference_type.py index f4882fc97..2ea723b92 100644 --- a/pyteal/ast/abi/reference_type.py +++ b/pyteal/ast/abi/reference_type.py @@ -58,7 +58,7 @@ def referenced_index(self) -> Expr: If this reference type is an application or asset, note that this DOES NOT return the application or asset ID. See :code:`application_id()` or :code:`asset_id()` for that. """ - return self.stored_value.load() + return self._data_storage.load_value() def decode( self, @@ -70,7 +70,7 @@ def decode( ) -> Expr: return uint_decode( self.type_spec().bit_size(), - self.stored_value, + self._data_storage, encoded, start_index, end_index, @@ -107,7 +107,7 @@ def __init__(self) -> None: def address(self) -> Expr: """Get the address of the account.""" - return Txn.accounts[self.stored_value.load()] + return Txn.accounts[self._data_storage.load_value()] def params(self) -> AccountParamObject: """Get information about the account.""" @@ -205,7 +205,7 @@ def __init__(self) -> None: def application_id(self) -> Expr: """Get the ID of the application.""" - return Txn.applications[self.stored_value.load()] + return Txn.applications[self._data_storage.load_value()] def params(self) -> AppParamObject: """Get information about the application's parameters.""" diff --git a/pyteal/ast/abi/reference_type_test.py b/pyteal/ast/abi/reference_type_test.py index 99555ab12..aaa1e5d97 100644 --- a/pyteal/ast/abi/reference_type_test.py +++ b/pyteal/ast/abi/reference_type_test.py @@ -1,4 +1,5 @@ import pytest +from typing import cast import pyteal as pt from pyteal import abi @@ -22,7 +23,11 @@ def test_ReferenceType_referenced_index(): expected = pt.TealSimpleBlock( [ - pt.TealOp(expr, pt.Op.load, value.stored_value.slot), + pt.TealOp( + expr, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) actual, _ = expr.__teal__(options) @@ -56,7 +61,7 @@ def test_ReferenceType_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expected_decoding = value.stored_value.store( + expected_decoding = value._data_storage.store_value( pt.GetByte( encoded, start_index if start_index is not None else pt.Int(0), @@ -109,7 +114,11 @@ def test_Account_address(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.txnas, "Accounts"), ] ) @@ -192,7 +201,11 @@ def test_Asset_asset_id(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.txnas, "Assets"), ] ) @@ -282,7 +295,11 @@ def test_Application_application_id(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.txnas, "Applications"), ] ) diff --git a/pyteal/ast/abi/string.py b/pyteal/ast/abi/string.py index 4c9b31c08..0359aee76 100644 --- a/pyteal/ast/abi/string.py +++ b/pyteal/ast/abi/string.py @@ -4,7 +4,7 @@ from algosdk.abi import ABIType from pyteal.ast.abi.uint import Byte -from pyteal.ast.abi.type import ComputedValue, BaseType +from pyteal.ast.abi.type import ComputedValue, BaseType, DataStorageSchema from pyteal.ast.abi.array_dynamic import DynamicArray, DynamicArrayTypeSpec from pyteal.ast.abi.uint import ByteTypeSpec, Uint16TypeSpec @@ -12,7 +12,6 @@ from pyteal.ast.expr import Expr from pyteal.ast.bytes import Bytes from pyteal.ast.seq import Seq -from pyteal.ast.scratchvar import ScratchVar from pyteal.ast.unaryexpr import Itob, Len from pyteal.ast.substring import Suffix from pyteal.ast.naryexpr import Concat @@ -25,11 +24,15 @@ def _encoded_byte_string(s: bytes | bytearray) -> Expr: return Bytes(prefix + s) -def _store_encoded_expr_byte_string_into_var(value: Expr, location: ScratchVar) -> Expr: +def _store_encoded_expr_byte_string_into_var( + value: Expr, location: DataStorageSchema +) -> Expr: return Seq( - location.store(value), - location.store( - Concat(Suffix(Itob(Len(location.load())), Int(6)), location.load()) + location.store_value(value), + location.store_value( + Concat( + Suffix(Itob(Len(location.load_value())), Int(6)), location.load_value() + ) ), ) @@ -67,7 +70,7 @@ def get(self) -> Expr: The expression will have the type TealType.bytes. """ return Suffix( - self.stored_value.load(), Int(Uint16TypeSpec().byte_length_static()) + self._data_storage.load_value(), Int(Uint16TypeSpec().byte_length_static()) ) def set( @@ -110,18 +113,22 @@ def set( if value.type_spec() == StringTypeSpec() or ( value.type_spec() == DynamicArrayTypeSpec(ByteTypeSpec()) ): - return self.stored_value.store(value.stored_value.load()) + return self._data_storage.store_value( + value._data_storage.load_value() + ) raise TealInputError( f"Got {value} with type spec {value.type_spec()}, expected {StringTypeSpec}" ) case bytes() | bytearray(): - return self.stored_value.store(_encoded_byte_string(value)) + return self._data_storage.store_value(_encoded_byte_string(value)) case str(): - return self.stored_value.store(_encoded_byte_string(value.encode())) + return self._data_storage.store_value( + _encoded_byte_string(value.encode()) + ) case Expr(): return _store_encoded_expr_byte_string_into_var( - value, self.stored_value + value, self._data_storage ) case CollectionSequence(): return super().set(cast(Sequence[Byte], value)) diff --git a/pyteal/ast/abi/string_test.py b/pyteal/ast/abi/string_test.py index 6a600d55a..79a699a4c 100644 --- a/pyteal/ast/abi/string_test.py +++ b/pyteal/ast/abi/string_test.py @@ -1,4 +1,5 @@ import pytest +from typing import cast import pyteal as pt from pyteal import abi @@ -39,7 +40,13 @@ def test_String_encode(): assert expr.has_return() is False expected = pt.TealSimpleBlock( - [pt.TealOp(expr, pt.Op.load, value.stored_value.slot)] + [ + pt.TealOp( + expr, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + ] ) actual, _ = expr.__teal__(options) assert actual == expected @@ -69,7 +76,7 @@ def test_DynamicArray_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expectedExpr = value.stored_value.store( + expectedExpr = value._data_storage.store_value( substring_for_decoding( encoded, start_index=start_index, @@ -97,7 +104,11 @@ def test_String_get(): expected = pt.TealSimpleBlock( [ - pt.TealOp(expr, pt.Op.load, value.stored_value.slot), + pt.TealOp( + expr, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.extract, 2, 0), ] ) @@ -129,7 +140,11 @@ def test_String_set_static(value_to_set, value_encoded): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.byte, "0x" + value_encoded.hex()), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -156,14 +171,30 @@ def test_String_set_expr(): value_start, value_end = value_to_set.__teal__(options) expected_body = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.store, value.stored_value.slot), - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.itob), pt.TealOp(None, pt.Op.extract, 6, 0), - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.concat), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) value_end.setNextBlock(expected_body) @@ -188,8 +219,16 @@ def test_String_set_copy(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, other.stored_value.slot), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -217,7 +256,11 @@ def test_String_set_computed(): expected = pt.TealSimpleBlock( [ byte_ops.ops[0], - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) diff --git a/pyteal/ast/abi/transaction.py b/pyteal/ast/abi/transaction.py index aeb5c7a33..2451a1285 100644 --- a/pyteal/ast/abi/transaction.py +++ b/pyteal/ast/abi/transaction.py @@ -82,16 +82,16 @@ def _set_index( case ComputedValue(): return self._set_with_computed_type(value) case BaseType(): - return self.stored_value.store(self.stored_value.load()) + return self._data_storage.store_value(self._data_storage.load_value()) case int(): - return self.stored_value.store(Int(value)) + return self._data_storage.store_value(Int(value)) case Expr(): - return self.stored_value.store(value) + return self._data_storage.store_value(value) case _: raise TealInputError(f"Cant store a {type(value)} in a Transaction") def index(self) -> Expr: - return self.stored_value.load() + return self._data_storage.load_value() def decode( self, diff --git a/pyteal/ast/abi/transaction_test.py b/pyteal/ast/abi/transaction_test.py index 5803b8f32..573d6f440 100644 --- a/pyteal/ast/abi/transaction_test.py +++ b/pyteal/ast/abi/transaction_test.py @@ -1,5 +1,5 @@ from dataclasses import dataclass -from typing import List +from typing import List, cast import pyteal as pt from pyteal import abi import pytest @@ -131,7 +131,11 @@ def test_Transaction__set_index(): expected = pt.TealSimpleBlock( [ pt.TealOp(expr, pt.Op.int, val_to_set), - pt.TealOp(None, pt.Op.store, tv.t.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, tv.t._data_storage).scratchvar.slot, + ), ] ) actual, _ = expr.__teal__(options) diff --git a/pyteal/ast/abi/tuple.py b/pyteal/ast/abi/tuple.py index bc1966414..2f2dceeab 100644 --- a/pyteal/ast/abi/tuple.py +++ b/pyteal/ast/abi/tuple.py @@ -309,7 +309,7 @@ def decode( extracted = substring_for_decoding( encoded, start_index=start_index, end_index=end_index, length=length ) - return self.stored_value.store(extracted) + return self._data_storage.store_value(extracted) @overload def set(self, *values: BaseType) -> Expr: @@ -352,10 +352,10 @@ def set(self, *values): ) if not all(myTypes[i] == values[i].type_spec() for i in range(len(myTypes))): raise TealInputError("Input values do not match type") - return self.stored_value.store(_encode_tuple(values)) + return self._data_storage.store_value(_encode_tuple(values)) def encode(self) -> Expr: - return self.stored_value.load() + return self._data_storage.load_value() def length(self) -> Expr: """Get the number of values this tuple holds as an Expr.""" diff --git a/pyteal/ast/abi/tuple_test.py b/pyteal/ast/abi/tuple_test.py index 7fc98cdae..8365769cc 100644 --- a/pyteal/ast/abi/tuple_test.py +++ b/pyteal/ast/abi/tuple_test.py @@ -1,4 +1,4 @@ -from typing import NamedTuple, List, Callable, Literal +from typing import NamedTuple, List, Callable, Literal, cast import pytest import pyteal as pt @@ -623,7 +623,7 @@ def test_Tuple_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = tupleValue.stored_value.store( + expectedExpr = tupleValue._data_storage.store_value( substring_for_decoding( encoded, start_index=start_index, @@ -672,7 +672,9 @@ def test_Tuple_set(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = tupleValue.stored_value.store(_encode_tuple([uint8, uint16, uint32])) + expectedExpr = tupleValue._data_storage.store_value( + _encode_tuple([uint8, uint16, uint32]) + ) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) @@ -701,7 +703,11 @@ def test_Tuple_set_Computed(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.byte, '"internal representation"'), - pt.TealOp(None, pt.Op.store, tupleValue.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, tupleValue._data_storage).scratchvar.slot, + ), ] ) actual, _ = expr.__teal__(options) @@ -727,7 +733,13 @@ def test_Tuple_encode(): assert not expr.has_return() expected = pt.TealSimpleBlock( - [pt.TealOp(None, pt.Op.load, tupleValue.stored_value.slot)] + [ + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, tupleValue._data_storage).scratchvar.slot, + ), + ] ) actual, _ = expr.__teal__(options) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index 4b0b1e0f3..67d75cc4b 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -65,6 +65,55 @@ def __str__(self) -> str: TypeSpec.__module__ = "pyteal.abi" +class DataStorageSchema(ABC): + @abstractmethod + def store_value(self, value: Expr) -> Expr: + pass + + @abstractmethod + def load_value(self) -> Expr: + pass + + @abstractmethod + def storage_type(self) -> TealType: + pass + + +class ScratchVarStorage(DataStorageSchema): + def __init__(self, storage_type: TealType) -> None: + super().__init__() + self.scratchvar: Final = ScratchVar(storage_type) + + def load_value(self) -> Expr: + return self.scratchvar.load() + + def store_value(self, value: Expr) -> Expr: + return self.scratchvar.slot.store(value) + + def storage_type(self) -> TealType: + return self.scratchvar.storage_type() + + +class FrameStorage(DataStorageSchema): + def __init__(self, storage_type: TealType, stack_depth: int) -> None: + super().__init__() + self.stack_type = storage_type + self.stack_depth = stack_depth + + def storage_type(self) -> TealType: + return self.stack_type + + def store_value(self, value: Expr) -> Expr: + from pyteal.ast import FrameBury + + return FrameBury(value, self.stack_depth) + + def load_value(self) -> Expr: + from pyteal.ast import FrameDig + + return FrameDig(self.stack_depth) + + class BaseType(ABC): """The abstract base class for all ABI type instances. @@ -77,7 +126,18 @@ def __init__(self, spec: TypeSpec) -> None: """Create a new BaseType.""" super().__init__() self._type_spec: Final = spec - self.stored_value: Final = ScratchVar(spec.storage_type()) + self._data_storage: DataStorageSchema = ScratchVarStorage(spec.storage_type()) + + # self.stored_value: Final = ScratchVar(spec.storage_type()) + + def _set_data_source(self, storage: DataStorageSchema) -> None: + self._data_storage = storage + + def _load_value(self) -> Expr: + return self._data_storage.load_value() + + def _store_value(self, value: Expr) -> Expr: + return self._data_storage.store_value(value) def type_spec(self) -> TypeSpec: """Get the TypeSpec for this ABI type instance.""" @@ -231,7 +291,7 @@ def store_into(self, output: BaseType) -> Expr: f"ABI return subroutine deferred_expr is expected to be typed {output.type_spec().storage_type()}, " f"but has type {declaration.deferred_expr.type_of()}." ) - return output.stored_value.slot.store(self.computation) + return output._data_storage.store_value(self.computation) ReturnedValue.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/type_test.py b/pyteal/ast/abi/type_test.py index 56a9e6c76..b5134ef7d 100644 --- a/pyteal/ast/abi/type_test.py +++ b/pyteal/ast/abi/type_test.py @@ -17,7 +17,7 @@ def store_into(self, output: abi.BaseType) -> pt.Expr: raise pt.TealInputError( f"expected type_spec {self.type_spec} but get {output.type_spec()}" ) - return output.stored_value.store(self.encodings) + return output._data_storage.store_value(self.encodings) def test_ComputedType_use(): diff --git a/pyteal/ast/abi/uint.py b/pyteal/ast/abi/uint.py index 9855c29b9..e34daac9a 100644 --- a/pyteal/ast/abi/uint.py +++ b/pyteal/ast/abi/uint.py @@ -8,7 +8,6 @@ from pyteal.types import TealType from pyteal.errors import TealInputError -from pyteal.ast.scratchvar import ScratchVar from pyteal.ast.expr import Expr from pyteal.ast.seq import Seq from pyteal.ast.assert_ import Assert @@ -18,7 +17,7 @@ from pyteal.ast.unaryexpr import Itob, Btoi from pyteal.ast.binaryexpr import GetByte, ExtractUint16, ExtractUint32, ExtractUint64 from pyteal.ast.ternaryexpr import SetByte -from pyteal.ast.abi.type import ComputedValue, TypeSpec, BaseType +from pyteal.ast.abi.type import ComputedValue, TypeSpec, BaseType, DataStorageSchema NUM_BITS_IN_BYTE = 8 @@ -31,7 +30,9 @@ def uint_storage_type(size: int) -> TealType: return TealType.bytes -def uint_set(size: int, uint_var: ScratchVar, value: Union[int, Expr, "Uint"]) -> Expr: +def uint_set( + size: int, uint_var: DataStorageSchema, value: Union[int, Expr, "Uint"] +) -> Expr: if size > 64: raise NotImplementedError( "Uint operations have not yet been implemented for bit sizes larger than 64" @@ -49,17 +50,17 @@ def uint_set(size: int, uint_var: ScratchVar, value: Union[int, Expr, "Uint"]) - checked = True if checked or size == 64: - return uint_var.store(cast(Expr, value)) + return uint_var.store_value(cast(Expr, value)) return Seq( - uint_var.store(cast(Expr, value)), - Assert(uint_var.load() < Int(2**size)), + uint_var.store_value(cast(Expr, value)), + Assert(uint_var.load_value() < Int(2**size)), ) def uint_decode( size: int, - uint_var: ScratchVar, + uint_var: DataStorageSchema, encoded: Expr, start_index: Optional[Expr], end_index: Optional[Expr], @@ -73,27 +74,27 @@ def uint_decode( if size == 64: if start_index is None: if end_index is None and length is None: - return uint_var.store(Btoi(encoded)) + return uint_var.store_value(Btoi(encoded)) start_index = Int(0) - return uint_var.store(ExtractUint64(encoded, start_index)) + return uint_var.store_value(ExtractUint64(encoded, start_index)) if start_index is None: start_index = Int(0) if size == 8: - return uint_var.store(GetByte(encoded, start_index)) + return uint_var.store_value(GetByte(encoded, start_index)) if size == 16: - return uint_var.store(ExtractUint16(encoded, start_index)) + return uint_var.store_value(ExtractUint16(encoded, start_index)) if size == 32: - return uint_var.store(ExtractUint32(encoded, start_index)) + return uint_var.store_value(ExtractUint32(encoded, start_index)) raise ValueError("Unsupported uint size: {}".format(size)) -def uint_encode(size: int, uint_var: Expr | ScratchVar) -> Expr: +def uint_encode(size: int, uint_var: Expr | DataStorageSchema) -> Expr: - if isinstance(uint_var, ScratchVar): - uint_var = uint_var.load() + if isinstance(uint_var, DataStorageSchema): + uint_var = uint_var.load_value() if size > 64: raise NotImplementedError( @@ -240,7 +241,7 @@ def get(self) -> Expr: The expression will have the type TealType.uint64. """ - return self.stored_value.load() + return self._data_storage.load_value() def set(self, value: Union[int, Expr, "Uint", ComputedValue["Uint"]]) -> Expr: """Set the value of this Uint to the input value. @@ -275,7 +276,7 @@ def set(self, value: Union[int, Expr, "Uint", ComputedValue["Uint"]]) -> Expr: value.type_spec(), self.type_spec() ) ) - return uint_set(self.type_spec().bit_size(), self.stored_value, value) + return uint_set(self.type_spec().bit_size(), self._data_storage, value) def decode( self, @@ -287,7 +288,7 @@ def decode( ) -> Expr: return uint_decode( self.type_spec().bit_size(), - self.stored_value, + self._data_storage, encoded, start_index, end_index, @@ -295,7 +296,7 @@ def decode( ) def encode(self) -> Expr: - return uint_encode(self.type_spec().bit_size(), self.stored_value) + return uint_encode(self.type_spec().bit_size(), self._data_storage) Uint.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/uint_test.py b/pyteal/ast/abi/uint_test.py index 3af64f865..c4659fdb9 100644 --- a/pyteal/ast/abi/uint_test.py +++ b/pyteal/ast/abi/uint_test.py @@ -1,4 +1,4 @@ -from typing import List, Tuple, NamedTuple, Callable, Union, Optional +from typing import List, Tuple, NamedTuple, Callable, Union, Optional, cast from pyteal.ast.abi.type_test import ContainerType import pyteal as pt from pyteal import abi @@ -139,7 +139,13 @@ def test_Uint_set_static(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.int, value_to_set), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast( + abi.ScratchVarStorage, value._data_storage + ).scratchvar.slot, + ), ] ) @@ -167,7 +173,11 @@ def test_Uint_set_expr(): upperBoundCheck = [] if test.checkUpperBound: upperBoundCheck = [ - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.int, test.maxValue + 1), pt.TealOp(None, pt.Op.lt), pt.TealOp(None, pt.Op.assert_), @@ -178,7 +188,11 @@ def test_Uint_set_expr(): pt.TealOp(None, pt.Op.int, 10), pt.TealOp(None, pt.Op.int, 1), pt.TealOp(None, pt.Op.add), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] + upperBoundCheck ) @@ -201,8 +215,16 @@ def test_Uint_set_copy(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, other.stored_value.slot), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -230,7 +252,11 @@ def test_Uint_set_computed(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.int, 0x44), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -253,7 +279,13 @@ def test_Uint_get(): assert not expr.has_return() expected = pt.TealSimpleBlock( - [pt.TealOp(expr, pt.Op.load, value.stored_value.slot)] + [ + pt.TealOp( + expr, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + ] ) actual, _ = expr.__teal__(options) @@ -277,7 +309,7 @@ def test_Uint_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedDecoding = value.stored_value.store( + expectedDecoding = value._data_storage.store_value( test.expectedDecoding(encoded, start_index, end_index, length) ) expected, _ = expectedDecoding.__teal__(options) @@ -326,8 +358,18 @@ def test_ByteUint8_mutual_conversion(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, other.stored_value.slot), - pt.TealOp(None, pt.Op.store, type_b_instance.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.store, + cast( + abi.ScratchVarStorage, type_b_instance._data_storage + ).scratchvar.slot, + ), ] ) diff --git a/pyteal/ast/comment.py b/pyteal/ast/comment.py index 58c89d63d..361694677 100644 --- a/pyteal/ast/comment.py +++ b/pyteal/ast/comment.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, Tuple +from typing import TYPE_CHECKING from pyteal.errors import TealInputError from pyteal.types import TealType @@ -26,7 +26,7 @@ def __init__(self, single_line_comment: str) -> None: ) self.comment = single_line_comment - def __teal__(self, options: "CompileOptions") -> Tuple[TealBlock, TealSimpleBlock]: + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: op = TealOp(self, Op.comment, self.comment) return TealBlock.FromOp(options, op) diff --git a/pyteal/ast/expr.py b/pyteal/ast/expr.py index c2de1ca32..0f57eebce 100644 --- a/pyteal/ast/expr.py +++ b/pyteal/ast/expr.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from typing import Tuple, List, TYPE_CHECKING +from typing import TYPE_CHECKING from pyteal.types import TealType from pyteal.ir import TealBlock, TealSimpleBlock @@ -16,7 +16,7 @@ def __init__(self): self.trace = traceback.format_stack()[0:-1] - def getDefinitionTrace(self) -> List[str]: + def getDefinitionTrace(self) -> list[str]: return self.trace @abstractmethod @@ -35,7 +35,7 @@ def __str__(self) -> str: pass @abstractmethod - def __teal__(self, options: "CompileOptions") -> Tuple[TealBlock, TealSimpleBlock]: + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: """Assemble TEAL IR for this component and its arguments.""" pass diff --git a/pyteal/ast/router.py b/pyteal/ast/router.py index 5349cfe84..d10204501 100644 --- a/pyteal/ast/router.py +++ b/pyteal/ast/router.py @@ -352,7 +352,7 @@ def wrap_handler( ) # All subroutine arg values, initialize here and use below instead of - # creating new instances on the fly so we dont have to think about splicing + # creating new instances on the fly, so we don't have to think about splicing # back in the transaction types arg_vals = [typespec.new_instance() for typespec in arg_type_specs] diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 0c5e0205f..7fd38bc9d 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -9,7 +9,7 @@ from pyteal.ast.expr import Expr from pyteal.ast.seq import Seq from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar -from pyteal.errors import TealInputError, verifyProgramVersion +from pyteal.errors import TealInputError, TealInternalError, verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.types import TealType @@ -378,7 +378,7 @@ def __init__( elif isinstance(arg, ScratchVar): arg_type = arg.type elif isinstance(arg, abi.BaseType): - arg_type = cast(abi.BaseType, arg).stored_value.type + arg_type = cast(abi.BaseType, arg)._data_storage.storage_type() else: raise TealInputError( f"Subroutine argument {arg} at index {i} was of unexpected Python type {type(arg)}" @@ -420,7 +420,7 @@ def handle_arg(arg: Expr | ScratchVar | abi.BaseType) -> Expr: elif isinstance(arg, Expr): return arg elif isinstance(arg, abi.BaseType): - return arg.stored_value.load() + return arg._data_storage.load_value() else: raise TealInputError( f"cannot handle current arg: {arg} to put it on stack" @@ -595,8 +595,6 @@ def __call__( ) return invoked - self.subroutine.get_declaration() - return abi.ReturnedValue( self.output_kwarg_info.abi_type, invoked, @@ -793,6 +791,8 @@ def evaluate_subroutine(subroutine: SubroutineDefinition) -> SubroutineDeclarati def var_n_loaded( param: str, ) -> tuple[ScratchVar, ScratchVar | abi.BaseType | Expr]: + from pyteal.ast.abi.type import ScratchVarStorage + loaded_var: ScratchVar | abi.BaseType | Expr argument_var: ScratchVar @@ -801,7 +801,11 @@ def var_n_loaded( loaded_var = argument_var elif param in subroutine.abi_args: internal_abi_var = subroutine.abi_args[param].new_instance() - argument_var = internal_abi_var.stored_value + if not isinstance(internal_abi_var._data_storage, ScratchVarStorage): + raise TealInternalError( + "subroutine ABI args must have data schema being ScratchVarStorage" + ) + argument_var = internal_abi_var._data_storage.scratchvar loaded_var = internal_abi_var else: argument_var = ScratchVar(TealType.anytype) @@ -849,7 +853,7 @@ def var_n_loaded( f"ABI returning subroutine definition should evaluate to TealType.none, " f"while evaluate to {subroutine_body.type_of()}." ) - deferred_expr = output_carrying_abi.stored_value.load() + deferred_expr = output_carrying_abi._data_storage.load_value() # Arg usage "A" to be pick up and store in scratch parameters that have been placed on the stack # need to reverse order of argumentVars because the last argument will be on top of the stack From e8c5d2ca085a3194c21ed762e5abf95a952c6797 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 19 Oct 2022 13:22:41 -0400 Subject: [PATCH 020/157] squashed --- pyteal/ast/subroutine.py | 253 ++++++++++++++++++++++++++++++++++-- pyteal/compiler/compiler.py | 10 +- 2 files changed, 250 insertions(+), 13 deletions(-) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 7fd38bc9d..bad4b5cb1 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -8,7 +8,8 @@ from pyteal.ast import abi from pyteal.ast.expr import Expr from pyteal.ast.seq import Seq -from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar +from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar, ScratchSlot +from pyteal.ast.frame import FrameDig, Proto from pyteal.errors import TealInputError, TealInternalError, verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.types import TealType @@ -17,6 +18,100 @@ from pyteal.compiler import CompileOptions +class _SubroutineDeclByVersion: + def __init__(self, subroutine_def: "SubroutineDefinition") -> None: + from pyteal.compiler.compiler import FRAME_POINTER_VERSION, MAX_PROGRAM_VERSION + from pyteal.ir import Op + + self.subroutine: SubroutineDefinition = subroutine_def + self.version_map: dict[range, Optional[SubroutineDeclaration]] = { + range(Op.callsub.min_version, FRAME_POINTER_VERSION): None, + range(FRAME_POINTER_VERSION, MAX_PROGRAM_VERSION + 1): None, + } + self.version_method: dict[range, Callable[..., SubroutineDeclaration]] = { + range( + Op.callsub.min_version, FRAME_POINTER_VERSION + ): SubroutineEval.evaluator_gen(SubroutineEval.var_n_loaded), + range( + FRAME_POINTER_VERSION, MAX_PROGRAM_VERSION + 1 + ): SubroutineEval.evaluator_gen( + SubroutineEval.var_n_loaded_fp, use_proto=True + ), + } + self.has_return: Optional[bool] = None + self.type_of: Optional[TealType] = None + + def get_declaration(self) -> "SubroutineDeclaration": + # XXX MARK THIS METHOD TO BE DEPRECATED LATER I GUESS + from pyteal.ir import Op + + return self.get_declaration_by_version(Op.callsub.min_version) + + def get_declaration_by_version(self, version: int) -> "SubroutineDeclaration": + from pyteal.compiler.compiler import MAX_PROGRAM_VERSION + from pyteal.ir import Op + + for _r, decl in self.version_map.items(): + if version not in _r: + continue + if decl: + return decl + self.version_map[_r] = self.version_method[_r](self.subroutine) + return cast(SubroutineDeclaration, self.version_map[_r]) + + raise TealInputError( + f"version {version} must be in range [{Op.callsub.min_version}, {MAX_PROGRAM_VERSION}]." + ) + + def __erase_version(self, version: int): + for _r in self.version_map: + if version in _r: + self.version_map[_r] = None + + def __is_version_pre_existing(self, version: int) -> bool: + for _r in self.version_map: + if version in _r: + return self.version_map[_r] is not None + raise TealInputError(f"no such versioning {version}") + + def __probe_info(self, version: int) -> tuple[bool, TealType]: + current_slot_id = ScratchSlot.nextSlotId + is_pre_existing = self.__is_version_pre_existing(version) + decl = self.get_declaration_by_version(version) + has_return = decl.has_return() + type_of = decl.type_of() + if not is_pre_existing: + self.__erase_version(version) + ScratchSlot.nextSlotId = current_slot_id + return has_return, type_of + + def __info_prepare(self): + from pyteal.compiler.compiler import FRAME_POINTER_VERSION + + if self.has_return is not None and self.type_of is not None: + return + v2_ret, v2_type = self.__probe_info(FRAME_POINTER_VERSION - 1) + v8_ret, v8_type = self.__probe_info(FRAME_POINTER_VERSION) + assert v2_ret == v8_ret + assert v2_type == v8_type + self.has_return = v2_ret + self.type_of = v2_type + + def versions_type_of(self) -> TealType: + self.__info_prepare() + return cast(TealType, self.type_of) + + def versions_has_return(self) -> bool: + self.__info_prepare() + return cast(bool, self.has_return) + + def get_declarations(self): + for _r, decl in self.version_map.items(): + if decl: + continue + self.version_map[_r] = self.get_declaration_by_version(_r.start) + + class SubroutineDefinition: """ Class that leverages TEAL's `callsub` and `retsub` opcode-pair for subroutines @@ -45,6 +140,7 @@ def __init__( self.return_type = return_type self.declaration: Optional["SubroutineDeclaration"] = None + self.declarations: _SubroutineDeclByVersion = _SubroutineDeclByVersion(self) self.implementation: Callable = implementation self.has_abi_output: bool = has_abi_output @@ -239,10 +335,11 @@ def _validate_annotation( ) def get_declaration(self) -> "SubroutineDeclaration": - if self.declaration is None: - # lazy evaluate subroutine - self.declaration = evaluate_subroutine(self) - return self.declaration + # XXX MARK THIS METHOD TO BE DEPRECATED LATER I GUESS + return self.declarations.get_declaration() + + def get_declaration_by_version(self, version: int) -> "SubroutineDeclaration": + return self.declarations.get_declaration_by_version(version) def name(self) -> str: return self.__name @@ -472,10 +569,10 @@ def name(self) -> str: return self.subroutine.name() def type_of(self): - return self.subroutine.get_declaration().type_of() + return self.subroutine.declarations.versions_type_of() def has_return(self): - return self.subroutine.get_declaration().has_return() + return self.subroutine.declarations.versions_type_of() SubroutineFnWrapper.__module__ = "pyteal" @@ -744,6 +841,144 @@ def __call__(self, fn_implementation: Callable[..., Expr]) -> SubroutineFnWrappe Subroutine.__module__ = "pyteal" +# Personally prefer not to expose this evaluator static class, also not exposing evaluate_subroutine (to be deprecated) +class SubroutineEval: + @staticmethod + def var_n_loaded( + subroutine: SubroutineDefinition, + param: str, + ) -> tuple[ScratchVar, ScratchVar | abi.BaseType | Expr]: + from pyteal.ast.abi.type import ScratchVarStorage + + loaded_var: ScratchVar | abi.BaseType | Expr + argument_var: ScratchVar + + if param in subroutine.by_ref_args: + argument_var = DynamicScratchVar(TealType.anytype) + loaded_var = argument_var + elif param in subroutine.abi_args: + internal_abi_var = subroutine.abi_args[param].new_instance() + if not isinstance(internal_abi_var._data_storage, ScratchVarStorage): + raise TealInternalError("...") + argument_var = internal_abi_var._data_storage.scratchvar + loaded_var = internal_abi_var + else: + argument_var = ScratchVar(TealType.anytype) + loaded_var = argument_var.load() + + return argument_var, loaded_var + + @staticmethod + def var_n_loaded_fp( + subroutine: SubroutineDefinition, + param: str, + ) -> tuple[Optional[ScratchVar], ScratchVar | abi.BaseType | Expr]: + from pyteal.ast.abi.type import FrameStorage + + loaded_var: ScratchVar | abi.BaseType | Expr + argument_var: Optional[ScratchVar] + + if param in subroutine.by_ref_args: + argument_var = DynamicScratchVar(TealType.anytype) + loaded_var = argument_var + elif param in subroutine.abi_args: + internal_abi_var = subroutine.abi_args[param].new_instance() + dig_index = ( + subroutine.arguments().index(param) - subroutine.argument_count() + ) + internal_abi_var._set_data_source(FrameStorage(TealType.anytype, dig_index)) + argument_var = None + loaded_var = internal_abi_var + else: + dig_index = ( + subroutine.arguments().index(param) - subroutine.argument_count() + ) + argument_var = None + loaded_var = FrameDig(dig_index) + + return argument_var, loaded_var + + @staticmethod + def evaluator_gen( + var_n_loaded: Callable[ + [SubroutineDefinition, str], + tuple[Optional[ScratchVar], ScratchVar | abi.BaseType | Expr], + ], + /, + *, + use_proto: bool = False, + ) -> Callable[[SubroutineDefinition], SubroutineDeclaration]: + from pyteal.ast.abi.type import FrameStorage + + def evaluator(subroutine: SubroutineDefinition) -> SubroutineDeclaration: + args = subroutine.arguments() + arg_vars: list[ScratchVar] = [] + loaded_args: list[ScratchVar | Expr | abi.BaseType] = [] + for arg in args: + arg_var, loaded_arg = var_n_loaded(subroutine, arg) + if arg_var: + arg_vars.append(arg_var) + loaded_args.append(loaded_arg) + + abi_output_kwargs: dict[str, abi.BaseType] = {} + output_kwarg_info = OutputKwArgInfo.from_dict(subroutine.output_kwarg) + output_carrying_abi: Optional[abi.BaseType] = None + + if output_kwarg_info: + output_carrying_abi = output_kwarg_info.abi_type.new_instance() + if use_proto: + output_carrying_abi._data_storage = FrameStorage( + TealType.anytype, 0 + ) + abi_output_kwargs[output_kwarg_info.name] = output_carrying_abi + + # Arg usage "B" supplied to build an AST from the user-defined PyTEAL function: + subroutine_body = subroutine.implementation( + *loaded_args, **abi_output_kwargs + ) + if not isinstance(subroutine_body, Expr): + raise TealInputError( + f"Subroutine function does not return a PyTeal expression. Got type {type(subroutine_body)}." + ) + + deferred_expr: Optional[Expr] = None + + # if there is an output keyword argument for ABI, place the storing on the stack + if output_carrying_abi: + if subroutine_body.type_of() != TealType.none: + raise TealInputError( + f"ABI returning subroutine definition should evaluate to TealType.none, " + f"while evaluate to {subroutine_body.type_of()}." + ) + deferred_expr = output_carrying_abi._data_storage.load_value() + + # Arg usage "A" to be pick up and store in scratch parameters that have been placed on the stack + # need to reverse order of argumentVars because the last argument will be on top of the stack + body_ops: list[Expr] = [] + if use_proto: + body_ops += [ + Proto( + subroutine.argument_count(), + int( + subroutine_body.type_of() != TealType.none + if not subroutine.has_abi_output + else len(abi_output_kwargs) + ), + ) + ] + body_ops += [var.slot.store() for var in arg_vars[::-1]] + body_ops.append(subroutine_body) + + sd = SubroutineDeclaration(subroutine, Seq(body_ops), deferred_expr) + sd.trace = subroutine_body.trace + return sd + + return evaluator + + +SubroutineEval.__module__ = "pyteal" + + def evaluate_subroutine(subroutine: SubroutineDefinition) -> SubroutineDeclaration: """ Puts together the data necessary to define the code for a subroutine. @@ -802,9 +1037,7 @@ def var_n_loaded( elif param in subroutine.abi_args: internal_abi_var = subroutine.abi_args[param].new_instance() if not isinstance(internal_abi_var._data_storage, ScratchVarStorage): - raise TealInternalError( - "subroutine ABI args must have data schema being ScratchVarStorage" - ) + raise TealInternalError("...") argument_var = internal_abi_var._data_storage.scratchvar loaded_var = internal_abi_var else: diff --git a/pyteal/compiler/compiler.py b/pyteal/compiler/compiler.py index f2b25b489..3231b8e85 100644 --- a/pyteal/compiler/compiler.py +++ b/pyteal/compiler/compiler.py @@ -155,10 +155,14 @@ def compileSubroutine( if ( currentSubroutine is not None - and currentSubroutine.get_declaration().deferred_expr is not None + and currentSubroutine.get_declaration_by_version(options.version).deferred_expr + is not None ): # this represents code that should be inserted before each retsub op - deferred_expr = cast(Expr, currentSubroutine.get_declaration().deferred_expr) + deferred_expr = cast( + Expr, + currentSubroutine.get_declaration_by_version(options.version).deferred_expr, + ) for block in TealBlock.Iterate(start): if not any(op.getOp() == Op.retsub for op in block.ops): @@ -209,7 +213,7 @@ def compileSubroutine( newSubroutines = referencedSubroutines - subroutine_start_blocks.keys() for subroutine in sorted(newSubroutines, key=lambda subroutine: subroutine.id): compileSubroutine( - subroutine.get_declaration(), + subroutine.get_declaration_by_version(options.version), options, subroutineGraph, subroutine_start_blocks, From a044f803f2424a0f241530bb0f60a6db2024377b Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 19 Oct 2022 14:34:00 -0400 Subject: [PATCH 021/157] change in round trip test, stop something blocking me --- tests/abi_roundtrip.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/tests/abi_roundtrip.py b/tests/abi_roundtrip.py index efde3ecd3..ba0f4d8c0 100644 --- a/tests/abi_roundtrip.py +++ b/tests/abi_roundtrip.py @@ -1,4 +1,4 @@ -from typing import Generic, TypeVar +from typing import Generic, TypeVar, Optional import pyteal as pt from pyteal import abi @@ -14,13 +14,13 @@ class ABIRoundtrip(Generic[T]): def __init__( self, annotation_instance: abi.BaseType, - length: int | None = None, + length: Optional[int] = None, ): self.instance: abi.BaseType = annotation_instance self.type_spec: abi.TypeSpec = annotation_instance.type_spec() self.annotation: type[abi.BaseType] = self.type_spec.annotation_type() - self.length: int | None = length + self.length: Optional[int] = length def pytealer(self) -> PyTealDryRunExecutor: roundtrip = self.roundtrip_factory() @@ -120,13 +120,21 @@ def array_comp_factory(self) -> pt.ABIReturnSubroutine: When the length has not been provided for a dynamic array, default to DEFAULT_DYNAMIC_ARRAY_LENGTH """ - if self.length is not None: - assert self.type_spec.is_length_dynamic() # type: ignore[attr-defined] - elif not self.type_spec.is_length_dynamic(): # type: ignore[attr-defined] - self.length = self.type_spec.length_static() # type: ignore[attr-defined] - else: + if not self.type_spec.is_length_dynamic(): # type: ignore[attr-defined] + if self.length: + assert self.length == self.type_spec.length_static() # type: ignore[attr-defined] + else: + self.length = self.type_spec.length_static() # type: ignore[attr-defined] + elif self.length is None: self.length = DEFAULT_DYNAMIC_ARRAY_LENGTH + # if self.length is not None: + # assert self.type_spec.is_length_dynamic() # type: ignore[attr-defined] + # elif not self.type_spec.is_length_dynamic(): # type: ignore[attr-defined] + # self.length = self.type_spec.length_static() # type: ignore[attr-defined] + # else: + # self.length = DEFAULT_DYNAMIC_ARRAY_LENGTH + internal_type_spec = self.type_spec.value_type_spec() # type: ignore[attr-defined] internal_ann_inst = internal_type_spec.new_instance() comp_func = ABIRoundtrip(internal_ann_inst, length=None).mutator_factory() From 6739c00cbf1296d32dd694c854d8a5b8e31a1a01 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 19 Oct 2022 15:43:27 -0400 Subject: [PATCH 022/157] update frame dig and proto use --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 50b59f15f..b18775124 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,6 +11,6 @@ services: - DEV_MODE - TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa healthcheck: - test: goal node status || exit 1 + test: goal node status interval: 2s retries: 10 From ce9aec85f5825a8295dd6e18159ddab3e1dbc3cb Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 19 Oct 2022 19:29:48 -0400 Subject: [PATCH 023/157] fix var n loaded --- pyteal/ast/subroutine.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index bad4b5cb1..ab63e15e6 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -21,7 +21,6 @@ class _SubroutineDeclByVersion: def __init__(self, subroutine_def: "SubroutineDefinition") -> None: from pyteal.compiler.compiler import FRAME_POINTER_VERSION, MAX_PROGRAM_VERSION - from pyteal.ir import Op self.subroutine: SubroutineDefinition = subroutine_def self.version_map: dict[range, Optional[SubroutineDeclaration]] = { @@ -43,13 +42,10 @@ def __init__(self, subroutine_def: "SubroutineDefinition") -> None: def get_declaration(self) -> "SubroutineDeclaration": # XXX MARK THIS METHOD TO BE DEPRECATED LATER I GUESS - from pyteal.ir import Op - return self.get_declaration_by_version(Op.callsub.min_version) def get_declaration_by_version(self, version: int) -> "SubroutineDeclaration": from pyteal.compiler.compiler import MAX_PROGRAM_VERSION - from pyteal.ir import Op for _r, decl in self.version_map.items(): if version not in _r: From 620c61e6880d26dcfa83ceb7c6672459835b6263 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 26 Oct 2022 16:45:21 -0400 Subject: [PATCH 024/157] documentation --- pyteal/ast/subroutine.py | 110 +++++++++++++++++++++++++++++++----- pyteal/compiler/compiler.py | 3 +- 2 files changed, 97 insertions(+), 16 deletions(-) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index ab63e15e6..b9c95d221 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -30,12 +30,10 @@ def __init__(self, subroutine_def: "SubroutineDefinition") -> None: self.version_method: dict[range, Callable[..., SubroutineDeclaration]] = { range( Op.callsub.min_version, FRAME_POINTER_VERSION - ): SubroutineEval.evaluator_gen(SubroutineEval.var_n_loaded), + ): SubroutineEval.normal_evaluator, range( FRAME_POINTER_VERSION, MAX_PROGRAM_VERSION + 1 - ): SubroutineEval.evaluator_gen( - SubroutineEval.var_n_loaded_fp, use_proto=True - ), + ): SubroutineEval.fp_evaluator, } self.has_return: Optional[bool] = None self.type_of: Optional[TealType] = None @@ -59,10 +57,16 @@ def get_declaration_by_version(self, version: int) -> "SubroutineDeclaration": f"version {version} must be in range [{Op.callsub.min_version}, {MAX_PROGRAM_VERSION}]." ) - def __erase_version(self, version: int): + def __erase_version(self, version: int) -> None: + from pyteal.compiler.compiler import MAX_PROGRAM_VERSION + for _r in self.version_map: if version in _r: self.version_map[_r] = None + return + raise TealInputError( + f"version {version} must be in range [{Op.callsub.min_version}, {MAX_PROGRAM_VERSION}]." + ) def __is_version_pre_existing(self, version: int) -> bool: for _r in self.version_map: @@ -74,17 +78,16 @@ def __probe_info(self, version: int) -> tuple[bool, TealType]: current_slot_id = ScratchSlot.nextSlotId is_pre_existing = self.__is_version_pre_existing(version) decl = self.get_declaration_by_version(version) - has_return = decl.has_return() - type_of = decl.type_of() + has_return, type_of = decl.has_return(), decl.type_of() if not is_pre_existing: self.__erase_version(version) ScratchSlot.nextSlotId = current_slot_id return has_return, type_of - def __info_prepare(self): + def __info_prepare(self) -> None: from pyteal.compiler.compiler import FRAME_POINTER_VERSION - if self.has_return is not None and self.type_of is not None: + if self.has_return and self.type_of: return v2_ret, v2_type = self.__probe_info(FRAME_POINTER_VERSION - 1) v8_ret, v8_type = self.__probe_info(FRAME_POINTER_VERSION) @@ -101,7 +104,7 @@ def versions_has_return(self) -> bool: self.__info_prepare() return cast(bool, self.has_return) - def get_declarations(self): + def get_declarations(self) -> None: for _r, decl in self.version_map.items(): if decl: continue @@ -837,10 +840,77 @@ def __call__(self, fn_implementation: Callable[..., Expr]) -> SubroutineFnWrappe Subroutine.__module__ = "pyteal" -# Personally prefer not to expose this evaluator static class, also not exposing evaluate_subroutine (to be deprecated) class SubroutineEval: + """ + Puts together the data necessary to define the code for a subroutine. + "evaluate" is used here to connote evaluating the PyTEAL AST into a SubroutineDeclaration, + but not actually placing it at call locations. The trickiest part here is managing the subroutine's arguments. + The arguments are needed for two different code-paths, and there are 2 different argument types to consider + for each of the code-paths. + + 2 Argument Usages / Code-Paths + - -------- ------ ---------- + Usage (A) for run-time: "argumentVars" --reverse--> "body_ops" + These are "store" expressions that pick up parameters that have been pre-placed on the stack prior to subroutine invocation. + The argumentVars are stored into local scratch space to be used by the TEAL subroutine. + + Usage (B) for compile-time: "loadedArgs" + These are expressions supplied to the user-defined PyTEAL function. + The loadedArgs are invoked to by the subroutine to create a self-contained AST which will translate into a TEAL subroutine. + + In both usage cases, we need to handle + + 4 Argument Types + - -------- ----- + Type 1 (by-value): these have python type Expr + Type 2 (by-reference): these have python type ScratchVar + Type 3 (ABI): these are ABI typed variables with scratch space storage, and still pass by value + Type 4 (ABI-output-arg): ABI typed variables with scratch space, a new ABI instance is generated inside function body, + not one of the cases in the previous three options + + Because of the introduction of frame pointer, the "argumentVars" and "loadedArgs" are different before and after program version 8. + + "argumentVars" and "loadedArgs" before version 8 (frame pointer version) + -------------- --- ------------ ------ ------- - ----------------------- + + Usage (A) "argumentVars" - Storing pre-placed stack variables into local scratch space: + Type 1. (by-value) use ScratchVar.store() to pick the actual value into a local scratch space + Type 2. (by-reference) ALSO use ScratchVar.store() to pick up from the stack + NOTE: SubroutineCall.__teal__() has placed the _SLOT INDEX_ on the stack so this is stored into the local scratch space + Type 3. (ABI) abi_value.stored_value.store() to pick from the stack + Type 4. (ABI-output-arg) it is not really used here, since it is only generated internal of the subroutine + + Usage (B) "loadedArgs" - Passing through to an invoked PyTEAL subroutine AST: + Type 1. (by-value) use ScratchVar.load() to have an Expr that can be compiled in python by the PyTEAL subroutine + Type 2. (by-reference) use a DynamicScratchVar as the user will have written the PyTEAL in a way that satisfies + the ScratchVar API. I.e., the user will write `x.load()` and `x.store(val)` as opposed to just `x`. + Type 3. (ABI) use abi_value itself after storing stack value into scratch space. + Type 4. (ABI-output-arg) generates a new instance of the ABI value, + and appends a return expression of stored value of the ABI keyword value. + + "argumentVars" and "loadedArgs" after version 8 (frame pointer version) + -------------- --- ------------ ----- ------- - ----------------------- + + Usage (A) "argumentVars" - Storing pre-placed stack variables with frame pointer: + Type 1. (by-value) use None for we can load from stack with FrameDig() + Type 2. (by-reference) ALSO use FrameDig to pick up from the stack + NOTE: SubroutineCall.__teal__() has placed the _SLOT INDEX_ on the stack so this is stored into the local scratch space + Type 3. (ABI) use None for we can load from stack with FrameDig() + NOTE: SubroutineCall.__teal__() has placed the ABI encoding on the stack, so ABI set and get methods are working over stack + Type 4. (ABI-output-arg) it is not really used here, but we use FrameDig/Bury to interact with it + + TODO need to repolish later after merge and rebase + Usage (B) "loadedArgs" - Passing through to an invoked PyTEAL subroutine AST: + Type 1. (by-value) use FrameDig() to have an Expr that can be compiled in python by the PyTEAL subroutine + Type 2. (by-reference) use a DynamicScratchVar as the user will have written the PyTEAL in a way that satisfies + the ScratchVar API. I.e., the user will write `x.load()` and `x.store(val)` as opposed to just `x`. + Type 3. (ABI) use abi_value that interface with stack data through FrameDig/FrameBury + Type 4. (ABI-output-arg) generates a new instance of the ABI value, + and appends a return expression of stored value of the ABI keyword value. + """ + @staticmethod - def var_n_loaded( + def __var_n_loaded( subroutine: SubroutineDefinition, param: str, ) -> tuple[ScratchVar, ScratchVar | abi.BaseType | Expr]: @@ -865,7 +935,7 @@ def var_n_loaded( return argument_var, loaded_var @staticmethod - def var_n_loaded_fp( + def __var_n_loaded_fp( subroutine: SubroutineDefinition, param: str, ) -> tuple[Optional[ScratchVar], ScratchVar | abi.BaseType | Expr]: @@ -895,7 +965,7 @@ def var_n_loaded_fp( return argument_var, loaded_var @staticmethod - def evaluator_gen( + def __evaluator_gen( var_n_loaded: Callable[ [SubroutineDefinition, str], tuple[Optional[ScratchVar], ScratchVar | abi.BaseType | Expr], @@ -971,12 +1041,24 @@ def evaluator(subroutine: SubroutineDefinition) -> SubroutineDeclaration: return evaluator + @staticmethod + def normal_evaluator(subroutine: SubroutineDefinition) -> SubroutineDeclaration: + return SubroutineEval.__evaluator_gen(SubroutineEval.__var_n_loaded)(subroutine) + + @staticmethod + def fp_evaluator(subroutine: SubroutineDefinition) -> SubroutineDeclaration: + return SubroutineEval.__evaluator_gen( + SubroutineEval.__var_n_loaded_fp, use_proto=True + )(subroutine) + SubroutineEval.__module__ = "pyteal" def evaluate_subroutine(subroutine: SubroutineDefinition) -> SubroutineDeclaration: """ + NOTE: THIS METHOD IS DEPRECATED, USE CLASS `SubroutineEval` INSTEAD FOR SUBROUTINE EVALUATOR + Puts together the data necessary to define the code for a subroutine. "evaluate" is used here to connote evaluating the PyTEAL AST into a SubroutineDeclaration, but not actually placing it at call locations. The trickiest part here is managing the subroutine's arguments. diff --git a/pyteal/compiler/compiler.py b/pyteal/compiler/compiler.py index 3231b8e85..304c40383 100644 --- a/pyteal/compiler/compiler.py +++ b/pyteal/compiler/compiler.py @@ -154,9 +154,8 @@ def compileSubroutine( start.validateTree() if ( - currentSubroutine is not None + currentSubroutine and currentSubroutine.get_declaration_by_version(options.version).deferred_expr - is not None ): # this represents code that should be inserted before each retsub op deferred_expr = cast( From 87d97b1e41924771e4a02927e34ff4338b844113 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Thu, 27 Oct 2022 10:49:51 -0400 Subject: [PATCH 025/157] narrower name, module name --- pyteal/ast/abi/__init__.py | 4 ++-- pyteal/ast/abi/address_test.py | 22 +++++++++++----------- pyteal/ast/abi/array_dynamic_test.py | 20 ++++++++++---------- pyteal/ast/abi/array_static_test.py | 14 +++++++------- pyteal/ast/abi/bool_test.py | 20 ++++++++++---------- pyteal/ast/abi/reference_type_test.py | 8 ++++---- pyteal/ast/abi/string_test.py | 20 ++++++++++---------- pyteal/ast/abi/transaction_test.py | 2 +- pyteal/ast/abi/tuple_test.py | 4 ++-- pyteal/ast/abi/type.py | 13 +++++++++++-- pyteal/ast/abi/uint_test.py | 20 +++++++++----------- pyteal/ast/subroutine.py | 4 ++-- 12 files changed, 79 insertions(+), 72 deletions(-) diff --git a/pyteal/ast/abi/__init__.py b/pyteal/ast/abi/__init__.py index 3113b8d72..3ca3ab290 100644 --- a/pyteal/ast/abi/__init__.py +++ b/pyteal/ast/abi/__init__.py @@ -11,7 +11,7 @@ ReturnedValue, DataStorageSchema, FrameStorage, - ScratchVarStorage, + ScratchStorage, ) from pyteal.ast.abi.bool import BoolTypeSpec, Bool from pyteal.ast.abi.uint import ( @@ -176,7 +176,7 @@ "size_of", "DataStorageSchema", "FrameStorage", - "ScratchVarStorage", + "ScratchStorage", "algosdk_from_annotation", "algosdk_from_type_spec", "contains_type_spec", diff --git a/pyteal/ast/abi/address_test.py b/pyteal/ast/abi/address_test.py index 305046619..dca9136dc 100644 --- a/pyteal/ast/abi/address_test.py +++ b/pyteal/ast/abi/address_test.py @@ -53,7 +53,7 @@ def test_Address_encode(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -117,7 +117,7 @@ def test_Address_get(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -139,12 +139,12 @@ def test_Address_set_StaticArray(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value_to_set._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value_to_set._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -174,7 +174,7 @@ def test_Address_set_str(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -203,7 +203,7 @@ def test_Address_set_bytes(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -236,12 +236,12 @@ def test_Address_set_expr(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.int, AddressLength.Bytes.value), @@ -270,12 +270,12 @@ def test_Address_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -307,7 +307,7 @@ def test_Address_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) diff --git a/pyteal/ast/abi/array_dynamic_test.py b/pyteal/ast/abi/array_dynamic_test.py index fa0e122e1..3e172eeee 100644 --- a/pyteal/ast/abi/array_dynamic_test.py +++ b/pyteal/ast/abi/array_dynamic_test.py @@ -185,12 +185,12 @@ def test_DynamicArray_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, otherArray._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, otherArray._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -218,7 +218,7 @@ def test_DynamicArray_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -268,7 +268,7 @@ def test_DynamicBytes_set_py_bytes(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -299,12 +299,12 @@ def test_DynamicBytes_set_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.itob), @@ -312,13 +312,13 @@ def test_DynamicBytes_set_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.concat), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -343,7 +343,7 @@ def test_DynamicBytes_get(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.extract, 2, 0), ] @@ -365,7 +365,7 @@ def test_DynamicArray_encode(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) diff --git a/pyteal/ast/abi/array_static_test.py b/pyteal/ast/abi/array_static_test.py index 236e2591e..7d0a8ae0a 100644 --- a/pyteal/ast/abi/array_static_test.py +++ b/pyteal/ast/abi/array_static_test.py @@ -237,12 +237,12 @@ def test_StaticArray_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, otherArray._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, otherArray._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -270,7 +270,7 @@ def test_StaticArray_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -317,7 +317,7 @@ def test_StaticBytes_set_py_bytes(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -352,13 +352,13 @@ def test_StaticBytes_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.int, 32), pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.eq), @@ -381,7 +381,7 @@ def test_StaticArray_encode(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) diff --git a/pyteal/ast/abi/bool_test.py b/pyteal/ast/abi/bool_test.py index 411bdf376..4299b72ce 100644 --- a/pyteal/ast/abi/bool_test.py +++ b/pyteal/ast/abi/bool_test.py @@ -56,7 +56,7 @@ def test_Bool_set_static(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -85,7 +85,7 @@ def test_Bool_set_expr(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -110,12 +110,12 @@ def test_Bool_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -144,7 +144,7 @@ def test_Bool_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -171,7 +171,7 @@ def test_Bool_get(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -204,7 +204,7 @@ def test_Bool_decode(): None, pt.Op.store, cast( - abi.ScratchVarStorage, value._data_storage + abi.ScratchStorage, value._data_storage ).scratchvar.slot, ), ] @@ -234,7 +234,7 @@ def test_Bool_decode_bit(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -260,7 +260,7 @@ def test_Bool_encode(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.setbit), ] @@ -444,7 +444,7 @@ class EncodeSeqTest(NamedTuple): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, testType._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, testType._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.setbit), ] diff --git a/pyteal/ast/abi/reference_type_test.py b/pyteal/ast/abi/reference_type_test.py index aaa1e5d97..d3b8aaf93 100644 --- a/pyteal/ast/abi/reference_type_test.py +++ b/pyteal/ast/abi/reference_type_test.py @@ -26,7 +26,7 @@ def test_ReferenceType_referenced_index(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -117,7 +117,7 @@ def test_Account_address(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.txnas, "Accounts"), ] @@ -204,7 +204,7 @@ def test_Asset_asset_id(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.txnas, "Assets"), ] @@ -298,7 +298,7 @@ def test_Application_application_id(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.txnas, "Applications"), ] diff --git a/pyteal/ast/abi/string_test.py b/pyteal/ast/abi/string_test.py index 79a699a4c..fb8de7fb9 100644 --- a/pyteal/ast/abi/string_test.py +++ b/pyteal/ast/abi/string_test.py @@ -44,7 +44,7 @@ def test_String_encode(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -107,7 +107,7 @@ def test_String_get(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.extract, 2, 0), ] @@ -143,7 +143,7 @@ def test_String_set_static(value_to_set, value_encoded): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -174,12 +174,12 @@ def test_String_set_expr(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.itob), @@ -187,13 +187,13 @@ def test_String_set_expr(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.concat), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -222,12 +222,12 @@ def test_String_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -259,7 +259,7 @@ def test_String_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) diff --git a/pyteal/ast/abi/transaction_test.py b/pyteal/ast/abi/transaction_test.py index 573d6f440..e21802950 100644 --- a/pyteal/ast/abi/transaction_test.py +++ b/pyteal/ast/abi/transaction_test.py @@ -134,7 +134,7 @@ def test_Transaction__set_index(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, tv.t._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, tv.t._data_storage).scratchvar.slot, ), ] ) diff --git a/pyteal/ast/abi/tuple_test.py b/pyteal/ast/abi/tuple_test.py index 8365769cc..777d3688e 100644 --- a/pyteal/ast/abi/tuple_test.py +++ b/pyteal/ast/abi/tuple_test.py @@ -706,7 +706,7 @@ def test_Tuple_set_Computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, tupleValue._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, tupleValue._data_storage).scratchvar.slot, ), ] ) @@ -737,7 +737,7 @@ def test_Tuple_encode(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, tupleValue._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, tupleValue._data_storage).scratchvar.slot, ), ] ) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index 67d75cc4b..c505021c0 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -79,7 +79,10 @@ def storage_type(self) -> TealType: pass -class ScratchVarStorage(DataStorageSchema): +DataStorageSchema.__module__ = "pyteal" + + +class ScratchStorage(DataStorageSchema): def __init__(self, storage_type: TealType) -> None: super().__init__() self.scratchvar: Final = ScratchVar(storage_type) @@ -94,6 +97,9 @@ def storage_type(self) -> TealType: return self.scratchvar.storage_type() +ScratchStorage.__module__ = "pyteal" + + class FrameStorage(DataStorageSchema): def __init__(self, storage_type: TealType, stack_depth: int) -> None: super().__init__() @@ -114,6 +120,9 @@ def load_value(self) -> Expr: return FrameDig(self.stack_depth) +FrameStorage.__module__ = "pyteal" + + class BaseType(ABC): """The abstract base class for all ABI type instances. @@ -126,7 +135,7 @@ def __init__(self, spec: TypeSpec) -> None: """Create a new BaseType.""" super().__init__() self._type_spec: Final = spec - self._data_storage: DataStorageSchema = ScratchVarStorage(spec.storage_type()) + self._data_storage: DataStorageSchema = ScratchStorage(spec.storage_type()) # self.stored_value: Final = ScratchVar(spec.storage_type()) diff --git a/pyteal/ast/abi/uint_test.py b/pyteal/ast/abi/uint_test.py index c4659fdb9..d4b7cd137 100644 --- a/pyteal/ast/abi/uint_test.py +++ b/pyteal/ast/abi/uint_test.py @@ -142,9 +142,7 @@ def test_Uint_set_static(): pt.TealOp( None, pt.Op.store, - cast( - abi.ScratchVarStorage, value._data_storage - ).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -176,7 +174,7 @@ def test_Uint_set_expr(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.int, test.maxValue + 1), pt.TealOp(None, pt.Op.lt), @@ -191,7 +189,7 @@ def test_Uint_set_expr(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] + upperBoundCheck @@ -218,12 +216,12 @@ def test_Uint_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -255,7 +253,7 @@ def test_Uint_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -283,7 +281,7 @@ def test_Uint_get(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -361,13 +359,13 @@ def test_ByteUint8_mutual_conversion(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.store, cast( - abi.ScratchVarStorage, type_b_instance._data_storage + abi.ScratchStorage, type_b_instance._data_storage ).scratchvar.slot, ), ] diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 7fd38bc9d..70365d756 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -791,7 +791,7 @@ def evaluate_subroutine(subroutine: SubroutineDefinition) -> SubroutineDeclarati def var_n_loaded( param: str, ) -> tuple[ScratchVar, ScratchVar | abi.BaseType | Expr]: - from pyteal.ast.abi.type import ScratchVarStorage + from pyteal.ast.abi.type import ScratchStorage loaded_var: ScratchVar | abi.BaseType | Expr argument_var: ScratchVar @@ -801,7 +801,7 @@ def var_n_loaded( loaded_var = argument_var elif param in subroutine.abi_args: internal_abi_var = subroutine.abi_args[param].new_instance() - if not isinstance(internal_abi_var._data_storage, ScratchVarStorage): + if not isinstance(internal_abi_var._data_storage, ScratchStorage): raise TealInternalError( "subroutine ABI args must have data schema being ScratchVarStorage" ) From 208be8008e7ea4c0a8456e70a0ed977e2bb41308 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Thu, 27 Oct 2022 11:30:59 -0400 Subject: [PATCH 026/157] reformat evaluator code, less indentation --- pyteal/ast/subroutine.py | 155 ++++++++++++++++++--------------------- 1 file changed, 73 insertions(+), 82 deletions(-) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index b32df07e8..d9b87beb8 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -27,13 +27,13 @@ def __init__(self, subroutine_def: "SubroutineDefinition") -> None: range(Op.callsub.min_version, FRAME_POINTER_VERSION): None, range(FRAME_POINTER_VERSION, MAX_PROGRAM_VERSION + 1): None, } - self.version_method: dict[range, Callable[..., SubroutineDeclaration]] = { + self.version_method: dict[range, SubroutineEval] = { range( Op.callsub.min_version, FRAME_POINTER_VERSION - ): SubroutineEval.normal_evaluator, + ): SubroutineEval.normal_evaluator(), range( FRAME_POINTER_VERSION, MAX_PROGRAM_VERSION + 1 - ): SubroutineEval.fp_evaluator, + ): SubroutineEval.fp_evaluator(), } self.has_return: Optional[bool] = None self.type_of: Optional[TealType] = None @@ -111,6 +111,9 @@ def get_declarations(self) -> None: self.version_map[_r] = self.get_declaration_by_version(_r.start) +_SubroutineDeclByVersion.__module__ = "pyteal" + + class SubroutineDefinition: """ Class that leverages TEAL's `callsub` and `retsub` opcode-pair for subroutines @@ -840,6 +843,7 @@ def __call__(self, fn_implementation: Callable[..., Expr]) -> SubroutineFnWrappe Subroutine.__module__ = "pyteal" +@dataclass class SubroutineEval: """ Puts together the data necessary to define the code for a subroutine. @@ -909,6 +913,12 @@ class SubroutineEval: and appends a return expression of stored value of the ABI keyword value. """ + var_n_loaded: Callable[ + [SubroutineDefinition, str], + tuple[Optional[ScratchVar], ScratchVar | abi.BaseType | Expr], + ] + use_frame_pt: bool = False + @staticmethod def __var_n_loaded( subroutine: SubroutineDefinition, @@ -966,92 +976,73 @@ def __var_n_loaded_fp( return argument_var, loaded_var - @staticmethod - def __evaluator_gen( - var_n_loaded: Callable[ - [SubroutineDefinition, str], - tuple[Optional[ScratchVar], ScratchVar | abi.BaseType | Expr], - ], - /, - *, - use_proto: bool = False, - ) -> Callable[[SubroutineDefinition], SubroutineDeclaration]: + def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: from pyteal.ast.abi.type import FrameStorage - def evaluator(subroutine: SubroutineDefinition) -> SubroutineDeclaration: - args = subroutine.arguments() - arg_vars: list[ScratchVar] = [] - loaded_args: list[ScratchVar | Expr | abi.BaseType] = [] - for arg in args: - arg_var, loaded_arg = var_n_loaded(subroutine, arg) - if arg_var: - arg_vars.append(arg_var) - loaded_args.append(loaded_arg) - - abi_output_kwargs: dict[str, abi.BaseType] = {} - output_kwarg_info = OutputKwArgInfo.from_dict(subroutine.output_kwarg) - output_carrying_abi: Optional[abi.BaseType] = None - - if output_kwarg_info: - output_carrying_abi = output_kwarg_info.abi_type.new_instance() - if use_proto: - output_carrying_abi._data_storage = FrameStorage( - TealType.anytype, 0 - ) - abi_output_kwargs[output_kwarg_info.name] = output_carrying_abi - - # Arg usage "B" supplied to build an AST from the user-defined PyTEAL function: - subroutine_body = subroutine.implementation( - *loaded_args, **abi_output_kwargs + args = subroutine.arguments() + arg_vars: list[ScratchVar] = [] + loaded_args: list[ScratchVar | Expr | abi.BaseType] = [] + for arg in args: + arg_var, loaded_arg = self.var_n_loaded(subroutine, arg) + if arg_var: + arg_vars.append(arg_var) + loaded_args.append(loaded_arg) + + abi_output_kwargs: dict[str, abi.BaseType] = {} + output_kwarg_info = OutputKwArgInfo.from_dict(subroutine.output_kwarg) + output_carrying_abi: Optional[abi.BaseType] = None + + if output_kwarg_info: + output_carrying_abi = output_kwarg_info.abi_type.new_instance() + if self.use_frame_pt: + output_carrying_abi._data_storage = FrameStorage(TealType.anytype, 0) + abi_output_kwargs[output_kwarg_info.name] = output_carrying_abi + + # Arg usage "B" supplied to build an AST from the user-defined PyTEAL function: + subroutine_body = subroutine.implementation(*loaded_args, **abi_output_kwargs) + if not isinstance(subroutine_body, Expr): + raise TealInputError( + f"Subroutine function does not return a PyTeal expression. Got type {type(subroutine_body)}." ) - if not isinstance(subroutine_body, Expr): - raise TealInputError( - f"Subroutine function does not return a PyTeal expression. Got type {type(subroutine_body)}." - ) - - deferred_expr: Optional[Expr] = None - # if there is an output keyword argument for ABI, place the storing on the stack - if output_carrying_abi: - if subroutine_body.type_of() != TealType.none: - raise TealInputError( - f"ABI returning subroutine definition should evaluate to TealType.none, " - f"while evaluate to {subroutine_body.type_of()}." - ) - deferred_expr = output_carrying_abi._data_storage.load_value() - - # Arg usage "A" to be pick up and store in scratch parameters that have been placed on the stack - # need to reverse order of argumentVars because the last argument will be on top of the stack - body_ops: list[Expr] = [] - if use_proto: - body_ops += [ - Proto( - subroutine.argument_count(), - int( - subroutine_body.type_of() != TealType.none - if not subroutine.has_abi_output - else len(abi_output_kwargs) - ), - ) - ] - body_ops += [var.slot.store() for var in arg_vars[::-1]] - body_ops.append(subroutine_body) + deferred_expr: Optional[Expr] = None - sd = SubroutineDeclaration(subroutine, Seq(body_ops), deferred_expr) - sd.trace = subroutine_body.trace - return sd - - return evaluator + # if there is an output keyword argument for ABI, place the storing on the stack + if output_carrying_abi: + if subroutine_body.type_of() != TealType.none: + raise TealInputError( + f"ABI returning subroutine definition should evaluate to TealType.none, " + f"while evaluate to {subroutine_body.type_of()}." + ) + deferred_expr = output_carrying_abi._data_storage.load_value() + + # Arg usage "A" to be pick up and store in scratch parameters that have been placed on the stack + # need to reverse order of argumentVars because the last argument will be on top of the stack + body_ops: list[Expr] = [] + if self.use_frame_pt: + body_ops += [ + Proto( + subroutine.argument_count(), + int( + subroutine_body.type_of() != TealType.none + if not subroutine.has_abi_output + else len(abi_output_kwargs) + ), + ) + ] + body_ops += [var.slot.store() for var in arg_vars[::-1]] + body_ops.append(subroutine_body) + sd = SubroutineDeclaration(subroutine, Seq(body_ops), deferred_expr) + sd.trace = subroutine_body.trace + return sd - @staticmethod - def normal_evaluator(subroutine: SubroutineDefinition) -> SubroutineDeclaration: - return SubroutineEval.__evaluator_gen(SubroutineEval.__var_n_loaded)(subroutine) + @classmethod + def normal_evaluator(cls) -> "SubroutineEval": + return cls(SubroutineEval.__var_n_loaded, False) - @staticmethod - def fp_evaluator(subroutine: SubroutineDefinition) -> SubroutineDeclaration: - return SubroutineEval.__evaluator_gen( - SubroutineEval.__var_n_loaded_fp, use_proto=True - )(subroutine) + @classmethod + def fp_evaluator(cls) -> "SubroutineEval": + return cls(SubroutineEval.__var_n_loaded_fp, True) SubroutineEval.__module__ = "pyteal" From d3fd16d58e46c278d50d5957f345ff55e112b0a6 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Thu, 27 Oct 2022 12:42:26 -0400 Subject: [PATCH 027/157] minor, found a bug on output setting in subroutine in frame pointer compile --- pyteal/ast/subroutine.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index d9b87beb8..20a831493 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -8,8 +8,9 @@ from pyteal.ast import abi from pyteal.ast.expr import Expr from pyteal.ast.seq import Seq +from pyteal.ast.int import Int from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar, ScratchSlot -from pyteal.ast.frame import FrameDig, Proto +from pyteal.ast.frame import FrameBury, FrameDig, Proto from pyteal.errors import TealInputError, TealInternalError, verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.types import TealType @@ -1019,17 +1020,22 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: # Arg usage "A" to be pick up and store in scratch parameters that have been placed on the stack # need to reverse order of argumentVars because the last argument will be on top of the stack body_ops: list[Expr] = [] + + stack_output_cnt: int + if not subroutine.has_abi_output: + # if subroutine do not have abi output, then only two cases happen: + # - subroutine is a normal subroutine, then check subroutine body evaluates to something, rather than none + # - subroutine is an ABIReturnSubroutine, the type is void, and its subroutine body type of is always none + stack_output_cnt = int(subroutine_body.type_of() != TealType.none) + else: + stack_output_cnt = len(abi_output_kwargs) + if self.use_frame_pt: - body_ops += [ - Proto( - subroutine.argument_count(), - int( - subroutine_body.type_of() != TealType.none - if not subroutine.has_abi_output - else len(abi_output_kwargs) - ), - ) - ] + body_ops = [Proto(subroutine.argument_count(), stack_output_cnt)] + # reserve a spot for output variable on stack? + if stack_output_cnt > 0 and subroutine.has_abi_output: + body_ops.append(FrameBury(Int(0), 0)) + body_ops += [var.slot.store() for var in arg_vars[::-1]] body_ops.append(subroutine_body) sd = SubroutineDeclaration(subroutine, Seq(body_ops), deferred_expr) From 2b4bb176e44a4b7bb772174519cbf6757a7b1c4e Mon Sep 17 00:00:00 2001 From: Hang Su Date: Thu, 27 Oct 2022 17:33:01 -0400 Subject: [PATCH 028/157] one small step in testing, a big step for frame pointer! --- docker-compose.yml | 2 +- tests/integration/graviton_test.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index b18775124..8c18a1501 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,7 +8,7 @@ services: - "4160:4160" # gossip - "9100:9100" # prometheus environment: - - DEV_MODE + - DEV_MODE=true - TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa healthcheck: test: goal node status diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index 1b0bc3c04..91d2a655e 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -549,6 +549,7 @@ def test_blackbox_subroutines_as_apps( scenario: Dict[str, Any], ): blackbox_test_runner(subr, pt.Mode.Application, scenario, 6) + blackbox_test_runner(subr, pt.Mode.Application, scenario, 8) @pytest.mark.parametrize("subr, scenario", LOGICSIG_SCENARIOS.items()) @@ -557,6 +558,7 @@ def test_blackbox_subroutines_as_logic_sigs( scenario: Dict[str, Any], ): blackbox_test_runner(subr, pt.Mode.Signature, scenario, 6) + blackbox_test_runner(subr, pt.Mode.Signature, scenario, 8) def blackbox_pyteal_example1(): From 411f007b93b9a06de33448a8cce511932a047ea8 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Fri, 28 Oct 2022 13:38:35 -0400 Subject: [PATCH 029/157] work in black box testing --- pyteal/ast/subroutine.py | 18 ++++--- tests/integration/graviton_test.py | 84 ++++++++++++++++++++++++++++-- 2 files changed, 91 insertions(+), 11 deletions(-) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 20a831493..3f1feb24d 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -8,9 +8,10 @@ from pyteal.ast import abi from pyteal.ast.expr import Expr from pyteal.ast.seq import Seq -from pyteal.ast.int import Int + +# from pyteal.ast.int import Int from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar, ScratchSlot -from pyteal.ast.frame import FrameBury, FrameDig, Proto +from pyteal.ast.frame import FrameDig, Proto # FrameBury from pyteal.errors import TealInputError, TealInternalError, verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.types import TealType @@ -978,7 +979,7 @@ def __var_n_loaded_fp( return argument_var, loaded_var def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: - from pyteal.ast.abi.type import FrameStorage + # from pyteal.ast.abi.type import FrameStorage args = subroutine.arguments() arg_vars: list[ScratchVar] = [] @@ -995,8 +996,9 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: if output_kwarg_info: output_carrying_abi = output_kwarg_info.abi_type.new_instance() - if self.use_frame_pt: - output_carrying_abi._data_storage = FrameStorage(TealType.anytype, 0) + # TODO seems to need a "prefix expr" to let output frame bury work + # if self.use_frame_pt: + # output_carrying_abi._data_storage = FrameStorage(TealType.anytype, 0) abi_output_kwargs[output_kwarg_info.name] = output_carrying_abi # Arg usage "B" supplied to build an AST from the user-defined PyTEAL function: @@ -1026,15 +1028,15 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: # if subroutine do not have abi output, then only two cases happen: # - subroutine is a normal subroutine, then check subroutine body evaluates to something, rather than none # - subroutine is an ABIReturnSubroutine, the type is void, and its subroutine body type of is always none - stack_output_cnt = int(subroutine_body.type_of() != TealType.none) + stack_output_cnt = int(subroutine.return_type != TealType.none) else: stack_output_cnt = len(abi_output_kwargs) if self.use_frame_pt: body_ops = [Proto(subroutine.argument_count(), stack_output_cnt)] # reserve a spot for output variable on stack? - if stack_output_cnt > 0 and subroutine.has_abi_output: - body_ops.append(FrameBury(Int(0), 0)) + # if stack_output_cnt > 0 and subroutine.has_abi_output: + # body_ops += [Int(0), FrameBury(Int(0), 0)] body_ops += [var.slot.store() for var in arg_vars[::-1]] body_ops.append(subroutine_body) diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index 91d2a655e..36c5bbdf9 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -594,6 +594,27 @@ def square(x): args, "last_log() gave unexpected results from app" ) + # evaluate the programs in version 8 + app_result = PyTealDryRunExecutor(square, Mode.Application).dryrun( + args, compiler_version=8 + ) + lsig_result = PyTealDryRunExecutor(square, Mode.Signature).dryrun( + args, compiler_version=8 + ) + + # check to see that x^2 is at the top of the stack as expected + assert app_result.stack_top() == x**2, app_result.report( + args, "stack_top() gave unexpected results for app" + ) + assert lsig_result.stack_top() == x**2, lsig_result.report( + args, "stack_top() gave unexpected results for lsig" + ) + + # check to see that itob of x^2 has been logged (only for the app case) + assert app_result.last_log() == DryRunEncoder.hex(x**2), app_result.report( + args, "last_log() gave unexpected results from app" + ) + def blackbox_pyteal_example2(): # Example 2: Using blackbox_pyteal to make 400 assertions and generate a CSV report with 400 dryrun rows @@ -656,6 +677,22 @@ def euclid(x, y): with open(Path.cwd() / "euclid.csv", "w") as f: f.write(euclid_csv) + # assert that each result is that same as what Python's math.gcd() computes + # (over v8) + inspectors = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( + inputs, compiler_version=8 + ) + for i, result in enumerate(inspectors): + args = inputs[i] + assert result.stack_top() == math.gcd(*args), result.report( + args, f"failed for {args}" + ) + + # save the CSV to ...current working directory.../euclid_v8.csv + euclid_csv = DryRunInspector.csv_report(inputs, inspectors) + with open(Path.cwd() / "euclid_v8.csv", "w") as f: + f.write(euclid_csv) + def blackbox_pyteal_example3(): # Example 3: declarative Test Driven Development approach through Invariant's @@ -733,6 +770,15 @@ def euclid(x, y): for property, predicate in predicates.items(): Invariant(predicate).validates(property, inputs, inspectors) + # Execute on the input sequence to get a dry-run inspectors: + inspectors = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( + inputs, compiler_version=8 + ) + + # Assert that each invariant holds on the sequences of inputs and dry-runs: + for property, predicate in predicates.items(): + Invariant(predicate).validates(property, inputs, inspectors) + def blackbox_pyteal_example4(): # Example 4: Using PyTealDryRunExecutor to debug an ABIReturnSubroutine with an app, logic sig and csv report @@ -865,6 +911,24 @@ def cubed(n: abi.Uint64): args=inputs[index], msg="stack_top() gave unexpected results from app" ) + app_inspect = app_pytealer.dryrun_on_sequence(inputs, compiler_version=8) + lsig_inspect = lsig_pytealer.dryrun_on_sequence(inputs, compiler_version=8) + + for index, inspect in enumerate(app_inspect): + input_var = inputs[index][0] + assert inspect.stack_top() == input_var**3, inspect.report( + args=inputs[index], msg="stack_top() gave unexpected results from app" + ) + assert inspect.last_log() == DryRunEncoder.hex(input_var**3), inspect.report( + args=inputs[index], msg="last_log() gave unexpected results from app" + ) + + for index, inspect in enumerate(lsig_inspect): + input_var = inputs[index][0] + assert inspect.stack_top() == input_var**3, inspect.report( + args=inputs[index], msg="stack_top() gave unexpected results from app" + ) + def blackbox_pyteal_while_continue_test(): from tests.blackbox import Blackbox @@ -895,11 +959,21 @@ def while_continue_accumulation(n): Return(i.load()), ) + executor = PyTealDryRunExecutor(while_continue_accumulation, Mode.Signature) + for x in range(30): args = [x] - lsig_result = PyTealDryRunExecutor( - while_continue_accumulation, Mode.Signature - ).dryrun(args) + lsig_result = executor.dryrun(args) + if x == 0: + assert not lsig_result.passed() + else: + assert lsig_result.passed() + + assert lsig_result.stack_top() == x, lsig_result.report( + args, "stack_top() gave unexpected results for lsig" + ) + + lsig_result = executor.dryrun(args, compiler_version=8) if x == 0: assert not lsig_result.passed() else: @@ -969,6 +1043,10 @@ def named_tuple_field_access( assert inspector.stack_top() == 1 assert inspector.passed() + inspector = lsig_pytealer.dryrun(args, compiler_version=8) + assert inspector.passed() + assert inspector.stack_top() == 1 + @pytest.mark.parametrize( "example", From a70c125933898bbb69a82d2a7f95d6bf89641266 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Fri, 28 Oct 2022 14:27:51 -0400 Subject: [PATCH 030/157] 0xBAD hack, need to revisit for ugly pass by for type system --- pyteal/ast/subroutine.py | 49 +++++++++++++++++++++++------- tests/integration/graviton_test.py | 4 +-- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 3f1feb24d..7cdddc809 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -8,10 +8,8 @@ from pyteal.ast import abi from pyteal.ast.expr import Expr from pyteal.ast.seq import Seq - -# from pyteal.ast.int import Int from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar, ScratchSlot -from pyteal.ast.frame import FrameDig, Proto # FrameBury +from pyteal.ast.frame import FrameDig, Proto from pyteal.errors import TealInputError, TealInternalError, verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.types import TealType @@ -979,7 +977,10 @@ def __var_n_loaded_fp( return argument_var, loaded_var def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: - # from pyteal.ast.abi.type import FrameStorage + # TODO need to make it better for my temp hack, kinda ugly but it works + from pyteal.ast.abi.type import FrameStorage + from pyteal.compiler.compiler import TealSimpleBlock + from pyteal.ast.int import Int args = subroutine.arguments() arg_vars: list[ScratchVar] = [] @@ -996,9 +997,8 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: if output_kwarg_info: output_carrying_abi = output_kwarg_info.abi_type.new_instance() - # TODO seems to need a "prefix expr" to let output frame bury work - # if self.use_frame_pt: - # output_carrying_abi._data_storage = FrameStorage(TealType.anytype, 0) + if self.use_frame_pt: + output_carrying_abi._data_storage = FrameStorage(TealType.anytype, 0) abi_output_kwargs[output_kwarg_info.name] = output_carrying_abi # Arg usage "B" supplied to build an AST from the user-defined PyTEAL function: @@ -1033,10 +1033,37 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: stack_output_cnt = len(abi_output_kwargs) if self.use_frame_pt: - body_ops = [Proto(subroutine.argument_count(), stack_output_cnt)] - # reserve a spot for output variable on stack? - # if stack_output_cnt > 0 and subroutine.has_abi_output: - # body_ops += [Int(0), FrameBury(Int(0), 0)] + if not subroutine.has_abi_output: + body_ops = [Proto(subroutine.argument_count(), stack_output_cnt)] + else: + + class TempStuff(Expr): + def __init__(self, arg_cnt, stack_out_cnt): + super().__init__() + self.arg_cnt = arg_cnt + self.stack_cnt = stack_out_cnt + + def __teal__( + self, options: "CompileOptions" + ) -> tuple[TealBlock, TealSimpleBlock]: + proto_srt, proto_end = Proto( + self.arg_cnt, self.stack_cnt + ).__teal__(options) + int_srt, int_end = Int(0xB0BA7EA).__teal__(options) + srt, end = proto_srt, int_end + proto_end.setNextBlock(int_srt) + return srt, end + + def has_return(self) -> bool: + return False + + def type_of(self) -> TealType: + return TealType.none + + def __str__(self) -> str: + return "why_are_you_here" + + body_ops = [TempStuff(subroutine.argument_count(), stack_output_cnt)] body_ops += [var.slot.store() for var in arg_vars[::-1]] body_ops.append(subroutine_body) diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index 36c5bbdf9..2ce12d2a9 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -834,9 +834,9 @@ def abi_sum(toSum: abi.DynamicArray[abi.Uint64], *, output: abi.Uint64) -> Expr: for n in range(N): inputs.append(tuple([random.sample(choices, n)])) - app_inspectors = app_pytealer.dryrun_on_sequence(inputs) + app_inspectors = app_pytealer.dryrun_on_sequence(inputs, compiler_version=8) - lsig_inspectors = lsig_pytealer.dryrun_on_sequence(inputs) + lsig_inspectors = lsig_pytealer.dryrun_on_sequence(inputs, compiler_version=8) for i in range(N): args = inputs[i] From 1e12ca0e322b12e5d81cbab72405a0b614fd9886 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Fri, 28 Oct 2022 17:02:26 -0400 Subject: [PATCH 031/157] move spot reserving in proto --- pyteal/ast/frame.py | 22 +++++++++++++++++++--- pyteal/ast/subroutine.py | 40 +++++++--------------------------------- 2 files changed, 26 insertions(+), 36 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 8b1cb6080..d31e99138 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -1,6 +1,7 @@ from typing import TYPE_CHECKING from pyteal.ast.expr import Expr +from pyteal.ast.int import Int from pyteal.types import TealType, require_type from pyteal.errors import TealInputError, verifyProgramVersion from pyteal.ir import TealBlock, TealSimpleBlock, TealOp, Op @@ -10,14 +11,17 @@ class Proto(Expr): - def __init__(self, arg_num: int, ret_num: int): + def __init__(self, arg_num: int, ret_num: int, /, *, reserve_spot: int = 0): super().__init__() if arg_num < 0: raise TealInputError(f"subroutine arg number {arg_num} must be >= 0") if ret_num < 0: raise TealInputError(f"return value number {ret_num} must be >= 0") + if reserve_spot < 0: + raise TealInputError(f"reserve spot number {reserve_spot} must be >= 0") self.arg_num = arg_num self.ret_num = ret_num + self.reserve_spot = reserve_spot def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: verifyProgramVersion( @@ -26,10 +30,22 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc "Program version too low to use op proto", ) op = TealOp(self, Op.proto, self.arg_num, self.ret_num) - return TealBlock.FromOp(options, op) + proto_srt, proto_end = TealBlock.FromOp(options, op) + if self.reserve_spot == 0: + return proto_srt, proto_end + elif self.reserve_spot == 1: + int_srt, int_end = Int(0xD00D1E).__teal__(options) + proto_end.setNextBlock(int_srt) + return proto_srt, int_end + else: + dupn_srt, dupn_end = DupN(Int(0x5EA51DE), self.reserve_spot).__teal__( + options + ) + proto_end.setNextBlock(dupn_srt) + return proto_srt, dupn_end def __str__(self) -> str: - return f"(proto: arg_num = {self.arg_num}, ret_num = {self.ret_num})" + return f"(proto: arg_num = {self.arg_num}, ret_num = {self.ret_num}, reserve_spot = {self.reserve_spot})" def type_of(self) -> TealType: return TealType.none diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 7cdddc809..0280d0834 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -979,8 +979,6 @@ def __var_n_loaded_fp( def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: # TODO need to make it better for my temp hack, kinda ugly but it works from pyteal.ast.abi.type import FrameStorage - from pyteal.compiler.compiler import TealSimpleBlock - from pyteal.ast.int import Int args = subroutine.arguments() arg_vars: list[ScratchVar] = [] @@ -1033,37 +1031,13 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: stack_output_cnt = len(abi_output_kwargs) if self.use_frame_pt: - if not subroutine.has_abi_output: - body_ops = [Proto(subroutine.argument_count(), stack_output_cnt)] - else: - - class TempStuff(Expr): - def __init__(self, arg_cnt, stack_out_cnt): - super().__init__() - self.arg_cnt = arg_cnt - self.stack_cnt = stack_out_cnt - - def __teal__( - self, options: "CompileOptions" - ) -> tuple[TealBlock, TealSimpleBlock]: - proto_srt, proto_end = Proto( - self.arg_cnt, self.stack_cnt - ).__teal__(options) - int_srt, int_end = Int(0xB0BA7EA).__teal__(options) - srt, end = proto_srt, int_end - proto_end.setNextBlock(int_srt) - return srt, end - - def has_return(self) -> bool: - return False - - def type_of(self) -> TealType: - return TealType.none - - def __str__(self) -> str: - return "why_are_you_here" - - body_ops = [TempStuff(subroutine.argument_count(), stack_output_cnt)] + body_ops = [ + Proto( + subroutine.argument_count(), + stack_output_cnt, + reserve_spot=int(subroutine.has_abi_output), + ) + ] body_ops += [var.slot.store() for var in arg_vars[::-1]] body_ops.append(subroutine_body) From a5cd38aa87e11282f4d6baa114ef66008877a193 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Mon, 31 Oct 2022 10:43:16 -0400 Subject: [PATCH 032/157] reformat code a bit on black box example part --- tests/integration/graviton_test.py | 225 +++++++++++++---------------- 1 file changed, 98 insertions(+), 127 deletions(-) diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index 2ce12d2a9..77c1451f7 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -42,7 +42,7 @@ def wrap_compile_and_save( is_app = mode == pt.Mode.Application teal = PyTealDryRunExecutor(subr, mode).compile(version, assemble_constants) - tealfile = f'{"app" if is_app else "lsig"}_{case_name}.teal' + tealfile = f'{"app" if is_app else "lsig"}_{case_name}_v{version}.teal' tealdir = GENERATED / test_name tealdir.mkdir(parents=True, exist_ok=True) @@ -519,7 +519,7 @@ def blackbox_test_runner( inspectors = list(map(lambda a: execute(algod, teal, a, exec_mode), inputs)) # 4. Statistical report: - csvpath = GENERATED / "blackbox" / f"{tealfile}.csv" + csvpath = GENERATED / "blackbox" / f"{tealfile}_v{version}.csv" with open(csvpath, "w") as f: f.write(DryRunInspector.csv_report(inputs, inspectors)) @@ -577,43 +577,30 @@ def square(x): x = 9 args = [x] - # evaluate the programs - app_result = PyTealDryRunExecutor(square, Mode.Application).dryrun(args) - lsig_result = PyTealDryRunExecutor(square, Mode.Signature).dryrun(args) - - # check to see that x^2 is at the top of the stack as expected - assert app_result.stack_top() == x**2, app_result.report( - args, "stack_top() gave unexpected results for app" - ) - assert lsig_result.stack_top() == x**2, lsig_result.report( - args, "stack_top() gave unexpected results for lsig" - ) - - # check to see that itob of x^2 has been logged (only for the app case) - assert app_result.last_log() == DryRunEncoder.hex(x**2), app_result.report( - args, "last_log() gave unexpected results from app" - ) + def evaluate_and_check(_version: int): + # evaluate the programs + app_result = PyTealDryRunExecutor(square, Mode.Application).dryrun( + args, compiler_version=_version + ) + lsig_result = PyTealDryRunExecutor(square, Mode.Signature).dryrun( + args, compiler_version=_version + ) - # evaluate the programs in version 8 - app_result = PyTealDryRunExecutor(square, Mode.Application).dryrun( - args, compiler_version=8 - ) - lsig_result = PyTealDryRunExecutor(square, Mode.Signature).dryrun( - args, compiler_version=8 - ) + # check to see that x^2 is at the top of the stack as expected + assert app_result.stack_top() == x**2, app_result.report( + args, "stack_top() gave unexpected results for app" + ) + assert lsig_result.stack_top() == x**2, lsig_result.report( + args, "stack_top() gave unexpected results for lsig" + ) - # check to see that x^2 is at the top of the stack as expected - assert app_result.stack_top() == x**2, app_result.report( - args, "stack_top() gave unexpected results for app" - ) - assert lsig_result.stack_top() == x**2, lsig_result.report( - args, "stack_top() gave unexpected results for lsig" - ) + # check to see that itob of x^2 has been logged (only for the app case) + assert app_result.last_log() == DryRunEncoder.hex(x**2), app_result.report( + args, "last_log() gave unexpected results from app" + ) - # check to see that itob of x^2 has been logged (only for the app case) - assert app_result.last_log() == DryRunEncoder.hex(x**2), app_result.report( - args, "last_log() gave unexpected results from app" - ) + evaluate_and_check(6) + evaluate_and_check(8) def blackbox_pyteal_example2(): @@ -662,36 +649,24 @@ def euclid(x, y): ) ) - # assert that each result is that same as what Python's math.gcd() computes - inspectors = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( - inputs - ) - for i, result in enumerate(inspectors): - args = inputs[i] - assert result.stack_top() == math.gcd(*args), result.report( - args, f"failed for {args}" + def test_and_report(_verison: int): + # assert that each result is that same as what Python's math.gcd() computes + inspectors = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( + inputs, compiler_version=_verison ) + for i, result in enumerate(inspectors): + args = inputs[i] + assert result.stack_top() == math.gcd(*args), result.report( + args, f"failed for {args}" + ) - # save the CSV to ...current working directory.../euclid.csv - euclid_csv = DryRunInspector.csv_report(inputs, inspectors) - with open(Path.cwd() / "euclid.csv", "w") as f: - f.write(euclid_csv) - - # assert that each result is that same as what Python's math.gcd() computes - # (over v8) - inspectors = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( - inputs, compiler_version=8 - ) - for i, result in enumerate(inspectors): - args = inputs[i] - assert result.stack_top() == math.gcd(*args), result.report( - args, f"failed for {args}" - ) + # save the CSV to ...current working directory.../euclid_v{version}.csv + euclid_csv = DryRunInspector.csv_report(inputs, inspectors) + with open(Path.cwd() / f"euclid_v{_verison}.csv", "w") as f: + f.write(euclid_csv) - # save the CSV to ...current working directory.../euclid_v8.csv - euclid_csv = DryRunInspector.csv_report(inputs, inspectors) - with open(Path.cwd() / "euclid_v8.csv", "w") as f: - f.write(euclid_csv) + test_and_report(6) + test_and_report(8) def blackbox_pyteal_example3(): @@ -834,47 +809,53 @@ def abi_sum(toSum: abi.DynamicArray[abi.Uint64], *, output: abi.Uint64) -> Expr: for n in range(N): inputs.append(tuple([random.sample(choices, n)])) - app_inspectors = app_pytealer.dryrun_on_sequence(inputs, compiler_version=8) + def test_and_report_for_app_and_lsig(_version: int): + app_inspectors = app_pytealer.dryrun_on_sequence( + inputs, compiler_version=_version + ) + lsig_inspectors = lsig_pytealer.dryrun_on_sequence( + inputs, compiler_version=_version + ) + for i in range(N): + args = inputs[i] - lsig_inspectors = lsig_pytealer.dryrun_on_sequence(inputs, compiler_version=8) + app_inspector = app_inspectors[i] + lsig_inspector = lsig_inspectors[i] - for i in range(N): - args = inputs[i] + def message(insp): + return insp.report(args, f"failed for {args}", row=i) - app_inspector = app_inspectors[i] - lsig_inspector = lsig_inspectors[i] + # the app should pass exactly when it's cost was within the 700 budget: + assert app_inspector.passed() == (app_inspector.cost() <= 700), message( + app_inspector + ) + # the lsig always passes (never goes over budget): + assert lsig_inspector.passed(), message(lsig_inspector) - def message(insp): - return insp.report(args, f"failed for {args}", row=i) + expected = sum(args[0]) + actual4app = app_inspector.last_log() + assert expected == actual4app, message(app_inspector) - # the app should pass exactly when it's cost was within the 700 budget: - assert app_inspector.passed() == (app_inspector.cost() <= 700), message( - app_inspector - ) - # the lsig always passes (never goes over budget): - assert lsig_inspector.passed(), message(lsig_inspector) + if i > 0: + assert expected in app_inspector.final_scratch().values(), message( + app_inspector + ) + assert expected in lsig_inspector.final_scratch().values(), message( + lsig_inspector + ) - expected = sum(args[0]) - actual4app = app_inspector.last_log() - assert expected == actual4app, message(app_inspector) + def report(kind): + assert kind in ("app", "lsig") + insps = app_inspectors if kind == "app" else lsig_inspectors + csv_report = DryRunInspector.csv_report(inputs, insps) + with open(Path.cwd() / f"abi_sum_{kind}_v{_version}.csv", "w") as f: + f.write(csv_report) - if i > 0: - assert expected in app_inspector.final_scratch().values(), message( - app_inspector - ) - assert expected in lsig_inspector.final_scratch().values(), message( - lsig_inspector - ) + report("app") + report("lsig") - def report(kind): - assert kind in ("app", "lsig") - insps = app_inspectors if kind == "app" else lsig_inspectors - csv_report = DryRunInspector.csv_report(inputs, insps) - with open(Path.cwd() / f"abi_sum_{kind}.csv", "w") as f: - f.write(csv_report) - - report("app") - report("lsig") + test_and_report_for_app_and_lsig(6) + test_and_report_for_app_and_lsig(8) def blackbox_pyteal_example5(): @@ -893,41 +874,31 @@ def cubed(n: abi.Uint64): inputs = [[i] for i in range(1, 11)] - app_inspect = app_pytealer.dryrun_on_sequence(inputs) - lsig_inspect = lsig_pytealer.dryrun_on_sequence(inputs) - - for index, inspect in enumerate(app_inspect): - input_var = inputs[index][0] - assert inspect.stack_top() == input_var**3, inspect.report( - args=inputs[index], msg="stack_top() gave unexpected results from app" - ) - assert inspect.last_log() == DryRunEncoder.hex(input_var**3), inspect.report( - args=inputs[index], msg="last_log() gave unexpected results from app" - ) - - for index, inspect in enumerate(lsig_inspect): - input_var = inputs[index][0] - assert inspect.stack_top() == input_var**3, inspect.report( - args=inputs[index], msg="stack_top() gave unexpected results from app" + def test_app_and_lsig(_version: int): + app_inspect = app_pytealer.dryrun_on_sequence(inputs, compiler_version=_version) + lsig_inspect = lsig_pytealer.dryrun_on_sequence( + inputs, compiler_version=_version ) - app_inspect = app_pytealer.dryrun_on_sequence(inputs, compiler_version=8) - lsig_inspect = lsig_pytealer.dryrun_on_sequence(inputs, compiler_version=8) + for index, inspect in enumerate(app_inspect): + input_var = inputs[index][0] + assert inspect.stack_top() == input_var**3, inspect.report( + args=inputs[index], msg="stack_top() gave unexpected results from app" + ) + assert inspect.last_log() == DryRunEncoder.hex( + input_var**3 + ), inspect.report( + args=inputs[index], msg="last_log() gave unexpected results from app" + ) - for index, inspect in enumerate(app_inspect): - input_var = inputs[index][0] - assert inspect.stack_top() == input_var**3, inspect.report( - args=inputs[index], msg="stack_top() gave unexpected results from app" - ) - assert inspect.last_log() == DryRunEncoder.hex(input_var**3), inspect.report( - args=inputs[index], msg="last_log() gave unexpected results from app" - ) + for index, inspect in enumerate(lsig_inspect): + input_var = inputs[index][0] + assert inspect.stack_top() == input_var**3, inspect.report( + args=inputs[index], msg="stack_top() gave unexpected results from app" + ) - for index, inspect in enumerate(lsig_inspect): - input_var = inputs[index][0] - assert inspect.stack_top() == input_var**3, inspect.report( - args=inputs[index], msg="stack_top() gave unexpected results from app" - ) + test_app_and_lsig(6) + test_app_and_lsig(8) def blackbox_pyteal_while_continue_test(): From 7db5dfae8412128cfbd20a0d36ef98a8c00a1252 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Mon, 31 Oct 2022 11:26:24 -0400 Subject: [PATCH 033/157] start changing abi roundtrip tesal file name --- tests/integration/abi_roundtrip_test.py | 6 +- tests/integration/graviton_abi_test.py | 20 ++-- tests/integration/graviton_test.py | 2 + ...dtrip_().teal => app_roundtrip_()_v6.teal} | 0 ....teal => app_roundtrip_(bool)[10]_v6.teal} | 0 ...ool).teal => app_roundtrip_(bool)_v6.teal} | 0 ...64,bool),byte[10],bool[4],uint64)_v6.teal} | 0 ...teal => app_roundtrip_(bool,byte)_v6.teal} | 0 ...ndtrip_(bool,byte,address,string)_v6.teal} | 0 ...te),uint8)[2],string,bool[]))[]_2_v6.teal} | 0 ...(bool,byte,address,string,uint64)_v6.teal} | 0 ...pp_roundtrip_(bool,uint64,uint32)_v6.teal} | 0 ...yte).teal => app_roundtrip_(byte)_v6.teal} | 0 ... app_roundtrip_(byte,bool,uint64)_v6.teal} | 0 ...],(bool,bool),uint64,address)[]_7_v6.teal} | 0 ...6).teal => app_roundtrip_(uint16)_v6.teal} | 0 ...app_roundtrip_(uint16,uint8,byte)_v6.teal} | 0 ...2).teal => app_roundtrip_(uint32)_v6.teal} | 0 ...p_roundtrip_(uint32,uint16,uint8)_v6.teal} | 0 ...4).teal => app_roundtrip_(uint64)_v6.teal} | 0 ..._roundtrip_(uint64,uint32,uint16)_v6.teal} | 0 ...t8).teal => app_roundtrip_(uint8)_v6.teal} | 0 .../app_roundtrip_(uint8,byte,bool).teal | 111 ------------------ .../app_roundtrip_(uint8,byte,bool)_v6.teal | 111 ++++++++++++++++++ ...eal => app_roundtrip_address[]_10_v6.teal} | 0 ...ess.teal => app_roundtrip_address_v6.teal} | 0 ...[1].teal => app_roundtrip_bool[1]_v6.teal} | 0 ...eal => app_roundtrip_bool[3][]_11_v6.teal} | 0 ...2].teal => app_roundtrip_bool[42]_v6.teal} | 0 ..._0.teal => app_roundtrip_bool[]_0_v6.teal} | 0 ..._1.teal => app_roundtrip_bool[]_1_v6.teal} | 0 ...2.teal => app_roundtrip_bool[]_42_v6.teal} | 0 ...p_bool.teal => app_roundtrip_bool_v6.teal} | 0 ...6].teal => app_roundtrip_byte[16]_v6.teal} | 0 ...6.teal => app_roundtrip_byte[]_36_v6.teal} | 0 ...p_byte.teal => app_roundtrip_byte_v6.teal} | 0 ..._0.teal => app_roundtrip_string_0_v6.teal} | 0 ...3.teal => app_roundtrip_string_13_v6.teal} | 0 ..._1.teal => app_roundtrip_string_1_v6.teal} | 0 ...nt16.teal => app_roundtrip_uint16_v6.teal} | 0 ...nt32.teal => app_roundtrip_uint32_v6.teal} | 0 ...].teal => app_roundtrip_uint64[1]_v6.teal} | 0 ....teal => app_roundtrip_uint64[42]_v6.teal} | 0 ....teal => app_roundtrip_uint64[]_0_v6.teal} | 0 ....teal => app_roundtrip_uint64[]_1_v6.teal} | 0 ...teal => app_roundtrip_uint64[]_42_v6.teal} | 0 ...nt64.teal => app_roundtrip_uint64_v6.teal} | 0 ...uint8.teal => app_roundtrip_uint8_v6.teal} | 0 48 files changed, 130 insertions(+), 120 deletions(-) rename tests/integration/teal/roundtrip/{app_roundtrip_().teal => app_roundtrip_()_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(bool)[10].teal => app_roundtrip_(bool)[10]_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(bool).teal => app_roundtrip_(bool)_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64).teal => app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(bool,byte).teal => app_roundtrip_(bool,byte)_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(bool,byte,address,string).teal => app_roundtrip_(bool,byte,address,string)_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2.teal => app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(bool,byte,address,string,uint64).teal => app_roundtrip_(bool,byte,address,string,uint64)_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(bool,uint64,uint32).teal => app_roundtrip_(bool,uint64,uint32)_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(byte).teal => app_roundtrip_(byte)_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(byte,bool,uint64).teal => app_roundtrip_(byte,bool,uint64)_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7.teal => app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(uint16).teal => app_roundtrip_(uint16)_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(uint16,uint8,byte).teal => app_roundtrip_(uint16,uint8,byte)_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(uint32).teal => app_roundtrip_(uint32)_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(uint32,uint16,uint8).teal => app_roundtrip_(uint32,uint16,uint8)_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(uint64).teal => app_roundtrip_(uint64)_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(uint64,uint32,uint16).teal => app_roundtrip_(uint64,uint32,uint16)_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_(uint8).teal => app_roundtrip_(uint8)_v6.teal} (100%) delete mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool).teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v6.teal rename tests/integration/teal/roundtrip/{app_roundtrip_address[]_10.teal => app_roundtrip_address[]_10_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_address.teal => app_roundtrip_address_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_bool[1].teal => app_roundtrip_bool[1]_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_bool[3][]_11.teal => app_roundtrip_bool[3][]_11_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_bool[42].teal => app_roundtrip_bool[42]_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_bool[]_0.teal => app_roundtrip_bool[]_0_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_bool[]_1.teal => app_roundtrip_bool[]_1_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_bool[]_42.teal => app_roundtrip_bool[]_42_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_bool.teal => app_roundtrip_bool_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_byte[16].teal => app_roundtrip_byte[16]_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_byte[]_36.teal => app_roundtrip_byte[]_36_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_byte.teal => app_roundtrip_byte_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_string_0.teal => app_roundtrip_string_0_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_string_13.teal => app_roundtrip_string_13_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_string_1.teal => app_roundtrip_string_1_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_uint16.teal => app_roundtrip_uint16_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_uint32.teal => app_roundtrip_uint32_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_uint64[1].teal => app_roundtrip_uint64[1]_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_uint64[42].teal => app_roundtrip_uint64[42]_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_uint64[]_0.teal => app_roundtrip_uint64[]_0_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_uint64[]_1.teal => app_roundtrip_uint64[]_1_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_uint64[]_42.teal => app_roundtrip_uint64[]_42_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_uint64.teal => app_roundtrip_uint64_v6.teal} (100%) rename tests/integration/teal/roundtrip/{app_roundtrip_uint8.teal => app_roundtrip_uint8_v6.teal} (100%) diff --git a/tests/integration/abi_roundtrip_test.py b/tests/integration/abi_roundtrip_test.py index e0ca05484..debded3aa 100644 --- a/tests/integration/abi_roundtrip_test.py +++ b/tests/integration/abi_roundtrip_test.py @@ -196,6 +196,10 @@ def test_pure_compilation(abi_type): print(f"Pure Compilation Test for {abi_type=}") abi_type, type_str, dynamic_length, roundtripper = roundtrip_setup(abi_type) + # TODO neeed to make this version flexible + + _version = 6 + if type_str in BAD_TYPES: print( f"Skipping encoding roundtrip test of '{abi_type}' because of {BAD_TYPES[type_str]}" @@ -214,7 +218,7 @@ def test_pure_compilation(abi_type): filename = ( f"app_roundtrip_{sdk_abi_type}" + ("" if dynamic_length is None else f"_{dynamic_length}") - + ".teal" + + f"_v{_version}.teal" ) tealdir = GENERATED / "roundtrip" tealdir.mkdir(parents=True, exist_ok=True) diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index 229b7a671..0b571824c 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -15,8 +15,8 @@ """ -WARNING: The following ABI types Int65 and Complex130 are ONLY for the purpose of testing/demo'ing -ABISubroutine and graviton ABI capabilities and are NOT the recommended approach for +WARNING: The following ABI types Int65 and Complex130 are ONLY for the purpose of testing/demo'ing +ABISubroutine and graviton ABI capabilities and are NOT the recommended approach for implementing integers and complex integers. A better approach would likely leverage `Uint64` (if any ABI type at all) and make use of 2's complement arithmetic. @@ -438,17 +438,21 @@ def pytuple_to_complex(tt): ] # Binary: - def binary_dryrun(p: PyTealDryRunExecutor) -> list[DryRunInspector]: - return p.dryrun_on_sequence(binary_inputs) + def binary_dryrun( + p: PyTealDryRunExecutor, _version: int = 6 + ) -> list[DryRunInspector]: + return p.dryrun_on_sequence(binary_inputs, compiler_version=_version) + + # Unary: + def unary_dryrun( + p: PyTealDryRunExecutor, _version: int = 6 + ) -> list[DryRunInspector]: + return p.dryrun_on_sequence(unary_inputs, compiler_version=_version) inspectors_cplx_add = binary_dryrun(bbpt_cplx_add) inspectors_cplx_mult = binary_dryrun(bbpt_cplx_mult) - # Unary: - def unary_dryrun(p: PyTealDryRunExecutor) -> list[DryRunInspector]: - return p.dryrun_on_sequence(unary_inputs) - inspectors_cplx_real = unary_dryrun(bbpt_complex_real) inspectors_cplx_imag = unary_dryrun(bbpt_complex_imag) diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index 77c1451f7..8dd141180 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -163,6 +163,8 @@ def test_stable_teal_generation(subr, mode): case_name = subr.name() print(f"stable TEAL generation test for {case_name} in mode {mode}") + # HANG NOTE: I prefer not to modify this test, for it is skipped now on thread-unsafe behavior, + # and I would suggest revisiting later after we have satisfied solution for #199. _, _, tealfile = wrap_compile_and_save(subr, mode, 6, True, "stability", case_name) path2actual = GENERATED / "stability" / tealfile path2expected = FIXTURES / "stability" / tealfile diff --git a/tests/integration/teal/roundtrip/app_roundtrip_().teal b/tests/integration/teal/roundtrip/app_roundtrip_()_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_().teal rename to tests/integration/teal/roundtrip/app_roundtrip_()_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool)[10].teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(bool)[10].teal rename to tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool).teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool)_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(bool).teal rename to tests/integration/teal/roundtrip/app_roundtrip_(bool)_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64).teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64).teal rename to tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte).teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(bool,byte).teal rename to tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string).teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string).teal rename to tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2.teal rename to tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64).teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64).teal rename to tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32).teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32).teal rename to tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(byte).teal b/tests/integration/teal/roundtrip/app_roundtrip_(byte)_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(byte).teal rename to tests/integration/teal/roundtrip/app_roundtrip_(byte)_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64).teal b/tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64).teal rename to tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7.teal b/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7.teal rename to tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint16).teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(uint16).teal rename to tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte).teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte).teal rename to tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint32).teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(uint32).teal rename to tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8).teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8).teal rename to tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint64).teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(uint64).teal rename to tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16).teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16).teal rename to tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint8).teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_(uint8).teal rename to tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool).teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool).teal deleted file mode 100644 index 251e70b5e..000000000 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool).teal +++ /dev/null @@ -1,111 +0,0 @@ -#pragma version 6 -txna ApplicationArgs 0 // [uint8|byte|bool] -store 4 // 4 -> uint8|byte|bool -load 4 // [uint8|byte|bool] -callsub roundtripper_1 // [uint8|byte|bool | 255 - uint8 | 255 - byte | !bool | uint8|byte|bool] -store 3 // 3 -> uint8|byte|bool | 255 - uint8 | 255 - byte | !bool | uint8|byte|bool -byte 0x151f7c75 // [0x151f7c75] -load 3 // [0x151f7c75, uint8|byte|bool | 255 - uint8 | 255 - byte | !bool | uint8|byte|bool] -concat // [0x151f7c75 | uint8|byte|bool | 255 - uint8 | 255 - byte | !bool | uint8|byte|bool] -log // log(0x151f7c75 | uint8|byte|bool | 255 - uint8 | 255 - byte | !bool | uint8|byte|bool) -int 1 // [1] -return // PASSED - -// tuple_complement -tuplecomplement_0: // [uint8|byte|bool] -store 9 // 9 -> uint8|byte|bool -load 9 // [uint8|byte|bool] -int 0 // [uint8|byte|bool, 0] -getbyte // [uint8] -store 0 // 0 -> uint8 -load 9 // [uint8|byte|bool] -int 1 // [uint8|byte|bool, 1] -getbyte // [byte] -store 1 // 1 -> byte -load 9 // [uint8|byte|bool] -int 16 // [uint8|byte|bool, 16] -getbit // bool -store 2 // 2 -> bool -load 0 // [uint8] -callsub numericalcomp_2 // [255 - uint8] -store 0 // 0 -> 255 - uint8 -load 1 // [byte] -callsub numericalcomp_3 // [255 - byte] -store 1 // 1 -> 255 - byte -load 2 // [bool] -callsub boolcomp_4 // [!bool] -store 2 // 2 -> !bool -byte 0x00 // [0x00] -int 0 // [0x00, 0] -load 0 // [0x00, 0, 255 - uint8] -setbyte // [255 - uint8] -byte 0x00 // [255 - uint8, 0x00] -int 0 // [255 - uint8, 0x00, 0] -load 1 // [255 - uint8, 0x00, 0, 255 - byte] -setbyte // [255 - uint8, 255 - byte] -concat // [255 - uint8 | 255 - byte] -byte 0x00 // [255 - uint8 | 255 - byte, 0x00] -int 0 // [255 - uint8 | 255 - byte, 0x00, 0] -load 2 // [255 - uint8 | 255 - byte, 0x00, 0, !bool] -setbit // [255 - uint8 | 255 - byte, !bool] -concat // [255 - uint8 | 255 - byte | !bool] -store 10 // 10 -> 255 - uint8 | 255 - byte | !bool -load 10 // [255 - uint8 | 255 - byte | !bool] -retsub - -// round_tripper -roundtripper_1: // [uint8|byte|bool] -store 5 // 5 -> uint8|byte|bool -load 5 // [uint8|byte|bool] -callsub tuplecomplement_0 // [255 - uint8 | 255 - byte | !bool] -store 7 // 7 -> 255 - uint8 | 255 - byte | !bool -load 7 // [255 - uint8 | 255 - byte | !bool] -callsub tuplecomplement_0 // [255 - (255 - uint8) | 255 - (255 - byte) | !!bool] -store 8 // 8 -> uint8|byte|bool -load 5 // [uint8|byte|bool] -load 7 // [uint8|byte|bool, 255 - uint8 | 255 - byte | !bool] -concat // [uint8|byte|bool | 255 - uint8 | 255 - byte | !bool] -load 8 // [uint8|byte|bool | 255 - uint8 | 255 - byte | !bool, uint8|byte|bool] -concat // [uint8|byte|bool | 255 - uint8 | 255 - byte | !bool | uint8|byte|bool] -store 6 // 6 -> uint8|byte|bool | 255 - uint8 | 255 - byte | !bool | uint8|byte|bool -load 6 // [uint8|byte|bool | 255 - uint8 | 255 - byte | !bool | uint8|byte|bool] -retsub - -// numerical_comp -numericalcomp_2: // [uint8] -store 11 // 11 -> uint8 -int 255 // [255] -load 11 // [255, uint8] -- // [255 - uint8] -store 12 // 12 -> 255 - uint8 -load 12 // [255 - uint8] -int 256 // [255 - uint8, 256] -< // [1] -assert // [] -load 12 // [255 - uint8] -retsub - -// numerical_comp -numericalcomp_3: // [byte] -store 13 // 13 -> byte -int 255 // [255] -load 13 // [255, byte] -- // [255 - byte] -store 14 // 14 -> 255 - byte -load 14 // [255 - byte] -int 256 // [255 - byte, 256] -< // [1] -assert // [] -load 14 // [255 - byte] -retsub - -// bool_comp -boolcomp_4: // [bool] -store 15 // 15 -> bool -load 15 // [bool] -! // [!bool] -! -! -store 16 // 16 -> !bool -load 16 // [!bool] -retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v6.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v6.teal new file mode 100644 index 000000000..d2f050703 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v6.teal @@ -0,0 +1,111 @@ +#pragma version 6 +txna ApplicationArgs 0 +store 4 +load 4 +callsub roundtripper_1 +store 3 +byte 0x151f7c75 +load 3 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +store 9 +load 9 +int 0 +getbyte +store 0 +load 9 +int 1 +getbyte +store 1 +load 9 +int 16 +getbit +store 2 +load 0 +callsub numericalcomp_2 +store 0 +load 1 +callsub numericalcomp_3 +store 1 +load 2 +callsub boolcomp_4 +store 2 +byte 0x00 +int 0 +load 0 +setbyte +byte 0x00 +int 0 +load 1 +setbyte +concat +byte 0x00 +int 0 +load 2 +setbit +concat +store 10 +load 10 +retsub + +// round_tripper +roundtripper_1: +store 5 +load 5 +callsub tuplecomplement_0 +store 7 +load 7 +callsub tuplecomplement_0 +store 8 +load 5 +load 7 +concat +load 8 +concat +store 6 +load 6 +retsub + +// numerical_comp +numericalcomp_2: +store 11 +int 255 +load 11 +- +store 12 +load 12 +int 256 +< +assert +load 12 +retsub + +// numerical_comp +numericalcomp_3: +store 13 +int 255 +load 13 +- +store 14 +load 14 +int 256 +< +assert +load 14 +retsub + +// bool_comp +boolcomp_4: +store 15 +load 15 +! +! +! +store 16 +load 16 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_address[]_10.teal b/tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_address[]_10.teal rename to tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_address.teal b/tests/integration/teal/roundtrip/app_roundtrip_address_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_address.teal rename to tests/integration/teal/roundtrip/app_roundtrip_address_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[1].teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_bool[1].teal rename to tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11.teal rename to tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[42].teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_bool[42].teal rename to tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_bool[]_0.teal rename to tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_bool[]_1.teal rename to tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_bool[]_42.teal rename to tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_bool.teal rename to tests/integration/teal/roundtrip/app_roundtrip_bool_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_byte[16].teal b/tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_byte[16].teal rename to tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_byte[]_36.teal b/tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_byte[]_36.teal rename to tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_byte.teal b/tests/integration/teal/roundtrip/app_roundtrip_byte_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_byte.teal rename to tests/integration/teal/roundtrip/app_roundtrip_byte_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_0.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_0_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_string_0.teal rename to tests/integration/teal/roundtrip/app_roundtrip_string_0_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_13.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_13_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_string_13.teal rename to tests/integration/teal/roundtrip/app_roundtrip_string_13_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_1.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_1_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_string_1.teal rename to tests/integration/teal/roundtrip/app_roundtrip_string_1_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint16.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint16_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_uint16.teal rename to tests/integration/teal/roundtrip/app_roundtrip_uint16_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint32.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint32_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_uint32.teal rename to tests/integration/teal/roundtrip/app_roundtrip_uint32_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[1].teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_uint64[1].teal rename to tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[42].teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_uint64[42].teal rename to tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0.teal rename to tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1.teal rename to tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42.teal rename to tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_uint64.teal rename to tests/integration/teal/roundtrip/app_roundtrip_uint64_v6.teal diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint8_v6.teal similarity index 100% rename from tests/integration/teal/roundtrip/app_roundtrip_uint8.teal rename to tests/integration/teal/roundtrip/app_roundtrip_uint8_v6.teal From e1dbcd77e637c6b9acb6eb04aa858bb43b32f433 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Mon, 31 Oct 2022 12:37:20 -0400 Subject: [PATCH 034/157] roundtrip test --- pyteal/ast/abi/tuple.py | 4 + pyteal/ast/subroutine.py | 2 +- tests/integration/abi_roundtrip_test.py | 6 +- .../teal/roundtrip/app_roundtrip_()_v8.teal | 40 + .../app_roundtrip_(bool)[10]_v8.teal | 189 ++ .../roundtrip/app_roundtrip_(bool)_v8.teal | 62 + ...t64,bool),byte[10],bool[4],uint64)_v8.teal | 860 +++++++ .../app_roundtrip_(bool,byte)_v8.teal | 89 + ...undtrip_(bool,byte,address,string)_v8.teal | 690 ++++++ ...yte),uint8)[2],string,bool[]))[]_2_v8.teal | 2057 +++++++++++++++++ ..._(bool,byte,address,string,uint64)_v8.teal | 711 ++++++ ...app_roundtrip_(bool,uint64,uint32)_v8.teal | 109 + .../roundtrip/app_roundtrip_(byte)_v8.teal | 65 + .../app_roundtrip_(byte,bool,uint64)_v8.teal | 110 + ...4],(bool,bool),uint64,address)[]_7_v8.teal | 843 +++++++ .../roundtrip/app_roundtrip_(uint16)_v8.teal | 64 + .../app_roundtrip_(uint16,uint8,byte)_v8.teal | 118 + .../roundtrip/app_roundtrip_(uint32)_v8.teal | 64 + ...pp_roundtrip_(uint32,uint16,uint8)_v8.teal | 117 + .../roundtrip/app_roundtrip_(uint64)_v8.teal | 58 + ...p_roundtrip_(uint64,uint32,uint16)_v8.teal | 111 + .../roundtrip/app_roundtrip_(uint8)_v8.teal | 65 + .../app_roundtrip_(uint8,byte,bool)_v8.teal | 116 + .../app_roundtrip_address[]_10_v8.teal | 702 ++++++ .../roundtrip/app_roundtrip_address_v8.teal | 501 ++++ .../roundtrip/app_roundtrip_bool[1]_v8.teal | 62 + .../app_roundtrip_bool[3][]_11_v8.teal | 297 +++ .../roundtrip/app_roundtrip_bool[42]_v8.teal | 472 ++++ .../roundtrip/app_roundtrip_bool[]_0_v8.teal | 94 + .../roundtrip/app_roundtrip_bool[]_1_v8.teal | 118 + .../roundtrip/app_roundtrip_bool[]_42_v8.teal | 610 +++++ .../teal/roundtrip/app_roundtrip_bool_v8.teal | 52 + .../roundtrip/app_roundtrip_byte[16]_v8.teal | 277 +++ .../roundtrip/app_roundtrip_byte[]_36_v8.teal | 683 ++++++ .../teal/roundtrip/app_roundtrip_byte_v8.teal | 57 + .../roundtrip/app_roundtrip_string_0_v8.teal | 94 + .../roundtrip/app_roundtrip_string_13_v8.teal | 261 +++ .../roundtrip/app_roundtrip_string_1_v8.teal | 105 + .../roundtrip/app_roundtrip_uint16_v8.teal | 54 + .../roundtrip/app_roundtrip_uint32_v8.teal | 54 + .../roundtrip/app_roundtrip_uint64[1]_v8.teal | 61 + .../app_roundtrip_uint64[42]_v8.teal | 553 +++++ .../app_roundtrip_uint64[]_0_v8.teal | 94 + .../app_roundtrip_uint64[]_1_v8.teal | 117 + .../app_roundtrip_uint64[]_42_v8.teal | 691 ++++++ .../roundtrip/app_roundtrip_uint64_v8.teal | 46 + .../roundtrip/app_roundtrip_uint8_v8.teal | 57 + 47 files changed, 12658 insertions(+), 4 deletions(-) create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_()_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(bool)_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(byte)_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_address_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_bool_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_byte_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_string_0_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_string_13_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_string_1_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_uint16_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_uint32_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_uint64_v8.teal create mode 100644 tests/integration/teal/roundtrip/app_roundtrip_uint8_v8.teal diff --git a/pyteal/ast/abi/tuple.py b/pyteal/ast/abi/tuple.py index 2f2dceeab..cabe52f7c 100644 --- a/pyteal/ast/abi/tuple.py +++ b/pyteal/ast/abi/tuple.py @@ -679,6 +679,10 @@ def __setattr__(self, name: str, field: Any) -> None: if name == "_NamedTuple__ready" or not self.__ready: super().__setattr__(name, field) return + # TODO need to relax this part lol + if name.startswith("_") and name != "_NamedTuple__ready" and self.__ready: + super().__setattr__(name, field) + return raise TealInputError("cannot assign to NamedTuple attributes.") diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 0280d0834..739bc498a 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -996,7 +996,7 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: if output_kwarg_info: output_carrying_abi = output_kwarg_info.abi_type.new_instance() if self.use_frame_pt: - output_carrying_abi._data_storage = FrameStorage(TealType.anytype, 0) + output_carrying_abi._set_data_source(FrameStorage(TealType.anytype, 0)) abi_output_kwargs[output_kwarg_info.name] = output_carrying_abi # Arg usage "B" supplied to build an AST from the user-defined PyTEAL function: diff --git a/tests/integration/abi_roundtrip_test.py b/tests/integration/abi_roundtrip_test.py index debded3aa..52b226471 100644 --- a/tests/integration/abi_roundtrip_test.py +++ b/tests/integration/abi_roundtrip_test.py @@ -198,7 +198,7 @@ def test_pure_compilation(abi_type): # TODO neeed to make this version flexible - _version = 6 + _version = 8 if type_str in BAD_TYPES: print( @@ -213,7 +213,7 @@ def test_pure_compilation(abi_type): assert [sdk_abi_type] == abi_arg_types assert algosdk.abi.TupleType([sdk_abi_type] * 3) == abi_ret_type - teal = roundtripper.compile(version=6) + teal = roundtripper.compile(version=_version) filename = ( f"app_roundtrip_{sdk_abi_type}" @@ -255,7 +255,7 @@ def test_roundtrip(abi_type): abi_strat = ABIStrategy(sdk_abi_types[0], dynamic_length=dynamic_length) rand_abi_instance = abi_strat.get_random() args = (rand_abi_instance,) - inspector = roundtripper.dryrun(args) + inspector = roundtripper.dryrun(args, compiler_version=8) cost = inspector.cost() passed = inspector.passed() diff --git a/tests/integration/teal/roundtrip/app_roundtrip_()_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_()_v8.teal new file mode 100644 index 000000000..7f74c2e54 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_()_v8.teal @@ -0,0 +1,40 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_1 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +byte "" +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub tuplecomplement_0 +store 2 +load 2 +callsub tuplecomplement_0 +store 3 +frame_dig -1 +load 2 +concat +load 3 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v8.teal new file mode 100644 index 000000000..f2c4408b5 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v8.teal @@ -0,0 +1,189 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 2 +load 2 +callsub roundtripper_2 +store 1 +byte 0x151f7c75 +load 1 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbit +store 0 +load 0 +callsub boolcomp_3 +store 0 +byte 0x00 +int 0 +load 0 +setbit +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_1: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +int 1 +extract3 +store 5 +frame_dig -1 +int 1 +int 1 +* +int 1 +extract3 +store 6 +frame_dig -1 +int 1 +int 2 +* +int 1 +extract3 +store 7 +frame_dig -1 +int 1 +int 3 +* +int 1 +extract3 +store 8 +frame_dig -1 +int 1 +int 4 +* +int 1 +extract3 +store 9 +frame_dig -1 +int 1 +int 5 +* +int 1 +extract3 +store 10 +frame_dig -1 +int 1 +int 6 +* +int 1 +extract3 +store 11 +frame_dig -1 +int 1 +int 7 +* +int 1 +extract3 +store 12 +frame_dig -1 +int 1 +int 8 +* +int 1 +extract3 +store 13 +frame_dig -1 +int 1 +int 9 +* +int 1 +extract3 +store 14 +load 5 +callsub tuplecomplement_0 +store 5 +load 6 +callsub tuplecomplement_0 +store 6 +load 7 +callsub tuplecomplement_0 +store 7 +load 8 +callsub tuplecomplement_0 +store 8 +load 9 +callsub tuplecomplement_0 +store 9 +load 10 +callsub tuplecomplement_0 +store 10 +load 11 +callsub tuplecomplement_0 +store 11 +load 12 +callsub tuplecomplement_0 +store 12 +load 13 +callsub tuplecomplement_0 +store 13 +load 14 +callsub tuplecomplement_0 +store 14 +load 5 +load 6 +concat +load 7 +concat +load 8 +concat +load 9 +concat +load 10 +concat +load 11 +concat +load 12 +concat +load 13 +concat +load 14 +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_2: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_1 +store 3 +load 3 +callsub arraycomplement_1 +store 4 +frame_dig -1 +load 3 +concat +load 4 +concat +frame_bury 0 +frame_dig 0 +retsub + +// bool_comp +boolcomp_3: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool)_v8.teal new file mode 100644 index 000000000..740a8041a --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool)_v8.teal @@ -0,0 +1,62 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 2 +load 2 +callsub roundtripper_1 +store 1 +byte 0x151f7c75 +load 1 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbit +store 0 +load 0 +callsub boolcomp_2 +store 0 +byte 0x00 +int 0 +load 0 +setbit +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub tuplecomplement_0 +store 3 +load 3 +callsub tuplecomplement_0 +store 4 +frame_dig -1 +load 3 +concat +load 4 +concat +frame_bury 0 +frame_dig 0 +retsub + +// bool_comp +boolcomp_2: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v8.teal new file mode 100644 index 000000000..cc255e503 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v8.teal @@ -0,0 +1,860 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 7 +load 7 +callsub roundtripper_1 +store 6 +byte 0x151f7c75 +load 6 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbit +store 0 +frame_dig -1 +extract 1 32 +store 1 +frame_dig -1 +extract 33 9 +store 2 +frame_dig -1 +extract 42 10 +store 3 +frame_dig -1 +extract 52 1 +store 4 +frame_dig -1 +int 53 +extract_uint64 +store 5 +load 0 +callsub boolcomp_2 +store 0 +load 1 +callsub arraycomplement_4 +store 1 +load 2 +callsub tuplecomplement_5 +store 2 +load 3 +callsub arraycomplement_7 +store 3 +load 4 +callsub arraycomplement_9 +store 4 +load 5 +callsub numericalcomp_10 +store 5 +byte 0x00 +int 0 +load 0 +setbit +load 1 +concat +load 2 +concat +load 3 +concat +load 4 +concat +load 5 +itob +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub tuplecomplement_0 +store 8 +load 8 +callsub tuplecomplement_0 +store 9 +frame_dig -1 +load 8 +concat +load 9 +concat +frame_bury 0 +frame_dig 0 +retsub + +// bool_comp +boolcomp_2: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_3: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// array_complement +arraycomplement_4: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +getbyte +store 12 +frame_dig -1 +int 1 +int 1 +* +getbyte +store 13 +frame_dig -1 +int 1 +int 2 +* +getbyte +store 14 +frame_dig -1 +int 1 +int 3 +* +getbyte +store 15 +frame_dig -1 +int 1 +int 4 +* +getbyte +store 16 +frame_dig -1 +int 1 +int 5 +* +getbyte +store 17 +frame_dig -1 +int 1 +int 6 +* +getbyte +store 18 +frame_dig -1 +int 1 +int 7 +* +getbyte +store 19 +frame_dig -1 +int 1 +int 8 +* +getbyte +store 20 +frame_dig -1 +int 1 +int 9 +* +getbyte +store 21 +frame_dig -1 +int 1 +int 10 +* +getbyte +store 22 +frame_dig -1 +int 1 +int 11 +* +getbyte +store 23 +frame_dig -1 +int 1 +int 12 +* +getbyte +store 24 +frame_dig -1 +int 1 +int 13 +* +getbyte +store 25 +frame_dig -1 +int 1 +int 14 +* +getbyte +store 26 +frame_dig -1 +int 1 +int 15 +* +getbyte +store 27 +frame_dig -1 +int 1 +int 16 +* +getbyte +store 28 +frame_dig -1 +int 1 +int 17 +* +getbyte +store 29 +frame_dig -1 +int 1 +int 18 +* +getbyte +store 30 +frame_dig -1 +int 1 +int 19 +* +getbyte +store 31 +frame_dig -1 +int 1 +int 20 +* +getbyte +store 32 +frame_dig -1 +int 1 +int 21 +* +getbyte +store 33 +frame_dig -1 +int 1 +int 22 +* +getbyte +store 34 +frame_dig -1 +int 1 +int 23 +* +getbyte +store 35 +frame_dig -1 +int 1 +int 24 +* +getbyte +store 36 +frame_dig -1 +int 1 +int 25 +* +getbyte +store 37 +frame_dig -1 +int 1 +int 26 +* +getbyte +store 38 +frame_dig -1 +int 1 +int 27 +* +getbyte +store 39 +frame_dig -1 +int 1 +int 28 +* +getbyte +store 40 +frame_dig -1 +int 1 +int 29 +* +getbyte +store 41 +frame_dig -1 +int 1 +int 30 +* +getbyte +store 42 +frame_dig -1 +int 1 +int 31 +* +getbyte +store 43 +load 12 +callsub numericalcomp_3 +store 12 +load 13 +callsub numericalcomp_3 +store 13 +load 14 +callsub numericalcomp_3 +store 14 +load 15 +callsub numericalcomp_3 +store 15 +load 16 +callsub numericalcomp_3 +store 16 +load 17 +callsub numericalcomp_3 +store 17 +load 18 +callsub numericalcomp_3 +store 18 +load 19 +callsub numericalcomp_3 +store 19 +load 20 +callsub numericalcomp_3 +store 20 +load 21 +callsub numericalcomp_3 +store 21 +load 22 +callsub numericalcomp_3 +store 22 +load 23 +callsub numericalcomp_3 +store 23 +load 24 +callsub numericalcomp_3 +store 24 +load 25 +callsub numericalcomp_3 +store 25 +load 26 +callsub numericalcomp_3 +store 26 +load 27 +callsub numericalcomp_3 +store 27 +load 28 +callsub numericalcomp_3 +store 28 +load 29 +callsub numericalcomp_3 +store 29 +load 30 +callsub numericalcomp_3 +store 30 +load 31 +callsub numericalcomp_3 +store 31 +load 32 +callsub numericalcomp_3 +store 32 +load 33 +callsub numericalcomp_3 +store 33 +load 34 +callsub numericalcomp_3 +store 34 +load 35 +callsub numericalcomp_3 +store 35 +load 36 +callsub numericalcomp_3 +store 36 +load 37 +callsub numericalcomp_3 +store 37 +load 38 +callsub numericalcomp_3 +store 38 +load 39 +callsub numericalcomp_3 +store 39 +load 40 +callsub numericalcomp_3 +store 40 +load 41 +callsub numericalcomp_3 +store 41 +load 42 +callsub numericalcomp_3 +store 42 +load 43 +callsub numericalcomp_3 +store 43 +byte 0x00 +int 0 +load 12 +setbyte +byte 0x00 +int 0 +load 13 +setbyte +concat +byte 0x00 +int 0 +load 14 +setbyte +concat +byte 0x00 +int 0 +load 15 +setbyte +concat +byte 0x00 +int 0 +load 16 +setbyte +concat +byte 0x00 +int 0 +load 17 +setbyte +concat +byte 0x00 +int 0 +load 18 +setbyte +concat +byte 0x00 +int 0 +load 19 +setbyte +concat +byte 0x00 +int 0 +load 20 +setbyte +concat +byte 0x00 +int 0 +load 21 +setbyte +concat +byte 0x00 +int 0 +load 22 +setbyte +concat +byte 0x00 +int 0 +load 23 +setbyte +concat +byte 0x00 +int 0 +load 24 +setbyte +concat +byte 0x00 +int 0 +load 25 +setbyte +concat +byte 0x00 +int 0 +load 26 +setbyte +concat +byte 0x00 +int 0 +load 27 +setbyte +concat +byte 0x00 +int 0 +load 28 +setbyte +concat +byte 0x00 +int 0 +load 29 +setbyte +concat +byte 0x00 +int 0 +load 30 +setbyte +concat +byte 0x00 +int 0 +load 31 +setbyte +concat +byte 0x00 +int 0 +load 32 +setbyte +concat +byte 0x00 +int 0 +load 33 +setbyte +concat +byte 0x00 +int 0 +load 34 +setbyte +concat +byte 0x00 +int 0 +load 35 +setbyte +concat +byte 0x00 +int 0 +load 36 +setbyte +concat +byte 0x00 +int 0 +load 37 +setbyte +concat +byte 0x00 +int 0 +load 38 +setbyte +concat +byte 0x00 +int 0 +load 39 +setbyte +concat +byte 0x00 +int 0 +load 40 +setbyte +concat +byte 0x00 +int 0 +load 41 +setbyte +concat +byte 0x00 +int 0 +load 42 +setbyte +concat +byte 0x00 +int 0 +load 43 +setbyte +concat +frame_bury 0 +frame_dig 0 +retsub + +// tuple_complement +tuplecomplement_5: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +extract_uint64 +store 10 +frame_dig -1 +int 64 +getbit +store 11 +load 10 +callsub numericalcomp_11 +store 10 +load 11 +callsub boolcomp_12 +store 11 +load 10 +itob +byte 0x00 +int 0 +load 11 +setbit +concat +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_6: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// array_complement +arraycomplement_7: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +getbyte +store 44 +frame_dig -1 +int 1 +int 1 +* +getbyte +store 45 +frame_dig -1 +int 1 +int 2 +* +getbyte +store 46 +frame_dig -1 +int 1 +int 3 +* +getbyte +store 47 +frame_dig -1 +int 1 +int 4 +* +getbyte +store 48 +frame_dig -1 +int 1 +int 5 +* +getbyte +store 49 +frame_dig -1 +int 1 +int 6 +* +getbyte +store 50 +frame_dig -1 +int 1 +int 7 +* +getbyte +store 51 +frame_dig -1 +int 1 +int 8 +* +getbyte +store 52 +frame_dig -1 +int 1 +int 9 +* +getbyte +store 53 +load 44 +callsub numericalcomp_6 +store 44 +load 45 +callsub numericalcomp_6 +store 45 +load 46 +callsub numericalcomp_6 +store 46 +load 47 +callsub numericalcomp_6 +store 47 +load 48 +callsub numericalcomp_6 +store 48 +load 49 +callsub numericalcomp_6 +store 49 +load 50 +callsub numericalcomp_6 +store 50 +load 51 +callsub numericalcomp_6 +store 51 +load 52 +callsub numericalcomp_6 +store 52 +load 53 +callsub numericalcomp_6 +store 53 +byte 0x00 +int 0 +load 44 +setbyte +byte 0x00 +int 0 +load 45 +setbyte +concat +byte 0x00 +int 0 +load 46 +setbyte +concat +byte 0x00 +int 0 +load 47 +setbyte +concat +byte 0x00 +int 0 +load 48 +setbyte +concat +byte 0x00 +int 0 +load 49 +setbyte +concat +byte 0x00 +int 0 +load 50 +setbyte +concat +byte 0x00 +int 0 +load 51 +setbyte +concat +byte 0x00 +int 0 +load 52 +setbyte +concat +byte 0x00 +int 0 +load 53 +setbyte +concat +frame_bury 0 +frame_dig 0 +retsub + +// bool_comp +boolcomp_8: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_9: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbit +store 54 +frame_dig -1 +int 1 +getbit +store 55 +frame_dig -1 +int 2 +getbit +store 56 +frame_dig -1 +int 3 +getbit +store 57 +load 54 +callsub boolcomp_8 +store 54 +load 55 +callsub boolcomp_8 +store 55 +load 56 +callsub boolcomp_8 +store 56 +load 57 +callsub boolcomp_8 +store 57 +byte 0x00 +int 0 +load 54 +setbit +int 1 +load 55 +setbit +int 2 +load 56 +setbit +int 3 +load 57 +setbit +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_10: +proto 1 1 +int 13634846 +int 18446744073709551615 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_11: +proto 1 1 +int 13634846 +int 18446744073709551615 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +retsub + +// bool_comp +boolcomp_12: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v8.teal new file mode 100644 index 000000000..c8147ff68 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v8.teal @@ -0,0 +1,89 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 3 +load 3 +callsub roundtripper_1 +store 2 +byte 0x151f7c75 +load 2 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbit +store 0 +frame_dig -1 +int 1 +getbyte +store 1 +load 0 +callsub boolcomp_2 +store 0 +load 1 +callsub numericalcomp_3 +store 1 +byte 0x00 +int 0 +load 0 +setbit +byte 0x00 +int 0 +load 1 +setbyte +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub tuplecomplement_0 +store 4 +load 4 +callsub tuplecomplement_0 +store 5 +frame_dig -1 +load 4 +concat +load 5 +concat +frame_bury 0 +frame_dig 0 +retsub + +// bool_comp +boolcomp_2: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_3: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v8.teal new file mode 100644 index 000000000..1840f754d --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v8.teal @@ -0,0 +1,690 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 5 +load 5 +callsub roundtripper_1 +store 4 +byte 0x151f7c75 +load 4 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbit +store 0 +frame_dig -1 +int 1 +getbyte +store 1 +frame_dig -1 +extract 2 32 +store 2 +frame_dig -1 +frame_dig -1 +int 34 +extract_uint16 +dig 1 +len +substring3 +store 3 +load 0 +callsub boolcomp_2 +store 0 +load 1 +callsub numericalcomp_3 +store 1 +load 2 +callsub arraycomplement_5 +store 2 +load 3 +callsub stringreverse_6 +store 3 +byte 0x00 +int 0 +load 0 +setbit +byte 0x00 +int 0 +load 1 +setbyte +concat +load 2 +concat +load 3 +store 14 +load 14 +store 13 +int 36 +store 12 +load 12 +itob +extract 6 0 +concat +load 13 +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub tuplecomplement_0 +store 6 +load 6 +callsub tuplecomplement_0 +store 7 +frame_dig -1 +store 11 +load 11 +store 10 +int 6 +store 8 +load 8 +load 11 +len ++ +store 9 +load 9 +int 65536 +< +assert +load 8 +itob +extract 6 0 +load 6 +store 11 +load 10 +load 11 +concat +store 10 +load 9 +store 8 +load 8 +load 11 +len ++ +store 9 +load 9 +int 65536 +< +assert +load 8 +itob +extract 6 0 +concat +load 7 +store 11 +load 10 +load 11 +concat +store 10 +load 9 +store 8 +load 8 +itob +extract 6 0 +concat +load 10 +concat +frame_bury 0 +frame_dig 0 +retsub + +// bool_comp +boolcomp_2: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_3: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_4: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// array_complement +arraycomplement_5: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +getbyte +store 15 +frame_dig -1 +int 1 +int 1 +* +getbyte +store 16 +frame_dig -1 +int 1 +int 2 +* +getbyte +store 17 +frame_dig -1 +int 1 +int 3 +* +getbyte +store 18 +frame_dig -1 +int 1 +int 4 +* +getbyte +store 19 +frame_dig -1 +int 1 +int 5 +* +getbyte +store 20 +frame_dig -1 +int 1 +int 6 +* +getbyte +store 21 +frame_dig -1 +int 1 +int 7 +* +getbyte +store 22 +frame_dig -1 +int 1 +int 8 +* +getbyte +store 23 +frame_dig -1 +int 1 +int 9 +* +getbyte +store 24 +frame_dig -1 +int 1 +int 10 +* +getbyte +store 25 +frame_dig -1 +int 1 +int 11 +* +getbyte +store 26 +frame_dig -1 +int 1 +int 12 +* +getbyte +store 27 +frame_dig -1 +int 1 +int 13 +* +getbyte +store 28 +frame_dig -1 +int 1 +int 14 +* +getbyte +store 29 +frame_dig -1 +int 1 +int 15 +* +getbyte +store 30 +frame_dig -1 +int 1 +int 16 +* +getbyte +store 31 +frame_dig -1 +int 1 +int 17 +* +getbyte +store 32 +frame_dig -1 +int 1 +int 18 +* +getbyte +store 33 +frame_dig -1 +int 1 +int 19 +* +getbyte +store 34 +frame_dig -1 +int 1 +int 20 +* +getbyte +store 35 +frame_dig -1 +int 1 +int 21 +* +getbyte +store 36 +frame_dig -1 +int 1 +int 22 +* +getbyte +store 37 +frame_dig -1 +int 1 +int 23 +* +getbyte +store 38 +frame_dig -1 +int 1 +int 24 +* +getbyte +store 39 +frame_dig -1 +int 1 +int 25 +* +getbyte +store 40 +frame_dig -1 +int 1 +int 26 +* +getbyte +store 41 +frame_dig -1 +int 1 +int 27 +* +getbyte +store 42 +frame_dig -1 +int 1 +int 28 +* +getbyte +store 43 +frame_dig -1 +int 1 +int 29 +* +getbyte +store 44 +frame_dig -1 +int 1 +int 30 +* +getbyte +store 45 +frame_dig -1 +int 1 +int 31 +* +getbyte +store 46 +load 15 +callsub numericalcomp_4 +store 15 +load 16 +callsub numericalcomp_4 +store 16 +load 17 +callsub numericalcomp_4 +store 17 +load 18 +callsub numericalcomp_4 +store 18 +load 19 +callsub numericalcomp_4 +store 19 +load 20 +callsub numericalcomp_4 +store 20 +load 21 +callsub numericalcomp_4 +store 21 +load 22 +callsub numericalcomp_4 +store 22 +load 23 +callsub numericalcomp_4 +store 23 +load 24 +callsub numericalcomp_4 +store 24 +load 25 +callsub numericalcomp_4 +store 25 +load 26 +callsub numericalcomp_4 +store 26 +load 27 +callsub numericalcomp_4 +store 27 +load 28 +callsub numericalcomp_4 +store 28 +load 29 +callsub numericalcomp_4 +store 29 +load 30 +callsub numericalcomp_4 +store 30 +load 31 +callsub numericalcomp_4 +store 31 +load 32 +callsub numericalcomp_4 +store 32 +load 33 +callsub numericalcomp_4 +store 33 +load 34 +callsub numericalcomp_4 +store 34 +load 35 +callsub numericalcomp_4 +store 35 +load 36 +callsub numericalcomp_4 +store 36 +load 37 +callsub numericalcomp_4 +store 37 +load 38 +callsub numericalcomp_4 +store 38 +load 39 +callsub numericalcomp_4 +store 39 +load 40 +callsub numericalcomp_4 +store 40 +load 41 +callsub numericalcomp_4 +store 41 +load 42 +callsub numericalcomp_4 +store 42 +load 43 +callsub numericalcomp_4 +store 43 +load 44 +callsub numericalcomp_4 +store 44 +load 45 +callsub numericalcomp_4 +store 45 +load 46 +callsub numericalcomp_4 +store 46 +byte 0x00 +int 0 +load 15 +setbyte +byte 0x00 +int 0 +load 16 +setbyte +concat +byte 0x00 +int 0 +load 17 +setbyte +concat +byte 0x00 +int 0 +load 18 +setbyte +concat +byte 0x00 +int 0 +load 19 +setbyte +concat +byte 0x00 +int 0 +load 20 +setbyte +concat +byte 0x00 +int 0 +load 21 +setbyte +concat +byte 0x00 +int 0 +load 22 +setbyte +concat +byte 0x00 +int 0 +load 23 +setbyte +concat +byte 0x00 +int 0 +load 24 +setbyte +concat +byte 0x00 +int 0 +load 25 +setbyte +concat +byte 0x00 +int 0 +load 26 +setbyte +concat +byte 0x00 +int 0 +load 27 +setbyte +concat +byte 0x00 +int 0 +load 28 +setbyte +concat +byte 0x00 +int 0 +load 29 +setbyte +concat +byte 0x00 +int 0 +load 30 +setbyte +concat +byte 0x00 +int 0 +load 31 +setbyte +concat +byte 0x00 +int 0 +load 32 +setbyte +concat +byte 0x00 +int 0 +load 33 +setbyte +concat +byte 0x00 +int 0 +load 34 +setbyte +concat +byte 0x00 +int 0 +load 35 +setbyte +concat +byte 0x00 +int 0 +load 36 +setbyte +concat +byte 0x00 +int 0 +load 37 +setbyte +concat +byte 0x00 +int 0 +load 38 +setbyte +concat +byte 0x00 +int 0 +load 39 +setbyte +concat +byte 0x00 +int 0 +load 40 +setbyte +concat +byte 0x00 +int 0 +load 41 +setbyte +concat +byte 0x00 +int 0 +load 42 +setbyte +concat +byte 0x00 +int 0 +load 43 +setbyte +concat +byte 0x00 +int 0 +load 44 +setbyte +concat +byte 0x00 +int 0 +load 45 +setbyte +concat +byte 0x00 +int 0 +load 46 +setbyte +concat +frame_bury 0 +frame_dig 0 +retsub + +// string_reverse +stringreverse_6: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +int 2 ++ +getbyte +store 49 +frame_dig -1 +int 1 +int 1 +* +int 2 ++ +getbyte +store 48 +frame_dig -1 +int 1 +int 2 +* +int 2 ++ +getbyte +store 47 +int 3 +store 50 +load 50 +itob +extract 6 0 +byte 0x00 +int 0 +load 47 +setbyte +byte 0x00 +int 0 +load 48 +setbyte +concat +byte 0x00 +int 0 +load 49 +setbyte +concat +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v8.teal new file mode 100644 index 000000000..b2fae5c07 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v8.teal @@ -0,0 +1,2057 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 6 +load 6 +callsub roundtripper_2 +store 5 +byte 0x151f7c75 +load 5 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbit +store 0 +frame_dig -1 +int 1 +getbyte +store 1 +frame_dig -1 +extract 2 32 +store 2 +frame_dig -1 +frame_dig -1 +int 34 +extract_uint16 +frame_dig -1 +int 36 +extract_uint16 +substring3 +store 3 +frame_dig -1 +frame_dig -1 +int 36 +extract_uint16 +dig 1 +len +substring3 +store 4 +load 0 +callsub boolcomp_3 +store 0 +load 1 +callsub numericalcomp_4 +store 1 +load 2 +callsub arraycomplement_6 +store 2 +load 3 +callsub stringreverse_7 +store 3 +load 4 +callsub tuplecomplement_8 +store 4 +byte 0x00 +int 0 +load 0 +setbit +byte 0x00 +int 0 +load 1 +setbyte +concat +load 2 +concat +load 3 +store 29 +load 29 +store 28 +int 38 +store 26 +load 26 +load 29 +len ++ +store 27 +load 27 +int 65536 +< +assert +load 26 +itob +extract 6 0 +concat +load 4 +store 29 +load 28 +load 29 +concat +store 28 +load 27 +store 26 +load 26 +itob +extract 6 0 +concat +load 28 +concat +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_1: +proto 1 1 +int 13634846 +frame_dig -1 +frame_dig -1 +int 2 +int 0 +* +int 2 ++ +extract_uint16 +int 2 ++ +int 0 +int 1 ++ +frame_dig -1 +int 0 +extract_uint16 +store 15 +load 15 +== +bnz arraycomplement_1_l5 +frame_dig -1 +int 2 +int 0 +* +int 2 ++ +int 2 ++ +extract_uint16 +int 2 ++ +arraycomplement_1_l2: +substring3 +store 13 +frame_dig -1 +frame_dig -1 +int 2 +int 1 +* +int 2 ++ +extract_uint16 +int 2 ++ +int 1 +int 1 ++ +frame_dig -1 +int 0 +extract_uint16 +store 16 +load 16 +== +bnz arraycomplement_1_l4 +frame_dig -1 +int 2 +int 1 +* +int 2 ++ +int 2 ++ +extract_uint16 +int 2 ++ +b arraycomplement_1_l6 +arraycomplement_1_l4: +frame_dig -1 +len +b arraycomplement_1_l6 +arraycomplement_1_l5: +frame_dig -1 +len +b arraycomplement_1_l2 +arraycomplement_1_l6: +substring3 +store 14 +load 13 +callsub tuplecomplement_0 +store 13 +load 14 +callsub tuplecomplement_0 +store 14 +int 2 +store 21 +load 21 +itob +extract 6 0 +load 13 +store 20 +load 20 +store 19 +int 4 +store 17 +load 17 +load 20 +len ++ +store 18 +load 18 +int 65536 +< +assert +load 17 +itob +extract 6 0 +load 14 +store 20 +load 19 +load 20 +concat +store 19 +load 18 +store 17 +load 17 +itob +extract 6 0 +concat +load 19 +concat +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_2: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_1 +store 7 +load 7 +callsub arraycomplement_1 +store 8 +frame_dig -1 +store 12 +load 12 +store 11 +int 6 +store 9 +load 9 +load 12 +len ++ +store 10 +load 10 +int 65536 +< +assert +load 9 +itob +extract 6 0 +load 7 +store 12 +load 11 +load 12 +concat +store 11 +load 10 +store 9 +load 9 +load 12 +len ++ +store 10 +load 10 +int 65536 +< +assert +load 9 +itob +extract 6 0 +concat +load 8 +store 12 +load 11 +load 12 +concat +store 11 +load 10 +store 9 +load 9 +itob +extract 6 0 +concat +load 11 +concat +frame_bury 0 +frame_dig 0 +retsub + +// bool_comp +boolcomp_3: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_4: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_5: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// array_complement +arraycomplement_6: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +getbyte +store 30 +frame_dig -1 +int 1 +int 1 +* +getbyte +store 31 +frame_dig -1 +int 1 +int 2 +* +getbyte +store 32 +frame_dig -1 +int 1 +int 3 +* +getbyte +store 33 +frame_dig -1 +int 1 +int 4 +* +getbyte +store 34 +frame_dig -1 +int 1 +int 5 +* +getbyte +store 35 +frame_dig -1 +int 1 +int 6 +* +getbyte +store 36 +frame_dig -1 +int 1 +int 7 +* +getbyte +store 37 +frame_dig -1 +int 1 +int 8 +* +getbyte +store 38 +frame_dig -1 +int 1 +int 9 +* +getbyte +store 39 +frame_dig -1 +int 1 +int 10 +* +getbyte +store 40 +frame_dig -1 +int 1 +int 11 +* +getbyte +store 41 +frame_dig -1 +int 1 +int 12 +* +getbyte +store 42 +frame_dig -1 +int 1 +int 13 +* +getbyte +store 43 +frame_dig -1 +int 1 +int 14 +* +getbyte +store 44 +frame_dig -1 +int 1 +int 15 +* +getbyte +store 45 +frame_dig -1 +int 1 +int 16 +* +getbyte +store 46 +frame_dig -1 +int 1 +int 17 +* +getbyte +store 47 +frame_dig -1 +int 1 +int 18 +* +getbyte +store 48 +frame_dig -1 +int 1 +int 19 +* +getbyte +store 49 +frame_dig -1 +int 1 +int 20 +* +getbyte +store 50 +frame_dig -1 +int 1 +int 21 +* +getbyte +store 51 +frame_dig -1 +int 1 +int 22 +* +getbyte +store 52 +frame_dig -1 +int 1 +int 23 +* +getbyte +store 53 +frame_dig -1 +int 1 +int 24 +* +getbyte +store 54 +frame_dig -1 +int 1 +int 25 +* +getbyte +store 55 +frame_dig -1 +int 1 +int 26 +* +getbyte +store 56 +frame_dig -1 +int 1 +int 27 +* +getbyte +store 57 +frame_dig -1 +int 1 +int 28 +* +getbyte +store 58 +frame_dig -1 +int 1 +int 29 +* +getbyte +store 59 +frame_dig -1 +int 1 +int 30 +* +getbyte +store 60 +frame_dig -1 +int 1 +int 31 +* +getbyte +store 61 +load 30 +callsub numericalcomp_5 +store 30 +load 31 +callsub numericalcomp_5 +store 31 +load 32 +callsub numericalcomp_5 +store 32 +load 33 +callsub numericalcomp_5 +store 33 +load 34 +callsub numericalcomp_5 +store 34 +load 35 +callsub numericalcomp_5 +store 35 +load 36 +callsub numericalcomp_5 +store 36 +load 37 +callsub numericalcomp_5 +store 37 +load 38 +callsub numericalcomp_5 +store 38 +load 39 +callsub numericalcomp_5 +store 39 +load 40 +callsub numericalcomp_5 +store 40 +load 41 +callsub numericalcomp_5 +store 41 +load 42 +callsub numericalcomp_5 +store 42 +load 43 +callsub numericalcomp_5 +store 43 +load 44 +callsub numericalcomp_5 +store 44 +load 45 +callsub numericalcomp_5 +store 45 +load 46 +callsub numericalcomp_5 +store 46 +load 47 +callsub numericalcomp_5 +store 47 +load 48 +callsub numericalcomp_5 +store 48 +load 49 +callsub numericalcomp_5 +store 49 +load 50 +callsub numericalcomp_5 +store 50 +load 51 +callsub numericalcomp_5 +store 51 +load 52 +callsub numericalcomp_5 +store 52 +load 53 +callsub numericalcomp_5 +store 53 +load 54 +callsub numericalcomp_5 +store 54 +load 55 +callsub numericalcomp_5 +store 55 +load 56 +callsub numericalcomp_5 +store 56 +load 57 +callsub numericalcomp_5 +store 57 +load 58 +callsub numericalcomp_5 +store 58 +load 59 +callsub numericalcomp_5 +store 59 +load 60 +callsub numericalcomp_5 +store 60 +load 61 +callsub numericalcomp_5 +store 61 +byte 0x00 +int 0 +load 30 +setbyte +byte 0x00 +int 0 +load 31 +setbyte +concat +byte 0x00 +int 0 +load 32 +setbyte +concat +byte 0x00 +int 0 +load 33 +setbyte +concat +byte 0x00 +int 0 +load 34 +setbyte +concat +byte 0x00 +int 0 +load 35 +setbyte +concat +byte 0x00 +int 0 +load 36 +setbyte +concat +byte 0x00 +int 0 +load 37 +setbyte +concat +byte 0x00 +int 0 +load 38 +setbyte +concat +byte 0x00 +int 0 +load 39 +setbyte +concat +byte 0x00 +int 0 +load 40 +setbyte +concat +byte 0x00 +int 0 +load 41 +setbyte +concat +byte 0x00 +int 0 +load 42 +setbyte +concat +byte 0x00 +int 0 +load 43 +setbyte +concat +byte 0x00 +int 0 +load 44 +setbyte +concat +byte 0x00 +int 0 +load 45 +setbyte +concat +byte 0x00 +int 0 +load 46 +setbyte +concat +byte 0x00 +int 0 +load 47 +setbyte +concat +byte 0x00 +int 0 +load 48 +setbyte +concat +byte 0x00 +int 0 +load 49 +setbyte +concat +byte 0x00 +int 0 +load 50 +setbyte +concat +byte 0x00 +int 0 +load 51 +setbyte +concat +byte 0x00 +int 0 +load 52 +setbyte +concat +byte 0x00 +int 0 +load 53 +setbyte +concat +byte 0x00 +int 0 +load 54 +setbyte +concat +byte 0x00 +int 0 +load 55 +setbyte +concat +byte 0x00 +int 0 +load 56 +setbyte +concat +byte 0x00 +int 0 +load 57 +setbyte +concat +byte 0x00 +int 0 +load 58 +setbyte +concat +byte 0x00 +int 0 +load 59 +setbyte +concat +byte 0x00 +int 0 +load 60 +setbyte +concat +byte 0x00 +int 0 +load 61 +setbyte +concat +frame_bury 0 +frame_dig 0 +retsub + +// string_reverse +stringreverse_7: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +int 2 ++ +getbyte +store 64 +frame_dig -1 +int 1 +int 1 +* +int 2 ++ +getbyte +store 63 +frame_dig -1 +int 1 +int 2 +* +int 2 ++ +getbyte +store 62 +int 3 +store 65 +load 65 +itob +extract 6 0 +byte 0x00 +int 0 +load 62 +setbyte +byte 0x00 +int 0 +load 63 +setbyte +concat +byte 0x00 +int 0 +load 64 +setbyte +concat +concat +frame_bury 0 +frame_dig 0 +retsub + +// tuple_complement +tuplecomplement_8: +proto 1 1 +int 13634846 +frame_dig -1 +extract 0 32 +store 22 +frame_dig -1 +frame_dig -1 +int 32 +extract_uint16 +frame_dig -1 +int 34 +extract_uint16 +substring3 +store 23 +frame_dig -1 +frame_dig -1 +int 34 +extract_uint16 +frame_dig -1 +int 36 +extract_uint16 +substring3 +store 24 +frame_dig -1 +frame_dig -1 +int 36 +extract_uint16 +dig 1 +len +substring3 +store 25 +load 22 +callsub arraycomplement_10 +store 22 +load 23 +callsub arraycomplement_12 +store 23 +load 24 +callsub stringreverse_13 +store 24 +load 25 +callsub arraycomplement_15 +store 25 +load 22 +load 23 +store 74 +load 74 +store 73 +int 38 +store 71 +load 71 +load 74 +len ++ +store 72 +load 72 +int 65536 +< +assert +load 71 +itob +extract 6 0 +concat +load 24 +store 74 +load 73 +load 74 +concat +store 73 +load 72 +store 71 +load 71 +load 74 +len ++ +store 72 +load 72 +int 65536 +< +assert +load 71 +itob +extract 6 0 +concat +load 25 +store 74 +load 73 +load 74 +concat +store 73 +load 72 +store 71 +load 71 +itob +extract 6 0 +concat +load 73 +concat +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_9: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// array_complement +arraycomplement_10: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +getbyte +store 75 +frame_dig -1 +int 1 +int 1 +* +getbyte +store 76 +frame_dig -1 +int 1 +int 2 +* +getbyte +store 77 +frame_dig -1 +int 1 +int 3 +* +getbyte +store 78 +frame_dig -1 +int 1 +int 4 +* +getbyte +store 79 +frame_dig -1 +int 1 +int 5 +* +getbyte +store 80 +frame_dig -1 +int 1 +int 6 +* +getbyte +store 81 +frame_dig -1 +int 1 +int 7 +* +getbyte +store 82 +frame_dig -1 +int 1 +int 8 +* +getbyte +store 83 +frame_dig -1 +int 1 +int 9 +* +getbyte +store 84 +frame_dig -1 +int 1 +int 10 +* +getbyte +store 85 +frame_dig -1 +int 1 +int 11 +* +getbyte +store 86 +frame_dig -1 +int 1 +int 12 +* +getbyte +store 87 +frame_dig -1 +int 1 +int 13 +* +getbyte +store 88 +frame_dig -1 +int 1 +int 14 +* +getbyte +store 89 +frame_dig -1 +int 1 +int 15 +* +getbyte +store 90 +frame_dig -1 +int 1 +int 16 +* +getbyte +store 91 +frame_dig -1 +int 1 +int 17 +* +getbyte +store 92 +frame_dig -1 +int 1 +int 18 +* +getbyte +store 93 +frame_dig -1 +int 1 +int 19 +* +getbyte +store 94 +frame_dig -1 +int 1 +int 20 +* +getbyte +store 95 +frame_dig -1 +int 1 +int 21 +* +getbyte +store 96 +frame_dig -1 +int 1 +int 22 +* +getbyte +store 97 +frame_dig -1 +int 1 +int 23 +* +getbyte +store 98 +frame_dig -1 +int 1 +int 24 +* +getbyte +store 99 +frame_dig -1 +int 1 +int 25 +* +getbyte +store 100 +frame_dig -1 +int 1 +int 26 +* +getbyte +store 101 +frame_dig -1 +int 1 +int 27 +* +getbyte +store 102 +frame_dig -1 +int 1 +int 28 +* +getbyte +store 103 +frame_dig -1 +int 1 +int 29 +* +getbyte +store 104 +frame_dig -1 +int 1 +int 30 +* +getbyte +store 105 +frame_dig -1 +int 1 +int 31 +* +getbyte +store 106 +load 75 +callsub numericalcomp_9 +store 75 +load 76 +callsub numericalcomp_9 +store 76 +load 77 +callsub numericalcomp_9 +store 77 +load 78 +callsub numericalcomp_9 +store 78 +load 79 +callsub numericalcomp_9 +store 79 +load 80 +callsub numericalcomp_9 +store 80 +load 81 +callsub numericalcomp_9 +store 81 +load 82 +callsub numericalcomp_9 +store 82 +load 83 +callsub numericalcomp_9 +store 83 +load 84 +callsub numericalcomp_9 +store 84 +load 85 +callsub numericalcomp_9 +store 85 +load 86 +callsub numericalcomp_9 +store 86 +load 87 +callsub numericalcomp_9 +store 87 +load 88 +callsub numericalcomp_9 +store 88 +load 89 +callsub numericalcomp_9 +store 89 +load 90 +callsub numericalcomp_9 +store 90 +load 91 +callsub numericalcomp_9 +store 91 +load 92 +callsub numericalcomp_9 +store 92 +load 93 +callsub numericalcomp_9 +store 93 +load 94 +callsub numericalcomp_9 +store 94 +load 95 +callsub numericalcomp_9 +store 95 +load 96 +callsub numericalcomp_9 +store 96 +load 97 +callsub numericalcomp_9 +store 97 +load 98 +callsub numericalcomp_9 +store 98 +load 99 +callsub numericalcomp_9 +store 99 +load 100 +callsub numericalcomp_9 +store 100 +load 101 +callsub numericalcomp_9 +store 101 +load 102 +callsub numericalcomp_9 +store 102 +load 103 +callsub numericalcomp_9 +store 103 +load 104 +callsub numericalcomp_9 +store 104 +load 105 +callsub numericalcomp_9 +store 105 +load 106 +callsub numericalcomp_9 +store 106 +byte 0x00 +int 0 +load 75 +setbyte +byte 0x00 +int 0 +load 76 +setbyte +concat +byte 0x00 +int 0 +load 77 +setbyte +concat +byte 0x00 +int 0 +load 78 +setbyte +concat +byte 0x00 +int 0 +load 79 +setbyte +concat +byte 0x00 +int 0 +load 80 +setbyte +concat +byte 0x00 +int 0 +load 81 +setbyte +concat +byte 0x00 +int 0 +load 82 +setbyte +concat +byte 0x00 +int 0 +load 83 +setbyte +concat +byte 0x00 +int 0 +load 84 +setbyte +concat +byte 0x00 +int 0 +load 85 +setbyte +concat +byte 0x00 +int 0 +load 86 +setbyte +concat +byte 0x00 +int 0 +load 87 +setbyte +concat +byte 0x00 +int 0 +load 88 +setbyte +concat +byte 0x00 +int 0 +load 89 +setbyte +concat +byte 0x00 +int 0 +load 90 +setbyte +concat +byte 0x00 +int 0 +load 91 +setbyte +concat +byte 0x00 +int 0 +load 92 +setbyte +concat +byte 0x00 +int 0 +load 93 +setbyte +concat +byte 0x00 +int 0 +load 94 +setbyte +concat +byte 0x00 +int 0 +load 95 +setbyte +concat +byte 0x00 +int 0 +load 96 +setbyte +concat +byte 0x00 +int 0 +load 97 +setbyte +concat +byte 0x00 +int 0 +load 98 +setbyte +concat +byte 0x00 +int 0 +load 99 +setbyte +concat +byte 0x00 +int 0 +load 100 +setbyte +concat +byte 0x00 +int 0 +load 101 +setbyte +concat +byte 0x00 +int 0 +load 102 +setbyte +concat +byte 0x00 +int 0 +load 103 +setbyte +concat +byte 0x00 +int 0 +load 104 +setbyte +concat +byte 0x00 +int 0 +load 105 +setbyte +concat +byte 0x00 +int 0 +load 106 +setbyte +concat +frame_bury 0 +frame_dig 0 +retsub + +// tuple_complement +tuplecomplement_11: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +extract_uint32 +store 66 +frame_dig -1 +frame_dig -1 +int 4 +extract_uint16 +dig 1 +len +substring3 +store 67 +frame_dig -1 +extract 6 1 +store 68 +frame_dig -1 +extract 7 1 +store 69 +frame_dig -1 +int 8 +getbyte +store 70 +load 66 +callsub numericalcomp_16 +store 66 +load 67 +callsub arraycomplement_18 +store 67 +load 68 +callsub arraycomplement_20 +store 68 +load 69 +callsub tuplecomplement_21 +store 69 +load 70 +callsub numericalcomp_22 +store 70 +load 66 +itob +extract 4 0 +load 67 +store 116 +load 116 +store 115 +int 9 +store 114 +load 114 +itob +extract 6 0 +concat +load 68 +concat +load 69 +concat +byte 0x00 +int 0 +load 70 +setbyte +concat +load 115 +concat +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_12: +proto 1 1 +int 13634846 +frame_dig -1 +frame_dig -1 +int 2 +int 0 +* +extract_uint16 +int 0 +int 1 ++ +int 2 +== +bnz arraycomplement_12_l5 +frame_dig -1 +int 2 +int 0 +* +int 2 ++ +extract_uint16 +arraycomplement_12_l2: +substring3 +store 107 +frame_dig -1 +frame_dig -1 +int 2 +int 1 +* +extract_uint16 +int 1 +int 1 ++ +int 2 +== +bnz arraycomplement_12_l4 +frame_dig -1 +int 2 +int 1 +* +int 2 ++ +extract_uint16 +b arraycomplement_12_l6 +arraycomplement_12_l4: +frame_dig -1 +len +b arraycomplement_12_l6 +arraycomplement_12_l5: +frame_dig -1 +len +b arraycomplement_12_l2 +arraycomplement_12_l6: +substring3 +store 108 +load 107 +callsub tuplecomplement_11 +store 107 +load 108 +callsub tuplecomplement_11 +store 108 +load 107 +store 112 +load 112 +store 111 +int 4 +store 109 +load 109 +load 112 +len ++ +store 110 +load 110 +int 65536 +< +assert +load 109 +itob +extract 6 0 +load 108 +store 112 +load 111 +load 112 +concat +store 111 +load 110 +store 109 +load 109 +itob +extract 6 0 +concat +load 111 +concat +frame_bury 0 +frame_dig 0 +retsub + +// string_reverse +stringreverse_13: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +int 2 ++ +getbyte +store 136 +frame_dig -1 +int 1 +int 1 +* +int 2 ++ +getbyte +store 135 +frame_dig -1 +int 1 +int 2 +* +int 2 ++ +getbyte +store 134 +int 3 +store 137 +load 137 +itob +extract 6 0 +byte 0x00 +int 0 +load 134 +setbyte +byte 0x00 +int 0 +load 135 +setbyte +concat +byte 0x00 +int 0 +load 136 +setbyte +concat +concat +frame_bury 0 +frame_dig 0 +retsub + +// bool_comp +boolcomp_14: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_15: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +int 16 ++ +getbit +store 138 +frame_dig -1 +int 1 +int 16 ++ +getbit +store 139 +frame_dig -1 +int 2 +int 16 ++ +getbit +store 140 +load 138 +callsub boolcomp_14 +store 138 +load 139 +callsub boolcomp_14 +store 139 +load 140 +callsub boolcomp_14 +store 140 +int 3 +store 141 +load 141 +itob +extract 6 0 +byte 0x00 +int 0 +load 138 +setbit +int 1 +load 139 +setbit +int 2 +load 140 +setbit +concat +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_16: +proto 1 1 +int 13634846 +int 4294967295 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 4294967296 +< +assert +frame_dig 0 +retsub + +// string_reverse +stringreverse_17: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +int 2 ++ +getbyte +store 130 +frame_dig -1 +int 1 +int 1 +* +int 2 ++ +getbyte +store 129 +frame_dig -1 +int 1 +int 2 +* +int 2 ++ +getbyte +store 128 +int 3 +store 131 +load 131 +itob +extract 6 0 +byte 0x00 +int 0 +load 128 +setbyte +byte 0x00 +int 0 +load 129 +setbyte +concat +byte 0x00 +int 0 +load 130 +setbyte +concat +concat +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_18: +proto 1 1 +int 13634846 +frame_dig -1 +frame_dig -1 +int 2 +int 0 +* +int 2 ++ +extract_uint16 +int 2 ++ +int 0 +int 1 ++ +frame_dig -1 +int 0 +extract_uint16 +store 120 +load 120 +== +bnz arraycomplement_18_l8 +frame_dig -1 +int 2 +int 0 +* +int 2 ++ +int 2 ++ +extract_uint16 +int 2 ++ +arraycomplement_18_l2: +substring3 +store 117 +frame_dig -1 +frame_dig -1 +int 2 +int 1 +* +int 2 ++ +extract_uint16 +int 2 ++ +int 1 +int 1 ++ +frame_dig -1 +int 0 +extract_uint16 +store 121 +load 121 +== +bnz arraycomplement_18_l7 +frame_dig -1 +int 2 +int 1 +* +int 2 ++ +int 2 ++ +extract_uint16 +int 2 ++ +arraycomplement_18_l4: +substring3 +store 118 +frame_dig -1 +frame_dig -1 +int 2 +int 2 +* +int 2 ++ +extract_uint16 +int 2 ++ +int 2 +int 1 ++ +frame_dig -1 +int 0 +extract_uint16 +store 122 +load 122 +== +bnz arraycomplement_18_l6 +frame_dig -1 +int 2 +int 2 +* +int 2 ++ +int 2 ++ +extract_uint16 +int 2 ++ +b arraycomplement_18_l9 +arraycomplement_18_l6: +frame_dig -1 +len +b arraycomplement_18_l9 +arraycomplement_18_l7: +frame_dig -1 +len +b arraycomplement_18_l4 +arraycomplement_18_l8: +frame_dig -1 +len +b arraycomplement_18_l2 +arraycomplement_18_l9: +substring3 +store 119 +load 117 +callsub stringreverse_17 +store 117 +load 118 +callsub stringreverse_17 +store 118 +load 119 +callsub stringreverse_17 +store 119 +int 3 +store 127 +load 127 +itob +extract 6 0 +load 117 +store 126 +load 126 +store 125 +int 6 +store 123 +load 123 +load 126 +len ++ +store 124 +load 124 +int 65536 +< +assert +load 123 +itob +extract 6 0 +load 118 +store 126 +load 125 +load 126 +concat +store 125 +load 124 +store 123 +load 123 +load 126 +len ++ +store 124 +load 124 +int 65536 +< +assert +load 123 +itob +extract 6 0 +concat +load 119 +store 126 +load 125 +load 126 +concat +store 125 +load 124 +store 123 +load 123 +itob +extract 6 0 +concat +load 125 +concat +concat +frame_bury 0 +frame_dig 0 +retsub + +// bool_comp +boolcomp_19: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_20: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbit +store 132 +frame_dig -1 +int 1 +getbit +store 133 +load 132 +callsub boolcomp_19 +store 132 +load 133 +callsub boolcomp_19 +store 133 +byte 0x00 +int 0 +load 132 +setbit +int 1 +load 133 +setbit +frame_bury 0 +frame_dig 0 +retsub + +// tuple_complement +tuplecomplement_21: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbyte +store 113 +load 113 +callsub numericalcomp_23 +store 113 +byte 0x00 +int 0 +load 113 +setbyte +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_22: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_23: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v8.teal new file mode 100644 index 000000000..0d22f98ea --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v8.teal @@ -0,0 +1,711 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 6 +load 6 +callsub roundtripper_1 +store 5 +byte 0x151f7c75 +load 5 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbit +store 0 +frame_dig -1 +int 1 +getbyte +store 1 +frame_dig -1 +extract 2 32 +store 2 +frame_dig -1 +frame_dig -1 +int 34 +extract_uint16 +dig 1 +len +substring3 +store 3 +frame_dig -1 +int 36 +extract_uint64 +store 4 +load 0 +callsub boolcomp_2 +store 0 +load 1 +callsub numericalcomp_3 +store 1 +load 2 +callsub arraycomplement_5 +store 2 +load 3 +callsub stringreverse_6 +store 3 +load 4 +callsub numericalcomp_7 +store 4 +byte 0x00 +int 0 +load 0 +setbit +byte 0x00 +int 0 +load 1 +setbyte +concat +load 2 +concat +load 3 +store 15 +load 15 +store 14 +int 44 +store 13 +load 13 +itob +extract 6 0 +concat +load 4 +itob +concat +load 14 +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub tuplecomplement_0 +store 7 +load 7 +callsub tuplecomplement_0 +store 8 +frame_dig -1 +store 12 +load 12 +store 11 +int 6 +store 9 +load 9 +load 12 +len ++ +store 10 +load 10 +int 65536 +< +assert +load 9 +itob +extract 6 0 +load 7 +store 12 +load 11 +load 12 +concat +store 11 +load 10 +store 9 +load 9 +load 12 +len ++ +store 10 +load 10 +int 65536 +< +assert +load 9 +itob +extract 6 0 +concat +load 8 +store 12 +load 11 +load 12 +concat +store 11 +load 10 +store 9 +load 9 +itob +extract 6 0 +concat +load 11 +concat +frame_bury 0 +frame_dig 0 +retsub + +// bool_comp +boolcomp_2: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_3: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_4: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// array_complement +arraycomplement_5: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +getbyte +store 16 +frame_dig -1 +int 1 +int 1 +* +getbyte +store 17 +frame_dig -1 +int 1 +int 2 +* +getbyte +store 18 +frame_dig -1 +int 1 +int 3 +* +getbyte +store 19 +frame_dig -1 +int 1 +int 4 +* +getbyte +store 20 +frame_dig -1 +int 1 +int 5 +* +getbyte +store 21 +frame_dig -1 +int 1 +int 6 +* +getbyte +store 22 +frame_dig -1 +int 1 +int 7 +* +getbyte +store 23 +frame_dig -1 +int 1 +int 8 +* +getbyte +store 24 +frame_dig -1 +int 1 +int 9 +* +getbyte +store 25 +frame_dig -1 +int 1 +int 10 +* +getbyte +store 26 +frame_dig -1 +int 1 +int 11 +* +getbyte +store 27 +frame_dig -1 +int 1 +int 12 +* +getbyte +store 28 +frame_dig -1 +int 1 +int 13 +* +getbyte +store 29 +frame_dig -1 +int 1 +int 14 +* +getbyte +store 30 +frame_dig -1 +int 1 +int 15 +* +getbyte +store 31 +frame_dig -1 +int 1 +int 16 +* +getbyte +store 32 +frame_dig -1 +int 1 +int 17 +* +getbyte +store 33 +frame_dig -1 +int 1 +int 18 +* +getbyte +store 34 +frame_dig -1 +int 1 +int 19 +* +getbyte +store 35 +frame_dig -1 +int 1 +int 20 +* +getbyte +store 36 +frame_dig -1 +int 1 +int 21 +* +getbyte +store 37 +frame_dig -1 +int 1 +int 22 +* +getbyte +store 38 +frame_dig -1 +int 1 +int 23 +* +getbyte +store 39 +frame_dig -1 +int 1 +int 24 +* +getbyte +store 40 +frame_dig -1 +int 1 +int 25 +* +getbyte +store 41 +frame_dig -1 +int 1 +int 26 +* +getbyte +store 42 +frame_dig -1 +int 1 +int 27 +* +getbyte +store 43 +frame_dig -1 +int 1 +int 28 +* +getbyte +store 44 +frame_dig -1 +int 1 +int 29 +* +getbyte +store 45 +frame_dig -1 +int 1 +int 30 +* +getbyte +store 46 +frame_dig -1 +int 1 +int 31 +* +getbyte +store 47 +load 16 +callsub numericalcomp_4 +store 16 +load 17 +callsub numericalcomp_4 +store 17 +load 18 +callsub numericalcomp_4 +store 18 +load 19 +callsub numericalcomp_4 +store 19 +load 20 +callsub numericalcomp_4 +store 20 +load 21 +callsub numericalcomp_4 +store 21 +load 22 +callsub numericalcomp_4 +store 22 +load 23 +callsub numericalcomp_4 +store 23 +load 24 +callsub numericalcomp_4 +store 24 +load 25 +callsub numericalcomp_4 +store 25 +load 26 +callsub numericalcomp_4 +store 26 +load 27 +callsub numericalcomp_4 +store 27 +load 28 +callsub numericalcomp_4 +store 28 +load 29 +callsub numericalcomp_4 +store 29 +load 30 +callsub numericalcomp_4 +store 30 +load 31 +callsub numericalcomp_4 +store 31 +load 32 +callsub numericalcomp_4 +store 32 +load 33 +callsub numericalcomp_4 +store 33 +load 34 +callsub numericalcomp_4 +store 34 +load 35 +callsub numericalcomp_4 +store 35 +load 36 +callsub numericalcomp_4 +store 36 +load 37 +callsub numericalcomp_4 +store 37 +load 38 +callsub numericalcomp_4 +store 38 +load 39 +callsub numericalcomp_4 +store 39 +load 40 +callsub numericalcomp_4 +store 40 +load 41 +callsub numericalcomp_4 +store 41 +load 42 +callsub numericalcomp_4 +store 42 +load 43 +callsub numericalcomp_4 +store 43 +load 44 +callsub numericalcomp_4 +store 44 +load 45 +callsub numericalcomp_4 +store 45 +load 46 +callsub numericalcomp_4 +store 46 +load 47 +callsub numericalcomp_4 +store 47 +byte 0x00 +int 0 +load 16 +setbyte +byte 0x00 +int 0 +load 17 +setbyte +concat +byte 0x00 +int 0 +load 18 +setbyte +concat +byte 0x00 +int 0 +load 19 +setbyte +concat +byte 0x00 +int 0 +load 20 +setbyte +concat +byte 0x00 +int 0 +load 21 +setbyte +concat +byte 0x00 +int 0 +load 22 +setbyte +concat +byte 0x00 +int 0 +load 23 +setbyte +concat +byte 0x00 +int 0 +load 24 +setbyte +concat +byte 0x00 +int 0 +load 25 +setbyte +concat +byte 0x00 +int 0 +load 26 +setbyte +concat +byte 0x00 +int 0 +load 27 +setbyte +concat +byte 0x00 +int 0 +load 28 +setbyte +concat +byte 0x00 +int 0 +load 29 +setbyte +concat +byte 0x00 +int 0 +load 30 +setbyte +concat +byte 0x00 +int 0 +load 31 +setbyte +concat +byte 0x00 +int 0 +load 32 +setbyte +concat +byte 0x00 +int 0 +load 33 +setbyte +concat +byte 0x00 +int 0 +load 34 +setbyte +concat +byte 0x00 +int 0 +load 35 +setbyte +concat +byte 0x00 +int 0 +load 36 +setbyte +concat +byte 0x00 +int 0 +load 37 +setbyte +concat +byte 0x00 +int 0 +load 38 +setbyte +concat +byte 0x00 +int 0 +load 39 +setbyte +concat +byte 0x00 +int 0 +load 40 +setbyte +concat +byte 0x00 +int 0 +load 41 +setbyte +concat +byte 0x00 +int 0 +load 42 +setbyte +concat +byte 0x00 +int 0 +load 43 +setbyte +concat +byte 0x00 +int 0 +load 44 +setbyte +concat +byte 0x00 +int 0 +load 45 +setbyte +concat +byte 0x00 +int 0 +load 46 +setbyte +concat +byte 0x00 +int 0 +load 47 +setbyte +concat +frame_bury 0 +frame_dig 0 +retsub + +// string_reverse +stringreverse_6: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +int 2 ++ +getbyte +store 50 +frame_dig -1 +int 1 +int 1 +* +int 2 ++ +getbyte +store 49 +frame_dig -1 +int 1 +int 2 +* +int 2 ++ +getbyte +store 48 +int 3 +store 51 +load 51 +itob +extract 6 0 +byte 0x00 +int 0 +load 48 +setbyte +byte 0x00 +int 0 +load 49 +setbyte +concat +byte 0x00 +int 0 +load 50 +setbyte +concat +concat +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_7: +proto 1 1 +int 13634846 +int 18446744073709551615 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v8.teal new file mode 100644 index 000000000..a1ba69bfb --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v8.teal @@ -0,0 +1,109 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 4 +load 4 +callsub roundtripper_1 +store 3 +byte 0x151f7c75 +load 3 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbit +store 0 +frame_dig -1 +int 1 +extract_uint64 +store 1 +frame_dig -1 +int 9 +extract_uint32 +store 2 +load 0 +callsub boolcomp_2 +store 0 +load 1 +callsub numericalcomp_3 +store 1 +load 2 +callsub numericalcomp_4 +store 2 +byte 0x00 +int 0 +load 0 +setbit +load 1 +itob +concat +load 2 +itob +extract 4 0 +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub tuplecomplement_0 +store 5 +load 5 +callsub tuplecomplement_0 +store 6 +frame_dig -1 +load 5 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub + +// bool_comp +boolcomp_2: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_3: +proto 1 1 +int 13634846 +int 18446744073709551615 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_4: +proto 1 1 +int 13634846 +int 4294967295 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 4294967296 +< +assert +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(byte)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(byte)_v8.teal new file mode 100644 index 000000000..ea0e98fc2 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(byte)_v8.teal @@ -0,0 +1,65 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 2 +load 2 +callsub roundtripper_1 +store 1 +byte 0x151f7c75 +load 1 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbyte +store 0 +load 0 +callsub numericalcomp_2 +store 0 +byte 0x00 +int 0 +load 0 +setbyte +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub tuplecomplement_0 +store 3 +load 3 +callsub tuplecomplement_0 +store 4 +frame_dig -1 +load 3 +concat +load 4 +concat +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_2: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v8.teal new file mode 100644 index 000000000..d0db45543 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v8.teal @@ -0,0 +1,110 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 4 +load 4 +callsub roundtripper_1 +store 3 +byte 0x151f7c75 +load 3 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbyte +store 0 +frame_dig -1 +int 8 +getbit +store 1 +frame_dig -1 +int 2 +extract_uint64 +store 2 +load 0 +callsub numericalcomp_2 +store 0 +load 1 +callsub boolcomp_3 +store 1 +load 2 +callsub numericalcomp_4 +store 2 +byte 0x00 +int 0 +load 0 +setbyte +byte 0x00 +int 0 +load 1 +setbit +concat +load 2 +itob +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub tuplecomplement_0 +store 5 +load 5 +callsub tuplecomplement_0 +store 6 +frame_dig -1 +load 5 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_2: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// bool_comp +boolcomp_3: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_4: +proto 1 1 +int 13634846 +int 18446744073709551615 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v8.teal new file mode 100644 index 000000000..915b57058 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v8.teal @@ -0,0 +1,843 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 5 +load 5 +callsub roundtripper_2 +store 4 +byte 0x151f7c75 +load 4 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +extract 0 4 +store 0 +frame_dig -1 +extract 4 1 +store 1 +frame_dig -1 +int 5 +extract_uint64 +store 2 +frame_dig -1 +extract 13 0 +store 3 +load 0 +callsub arraycomplement_4 +store 0 +load 1 +callsub tuplecomplement_5 +store 1 +load 2 +callsub numericalcomp_6 +store 2 +load 3 +callsub arraycomplement_8 +store 3 +load 0 +load 1 +concat +load 2 +itob +concat +load 3 +concat +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_1: +proto 1 1 +int 13634846 +frame_dig -1 +int 45 +int 0 +* +int 2 ++ +int 45 +extract3 +store 12 +frame_dig -1 +int 45 +int 1 +* +int 2 ++ +int 45 +extract3 +store 13 +frame_dig -1 +int 45 +int 2 +* +int 2 ++ +int 45 +extract3 +store 14 +frame_dig -1 +int 45 +int 3 +* +int 2 ++ +int 45 +extract3 +store 15 +frame_dig -1 +int 45 +int 4 +* +int 2 ++ +int 45 +extract3 +store 16 +frame_dig -1 +int 45 +int 5 +* +int 2 ++ +int 45 +extract3 +store 17 +frame_dig -1 +int 45 +int 6 +* +int 2 ++ +int 45 +extract3 +store 18 +load 12 +callsub tuplecomplement_0 +store 12 +load 13 +callsub tuplecomplement_0 +store 13 +load 14 +callsub tuplecomplement_0 +store 14 +load 15 +callsub tuplecomplement_0 +store 15 +load 16 +callsub tuplecomplement_0 +store 16 +load 17 +callsub tuplecomplement_0 +store 17 +load 18 +callsub tuplecomplement_0 +store 18 +int 7 +store 19 +load 19 +itob +extract 6 0 +load 12 +load 13 +concat +load 14 +concat +load 15 +concat +load 16 +concat +load 17 +concat +load 18 +concat +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_2: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_1 +store 6 +load 6 +callsub arraycomplement_1 +store 7 +frame_dig -1 +store 11 +load 11 +store 10 +int 6 +store 8 +load 8 +load 11 +len ++ +store 9 +load 9 +int 65536 +< +assert +load 8 +itob +extract 6 0 +load 6 +store 11 +load 10 +load 11 +concat +store 10 +load 9 +store 8 +load 8 +load 11 +len ++ +store 9 +load 9 +int 65536 +< +assert +load 8 +itob +extract 6 0 +concat +load 7 +store 11 +load 10 +load 11 +concat +store 10 +load 9 +store 8 +load 8 +itob +extract 6 0 +concat +load 10 +concat +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_3: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// array_complement +arraycomplement_4: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +getbyte +store 22 +frame_dig -1 +int 1 +int 1 +* +getbyte +store 23 +frame_dig -1 +int 1 +int 2 +* +getbyte +store 24 +frame_dig -1 +int 1 +int 3 +* +getbyte +store 25 +load 22 +callsub numericalcomp_3 +store 22 +load 23 +callsub numericalcomp_3 +store 23 +load 24 +callsub numericalcomp_3 +store 24 +load 25 +callsub numericalcomp_3 +store 25 +byte 0x00 +int 0 +load 22 +setbyte +byte 0x00 +int 0 +load 23 +setbyte +concat +byte 0x00 +int 0 +load 24 +setbyte +concat +byte 0x00 +int 0 +load 25 +setbyte +concat +frame_bury 0 +frame_dig 0 +retsub + +// tuple_complement +tuplecomplement_5: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbit +store 20 +frame_dig -1 +int 1 +getbit +store 21 +load 20 +callsub boolcomp_9 +store 20 +load 21 +callsub boolcomp_10 +store 21 +byte 0x00 +int 0 +load 20 +setbit +int 1 +load 21 +setbit +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_6: +proto 1 1 +int 13634846 +int 18446744073709551615 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_7: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// array_complement +arraycomplement_8: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +getbyte +store 26 +frame_dig -1 +int 1 +int 1 +* +getbyte +store 27 +frame_dig -1 +int 1 +int 2 +* +getbyte +store 28 +frame_dig -1 +int 1 +int 3 +* +getbyte +store 29 +frame_dig -1 +int 1 +int 4 +* +getbyte +store 30 +frame_dig -1 +int 1 +int 5 +* +getbyte +store 31 +frame_dig -1 +int 1 +int 6 +* +getbyte +store 32 +frame_dig -1 +int 1 +int 7 +* +getbyte +store 33 +frame_dig -1 +int 1 +int 8 +* +getbyte +store 34 +frame_dig -1 +int 1 +int 9 +* +getbyte +store 35 +frame_dig -1 +int 1 +int 10 +* +getbyte +store 36 +frame_dig -1 +int 1 +int 11 +* +getbyte +store 37 +frame_dig -1 +int 1 +int 12 +* +getbyte +store 38 +frame_dig -1 +int 1 +int 13 +* +getbyte +store 39 +frame_dig -1 +int 1 +int 14 +* +getbyte +store 40 +frame_dig -1 +int 1 +int 15 +* +getbyte +store 41 +frame_dig -1 +int 1 +int 16 +* +getbyte +store 42 +frame_dig -1 +int 1 +int 17 +* +getbyte +store 43 +frame_dig -1 +int 1 +int 18 +* +getbyte +store 44 +frame_dig -1 +int 1 +int 19 +* +getbyte +store 45 +frame_dig -1 +int 1 +int 20 +* +getbyte +store 46 +frame_dig -1 +int 1 +int 21 +* +getbyte +store 47 +frame_dig -1 +int 1 +int 22 +* +getbyte +store 48 +frame_dig -1 +int 1 +int 23 +* +getbyte +store 49 +frame_dig -1 +int 1 +int 24 +* +getbyte +store 50 +frame_dig -1 +int 1 +int 25 +* +getbyte +store 51 +frame_dig -1 +int 1 +int 26 +* +getbyte +store 52 +frame_dig -1 +int 1 +int 27 +* +getbyte +store 53 +frame_dig -1 +int 1 +int 28 +* +getbyte +store 54 +frame_dig -1 +int 1 +int 29 +* +getbyte +store 55 +frame_dig -1 +int 1 +int 30 +* +getbyte +store 56 +frame_dig -1 +int 1 +int 31 +* +getbyte +store 57 +load 26 +callsub numericalcomp_7 +store 26 +load 27 +callsub numericalcomp_7 +store 27 +load 28 +callsub numericalcomp_7 +store 28 +load 29 +callsub numericalcomp_7 +store 29 +load 30 +callsub numericalcomp_7 +store 30 +load 31 +callsub numericalcomp_7 +store 31 +load 32 +callsub numericalcomp_7 +store 32 +load 33 +callsub numericalcomp_7 +store 33 +load 34 +callsub numericalcomp_7 +store 34 +load 35 +callsub numericalcomp_7 +store 35 +load 36 +callsub numericalcomp_7 +store 36 +load 37 +callsub numericalcomp_7 +store 37 +load 38 +callsub numericalcomp_7 +store 38 +load 39 +callsub numericalcomp_7 +store 39 +load 40 +callsub numericalcomp_7 +store 40 +load 41 +callsub numericalcomp_7 +store 41 +load 42 +callsub numericalcomp_7 +store 42 +load 43 +callsub numericalcomp_7 +store 43 +load 44 +callsub numericalcomp_7 +store 44 +load 45 +callsub numericalcomp_7 +store 45 +load 46 +callsub numericalcomp_7 +store 46 +load 47 +callsub numericalcomp_7 +store 47 +load 48 +callsub numericalcomp_7 +store 48 +load 49 +callsub numericalcomp_7 +store 49 +load 50 +callsub numericalcomp_7 +store 50 +load 51 +callsub numericalcomp_7 +store 51 +load 52 +callsub numericalcomp_7 +store 52 +load 53 +callsub numericalcomp_7 +store 53 +load 54 +callsub numericalcomp_7 +store 54 +load 55 +callsub numericalcomp_7 +store 55 +load 56 +callsub numericalcomp_7 +store 56 +load 57 +callsub numericalcomp_7 +store 57 +byte 0x00 +int 0 +load 26 +setbyte +byte 0x00 +int 0 +load 27 +setbyte +concat +byte 0x00 +int 0 +load 28 +setbyte +concat +byte 0x00 +int 0 +load 29 +setbyte +concat +byte 0x00 +int 0 +load 30 +setbyte +concat +byte 0x00 +int 0 +load 31 +setbyte +concat +byte 0x00 +int 0 +load 32 +setbyte +concat +byte 0x00 +int 0 +load 33 +setbyte +concat +byte 0x00 +int 0 +load 34 +setbyte +concat +byte 0x00 +int 0 +load 35 +setbyte +concat +byte 0x00 +int 0 +load 36 +setbyte +concat +byte 0x00 +int 0 +load 37 +setbyte +concat +byte 0x00 +int 0 +load 38 +setbyte +concat +byte 0x00 +int 0 +load 39 +setbyte +concat +byte 0x00 +int 0 +load 40 +setbyte +concat +byte 0x00 +int 0 +load 41 +setbyte +concat +byte 0x00 +int 0 +load 42 +setbyte +concat +byte 0x00 +int 0 +load 43 +setbyte +concat +byte 0x00 +int 0 +load 44 +setbyte +concat +byte 0x00 +int 0 +load 45 +setbyte +concat +byte 0x00 +int 0 +load 46 +setbyte +concat +byte 0x00 +int 0 +load 47 +setbyte +concat +byte 0x00 +int 0 +load 48 +setbyte +concat +byte 0x00 +int 0 +load 49 +setbyte +concat +byte 0x00 +int 0 +load 50 +setbyte +concat +byte 0x00 +int 0 +load 51 +setbyte +concat +byte 0x00 +int 0 +load 52 +setbyte +concat +byte 0x00 +int 0 +load 53 +setbyte +concat +byte 0x00 +int 0 +load 54 +setbyte +concat +byte 0x00 +int 0 +load 55 +setbyte +concat +byte 0x00 +int 0 +load 56 +setbyte +concat +byte 0x00 +int 0 +load 57 +setbyte +concat +frame_bury 0 +frame_dig 0 +retsub + +// bool_comp +boolcomp_9: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub + +// bool_comp +boolcomp_10: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v8.teal new file mode 100644 index 000000000..306ab7acb --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v8.teal @@ -0,0 +1,64 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 2 +load 2 +callsub roundtripper_1 +store 1 +byte 0x151f7c75 +load 1 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +extract_uint16 +store 0 +load 0 +callsub numericalcomp_2 +store 0 +load 0 +itob +extract 6 0 +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub tuplecomplement_0 +store 3 +load 3 +callsub tuplecomplement_0 +store 4 +frame_dig -1 +load 3 +concat +load 4 +concat +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_2: +proto 1 1 +int 13634846 +int 65535 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 65536 +< +assert +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v8.teal new file mode 100644 index 000000000..ef7c2428d --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v8.teal @@ -0,0 +1,118 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 4 +load 4 +callsub roundtripper_1 +store 3 +byte 0x151f7c75 +load 3 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +extract_uint16 +store 0 +frame_dig -1 +int 2 +getbyte +store 1 +frame_dig -1 +int 3 +getbyte +store 2 +load 0 +callsub numericalcomp_2 +store 0 +load 1 +callsub numericalcomp_3 +store 1 +load 2 +callsub numericalcomp_4 +store 2 +load 0 +itob +extract 6 0 +byte 0x00 +int 0 +load 1 +setbyte +concat +byte 0x00 +int 0 +load 2 +setbyte +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub tuplecomplement_0 +store 5 +load 5 +callsub tuplecomplement_0 +store 6 +frame_dig -1 +load 5 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_2: +proto 1 1 +int 13634846 +int 65535 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 65536 +< +assert +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_3: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_4: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v8.teal new file mode 100644 index 000000000..741db6e80 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v8.teal @@ -0,0 +1,64 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 2 +load 2 +callsub roundtripper_1 +store 1 +byte 0x151f7c75 +load 1 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +extract_uint32 +store 0 +load 0 +callsub numericalcomp_2 +store 0 +load 0 +itob +extract 4 0 +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub tuplecomplement_0 +store 3 +load 3 +callsub tuplecomplement_0 +store 4 +frame_dig -1 +load 3 +concat +load 4 +concat +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_2: +proto 1 1 +int 13634846 +int 4294967295 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 4294967296 +< +assert +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v8.teal new file mode 100644 index 000000000..03e6b2c06 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v8.teal @@ -0,0 +1,117 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 4 +load 4 +callsub roundtripper_1 +store 3 +byte 0x151f7c75 +load 3 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +extract_uint32 +store 0 +frame_dig -1 +int 4 +extract_uint16 +store 1 +frame_dig -1 +int 6 +getbyte +store 2 +load 0 +callsub numericalcomp_2 +store 0 +load 1 +callsub numericalcomp_3 +store 1 +load 2 +callsub numericalcomp_4 +store 2 +load 0 +itob +extract 4 0 +load 1 +itob +extract 6 0 +concat +byte 0x00 +int 0 +load 2 +setbyte +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub tuplecomplement_0 +store 5 +load 5 +callsub tuplecomplement_0 +store 6 +frame_dig -1 +load 5 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_2: +proto 1 1 +int 13634846 +int 4294967295 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 4294967296 +< +assert +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_3: +proto 1 1 +int 13634846 +int 65535 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 65536 +< +assert +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_4: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v8.teal new file mode 100644 index 000000000..b88127140 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v8.teal @@ -0,0 +1,58 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 2 +load 2 +callsub roundtripper_1 +store 1 +byte 0x151f7c75 +load 1 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +btoi +store 0 +load 0 +callsub numericalcomp_2 +store 0 +load 0 +itob +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub tuplecomplement_0 +store 3 +load 3 +callsub tuplecomplement_0 +store 4 +frame_dig -1 +load 3 +concat +load 4 +concat +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_2: +proto 1 1 +int 13634846 +int 18446744073709551615 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v8.teal new file mode 100644 index 000000000..eacfb78f8 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v8.teal @@ -0,0 +1,111 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 4 +load 4 +callsub roundtripper_1 +store 3 +byte 0x151f7c75 +load 3 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +extract_uint64 +store 0 +frame_dig -1 +int 8 +extract_uint32 +store 1 +frame_dig -1 +int 12 +extract_uint16 +store 2 +load 0 +callsub numericalcomp_2 +store 0 +load 1 +callsub numericalcomp_3 +store 1 +load 2 +callsub numericalcomp_4 +store 2 +load 0 +itob +load 1 +itob +extract 4 0 +concat +load 2 +itob +extract 6 0 +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub tuplecomplement_0 +store 5 +load 5 +callsub tuplecomplement_0 +store 6 +frame_dig -1 +load 5 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_2: +proto 1 1 +int 13634846 +int 18446744073709551615 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_3: +proto 1 1 +int 13634846 +int 4294967295 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 4294967296 +< +assert +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_4: +proto 1 1 +int 13634846 +int 65535 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 65536 +< +assert +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v8.teal new file mode 100644 index 000000000..ea0e98fc2 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v8.teal @@ -0,0 +1,65 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 2 +load 2 +callsub roundtripper_1 +store 1 +byte 0x151f7c75 +load 1 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbyte +store 0 +load 0 +callsub numericalcomp_2 +store 0 +byte 0x00 +int 0 +load 0 +setbyte +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub tuplecomplement_0 +store 3 +load 3 +callsub tuplecomplement_0 +store 4 +frame_dig -1 +load 3 +concat +load 4 +concat +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_2: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v8.teal new file mode 100644 index 000000000..9addccd5d --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v8.teal @@ -0,0 +1,116 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 4 +load 4 +callsub roundtripper_1 +store 3 +byte 0x151f7c75 +load 3 +concat +log +int 1 +return + +// tuple_complement +tuplecomplement_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbyte +store 0 +frame_dig -1 +int 1 +getbyte +store 1 +frame_dig -1 +int 16 +getbit +store 2 +load 0 +callsub numericalcomp_2 +store 0 +load 1 +callsub numericalcomp_3 +store 1 +load 2 +callsub boolcomp_4 +store 2 +byte 0x00 +int 0 +load 0 +setbyte +byte 0x00 +int 0 +load 1 +setbyte +concat +byte 0x00 +int 0 +load 2 +setbit +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub tuplecomplement_0 +store 5 +load 5 +callsub tuplecomplement_0 +store 6 +frame_dig -1 +load 5 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_2: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// numerical_comp +numericalcomp_3: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// bool_comp +boolcomp_4: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v8.teal new file mode 100644 index 000000000..be15e1a34 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v8.teal @@ -0,0 +1,702 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_3 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// numerical_comp +numericalcomp_0: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// array_complement +arraycomplement_1: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +getbyte +store 19 +frame_dig -1 +int 1 +int 1 +* +getbyte +store 20 +frame_dig -1 +int 1 +int 2 +* +getbyte +store 21 +frame_dig -1 +int 1 +int 3 +* +getbyte +store 22 +frame_dig -1 +int 1 +int 4 +* +getbyte +store 23 +frame_dig -1 +int 1 +int 5 +* +getbyte +store 24 +frame_dig -1 +int 1 +int 6 +* +getbyte +store 25 +frame_dig -1 +int 1 +int 7 +* +getbyte +store 26 +frame_dig -1 +int 1 +int 8 +* +getbyte +store 27 +frame_dig -1 +int 1 +int 9 +* +getbyte +store 28 +frame_dig -1 +int 1 +int 10 +* +getbyte +store 29 +frame_dig -1 +int 1 +int 11 +* +getbyte +store 30 +frame_dig -1 +int 1 +int 12 +* +getbyte +store 31 +frame_dig -1 +int 1 +int 13 +* +getbyte +store 32 +frame_dig -1 +int 1 +int 14 +* +getbyte +store 33 +frame_dig -1 +int 1 +int 15 +* +getbyte +store 34 +frame_dig -1 +int 1 +int 16 +* +getbyte +store 35 +frame_dig -1 +int 1 +int 17 +* +getbyte +store 36 +frame_dig -1 +int 1 +int 18 +* +getbyte +store 37 +frame_dig -1 +int 1 +int 19 +* +getbyte +store 38 +frame_dig -1 +int 1 +int 20 +* +getbyte +store 39 +frame_dig -1 +int 1 +int 21 +* +getbyte +store 40 +frame_dig -1 +int 1 +int 22 +* +getbyte +store 41 +frame_dig -1 +int 1 +int 23 +* +getbyte +store 42 +frame_dig -1 +int 1 +int 24 +* +getbyte +store 43 +frame_dig -1 +int 1 +int 25 +* +getbyte +store 44 +frame_dig -1 +int 1 +int 26 +* +getbyte +store 45 +frame_dig -1 +int 1 +int 27 +* +getbyte +store 46 +frame_dig -1 +int 1 +int 28 +* +getbyte +store 47 +frame_dig -1 +int 1 +int 29 +* +getbyte +store 48 +frame_dig -1 +int 1 +int 30 +* +getbyte +store 49 +frame_dig -1 +int 1 +int 31 +* +getbyte +store 50 +load 19 +callsub numericalcomp_0 +store 19 +load 20 +callsub numericalcomp_0 +store 20 +load 21 +callsub numericalcomp_0 +store 21 +load 22 +callsub numericalcomp_0 +store 22 +load 23 +callsub numericalcomp_0 +store 23 +load 24 +callsub numericalcomp_0 +store 24 +load 25 +callsub numericalcomp_0 +store 25 +load 26 +callsub numericalcomp_0 +store 26 +load 27 +callsub numericalcomp_0 +store 27 +load 28 +callsub numericalcomp_0 +store 28 +load 29 +callsub numericalcomp_0 +store 29 +load 30 +callsub numericalcomp_0 +store 30 +load 31 +callsub numericalcomp_0 +store 31 +load 32 +callsub numericalcomp_0 +store 32 +load 33 +callsub numericalcomp_0 +store 33 +load 34 +callsub numericalcomp_0 +store 34 +load 35 +callsub numericalcomp_0 +store 35 +load 36 +callsub numericalcomp_0 +store 36 +load 37 +callsub numericalcomp_0 +store 37 +load 38 +callsub numericalcomp_0 +store 38 +load 39 +callsub numericalcomp_0 +store 39 +load 40 +callsub numericalcomp_0 +store 40 +load 41 +callsub numericalcomp_0 +store 41 +load 42 +callsub numericalcomp_0 +store 42 +load 43 +callsub numericalcomp_0 +store 43 +load 44 +callsub numericalcomp_0 +store 44 +load 45 +callsub numericalcomp_0 +store 45 +load 46 +callsub numericalcomp_0 +store 46 +load 47 +callsub numericalcomp_0 +store 47 +load 48 +callsub numericalcomp_0 +store 48 +load 49 +callsub numericalcomp_0 +store 49 +load 50 +callsub numericalcomp_0 +store 50 +byte 0x00 +int 0 +load 19 +setbyte +byte 0x00 +int 0 +load 20 +setbyte +concat +byte 0x00 +int 0 +load 21 +setbyte +concat +byte 0x00 +int 0 +load 22 +setbyte +concat +byte 0x00 +int 0 +load 23 +setbyte +concat +byte 0x00 +int 0 +load 24 +setbyte +concat +byte 0x00 +int 0 +load 25 +setbyte +concat +byte 0x00 +int 0 +load 26 +setbyte +concat +byte 0x00 +int 0 +load 27 +setbyte +concat +byte 0x00 +int 0 +load 28 +setbyte +concat +byte 0x00 +int 0 +load 29 +setbyte +concat +byte 0x00 +int 0 +load 30 +setbyte +concat +byte 0x00 +int 0 +load 31 +setbyte +concat +byte 0x00 +int 0 +load 32 +setbyte +concat +byte 0x00 +int 0 +load 33 +setbyte +concat +byte 0x00 +int 0 +load 34 +setbyte +concat +byte 0x00 +int 0 +load 35 +setbyte +concat +byte 0x00 +int 0 +load 36 +setbyte +concat +byte 0x00 +int 0 +load 37 +setbyte +concat +byte 0x00 +int 0 +load 38 +setbyte +concat +byte 0x00 +int 0 +load 39 +setbyte +concat +byte 0x00 +int 0 +load 40 +setbyte +concat +byte 0x00 +int 0 +load 41 +setbyte +concat +byte 0x00 +int 0 +load 42 +setbyte +concat +byte 0x00 +int 0 +load 43 +setbyte +concat +byte 0x00 +int 0 +load 44 +setbyte +concat +byte 0x00 +int 0 +load 45 +setbyte +concat +byte 0x00 +int 0 +load 46 +setbyte +concat +byte 0x00 +int 0 +load 47 +setbyte +concat +byte 0x00 +int 0 +load 48 +setbyte +concat +byte 0x00 +int 0 +load 49 +setbyte +concat +byte 0x00 +int 0 +load 50 +setbyte +concat +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_2: +proto 1 1 +int 13634846 +frame_dig -1 +int 32 +int 0 +* +int 2 ++ +int 32 +extract3 +store 8 +frame_dig -1 +int 32 +int 1 +* +int 2 ++ +int 32 +extract3 +store 9 +frame_dig -1 +int 32 +int 2 +* +int 2 ++ +int 32 +extract3 +store 10 +frame_dig -1 +int 32 +int 3 +* +int 2 ++ +int 32 +extract3 +store 11 +frame_dig -1 +int 32 +int 4 +* +int 2 ++ +int 32 +extract3 +store 12 +frame_dig -1 +int 32 +int 5 +* +int 2 ++ +int 32 +extract3 +store 13 +frame_dig -1 +int 32 +int 6 +* +int 2 ++ +int 32 +extract3 +store 14 +frame_dig -1 +int 32 +int 7 +* +int 2 ++ +int 32 +extract3 +store 15 +frame_dig -1 +int 32 +int 8 +* +int 2 ++ +int 32 +extract3 +store 16 +frame_dig -1 +int 32 +int 9 +* +int 2 ++ +int 32 +extract3 +store 17 +load 8 +callsub arraycomplement_1 +store 8 +load 9 +callsub arraycomplement_1 +store 9 +load 10 +callsub arraycomplement_1 +store 10 +load 11 +callsub arraycomplement_1 +store 11 +load 12 +callsub arraycomplement_1 +store 12 +load 13 +callsub arraycomplement_1 +store 13 +load 14 +callsub arraycomplement_1 +store 14 +load 15 +callsub arraycomplement_1 +store 15 +load 16 +callsub arraycomplement_1 +store 16 +load 17 +callsub arraycomplement_1 +store 17 +int 10 +store 18 +load 18 +itob +extract 6 0 +load 8 +load 9 +concat +load 10 +concat +load 11 +concat +load 12 +concat +load 13 +concat +load 14 +concat +load 15 +concat +load 16 +concat +load 17 +concat +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_3: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_2 +store 2 +load 2 +callsub arraycomplement_2 +store 3 +frame_dig -1 +store 7 +load 7 +store 6 +int 6 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +load 2 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +concat +load 3 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +itob +extract 6 0 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_address_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_address_v8.teal new file mode 100644 index 000000000..7444fb267 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_address_v8.teal @@ -0,0 +1,501 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_2 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// numerical_comp +numericalcomp_0: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// array_complement +arraycomplement_1: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +getbyte +store 4 +frame_dig -1 +int 1 +int 1 +* +getbyte +store 5 +frame_dig -1 +int 1 +int 2 +* +getbyte +store 6 +frame_dig -1 +int 1 +int 3 +* +getbyte +store 7 +frame_dig -1 +int 1 +int 4 +* +getbyte +store 8 +frame_dig -1 +int 1 +int 5 +* +getbyte +store 9 +frame_dig -1 +int 1 +int 6 +* +getbyte +store 10 +frame_dig -1 +int 1 +int 7 +* +getbyte +store 11 +frame_dig -1 +int 1 +int 8 +* +getbyte +store 12 +frame_dig -1 +int 1 +int 9 +* +getbyte +store 13 +frame_dig -1 +int 1 +int 10 +* +getbyte +store 14 +frame_dig -1 +int 1 +int 11 +* +getbyte +store 15 +frame_dig -1 +int 1 +int 12 +* +getbyte +store 16 +frame_dig -1 +int 1 +int 13 +* +getbyte +store 17 +frame_dig -1 +int 1 +int 14 +* +getbyte +store 18 +frame_dig -1 +int 1 +int 15 +* +getbyte +store 19 +frame_dig -1 +int 1 +int 16 +* +getbyte +store 20 +frame_dig -1 +int 1 +int 17 +* +getbyte +store 21 +frame_dig -1 +int 1 +int 18 +* +getbyte +store 22 +frame_dig -1 +int 1 +int 19 +* +getbyte +store 23 +frame_dig -1 +int 1 +int 20 +* +getbyte +store 24 +frame_dig -1 +int 1 +int 21 +* +getbyte +store 25 +frame_dig -1 +int 1 +int 22 +* +getbyte +store 26 +frame_dig -1 +int 1 +int 23 +* +getbyte +store 27 +frame_dig -1 +int 1 +int 24 +* +getbyte +store 28 +frame_dig -1 +int 1 +int 25 +* +getbyte +store 29 +frame_dig -1 +int 1 +int 26 +* +getbyte +store 30 +frame_dig -1 +int 1 +int 27 +* +getbyte +store 31 +frame_dig -1 +int 1 +int 28 +* +getbyte +store 32 +frame_dig -1 +int 1 +int 29 +* +getbyte +store 33 +frame_dig -1 +int 1 +int 30 +* +getbyte +store 34 +frame_dig -1 +int 1 +int 31 +* +getbyte +store 35 +load 4 +callsub numericalcomp_0 +store 4 +load 5 +callsub numericalcomp_0 +store 5 +load 6 +callsub numericalcomp_0 +store 6 +load 7 +callsub numericalcomp_0 +store 7 +load 8 +callsub numericalcomp_0 +store 8 +load 9 +callsub numericalcomp_0 +store 9 +load 10 +callsub numericalcomp_0 +store 10 +load 11 +callsub numericalcomp_0 +store 11 +load 12 +callsub numericalcomp_0 +store 12 +load 13 +callsub numericalcomp_0 +store 13 +load 14 +callsub numericalcomp_0 +store 14 +load 15 +callsub numericalcomp_0 +store 15 +load 16 +callsub numericalcomp_0 +store 16 +load 17 +callsub numericalcomp_0 +store 17 +load 18 +callsub numericalcomp_0 +store 18 +load 19 +callsub numericalcomp_0 +store 19 +load 20 +callsub numericalcomp_0 +store 20 +load 21 +callsub numericalcomp_0 +store 21 +load 22 +callsub numericalcomp_0 +store 22 +load 23 +callsub numericalcomp_0 +store 23 +load 24 +callsub numericalcomp_0 +store 24 +load 25 +callsub numericalcomp_0 +store 25 +load 26 +callsub numericalcomp_0 +store 26 +load 27 +callsub numericalcomp_0 +store 27 +load 28 +callsub numericalcomp_0 +store 28 +load 29 +callsub numericalcomp_0 +store 29 +load 30 +callsub numericalcomp_0 +store 30 +load 31 +callsub numericalcomp_0 +store 31 +load 32 +callsub numericalcomp_0 +store 32 +load 33 +callsub numericalcomp_0 +store 33 +load 34 +callsub numericalcomp_0 +store 34 +load 35 +callsub numericalcomp_0 +store 35 +byte 0x00 +int 0 +load 4 +setbyte +byte 0x00 +int 0 +load 5 +setbyte +concat +byte 0x00 +int 0 +load 6 +setbyte +concat +byte 0x00 +int 0 +load 7 +setbyte +concat +byte 0x00 +int 0 +load 8 +setbyte +concat +byte 0x00 +int 0 +load 9 +setbyte +concat +byte 0x00 +int 0 +load 10 +setbyte +concat +byte 0x00 +int 0 +load 11 +setbyte +concat +byte 0x00 +int 0 +load 12 +setbyte +concat +byte 0x00 +int 0 +load 13 +setbyte +concat +byte 0x00 +int 0 +load 14 +setbyte +concat +byte 0x00 +int 0 +load 15 +setbyte +concat +byte 0x00 +int 0 +load 16 +setbyte +concat +byte 0x00 +int 0 +load 17 +setbyte +concat +byte 0x00 +int 0 +load 18 +setbyte +concat +byte 0x00 +int 0 +load 19 +setbyte +concat +byte 0x00 +int 0 +load 20 +setbyte +concat +byte 0x00 +int 0 +load 21 +setbyte +concat +byte 0x00 +int 0 +load 22 +setbyte +concat +byte 0x00 +int 0 +load 23 +setbyte +concat +byte 0x00 +int 0 +load 24 +setbyte +concat +byte 0x00 +int 0 +load 25 +setbyte +concat +byte 0x00 +int 0 +load 26 +setbyte +concat +byte 0x00 +int 0 +load 27 +setbyte +concat +byte 0x00 +int 0 +load 28 +setbyte +concat +byte 0x00 +int 0 +load 29 +setbyte +concat +byte 0x00 +int 0 +load 30 +setbyte +concat +byte 0x00 +int 0 +load 31 +setbyte +concat +byte 0x00 +int 0 +load 32 +setbyte +concat +byte 0x00 +int 0 +load 33 +setbyte +concat +byte 0x00 +int 0 +load 34 +setbyte +concat +byte 0x00 +int 0 +load 35 +setbyte +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_2: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_1 +store 2 +load 2 +callsub arraycomplement_1 +store 3 +frame_dig -1 +load 2 +concat +load 3 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v8.teal new file mode 100644 index 000000000..065807402 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v8.teal @@ -0,0 +1,62 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_2 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// bool_comp +boolcomp_0: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_1: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbit +store 4 +load 4 +callsub boolcomp_0 +store 4 +byte 0x00 +int 0 +load 4 +setbit +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_2: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_1 +store 2 +load 2 +callsub arraycomplement_1 +store 3 +frame_dig -1 +load 2 +concat +load 3 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v8.teal new file mode 100644 index 000000000..3f5d168b2 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v8.teal @@ -0,0 +1,297 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_3 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// bool_comp +boolcomp_0: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_1: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbit +store 20 +frame_dig -1 +int 1 +getbit +store 21 +frame_dig -1 +int 2 +getbit +store 22 +load 20 +callsub boolcomp_0 +store 20 +load 21 +callsub boolcomp_0 +store 21 +load 22 +callsub boolcomp_0 +store 22 +byte 0x00 +int 0 +load 20 +setbit +int 1 +load 21 +setbit +int 2 +load 22 +setbit +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_2: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +int 2 ++ +int 1 +extract3 +store 8 +frame_dig -1 +int 1 +int 1 +* +int 2 ++ +int 1 +extract3 +store 9 +frame_dig -1 +int 1 +int 2 +* +int 2 ++ +int 1 +extract3 +store 10 +frame_dig -1 +int 1 +int 3 +* +int 2 ++ +int 1 +extract3 +store 11 +frame_dig -1 +int 1 +int 4 +* +int 2 ++ +int 1 +extract3 +store 12 +frame_dig -1 +int 1 +int 5 +* +int 2 ++ +int 1 +extract3 +store 13 +frame_dig -1 +int 1 +int 6 +* +int 2 ++ +int 1 +extract3 +store 14 +frame_dig -1 +int 1 +int 7 +* +int 2 ++ +int 1 +extract3 +store 15 +frame_dig -1 +int 1 +int 8 +* +int 2 ++ +int 1 +extract3 +store 16 +frame_dig -1 +int 1 +int 9 +* +int 2 ++ +int 1 +extract3 +store 17 +frame_dig -1 +int 1 +int 10 +* +int 2 ++ +int 1 +extract3 +store 18 +load 8 +callsub arraycomplement_1 +store 8 +load 9 +callsub arraycomplement_1 +store 9 +load 10 +callsub arraycomplement_1 +store 10 +load 11 +callsub arraycomplement_1 +store 11 +load 12 +callsub arraycomplement_1 +store 12 +load 13 +callsub arraycomplement_1 +store 13 +load 14 +callsub arraycomplement_1 +store 14 +load 15 +callsub arraycomplement_1 +store 15 +load 16 +callsub arraycomplement_1 +store 16 +load 17 +callsub arraycomplement_1 +store 17 +load 18 +callsub arraycomplement_1 +store 18 +int 11 +store 19 +load 19 +itob +extract 6 0 +load 8 +load 9 +concat +load 10 +concat +load 11 +concat +load 12 +concat +load 13 +concat +load 14 +concat +load 15 +concat +load 16 +concat +load 17 +concat +load 18 +concat +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_3: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_2 +store 2 +load 2 +callsub arraycomplement_2 +store 3 +frame_dig -1 +store 7 +load 7 +store 6 +int 6 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +load 2 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +concat +load 3 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +itob +extract 6 0 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v8.teal new file mode 100644 index 000000000..20e422692 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v8.teal @@ -0,0 +1,472 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_2 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// bool_comp +boolcomp_0: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_1: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +getbit +store 4 +frame_dig -1 +int 1 +getbit +store 5 +frame_dig -1 +int 2 +getbit +store 6 +frame_dig -1 +int 3 +getbit +store 7 +frame_dig -1 +int 4 +getbit +store 8 +frame_dig -1 +int 5 +getbit +store 9 +frame_dig -1 +int 6 +getbit +store 10 +frame_dig -1 +int 7 +getbit +store 11 +frame_dig -1 +int 8 +getbit +store 12 +frame_dig -1 +int 9 +getbit +store 13 +frame_dig -1 +int 10 +getbit +store 14 +frame_dig -1 +int 11 +getbit +store 15 +frame_dig -1 +int 12 +getbit +store 16 +frame_dig -1 +int 13 +getbit +store 17 +frame_dig -1 +int 14 +getbit +store 18 +frame_dig -1 +int 15 +getbit +store 19 +frame_dig -1 +int 16 +getbit +store 20 +frame_dig -1 +int 17 +getbit +store 21 +frame_dig -1 +int 18 +getbit +store 22 +frame_dig -1 +int 19 +getbit +store 23 +frame_dig -1 +int 20 +getbit +store 24 +frame_dig -1 +int 21 +getbit +store 25 +frame_dig -1 +int 22 +getbit +store 26 +frame_dig -1 +int 23 +getbit +store 27 +frame_dig -1 +int 24 +getbit +store 28 +frame_dig -1 +int 25 +getbit +store 29 +frame_dig -1 +int 26 +getbit +store 30 +frame_dig -1 +int 27 +getbit +store 31 +frame_dig -1 +int 28 +getbit +store 32 +frame_dig -1 +int 29 +getbit +store 33 +frame_dig -1 +int 30 +getbit +store 34 +frame_dig -1 +int 31 +getbit +store 35 +frame_dig -1 +int 32 +getbit +store 36 +frame_dig -1 +int 33 +getbit +store 37 +frame_dig -1 +int 34 +getbit +store 38 +frame_dig -1 +int 35 +getbit +store 39 +frame_dig -1 +int 36 +getbit +store 40 +frame_dig -1 +int 37 +getbit +store 41 +frame_dig -1 +int 38 +getbit +store 42 +frame_dig -1 +int 39 +getbit +store 43 +frame_dig -1 +int 40 +getbit +store 44 +frame_dig -1 +int 41 +getbit +store 45 +load 4 +callsub boolcomp_0 +store 4 +load 5 +callsub boolcomp_0 +store 5 +load 6 +callsub boolcomp_0 +store 6 +load 7 +callsub boolcomp_0 +store 7 +load 8 +callsub boolcomp_0 +store 8 +load 9 +callsub boolcomp_0 +store 9 +load 10 +callsub boolcomp_0 +store 10 +load 11 +callsub boolcomp_0 +store 11 +load 12 +callsub boolcomp_0 +store 12 +load 13 +callsub boolcomp_0 +store 13 +load 14 +callsub boolcomp_0 +store 14 +load 15 +callsub boolcomp_0 +store 15 +load 16 +callsub boolcomp_0 +store 16 +load 17 +callsub boolcomp_0 +store 17 +load 18 +callsub boolcomp_0 +store 18 +load 19 +callsub boolcomp_0 +store 19 +load 20 +callsub boolcomp_0 +store 20 +load 21 +callsub boolcomp_0 +store 21 +load 22 +callsub boolcomp_0 +store 22 +load 23 +callsub boolcomp_0 +store 23 +load 24 +callsub boolcomp_0 +store 24 +load 25 +callsub boolcomp_0 +store 25 +load 26 +callsub boolcomp_0 +store 26 +load 27 +callsub boolcomp_0 +store 27 +load 28 +callsub boolcomp_0 +store 28 +load 29 +callsub boolcomp_0 +store 29 +load 30 +callsub boolcomp_0 +store 30 +load 31 +callsub boolcomp_0 +store 31 +load 32 +callsub boolcomp_0 +store 32 +load 33 +callsub boolcomp_0 +store 33 +load 34 +callsub boolcomp_0 +store 34 +load 35 +callsub boolcomp_0 +store 35 +load 36 +callsub boolcomp_0 +store 36 +load 37 +callsub boolcomp_0 +store 37 +load 38 +callsub boolcomp_0 +store 38 +load 39 +callsub boolcomp_0 +store 39 +load 40 +callsub boolcomp_0 +store 40 +load 41 +callsub boolcomp_0 +store 41 +load 42 +callsub boolcomp_0 +store 42 +load 43 +callsub boolcomp_0 +store 43 +load 44 +callsub boolcomp_0 +store 44 +load 45 +callsub boolcomp_0 +store 45 +byte 0x000000000000 +int 0 +load 4 +setbit +int 1 +load 5 +setbit +int 2 +load 6 +setbit +int 3 +load 7 +setbit +int 4 +load 8 +setbit +int 5 +load 9 +setbit +int 6 +load 10 +setbit +int 7 +load 11 +setbit +int 8 +load 12 +setbit +int 9 +load 13 +setbit +int 10 +load 14 +setbit +int 11 +load 15 +setbit +int 12 +load 16 +setbit +int 13 +load 17 +setbit +int 14 +load 18 +setbit +int 15 +load 19 +setbit +int 16 +load 20 +setbit +int 17 +load 21 +setbit +int 18 +load 22 +setbit +int 19 +load 23 +setbit +int 20 +load 24 +setbit +int 21 +load 25 +setbit +int 22 +load 26 +setbit +int 23 +load 27 +setbit +int 24 +load 28 +setbit +int 25 +load 29 +setbit +int 26 +load 30 +setbit +int 27 +load 31 +setbit +int 28 +load 32 +setbit +int 29 +load 33 +setbit +int 30 +load 34 +setbit +int 31 +load 35 +setbit +int 32 +load 36 +setbit +int 33 +load 37 +setbit +int 34 +load 38 +setbit +int 35 +load 39 +setbit +int 36 +load 40 +setbit +int 37 +load 41 +setbit +int 38 +load 42 +setbit +int 39 +load 43 +setbit +int 40 +load 44 +setbit +int 41 +load 45 +setbit +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_2: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_1 +store 2 +load 2 +callsub arraycomplement_1 +store 3 +frame_dig -1 +load 2 +concat +load 3 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v8.teal new file mode 100644 index 000000000..542046cc4 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v8.teal @@ -0,0 +1,94 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_1 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// array_complement +arraycomplement_0: +proto 1 1 +int 13634846 +int 0 +store 8 +load 8 +itob +extract 6 0 +byte "" +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_0 +store 2 +load 2 +callsub arraycomplement_0 +store 3 +frame_dig -1 +store 7 +load 7 +store 6 +int 6 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +load 2 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +concat +load 3 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +itob +extract 6 0 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v8.teal new file mode 100644 index 000000000..879b7adb5 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v8.teal @@ -0,0 +1,118 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_2 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// bool_comp +boolcomp_0: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_1: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +int 16 ++ +getbit +store 8 +load 8 +callsub boolcomp_0 +store 8 +int 1 +store 9 +load 9 +itob +extract 6 0 +byte 0x00 +int 0 +load 8 +setbit +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_2: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_1 +store 2 +load 2 +callsub arraycomplement_1 +store 3 +frame_dig -1 +store 7 +load 7 +store 6 +int 6 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +load 2 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +concat +load 3 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +itob +extract 6 0 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v8.teal new file mode 100644 index 000000000..34f1528fe --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v8.teal @@ -0,0 +1,610 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_2 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// bool_comp +boolcomp_0: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_1: +proto 1 1 +int 13634846 +frame_dig -1 +int 0 +int 16 ++ +getbit +store 8 +frame_dig -1 +int 1 +int 16 ++ +getbit +store 9 +frame_dig -1 +int 2 +int 16 ++ +getbit +store 10 +frame_dig -1 +int 3 +int 16 ++ +getbit +store 11 +frame_dig -1 +int 4 +int 16 ++ +getbit +store 12 +frame_dig -1 +int 5 +int 16 ++ +getbit +store 13 +frame_dig -1 +int 6 +int 16 ++ +getbit +store 14 +frame_dig -1 +int 7 +int 16 ++ +getbit +store 15 +frame_dig -1 +int 8 +int 16 ++ +getbit +store 16 +frame_dig -1 +int 9 +int 16 ++ +getbit +store 17 +frame_dig -1 +int 10 +int 16 ++ +getbit +store 18 +frame_dig -1 +int 11 +int 16 ++ +getbit +store 19 +frame_dig -1 +int 12 +int 16 ++ +getbit +store 20 +frame_dig -1 +int 13 +int 16 ++ +getbit +store 21 +frame_dig -1 +int 14 +int 16 ++ +getbit +store 22 +frame_dig -1 +int 15 +int 16 ++ +getbit +store 23 +frame_dig -1 +int 16 +int 16 ++ +getbit +store 24 +frame_dig -1 +int 17 +int 16 ++ +getbit +store 25 +frame_dig -1 +int 18 +int 16 ++ +getbit +store 26 +frame_dig -1 +int 19 +int 16 ++ +getbit +store 27 +frame_dig -1 +int 20 +int 16 ++ +getbit +store 28 +frame_dig -1 +int 21 +int 16 ++ +getbit +store 29 +frame_dig -1 +int 22 +int 16 ++ +getbit +store 30 +frame_dig -1 +int 23 +int 16 ++ +getbit +store 31 +frame_dig -1 +int 24 +int 16 ++ +getbit +store 32 +frame_dig -1 +int 25 +int 16 ++ +getbit +store 33 +frame_dig -1 +int 26 +int 16 ++ +getbit +store 34 +frame_dig -1 +int 27 +int 16 ++ +getbit +store 35 +frame_dig -1 +int 28 +int 16 ++ +getbit +store 36 +frame_dig -1 +int 29 +int 16 ++ +getbit +store 37 +frame_dig -1 +int 30 +int 16 ++ +getbit +store 38 +frame_dig -1 +int 31 +int 16 ++ +getbit +store 39 +frame_dig -1 +int 32 +int 16 ++ +getbit +store 40 +frame_dig -1 +int 33 +int 16 ++ +getbit +store 41 +frame_dig -1 +int 34 +int 16 ++ +getbit +store 42 +frame_dig -1 +int 35 +int 16 ++ +getbit +store 43 +frame_dig -1 +int 36 +int 16 ++ +getbit +store 44 +frame_dig -1 +int 37 +int 16 ++ +getbit +store 45 +frame_dig -1 +int 38 +int 16 ++ +getbit +store 46 +frame_dig -1 +int 39 +int 16 ++ +getbit +store 47 +frame_dig -1 +int 40 +int 16 ++ +getbit +store 48 +frame_dig -1 +int 41 +int 16 ++ +getbit +store 49 +load 8 +callsub boolcomp_0 +store 8 +load 9 +callsub boolcomp_0 +store 9 +load 10 +callsub boolcomp_0 +store 10 +load 11 +callsub boolcomp_0 +store 11 +load 12 +callsub boolcomp_0 +store 12 +load 13 +callsub boolcomp_0 +store 13 +load 14 +callsub boolcomp_0 +store 14 +load 15 +callsub boolcomp_0 +store 15 +load 16 +callsub boolcomp_0 +store 16 +load 17 +callsub boolcomp_0 +store 17 +load 18 +callsub boolcomp_0 +store 18 +load 19 +callsub boolcomp_0 +store 19 +load 20 +callsub boolcomp_0 +store 20 +load 21 +callsub boolcomp_0 +store 21 +load 22 +callsub boolcomp_0 +store 22 +load 23 +callsub boolcomp_0 +store 23 +load 24 +callsub boolcomp_0 +store 24 +load 25 +callsub boolcomp_0 +store 25 +load 26 +callsub boolcomp_0 +store 26 +load 27 +callsub boolcomp_0 +store 27 +load 28 +callsub boolcomp_0 +store 28 +load 29 +callsub boolcomp_0 +store 29 +load 30 +callsub boolcomp_0 +store 30 +load 31 +callsub boolcomp_0 +store 31 +load 32 +callsub boolcomp_0 +store 32 +load 33 +callsub boolcomp_0 +store 33 +load 34 +callsub boolcomp_0 +store 34 +load 35 +callsub boolcomp_0 +store 35 +load 36 +callsub boolcomp_0 +store 36 +load 37 +callsub boolcomp_0 +store 37 +load 38 +callsub boolcomp_0 +store 38 +load 39 +callsub boolcomp_0 +store 39 +load 40 +callsub boolcomp_0 +store 40 +load 41 +callsub boolcomp_0 +store 41 +load 42 +callsub boolcomp_0 +store 42 +load 43 +callsub boolcomp_0 +store 43 +load 44 +callsub boolcomp_0 +store 44 +load 45 +callsub boolcomp_0 +store 45 +load 46 +callsub boolcomp_0 +store 46 +load 47 +callsub boolcomp_0 +store 47 +load 48 +callsub boolcomp_0 +store 48 +load 49 +callsub boolcomp_0 +store 49 +int 42 +store 50 +load 50 +itob +extract 6 0 +byte 0x000000000000 +int 0 +load 8 +setbit +int 1 +load 9 +setbit +int 2 +load 10 +setbit +int 3 +load 11 +setbit +int 4 +load 12 +setbit +int 5 +load 13 +setbit +int 6 +load 14 +setbit +int 7 +load 15 +setbit +int 8 +load 16 +setbit +int 9 +load 17 +setbit +int 10 +load 18 +setbit +int 11 +load 19 +setbit +int 12 +load 20 +setbit +int 13 +load 21 +setbit +int 14 +load 22 +setbit +int 15 +load 23 +setbit +int 16 +load 24 +setbit +int 17 +load 25 +setbit +int 18 +load 26 +setbit +int 19 +load 27 +setbit +int 20 +load 28 +setbit +int 21 +load 29 +setbit +int 22 +load 30 +setbit +int 23 +load 31 +setbit +int 24 +load 32 +setbit +int 25 +load 33 +setbit +int 26 +load 34 +setbit +int 27 +load 35 +setbit +int 28 +load 36 +setbit +int 29 +load 37 +setbit +int 30 +load 38 +setbit +int 31 +load 39 +setbit +int 32 +load 40 +setbit +int 33 +load 41 +setbit +int 34 +load 42 +setbit +int 35 +load 43 +setbit +int 36 +load 44 +setbit +int 37 +load 45 +setbit +int 38 +load 46 +setbit +int 39 +load 47 +setbit +int 40 +load 48 +setbit +int 41 +load 49 +setbit +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_2: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_1 +store 2 +load 2 +callsub arraycomplement_1 +store 3 +frame_dig -1 +store 7 +load 7 +store 6 +int 6 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +load 2 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +concat +load 3 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +itob +extract 6 0 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool_v8.teal new file mode 100644 index 000000000..1e8311ecf --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool_v8.teal @@ -0,0 +1,52 @@ +#pragma version 8 +txna ApplicationArgs 0 +int 0 +int 8 +* +getbit +store 1 +load 1 +callsub roundtripper_1 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// bool_comp +boolcomp_0: +proto 1 1 +int 13634846 +frame_dig -1 +! +! +! +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub boolcomp_0 +store 2 +load 2 +callsub boolcomp_0 +store 3 +byte 0x00 +int 0 +frame_dig -1 +setbit +int 1 +load 2 +setbit +int 2 +load 3 +setbit +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v8.teal new file mode 100644 index 000000000..f96c0c3b4 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v8.teal @@ -0,0 +1,277 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_2 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// numerical_comp +numericalcomp_0: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// array_complement +arraycomplement_1: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +getbyte +store 4 +frame_dig -1 +int 1 +int 1 +* +getbyte +store 5 +frame_dig -1 +int 1 +int 2 +* +getbyte +store 6 +frame_dig -1 +int 1 +int 3 +* +getbyte +store 7 +frame_dig -1 +int 1 +int 4 +* +getbyte +store 8 +frame_dig -1 +int 1 +int 5 +* +getbyte +store 9 +frame_dig -1 +int 1 +int 6 +* +getbyte +store 10 +frame_dig -1 +int 1 +int 7 +* +getbyte +store 11 +frame_dig -1 +int 1 +int 8 +* +getbyte +store 12 +frame_dig -1 +int 1 +int 9 +* +getbyte +store 13 +frame_dig -1 +int 1 +int 10 +* +getbyte +store 14 +frame_dig -1 +int 1 +int 11 +* +getbyte +store 15 +frame_dig -1 +int 1 +int 12 +* +getbyte +store 16 +frame_dig -1 +int 1 +int 13 +* +getbyte +store 17 +frame_dig -1 +int 1 +int 14 +* +getbyte +store 18 +frame_dig -1 +int 1 +int 15 +* +getbyte +store 19 +load 4 +callsub numericalcomp_0 +store 4 +load 5 +callsub numericalcomp_0 +store 5 +load 6 +callsub numericalcomp_0 +store 6 +load 7 +callsub numericalcomp_0 +store 7 +load 8 +callsub numericalcomp_0 +store 8 +load 9 +callsub numericalcomp_0 +store 9 +load 10 +callsub numericalcomp_0 +store 10 +load 11 +callsub numericalcomp_0 +store 11 +load 12 +callsub numericalcomp_0 +store 12 +load 13 +callsub numericalcomp_0 +store 13 +load 14 +callsub numericalcomp_0 +store 14 +load 15 +callsub numericalcomp_0 +store 15 +load 16 +callsub numericalcomp_0 +store 16 +load 17 +callsub numericalcomp_0 +store 17 +load 18 +callsub numericalcomp_0 +store 18 +load 19 +callsub numericalcomp_0 +store 19 +byte 0x00 +int 0 +load 4 +setbyte +byte 0x00 +int 0 +load 5 +setbyte +concat +byte 0x00 +int 0 +load 6 +setbyte +concat +byte 0x00 +int 0 +load 7 +setbyte +concat +byte 0x00 +int 0 +load 8 +setbyte +concat +byte 0x00 +int 0 +load 9 +setbyte +concat +byte 0x00 +int 0 +load 10 +setbyte +concat +byte 0x00 +int 0 +load 11 +setbyte +concat +byte 0x00 +int 0 +load 12 +setbyte +concat +byte 0x00 +int 0 +load 13 +setbyte +concat +byte 0x00 +int 0 +load 14 +setbyte +concat +byte 0x00 +int 0 +load 15 +setbyte +concat +byte 0x00 +int 0 +load 16 +setbyte +concat +byte 0x00 +int 0 +load 17 +setbyte +concat +byte 0x00 +int 0 +load 18 +setbyte +concat +byte 0x00 +int 0 +load 19 +setbyte +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_2: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_1 +store 2 +load 2 +callsub arraycomplement_1 +store 3 +frame_dig -1 +load 2 +concat +load 3 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v8.teal new file mode 100644 index 000000000..9cab660b5 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v8.teal @@ -0,0 +1,683 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_2 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// numerical_comp +numericalcomp_0: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// array_complement +arraycomplement_1: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +int 2 ++ +getbyte +store 8 +frame_dig -1 +int 1 +int 1 +* +int 2 ++ +getbyte +store 9 +frame_dig -1 +int 1 +int 2 +* +int 2 ++ +getbyte +store 10 +frame_dig -1 +int 1 +int 3 +* +int 2 ++ +getbyte +store 11 +frame_dig -1 +int 1 +int 4 +* +int 2 ++ +getbyte +store 12 +frame_dig -1 +int 1 +int 5 +* +int 2 ++ +getbyte +store 13 +frame_dig -1 +int 1 +int 6 +* +int 2 ++ +getbyte +store 14 +frame_dig -1 +int 1 +int 7 +* +int 2 ++ +getbyte +store 15 +frame_dig -1 +int 1 +int 8 +* +int 2 ++ +getbyte +store 16 +frame_dig -1 +int 1 +int 9 +* +int 2 ++ +getbyte +store 17 +frame_dig -1 +int 1 +int 10 +* +int 2 ++ +getbyte +store 18 +frame_dig -1 +int 1 +int 11 +* +int 2 ++ +getbyte +store 19 +frame_dig -1 +int 1 +int 12 +* +int 2 ++ +getbyte +store 20 +frame_dig -1 +int 1 +int 13 +* +int 2 ++ +getbyte +store 21 +frame_dig -1 +int 1 +int 14 +* +int 2 ++ +getbyte +store 22 +frame_dig -1 +int 1 +int 15 +* +int 2 ++ +getbyte +store 23 +frame_dig -1 +int 1 +int 16 +* +int 2 ++ +getbyte +store 24 +frame_dig -1 +int 1 +int 17 +* +int 2 ++ +getbyte +store 25 +frame_dig -1 +int 1 +int 18 +* +int 2 ++ +getbyte +store 26 +frame_dig -1 +int 1 +int 19 +* +int 2 ++ +getbyte +store 27 +frame_dig -1 +int 1 +int 20 +* +int 2 ++ +getbyte +store 28 +frame_dig -1 +int 1 +int 21 +* +int 2 ++ +getbyte +store 29 +frame_dig -1 +int 1 +int 22 +* +int 2 ++ +getbyte +store 30 +frame_dig -1 +int 1 +int 23 +* +int 2 ++ +getbyte +store 31 +frame_dig -1 +int 1 +int 24 +* +int 2 ++ +getbyte +store 32 +frame_dig -1 +int 1 +int 25 +* +int 2 ++ +getbyte +store 33 +frame_dig -1 +int 1 +int 26 +* +int 2 ++ +getbyte +store 34 +frame_dig -1 +int 1 +int 27 +* +int 2 ++ +getbyte +store 35 +frame_dig -1 +int 1 +int 28 +* +int 2 ++ +getbyte +store 36 +frame_dig -1 +int 1 +int 29 +* +int 2 ++ +getbyte +store 37 +frame_dig -1 +int 1 +int 30 +* +int 2 ++ +getbyte +store 38 +frame_dig -1 +int 1 +int 31 +* +int 2 ++ +getbyte +store 39 +frame_dig -1 +int 1 +int 32 +* +int 2 ++ +getbyte +store 40 +frame_dig -1 +int 1 +int 33 +* +int 2 ++ +getbyte +store 41 +frame_dig -1 +int 1 +int 34 +* +int 2 ++ +getbyte +store 42 +frame_dig -1 +int 1 +int 35 +* +int 2 ++ +getbyte +store 43 +load 8 +callsub numericalcomp_0 +store 8 +load 9 +callsub numericalcomp_0 +store 9 +load 10 +callsub numericalcomp_0 +store 10 +load 11 +callsub numericalcomp_0 +store 11 +load 12 +callsub numericalcomp_0 +store 12 +load 13 +callsub numericalcomp_0 +store 13 +load 14 +callsub numericalcomp_0 +store 14 +load 15 +callsub numericalcomp_0 +store 15 +load 16 +callsub numericalcomp_0 +store 16 +load 17 +callsub numericalcomp_0 +store 17 +load 18 +callsub numericalcomp_0 +store 18 +load 19 +callsub numericalcomp_0 +store 19 +load 20 +callsub numericalcomp_0 +store 20 +load 21 +callsub numericalcomp_0 +store 21 +load 22 +callsub numericalcomp_0 +store 22 +load 23 +callsub numericalcomp_0 +store 23 +load 24 +callsub numericalcomp_0 +store 24 +load 25 +callsub numericalcomp_0 +store 25 +load 26 +callsub numericalcomp_0 +store 26 +load 27 +callsub numericalcomp_0 +store 27 +load 28 +callsub numericalcomp_0 +store 28 +load 29 +callsub numericalcomp_0 +store 29 +load 30 +callsub numericalcomp_0 +store 30 +load 31 +callsub numericalcomp_0 +store 31 +load 32 +callsub numericalcomp_0 +store 32 +load 33 +callsub numericalcomp_0 +store 33 +load 34 +callsub numericalcomp_0 +store 34 +load 35 +callsub numericalcomp_0 +store 35 +load 36 +callsub numericalcomp_0 +store 36 +load 37 +callsub numericalcomp_0 +store 37 +load 38 +callsub numericalcomp_0 +store 38 +load 39 +callsub numericalcomp_0 +store 39 +load 40 +callsub numericalcomp_0 +store 40 +load 41 +callsub numericalcomp_0 +store 41 +load 42 +callsub numericalcomp_0 +store 42 +load 43 +callsub numericalcomp_0 +store 43 +int 36 +store 44 +load 44 +itob +extract 6 0 +byte 0x00 +int 0 +load 8 +setbyte +byte 0x00 +int 0 +load 9 +setbyte +concat +byte 0x00 +int 0 +load 10 +setbyte +concat +byte 0x00 +int 0 +load 11 +setbyte +concat +byte 0x00 +int 0 +load 12 +setbyte +concat +byte 0x00 +int 0 +load 13 +setbyte +concat +byte 0x00 +int 0 +load 14 +setbyte +concat +byte 0x00 +int 0 +load 15 +setbyte +concat +byte 0x00 +int 0 +load 16 +setbyte +concat +byte 0x00 +int 0 +load 17 +setbyte +concat +byte 0x00 +int 0 +load 18 +setbyte +concat +byte 0x00 +int 0 +load 19 +setbyte +concat +byte 0x00 +int 0 +load 20 +setbyte +concat +byte 0x00 +int 0 +load 21 +setbyte +concat +byte 0x00 +int 0 +load 22 +setbyte +concat +byte 0x00 +int 0 +load 23 +setbyte +concat +byte 0x00 +int 0 +load 24 +setbyte +concat +byte 0x00 +int 0 +load 25 +setbyte +concat +byte 0x00 +int 0 +load 26 +setbyte +concat +byte 0x00 +int 0 +load 27 +setbyte +concat +byte 0x00 +int 0 +load 28 +setbyte +concat +byte 0x00 +int 0 +load 29 +setbyte +concat +byte 0x00 +int 0 +load 30 +setbyte +concat +byte 0x00 +int 0 +load 31 +setbyte +concat +byte 0x00 +int 0 +load 32 +setbyte +concat +byte 0x00 +int 0 +load 33 +setbyte +concat +byte 0x00 +int 0 +load 34 +setbyte +concat +byte 0x00 +int 0 +load 35 +setbyte +concat +byte 0x00 +int 0 +load 36 +setbyte +concat +byte 0x00 +int 0 +load 37 +setbyte +concat +byte 0x00 +int 0 +load 38 +setbyte +concat +byte 0x00 +int 0 +load 39 +setbyte +concat +byte 0x00 +int 0 +load 40 +setbyte +concat +byte 0x00 +int 0 +load 41 +setbyte +concat +byte 0x00 +int 0 +load 42 +setbyte +concat +byte 0x00 +int 0 +load 43 +setbyte +concat +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_2: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_1 +store 2 +load 2 +callsub arraycomplement_1 +store 3 +frame_dig -1 +store 7 +load 7 +store 6 +int 6 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +load 2 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +concat +load 3 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +itob +extract 6 0 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_byte_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_byte_v8.teal new file mode 100644 index 000000000..5fcfe7e85 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_byte_v8.teal @@ -0,0 +1,57 @@ +#pragma version 8 +txna ApplicationArgs 0 +int 0 +getbyte +store 1 +load 1 +callsub roundtripper_1 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// numerical_comp +numericalcomp_0: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub numericalcomp_0 +store 2 +load 2 +callsub numericalcomp_0 +store 3 +byte 0x00 +int 0 +frame_dig -1 +setbyte +byte 0x00 +int 0 +load 2 +setbyte +concat +byte 0x00 +int 0 +load 3 +setbyte +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_0_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_0_v8.teal new file mode 100644 index 000000000..68dbf97f6 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_string_0_v8.teal @@ -0,0 +1,94 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_1 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// string_reverse +stringreverse_0: +proto 1 1 +int 13634846 +int 0 +store 8 +load 8 +itob +extract 6 0 +byte "" +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub stringreverse_0 +store 2 +load 2 +callsub stringreverse_0 +store 3 +frame_dig -1 +store 7 +load 7 +store 6 +int 6 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +load 2 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +concat +load 3 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +itob +extract 6 0 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_13_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_13_v8.teal new file mode 100644 index 000000000..0b7ef9286 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_string_13_v8.teal @@ -0,0 +1,261 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_1 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// string_reverse +stringreverse_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +int 2 ++ +getbyte +store 20 +frame_dig -1 +int 1 +int 1 +* +int 2 ++ +getbyte +store 19 +frame_dig -1 +int 1 +int 2 +* +int 2 ++ +getbyte +store 18 +frame_dig -1 +int 1 +int 3 +* +int 2 ++ +getbyte +store 17 +frame_dig -1 +int 1 +int 4 +* +int 2 ++ +getbyte +store 16 +frame_dig -1 +int 1 +int 5 +* +int 2 ++ +getbyte +store 15 +frame_dig -1 +int 1 +int 6 +* +int 2 ++ +getbyte +store 14 +frame_dig -1 +int 1 +int 7 +* +int 2 ++ +getbyte +store 13 +frame_dig -1 +int 1 +int 8 +* +int 2 ++ +getbyte +store 12 +frame_dig -1 +int 1 +int 9 +* +int 2 ++ +getbyte +store 11 +frame_dig -1 +int 1 +int 10 +* +int 2 ++ +getbyte +store 10 +frame_dig -1 +int 1 +int 11 +* +int 2 ++ +getbyte +store 9 +frame_dig -1 +int 1 +int 12 +* +int 2 ++ +getbyte +store 8 +int 13 +store 21 +load 21 +itob +extract 6 0 +byte 0x00 +int 0 +load 8 +setbyte +byte 0x00 +int 0 +load 9 +setbyte +concat +byte 0x00 +int 0 +load 10 +setbyte +concat +byte 0x00 +int 0 +load 11 +setbyte +concat +byte 0x00 +int 0 +load 12 +setbyte +concat +byte 0x00 +int 0 +load 13 +setbyte +concat +byte 0x00 +int 0 +load 14 +setbyte +concat +byte 0x00 +int 0 +load 15 +setbyte +concat +byte 0x00 +int 0 +load 16 +setbyte +concat +byte 0x00 +int 0 +load 17 +setbyte +concat +byte 0x00 +int 0 +load 18 +setbyte +concat +byte 0x00 +int 0 +load 19 +setbyte +concat +byte 0x00 +int 0 +load 20 +setbyte +concat +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub stringreverse_0 +store 2 +load 2 +callsub stringreverse_0 +store 3 +frame_dig -1 +store 7 +load 7 +store 6 +int 6 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +load 2 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +concat +load 3 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +itob +extract 6 0 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_1_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_1_v8.teal new file mode 100644 index 000000000..453a7cdb9 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_string_1_v8.teal @@ -0,0 +1,105 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_1 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// string_reverse +stringreverse_0: +proto 1 1 +int 13634846 +frame_dig -1 +int 1 +int 0 +* +int 2 ++ +getbyte +store 8 +int 1 +store 9 +load 9 +itob +extract 6 0 +byte 0x00 +int 0 +load 8 +setbyte +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub stringreverse_0 +store 2 +load 2 +callsub stringreverse_0 +store 3 +frame_dig -1 +store 7 +load 7 +store 6 +int 6 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +load 2 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +concat +load 3 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +itob +extract 6 0 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint16_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint16_v8.teal new file mode 100644 index 000000000..b307d4c40 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint16_v8.teal @@ -0,0 +1,54 @@ +#pragma version 8 +txna ApplicationArgs 0 +int 0 +extract_uint16 +store 1 +load 1 +callsub roundtripper_1 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// numerical_comp +numericalcomp_0: +proto 1 1 +int 13634846 +int 65535 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 65536 +< +assert +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub numericalcomp_0 +store 2 +load 2 +callsub numericalcomp_0 +store 3 +frame_dig -1 +itob +extract 6 0 +load 2 +itob +extract 6 0 +concat +load 3 +itob +extract 6 0 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint32_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint32_v8.teal new file mode 100644 index 000000000..1cb435373 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint32_v8.teal @@ -0,0 +1,54 @@ +#pragma version 8 +txna ApplicationArgs 0 +int 0 +extract_uint32 +store 1 +load 1 +callsub roundtripper_1 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// numerical_comp +numericalcomp_0: +proto 1 1 +int 13634846 +int 4294967295 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 4294967296 +< +assert +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub numericalcomp_0 +store 2 +load 2 +callsub numericalcomp_0 +store 3 +frame_dig -1 +itob +extract 4 0 +load 2 +itob +extract 4 0 +concat +load 3 +itob +extract 4 0 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v8.teal new file mode 100644 index 000000000..19e3be236 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v8.teal @@ -0,0 +1,61 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_2 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// numerical_comp +numericalcomp_0: +proto 1 1 +int 13634846 +int 18446744073709551615 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_1: +proto 1 1 +int 13634846 +frame_dig -1 +int 8 +int 0 +* +extract_uint64 +store 4 +load 4 +callsub numericalcomp_0 +store 4 +load 4 +itob +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_2: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_1 +store 2 +load 2 +callsub arraycomplement_1 +store 3 +frame_dig -1 +load 2 +concat +load 3 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v8.teal new file mode 100644 index 000000000..6f93ba204 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v8.teal @@ -0,0 +1,553 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_2 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// numerical_comp +numericalcomp_0: +proto 1 1 +int 13634846 +int 18446744073709551615 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_1: +proto 1 1 +int 13634846 +frame_dig -1 +int 8 +int 0 +* +extract_uint64 +store 4 +frame_dig -1 +int 8 +int 1 +* +extract_uint64 +store 5 +frame_dig -1 +int 8 +int 2 +* +extract_uint64 +store 6 +frame_dig -1 +int 8 +int 3 +* +extract_uint64 +store 7 +frame_dig -1 +int 8 +int 4 +* +extract_uint64 +store 8 +frame_dig -1 +int 8 +int 5 +* +extract_uint64 +store 9 +frame_dig -1 +int 8 +int 6 +* +extract_uint64 +store 10 +frame_dig -1 +int 8 +int 7 +* +extract_uint64 +store 11 +frame_dig -1 +int 8 +int 8 +* +extract_uint64 +store 12 +frame_dig -1 +int 8 +int 9 +* +extract_uint64 +store 13 +frame_dig -1 +int 8 +int 10 +* +extract_uint64 +store 14 +frame_dig -1 +int 8 +int 11 +* +extract_uint64 +store 15 +frame_dig -1 +int 8 +int 12 +* +extract_uint64 +store 16 +frame_dig -1 +int 8 +int 13 +* +extract_uint64 +store 17 +frame_dig -1 +int 8 +int 14 +* +extract_uint64 +store 18 +frame_dig -1 +int 8 +int 15 +* +extract_uint64 +store 19 +frame_dig -1 +int 8 +int 16 +* +extract_uint64 +store 20 +frame_dig -1 +int 8 +int 17 +* +extract_uint64 +store 21 +frame_dig -1 +int 8 +int 18 +* +extract_uint64 +store 22 +frame_dig -1 +int 8 +int 19 +* +extract_uint64 +store 23 +frame_dig -1 +int 8 +int 20 +* +extract_uint64 +store 24 +frame_dig -1 +int 8 +int 21 +* +extract_uint64 +store 25 +frame_dig -1 +int 8 +int 22 +* +extract_uint64 +store 26 +frame_dig -1 +int 8 +int 23 +* +extract_uint64 +store 27 +frame_dig -1 +int 8 +int 24 +* +extract_uint64 +store 28 +frame_dig -1 +int 8 +int 25 +* +extract_uint64 +store 29 +frame_dig -1 +int 8 +int 26 +* +extract_uint64 +store 30 +frame_dig -1 +int 8 +int 27 +* +extract_uint64 +store 31 +frame_dig -1 +int 8 +int 28 +* +extract_uint64 +store 32 +frame_dig -1 +int 8 +int 29 +* +extract_uint64 +store 33 +frame_dig -1 +int 8 +int 30 +* +extract_uint64 +store 34 +frame_dig -1 +int 8 +int 31 +* +extract_uint64 +store 35 +frame_dig -1 +int 8 +int 32 +* +extract_uint64 +store 36 +frame_dig -1 +int 8 +int 33 +* +extract_uint64 +store 37 +frame_dig -1 +int 8 +int 34 +* +extract_uint64 +store 38 +frame_dig -1 +int 8 +int 35 +* +extract_uint64 +store 39 +frame_dig -1 +int 8 +int 36 +* +extract_uint64 +store 40 +frame_dig -1 +int 8 +int 37 +* +extract_uint64 +store 41 +frame_dig -1 +int 8 +int 38 +* +extract_uint64 +store 42 +frame_dig -1 +int 8 +int 39 +* +extract_uint64 +store 43 +frame_dig -1 +int 8 +int 40 +* +extract_uint64 +store 44 +frame_dig -1 +int 8 +int 41 +* +extract_uint64 +store 45 +load 4 +callsub numericalcomp_0 +store 4 +load 5 +callsub numericalcomp_0 +store 5 +load 6 +callsub numericalcomp_0 +store 6 +load 7 +callsub numericalcomp_0 +store 7 +load 8 +callsub numericalcomp_0 +store 8 +load 9 +callsub numericalcomp_0 +store 9 +load 10 +callsub numericalcomp_0 +store 10 +load 11 +callsub numericalcomp_0 +store 11 +load 12 +callsub numericalcomp_0 +store 12 +load 13 +callsub numericalcomp_0 +store 13 +load 14 +callsub numericalcomp_0 +store 14 +load 15 +callsub numericalcomp_0 +store 15 +load 16 +callsub numericalcomp_0 +store 16 +load 17 +callsub numericalcomp_0 +store 17 +load 18 +callsub numericalcomp_0 +store 18 +load 19 +callsub numericalcomp_0 +store 19 +load 20 +callsub numericalcomp_0 +store 20 +load 21 +callsub numericalcomp_0 +store 21 +load 22 +callsub numericalcomp_0 +store 22 +load 23 +callsub numericalcomp_0 +store 23 +load 24 +callsub numericalcomp_0 +store 24 +load 25 +callsub numericalcomp_0 +store 25 +load 26 +callsub numericalcomp_0 +store 26 +load 27 +callsub numericalcomp_0 +store 27 +load 28 +callsub numericalcomp_0 +store 28 +load 29 +callsub numericalcomp_0 +store 29 +load 30 +callsub numericalcomp_0 +store 30 +load 31 +callsub numericalcomp_0 +store 31 +load 32 +callsub numericalcomp_0 +store 32 +load 33 +callsub numericalcomp_0 +store 33 +load 34 +callsub numericalcomp_0 +store 34 +load 35 +callsub numericalcomp_0 +store 35 +load 36 +callsub numericalcomp_0 +store 36 +load 37 +callsub numericalcomp_0 +store 37 +load 38 +callsub numericalcomp_0 +store 38 +load 39 +callsub numericalcomp_0 +store 39 +load 40 +callsub numericalcomp_0 +store 40 +load 41 +callsub numericalcomp_0 +store 41 +load 42 +callsub numericalcomp_0 +store 42 +load 43 +callsub numericalcomp_0 +store 43 +load 44 +callsub numericalcomp_0 +store 44 +load 45 +callsub numericalcomp_0 +store 45 +load 4 +itob +load 5 +itob +concat +load 6 +itob +concat +load 7 +itob +concat +load 8 +itob +concat +load 9 +itob +concat +load 10 +itob +concat +load 11 +itob +concat +load 12 +itob +concat +load 13 +itob +concat +load 14 +itob +concat +load 15 +itob +concat +load 16 +itob +concat +load 17 +itob +concat +load 18 +itob +concat +load 19 +itob +concat +load 20 +itob +concat +load 21 +itob +concat +load 22 +itob +concat +load 23 +itob +concat +load 24 +itob +concat +load 25 +itob +concat +load 26 +itob +concat +load 27 +itob +concat +load 28 +itob +concat +load 29 +itob +concat +load 30 +itob +concat +load 31 +itob +concat +load 32 +itob +concat +load 33 +itob +concat +load 34 +itob +concat +load 35 +itob +concat +load 36 +itob +concat +load 37 +itob +concat +load 38 +itob +concat +load 39 +itob +concat +load 40 +itob +concat +load 41 +itob +concat +load 42 +itob +concat +load 43 +itob +concat +load 44 +itob +concat +load 45 +itob +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_2: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_1 +store 2 +load 2 +callsub arraycomplement_1 +store 3 +frame_dig -1 +load 2 +concat +load 3 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v8.teal new file mode 100644 index 000000000..542046cc4 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v8.teal @@ -0,0 +1,94 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_1 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// array_complement +arraycomplement_0: +proto 1 1 +int 13634846 +int 0 +store 8 +load 8 +itob +extract 6 0 +byte "" +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_0 +store 2 +load 2 +callsub arraycomplement_0 +store 3 +frame_dig -1 +store 7 +load 7 +store 6 +int 6 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +load 2 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +concat +load 3 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +itob +extract 6 0 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v8.teal new file mode 100644 index 000000000..4cc83c458 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v8.teal @@ -0,0 +1,117 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_2 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// numerical_comp +numericalcomp_0: +proto 1 1 +int 13634846 +int 18446744073709551615 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_1: +proto 1 1 +int 13634846 +frame_dig -1 +int 8 +int 0 +* +int 2 ++ +extract_uint64 +store 8 +load 8 +callsub numericalcomp_0 +store 8 +int 1 +store 9 +load 9 +itob +extract 6 0 +load 8 +itob +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_2: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_1 +store 2 +load 2 +callsub arraycomplement_1 +store 3 +frame_dig -1 +store 7 +load 7 +store 6 +int 6 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +load 2 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +concat +load 3 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +itob +extract 6 0 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v8.teal new file mode 100644 index 000000000..c3b990138 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v8.teal @@ -0,0 +1,691 @@ +#pragma version 8 +txna ApplicationArgs 0 +store 1 +load 1 +callsub roundtripper_2 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// numerical_comp +numericalcomp_0: +proto 1 1 +int 13634846 +int 18446744073709551615 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +retsub + +// array_complement +arraycomplement_1: +proto 1 1 +int 13634846 +frame_dig -1 +int 8 +int 0 +* +int 2 ++ +extract_uint64 +store 8 +frame_dig -1 +int 8 +int 1 +* +int 2 ++ +extract_uint64 +store 9 +frame_dig -1 +int 8 +int 2 +* +int 2 ++ +extract_uint64 +store 10 +frame_dig -1 +int 8 +int 3 +* +int 2 ++ +extract_uint64 +store 11 +frame_dig -1 +int 8 +int 4 +* +int 2 ++ +extract_uint64 +store 12 +frame_dig -1 +int 8 +int 5 +* +int 2 ++ +extract_uint64 +store 13 +frame_dig -1 +int 8 +int 6 +* +int 2 ++ +extract_uint64 +store 14 +frame_dig -1 +int 8 +int 7 +* +int 2 ++ +extract_uint64 +store 15 +frame_dig -1 +int 8 +int 8 +* +int 2 ++ +extract_uint64 +store 16 +frame_dig -1 +int 8 +int 9 +* +int 2 ++ +extract_uint64 +store 17 +frame_dig -1 +int 8 +int 10 +* +int 2 ++ +extract_uint64 +store 18 +frame_dig -1 +int 8 +int 11 +* +int 2 ++ +extract_uint64 +store 19 +frame_dig -1 +int 8 +int 12 +* +int 2 ++ +extract_uint64 +store 20 +frame_dig -1 +int 8 +int 13 +* +int 2 ++ +extract_uint64 +store 21 +frame_dig -1 +int 8 +int 14 +* +int 2 ++ +extract_uint64 +store 22 +frame_dig -1 +int 8 +int 15 +* +int 2 ++ +extract_uint64 +store 23 +frame_dig -1 +int 8 +int 16 +* +int 2 ++ +extract_uint64 +store 24 +frame_dig -1 +int 8 +int 17 +* +int 2 ++ +extract_uint64 +store 25 +frame_dig -1 +int 8 +int 18 +* +int 2 ++ +extract_uint64 +store 26 +frame_dig -1 +int 8 +int 19 +* +int 2 ++ +extract_uint64 +store 27 +frame_dig -1 +int 8 +int 20 +* +int 2 ++ +extract_uint64 +store 28 +frame_dig -1 +int 8 +int 21 +* +int 2 ++ +extract_uint64 +store 29 +frame_dig -1 +int 8 +int 22 +* +int 2 ++ +extract_uint64 +store 30 +frame_dig -1 +int 8 +int 23 +* +int 2 ++ +extract_uint64 +store 31 +frame_dig -1 +int 8 +int 24 +* +int 2 ++ +extract_uint64 +store 32 +frame_dig -1 +int 8 +int 25 +* +int 2 ++ +extract_uint64 +store 33 +frame_dig -1 +int 8 +int 26 +* +int 2 ++ +extract_uint64 +store 34 +frame_dig -1 +int 8 +int 27 +* +int 2 ++ +extract_uint64 +store 35 +frame_dig -1 +int 8 +int 28 +* +int 2 ++ +extract_uint64 +store 36 +frame_dig -1 +int 8 +int 29 +* +int 2 ++ +extract_uint64 +store 37 +frame_dig -1 +int 8 +int 30 +* +int 2 ++ +extract_uint64 +store 38 +frame_dig -1 +int 8 +int 31 +* +int 2 ++ +extract_uint64 +store 39 +frame_dig -1 +int 8 +int 32 +* +int 2 ++ +extract_uint64 +store 40 +frame_dig -1 +int 8 +int 33 +* +int 2 ++ +extract_uint64 +store 41 +frame_dig -1 +int 8 +int 34 +* +int 2 ++ +extract_uint64 +store 42 +frame_dig -1 +int 8 +int 35 +* +int 2 ++ +extract_uint64 +store 43 +frame_dig -1 +int 8 +int 36 +* +int 2 ++ +extract_uint64 +store 44 +frame_dig -1 +int 8 +int 37 +* +int 2 ++ +extract_uint64 +store 45 +frame_dig -1 +int 8 +int 38 +* +int 2 ++ +extract_uint64 +store 46 +frame_dig -1 +int 8 +int 39 +* +int 2 ++ +extract_uint64 +store 47 +frame_dig -1 +int 8 +int 40 +* +int 2 ++ +extract_uint64 +store 48 +frame_dig -1 +int 8 +int 41 +* +int 2 ++ +extract_uint64 +store 49 +load 8 +callsub numericalcomp_0 +store 8 +load 9 +callsub numericalcomp_0 +store 9 +load 10 +callsub numericalcomp_0 +store 10 +load 11 +callsub numericalcomp_0 +store 11 +load 12 +callsub numericalcomp_0 +store 12 +load 13 +callsub numericalcomp_0 +store 13 +load 14 +callsub numericalcomp_0 +store 14 +load 15 +callsub numericalcomp_0 +store 15 +load 16 +callsub numericalcomp_0 +store 16 +load 17 +callsub numericalcomp_0 +store 17 +load 18 +callsub numericalcomp_0 +store 18 +load 19 +callsub numericalcomp_0 +store 19 +load 20 +callsub numericalcomp_0 +store 20 +load 21 +callsub numericalcomp_0 +store 21 +load 22 +callsub numericalcomp_0 +store 22 +load 23 +callsub numericalcomp_0 +store 23 +load 24 +callsub numericalcomp_0 +store 24 +load 25 +callsub numericalcomp_0 +store 25 +load 26 +callsub numericalcomp_0 +store 26 +load 27 +callsub numericalcomp_0 +store 27 +load 28 +callsub numericalcomp_0 +store 28 +load 29 +callsub numericalcomp_0 +store 29 +load 30 +callsub numericalcomp_0 +store 30 +load 31 +callsub numericalcomp_0 +store 31 +load 32 +callsub numericalcomp_0 +store 32 +load 33 +callsub numericalcomp_0 +store 33 +load 34 +callsub numericalcomp_0 +store 34 +load 35 +callsub numericalcomp_0 +store 35 +load 36 +callsub numericalcomp_0 +store 36 +load 37 +callsub numericalcomp_0 +store 37 +load 38 +callsub numericalcomp_0 +store 38 +load 39 +callsub numericalcomp_0 +store 39 +load 40 +callsub numericalcomp_0 +store 40 +load 41 +callsub numericalcomp_0 +store 41 +load 42 +callsub numericalcomp_0 +store 42 +load 43 +callsub numericalcomp_0 +store 43 +load 44 +callsub numericalcomp_0 +store 44 +load 45 +callsub numericalcomp_0 +store 45 +load 46 +callsub numericalcomp_0 +store 46 +load 47 +callsub numericalcomp_0 +store 47 +load 48 +callsub numericalcomp_0 +store 48 +load 49 +callsub numericalcomp_0 +store 49 +int 42 +store 50 +load 50 +itob +extract 6 0 +load 8 +itob +load 9 +itob +concat +load 10 +itob +concat +load 11 +itob +concat +load 12 +itob +concat +load 13 +itob +concat +load 14 +itob +concat +load 15 +itob +concat +load 16 +itob +concat +load 17 +itob +concat +load 18 +itob +concat +load 19 +itob +concat +load 20 +itob +concat +load 21 +itob +concat +load 22 +itob +concat +load 23 +itob +concat +load 24 +itob +concat +load 25 +itob +concat +load 26 +itob +concat +load 27 +itob +concat +load 28 +itob +concat +load 29 +itob +concat +load 30 +itob +concat +load 31 +itob +concat +load 32 +itob +concat +load 33 +itob +concat +load 34 +itob +concat +load 35 +itob +concat +load 36 +itob +concat +load 37 +itob +concat +load 38 +itob +concat +load 39 +itob +concat +load 40 +itob +concat +load 41 +itob +concat +load 42 +itob +concat +load 43 +itob +concat +load 44 +itob +concat +load 45 +itob +concat +load 46 +itob +concat +load 47 +itob +concat +load 48 +itob +concat +load 49 +itob +concat +concat +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_2: +proto 1 1 +int 13634846 +frame_dig -1 +callsub arraycomplement_1 +store 2 +load 2 +callsub arraycomplement_1 +store 3 +frame_dig -1 +store 7 +load 7 +store 6 +int 6 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +load 2 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +load 7 +len ++ +store 5 +load 5 +int 65536 +< +assert +load 4 +itob +extract 6 0 +concat +load 3 +store 7 +load 6 +load 7 +concat +store 6 +load 5 +store 4 +load 4 +itob +extract 6 0 +concat +load 6 +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64_v8.teal new file mode 100644 index 000000000..03467d10c --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64_v8.teal @@ -0,0 +1,46 @@ +#pragma version 8 +txna ApplicationArgs 0 +btoi +store 1 +load 1 +callsub roundtripper_1 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// numerical_comp +numericalcomp_0: +proto 1 1 +int 13634846 +int 18446744073709551615 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub numericalcomp_0 +store 2 +load 2 +callsub numericalcomp_0 +store 3 +frame_dig -1 +itob +load 2 +itob +concat +load 3 +itob +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint8_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint8_v8.teal new file mode 100644 index 000000000..5fcfe7e85 --- /dev/null +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint8_v8.teal @@ -0,0 +1,57 @@ +#pragma version 8 +txna ApplicationArgs 0 +int 0 +getbyte +store 1 +load 1 +callsub roundtripper_1 +store 0 +byte 0x151f7c75 +load 0 +concat +log +int 1 +return + +// numerical_comp +numericalcomp_0: +proto 1 1 +int 13634846 +int 255 +frame_dig -1 +- +frame_bury 0 +frame_dig 0 +int 256 +< +assert +frame_dig 0 +retsub + +// round_tripper +roundtripper_1: +proto 1 1 +int 13634846 +frame_dig -1 +callsub numericalcomp_0 +store 2 +load 2 +callsub numericalcomp_0 +store 3 +byte 0x00 +int 0 +frame_dig -1 +setbyte +byte 0x00 +int 0 +load 2 +setbyte +concat +byte 0x00 +int 0 +load 3 +setbyte +concat +frame_bury 0 +frame_dig 0 +retsub \ No newline at end of file From ac98d94848bd8bdc11ea141012529ca49469f7f1 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Mon, 31 Oct 2022 12:46:12 -0400 Subject: [PATCH 035/157] comments --- pyteal/ast/abi/tuple.py | 5 ++++- pyteal/ast/subroutine.py | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pyteal/ast/abi/tuple.py b/pyteal/ast/abi/tuple.py index cabe52f7c..05878ec12 100644 --- a/pyteal/ast/abi/tuple.py +++ b/pyteal/ast/abi/tuple.py @@ -679,7 +679,10 @@ def __setattr__(self, name: str, field: Any) -> None: if name == "_NamedTuple__ready" or not self.__ready: super().__setattr__(name, field) return - # TODO need to relax this part lol + # NOTE this pass condition is for following scenario: + # NamedTuple is an argument, and inside subroutine, subroutine set internal ABI value with FrameStorage + # This used to violate `__setattr__` for not allowing any assignment to attributes + # Now this case is lifted such that we can shift the storage scheme. if name.startswith("_") and name != "_NamedTuple__ready" and self.__ready: super().__setattr__(name, field) return diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 739bc498a..7c7da13b7 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -977,7 +977,6 @@ def __var_n_loaded_fp( return argument_var, loaded_var def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: - # TODO need to make it better for my temp hack, kinda ugly but it works from pyteal.ast.abi.type import FrameStorage args = subroutine.arguments() From cf0c331e3f2f93b5eabd4d958c83ec1097479b66 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Mon, 31 Oct 2022 13:20:14 -0400 Subject: [PATCH 036/157] still wristing with docker, revert space reserving stuffs --- pyteal/ast/frame.py | 6 +-- .../teal/roundtrip/app_roundtrip_()_v8.teal | 4 +- .../app_roundtrip_(bool)[10]_v8.teal | 8 ++-- .../roundtrip/app_roundtrip_(bool)_v8.teal | 6 +-- ...t64,bool),byte[10],bool[4],uint64)_v8.teal | 26 +++++----- .../app_roundtrip_(bool,byte)_v8.teal | 8 ++-- ...undtrip_(bool,byte,address,string)_v8.teal | 14 +++--- ...yte),uint8)[2],string,bool[]))[]_2_v8.teal | 48 +++++++++---------- ..._(bool,byte,address,string,uint64)_v8.teal | 16 +++---- ...app_roundtrip_(bool,uint64,uint32)_v8.teal | 10 ++-- .../roundtrip/app_roundtrip_(byte)_v8.teal | 6 +-- .../app_roundtrip_(byte,bool,uint64)_v8.teal | 10 ++-- ...4],(bool,bool),uint64,address)[]_7_v8.teal | 22 ++++----- .../roundtrip/app_roundtrip_(uint16)_v8.teal | 6 +-- .../app_roundtrip_(uint16,uint8,byte)_v8.teal | 10 ++-- .../roundtrip/app_roundtrip_(uint32)_v8.teal | 6 +-- ...pp_roundtrip_(uint32,uint16,uint8)_v8.teal | 10 ++-- .../roundtrip/app_roundtrip_(uint64)_v8.teal | 6 +-- ...p_roundtrip_(uint64,uint32,uint16)_v8.teal | 10 ++-- .../roundtrip/app_roundtrip_(uint8)_v8.teal | 6 +-- .../app_roundtrip_(uint8,byte,bool)_v8.teal | 10 ++-- .../app_roundtrip_address[]_10_v8.teal | 8 ++-- .../roundtrip/app_roundtrip_address_v8.teal | 6 +-- .../roundtrip/app_roundtrip_bool[1]_v8.teal | 6 +-- .../app_roundtrip_bool[3][]_11_v8.teal | 8 ++-- .../roundtrip/app_roundtrip_bool[42]_v8.teal | 6 +-- .../roundtrip/app_roundtrip_bool[]_0_v8.teal | 4 +- .../roundtrip/app_roundtrip_bool[]_1_v8.teal | 6 +-- .../roundtrip/app_roundtrip_bool[]_42_v8.teal | 6 +-- .../teal/roundtrip/app_roundtrip_bool_v8.teal | 4 +- .../roundtrip/app_roundtrip_byte[16]_v8.teal | 6 +-- .../roundtrip/app_roundtrip_byte[]_36_v8.teal | 6 +-- .../teal/roundtrip/app_roundtrip_byte_v8.teal | 4 +- .../roundtrip/app_roundtrip_string_0_v8.teal | 4 +- .../roundtrip/app_roundtrip_string_13_v8.teal | 4 +- .../roundtrip/app_roundtrip_string_1_v8.teal | 4 +- .../roundtrip/app_roundtrip_uint16_v8.teal | 4 +- .../roundtrip/app_roundtrip_uint32_v8.teal | 4 +- .../roundtrip/app_roundtrip_uint64[1]_v8.teal | 6 +-- .../app_roundtrip_uint64[42]_v8.teal | 6 +-- .../app_roundtrip_uint64[]_0_v8.teal | 4 +- .../app_roundtrip_uint64[]_1_v8.teal | 6 +-- .../app_roundtrip_uint64[]_42_v8.teal | 6 +-- .../roundtrip/app_roundtrip_uint64_v8.teal | 4 +- .../roundtrip/app_roundtrip_uint8_v8.teal | 4 +- 45 files changed, 186 insertions(+), 188 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index d31e99138..cca2f6447 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -34,13 +34,11 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc if self.reserve_spot == 0: return proto_srt, proto_end elif self.reserve_spot == 1: - int_srt, int_end = Int(0xD00D1E).__teal__(options) + int_srt, int_end = Int(0).__teal__(options) proto_end.setNextBlock(int_srt) return proto_srt, int_end else: - dupn_srt, dupn_end = DupN(Int(0x5EA51DE), self.reserve_spot).__teal__( - options - ) + dupn_srt, dupn_end = DupN(Int(0), self.reserve_spot).__teal__(options) proto_end.setNextBlock(dupn_srt) return proto_srt, dupn_end diff --git a/tests/integration/teal/roundtrip/app_roundtrip_()_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_()_v8.teal index 7f74c2e54..a15a4fc89 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_()_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_()_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 byte "" frame_bury 0 frame_dig 0 @@ -23,7 +23,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub tuplecomplement_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v8.teal index f2c4408b5..3fd706e70 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbit @@ -33,7 +33,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -160,7 +160,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_1 store 3 @@ -179,7 +179,7 @@ retsub // bool_comp boolcomp_3: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool)_v8.teal index 740a8041a..007dc02ea 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbit @@ -33,7 +33,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub tuplecomplement_0 store 3 @@ -52,7 +52,7 @@ retsub // bool_comp boolcomp_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v8.teal index cc255e503..6f72201c2 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbit @@ -75,7 +75,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub tuplecomplement_0 store 8 @@ -94,7 +94,7 @@ retsub // bool_comp boolcomp_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! @@ -106,7 +106,7 @@ retsub // numerical_comp numericalcomp_3: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -121,7 +121,7 @@ retsub // array_complement arraycomplement_4: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -576,7 +576,7 @@ retsub // tuple_complement tuplecomplement_5: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 extract_uint64 @@ -605,7 +605,7 @@ retsub // numerical_comp numericalcomp_6: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -620,7 +620,7 @@ retsub // array_complement arraycomplement_7: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -767,7 +767,7 @@ retsub // bool_comp boolcomp_8: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! @@ -779,7 +779,7 @@ retsub // array_complement arraycomplement_9: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbit @@ -828,7 +828,7 @@ retsub // numerical_comp numericalcomp_10: proto 1 1 -int 13634846 +int 0 int 18446744073709551615 frame_dig -1 - @@ -839,7 +839,7 @@ retsub // numerical_comp numericalcomp_11: proto 1 1 -int 13634846 +int 0 int 18446744073709551615 frame_dig -1 - @@ -850,7 +850,7 @@ retsub // bool_comp boolcomp_12: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v8.teal index c8147ff68..7de062794 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbit @@ -45,7 +45,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub tuplecomplement_0 store 4 @@ -64,7 +64,7 @@ retsub // bool_comp boolcomp_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! @@ -76,7 +76,7 @@ retsub // numerical_comp numericalcomp_3: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v8.teal index 1840f754d..c015db7d2 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbit @@ -76,7 +76,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub tuplecomplement_0 store 6 @@ -143,7 +143,7 @@ retsub // bool_comp boolcomp_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! @@ -155,7 +155,7 @@ retsub // numerical_comp numericalcomp_3: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -170,7 +170,7 @@ retsub // numerical_comp numericalcomp_4: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -185,7 +185,7 @@ retsub // array_complement arraycomplement_5: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -640,7 +640,7 @@ retsub // string_reverse stringreverse_6: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v8.teal index b2fae5c07..c7436e670 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbit @@ -109,7 +109,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 frame_dig -1 int 2 @@ -238,7 +238,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_1 store 7 @@ -305,7 +305,7 @@ retsub // bool_comp boolcomp_3: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! @@ -317,7 +317,7 @@ retsub // numerical_comp numericalcomp_4: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -332,7 +332,7 @@ retsub // numerical_comp numericalcomp_5: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -347,7 +347,7 @@ retsub // array_complement arraycomplement_6: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -802,7 +802,7 @@ retsub // string_reverse stringreverse_7: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -854,7 +854,7 @@ retsub // tuple_complement tuplecomplement_8: proto 1 1 -int 13634846 +int 0 frame_dig -1 extract 0 32 store 22 @@ -958,7 +958,7 @@ retsub // numerical_comp numericalcomp_9: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -973,7 +973,7 @@ retsub // array_complement arraycomplement_10: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -1428,7 +1428,7 @@ retsub // tuple_complement tuplecomplement_11: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 extract_uint32 @@ -1497,7 +1497,7 @@ retsub // array_complement arraycomplement_12: proto 1 1 -int 13634846 +int 0 frame_dig -1 frame_dig -1 int 2 @@ -1596,7 +1596,7 @@ retsub // string_reverse stringreverse_13: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -1648,7 +1648,7 @@ retsub // bool_comp boolcomp_14: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! @@ -1660,7 +1660,7 @@ retsub // array_complement arraycomplement_15: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 int 16 @@ -1711,7 +1711,7 @@ retsub // numerical_comp numericalcomp_16: proto 1 1 -int 13634846 +int 0 int 4294967295 frame_dig -1 - @@ -1726,7 +1726,7 @@ retsub // string_reverse stringreverse_17: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -1778,7 +1778,7 @@ retsub // array_complement arraycomplement_18: proto 1 1 -int 13634846 +int 0 frame_dig -1 frame_dig -1 int 2 @@ -1969,7 +1969,7 @@ retsub // bool_comp boolcomp_19: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! @@ -1981,7 +1981,7 @@ retsub // array_complement arraycomplement_20: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbit @@ -2010,7 +2010,7 @@ retsub // tuple_complement tuplecomplement_21: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbyte @@ -2029,7 +2029,7 @@ retsub // numerical_comp numericalcomp_22: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -2044,7 +2044,7 @@ retsub // numerical_comp numericalcomp_23: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v8.teal index 0d22f98ea..b20a2929e 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbit @@ -86,7 +86,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub tuplecomplement_0 store 7 @@ -153,7 +153,7 @@ retsub // bool_comp boolcomp_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! @@ -165,7 +165,7 @@ retsub // numerical_comp numericalcomp_3: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -180,7 +180,7 @@ retsub // numerical_comp numericalcomp_4: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -195,7 +195,7 @@ retsub // array_complement arraycomplement_5: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -650,7 +650,7 @@ retsub // string_reverse stringreverse_6: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -702,7 +702,7 @@ retsub // numerical_comp numericalcomp_7: proto 1 1 -int 13634846 +int 0 int 18446744073709551615 frame_dig -1 - diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v8.teal index a1ba69bfb..c6cb8d92a 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbit @@ -54,7 +54,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub tuplecomplement_0 store 5 @@ -73,7 +73,7 @@ retsub // bool_comp boolcomp_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! @@ -85,7 +85,7 @@ retsub // numerical_comp numericalcomp_3: proto 1 1 -int 13634846 +int 0 int 18446744073709551615 frame_dig -1 - @@ -96,7 +96,7 @@ retsub // numerical_comp numericalcomp_4: proto 1 1 -int 13634846 +int 0 int 4294967295 frame_dig -1 - diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(byte)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(byte)_v8.teal index ea0e98fc2..ed37a3f74 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(byte)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(byte)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbyte @@ -33,7 +33,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub tuplecomplement_0 store 3 @@ -52,7 +52,7 @@ retsub // numerical_comp numericalcomp_2: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v8.teal index d0db45543..328541097 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbyte @@ -55,7 +55,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub tuplecomplement_0 store 5 @@ -74,7 +74,7 @@ retsub // numerical_comp numericalcomp_2: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -89,7 +89,7 @@ retsub // bool_comp boolcomp_3: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! @@ -101,7 +101,7 @@ retsub // numerical_comp numericalcomp_4: proto 1 1 -int 13634846 +int 0 int 18446744073709551615 frame_dig -1 - diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v8.teal index 915b57058..12e8535c4 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 extract 0 4 store 0 @@ -55,7 +55,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 45 int 0 @@ -166,7 +166,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_1 store 6 @@ -233,7 +233,7 @@ retsub // numerical_comp numericalcomp_3: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -248,7 +248,7 @@ retsub // array_complement arraycomplement_4: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -311,7 +311,7 @@ retsub // tuple_complement tuplecomplement_5: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbit @@ -340,7 +340,7 @@ retsub // numerical_comp numericalcomp_6: proto 1 1 -int 13634846 +int 0 int 18446744073709551615 frame_dig -1 - @@ -351,7 +351,7 @@ retsub // numerical_comp numericalcomp_7: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -366,7 +366,7 @@ retsub // array_complement arraycomplement_8: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -821,7 +821,7 @@ retsub // bool_comp boolcomp_9: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! @@ -833,7 +833,7 @@ retsub // bool_comp boolcomp_10: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v8.teal index 306ab7acb..ce75f2421 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 extract_uint16 @@ -32,7 +32,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub tuplecomplement_0 store 3 @@ -51,7 +51,7 @@ retsub // numerical_comp numericalcomp_2: proto 1 1 -int 13634846 +int 0 int 65535 frame_dig -1 - diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v8.teal index ef7c2428d..b2cde5b27 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 extract_uint16 @@ -56,7 +56,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub tuplecomplement_0 store 5 @@ -75,7 +75,7 @@ retsub // numerical_comp numericalcomp_2: proto 1 1 -int 13634846 +int 0 int 65535 frame_dig -1 - @@ -90,7 +90,7 @@ retsub // numerical_comp numericalcomp_3: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -105,7 +105,7 @@ retsub // numerical_comp numericalcomp_4: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v8.teal index 741db6e80..4e9b98403 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 extract_uint32 @@ -32,7 +32,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub tuplecomplement_0 store 3 @@ -51,7 +51,7 @@ retsub // numerical_comp numericalcomp_2: proto 1 1 -int 13634846 +int 0 int 4294967295 frame_dig -1 - diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v8.teal index 03e6b2c06..fe6043f2f 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 extract_uint32 @@ -55,7 +55,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub tuplecomplement_0 store 5 @@ -74,7 +74,7 @@ retsub // numerical_comp numericalcomp_2: proto 1 1 -int 13634846 +int 0 int 4294967295 frame_dig -1 - @@ -89,7 +89,7 @@ retsub // numerical_comp numericalcomp_3: proto 1 1 -int 13634846 +int 0 int 65535 frame_dig -1 - @@ -104,7 +104,7 @@ retsub // numerical_comp numericalcomp_4: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v8.teal index b88127140..64e19a464 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 btoi store 0 @@ -30,7 +30,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub tuplecomplement_0 store 3 @@ -49,7 +49,7 @@ retsub // numerical_comp numericalcomp_2: proto 1 1 -int 13634846 +int 0 int 18446744073709551615 frame_dig -1 - diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v8.teal index eacfb78f8..cdbd5954b 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 extract_uint64 @@ -53,7 +53,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub tuplecomplement_0 store 5 @@ -72,7 +72,7 @@ retsub // numerical_comp numericalcomp_2: proto 1 1 -int 13634846 +int 0 int 18446744073709551615 frame_dig -1 - @@ -83,7 +83,7 @@ retsub // numerical_comp numericalcomp_3: proto 1 1 -int 13634846 +int 0 int 4294967295 frame_dig -1 - @@ -98,7 +98,7 @@ retsub // numerical_comp numericalcomp_4: proto 1 1 -int 13634846 +int 0 int 65535 frame_dig -1 - diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v8.teal index ea0e98fc2..ed37a3f74 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbyte @@ -33,7 +33,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub tuplecomplement_0 store 3 @@ -52,7 +52,7 @@ retsub // numerical_comp numericalcomp_2: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v8.teal index 9addccd5d..689248d79 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbyte @@ -57,7 +57,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub tuplecomplement_0 store 5 @@ -76,7 +76,7 @@ retsub // numerical_comp numericalcomp_2: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -91,7 +91,7 @@ retsub // numerical_comp numericalcomp_3: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -106,7 +106,7 @@ retsub // bool_comp boolcomp_4: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! diff --git a/tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v8.teal index be15e1a34..280f65569 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v8.teal @@ -14,7 +14,7 @@ return // numerical_comp numericalcomp_0: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -29,7 +29,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -484,7 +484,7 @@ retsub // array_complement arraycomplement_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 32 int 0 @@ -637,7 +637,7 @@ retsub // round_tripper roundtripper_3: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_2 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_address_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_address_v8.teal index 7444fb267..33347e57b 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_address_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_address_v8.teal @@ -14,7 +14,7 @@ return // numerical_comp numericalcomp_0: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -29,7 +29,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -484,7 +484,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v8.teal index 065807402..35258686a 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v8.teal @@ -14,7 +14,7 @@ return // bool_comp boolcomp_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! @@ -26,7 +26,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbit @@ -45,7 +45,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v8.teal index 3f5d168b2..07faee81c 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v8.teal @@ -14,7 +14,7 @@ return // bool_comp boolcomp_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! @@ -26,7 +26,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbit @@ -65,7 +65,7 @@ retsub // array_complement arraycomplement_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -232,7 +232,7 @@ retsub // round_tripper roundtripper_3: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_2 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v8.teal index 20e422692..31fa09e84 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v8.teal @@ -14,7 +14,7 @@ return // bool_comp boolcomp_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! @@ -26,7 +26,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 getbit @@ -455,7 +455,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v8.teal index 542046cc4..67050ca70 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v8.teal @@ -14,7 +14,7 @@ return // array_complement arraycomplement_0: proto 1 1 -int 13634846 +int 0 int 0 store 8 load 8 @@ -29,7 +29,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v8.teal index 879b7adb5..61b164f60 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v8.teal @@ -14,7 +14,7 @@ return // bool_comp boolcomp_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! @@ -26,7 +26,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 int 16 @@ -53,7 +53,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v8.teal index 34f1528fe..a5c7c3d9f 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v8.teal @@ -14,7 +14,7 @@ return // bool_comp boolcomp_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! @@ -26,7 +26,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 0 int 16 @@ -545,7 +545,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool_v8.teal index 1e8311ecf..b241c509d 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool_v8.teal @@ -18,7 +18,7 @@ return // bool_comp boolcomp_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 ! ! @@ -30,7 +30,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub boolcomp_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v8.teal index f96c0c3b4..4d3b6e7c2 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v8.teal @@ -14,7 +14,7 @@ return // numerical_comp numericalcomp_0: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -29,7 +29,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -260,7 +260,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v8.teal index 9cab660b5..731fb06d0 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v8.teal @@ -14,7 +14,7 @@ return // numerical_comp numericalcomp_0: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -29,7 +29,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -618,7 +618,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_byte_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_byte_v8.teal index 5fcfe7e85..b1ec9822c 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_byte_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_byte_v8.teal @@ -16,7 +16,7 @@ return // numerical_comp numericalcomp_0: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -31,7 +31,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub numericalcomp_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_0_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_0_v8.teal index 68dbf97f6..fb6e4bfeb 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_string_0_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_string_0_v8.teal @@ -14,7 +14,7 @@ return // string_reverse stringreverse_0: proto 1 1 -int 13634846 +int 0 int 0 store 8 load 8 @@ -29,7 +29,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub stringreverse_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_13_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_13_v8.teal index 0b7ef9286..6b9d3620f 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_string_13_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_string_13_v8.teal @@ -14,7 +14,7 @@ return // string_reverse stringreverse_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -196,7 +196,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub stringreverse_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_1_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_1_v8.teal index 453a7cdb9..15bec0ea9 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_string_1_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_string_1_v8.teal @@ -14,7 +14,7 @@ return // string_reverse stringreverse_0: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 1 int 0 @@ -40,7 +40,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub stringreverse_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint16_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint16_v8.teal index b307d4c40..4204c502b 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint16_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint16_v8.teal @@ -16,7 +16,7 @@ return // numerical_comp numericalcomp_0: proto 1 1 -int 13634846 +int 0 int 65535 frame_dig -1 - @@ -31,7 +31,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub numericalcomp_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint32_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint32_v8.teal index 1cb435373..2ed29b2ee 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint32_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint32_v8.teal @@ -16,7 +16,7 @@ return // numerical_comp numericalcomp_0: proto 1 1 -int 13634846 +int 0 int 4294967295 frame_dig -1 - @@ -31,7 +31,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub numericalcomp_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v8.teal index 19e3be236..fb6a67b3a 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v8.teal @@ -14,7 +14,7 @@ return // numerical_comp numericalcomp_0: proto 1 1 -int 13634846 +int 0 int 18446744073709551615 frame_dig -1 - @@ -25,7 +25,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 8 int 0 @@ -44,7 +44,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v8.teal index 6f93ba204..e82c27443 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v8.teal @@ -14,7 +14,7 @@ return // numerical_comp numericalcomp_0: proto 1 1 -int 13634846 +int 0 int 18446744073709551615 frame_dig -1 - @@ -25,7 +25,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 8 int 0 @@ -536,7 +536,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v8.teal index 542046cc4..67050ca70 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v8.teal @@ -14,7 +14,7 @@ return // array_complement arraycomplement_0: proto 1 1 -int 13634846 +int 0 int 0 store 8 load 8 @@ -29,7 +29,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v8.teal index 4cc83c458..cd6867a22 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v8.teal @@ -14,7 +14,7 @@ return // numerical_comp numericalcomp_0: proto 1 1 -int 13634846 +int 0 int 18446744073709551615 frame_dig -1 - @@ -25,7 +25,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 8 int 0 @@ -52,7 +52,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v8.teal index c3b990138..0b2bddb45 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v8.teal @@ -14,7 +14,7 @@ return // numerical_comp numericalcomp_0: proto 1 1 -int 13634846 +int 0 int 18446744073709551615 frame_dig -1 - @@ -25,7 +25,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 int 8 int 0 @@ -626,7 +626,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64_v8.teal index 03467d10c..4f6069984 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64_v8.teal @@ -15,7 +15,7 @@ return // numerical_comp numericalcomp_0: proto 1 1 -int 13634846 +int 0 int 18446744073709551615 frame_dig -1 - @@ -26,7 +26,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub numericalcomp_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint8_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint8_v8.teal index 5fcfe7e85..b1ec9822c 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint8_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint8_v8.teal @@ -16,7 +16,7 @@ return // numerical_comp numericalcomp_0: proto 1 1 -int 13634846 +int 0 int 255 frame_dig -1 - @@ -31,7 +31,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 13634846 +int 0 frame_dig -1 callsub numericalcomp_0 store 2 From 769419b1f330c35cd0e73cccd71ca7cc55b09eb0 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Mon, 31 Oct 2022 15:26:55 -0400 Subject: [PATCH 037/157] minor, pure compilation more flexible --- tests/integration/abi_roundtrip_test.py | 32 ++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/integration/abi_roundtrip_test.py b/tests/integration/abi_roundtrip_test.py index 52b226471..3f9961415 100644 --- a/tests/integration/abi_roundtrip_test.py +++ b/tests/integration/abi_roundtrip_test.py @@ -196,10 +196,6 @@ def test_pure_compilation(abi_type): print(f"Pure Compilation Test for {abi_type=}") abi_type, type_str, dynamic_length, roundtripper = roundtrip_setup(abi_type) - # TODO neeed to make this version flexible - - _version = 8 - if type_str in BAD_TYPES: print( f"Skipping encoding roundtrip test of '{abi_type}' because of {BAD_TYPES[type_str]}" @@ -213,21 +209,25 @@ def test_pure_compilation(abi_type): assert [sdk_abi_type] == abi_arg_types assert algosdk.abi.TupleType([sdk_abi_type] * 3) == abi_ret_type - teal = roundtripper.compile(version=_version) + def compile_and_compare(_version: int): + teal = roundtripper.compile(_version) - filename = ( - f"app_roundtrip_{sdk_abi_type}" - + ("" if dynamic_length is None else f"_{dynamic_length}") - + f"_v{_version}.teal" - ) - tealdir = GENERATED / "roundtrip" - tealdir.mkdir(parents=True, exist_ok=True) + filename = ( + f"app_roundtrip_{sdk_abi_type}" + + ("" if dynamic_length is None else f"_{dynamic_length}") + + f"_v{_version}.teal" + ) + tealdir = GENERATED / "roundtrip" + tealdir.mkdir(parents=True, exist_ok=True) + + save_to = tealdir / filename + with open(save_to, "w") as f: + f.write(teal) - save_to = tealdir / filename - with open(save_to, "w") as f: - f.write(teal) + assert_teal_as_expected(save_to, FIXTURES / "roundtrip" / filename) - assert_teal_as_expected(save_to, FIXTURES / "roundtrip" / filename) + compile_and_compare(6) + compile_and_compare(8) @pytest.mark.parametrize("abi_type", ABI_TYPES) From d77b4421b63b8448218c32114ff761c439cf3c79 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Mon, 31 Oct 2022 15:45:37 -0400 Subject: [PATCH 038/157] roundtrip dryrun flexibility --- tests/integration/abi_roundtrip_test.py | 54 ++++++++++++++----------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/tests/integration/abi_roundtrip_test.py b/tests/integration/abi_roundtrip_test.py index 3f9961415..ef611f385 100644 --- a/tests/integration/abi_roundtrip_test.py +++ b/tests/integration/abi_roundtrip_test.py @@ -255,14 +255,17 @@ def test_roundtrip(abi_type): abi_strat = ABIStrategy(sdk_abi_types[0], dynamic_length=dynamic_length) rand_abi_instance = abi_strat.get_random() args = (rand_abi_instance,) - inspector = roundtripper.dryrun(args, compiler_version=8) - cost = inspector.cost() - passed = inspector.passed() - original, mut, mut_mut = inspector.last_log() + def dryrun_roundtrip(_version: int): + inspector = roundtripper.dryrun(args, compiler_version=_version) - print( - f""" + cost = inspector.cost() + passed = inspector.passed() + original, mut, mut_mut = inspector.last_log() + + print( + f""" +version={_version} {abi_type=} {sdk_abi_str=} {dynamic_length=} @@ -274,21 +277,24 @@ def test_roundtrip(abi_type): {mut=} {mut_mut=} """ - ) - - last_steps = 2 - - assert passed == (cost <= 700), inspector.report( - args, f"passed={passed} contradicted cost={cost}", last_steps=last_steps - ) - assert rand_abi_instance == original, inspector.report( - args, "rand_abi_instance v. original", last_steps=last_steps - ) - assert original == mut_mut, inspector.report( - args, "orginal v. mut_mut", last_steps=last_steps - ) - - expected_mut = abi_strat.mutate_for_roundtrip(rand_abi_instance) - assert expected_mut == mut, inspector.report( - args, "expected_mut v. mut", last_steps=last_steps - ) + ) + + last_steps = 2 + + assert passed == (cost <= 700), inspector.report( + args, f"passed={passed} contradicted cost={cost}", last_steps=last_steps + ) + assert rand_abi_instance == original, inspector.report( + args, "rand_abi_instance v. original", last_steps=last_steps + ) + assert original == mut_mut, inspector.report( + args, "orginal v. mut_mut", last_steps=last_steps + ) + + expected_mut = abi_strat.mutate_for_roundtrip(rand_abi_instance) + assert expected_mut == mut, inspector.report( + args, "expected_mut v. mut", last_steps=last_steps + ) + + dryrun_roundtrip(6) + dryrun_roundtrip(8) From 20c0ef891240da57c002845d53d64d36c29ff8b2 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Mon, 31 Oct 2022 15:55:21 -0400 Subject: [PATCH 039/157] conditional factorial done, need int65 and complex130 --- tests/integration/graviton_abi_test.py | 41 +++++++++++++++----------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index 0b571824c..5927589d1 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -520,21 +520,26 @@ def py_factorial(n): def test_conditional_factorial(): ptdre = PyTealDryRunExecutor(conditional_factorial, pt.Mode.Application) inputs = [(n,) for n in range(20)] - inspectors = ptdre.dryrun_on_sequence(inputs) - for i, args in enumerate(inputs): - inspector = inspectors[i] - n = args[0] - assert inspector.passed(), inspector.report(args, row=i + 1) - - expected = py_factorial(n) - assert expected == inspector.last_log(), inspector.report(args, row=i + 1) - - n = 21 - args = (n,) - inspector = ptdre.dryrun(args) - assert inspector.rejected(), inspector.report( - args, f"FAILED: should have rejected for {n=}", row=n + 1 - ) - assert inspector.error(), inspector.report( - args, f"FAILED: should error for {n=}", row=n + 1 - ) + + def dryrun_on_version(_version: int): + inspectors = ptdre.dryrun_on_sequence(inputs, compiler_version=_version) + for i, args in enumerate(inputs): + inspector = inspectors[i] + n = args[0] + assert inspector.passed(), inspector.report(args, row=i + 1) + + expected = py_factorial(n) + assert expected == inspector.last_log(), inspector.report(args, row=i + 1) + + n = 21 + args = (n,) + inspector = ptdre.dryrun(args) + assert inspector.rejected(), inspector.report( + args, f"FAILED: should have rejected for {n=}", row=n + 1 + ) + assert inspector.error(), inspector.report( + args, f"FAILED: should error for {n=}", row=n + 1 + ) + + dryrun_on_version(6) + dryrun_on_version(8) From d056f4af2a7841bb87cee58900d4088727b1c535 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Tue, 1 Nov 2022 10:48:03 -0400 Subject: [PATCH 040/157] gravition abi test pytest mark parameterized --- pyteal/ast/frame.py | 1 - pyteal/ast/frame_test.py | 3 -- tests/integration/graviton_abi_test.py | 66 +++++++++++++------------- 3 files changed, 32 insertions(+), 38 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index cca2f6447..1fe9d9c88 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -85,7 +85,6 @@ def has_return(self) -> bool: class FrameBury(Expr): def __init__(self, what: Expr, depth: int): super().__init__() - require_type(what, TealType.anytype) self.what = what self.depth = depth diff --git a/pyteal/ast/frame_test.py b/pyteal/ast/frame_test.py index b21b47d0e..c1cf5edd1 100644 --- a/pyteal/ast/frame_test.py +++ b/pyteal/ast/frame_test.py @@ -70,9 +70,6 @@ def test_frame_bury(): def test_frame_bury_invalid(): - with pytest.raises(pt.TealTypeError): - pt.FrameBury(pt.Seq(), 1) - with pytest.raises(pt.TealInputError): pt.FrameBury(pt.Int(1), 1).__teal__(avm7Options) diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index 5927589d1..0806ee96e 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -1,4 +1,5 @@ import random +import pytest from graviton.blackbox import DryRunInspector @@ -299,7 +300,8 @@ def conditional_factorial(_factor: pt.abi.Uint64, *, output: pt.abi.Uint64) -> p # ---- integration test functions ---- # -def test_integer65(): +@pytest.mark.parametrize("version", [6, 8]) +def test_integer65(version: int): bbpt_subtract_slick = PyTealDryRunExecutor(int65_sub, pt.Mode.Application) bbpt_subtract_cond = PyTealDryRunExecutor(int65_minus_cond, pt.Mode.Application) @@ -329,7 +331,7 @@ def pytuple_to_num(t): ] def binary_dryrun(p: PyTealDryRunExecutor) -> list[DryRunInspector]: - return p.dryrun_on_sequence(binary_inputs) + return p.dryrun_on_sequence(binary_inputs, compiler_version=version) # type: ignore # Binary: inspectors_subtract_slick = binary_dryrun(bbpt_subtract_slick) @@ -341,7 +343,9 @@ def binary_dryrun(p: PyTealDryRunExecutor) -> list[DryRunInspector]: inspectors_add = binary_dryrun(bbpt_add) # Unary: - inspectors_negate = bbpt_negate.dryrun_on_sequence(unary_inputs) + inspectors_negate = bbpt_negate.dryrun_on_sequence( + unary_inputs, compiler_version=version # type: ignore + ) for i in range(N): binary_args = binary_inputs[i] @@ -382,7 +386,8 @@ def binary_dryrun(p: PyTealDryRunExecutor) -> list[DryRunInspector]: ), inspector_negate.report(unary_args, f"failed for {unary_args}", row=i) -def test_complex130(): +@pytest.mark.parametrize("version", [6, 8]) +def test_complex130(version: int): # Binary: bbpt_cplx_add = PyTealDryRunExecutor(complex130_add, pt.Mode.Application) @@ -438,16 +443,12 @@ def pytuple_to_complex(tt): ] # Binary: - def binary_dryrun( - p: PyTealDryRunExecutor, _version: int = 6 - ) -> list[DryRunInspector]: - return p.dryrun_on_sequence(binary_inputs, compiler_version=_version) + def binary_dryrun(p: PyTealDryRunExecutor) -> list[DryRunInspector]: + return p.dryrun_on_sequence(binary_inputs, compiler_version=version) # type: ignore # Unary: - def unary_dryrun( - p: PyTealDryRunExecutor, _version: int = 6 - ) -> list[DryRunInspector]: - return p.dryrun_on_sequence(unary_inputs, compiler_version=_version) + def unary_dryrun(p: PyTealDryRunExecutor) -> list[DryRunInspector]: + return p.dryrun_on_sequence(unary_inputs, compiler_version=version) # type: ignore inspectors_cplx_add = binary_dryrun(bbpt_cplx_add) @@ -517,29 +518,26 @@ def py_factorial(n): return 1 if n <= 1 else n * py_factorial(n - 1) -def test_conditional_factorial(): +@pytest.mark.parametrize("version", [6, 8]) +def test_conditional_factorial(version: int): ptdre = PyTealDryRunExecutor(conditional_factorial, pt.Mode.Application) inputs = [(n,) for n in range(20)] - def dryrun_on_version(_version: int): - inspectors = ptdre.dryrun_on_sequence(inputs, compiler_version=_version) - for i, args in enumerate(inputs): - inspector = inspectors[i] - n = args[0] - assert inspector.passed(), inspector.report(args, row=i + 1) - - expected = py_factorial(n) - assert expected == inspector.last_log(), inspector.report(args, row=i + 1) - - n = 21 - args = (n,) - inspector = ptdre.dryrun(args) - assert inspector.rejected(), inspector.report( - args, f"FAILED: should have rejected for {n=}", row=n + 1 - ) - assert inspector.error(), inspector.report( - args, f"FAILED: should error for {n=}", row=n + 1 - ) + inspectors = ptdre.dryrun_on_sequence(inputs, compiler_version=version) # type: ignore + for i, args in enumerate(inputs): + inspector = inspectors[i] + n = args[0] + assert inspector.passed(), inspector.report(args, row=i + 1) - dryrun_on_version(6) - dryrun_on_version(8) + expected = py_factorial(n) + assert expected == inspector.last_log(), inspector.report(args, row=i + 1) + + n = 21 + args = (n,) + inspector = ptdre.dryrun(args) + assert inspector.rejected(), inspector.report( + args, f"FAILED: should have rejected for {n=}", row=n + 1 + ) + assert inspector.error(), inspector.report( + args, f"FAILED: should error for {n=}", row=n + 1 + ) From 6ba772a69721fe43409a7fa03f8235741dd38d8b Mon Sep 17 00:00:00 2001 From: Hang Su Date: Tue, 1 Nov 2022 11:31:04 -0400 Subject: [PATCH 041/157] module --- pyteal/ast/abi/type.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index c505021c0..e1475166c 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -79,7 +79,7 @@ def storage_type(self) -> TealType: pass -DataStorageSchema.__module__ = "pyteal" +DataStorageSchema.__module__ = "pyteal.abi" class ScratchStorage(DataStorageSchema): @@ -97,7 +97,7 @@ def storage_type(self) -> TealType: return self.scratchvar.storage_type() -ScratchStorage.__module__ = "pyteal" +ScratchStorage.__module__ = "pyteal.abi" class FrameStorage(DataStorageSchema): @@ -120,7 +120,7 @@ def load_value(self) -> Expr: return FrameDig(self.stack_depth) -FrameStorage.__module__ = "pyteal" +FrameStorage.__module__ = "pyteal.abi" class BaseType(ABC): From 5840a8bb772416254c3ab8cc5cc11c5278912e02 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Tue, 1 Nov 2022 14:19:15 -0400 Subject: [PATCH 042/157] per review comments --- pyteal/ast/frame.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 8b1cb6080..5799ef90b 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -10,14 +10,18 @@ class Proto(Expr): - def __init__(self, arg_num: int, ret_num: int): + def __init__(self, num_args: int, num_returns: int): super().__init__() - if arg_num < 0: - raise TealInputError(f"subroutine arg number {arg_num} must be >= 0") - if ret_num < 0: - raise TealInputError(f"return value number {ret_num} must be >= 0") - self.arg_num = arg_num - self.ret_num = ret_num + if num_args < 0: + raise TealInputError( + f"the number of arguments provided to Proto must be >= 0 but {num_args=}" + ) + if num_returns < 0: + raise TealInputError( + f"the number of return values provided to Proto must be >= 0 but {num_returns=}" + ) + self.num_args = num_args + self.num_returns = num_returns def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: verifyProgramVersion( @@ -25,11 +29,11 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc options.version, "Program version too low to use op proto", ) - op = TealOp(self, Op.proto, self.arg_num, self.ret_num) + op = TealOp(self, Op.proto, self.num_args, self.num_returns) return TealBlock.FromOp(options, op) def __str__(self) -> str: - return f"(proto: arg_num = {self.arg_num}, ret_num = {self.ret_num})" + return f"(proto: num_args = {self.num_args}, num_returns = {self.num_returns})" def type_of(self) -> TealType: return TealType.none From a596fc15472029b2445f6e7351c4c18bdbb9a616 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 08:42:32 -0400 Subject: [PATCH 043/157] per review comments --- pyteal/ast/frame.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 5799ef90b..7334a39b6 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -73,10 +73,10 @@ def has_return(self) -> bool: class FrameBury(Expr): - def __init__(self, what: Expr, depth: int): + def __init__(self, value: Expr, depth: int): super().__init__() - require_type(what, TealType.anytype) - self.what = what + require_type(value, TealType.anytype) + self.value = value self.depth = depth def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: @@ -86,10 +86,10 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc "Program version too low to use op frame_bury", ) op = TealOp(self, Op.frame_bury, self.depth) - return TealBlock.FromOp(options, op, self.what) + return TealBlock.FromOp(options, op, self.value) def __str__(self) -> str: - return f"(frame_bury (bury_depth = {self.depth}) ({self.what}))" + return f"(frame_bury (bury_depth = {self.depth}) ({self.value}))" def type_of(self) -> TealType: return TealType.none @@ -102,12 +102,12 @@ def has_return(self) -> bool: class Bury(Expr): - def __init__(self, what: Expr, depth: int): + def __init__(self, value: Expr, depth: int): super().__init__() - require_type(what, TealType.anytype) + require_type(value, TealType.anytype) if depth <= 0: raise TealInputError("bury depth should be strictly positive") - self.what = what + self.value = value self.depth = depth def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: @@ -117,10 +117,10 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc "Program version too low to use op bury", ) op = TealOp(self, Op.bury, self.depth) - return TealBlock.FromOp(options, op, self.what) + return TealBlock.FromOp(options, op, self.value) def __str__(self) -> str: - return f"(bury (depth = {self.depth}) ({self.what}))" + return f"(bury (depth = {self.depth}) ({self.value}))" def type_of(self) -> TealType: return TealType.none @@ -133,12 +133,12 @@ def has_return(self) -> bool: class DupN(Expr): - def __init__(self, what: Expr, repetition: int): + def __init__(self, value: Expr, repetition: int): super().__init__() - require_type(what, TealType.anytype) + require_type(value, TealType.anytype) if repetition < 0: raise TealInputError("dupn repetition should be non negative") - self.what = what + self.value = value self.repetition = repetition def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: @@ -148,13 +148,13 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc "Program version too low to use op dupn", ) op = TealOp(self, Op.dupn, self.repetition) - return TealBlock.FromOp(options, op, self.what) + return TealBlock.FromOp(options, op, self.value) def __str__(self) -> str: - return f"(dupn (repetition = {self.repetition}) ({self.what}))" + return f"(dupn (repetition = {self.repetition}) ({self.value}))" def type_of(self) -> TealType: - return self.what.type_of() + return self.value.type_of() def has_return(self) -> bool: return False From 519c7528b6f301d077bf3133ba41f6dab1d06e74 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 08:46:45 -0400 Subject: [PATCH 044/157] per review comments, depth -> frame_depth --- pyteal/ast/frame.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 7334a39b6..68ce3a2f2 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -46,9 +46,9 @@ def has_return(self) -> bool: class FrameDig(Expr): - def __init__(self, depth: int): + def __init__(self, frame_index: int): super().__init__() - self.depth = depth + self.frame_index = frame_index def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: verifyProgramVersion( @@ -56,11 +56,11 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc options.version, "Program version too low to use op frame_dig", ) - op = TealOp(self, Op.frame_dig, self.depth) + op = TealOp(self, Op.frame_dig, self.frame_index) return TealBlock.FromOp(options, op) def __str__(self) -> str: - return f"(frame_dig: dig_depth = {self.depth})" + return f"(frame_dig: dig_from = {self.frame_index})" def type_of(self) -> TealType: return TealType.anytype @@ -73,11 +73,11 @@ def has_return(self) -> bool: class FrameBury(Expr): - def __init__(self, value: Expr, depth: int): + def __init__(self, value: Expr, frame_index: int): super().__init__() require_type(value, TealType.anytype) self.value = value - self.depth = depth + self.frame_index = frame_index def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: verifyProgramVersion( @@ -85,11 +85,11 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc options.version, "Program version too low to use op frame_bury", ) - op = TealOp(self, Op.frame_bury, self.depth) + op = TealOp(self, Op.frame_bury, self.frame_index) return TealBlock.FromOp(options, op, self.value) def __str__(self) -> str: - return f"(frame_bury (bury_depth = {self.depth}) ({self.value}))" + return f"(frame_bury (bury_to = {self.frame_index}) ({self.value}))" def type_of(self) -> TealType: return TealType.none From 48d06786aa53ff2b65aa57008ab43c2584420ddb Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 09:05:09 -0400 Subject: [PATCH 045/157] per review comments, on final type annotation --- pyteal/ast/abi/type.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index c505021c0..dfaa9bd16 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -85,7 +85,7 @@ def storage_type(self) -> TealType: class ScratchStorage(DataStorageSchema): def __init__(self, storage_type: TealType) -> None: super().__init__() - self.scratchvar: Final = ScratchVar(storage_type) + self.scratchvar: Final[ScratchVar] = ScratchVar(storage_type) def load_value(self) -> Expr: return self.scratchvar.load() @@ -134,7 +134,7 @@ class BaseType(ABC): def __init__(self, spec: TypeSpec) -> None: """Create a new BaseType.""" super().__init__() - self._type_spec: Final = spec + self._type_spec: Final[TypeSpec] = spec self._data_storage: DataStorageSchema = ScratchStorage(spec.storage_type()) # self.stored_value: Final = ScratchVar(spec.storage_type()) From 7d4277b5cfb64317bd5253dcd7f96eee64fdfb78 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 09:33:35 -0400 Subject: [PATCH 046/157] per review comments, renaem to AbstractVar/FrameVar --- pyteal/ast/abi/__init__.py | 4 ++-- pyteal/ast/abi/address.py | 15 +++++-------- pyteal/ast/abi/address_test.py | 2 +- pyteal/ast/abi/array_base.py | 6 ++--- pyteal/ast/abi/array_dynamic.py | 6 ++--- pyteal/ast/abi/array_dynamic_test.py | 4 ++-- pyteal/ast/abi/array_static.py | 10 ++++----- pyteal/ast/abi/array_static_test.py | 4 ++-- pyteal/ast/abi/bool.py | 8 +++---- pyteal/ast/abi/reference_type.py | 6 ++--- pyteal/ast/abi/reference_type_test.py | 2 +- pyteal/ast/abi/string.py | 24 ++++++++------------ pyteal/ast/abi/string_test.py | 2 +- pyteal/ast/abi/transaction.py | 8 +++---- pyteal/ast/abi/tuple.py | 6 ++--- pyteal/ast/abi/tuple_test.py | 4 ++-- pyteal/ast/abi/type.py | 30 ++++++++++++------------- pyteal/ast/abi/type_test.py | 2 +- pyteal/ast/abi/uint.py | 32 +++++++++++++-------------- pyteal/ast/abi/uint_test.py | 2 +- pyteal/ast/subroutine.py | 4 ++-- 21 files changed, 85 insertions(+), 96 deletions(-) diff --git a/pyteal/ast/abi/__init__.py b/pyteal/ast/abi/__init__.py index 3ca3ab290..4baa3bc16 100644 --- a/pyteal/ast/abi/__init__.py +++ b/pyteal/ast/abi/__init__.py @@ -9,7 +9,7 @@ BaseType, ComputedValue, ReturnedValue, - DataStorageSchema, + AbstractVar, FrameStorage, ScratchStorage, ) @@ -174,7 +174,7 @@ "type_specs_from_signature", "make", "size_of", - "DataStorageSchema", + "AbstractVar", "FrameStorage", "ScratchStorage", "algosdk_from_annotation", diff --git a/pyteal/ast/abi/address.py b/pyteal/ast/abi/address.py index 3165fcd9a..0fea62c8a 100644 --- a/pyteal/ast/abi/address.py +++ b/pyteal/ast/abi/address.py @@ -56,7 +56,7 @@ def get(self) -> Expr: The expression will have the type TealType.bytes. """ - return self._data_storage.load_value() + return self._data_storage.load() def set( self, @@ -108,28 +108,25 @@ def set( or value.type_spec() == StaticArrayTypeSpec(ByteTypeSpec(), AddressLength.Bytes) ): - return self._data_storage.store_value( - value._data_storage.load_value() - ) + return self._data_storage.store(value._data_storage.load()) raise TealInputError( f"Got {value} with type spec {value.type_spec()}, expected AddressTypeSpec" ) case str(): # Addr throws if value is invalid address - return self._data_storage.store_value(Addr(value)) + return self._data_storage.store(Addr(value)) case bytes(): if len(value) == AddressLength.Bytes: - return self._data_storage.store_value(Bytes(value)) + return self._data_storage.store(Bytes(value)) raise TealInputError( f"Got bytes with length {len(value)}, expected {AddressLength.Bytes}" ) case Expr(): return Seq( - self._data_storage.store_value(value), + self._data_storage.store(value), Assert( - Len(self._data_storage.load_value()) - == Int(AddressLength.Bytes.value) + Len(self._data_storage.load()) == Int(AddressLength.Bytes.value) ), ) case CollectionSequence(): diff --git a/pyteal/ast/abi/address_test.py b/pyteal/ast/abi/address_test.py index dca9136dc..ccecb0ecf 100644 --- a/pyteal/ast/abi/address_test.py +++ b/pyteal/ast/abi/address_test.py @@ -86,7 +86,7 @@ def test_Address_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expectedExpr = value._data_storage.store_value( + expectedExpr = value._data_storage.store( substring_for_decoding( encoded, start_index=start_index, diff --git a/pyteal/ast/abi/array_base.py b/pyteal/ast/abi/array_base.py index 4674f1d90..417e401e1 100644 --- a/pyteal/ast/abi/array_base.py +++ b/pyteal/ast/abi/array_base.py @@ -104,7 +104,7 @@ def decode( extracted = substring_for_decoding( encoded, start_index=start_index, end_index=end_index, length=length ) - return self._data_storage.store_value(extracted) + return self._data_storage.store(extracted) def set(self, values: Sequence[T]) -> Expr: """Set the ABI array with a sequence of ABI type variables. @@ -142,7 +142,7 @@ def set(self, values: Sequence[T]) -> Expr: length_prefix = Seq(length_tmp.set(len(values)), length_tmp.encode()) encoded = Concat(length_prefix, encoded) - return self._data_storage.store_value(encoded) + return self._data_storage.store(encoded) def encode(self) -> Expr: """Encode the ABI array to be a byte string. @@ -150,7 +150,7 @@ def encode(self) -> Expr: Returns: A PyTeal expression that encodes this ABI array to a byte string. """ - return self._data_storage.load_value() + return self._data_storage.load() @abstractmethod def length(self) -> Expr: diff --git a/pyteal/ast/abi/array_dynamic.py b/pyteal/ast/abi/array_dynamic.py index 2a5f7367d..a39373324 100644 --- a/pyteal/ast/abi/array_dynamic.py +++ b/pyteal/ast/abi/array_dynamic.py @@ -79,7 +79,7 @@ def set( raise TealInputError( f"Cannot assign type {values.type_spec()} to {self.type_spec()}" ) - return self._data_storage.store_value(values.encode()) + return self._data_storage.store(values.encode()) return super().set(values) def length(self) -> Expr: @@ -165,7 +165,7 @@ def set( match values: case bytes() | bytearray(): - return self._data_storage.store_value(_encoded_byte_string(values)) + return self._data_storage.store(_encoded_byte_string(values)) case Expr(): return _store_encoded_expr_byte_string_into_var( values, self._data_storage @@ -181,7 +181,7 @@ def get(self) -> Expr: Returns: A Pyteal expression that loads byte encoding of this DynamicBytes, and drop the first uint16 DynamicArray length encoding. """ - return Suffix(self._data_storage.load_value(), Int(2)) + return Suffix(self._data_storage.load(), Int(2)) DynamicBytes.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/array_dynamic_test.py b/pyteal/ast/abi/array_dynamic_test.py index 3e172eeee..589d52664 100644 --- a/pyteal/ast/abi/array_dynamic_test.py +++ b/pyteal/ast/abi/array_dynamic_test.py @@ -106,7 +106,7 @@ def test_DynamicArray_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value._data_storage.store_value( + expectedExpr = value._data_storage.store( substring_for_decoding( encoded, start_index=start_index, @@ -141,7 +141,7 @@ def test_DynamicArray_set_values(): assert not expr.has_return() length_tmp = abi.Uint16() - expectedExpr = value._data_storage.store_value( + expectedExpr = value._data_storage.store( pt.Concat( pt.Seq(length_tmp.set(len(values)), length_tmp.encode()), _encode_tuple(values), diff --git a/pyteal/ast/abi/array_static.py b/pyteal/ast/abi/array_static.py index caf2dcc88..a631687f3 100644 --- a/pyteal/ast/abi/array_static.py +++ b/pyteal/ast/abi/array_static.py @@ -109,7 +109,7 @@ def set( raise TealInputError( f"Cannot assign type {values.type_spec()} to {self.type_spec()}" ) - return self._data_storage.store_value(values.encode()) + return self._data_storage.store(values.encode()) if self.type_spec().length_static() != len(values): raise TealInputError( @@ -207,11 +207,11 @@ def set( raise TealInputError( f"Got bytes with length {len(values)}, expect {self.type_spec().length_static()}" ) - return self._data_storage.store_value(Bytes(values)) + return self._data_storage.store(Bytes(values)) case Expr(): return Seq( - self._data_storage.store_value(values), - Assert(self.length() == Len(self._data_storage.load_value())), + self._data_storage.store(values), + Assert(self.length() == Len(self._data_storage.load())), ) return super().set(values) @@ -222,7 +222,7 @@ def get(self) -> Expr: Returns: A Pyteal expression that loads byte encoding of this StaticBytes. """ - return self._data_storage.load_value() + return self._data_storage.load() StaticBytes.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/array_static_test.py b/pyteal/ast/abi/array_static_test.py index 7d0a8ae0a..7174c2ebb 100644 --- a/pyteal/ast/abi/array_static_test.py +++ b/pyteal/ast/abi/array_static_test.py @@ -159,7 +159,7 @@ def test_StaticArray_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value._data_storage.store_value( + expectedExpr = value._data_storage.store( substring_for_decoding( encoded, start_index=start_index, @@ -202,7 +202,7 @@ def test_StaticArray_set_values(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value._data_storage.store_value(_encode_tuple(values)) + expectedExpr = value._data_storage.store(_encode_tuple(values)) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) diff --git a/pyteal/ast/abi/bool.py b/pyteal/ast/abi/bool.py index 2bfbd3aca..6d42c2fdd 100644 --- a/pyteal/ast/abi/bool.py +++ b/pyteal/ast/abi/bool.py @@ -50,7 +50,7 @@ def get(self) -> Expr: expression that evaluates to 0 will be returned. In either case, the expression will have the type TealType.uint64. """ - return self._data_storage.load_value() + return self._data_storage.load() def set(self, value: Union[bool, Expr, "Bool", ComputedValue["Bool"]]) -> Expr: """Set the value of this Bool to the input value. @@ -85,10 +85,10 @@ def set(self, value: Union[bool, Expr, "Bool", ComputedValue["Bool"]]) -> Expr: checked = True if checked: - return self._data_storage.store_value(value) + return self._data_storage.store(value) # Not(Not(value)) coerces all values greater than 0 to 1 - return self._data_storage.store_value(Not(Not(value))) + return self._data_storage.store(Not(Not(value))) def decode( self, @@ -103,7 +103,7 @@ def decode( return self.decode_bit(encoded, start_index * Int(NUM_BITS_IN_BYTE)) def decode_bit(self, encoded, bit_index: Expr) -> Expr: - return self._data_storage.store_value(GetBit(encoded, bit_index)) + return self._data_storage.store(GetBit(encoded, bit_index)) def encode(self) -> Expr: return SetBit(Bytes(b"\x00"), Int(0), self.get()) diff --git a/pyteal/ast/abi/reference_type.py b/pyteal/ast/abi/reference_type.py index 2ea723b92..aa0709ffe 100644 --- a/pyteal/ast/abi/reference_type.py +++ b/pyteal/ast/abi/reference_type.py @@ -58,7 +58,7 @@ def referenced_index(self) -> Expr: If this reference type is an application or asset, note that this DOES NOT return the application or asset ID. See :code:`application_id()` or :code:`asset_id()` for that. """ - return self._data_storage.load_value() + return self._data_storage.load() def decode( self, @@ -107,7 +107,7 @@ def __init__(self) -> None: def address(self) -> Expr: """Get the address of the account.""" - return Txn.accounts[self._data_storage.load_value()] + return Txn.accounts[self._data_storage.load()] def params(self) -> AccountParamObject: """Get information about the account.""" @@ -205,7 +205,7 @@ def __init__(self) -> None: def application_id(self) -> Expr: """Get the ID of the application.""" - return Txn.applications[self._data_storage.load_value()] + return Txn.applications[self._data_storage.load()] def params(self) -> AppParamObject: """Get information about the application's parameters.""" diff --git a/pyteal/ast/abi/reference_type_test.py b/pyteal/ast/abi/reference_type_test.py index d3b8aaf93..edc0a857c 100644 --- a/pyteal/ast/abi/reference_type_test.py +++ b/pyteal/ast/abi/reference_type_test.py @@ -61,7 +61,7 @@ def test_ReferenceType_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expected_decoding = value._data_storage.store_value( + expected_decoding = value._data_storage.store( pt.GetByte( encoded, start_index if start_index is not None else pt.Int(0), diff --git a/pyteal/ast/abi/string.py b/pyteal/ast/abi/string.py index 0359aee76..f91eb272f 100644 --- a/pyteal/ast/abi/string.py +++ b/pyteal/ast/abi/string.py @@ -4,7 +4,7 @@ from algosdk.abi import ABIType from pyteal.ast.abi.uint import Byte -from pyteal.ast.abi.type import ComputedValue, BaseType, DataStorageSchema +from pyteal.ast.abi.type import ComputedValue, BaseType, AbstractVar from pyteal.ast.abi.array_dynamic import DynamicArray, DynamicArrayTypeSpec from pyteal.ast.abi.uint import ByteTypeSpec, Uint16TypeSpec @@ -25,14 +25,12 @@ def _encoded_byte_string(s: bytes | bytearray) -> Expr: def _store_encoded_expr_byte_string_into_var( - value: Expr, location: DataStorageSchema + value: Expr, location: AbstractVar ) -> Expr: return Seq( - location.store_value(value), - location.store_value( - Concat( - Suffix(Itob(Len(location.load_value())), Int(6)), location.load_value() - ) + location.store(value), + location.store( + Concat(Suffix(Itob(Len(location.load())), Int(6)), location.load()) ), ) @@ -70,7 +68,7 @@ def get(self) -> Expr: The expression will have the type TealType.bytes. """ return Suffix( - self._data_storage.load_value(), Int(Uint16TypeSpec().byte_length_static()) + self._data_storage.load(), Int(Uint16TypeSpec().byte_length_static()) ) def set( @@ -113,19 +111,15 @@ def set( if value.type_spec() == StringTypeSpec() or ( value.type_spec() == DynamicArrayTypeSpec(ByteTypeSpec()) ): - return self._data_storage.store_value( - value._data_storage.load_value() - ) + return self._data_storage.store(value._data_storage.load()) raise TealInputError( f"Got {value} with type spec {value.type_spec()}, expected {StringTypeSpec}" ) case bytes() | bytearray(): - return self._data_storage.store_value(_encoded_byte_string(value)) + return self._data_storage.store(_encoded_byte_string(value)) case str(): - return self._data_storage.store_value( - _encoded_byte_string(value.encode()) - ) + return self._data_storage.store(_encoded_byte_string(value.encode())) case Expr(): return _store_encoded_expr_byte_string_into_var( value, self._data_storage diff --git a/pyteal/ast/abi/string_test.py b/pyteal/ast/abi/string_test.py index fb8de7fb9..e335da1a1 100644 --- a/pyteal/ast/abi/string_test.py +++ b/pyteal/ast/abi/string_test.py @@ -76,7 +76,7 @@ def test_DynamicArray_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expectedExpr = value._data_storage.store_value( + expectedExpr = value._data_storage.store( substring_for_decoding( encoded, start_index=start_index, diff --git a/pyteal/ast/abi/transaction.py b/pyteal/ast/abi/transaction.py index 2451a1285..1f3ea9ba2 100644 --- a/pyteal/ast/abi/transaction.py +++ b/pyteal/ast/abi/transaction.py @@ -82,16 +82,16 @@ def _set_index( case ComputedValue(): return self._set_with_computed_type(value) case BaseType(): - return self._data_storage.store_value(self._data_storage.load_value()) + return self._data_storage.store(self._data_storage.load()) case int(): - return self._data_storage.store_value(Int(value)) + return self._data_storage.store(Int(value)) case Expr(): - return self._data_storage.store_value(value) + return self._data_storage.store(value) case _: raise TealInputError(f"Cant store a {type(value)} in a Transaction") def index(self) -> Expr: - return self._data_storage.load_value() + return self._data_storage.load() def decode( self, diff --git a/pyteal/ast/abi/tuple.py b/pyteal/ast/abi/tuple.py index 2f2dceeab..efea10e36 100644 --- a/pyteal/ast/abi/tuple.py +++ b/pyteal/ast/abi/tuple.py @@ -309,7 +309,7 @@ def decode( extracted = substring_for_decoding( encoded, start_index=start_index, end_index=end_index, length=length ) - return self._data_storage.store_value(extracted) + return self._data_storage.store(extracted) @overload def set(self, *values: BaseType) -> Expr: @@ -352,10 +352,10 @@ def set(self, *values): ) if not all(myTypes[i] == values[i].type_spec() for i in range(len(myTypes))): raise TealInputError("Input values do not match type") - return self._data_storage.store_value(_encode_tuple(values)) + return self._data_storage.store(_encode_tuple(values)) def encode(self) -> Expr: - return self._data_storage.load_value() + return self._data_storage.load() def length(self) -> Expr: """Get the number of values this tuple holds as an Expr.""" diff --git a/pyteal/ast/abi/tuple_test.py b/pyteal/ast/abi/tuple_test.py index 777d3688e..ad231784f 100644 --- a/pyteal/ast/abi/tuple_test.py +++ b/pyteal/ast/abi/tuple_test.py @@ -623,7 +623,7 @@ def test_Tuple_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = tupleValue._data_storage.store_value( + expectedExpr = tupleValue._data_storage.store( substring_for_decoding( encoded, start_index=start_index, @@ -672,7 +672,7 @@ def test_Tuple_set(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = tupleValue._data_storage.store_value( + expectedExpr = tupleValue._data_storage.store( _encode_tuple([uint8, uint16, uint32]) ) expected, _ = expectedExpr.__teal__(options) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index dfaa9bd16..3ae5d585c 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -65,13 +65,13 @@ def __str__(self) -> str: TypeSpec.__module__ = "pyteal.abi" -class DataStorageSchema(ABC): +class AbstractVar(ABC): @abstractmethod - def store_value(self, value: Expr) -> Expr: + def store(self, value: Expr) -> Expr: pass @abstractmethod - def load_value(self) -> Expr: + def load(self) -> Expr: pass @abstractmethod @@ -79,18 +79,18 @@ def storage_type(self) -> TealType: pass -DataStorageSchema.__module__ = "pyteal" +AbstractVar.__module__ = "pyteal" -class ScratchStorage(DataStorageSchema): +class ScratchStorage(AbstractVar): def __init__(self, storage_type: TealType) -> None: super().__init__() self.scratchvar: Final[ScratchVar] = ScratchVar(storage_type) - def load_value(self) -> Expr: + def load(self) -> Expr: return self.scratchvar.load() - def store_value(self, value: Expr) -> Expr: + def store(self, value: Expr) -> Expr: return self.scratchvar.slot.store(value) def storage_type(self) -> TealType: @@ -100,7 +100,7 @@ def storage_type(self) -> TealType: ScratchStorage.__module__ = "pyteal" -class FrameStorage(DataStorageSchema): +class FrameStorage(AbstractVar): def __init__(self, storage_type: TealType, stack_depth: int) -> None: super().__init__() self.stack_type = storage_type @@ -109,12 +109,12 @@ def __init__(self, storage_type: TealType, stack_depth: int) -> None: def storage_type(self) -> TealType: return self.stack_type - def store_value(self, value: Expr) -> Expr: + def store(self, value: Expr) -> Expr: from pyteal.ast import FrameBury return FrameBury(value, self.stack_depth) - def load_value(self) -> Expr: + def load(self) -> Expr: from pyteal.ast import FrameDig return FrameDig(self.stack_depth) @@ -135,18 +135,18 @@ def __init__(self, spec: TypeSpec) -> None: """Create a new BaseType.""" super().__init__() self._type_spec: Final[TypeSpec] = spec - self._data_storage: DataStorageSchema = ScratchStorage(spec.storage_type()) + self._data_storage: AbstractVar = ScratchStorage(spec.storage_type()) # self.stored_value: Final = ScratchVar(spec.storage_type()) - def _set_data_source(self, storage: DataStorageSchema) -> None: + def _set_data_source(self, storage: AbstractVar) -> None: self._data_storage = storage def _load_value(self) -> Expr: - return self._data_storage.load_value() + return self._data_storage.load() def _store_value(self, value: Expr) -> Expr: - return self._data_storage.store_value(value) + return self._data_storage.store(value) def type_spec(self) -> TypeSpec: """Get the TypeSpec for this ABI type instance.""" @@ -300,7 +300,7 @@ def store_into(self, output: BaseType) -> Expr: f"ABI return subroutine deferred_expr is expected to be typed {output.type_spec().storage_type()}, " f"but has type {declaration.deferred_expr.type_of()}." ) - return output._data_storage.store_value(self.computation) + return output._data_storage.store(self.computation) ReturnedValue.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/type_test.py b/pyteal/ast/abi/type_test.py index b5134ef7d..30f39e0fc 100644 --- a/pyteal/ast/abi/type_test.py +++ b/pyteal/ast/abi/type_test.py @@ -17,7 +17,7 @@ def store_into(self, output: abi.BaseType) -> pt.Expr: raise pt.TealInputError( f"expected type_spec {self.type_spec} but get {output.type_spec()}" ) - return output._data_storage.store_value(self.encodings) + return output._data_storage.store(self.encodings) def test_ComputedType_use(): diff --git a/pyteal/ast/abi/uint.py b/pyteal/ast/abi/uint.py index e34daac9a..67d3ff428 100644 --- a/pyteal/ast/abi/uint.py +++ b/pyteal/ast/abi/uint.py @@ -17,7 +17,7 @@ from pyteal.ast.unaryexpr import Itob, Btoi from pyteal.ast.binaryexpr import GetByte, ExtractUint16, ExtractUint32, ExtractUint64 from pyteal.ast.ternaryexpr import SetByte -from pyteal.ast.abi.type import ComputedValue, TypeSpec, BaseType, DataStorageSchema +from pyteal.ast.abi.type import ComputedValue, TypeSpec, BaseType, AbstractVar NUM_BITS_IN_BYTE = 8 @@ -30,9 +30,7 @@ def uint_storage_type(size: int) -> TealType: return TealType.bytes -def uint_set( - size: int, uint_var: DataStorageSchema, value: Union[int, Expr, "Uint"] -) -> Expr: +def uint_set(size: int, uint_var: AbstractVar, value: Union[int, Expr, "Uint"]) -> Expr: if size > 64: raise NotImplementedError( "Uint operations have not yet been implemented for bit sizes larger than 64" @@ -50,17 +48,17 @@ def uint_set( checked = True if checked or size == 64: - return uint_var.store_value(cast(Expr, value)) + return uint_var.store(cast(Expr, value)) return Seq( - uint_var.store_value(cast(Expr, value)), - Assert(uint_var.load_value() < Int(2**size)), + uint_var.store(cast(Expr, value)), + Assert(uint_var.load() < Int(2**size)), ) def uint_decode( size: int, - uint_var: DataStorageSchema, + uint_var: AbstractVar, encoded: Expr, start_index: Optional[Expr], end_index: Optional[Expr], @@ -74,27 +72,27 @@ def uint_decode( if size == 64: if start_index is None: if end_index is None and length is None: - return uint_var.store_value(Btoi(encoded)) + return uint_var.store(Btoi(encoded)) start_index = Int(0) - return uint_var.store_value(ExtractUint64(encoded, start_index)) + return uint_var.store(ExtractUint64(encoded, start_index)) if start_index is None: start_index = Int(0) if size == 8: - return uint_var.store_value(GetByte(encoded, start_index)) + return uint_var.store(GetByte(encoded, start_index)) if size == 16: - return uint_var.store_value(ExtractUint16(encoded, start_index)) + return uint_var.store(ExtractUint16(encoded, start_index)) if size == 32: - return uint_var.store_value(ExtractUint32(encoded, start_index)) + return uint_var.store(ExtractUint32(encoded, start_index)) raise ValueError("Unsupported uint size: {}".format(size)) -def uint_encode(size: int, uint_var: Expr | DataStorageSchema) -> Expr: +def uint_encode(size: int, uint_var: Expr | AbstractVar) -> Expr: - if isinstance(uint_var, DataStorageSchema): - uint_var = uint_var.load_value() + if isinstance(uint_var, AbstractVar): + uint_var = uint_var.load() if size > 64: raise NotImplementedError( @@ -241,7 +239,7 @@ def get(self) -> Expr: The expression will have the type TealType.uint64. """ - return self._data_storage.load_value() + return self._data_storage.load() def set(self, value: Union[int, Expr, "Uint", ComputedValue["Uint"]]) -> Expr: """Set the value of this Uint to the input value. diff --git a/pyteal/ast/abi/uint_test.py b/pyteal/ast/abi/uint_test.py index d4b7cd137..d571e7aa6 100644 --- a/pyteal/ast/abi/uint_test.py +++ b/pyteal/ast/abi/uint_test.py @@ -307,7 +307,7 @@ def test_Uint_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedDecoding = value._data_storage.store_value( + expectedDecoding = value._data_storage.store( test.expectedDecoding(encoded, start_index, end_index, length) ) expected, _ = expectedDecoding.__teal__(options) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 70365d756..d509f980b 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -420,7 +420,7 @@ def handle_arg(arg: Expr | ScratchVar | abi.BaseType) -> Expr: elif isinstance(arg, Expr): return arg elif isinstance(arg, abi.BaseType): - return arg._data_storage.load_value() + return arg._data_storage.load() else: raise TealInputError( f"cannot handle current arg: {arg} to put it on stack" @@ -853,7 +853,7 @@ def var_n_loaded( f"ABI returning subroutine definition should evaluate to TealType.none, " f"while evaluate to {subroutine_body.type_of()}." ) - deferred_expr = output_carrying_abi._data_storage.load_value() + deferred_expr = output_carrying_abi._data_storage.load() # Arg usage "A" to be pick up and store in scratch parameters that have been placed on the stack # need to reverse order of argumentVars because the last argument will be on top of the stack From d93207d84a0c55983903b8947dda5e345d7030fb Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 10:42:18 -0400 Subject: [PATCH 047/157] per review comments, move storage model to AbstractVar, rough hack to make returned value type check deactivate --- pyteal/__init__.pyi | 1 + pyteal/ast/__init__.py | 3 ++- pyteal/ast/abi/__init__.py | 2 -- pyteal/ast/abi/address.py | 12 +++++----- pyteal/ast/abi/address_test.py | 24 ++++++++++---------- pyteal/ast/abi/array_base.py | 6 ++--- pyteal/ast/abi/array_dynamic.py | 8 +++---- pyteal/ast/abi/array_dynamic_test.py | 24 ++++++++++---------- pyteal/ast/abi/array_static.py | 10 ++++----- pyteal/ast/abi/array_static_test.py | 18 +++++++-------- pyteal/ast/abi/bool.py | 8 +++---- pyteal/ast/abi/bool_test.py | 22 +++++++++--------- pyteal/ast/abi/reference_type.py | 8 +++---- pyteal/ast/abi/reference_type_test.py | 10 ++++----- pyteal/ast/abi/string.py | 10 ++++----- pyteal/ast/abi/string_test.py | 22 +++++++++--------- pyteal/ast/abi/transaction.py | 8 +++---- pyteal/ast/abi/transaction_test.py | 2 +- pyteal/ast/abi/tuple.py | 6 ++--- pyteal/ast/abi/tuple_test.py | 10 ++++----- pyteal/ast/abi/type.py | 32 ++++++--------------------- pyteal/ast/abi/type_test.py | 2 +- pyteal/ast/abi/uint.py | 8 +++---- pyteal/ast/abi/uint_test.py | 22 +++++++++--------- pyteal/ast/scratchvar.py | 21 +++++++++++++++++- pyteal/ast/subroutine.py | 12 +++++----- 26 files changed, 152 insertions(+), 159 deletions(-) diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 40600d561..ed1d3c1e1 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -35,6 +35,7 @@ from pyteal.config import ( __all__ = [ "ABIReturnSubroutine", + "AbstractVar", "AccountParam", "AccountParamObject", "Add", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 1ca49a2e5..3d2671068 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -165,7 +165,7 @@ ScratchStackStore, ScratchStore, ) -from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar +from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar, AbstractVar from pyteal.ast.maybe import MaybeValue from pyteal.ast.multi import MultiValue from pyteal.ast.opup import OpUp, OpUpMode, OpUpFeeSource @@ -305,6 +305,7 @@ "ScratchStore", "DynamicScratchVar", "ScratchVar", + "AbstractVar", "MaybeValue", "MultiValue", "OpUp", diff --git a/pyteal/ast/abi/__init__.py b/pyteal/ast/abi/__init__.py index 4baa3bc16..bb2a0d1b2 100644 --- a/pyteal/ast/abi/__init__.py +++ b/pyteal/ast/abi/__init__.py @@ -9,7 +9,6 @@ BaseType, ComputedValue, ReturnedValue, - AbstractVar, FrameStorage, ScratchStorage, ) @@ -174,7 +173,6 @@ "type_specs_from_signature", "make", "size_of", - "AbstractVar", "FrameStorage", "ScratchStorage", "algosdk_from_annotation", diff --git a/pyteal/ast/abi/address.py b/pyteal/ast/abi/address.py index 0fea62c8a..d0413cf6c 100644 --- a/pyteal/ast/abi/address.py +++ b/pyteal/ast/abi/address.py @@ -56,7 +56,7 @@ def get(self) -> Expr: The expression will have the type TealType.bytes. """ - return self._data_storage.load() + return self.stored_value.load() def set( self, @@ -108,25 +108,25 @@ def set( or value.type_spec() == StaticArrayTypeSpec(ByteTypeSpec(), AddressLength.Bytes) ): - return self._data_storage.store(value._data_storage.load()) + return self.stored_value.store(value.stored_value.load()) raise TealInputError( f"Got {value} with type spec {value.type_spec()}, expected AddressTypeSpec" ) case str(): # Addr throws if value is invalid address - return self._data_storage.store(Addr(value)) + return self.stored_value.store(Addr(value)) case bytes(): if len(value) == AddressLength.Bytes: - return self._data_storage.store(Bytes(value)) + return self.stored_value.store(Bytes(value)) raise TealInputError( f"Got bytes with length {len(value)}, expected {AddressLength.Bytes}" ) case Expr(): return Seq( - self._data_storage.store(value), + self.stored_value.store(value), Assert( - Len(self._data_storage.load()) == Int(AddressLength.Bytes.value) + Len(self.stored_value.load()) == Int(AddressLength.Bytes.value) ), ) case CollectionSequence(): diff --git a/pyteal/ast/abi/address_test.py b/pyteal/ast/abi/address_test.py index ccecb0ecf..d115082cd 100644 --- a/pyteal/ast/abi/address_test.py +++ b/pyteal/ast/abi/address_test.py @@ -53,7 +53,7 @@ def test_Address_encode(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -86,7 +86,7 @@ def test_Address_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expectedExpr = value._data_storage.store( + expectedExpr = value.stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -117,7 +117,7 @@ def test_Address_get(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -139,12 +139,12 @@ def test_Address_set_StaticArray(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value_to_set._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value_to_set.stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -174,7 +174,7 @@ def test_Address_set_str(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -203,7 +203,7 @@ def test_Address_set_bytes(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -236,12 +236,12 @@ def test_Address_set_expr(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.int, AddressLength.Bytes.value), @@ -270,12 +270,12 @@ def test_Address_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, + cast(pt.ScratchVar, other.stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -307,7 +307,7 @@ def test_Address_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/array_base.py b/pyteal/ast/abi/array_base.py index 417e401e1..aea164c81 100644 --- a/pyteal/ast/abi/array_base.py +++ b/pyteal/ast/abi/array_base.py @@ -104,7 +104,7 @@ def decode( extracted = substring_for_decoding( encoded, start_index=start_index, end_index=end_index, length=length ) - return self._data_storage.store(extracted) + return self.stored_value.store(extracted) def set(self, values: Sequence[T]) -> Expr: """Set the ABI array with a sequence of ABI type variables. @@ -142,7 +142,7 @@ def set(self, values: Sequence[T]) -> Expr: length_prefix = Seq(length_tmp.set(len(values)), length_tmp.encode()) encoded = Concat(length_prefix, encoded) - return self._data_storage.store(encoded) + return self.stored_value.store(encoded) def encode(self) -> Expr: """Encode the ABI array to be a byte string. @@ -150,7 +150,7 @@ def encode(self) -> Expr: Returns: A PyTeal expression that encodes this ABI array to a byte string. """ - return self._data_storage.load() + return self.stored_value.load() @abstractmethod def length(self) -> Expr: diff --git a/pyteal/ast/abi/array_dynamic.py b/pyteal/ast/abi/array_dynamic.py index a39373324..9d53e0559 100644 --- a/pyteal/ast/abi/array_dynamic.py +++ b/pyteal/ast/abi/array_dynamic.py @@ -79,7 +79,7 @@ def set( raise TealInputError( f"Cannot assign type {values.type_spec()} to {self.type_spec()}" ) - return self._data_storage.store(values.encode()) + return self.stored_value.store(values.encode()) return super().set(values) def length(self) -> Expr: @@ -165,10 +165,10 @@ def set( match values: case bytes() | bytearray(): - return self._data_storage.store(_encoded_byte_string(values)) + return self.stored_value.store(_encoded_byte_string(values)) case Expr(): return _store_encoded_expr_byte_string_into_var( - values, self._data_storage + values, self.stored_value ) return super().set(values) @@ -181,7 +181,7 @@ def get(self) -> Expr: Returns: A Pyteal expression that loads byte encoding of this DynamicBytes, and drop the first uint16 DynamicArray length encoding. """ - return Suffix(self._data_storage.load(), Int(2)) + return Suffix(self.stored_value.load(), Int(2)) DynamicBytes.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/array_dynamic_test.py b/pyteal/ast/abi/array_dynamic_test.py index 589d52664..e8e930787 100644 --- a/pyteal/ast/abi/array_dynamic_test.py +++ b/pyteal/ast/abi/array_dynamic_test.py @@ -106,7 +106,7 @@ def test_DynamicArray_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value._data_storage.store( + expectedExpr = value.stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -141,7 +141,7 @@ def test_DynamicArray_set_values(): assert not expr.has_return() length_tmp = abi.Uint16() - expectedExpr = value._data_storage.store( + expectedExpr = value.stored_value.store( pt.Concat( pt.Seq(length_tmp.set(len(values)), length_tmp.encode()), _encode_tuple(values), @@ -185,12 +185,12 @@ def test_DynamicArray_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, otherArray._data_storage).scratchvar.slot, + cast(pt.ScratchVar, otherArray.stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -218,7 +218,7 @@ def test_DynamicArray_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -268,7 +268,7 @@ def test_DynamicBytes_set_py_bytes(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -299,12 +299,12 @@ def test_DynamicBytes_set_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.itob), @@ -312,13 +312,13 @@ def test_DynamicBytes_set_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.concat), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -343,7 +343,7 @@ def test_DynamicBytes_get(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.extract, 2, 0), ] @@ -365,7 +365,7 @@ def test_DynamicArray_encode(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/array_static.py b/pyteal/ast/abi/array_static.py index a631687f3..7744a6edb 100644 --- a/pyteal/ast/abi/array_static.py +++ b/pyteal/ast/abi/array_static.py @@ -109,7 +109,7 @@ def set( raise TealInputError( f"Cannot assign type {values.type_spec()} to {self.type_spec()}" ) - return self._data_storage.store(values.encode()) + return self.stored_value.store(values.encode()) if self.type_spec().length_static() != len(values): raise TealInputError( @@ -207,11 +207,11 @@ def set( raise TealInputError( f"Got bytes with length {len(values)}, expect {self.type_spec().length_static()}" ) - return self._data_storage.store(Bytes(values)) + return self.stored_value.store(Bytes(values)) case Expr(): return Seq( - self._data_storage.store(values), - Assert(self.length() == Len(self._data_storage.load())), + self.stored_value.store(values), + Assert(self.length() == Len(self.stored_value.load())), ) return super().set(values) @@ -222,7 +222,7 @@ def get(self) -> Expr: Returns: A Pyteal expression that loads byte encoding of this StaticBytes. """ - return self._data_storage.load() + return self.stored_value.load() StaticBytes.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/array_static_test.py b/pyteal/ast/abi/array_static_test.py index 7174c2ebb..7c2e914ec 100644 --- a/pyteal/ast/abi/array_static_test.py +++ b/pyteal/ast/abi/array_static_test.py @@ -159,7 +159,7 @@ def test_StaticArray_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value._data_storage.store( + expectedExpr = value.stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -202,7 +202,7 @@ def test_StaticArray_set_values(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value._data_storage.store(_encode_tuple(values)) + expectedExpr = value.stored_value.store(_encode_tuple(values)) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) @@ -237,12 +237,12 @@ def test_StaticArray_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, otherArray._data_storage).scratchvar.slot, + cast(pt.ScratchVar, otherArray.stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -270,7 +270,7 @@ def test_StaticArray_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -317,7 +317,7 @@ def test_StaticBytes_set_py_bytes(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -352,13 +352,13 @@ def test_StaticBytes_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.int, 32), pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.eq), @@ -381,7 +381,7 @@ def test_StaticArray_encode(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/bool.py b/pyteal/ast/abi/bool.py index 6d42c2fdd..13552b6db 100644 --- a/pyteal/ast/abi/bool.py +++ b/pyteal/ast/abi/bool.py @@ -50,7 +50,7 @@ def get(self) -> Expr: expression that evaluates to 0 will be returned. In either case, the expression will have the type TealType.uint64. """ - return self._data_storage.load() + return self.stored_value.load() def set(self, value: Union[bool, Expr, "Bool", ComputedValue["Bool"]]) -> Expr: """Set the value of this Bool to the input value. @@ -85,10 +85,10 @@ def set(self, value: Union[bool, Expr, "Bool", ComputedValue["Bool"]]) -> Expr: checked = True if checked: - return self._data_storage.store(value) + return self.stored_value.store(value) # Not(Not(value)) coerces all values greater than 0 to 1 - return self._data_storage.store(Not(Not(value))) + return self.stored_value.store(Not(Not(value))) def decode( self, @@ -103,7 +103,7 @@ def decode( return self.decode_bit(encoded, start_index * Int(NUM_BITS_IN_BYTE)) def decode_bit(self, encoded, bit_index: Expr) -> Expr: - return self._data_storage.store(GetBit(encoded, bit_index)) + return self.stored_value.store(GetBit(encoded, bit_index)) def encode(self) -> Expr: return SetBit(Bytes(b"\x00"), Int(0), self.get()) diff --git a/pyteal/ast/abi/bool_test.py b/pyteal/ast/abi/bool_test.py index 4299b72ce..1cf881d55 100644 --- a/pyteal/ast/abi/bool_test.py +++ b/pyteal/ast/abi/bool_test.py @@ -56,7 +56,7 @@ def test_Bool_set_static(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -85,7 +85,7 @@ def test_Bool_set_expr(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -110,12 +110,12 @@ def test_Bool_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, + cast(pt.ScratchVar, other.stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -144,7 +144,7 @@ def test_Bool_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -171,7 +171,7 @@ def test_Bool_get(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -203,9 +203,7 @@ def test_Bool_decode(): pt.TealOp( None, pt.Op.store, - cast( - abi.ScratchStorage, value._data_storage - ).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -234,7 +232,7 @@ def test_Bool_decode_bit(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -260,7 +258,7 @@ def test_Bool_encode(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.setbit), ] @@ -444,7 +442,7 @@ class EncodeSeqTest(NamedTuple): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, testType._data_storage).scratchvar.slot, + cast(pt.ScratchVar, testType.stored_value).slot, ), pt.TealOp(None, pt.Op.setbit), ] diff --git a/pyteal/ast/abi/reference_type.py b/pyteal/ast/abi/reference_type.py index aa0709ffe..f4882fc97 100644 --- a/pyteal/ast/abi/reference_type.py +++ b/pyteal/ast/abi/reference_type.py @@ -58,7 +58,7 @@ def referenced_index(self) -> Expr: If this reference type is an application or asset, note that this DOES NOT return the application or asset ID. See :code:`application_id()` or :code:`asset_id()` for that. """ - return self._data_storage.load() + return self.stored_value.load() def decode( self, @@ -70,7 +70,7 @@ def decode( ) -> Expr: return uint_decode( self.type_spec().bit_size(), - self._data_storage, + self.stored_value, encoded, start_index, end_index, @@ -107,7 +107,7 @@ def __init__(self) -> None: def address(self) -> Expr: """Get the address of the account.""" - return Txn.accounts[self._data_storage.load()] + return Txn.accounts[self.stored_value.load()] def params(self) -> AccountParamObject: """Get information about the account.""" @@ -205,7 +205,7 @@ def __init__(self) -> None: def application_id(self) -> Expr: """Get the ID of the application.""" - return Txn.applications[self._data_storage.load()] + return Txn.applications[self.stored_value.load()] def params(self) -> AppParamObject: """Get information about the application's parameters.""" diff --git a/pyteal/ast/abi/reference_type_test.py b/pyteal/ast/abi/reference_type_test.py index edc0a857c..4ec862e66 100644 --- a/pyteal/ast/abi/reference_type_test.py +++ b/pyteal/ast/abi/reference_type_test.py @@ -26,7 +26,7 @@ def test_ReferenceType_referenced_index(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -61,7 +61,7 @@ def test_ReferenceType_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expected_decoding = value._data_storage.store( + expected_decoding = value.stored_value.store( pt.GetByte( encoded, start_index if start_index is not None else pt.Int(0), @@ -117,7 +117,7 @@ def test_Account_address(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.txnas, "Accounts"), ] @@ -204,7 +204,7 @@ def test_Asset_asset_id(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.txnas, "Assets"), ] @@ -298,7 +298,7 @@ def test_Application_application_id(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.txnas, "Applications"), ] diff --git a/pyteal/ast/abi/string.py b/pyteal/ast/abi/string.py index f91eb272f..ac5866cb2 100644 --- a/pyteal/ast/abi/string.py +++ b/pyteal/ast/abi/string.py @@ -68,7 +68,7 @@ def get(self) -> Expr: The expression will have the type TealType.bytes. """ return Suffix( - self._data_storage.load(), Int(Uint16TypeSpec().byte_length_static()) + self.stored_value.load(), Int(Uint16TypeSpec().byte_length_static()) ) def set( @@ -111,18 +111,18 @@ def set( if value.type_spec() == StringTypeSpec() or ( value.type_spec() == DynamicArrayTypeSpec(ByteTypeSpec()) ): - return self._data_storage.store(value._data_storage.load()) + return self.stored_value.store(value.stored_value.load()) raise TealInputError( f"Got {value} with type spec {value.type_spec()}, expected {StringTypeSpec}" ) case bytes() | bytearray(): - return self._data_storage.store(_encoded_byte_string(value)) + return self.stored_value.store(_encoded_byte_string(value)) case str(): - return self._data_storage.store(_encoded_byte_string(value.encode())) + return self.stored_value.store(_encoded_byte_string(value.encode())) case Expr(): return _store_encoded_expr_byte_string_into_var( - value, self._data_storage + value, self.stored_value ) case CollectionSequence(): return super().set(cast(Sequence[Byte], value)) diff --git a/pyteal/ast/abi/string_test.py b/pyteal/ast/abi/string_test.py index e335da1a1..c60ac52f4 100644 --- a/pyteal/ast/abi/string_test.py +++ b/pyteal/ast/abi/string_test.py @@ -44,7 +44,7 @@ def test_String_encode(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -76,7 +76,7 @@ def test_DynamicArray_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expectedExpr = value._data_storage.store( + expectedExpr = value.stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -107,7 +107,7 @@ def test_String_get(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.extract, 2, 0), ] @@ -143,7 +143,7 @@ def test_String_set_static(value_to_set, value_encoded): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -174,12 +174,12 @@ def test_String_set_expr(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.itob), @@ -187,13 +187,13 @@ def test_String_set_expr(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.concat), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -222,12 +222,12 @@ def test_String_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, + cast(pt.ScratchVar, other.stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -259,7 +259,7 @@ def test_String_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/transaction.py b/pyteal/ast/abi/transaction.py index 1f3ea9ba2..aeb5c7a33 100644 --- a/pyteal/ast/abi/transaction.py +++ b/pyteal/ast/abi/transaction.py @@ -82,16 +82,16 @@ def _set_index( case ComputedValue(): return self._set_with_computed_type(value) case BaseType(): - return self._data_storage.store(self._data_storage.load()) + return self.stored_value.store(self.stored_value.load()) case int(): - return self._data_storage.store(Int(value)) + return self.stored_value.store(Int(value)) case Expr(): - return self._data_storage.store(value) + return self.stored_value.store(value) case _: raise TealInputError(f"Cant store a {type(value)} in a Transaction") def index(self) -> Expr: - return self._data_storage.load() + return self.stored_value.load() def decode( self, diff --git a/pyteal/ast/abi/transaction_test.py b/pyteal/ast/abi/transaction_test.py index e21802950..b4c27a97c 100644 --- a/pyteal/ast/abi/transaction_test.py +++ b/pyteal/ast/abi/transaction_test.py @@ -134,7 +134,7 @@ def test_Transaction__set_index(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, tv.t._data_storage).scratchvar.slot, + cast(pt.ScratchVar, tv.t.stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/tuple.py b/pyteal/ast/abi/tuple.py index efea10e36..bc1966414 100644 --- a/pyteal/ast/abi/tuple.py +++ b/pyteal/ast/abi/tuple.py @@ -309,7 +309,7 @@ def decode( extracted = substring_for_decoding( encoded, start_index=start_index, end_index=end_index, length=length ) - return self._data_storage.store(extracted) + return self.stored_value.store(extracted) @overload def set(self, *values: BaseType) -> Expr: @@ -352,10 +352,10 @@ def set(self, *values): ) if not all(myTypes[i] == values[i].type_spec() for i in range(len(myTypes))): raise TealInputError("Input values do not match type") - return self._data_storage.store(_encode_tuple(values)) + return self.stored_value.store(_encode_tuple(values)) def encode(self) -> Expr: - return self._data_storage.load() + return self.stored_value.load() def length(self) -> Expr: """Get the number of values this tuple holds as an Expr.""" diff --git a/pyteal/ast/abi/tuple_test.py b/pyteal/ast/abi/tuple_test.py index ad231784f..a761d88af 100644 --- a/pyteal/ast/abi/tuple_test.py +++ b/pyteal/ast/abi/tuple_test.py @@ -623,7 +623,7 @@ def test_Tuple_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = tupleValue._data_storage.store( + expectedExpr = tupleValue.stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -672,9 +672,7 @@ def test_Tuple_set(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = tupleValue._data_storage.store( - _encode_tuple([uint8, uint16, uint32]) - ) + expectedExpr = tupleValue.stored_value.store(_encode_tuple([uint8, uint16, uint32])) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) @@ -706,7 +704,7 @@ def test_Tuple_set_Computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, tupleValue._data_storage).scratchvar.slot, + cast(pt.ScratchVar, tupleValue.stored_value).slot, ), ] ) @@ -737,7 +735,7 @@ def test_Tuple_encode(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, tupleValue._data_storage).scratchvar.slot, + cast(pt.ScratchVar, tupleValue.stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index 3ae5d585c..2e9027c5d 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -4,7 +4,7 @@ from pyteal.errors import TealInputError from pyteal.types import TealType from pyteal.ast.expr import Expr -from pyteal.ast.scratchvar import ScratchVar +from pyteal.ast.scratchvar import ScratchVar, AbstractVar from pyteal.ast.seq import Seq @@ -65,23 +65,6 @@ def __str__(self) -> str: TypeSpec.__module__ = "pyteal.abi" -class AbstractVar(ABC): - @abstractmethod - def store(self, value: Expr) -> Expr: - pass - - @abstractmethod - def load(self) -> Expr: - pass - - @abstractmethod - def storage_type(self) -> TealType: - pass - - -AbstractVar.__module__ = "pyteal" - - class ScratchStorage(AbstractVar): def __init__(self, storage_type: TealType) -> None: super().__init__() @@ -135,18 +118,16 @@ def __init__(self, spec: TypeSpec) -> None: """Create a new BaseType.""" super().__init__() self._type_spec: Final[TypeSpec] = spec - self._data_storage: AbstractVar = ScratchStorage(spec.storage_type()) - - # self.stored_value: Final = ScratchVar(spec.storage_type()) + self.stored_value: AbstractVar = ScratchVar(spec.storage_type()) def _set_data_source(self, storage: AbstractVar) -> None: - self._data_storage = storage + self.stored_value = storage def _load_value(self) -> Expr: - return self._data_storage.load() + return self.stored_value.load() def _store_value(self, value: Expr) -> Expr: - return self._data_storage.store(value) + return self.stored_value.store(value) def type_spec(self) -> TypeSpec: """Get the TypeSpec for this ABI type instance.""" @@ -300,7 +281,8 @@ def store_into(self, output: BaseType) -> Expr: f"ABI return subroutine deferred_expr is expected to be typed {output.type_spec().storage_type()}, " f"but has type {declaration.deferred_expr.type_of()}." ) - return output._data_storage.store(self.computation) + assert isinstance(output.stored_value, ScratchVar) + return output.stored_value.slot.store(self.computation) ReturnedValue.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/type_test.py b/pyteal/ast/abi/type_test.py index 30f39e0fc..56a9e6c76 100644 --- a/pyteal/ast/abi/type_test.py +++ b/pyteal/ast/abi/type_test.py @@ -17,7 +17,7 @@ def store_into(self, output: abi.BaseType) -> pt.Expr: raise pt.TealInputError( f"expected type_spec {self.type_spec} but get {output.type_spec()}" ) - return output._data_storage.store(self.encodings) + return output.stored_value.store(self.encodings) def test_ComputedType_use(): diff --git a/pyteal/ast/abi/uint.py b/pyteal/ast/abi/uint.py index 67d3ff428..0a99eb27f 100644 --- a/pyteal/ast/abi/uint.py +++ b/pyteal/ast/abi/uint.py @@ -239,7 +239,7 @@ def get(self) -> Expr: The expression will have the type TealType.uint64. """ - return self._data_storage.load() + return self.stored_value.load() def set(self, value: Union[int, Expr, "Uint", ComputedValue["Uint"]]) -> Expr: """Set the value of this Uint to the input value. @@ -274,7 +274,7 @@ def set(self, value: Union[int, Expr, "Uint", ComputedValue["Uint"]]) -> Expr: value.type_spec(), self.type_spec() ) ) - return uint_set(self.type_spec().bit_size(), self._data_storage, value) + return uint_set(self.type_spec().bit_size(), self.stored_value, value) def decode( self, @@ -286,7 +286,7 @@ def decode( ) -> Expr: return uint_decode( self.type_spec().bit_size(), - self._data_storage, + self.stored_value, encoded, start_index, end_index, @@ -294,7 +294,7 @@ def decode( ) def encode(self) -> Expr: - return uint_encode(self.type_spec().bit_size(), self._data_storage) + return uint_encode(self.type_spec().bit_size(), self.stored_value) Uint.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/uint_test.py b/pyteal/ast/abi/uint_test.py index d571e7aa6..26ba3541f 100644 --- a/pyteal/ast/abi/uint_test.py +++ b/pyteal/ast/abi/uint_test.py @@ -142,7 +142,7 @@ def test_Uint_set_static(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -174,7 +174,7 @@ def test_Uint_set_expr(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.int, test.maxValue + 1), pt.TealOp(None, pt.Op.lt), @@ -189,7 +189,7 @@ def test_Uint_set_expr(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] + upperBoundCheck @@ -216,12 +216,12 @@ def test_Uint_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, + cast(pt.ScratchVar, other.stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -253,7 +253,7 @@ def test_Uint_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -281,7 +281,7 @@ def test_Uint_get(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -307,7 +307,7 @@ def test_Uint_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedDecoding = value._data_storage.store( + expectedDecoding = value.stored_value.store( test.expectedDecoding(encoded, start_index, end_index, length) ) expected, _ = expectedDecoding.__teal__(options) @@ -359,14 +359,12 @@ def test_ByteUint8_mutual_conversion(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, + cast(pt.ScratchVar, other.stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast( - abi.ScratchStorage, type_b_instance._data_storage - ).scratchvar.slot, + cast(pt.ScratchVar, type_b_instance.stored_value).slot, ), ] ) diff --git a/pyteal/ast/scratchvar.py b/pyteal/ast/scratchvar.py index 81ce27fff..44d422782 100644 --- a/pyteal/ast/scratchvar.py +++ b/pyteal/ast/scratchvar.py @@ -1,3 +1,5 @@ +from abc import ABC, abstractmethod + from pyteal.errors import TealInputError from pyteal.types import TealType, require_type @@ -5,7 +7,24 @@ from pyteal.ast.scratch import ScratchSlot, ScratchLoad, ScratchStore -class ScratchVar: +class AbstractVar(ABC): + @abstractmethod + def store(self, value: Expr) -> Expr: + pass + + @abstractmethod + def load(self) -> Expr: + pass + + @abstractmethod + def storage_type(self) -> TealType: + pass + + +AbstractVar.__module__ = "pyteal" + + +class ScratchVar(AbstractVar): """ Interface around Scratch space, similar to get/put local/global state diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index d509f980b..437c9535d 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -378,7 +378,7 @@ def __init__( elif isinstance(arg, ScratchVar): arg_type = arg.type elif isinstance(arg, abi.BaseType): - arg_type = cast(abi.BaseType, arg)._data_storage.storage_type() + arg_type = cast(abi.BaseType, arg).stored_value.storage_type() else: raise TealInputError( f"Subroutine argument {arg} at index {i} was of unexpected Python type {type(arg)}" @@ -420,7 +420,7 @@ def handle_arg(arg: Expr | ScratchVar | abi.BaseType) -> Expr: elif isinstance(arg, Expr): return arg elif isinstance(arg, abi.BaseType): - return arg._data_storage.load() + return arg.stored_value.load() else: raise TealInputError( f"cannot handle current arg: {arg} to put it on stack" @@ -791,8 +791,6 @@ def evaluate_subroutine(subroutine: SubroutineDefinition) -> SubroutineDeclarati def var_n_loaded( param: str, ) -> tuple[ScratchVar, ScratchVar | abi.BaseType | Expr]: - from pyteal.ast.abi.type import ScratchStorage - loaded_var: ScratchVar | abi.BaseType | Expr argument_var: ScratchVar @@ -801,11 +799,11 @@ def var_n_loaded( loaded_var = argument_var elif param in subroutine.abi_args: internal_abi_var = subroutine.abi_args[param].new_instance() - if not isinstance(internal_abi_var._data_storage, ScratchStorage): + if not isinstance(internal_abi_var.stored_value, ScratchVar): raise TealInternalError( "subroutine ABI args must have data schema being ScratchVarStorage" ) - argument_var = internal_abi_var._data_storage.scratchvar + argument_var = internal_abi_var.stored_value loaded_var = internal_abi_var else: argument_var = ScratchVar(TealType.anytype) @@ -853,7 +851,7 @@ def var_n_loaded( f"ABI returning subroutine definition should evaluate to TealType.none, " f"while evaluate to {subroutine_body.type_of()}." ) - deferred_expr = output_carrying_abi._data_storage.load() + deferred_expr = output_carrying_abi.stored_value.load() # Arg usage "A" to be pick up and store in scratch parameters that have been placed on the stack # need to reverse order of argumentVars because the last argument will be on top of the stack From 71ad8a65f81d0e294e469bd656bb7c64e069e311 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 10:51:50 -0400 Subject: [PATCH 048/157] better type checking in scratch slot --- pyteal/ast/abi/type.py | 3 +-- pyteal/ast/scratchvar.py | 9 +++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index 2e9027c5d..f9368cbda 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -281,8 +281,7 @@ def store_into(self, output: BaseType) -> Expr: f"ABI return subroutine deferred_expr is expected to be typed {output.type_spec().storage_type()}, " f"but has type {declaration.deferred_expr.type_of()}." ) - assert isinstance(output.stored_value, ScratchVar) - return output.stored_value.slot.store(self.computation) + return output.stored_value.store(self.computation) ReturnedValue.__module__ = "pyteal.abi" diff --git a/pyteal/ast/scratchvar.py b/pyteal/ast/scratchvar.py index 44d422782..7b4962f97 100644 --- a/pyteal/ast/scratchvar.py +++ b/pyteal/ast/scratchvar.py @@ -1,7 +1,7 @@ from abc import ABC, abstractmethod from pyteal.errors import TealInputError -from pyteal.types import TealType, require_type +from pyteal.types import TealType, require_type, types_match from pyteal.ast.expr import Expr from pyteal.ast.scratch import ScratchSlot, ScratchLoad, ScratchStore @@ -61,7 +61,12 @@ def store(self, value: Expr) -> Expr: Args: value: The value to store. Must conform to this ScratchVar's type. """ - require_type(value, self.type) + from pyteal.ast.subroutine import SubroutineCall + + if not isinstance(value, SubroutineCall) or not value.output_kwarg: + require_type(value, self.type) + else: + assert types_match(value.output_kwarg.abi_type.storage_type(), self.type) return self.slot.store(value) def load(self) -> ScratchLoad: From 921bf85b656a78c6ccfea7a7a015c60b6c4f85f3 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 10:55:21 -0400 Subject: [PATCH 049/157] reformat imports and class decl for FrameVar and ScratchVar --- pyteal/__init__.pyi | 1 + pyteal/ast/__init__.py | 3 ++- pyteal/ast/abi/__init__.py | 11 +--------- pyteal/ast/abi/type.py | 41 -------------------------------------- pyteal/ast/frame.py | 24 ++++++++++++++++++++++ 5 files changed, 28 insertions(+), 52 deletions(-) diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index ed1d3c1e1..baf5ae050 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -122,6 +122,7 @@ __all__ = [ "For", "FrameBury", "FrameDig", + "FrameStorage", "Ge", "GeneratedID", "GetBit", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 3d2671068..0f2bcaa34 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -155,7 +155,7 @@ from pyteal.ast.for_ import For from pyteal.ast.break_ import Break from pyteal.ast.continue_ import Continue -from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN, Bury +from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN, Bury, FrameStorage # misc from pyteal.ast.scratch import ( @@ -344,6 +344,7 @@ "Bury", "DupN", "PopN", + "FrameStorage", "Router", "CallConfig", "MethodConfig", diff --git a/pyteal/ast/abi/__init__.py b/pyteal/ast/abi/__init__.py index bb2a0d1b2..f1cb3a58c 100644 --- a/pyteal/ast/abi/__init__.py +++ b/pyteal/ast/abi/__init__.py @@ -4,14 +4,7 @@ Address, AddressLength, ) -from pyteal.ast.abi.type import ( - TypeSpec, - BaseType, - ComputedValue, - ReturnedValue, - FrameStorage, - ScratchStorage, -) +from pyteal.ast.abi.type import TypeSpec, BaseType, ComputedValue, ReturnedValue from pyteal.ast.abi.bool import BoolTypeSpec, Bool from pyteal.ast.abi.uint import ( UintTypeSpec, @@ -173,8 +166,6 @@ "type_specs_from_signature", "make", "size_of", - "FrameStorage", - "ScratchStorage", "algosdk_from_annotation", "algosdk_from_type_spec", "contains_type_spec", diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index f9368cbda..b87fe1282 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -65,47 +65,6 @@ def __str__(self) -> str: TypeSpec.__module__ = "pyteal.abi" -class ScratchStorage(AbstractVar): - def __init__(self, storage_type: TealType) -> None: - super().__init__() - self.scratchvar: Final[ScratchVar] = ScratchVar(storage_type) - - def load(self) -> Expr: - return self.scratchvar.load() - - def store(self, value: Expr) -> Expr: - return self.scratchvar.slot.store(value) - - def storage_type(self) -> TealType: - return self.scratchvar.storage_type() - - -ScratchStorage.__module__ = "pyteal" - - -class FrameStorage(AbstractVar): - def __init__(self, storage_type: TealType, stack_depth: int) -> None: - super().__init__() - self.stack_type = storage_type - self.stack_depth = stack_depth - - def storage_type(self) -> TealType: - return self.stack_type - - def store(self, value: Expr) -> Expr: - from pyteal.ast import FrameBury - - return FrameBury(value, self.stack_depth) - - def load(self) -> Expr: - from pyteal.ast import FrameDig - - return FrameDig(self.stack_depth) - - -FrameStorage.__module__ = "pyteal" - - class BaseType(ABC): """The abstract base class for all ABI type instances. diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 68ce3a2f2..25aa437fc 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -1,6 +1,7 @@ from typing import TYPE_CHECKING from pyteal.ast.expr import Expr +from pyteal.ast.scratchvar import AbstractVar from pyteal.types import TealType, require_type from pyteal.errors import TealInputError, verifyProgramVersion from pyteal.ir import TealBlock, TealSimpleBlock, TealOp, Op @@ -101,6 +102,29 @@ def has_return(self) -> bool: FrameBury.__module__ = "pyteal" +class FrameStorage(AbstractVar): + def __init__(self, storage_type: TealType, stack_depth: int) -> None: + super().__init__() + self.stack_type = storage_type + self.stack_depth = stack_depth + + def storage_type(self) -> TealType: + return self.stack_type + + def store(self, value: Expr) -> Expr: + from pyteal.ast import FrameBury + + return FrameBury(value, self.stack_depth) + + def load(self) -> Expr: + from pyteal.ast import FrameDig + + return FrameDig(self.stack_depth) + + +FrameStorage.__module__ = "pyteal" + + class Bury(Expr): def __init__(self, value: Expr, depth: int): super().__init__() From 304f273990572b0f457d742f834824cf741f5c06 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 11:27:24 -0400 Subject: [PATCH 050/157] still thinking about hiding the _stored value --- pyteal/ast/abi/address.py | 12 ++++++------ pyteal/ast/abi/address_test.py | 24 ++++++++++++------------ pyteal/ast/abi/array_base.py | 6 +++--- pyteal/ast/abi/array_dynamic.py | 8 ++++---- pyteal/ast/abi/array_dynamic_test.py | 24 ++++++++++++------------ pyteal/ast/abi/array_static.py | 10 +++++----- pyteal/ast/abi/array_static_test.py | 18 +++++++++--------- pyteal/ast/abi/bool.py | 8 ++++---- pyteal/ast/abi/bool_test.py | 20 ++++++++++---------- pyteal/ast/abi/reference_type.py | 8 ++++---- pyteal/ast/abi/reference_type_test.py | 10 +++++----- pyteal/ast/abi/string.py | 10 +++++----- pyteal/ast/abi/string_test.py | 22 +++++++++++----------- pyteal/ast/abi/transaction.py | 8 ++++---- pyteal/ast/abi/transaction_test.py | 2 +- pyteal/ast/abi/tuple.py | 6 +++--- pyteal/ast/abi/tuple_test.py | 10 ++++++---- pyteal/ast/abi/type.py | 10 +++++----- pyteal/ast/abi/type_test.py | 2 +- pyteal/ast/abi/uint.py | 8 ++++---- pyteal/ast/abi/uint_test.py | 20 ++++++++++---------- pyteal/ast/subroutine.py | 10 +++++----- 22 files changed, 129 insertions(+), 127 deletions(-) diff --git a/pyteal/ast/abi/address.py b/pyteal/ast/abi/address.py index d0413cf6c..d8ad3cbc2 100644 --- a/pyteal/ast/abi/address.py +++ b/pyteal/ast/abi/address.py @@ -56,7 +56,7 @@ def get(self) -> Expr: The expression will have the type TealType.bytes. """ - return self.stored_value.load() + return self._stored_value.load() def set( self, @@ -108,25 +108,25 @@ def set( or value.type_spec() == StaticArrayTypeSpec(ByteTypeSpec(), AddressLength.Bytes) ): - return self.stored_value.store(value.stored_value.load()) + return self._stored_value.store(value._stored_value.load()) raise TealInputError( f"Got {value} with type spec {value.type_spec()}, expected AddressTypeSpec" ) case str(): # Addr throws if value is invalid address - return self.stored_value.store(Addr(value)) + return self._stored_value.store(Addr(value)) case bytes(): if len(value) == AddressLength.Bytes: - return self.stored_value.store(Bytes(value)) + return self._stored_value.store(Bytes(value)) raise TealInputError( f"Got bytes with length {len(value)}, expected {AddressLength.Bytes}" ) case Expr(): return Seq( - self.stored_value.store(value), + self._stored_value.store(value), Assert( - Len(self.stored_value.load()) == Int(AddressLength.Bytes.value) + Len(self._stored_value.load()) == Int(AddressLength.Bytes.value) ), ) case CollectionSequence(): diff --git a/pyteal/ast/abi/address_test.py b/pyteal/ast/abi/address_test.py index d115082cd..c70cbe5ea 100644 --- a/pyteal/ast/abi/address_test.py +++ b/pyteal/ast/abi/address_test.py @@ -53,7 +53,7 @@ def test_Address_encode(): pt.TealOp( expr, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -86,7 +86,7 @@ def test_Address_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expectedExpr = value.stored_value.store( + expectedExpr = value._stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -117,7 +117,7 @@ def test_Address_get(): pt.TealOp( expr, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -139,12 +139,12 @@ def test_Address_set_StaticArray(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value_to_set.stored_value).slot, + cast(pt.ScratchVar, value_to_set._stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -174,7 +174,7 @@ def test_Address_set_str(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -203,7 +203,7 @@ def test_Address_set_bytes(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -236,12 +236,12 @@ def test_Address_set_expr(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.int, AddressLength.Bytes.value), @@ -270,12 +270,12 @@ def test_Address_set_copy(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, other.stored_value).slot, + cast(pt.ScratchVar, other._stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -307,7 +307,7 @@ def test_Address_set_computed(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/array_base.py b/pyteal/ast/abi/array_base.py index aea164c81..8920637bc 100644 --- a/pyteal/ast/abi/array_base.py +++ b/pyteal/ast/abi/array_base.py @@ -104,7 +104,7 @@ def decode( extracted = substring_for_decoding( encoded, start_index=start_index, end_index=end_index, length=length ) - return self.stored_value.store(extracted) + return self._stored_value.store(extracted) def set(self, values: Sequence[T]) -> Expr: """Set the ABI array with a sequence of ABI type variables. @@ -142,7 +142,7 @@ def set(self, values: Sequence[T]) -> Expr: length_prefix = Seq(length_tmp.set(len(values)), length_tmp.encode()) encoded = Concat(length_prefix, encoded) - return self.stored_value.store(encoded) + return self._stored_value.store(encoded) def encode(self) -> Expr: """Encode the ABI array to be a byte string. @@ -150,7 +150,7 @@ def encode(self) -> Expr: Returns: A PyTeal expression that encodes this ABI array to a byte string. """ - return self.stored_value.load() + return self._stored_value.load() @abstractmethod def length(self) -> Expr: diff --git a/pyteal/ast/abi/array_dynamic.py b/pyteal/ast/abi/array_dynamic.py index 9d53e0559..ecbeeb49c 100644 --- a/pyteal/ast/abi/array_dynamic.py +++ b/pyteal/ast/abi/array_dynamic.py @@ -79,7 +79,7 @@ def set( raise TealInputError( f"Cannot assign type {values.type_spec()} to {self.type_spec()}" ) - return self.stored_value.store(values.encode()) + return self._stored_value.store(values.encode()) return super().set(values) def length(self) -> Expr: @@ -165,10 +165,10 @@ def set( match values: case bytes() | bytearray(): - return self.stored_value.store(_encoded_byte_string(values)) + return self._stored_value.store(_encoded_byte_string(values)) case Expr(): return _store_encoded_expr_byte_string_into_var( - values, self.stored_value + values, self._stored_value ) return super().set(values) @@ -181,7 +181,7 @@ def get(self) -> Expr: Returns: A Pyteal expression that loads byte encoding of this DynamicBytes, and drop the first uint16 DynamicArray length encoding. """ - return Suffix(self.stored_value.load(), Int(2)) + return Suffix(self._stored_value.load(), Int(2)) DynamicBytes.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/array_dynamic_test.py b/pyteal/ast/abi/array_dynamic_test.py index e8e930787..91497500a 100644 --- a/pyteal/ast/abi/array_dynamic_test.py +++ b/pyteal/ast/abi/array_dynamic_test.py @@ -106,7 +106,7 @@ def test_DynamicArray_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value.stored_value.store( + expectedExpr = value._stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -141,7 +141,7 @@ def test_DynamicArray_set_values(): assert not expr.has_return() length_tmp = abi.Uint16() - expectedExpr = value.stored_value.store( + expectedExpr = value._stored_value.store( pt.Concat( pt.Seq(length_tmp.set(len(values)), length_tmp.encode()), _encode_tuple(values), @@ -185,12 +185,12 @@ def test_DynamicArray_set_copy(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, otherArray.stored_value).slot, + cast(pt.ScratchVar, otherArray._stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -218,7 +218,7 @@ def test_DynamicArray_set_computed(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -268,7 +268,7 @@ def test_DynamicBytes_set_py_bytes(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -299,12 +299,12 @@ def test_DynamicBytes_set_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.itob), @@ -312,13 +312,13 @@ def test_DynamicBytes_set_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.concat), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -343,7 +343,7 @@ def test_DynamicBytes_get(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.extract, 2, 0), ] @@ -365,7 +365,7 @@ def test_DynamicArray_encode(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/array_static.py b/pyteal/ast/abi/array_static.py index 7744a6edb..3d9d56557 100644 --- a/pyteal/ast/abi/array_static.py +++ b/pyteal/ast/abi/array_static.py @@ -109,7 +109,7 @@ def set( raise TealInputError( f"Cannot assign type {values.type_spec()} to {self.type_spec()}" ) - return self.stored_value.store(values.encode()) + return self._stored_value.store(values.encode()) if self.type_spec().length_static() != len(values): raise TealInputError( @@ -207,11 +207,11 @@ def set( raise TealInputError( f"Got bytes with length {len(values)}, expect {self.type_spec().length_static()}" ) - return self.stored_value.store(Bytes(values)) + return self._stored_value.store(Bytes(values)) case Expr(): return Seq( - self.stored_value.store(values), - Assert(self.length() == Len(self.stored_value.load())), + self._stored_value.store(values), + Assert(self.length() == Len(self._stored_value.load())), ) return super().set(values) @@ -222,7 +222,7 @@ def get(self) -> Expr: Returns: A Pyteal expression that loads byte encoding of this StaticBytes. """ - return self.stored_value.load() + return self._stored_value.load() StaticBytes.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/array_static_test.py b/pyteal/ast/abi/array_static_test.py index 7c2e914ec..7a61e2b65 100644 --- a/pyteal/ast/abi/array_static_test.py +++ b/pyteal/ast/abi/array_static_test.py @@ -159,7 +159,7 @@ def test_StaticArray_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value.stored_value.store( + expectedExpr = value._stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -202,7 +202,7 @@ def test_StaticArray_set_values(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value.stored_value.store(_encode_tuple(values)) + expectedExpr = value._stored_value.store(_encode_tuple(values)) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) @@ -237,12 +237,12 @@ def test_StaticArray_set_copy(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, otherArray.stored_value).slot, + cast(pt.ScratchVar, otherArray._stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -270,7 +270,7 @@ def test_StaticArray_set_computed(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -317,7 +317,7 @@ def test_StaticBytes_set_py_bytes(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -352,13 +352,13 @@ def test_StaticBytes_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.int, 32), pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.eq), @@ -381,7 +381,7 @@ def test_StaticArray_encode(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/bool.py b/pyteal/ast/abi/bool.py index 13552b6db..6fa6d72a3 100644 --- a/pyteal/ast/abi/bool.py +++ b/pyteal/ast/abi/bool.py @@ -50,7 +50,7 @@ def get(self) -> Expr: expression that evaluates to 0 will be returned. In either case, the expression will have the type TealType.uint64. """ - return self.stored_value.load() + return self._stored_value.load() def set(self, value: Union[bool, Expr, "Bool", ComputedValue["Bool"]]) -> Expr: """Set the value of this Bool to the input value. @@ -85,10 +85,10 @@ def set(self, value: Union[bool, Expr, "Bool", ComputedValue["Bool"]]) -> Expr: checked = True if checked: - return self.stored_value.store(value) + return self._stored_value.store(value) # Not(Not(value)) coerces all values greater than 0 to 1 - return self.stored_value.store(Not(Not(value))) + return self._stored_value.store(Not(Not(value))) def decode( self, @@ -103,7 +103,7 @@ def decode( return self.decode_bit(encoded, start_index * Int(NUM_BITS_IN_BYTE)) def decode_bit(self, encoded, bit_index: Expr) -> Expr: - return self.stored_value.store(GetBit(encoded, bit_index)) + return self._stored_value.store(GetBit(encoded, bit_index)) def encode(self) -> Expr: return SetBit(Bytes(b"\x00"), Int(0), self.get()) diff --git a/pyteal/ast/abi/bool_test.py b/pyteal/ast/abi/bool_test.py index 1cf881d55..7dfb5c684 100644 --- a/pyteal/ast/abi/bool_test.py +++ b/pyteal/ast/abi/bool_test.py @@ -56,7 +56,7 @@ def test_Bool_set_static(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -85,7 +85,7 @@ def test_Bool_set_expr(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -110,12 +110,12 @@ def test_Bool_set_copy(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, other.stored_value).slot, + cast(pt.ScratchVar, other._stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -144,7 +144,7 @@ def test_Bool_set_computed(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -171,7 +171,7 @@ def test_Bool_get(): pt.TealOp( expr, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -203,7 +203,7 @@ def test_Bool_decode(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -232,7 +232,7 @@ def test_Bool_decode_bit(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -258,7 +258,7 @@ def test_Bool_encode(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.setbit), ] @@ -442,7 +442,7 @@ class EncodeSeqTest(NamedTuple): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, testType.stored_value).slot, + cast(pt.ScratchVar, testType._stored_value).slot, ), pt.TealOp(None, pt.Op.setbit), ] diff --git a/pyteal/ast/abi/reference_type.py b/pyteal/ast/abi/reference_type.py index f4882fc97..e1a228245 100644 --- a/pyteal/ast/abi/reference_type.py +++ b/pyteal/ast/abi/reference_type.py @@ -58,7 +58,7 @@ def referenced_index(self) -> Expr: If this reference type is an application or asset, note that this DOES NOT return the application or asset ID. See :code:`application_id()` or :code:`asset_id()` for that. """ - return self.stored_value.load() + return self._stored_value.load() def decode( self, @@ -70,7 +70,7 @@ def decode( ) -> Expr: return uint_decode( self.type_spec().bit_size(), - self.stored_value, + self._stored_value, encoded, start_index, end_index, @@ -107,7 +107,7 @@ def __init__(self) -> None: def address(self) -> Expr: """Get the address of the account.""" - return Txn.accounts[self.stored_value.load()] + return Txn.accounts[self._stored_value.load()] def params(self) -> AccountParamObject: """Get information about the account.""" @@ -205,7 +205,7 @@ def __init__(self) -> None: def application_id(self) -> Expr: """Get the ID of the application.""" - return Txn.applications[self.stored_value.load()] + return Txn.applications[self._stored_value.load()] def params(self) -> AppParamObject: """Get information about the application's parameters.""" diff --git a/pyteal/ast/abi/reference_type_test.py b/pyteal/ast/abi/reference_type_test.py index 4ec862e66..cbbc45d34 100644 --- a/pyteal/ast/abi/reference_type_test.py +++ b/pyteal/ast/abi/reference_type_test.py @@ -26,7 +26,7 @@ def test_ReferenceType_referenced_index(): pt.TealOp( expr, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -61,7 +61,7 @@ def test_ReferenceType_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expected_decoding = value.stored_value.store( + expected_decoding = value._stored_value.store( pt.GetByte( encoded, start_index if start_index is not None else pt.Int(0), @@ -117,7 +117,7 @@ def test_Account_address(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.txnas, "Accounts"), ] @@ -204,7 +204,7 @@ def test_Asset_asset_id(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.txnas, "Assets"), ] @@ -298,7 +298,7 @@ def test_Application_application_id(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.txnas, "Applications"), ] diff --git a/pyteal/ast/abi/string.py b/pyteal/ast/abi/string.py index ac5866cb2..f142eaa55 100644 --- a/pyteal/ast/abi/string.py +++ b/pyteal/ast/abi/string.py @@ -68,7 +68,7 @@ def get(self) -> Expr: The expression will have the type TealType.bytes. """ return Suffix( - self.stored_value.load(), Int(Uint16TypeSpec().byte_length_static()) + self._stored_value.load(), Int(Uint16TypeSpec().byte_length_static()) ) def set( @@ -111,18 +111,18 @@ def set( if value.type_spec() == StringTypeSpec() or ( value.type_spec() == DynamicArrayTypeSpec(ByteTypeSpec()) ): - return self.stored_value.store(value.stored_value.load()) + return self._stored_value.store(value._stored_value.load()) raise TealInputError( f"Got {value} with type spec {value.type_spec()}, expected {StringTypeSpec}" ) case bytes() | bytearray(): - return self.stored_value.store(_encoded_byte_string(value)) + return self._stored_value.store(_encoded_byte_string(value)) case str(): - return self.stored_value.store(_encoded_byte_string(value.encode())) + return self._stored_value.store(_encoded_byte_string(value.encode())) case Expr(): return _store_encoded_expr_byte_string_into_var( - value, self.stored_value + value, self._stored_value ) case CollectionSequence(): return super().set(cast(Sequence[Byte], value)) diff --git a/pyteal/ast/abi/string_test.py b/pyteal/ast/abi/string_test.py index c60ac52f4..9ebcbfadd 100644 --- a/pyteal/ast/abi/string_test.py +++ b/pyteal/ast/abi/string_test.py @@ -44,7 +44,7 @@ def test_String_encode(): pt.TealOp( expr, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -76,7 +76,7 @@ def test_DynamicArray_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expectedExpr = value.stored_value.store( + expectedExpr = value._stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -107,7 +107,7 @@ def test_String_get(): pt.TealOp( expr, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.extract, 2, 0), ] @@ -143,7 +143,7 @@ def test_String_set_static(value_to_set, value_encoded): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -174,12 +174,12 @@ def test_String_set_expr(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.itob), @@ -187,13 +187,13 @@ def test_String_set_expr(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.concat), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -222,12 +222,12 @@ def test_String_set_copy(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, other.stored_value).slot, + cast(pt.ScratchVar, other._stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -259,7 +259,7 @@ def test_String_set_computed(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/transaction.py b/pyteal/ast/abi/transaction.py index aeb5c7a33..69de7ea29 100644 --- a/pyteal/ast/abi/transaction.py +++ b/pyteal/ast/abi/transaction.py @@ -82,16 +82,16 @@ def _set_index( case ComputedValue(): return self._set_with_computed_type(value) case BaseType(): - return self.stored_value.store(self.stored_value.load()) + return self._stored_value.store(self._stored_value.load()) case int(): - return self.stored_value.store(Int(value)) + return self._stored_value.store(Int(value)) case Expr(): - return self.stored_value.store(value) + return self._stored_value.store(value) case _: raise TealInputError(f"Cant store a {type(value)} in a Transaction") def index(self) -> Expr: - return self.stored_value.load() + return self._stored_value.load() def decode( self, diff --git a/pyteal/ast/abi/transaction_test.py b/pyteal/ast/abi/transaction_test.py index b4c27a97c..3b0cdeae1 100644 --- a/pyteal/ast/abi/transaction_test.py +++ b/pyteal/ast/abi/transaction_test.py @@ -134,7 +134,7 @@ def test_Transaction__set_index(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, tv.t.stored_value).slot, + cast(pt.ScratchVar, tv.t._stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/tuple.py b/pyteal/ast/abi/tuple.py index bc1966414..3149250a6 100644 --- a/pyteal/ast/abi/tuple.py +++ b/pyteal/ast/abi/tuple.py @@ -309,7 +309,7 @@ def decode( extracted = substring_for_decoding( encoded, start_index=start_index, end_index=end_index, length=length ) - return self.stored_value.store(extracted) + return self._stored_value.store(extracted) @overload def set(self, *values: BaseType) -> Expr: @@ -352,10 +352,10 @@ def set(self, *values): ) if not all(myTypes[i] == values[i].type_spec() for i in range(len(myTypes))): raise TealInputError("Input values do not match type") - return self.stored_value.store(_encode_tuple(values)) + return self._stored_value.store(_encode_tuple(values)) def encode(self) -> Expr: - return self.stored_value.load() + return self._stored_value.load() def length(self) -> Expr: """Get the number of values this tuple holds as an Expr.""" diff --git a/pyteal/ast/abi/tuple_test.py b/pyteal/ast/abi/tuple_test.py index a761d88af..b175ce7bd 100644 --- a/pyteal/ast/abi/tuple_test.py +++ b/pyteal/ast/abi/tuple_test.py @@ -623,7 +623,7 @@ def test_Tuple_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = tupleValue.stored_value.store( + expectedExpr = tupleValue._stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -672,7 +672,9 @@ def test_Tuple_set(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = tupleValue.stored_value.store(_encode_tuple([uint8, uint16, uint32])) + expectedExpr = tupleValue._stored_value.store( + _encode_tuple([uint8, uint16, uint32]) + ) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) @@ -704,7 +706,7 @@ def test_Tuple_set_Computed(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, tupleValue.stored_value).slot, + cast(pt.ScratchVar, tupleValue._stored_value).slot, ), ] ) @@ -735,7 +737,7 @@ def test_Tuple_encode(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, tupleValue.stored_value).slot, + cast(pt.ScratchVar, tupleValue._stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index b87fe1282..adb76ecf3 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -77,16 +77,16 @@ def __init__(self, spec: TypeSpec) -> None: """Create a new BaseType.""" super().__init__() self._type_spec: Final[TypeSpec] = spec - self.stored_value: AbstractVar = ScratchVar(spec.storage_type()) + self._stored_value: AbstractVar = ScratchVar(spec.storage_type()) def _set_data_source(self, storage: AbstractVar) -> None: - self.stored_value = storage + self._stored_value = storage def _load_value(self) -> Expr: - return self.stored_value.load() + return self._stored_value.load() def _store_value(self, value: Expr) -> Expr: - return self.stored_value.store(value) + return self._stored_value.store(value) def type_spec(self) -> TypeSpec: """Get the TypeSpec for this ABI type instance.""" @@ -240,7 +240,7 @@ def store_into(self, output: BaseType) -> Expr: f"ABI return subroutine deferred_expr is expected to be typed {output.type_spec().storage_type()}, " f"but has type {declaration.deferred_expr.type_of()}." ) - return output.stored_value.store(self.computation) + return output._stored_value.store(self.computation) ReturnedValue.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/type_test.py b/pyteal/ast/abi/type_test.py index 56a9e6c76..568ebf94c 100644 --- a/pyteal/ast/abi/type_test.py +++ b/pyteal/ast/abi/type_test.py @@ -17,7 +17,7 @@ def store_into(self, output: abi.BaseType) -> pt.Expr: raise pt.TealInputError( f"expected type_spec {self.type_spec} but get {output.type_spec()}" ) - return output.stored_value.store(self.encodings) + return output._stored_value.store(self.encodings) def test_ComputedType_use(): diff --git a/pyteal/ast/abi/uint.py b/pyteal/ast/abi/uint.py index 0a99eb27f..c3f7c7f98 100644 --- a/pyteal/ast/abi/uint.py +++ b/pyteal/ast/abi/uint.py @@ -239,7 +239,7 @@ def get(self) -> Expr: The expression will have the type TealType.uint64. """ - return self.stored_value.load() + return self._stored_value.load() def set(self, value: Union[int, Expr, "Uint", ComputedValue["Uint"]]) -> Expr: """Set the value of this Uint to the input value. @@ -274,7 +274,7 @@ def set(self, value: Union[int, Expr, "Uint", ComputedValue["Uint"]]) -> Expr: value.type_spec(), self.type_spec() ) ) - return uint_set(self.type_spec().bit_size(), self.stored_value, value) + return uint_set(self.type_spec().bit_size(), self._stored_value, value) def decode( self, @@ -286,7 +286,7 @@ def decode( ) -> Expr: return uint_decode( self.type_spec().bit_size(), - self.stored_value, + self._stored_value, encoded, start_index, end_index, @@ -294,7 +294,7 @@ def decode( ) def encode(self) -> Expr: - return uint_encode(self.type_spec().bit_size(), self.stored_value) + return uint_encode(self.type_spec().bit_size(), self._stored_value) Uint.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/uint_test.py b/pyteal/ast/abi/uint_test.py index 26ba3541f..b9a74b64d 100644 --- a/pyteal/ast/abi/uint_test.py +++ b/pyteal/ast/abi/uint_test.py @@ -142,7 +142,7 @@ def test_Uint_set_static(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -174,7 +174,7 @@ def test_Uint_set_expr(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.int, test.maxValue + 1), pt.TealOp(None, pt.Op.lt), @@ -189,7 +189,7 @@ def test_Uint_set_expr(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] + upperBoundCheck @@ -216,12 +216,12 @@ def test_Uint_set_copy(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, other.stored_value).slot, + cast(pt.ScratchVar, other._stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -253,7 +253,7 @@ def test_Uint_set_computed(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -281,7 +281,7 @@ def test_Uint_get(): pt.TealOp( expr, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -307,7 +307,7 @@ def test_Uint_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedDecoding = value.stored_value.store( + expectedDecoding = value._stored_value.store( test.expectedDecoding(encoded, start_index, end_index, length) ) expected, _ = expectedDecoding.__teal__(options) @@ -359,12 +359,12 @@ def test_ByteUint8_mutual_conversion(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, other.stored_value).slot, + cast(pt.ScratchVar, other._stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, type_b_instance.stored_value).slot, + cast(pt.ScratchVar, type_b_instance._stored_value).slot, ), ] ) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 437c9535d..f3bf83a2c 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -378,7 +378,7 @@ def __init__( elif isinstance(arg, ScratchVar): arg_type = arg.type elif isinstance(arg, abi.BaseType): - arg_type = cast(abi.BaseType, arg).stored_value.storage_type() + arg_type = cast(abi.BaseType, arg)._stored_value.storage_type() else: raise TealInputError( f"Subroutine argument {arg} at index {i} was of unexpected Python type {type(arg)}" @@ -420,7 +420,7 @@ def handle_arg(arg: Expr | ScratchVar | abi.BaseType) -> Expr: elif isinstance(arg, Expr): return arg elif isinstance(arg, abi.BaseType): - return arg.stored_value.load() + return arg._stored_value.load() else: raise TealInputError( f"cannot handle current arg: {arg} to put it on stack" @@ -799,11 +799,11 @@ def var_n_loaded( loaded_var = argument_var elif param in subroutine.abi_args: internal_abi_var = subroutine.abi_args[param].new_instance() - if not isinstance(internal_abi_var.stored_value, ScratchVar): + if not isinstance(internal_abi_var._stored_value, ScratchVar): raise TealInternalError( "subroutine ABI args must have data schema being ScratchVarStorage" ) - argument_var = internal_abi_var.stored_value + argument_var = internal_abi_var._stored_value loaded_var = internal_abi_var else: argument_var = ScratchVar(TealType.anytype) @@ -851,7 +851,7 @@ def var_n_loaded( f"ABI returning subroutine definition should evaluate to TealType.none, " f"while evaluate to {subroutine_body.type_of()}." ) - deferred_expr = output_carrying_abi.stored_value.load() + deferred_expr = output_carrying_abi._stored_value.load() # Arg usage "A" to be pick up and store in scratch parameters that have been placed on the stack # need to reverse order of argumentVars because the last argument will be on top of the stack From 4b688dfd4879af15617ecbd934194c3c01018b2d Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 11:35:33 -0400 Subject: [PATCH 051/157] proto renaming stuffs --- pyteal/ast/frame.py | 12 ++++++------ pyteal/ast/subroutine.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 0a15e1a6b..7cccefb58 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -12,7 +12,7 @@ class Proto(Expr): - def __init__(self, num_args: int, num_returns: int, /, *, reserve_spot: int = 0): + def __init__(self, num_args: int, num_returns: int, /, *, num_local_vars: int = 0): super().__init__() if num_args < 0: raise TealInputError( @@ -24,7 +24,7 @@ def __init__(self, num_args: int, num_returns: int, /, *, reserve_spot: int = 0) ) self.num_args = num_args self.num_returns = num_returns - self.reserve_spot = reserve_spot + self.num_local_vars = num_local_vars def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: verifyProgramVersion( @@ -34,19 +34,19 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc ) op = TealOp(self, Op.proto, self.num_args, self.num_returns) proto_srt, proto_end = TealBlock.FromOp(options, op) - if self.reserve_spot == 0: + if self.num_local_vars == 0: return proto_srt, proto_end - elif self.reserve_spot == 1: + elif self.num_local_vars == 1: int_srt, int_end = Int(0).__teal__(options) proto_end.setNextBlock(int_srt) return proto_srt, int_end else: - dupn_srt, dupn_end = DupN(Int(0), self.reserve_spot).__teal__(options) + dupn_srt, dupn_end = DupN(Int(0), self.num_local_vars).__teal__(options) proto_end.setNextBlock(dupn_srt) return proto_srt, dupn_end def __str__(self) -> str: - return f"(proto: arg_num = {self.num_args}, ret_num = {self.num_returns}, reserve_spot = {self.reserve_spot})" + return f"(proto: num_args = {self.num_args}, num_rets = {self.num_returns}, num_local_vars = {self.num_local_vars})" def type_of(self) -> TealType: return TealType.none diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index d40f04746..8ac61c066 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -1032,7 +1032,7 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: Proto( subroutine.argument_count(), stack_output_cnt, - reserve_spot=int(subroutine.has_abi_output), + num_local_vars=int(subroutine.has_abi_output), ) ] From 0f5c916cec9946146cc5c9e5508c783d6d7ecb33 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 12:06:10 -0400 Subject: [PATCH 052/157] per pr comment, rename to FrameVar --- pyteal/__init__.pyi | 2 +- pyteal/ast/__init__.py | 4 ++-- pyteal/ast/frame.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index baf5ae050..2e03200b2 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -122,7 +122,7 @@ __all__ = [ "For", "FrameBury", "FrameDig", - "FrameStorage", + "FrameVar", "Ge", "GeneratedID", "GetBit", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 0f2bcaa34..f4ebd5f88 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -155,7 +155,7 @@ from pyteal.ast.for_ import For from pyteal.ast.break_ import Break from pyteal.ast.continue_ import Continue -from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN, Bury, FrameStorage +from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN, Bury, FrameVar # misc from pyteal.ast.scratch import ( @@ -344,7 +344,7 @@ "Bury", "DupN", "PopN", - "FrameStorage", + "FrameVar", "Router", "CallConfig", "MethodConfig", diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 25aa437fc..7c71333f5 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -102,7 +102,7 @@ def has_return(self) -> bool: FrameBury.__module__ = "pyteal" -class FrameStorage(AbstractVar): +class FrameVar(AbstractVar): def __init__(self, storage_type: TealType, stack_depth: int) -> None: super().__init__() self.stack_type = storage_type @@ -122,7 +122,7 @@ def load(self) -> Expr: return FrameDig(self.stack_depth) -FrameStorage.__module__ = "pyteal" +FrameVar.__module__ = "pyteal" class Bury(Expr): From 0924d94de17751eed420349717341d6064913f75 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 12:11:45 -0400 Subject: [PATCH 053/157] take bury out --- pyteal/__init__.pyi | 1 - pyteal/ast/__init__.py | 3 +-- pyteal/ast/frame.py | 31 ------------------------------- pyteal/ast/frame_test.py | 30 ------------------------------ 4 files changed, 1 insertion(+), 64 deletions(-) diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 40600d561..7682ab0b7 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -71,7 +71,6 @@ __all__ = [ "BoxReplace", "Break", "Btoi", - "Bury", "Bytes", "BytesAdd", "BytesAnd", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 1ca49a2e5..a1b21e071 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -155,7 +155,7 @@ from pyteal.ast.for_ import For from pyteal.ast.break_ import Break from pyteal.ast.continue_ import Continue -from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN, Bury +from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN # misc from pyteal.ast.scratch import ( @@ -340,7 +340,6 @@ "Proto", "FrameDig", "FrameBury", - "Bury", "DupN", "PopN", "Router", diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 68ce3a2f2..9260d3064 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -101,37 +101,6 @@ def has_return(self) -> bool: FrameBury.__module__ = "pyteal" -class Bury(Expr): - def __init__(self, value: Expr, depth: int): - super().__init__() - require_type(value, TealType.anytype) - if depth <= 0: - raise TealInputError("bury depth should be strictly positive") - self.value = value - self.depth = depth - - def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: - verifyProgramVersion( - Op.bury.min_version, - options.version, - "Program version too low to use op bury", - ) - op = TealOp(self, Op.bury, self.depth) - return TealBlock.FromOp(options, op, self.value) - - def __str__(self) -> str: - return f"(bury (depth = {self.depth}) ({self.value}))" - - def type_of(self) -> TealType: - return TealType.none - - def has_return(self) -> bool: - return False - - -Bury.__module__ = "pyteal" - - class DupN(Expr): def __init__(self, value: Expr, repetition: int): super().__init__() diff --git a/pyteal/ast/frame_test.py b/pyteal/ast/frame_test.py index b21b47d0e..8bbbf26c1 100644 --- a/pyteal/ast/frame_test.py +++ b/pyteal/ast/frame_test.py @@ -77,36 +77,6 @@ def test_frame_bury_invalid(): pt.FrameBury(pt.Int(1), 1).__teal__(avm7Options) -def test_bury(): - byte_expr = pt.Bytes("Astartes") - expr = pt.Bury(byte_expr, 4) - assert not expr.has_return() - assert expr.type_of() == TealType.none - - expected = pt.TealSimpleBlock( - [ - pt.TealOp(byte_expr, pt.Op.byte, '"Astartes"'), - pt.TealOp(expr, pt.Op.bury, 4), - ] - ) - actual, _ = expr.__teal__(avm8Options) - actual.addIncoming() - actual = pt.TealBlock.NormalizeBlocks(actual) - - assert actual == expected - - -def test_bury_invalid(): - with pytest.raises(pt.TealTypeError): - pt.Bury(pt.Seq(), 1) - - with pytest.raises(pt.TealInputError): - pt.Bury(pt.Int(1), 0) - - with pytest.raises(pt.TealInputError): - pt.Bury(pt.Int(1), 1).__teal__(avm7Options) - - @pytest.mark.parametrize("repetition", [0, 1, 2, 3, 4, 5]) def test_popn(repetition: int): expr = pt.PopN(repetition) From d1c52a2504d2190064533cdaf410bc613449fd3c Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 12:29:53 -0400 Subject: [PATCH 054/157] pop popn --- pyteal/__init__.pyi | 1 - pyteal/ast/__init__.py | 3 +-- pyteal/ast/frame.py | 29 ----------------------------- pyteal/ast/frame_test.py | 22 ---------------------- 4 files changed, 1 insertion(+), 54 deletions(-) diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 7682ab0b7..19dcc01fb 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -178,7 +178,6 @@ __all__ = [ "OptimizeOptions", "Or", "Pop", - "PopN", "Pragma", "Proto", "RETURN_HASH_PREFIX", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index a1b21e071..4a0b4e181 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -155,7 +155,7 @@ from pyteal.ast.for_ import For from pyteal.ast.break_ import Break from pyteal.ast.continue_ import Continue -from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN +from pyteal.ast.frame import Proto, FrameDig, FrameBury, DupN # misc from pyteal.ast.scratch import ( @@ -341,7 +341,6 @@ "FrameDig", "FrameBury", "DupN", - "PopN", "Router", "CallConfig", "MethodConfig", diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 9260d3064..8f5e24891 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -130,32 +130,3 @@ def has_return(self) -> bool: DupN.__module__ = "pyteal" - - -class PopN(Expr): - def __init__(self, repetition: int): - super().__init__() - if repetition < 0: - raise TealInputError("popn repetition should be non negative") - self.repetition = repetition - - def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: - verifyProgramVersion( - Op.popn.min_version, - options.version, - "Program version too low to use op popn", - ) - op = TealOp(self, Op.popn, self.repetition) - return TealBlock.FromOp(options, op) - - def __str__(self) -> str: - return f"(popn {self.repetition})" - - def type_of(self) -> TealType: - return TealType.none - - def has_return(self) -> bool: - return False - - -PopN.__module__ = "pyteal" diff --git a/pyteal/ast/frame_test.py b/pyteal/ast/frame_test.py index 8bbbf26c1..d02f526ba 100644 --- a/pyteal/ast/frame_test.py +++ b/pyteal/ast/frame_test.py @@ -77,28 +77,6 @@ def test_frame_bury_invalid(): pt.FrameBury(pt.Int(1), 1).__teal__(avm7Options) -@pytest.mark.parametrize("repetition", [0, 1, 2, 3, 4, 5]) -def test_popn(repetition: int): - expr = pt.PopN(repetition) - assert not expr.has_return() - assert expr.type_of() == pt.TealType.none - - expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.popn, repetition)]) - actual, _ = expr.__teal__(avm8Options) - actual.addIncoming() - actual = pt.TealBlock.NormalizeBlocks(actual) - - assert actual == expected - - -def test_popn_invalid(): - with pytest.raises(pt.TealInputError): - pt.PopN(-1) - - with pytest.raises(pt.TealInputError): - pt.PopN(5).__teal__(avm7Options) - - def test_dupn(): byte_expr = pt.Bytes("Astartes") expr = pt.DupN(byte_expr, 4) From d457f99da2649f7a4060d747757abee73a83b2f6 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 12:53:59 -0400 Subject: [PATCH 055/157] abstractvar.py --- pyteal/ast/__init__.py | 3 ++- pyteal/ast/abstractvar.py | 20 ++++++++++++++++++++ pyteal/ast/scratchvar.py | 20 +------------------- 3 files changed, 23 insertions(+), 20 deletions(-) create mode 100644 pyteal/ast/abstractvar.py diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 1721ce522..7de5e044a 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -165,7 +165,8 @@ ScratchStackStore, ScratchStore, ) -from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar, AbstractVar +from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar +from pyteal.ast.abstractvar import AbstractVar from pyteal.ast.maybe import MaybeValue from pyteal.ast.multi import MultiValue from pyteal.ast.opup import OpUp, OpUpMode, OpUpFeeSource diff --git a/pyteal/ast/abstractvar.py b/pyteal/ast/abstractvar.py new file mode 100644 index 000000000..59788e001 --- /dev/null +++ b/pyteal/ast/abstractvar.py @@ -0,0 +1,20 @@ +from abc import ABC, abstractmethod +from pyteal.types import TealType +from pyteal.ast.expr import Expr + + +class AbstractVar(ABC): + @abstractmethod + def store(self, value: Expr) -> Expr: + pass + + @abstractmethod + def load(self) -> Expr: + pass + + @abstractmethod + def storage_type(self) -> TealType: + pass + + +AbstractVar.__module__ = "pyteal" diff --git a/pyteal/ast/scratchvar.py b/pyteal/ast/scratchvar.py index 7b4962f97..e97b5d1ef 100644 --- a/pyteal/ast/scratchvar.py +++ b/pyteal/ast/scratchvar.py @@ -1,29 +1,11 @@ -from abc import ABC, abstractmethod - from pyteal.errors import TealInputError from pyteal.types import TealType, require_type, types_match +from pyteal.ast.abstractvar import AbstractVar from pyteal.ast.expr import Expr from pyteal.ast.scratch import ScratchSlot, ScratchLoad, ScratchStore -class AbstractVar(ABC): - @abstractmethod - def store(self, value: Expr) -> Expr: - pass - - @abstractmethod - def load(self) -> Expr: - pass - - @abstractmethod - def storage_type(self) -> TealType: - pass - - -AbstractVar.__module__ = "pyteal" - - class ScratchVar(AbstractVar): """ Interface around Scratch space, similar to get/put local/global state From 95bc48a97520da835394ffdb01a374ef542bbfd7 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 14:00:46 -0400 Subject: [PATCH 056/157] unexport FrameVar and AbstractVar --- pyteal/__init__.pyi | 2 -- pyteal/ast/__init__.py | 5 +---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 56c22a572..19dcc01fb 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -35,7 +35,6 @@ from pyteal.config import ( __all__ = [ "ABIReturnSubroutine", - "AbstractVar", "AccountParam", "AccountParamObject", "Add", @@ -121,7 +120,6 @@ __all__ = [ "For", "FrameBury", "FrameDig", - "FrameVar", "Ge", "GeneratedID", "GetBit", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 7de5e044a..4a0b4e181 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -155,7 +155,7 @@ from pyteal.ast.for_ import For from pyteal.ast.break_ import Break from pyteal.ast.continue_ import Continue -from pyteal.ast.frame import Proto, FrameDig, FrameBury, DupN, FrameVar +from pyteal.ast.frame import Proto, FrameDig, FrameBury, DupN # misc from pyteal.ast.scratch import ( @@ -166,7 +166,6 @@ ScratchStore, ) from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar -from pyteal.ast.abstractvar import AbstractVar from pyteal.ast.maybe import MaybeValue from pyteal.ast.multi import MultiValue from pyteal.ast.opup import OpUp, OpUpMode, OpUpFeeSource @@ -306,7 +305,6 @@ "ScratchStore", "DynamicScratchVar", "ScratchVar", - "AbstractVar", "MaybeValue", "MultiValue", "OpUp", @@ -343,7 +341,6 @@ "FrameDig", "FrameBury", "DupN", - "FrameVar", "Router", "CallConfig", "MethodConfig", From 8c41726c6d663ee5aff5241062e91a42ce336f4c Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 14:04:58 -0400 Subject: [PATCH 057/157] unexport use of frame ops --- pyteal/__init__.pyi | 4 ---- pyteal/ast/__init__.py | 5 ----- pyteal/ast/frame_test.py | 30 +++++++++++++++--------------- 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 19dcc01fb..3f69e10bd 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -99,7 +99,6 @@ __all__ = [ "DEFAULT_TEAL_VERSION", "Div", "Divw", - "DupN", "DynamicScratchVar", "EcdsaCurve", "EcdsaDecompress", @@ -118,8 +117,6 @@ __all__ = [ "ExtractUint64", "FRAME_POINTER_VERSION", "For", - "FrameBury", - "FrameDig", "Ge", "GeneratedID", "GetBit", @@ -179,7 +176,6 @@ __all__ = [ "Or", "Pop", "Pragma", - "Proto", "RETURN_HASH_PREFIX", "Reject", "Replace", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 4a0b4e181..9efe807c5 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -155,7 +155,6 @@ from pyteal.ast.for_ import For from pyteal.ast.break_ import Break from pyteal.ast.continue_ import Continue -from pyteal.ast.frame import Proto, FrameDig, FrameBury, DupN # misc from pyteal.ast.scratch import ( @@ -337,10 +336,6 @@ "For", "Break", "Continue", - "Proto", - "FrameDig", - "FrameBury", - "DupN", "Router", "CallConfig", "MethodConfig", diff --git a/pyteal/ast/frame_test.py b/pyteal/ast/frame_test.py index d02f526ba..e4cde2aa4 100644 --- a/pyteal/ast/frame_test.py +++ b/pyteal/ast/frame_test.py @@ -1,6 +1,6 @@ import pytest import pyteal as pt -from pyteal.types import TealType +from pyteal.ast.frame import FrameBury, FrameDig, Proto, DupN avm7Options = pt.CompileOptions(version=7) avm8Options = pt.CompileOptions(version=8) @@ -8,7 +8,7 @@ @pytest.mark.parametrize("input_num, output_num", [(1, 1), (1, 0), (5, 5)]) def test_proto(input_num: int, output_num: int): - expr = pt.Proto(input_num, output_num) + expr = Proto(input_num, output_num) assert not expr.has_return() assert expr.type_of() == pt.TealType.none @@ -22,18 +22,18 @@ def test_proto(input_num: int, output_num: int): def test_proto_invalid(): with pytest.raises(pt.TealInputError): - pt.Proto(-1, 1) + Proto(-1, 1) with pytest.raises(pt.TealInputError): - pt.Proto(1, -1) + Proto(1, -1) with pytest.raises(pt.TealInputError): - pt.Proto(1, 1).__teal__(avm7Options) + Proto(1, 1).__teal__(avm7Options) @pytest.mark.parametrize("depth", [-1, 0, 1, 2]) def test_frame_dig(depth: int): - expr = pt.FrameDig(depth) + expr = FrameDig(depth) assert not expr.has_return() assert expr.type_of() == pt.TealType.anytype @@ -47,14 +47,14 @@ def test_frame_dig(depth: int): def test_frame_dig_invalid(): with pytest.raises(pt.TealInputError): - pt.FrameDig(1).__teal__(avm7Options) + FrameDig(1).__teal__(avm7Options) def test_frame_bury(): byte_expr = pt.Bytes("Astartes") - expr = pt.FrameBury(byte_expr, 4) + expr = FrameBury(byte_expr, 4) assert not expr.has_return() - assert expr.type_of() == TealType.none + assert expr.type_of() == pt.TealType.none expected = pt.TealSimpleBlock( [ @@ -71,15 +71,15 @@ def test_frame_bury(): def test_frame_bury_invalid(): with pytest.raises(pt.TealTypeError): - pt.FrameBury(pt.Seq(), 1) + FrameBury(pt.Seq(), 1) with pytest.raises(pt.TealInputError): - pt.FrameBury(pt.Int(1), 1).__teal__(avm7Options) + FrameBury(pt.Int(1), 1).__teal__(avm7Options) def test_dupn(): byte_expr = pt.Bytes("Astartes") - expr = pt.DupN(byte_expr, 4) + expr = DupN(byte_expr, 4) assert not expr.has_return() assert expr.type_of() == byte_expr.type_of() @@ -98,10 +98,10 @@ def test_dupn(): def test_dupn_invalid(): with pytest.raises(pt.TealTypeError): - pt.DupN(pt.Seq(), 1) + DupN(pt.Seq(), 1) with pytest.raises(pt.TealInputError): - pt.DupN(pt.Int(1), -1) + DupN(pt.Int(1), -1) with pytest.raises(pt.TealInputError): - pt.DupN(pt.Int(1), 1).__teal__(avm7Options) + DupN(pt.Int(1), 1).__teal__(avm7Options) From 075710e38114c9294061e2381e6433d19f034a95 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 14:34:17 -0400 Subject: [PATCH 058/157] rename to num allocs --- pyteal/ast/frame.py | 12 ++++++------ pyteal/ast/subroutine.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 88d0a1798..ff2cb9e6c 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -12,7 +12,7 @@ class Proto(Expr): - def __init__(self, num_args: int, num_returns: int, /, *, num_local_vars: int = 0): + def __init__(self, num_args: int, num_returns: int, /, *, num_allocs: int = 0): super().__init__() if num_args < 0: raise TealInputError( @@ -24,7 +24,7 @@ def __init__(self, num_args: int, num_returns: int, /, *, num_local_vars: int = ) self.num_args = num_args self.num_returns = num_returns - self.num_local_vars = num_local_vars + self.num_allocs = num_allocs def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: verifyProgramVersion( @@ -34,19 +34,19 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc ) op = TealOp(self, Op.proto, self.num_args, self.num_returns) proto_srt, proto_end = TealBlock.FromOp(options, op) - if self.num_local_vars == 0: + if self.num_allocs == 0: return proto_srt, proto_end - elif self.num_local_vars == 1: + elif self.num_allocs == 1: int_srt, int_end = Int(0).__teal__(options) proto_end.setNextBlock(int_srt) return proto_srt, int_end else: - dupn_srt, dupn_end = DupN(Int(0), self.num_local_vars).__teal__(options) + dupn_srt, dupn_end = DupN(Int(0), self.num_allocs).__teal__(options) proto_end.setNextBlock(dupn_srt) return proto_srt, dupn_end def __str__(self) -> str: - return f"(proto: num_args = {self.num_args}, num_rets = {self.num_returns}, num_local_vars = {self.num_local_vars})" + return f"(proto: num_args = {self.num_args}, num_rets = {self.num_returns}, num_allocs = {self.num_allocs})" def type_of(self) -> TealType: return TealType.none diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index a57d100b4..36c343a8f 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -1032,7 +1032,7 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: Proto( subroutine.argument_count(), stack_output_cnt, - num_local_vars=int(subroutine.has_abi_output), + num_allocs=int(subroutine.has_abi_output), ) ] From 61551b83d6d8beac69b3c1c6469a43f17fea320f Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 14:49:48 -0400 Subject: [PATCH 059/157] remove _set_data_storage --- pyteal/ast/abi/type.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index adb76ecf3..24f396cf3 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -79,9 +79,6 @@ def __init__(self, spec: TypeSpec) -> None: self._type_spec: Final[TypeSpec] = spec self._stored_value: AbstractVar = ScratchVar(spec.storage_type()) - def _set_data_source(self, storage: AbstractVar) -> None: - self._stored_value = storage - def _load_value(self) -> Expr: return self._stored_value.load() From 885500281e98aaff7827fdd887d7bebf45e42acb Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 15:05:56 -0400 Subject: [PATCH 060/157] namedtuple set var method --- pyteal/ast/abi/tuple.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyteal/ast/abi/tuple.py b/pyteal/ast/abi/tuple.py index 458604f70..2d744eeeb 100644 --- a/pyteal/ast/abi/tuple.py +++ b/pyteal/ast/abi/tuple.py @@ -683,7 +683,7 @@ def __setattr__(self, name: str, field: Any) -> None: # NamedTuple is an argument, and inside subroutine, subroutine set internal ABI value with FrameStorage # This used to violate `__setattr__` for not allowing any assignment to attributes # Now this case is lifted such that we can shift the storage scheme. - if name.startswith("_") and name != "_NamedTuple__ready" and self.__ready: + if name == "_stored_value" and self.__ready: super().__setattr__(name, field) return raise TealInputError("cannot assign to NamedTuple attributes.") From 8eca96d6b1f1b29a1661bf7c0de95d4dbd411071 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 15:19:04 -0400 Subject: [PATCH 061/157] rename from stack_depth to frame_index --- pyteal/ast/frame.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index ac32eabd0..9ddcf237a 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -103,19 +103,19 @@ def has_return(self) -> bool: class FrameVar(AbstractVar): - def __init__(self, storage_type: TealType, stack_depth: int) -> None: + def __init__(self, storage_type: TealType, frame_index: int) -> None: super().__init__() self.stack_type = storage_type - self.stack_depth = stack_depth + self.frame_index = frame_index def storage_type(self) -> TealType: return self.stack_type def store(self, value: Expr) -> Expr: - return FrameBury(value, self.stack_depth) + return FrameBury(value, self.frame_index) def load(self) -> Expr: - return FrameDig(self.stack_depth) + return FrameDig(self.frame_index) FrameVar.__module__ = "pyteal" From c241cfa19c8290072b4707f21aace38e0a720053 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 16:29:57 -0400 Subject: [PATCH 062/157] CHANGELOG.md --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ff7c84a7..3b3f7c841 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Unreleased +## Added +* adding program page related ops ([#412](https://github.com/algorand/pyteal/pull/412)) +* Add Replace ([#413](https://github.com/algorand/pyteal/pull/413)) +* Add Block ([#415](https://github.com/algorand/pyteal/pull/415)) +* Add JsonRef ([#417](https://github.com/algorand/pyteal/pull/417)) +* Add Base64Decode ([#418](https://github.com/algorand/pyteal/pull/418)) +* Support Secp256r1 curve ([#423](https://github.com/algorand/pyteal/pull/423)) +* Add VrfVerify ([#419](https://github.com/algorand/pyteal/pull/419)) +* Add Sha3_256 ([#425](https://github.com/algorand/pyteal/pull/425)) +* Support FirstValidTime transaction field ([#424](https://github.com/algorand/pyteal/pull/424)) +* Add Ed25519Verify_Bare ([#426](https://github.com/algorand/pyteal/pull/426)) +* AVM Boxes Ops in Pyteal ([#438](https://github.com/algorand/pyteal/pull/438)) +* Support new AVM 8 account parameters ([#555](https://github.com/algorand/pyteal/pull/555)) + +## Changed +* Changes to avm8 docs ([#546](https://github.com/algorand/pyteal/pull/546)) + # 0.19.0 ## Added From dd687c7643b2e87f241f96250f43e689abb91abf Mon Sep 17 00:00:00 2001 From: Hang Su <87964331+ahangsu@users.noreply.github.com> Date: Wed, 2 Nov 2022 17:12:36 -0400 Subject: [PATCH 063/157] Frame Ops to `avm8` branch PR (#585) * add frame ops to avm8 branch * specify FRAME_POINTER_VERSION in frame-op branch * per review comments * per review comments * per review comments, depth -> frame_depth * take bury out * pop popn * unexport use of frame ops * hide FRAME_POINTER_VERISON --- pyteal/ast/frame.py | 132 ++++++++++++++++++++++++++++++++++++ pyteal/ast/frame_test.py | 107 +++++++++++++++++++++++++++++ pyteal/compiler/compiler.py | 1 + pyteal/ir/ops.py | 8 ++- 4 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 pyteal/ast/frame.py create mode 100644 pyteal/ast/frame_test.py diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py new file mode 100644 index 000000000..8f5e24891 --- /dev/null +++ b/pyteal/ast/frame.py @@ -0,0 +1,132 @@ +from typing import TYPE_CHECKING + +from pyteal.ast.expr import Expr +from pyteal.types import TealType, require_type +from pyteal.errors import TealInputError, verifyProgramVersion +from pyteal.ir import TealBlock, TealSimpleBlock, TealOp, Op + +if TYPE_CHECKING: + from pyteal.compiler import CompileOptions + + +class Proto(Expr): + def __init__(self, num_args: int, num_returns: int): + super().__init__() + if num_args < 0: + raise TealInputError( + f"the number of arguments provided to Proto must be >= 0 but {num_args=}" + ) + if num_returns < 0: + raise TealInputError( + f"the number of return values provided to Proto must be >= 0 but {num_returns=}" + ) + self.num_args = num_args + self.num_returns = num_returns + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + verifyProgramVersion( + Op.proto.min_version, + options.version, + "Program version too low to use op proto", + ) + op = TealOp(self, Op.proto, self.num_args, self.num_returns) + return TealBlock.FromOp(options, op) + + def __str__(self) -> str: + return f"(proto: num_args = {self.num_args}, num_returns = {self.num_returns})" + + def type_of(self) -> TealType: + return TealType.none + + def has_return(self) -> bool: + return False + + +Proto.__module__ = "pyteal" + + +class FrameDig(Expr): + def __init__(self, frame_index: int): + super().__init__() + self.frame_index = frame_index + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + verifyProgramVersion( + Op.frame_dig.min_version, + options.version, + "Program version too low to use op frame_dig", + ) + op = TealOp(self, Op.frame_dig, self.frame_index) + return TealBlock.FromOp(options, op) + + def __str__(self) -> str: + return f"(frame_dig: dig_from = {self.frame_index})" + + def type_of(self) -> TealType: + return TealType.anytype + + def has_return(self) -> bool: + return False + + +FrameDig.__module__ = "pyteal" + + +class FrameBury(Expr): + def __init__(self, value: Expr, frame_index: int): + super().__init__() + require_type(value, TealType.anytype) + self.value = value + self.frame_index = frame_index + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + verifyProgramVersion( + Op.frame_bury.min_version, + options.version, + "Program version too low to use op frame_bury", + ) + op = TealOp(self, Op.frame_bury, self.frame_index) + return TealBlock.FromOp(options, op, self.value) + + def __str__(self) -> str: + return f"(frame_bury (bury_to = {self.frame_index}) ({self.value}))" + + def type_of(self) -> TealType: + return TealType.none + + def has_return(self) -> bool: + return False + + +FrameBury.__module__ = "pyteal" + + +class DupN(Expr): + def __init__(self, value: Expr, repetition: int): + super().__init__() + require_type(value, TealType.anytype) + if repetition < 0: + raise TealInputError("dupn repetition should be non negative") + self.value = value + self.repetition = repetition + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + verifyProgramVersion( + Op.dupn.min_version, + options.version, + "Program version too low to use op dupn", + ) + op = TealOp(self, Op.dupn, self.repetition) + return TealBlock.FromOp(options, op, self.value) + + def __str__(self) -> str: + return f"(dupn (repetition = {self.repetition}) ({self.value}))" + + def type_of(self) -> TealType: + return self.value.type_of() + + def has_return(self) -> bool: + return False + + +DupN.__module__ = "pyteal" diff --git a/pyteal/ast/frame_test.py b/pyteal/ast/frame_test.py new file mode 100644 index 000000000..e4cde2aa4 --- /dev/null +++ b/pyteal/ast/frame_test.py @@ -0,0 +1,107 @@ +import pytest +import pyteal as pt +from pyteal.ast.frame import FrameBury, FrameDig, Proto, DupN + +avm7Options = pt.CompileOptions(version=7) +avm8Options = pt.CompileOptions(version=8) + + +@pytest.mark.parametrize("input_num, output_num", [(1, 1), (1, 0), (5, 5)]) +def test_proto(input_num: int, output_num: int): + expr = Proto(input_num, output_num) + assert not expr.has_return() + assert expr.type_of() == pt.TealType.none + + expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.proto, input_num, output_num)]) + actual, _ = expr.__teal__(avm8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + +def test_proto_invalid(): + with pytest.raises(pt.TealInputError): + Proto(-1, 1) + + with pytest.raises(pt.TealInputError): + Proto(1, -1) + + with pytest.raises(pt.TealInputError): + Proto(1, 1).__teal__(avm7Options) + + +@pytest.mark.parametrize("depth", [-1, 0, 1, 2]) +def test_frame_dig(depth: int): + expr = FrameDig(depth) + assert not expr.has_return() + assert expr.type_of() == pt.TealType.anytype + + expected = pt.TealSimpleBlock([pt.TealOp(expr, pt.Op.frame_dig, depth)]) + actual, _ = expr.__teal__(avm8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + +def test_frame_dig_invalid(): + with pytest.raises(pt.TealInputError): + FrameDig(1).__teal__(avm7Options) + + +def test_frame_bury(): + byte_expr = pt.Bytes("Astartes") + expr = FrameBury(byte_expr, 4) + assert not expr.has_return() + assert expr.type_of() == pt.TealType.none + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(byte_expr, pt.Op.byte, '"Astartes"'), + pt.TealOp(expr, pt.Op.frame_bury, 4), + ] + ) + actual, _ = expr.__teal__(avm8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + +def test_frame_bury_invalid(): + with pytest.raises(pt.TealTypeError): + FrameBury(pt.Seq(), 1) + + with pytest.raises(pt.TealInputError): + FrameBury(pt.Int(1), 1).__teal__(avm7Options) + + +def test_dupn(): + byte_expr = pt.Bytes("Astartes") + expr = DupN(byte_expr, 4) + assert not expr.has_return() + assert expr.type_of() == byte_expr.type_of() + + expected = pt.TealSimpleBlock( + [ + pt.TealOp(byte_expr, pt.Op.byte, '"Astartes"'), + pt.TealOp(expr, pt.Op.dupn, 4), + ] + ) + actual, _ = expr.__teal__(avm8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + assert actual == expected + + +def test_dupn_invalid(): + with pytest.raises(pt.TealTypeError): + DupN(pt.Seq(), 1) + + with pytest.raises(pt.TealInputError): + DupN(pt.Int(1), -1) + + with pytest.raises(pt.TealInputError): + DupN(pt.Int(1), 1).__teal__(avm7Options) diff --git a/pyteal/compiler/compiler.py b/pyteal/compiler/compiler.py index 1955d0430..f2b25b489 100644 --- a/pyteal/compiler/compiler.py +++ b/pyteal/compiler/compiler.py @@ -26,6 +26,7 @@ from pyteal.compiler.constants import createConstantBlocks MAX_PROGRAM_VERSION = 8 +FRAME_POINTER_VERSION = 8 MIN_PROGRAM_VERSION = 2 DEFAULT_PROGRAM_VERSION = MIN_PROGRAM_VERSION diff --git a/pyteal/ir/ops.py b/pyteal/ir/ops.py index 43a62b5d4..9ec496288 100644 --- a/pyteal/ir/ops.py +++ b/pyteal/ir/ops.py @@ -33,7 +33,7 @@ def min_version(self) -> int: # fmt: off # meta comment = OpType("//", Mode.Signature | Mode.Application, 0) - # avm + # avm err = OpType("err", Mode.Signature | Mode.Application, 2) sha256 = OpType("sha256", Mode.Signature | Mode.Application, 2) keccak256 = OpType("keccak256", Mode.Signature | Mode.Application, 2) @@ -197,6 +197,12 @@ def min_version(self) -> int: box_len = OpType("box_len", Mode.Application, 8) box_get = OpType("box_get", Mode.Application, 8) box_put = OpType("box_put", Mode.Application, 8) + popn = OpType("popn", Mode.Signature | Mode.Application, 8) + dupn = OpType("dupn", Mode.Signature | Mode.Application, 8) + bury = OpType("bury", Mode.Signature | Mode.Application, 8) + frame_dig = OpType("frame_dig", Mode.Signature | Mode.Application, 8) + frame_bury = OpType("frame_bury", Mode.Signature | Mode.Application, 8) + proto = OpType("proto", Mode.Signature | Mode.Application, 8) # fmt: on From 6ae67e6cf0dda8cc783b2965ab6d2c210150c382 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 26 Oct 2022 09:56:48 -0400 Subject: [PATCH 064/157] add frame ops to avm8 branch --- pyteal/__init__.pyi | 6 ++++++ pyteal/ast/__init__.py | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index ce347b0eb..69e3c55eb 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -70,6 +70,7 @@ __all__ = [ "BoxReplace", "Break", "Btoi", + "Bury", "Bytes", "BytesAdd", "BytesAnd", @@ -98,6 +99,7 @@ __all__ = [ "DEFAULT_TEAL_VERSION", "Div", "Divw", + "DupN", "DynamicScratchVar", "EcdsaCurve", "EcdsaDecompress", @@ -115,6 +117,8 @@ __all__ = [ "ExtractUint32", "ExtractUint64", "For", + "FrameBury", + "FrameDig", "Ge", "GeneratedID", "GetBit", @@ -173,7 +177,9 @@ __all__ = [ "OptimizeOptions", "Or", "Pop", + "PopN", "Pragma", + "Proto", "RETURN_HASH_PREFIX", "Reject", "Replace", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 9efe807c5..1ca49a2e5 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -155,6 +155,7 @@ from pyteal.ast.for_ import For from pyteal.ast.break_ import Break from pyteal.ast.continue_ import Continue +from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN, Bury # misc from pyteal.ast.scratch import ( @@ -336,6 +337,12 @@ "For", "Break", "Continue", + "Proto", + "FrameDig", + "FrameBury", + "Bury", + "DupN", + "PopN", "Router", "CallConfig", "MethodConfig", From 917229aa8a9b8339cfeac39cf2521274ea19816a Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 26 Oct 2022 13:52:43 -0400 Subject: [PATCH 065/157] specify FRAME_POINTER_VERSION in frame-op branch --- pyteal/__init__.py | 2 ++ pyteal/__init__.pyi | 2 ++ pyteal/compiler/__init__.py | 2 ++ 3 files changed, 6 insertions(+) diff --git a/pyteal/__init__.py b/pyteal/__init__.py index ac28dd641..ba6e8eead 100644 --- a/pyteal/__init__.py +++ b/pyteal/__init__.py @@ -8,6 +8,7 @@ MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, + FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -38,6 +39,7 @@ "MIN_TEAL_VERSION", "DEFAULT_TEAL_VERSION", "MAX_PROGRAM_VERSION", + "FRAME_POINTER_VERSION", "MIN_PROGRAM_VERSION", "DEFAULT_PROGRAM_VERSION", "CompileOptions", diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 69e3c55eb..40600d561 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -11,6 +11,7 @@ from pyteal.compiler import ( MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, + FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -116,6 +117,7 @@ __all__ = [ "ExtractUint16", "ExtractUint32", "ExtractUint64", + "FRAME_POINTER_VERSION", "For", "FrameBury", "FrameDig", diff --git a/pyteal/compiler/__init__.py b/pyteal/compiler/__init__.py index e0d29450d..9755ead4f 100644 --- a/pyteal/compiler/__init__.py +++ b/pyteal/compiler/__init__.py @@ -3,6 +3,7 @@ MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, + FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -16,6 +17,7 @@ "MIN_TEAL_VERSION", "DEFAULT_TEAL_VERSION", "MAX_PROGRAM_VERSION", + "FRAME_POINTER_VERSION", "MIN_PROGRAM_VERSION", "DEFAULT_PROGRAM_VERSION", "CompileOptions", From 892dd503023ee5eda563872ea6916d9bb0495207 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 26 Oct 2022 17:12:46 -0400 Subject: [PATCH 066/157] just the work of abi data schema --- pyteal/ast/abi/__init__.py | 13 ++++- pyteal/ast/abi/address.py | 15 +++--- pyteal/ast/abi/address_test.py | 73 ++++++++++++++++++++++----- pyteal/ast/abi/array_base.py | 6 +-- pyteal/ast/abi/array_dynamic.py | 8 +-- pyteal/ast/abi/array_dynamic_test.py | 68 ++++++++++++++++++++----- pyteal/ast/abi/array_static.py | 10 ++-- pyteal/ast/abi/array_static_test.py | 49 ++++++++++++++---- pyteal/ast/abi/bool.py | 8 +-- pyteal/ast/abi/bool_test.py | 66 ++++++++++++++++++++---- pyteal/ast/abi/reference_type.py | 8 +-- pyteal/ast/abi/reference_type_test.py | 27 ++++++++-- pyteal/ast/abi/string.py | 29 +++++++---- pyteal/ast/abi/string_test.py | 65 ++++++++++++++++++++---- pyteal/ast/abi/transaction.py | 8 +-- pyteal/ast/abi/transaction_test.py | 8 ++- pyteal/ast/abi/tuple.py | 6 +-- pyteal/ast/abi/tuple_test.py | 22 ++++++-- pyteal/ast/abi/type.py | 64 ++++++++++++++++++++++- pyteal/ast/abi/type_test.py | 2 +- pyteal/ast/abi/uint.py | 39 +++++++------- pyteal/ast/abi/uint_test.py | 64 +++++++++++++++++++---- pyteal/ast/comment.py | 4 +- pyteal/ast/expr.py | 6 +-- pyteal/ast/router.py | 2 +- pyteal/ast/subroutine.py | 18 ++++--- 26 files changed, 529 insertions(+), 159 deletions(-) diff --git a/pyteal/ast/abi/__init__.py b/pyteal/ast/abi/__init__.py index f1cb3a58c..3113b8d72 100644 --- a/pyteal/ast/abi/__init__.py +++ b/pyteal/ast/abi/__init__.py @@ -4,7 +4,15 @@ Address, AddressLength, ) -from pyteal.ast.abi.type import TypeSpec, BaseType, ComputedValue, ReturnedValue +from pyteal.ast.abi.type import ( + TypeSpec, + BaseType, + ComputedValue, + ReturnedValue, + DataStorageSchema, + FrameStorage, + ScratchVarStorage, +) from pyteal.ast.abi.bool import BoolTypeSpec, Bool from pyteal.ast.abi.uint import ( UintTypeSpec, @@ -166,6 +174,9 @@ "type_specs_from_signature", "make", "size_of", + "DataStorageSchema", + "FrameStorage", + "ScratchVarStorage", "algosdk_from_annotation", "algosdk_from_type_spec", "contains_type_spec", diff --git a/pyteal/ast/abi/address.py b/pyteal/ast/abi/address.py index d0413cf6c..3165fcd9a 100644 --- a/pyteal/ast/abi/address.py +++ b/pyteal/ast/abi/address.py @@ -56,7 +56,7 @@ def get(self) -> Expr: The expression will have the type TealType.bytes. """ - return self.stored_value.load() + return self._data_storage.load_value() def set( self, @@ -108,25 +108,28 @@ def set( or value.type_spec() == StaticArrayTypeSpec(ByteTypeSpec(), AddressLength.Bytes) ): - return self.stored_value.store(value.stored_value.load()) + return self._data_storage.store_value( + value._data_storage.load_value() + ) raise TealInputError( f"Got {value} with type spec {value.type_spec()}, expected AddressTypeSpec" ) case str(): # Addr throws if value is invalid address - return self.stored_value.store(Addr(value)) + return self._data_storage.store_value(Addr(value)) case bytes(): if len(value) == AddressLength.Bytes: - return self.stored_value.store(Bytes(value)) + return self._data_storage.store_value(Bytes(value)) raise TealInputError( f"Got bytes with length {len(value)}, expected {AddressLength.Bytes}" ) case Expr(): return Seq( - self.stored_value.store(value), + self._data_storage.store_value(value), Assert( - Len(self.stored_value.load()) == Int(AddressLength.Bytes.value) + Len(self._data_storage.load_value()) + == Int(AddressLength.Bytes.value) ), ) case CollectionSequence(): diff --git a/pyteal/ast/abi/address_test.py b/pyteal/ast/abi/address_test.py index 7cc9cd449..305046619 100644 --- a/pyteal/ast/abi/address_test.py +++ b/pyteal/ast/abi/address_test.py @@ -1,4 +1,5 @@ import pytest +from typing import cast import pyteal as pt from pyteal import abi @@ -48,7 +49,13 @@ def test_Address_encode(): assert expr.has_return() is False expected = pt.TealSimpleBlock( - [pt.TealOp(expr, pt.Op.load, value.stored_value.slot)] + [ + pt.TealOp( + expr, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + ] ) actual, _ = expr.__teal__(options) assert actual == expected @@ -79,7 +86,7 @@ def test_Address_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expectedExpr = value.stored_value.store( + expectedExpr = value._data_storage.store_value( substring_for_decoding( encoded, start_index=start_index, @@ -106,7 +113,13 @@ def test_Address_get(): assert expr.has_return() is False expected = pt.TealSimpleBlock( - [pt.TealOp(expr, pt.Op.load, value.stored_value.slot)] + [ + pt.TealOp( + expr, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + ] ) actual, _ = expr.__teal__(options) assert actual == expected @@ -123,8 +136,16 @@ def test_Address_set_StaticArray(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, value_to_set.stored_value.slot), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value_to_set._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -150,7 +171,11 @@ def test_Address_set_str(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.addr, value_to_set), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -175,7 +200,11 @@ def test_Address_set_bytes(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.byte, f"0x{value_to_set.hex()}"), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -204,8 +233,16 @@ def test_Address_set_expr(): expected = pt.TealSimpleBlock( [ vts.ops[0], - pt.TealOp(None, pt.Op.store, value.stored_value.slot), - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.int, AddressLength.Bytes.value), pt.TealOp(None, pt.Op.eq), @@ -230,8 +267,16 @@ def test_Address_set_copy(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, other.stored_value.slot), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -259,7 +304,11 @@ def test_Address_set_computed(): expected = pt.TealSimpleBlock( [ byte_ops.ops[0], - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) diff --git a/pyteal/ast/abi/array_base.py b/pyteal/ast/abi/array_base.py index aea164c81..4674f1d90 100644 --- a/pyteal/ast/abi/array_base.py +++ b/pyteal/ast/abi/array_base.py @@ -104,7 +104,7 @@ def decode( extracted = substring_for_decoding( encoded, start_index=start_index, end_index=end_index, length=length ) - return self.stored_value.store(extracted) + return self._data_storage.store_value(extracted) def set(self, values: Sequence[T]) -> Expr: """Set the ABI array with a sequence of ABI type variables. @@ -142,7 +142,7 @@ def set(self, values: Sequence[T]) -> Expr: length_prefix = Seq(length_tmp.set(len(values)), length_tmp.encode()) encoded = Concat(length_prefix, encoded) - return self.stored_value.store(encoded) + return self._data_storage.store_value(encoded) def encode(self) -> Expr: """Encode the ABI array to be a byte string. @@ -150,7 +150,7 @@ def encode(self) -> Expr: Returns: A PyTeal expression that encodes this ABI array to a byte string. """ - return self.stored_value.load() + return self._data_storage.load_value() @abstractmethod def length(self) -> Expr: diff --git a/pyteal/ast/abi/array_dynamic.py b/pyteal/ast/abi/array_dynamic.py index 9d53e0559..2a5f7367d 100644 --- a/pyteal/ast/abi/array_dynamic.py +++ b/pyteal/ast/abi/array_dynamic.py @@ -79,7 +79,7 @@ def set( raise TealInputError( f"Cannot assign type {values.type_spec()} to {self.type_spec()}" ) - return self.stored_value.store(values.encode()) + return self._data_storage.store_value(values.encode()) return super().set(values) def length(self) -> Expr: @@ -165,10 +165,10 @@ def set( match values: case bytes() | bytearray(): - return self.stored_value.store(_encoded_byte_string(values)) + return self._data_storage.store_value(_encoded_byte_string(values)) case Expr(): return _store_encoded_expr_byte_string_into_var( - values, self.stored_value + values, self._data_storage ) return super().set(values) @@ -181,7 +181,7 @@ def get(self) -> Expr: Returns: A Pyteal expression that loads byte encoding of this DynamicBytes, and drop the first uint16 DynamicArray length encoding. """ - return Suffix(self.stored_value.load(), Int(2)) + return Suffix(self._data_storage.load_value(), Int(2)) DynamicBytes.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/array_dynamic_test.py b/pyteal/ast/abi/array_dynamic_test.py index 326f72294..fa0e122e1 100644 --- a/pyteal/ast/abi/array_dynamic_test.py +++ b/pyteal/ast/abi/array_dynamic_test.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, cast import pytest import pyteal as pt @@ -106,7 +106,7 @@ def test_DynamicArray_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value.stored_value.store( + expectedExpr = value._data_storage.store_value( substring_for_decoding( encoded, start_index=start_index, @@ -141,7 +141,7 @@ def test_DynamicArray_set_values(): assert not expr.has_return() length_tmp = abi.Uint16() - expectedExpr = value.stored_value.store( + expectedExpr = value._data_storage.store_value( pt.Concat( pt.Seq(length_tmp.set(len(values)), length_tmp.encode()), _encode_tuple(values), @@ -182,8 +182,16 @@ def test_DynamicArray_set_copy(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, otherArray.stored_value.slot), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, otherArray._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -207,7 +215,11 @@ def test_DynamicArray_set_computed(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.byte, '"this should be a dynamic array"'), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) actual, _ = expr.__teal__(options) @@ -253,7 +265,11 @@ def test_DynamicBytes_set_py_bytes(test_case: bytes | bytearray): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.byte, "0x" + length_encoding + BYTE_HEX_TEST_CASE), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -280,14 +296,30 @@ def test_DynamicBytes_set_expr(test_case: bytes | bytearray): pt.TealOp(None, pt.Op.byte, "0x" + BYTE_HEX_TEST_CASE), pt.TealOp(None, pt.Op.byte, "0x" + BYTE_HEX_TEST_CASE), pt.TealOp(None, pt.Op.concat), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.itob), pt.TealOp(None, pt.Op.extract, 6, 0), - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.concat), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -308,7 +340,11 @@ def test_DynamicBytes_get(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.extract, 2, 0), ] ) @@ -325,7 +361,13 @@ def test_DynamicArray_encode(): assert not expr.has_return() expected = pt.TealSimpleBlock( - [pt.TealOp(None, pt.Op.load, value.stored_value.slot)] + [ + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + ] ) actual, _ = expr.__teal__(options) diff --git a/pyteal/ast/abi/array_static.py b/pyteal/ast/abi/array_static.py index 7744a6edb..caf2dcc88 100644 --- a/pyteal/ast/abi/array_static.py +++ b/pyteal/ast/abi/array_static.py @@ -109,7 +109,7 @@ def set( raise TealInputError( f"Cannot assign type {values.type_spec()} to {self.type_spec()}" ) - return self.stored_value.store(values.encode()) + return self._data_storage.store_value(values.encode()) if self.type_spec().length_static() != len(values): raise TealInputError( @@ -207,11 +207,11 @@ def set( raise TealInputError( f"Got bytes with length {len(values)}, expect {self.type_spec().length_static()}" ) - return self.stored_value.store(Bytes(values)) + return self._data_storage.store_value(Bytes(values)) case Expr(): return Seq( - self.stored_value.store(values), - Assert(self.length() == Len(self.stored_value.load())), + self._data_storage.store_value(values), + Assert(self.length() == Len(self._data_storage.load_value())), ) return super().set(values) @@ -222,7 +222,7 @@ def get(self) -> Expr: Returns: A Pyteal expression that loads byte encoding of this StaticBytes. """ - return self.stored_value.load() + return self._data_storage.load_value() StaticBytes.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/array_static_test.py b/pyteal/ast/abi/array_static_test.py index 91781a682..236e2591e 100644 --- a/pyteal/ast/abi/array_static_test.py +++ b/pyteal/ast/abi/array_static_test.py @@ -1,4 +1,5 @@ import pytest +from typing import cast import pyteal as pt from pyteal import abi @@ -158,7 +159,7 @@ def test_StaticArray_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value.stored_value.store( + expectedExpr = value._data_storage.store_value( substring_for_decoding( encoded, start_index=start_index, @@ -201,7 +202,7 @@ def test_StaticArray_set_values(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value.stored_value.store(_encode_tuple(values)) + expectedExpr = value._data_storage.store_value(_encode_tuple(values)) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) @@ -233,8 +234,16 @@ def test_StaticArray_set_copy(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, otherArray.stored_value.slot), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, otherArray._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -258,7 +267,11 @@ def test_StaticArray_set_computed(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.byte, '"indeed this is hard to simulate"'), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) actual, _ = expr.__teal__(options) @@ -301,7 +314,11 @@ def test_StaticBytes_set_py_bytes(test_case: bytes | bytearray): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.byte, "0x" + BYTE_HEX_TEST_CASE), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -332,9 +349,17 @@ def test_StaticBytes_expr(test_case: bytes | bytearray): pt.TealOp(None, pt.Op.byte, "0x" + BYTE_HEX_TEST_CASE), pt.TealOp(None, pt.Op.byte, "0x" + BYTE_HEX_TEST_CASE), pt.TealOp(None, pt.Op.concat), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.int, 32), - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.eq), pt.TealOp(None, pt.Op.assert_), @@ -352,7 +377,13 @@ def test_StaticArray_encode(): assert not expr.has_return() expected = pt.TealSimpleBlock( - [pt.TealOp(None, pt.Op.load, value.stored_value.slot)] + [ + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + ] ) actual, _ = expr.__teal__(options) diff --git a/pyteal/ast/abi/bool.py b/pyteal/ast/abi/bool.py index 13552b6db..2bfbd3aca 100644 --- a/pyteal/ast/abi/bool.py +++ b/pyteal/ast/abi/bool.py @@ -50,7 +50,7 @@ def get(self) -> Expr: expression that evaluates to 0 will be returned. In either case, the expression will have the type TealType.uint64. """ - return self.stored_value.load() + return self._data_storage.load_value() def set(self, value: Union[bool, Expr, "Bool", ComputedValue["Bool"]]) -> Expr: """Set the value of this Bool to the input value. @@ -85,10 +85,10 @@ def set(self, value: Union[bool, Expr, "Bool", ComputedValue["Bool"]]) -> Expr: checked = True if checked: - return self.stored_value.store(value) + return self._data_storage.store_value(value) # Not(Not(value)) coerces all values greater than 0 to 1 - return self.stored_value.store(Not(Not(value))) + return self._data_storage.store_value(Not(Not(value))) def decode( self, @@ -103,7 +103,7 @@ def decode( return self.decode_bit(encoded, start_index * Int(NUM_BITS_IN_BYTE)) def decode_bit(self, encoded, bit_index: Expr) -> Expr: - return self.stored_value.store(GetBit(encoded, bit_index)) + return self._data_storage.store_value(GetBit(encoded, bit_index)) def encode(self) -> Expr: return SetBit(Bytes(b"\x00"), Int(0), self.get()) diff --git a/pyteal/ast/abi/bool_test.py b/pyteal/ast/abi/bool_test.py index 45ffa7e30..411bdf376 100644 --- a/pyteal/ast/abi/bool_test.py +++ b/pyteal/ast/abi/bool_test.py @@ -1,4 +1,4 @@ -from typing import NamedTuple, List +from typing import NamedTuple, List, cast import pytest import pyteal as pt @@ -53,7 +53,11 @@ def test_Bool_set_static(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.int, 1 if value_to_set else 0), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -78,7 +82,11 @@ def test_Bool_set_expr(): pt.TealOp(None, pt.Op.logic_or), pt.TealOp(None, pt.Op.logic_not), pt.TealOp(None, pt.Op.logic_not), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -99,8 +107,16 @@ def test_Bool_set_copy(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, other.stored_value.slot), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -125,7 +141,11 @@ def test_Bool_set_computed(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.int, 0x80), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -147,7 +167,13 @@ def test_Bool_get(): assert not expr.has_return() expected = pt.TealSimpleBlock( - [pt.TealOp(expr, pt.Op.load, value.stored_value.slot)] + [ + pt.TealOp( + expr, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + ] ) actual, _ = expr.__teal__(options) @@ -174,7 +200,13 @@ def test_Bool_decode(): pt.TealOp(None, pt.Op.int, 8), pt.TealOp(None, pt.Op.mul), pt.TealOp(None, pt.Op.getbit), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast( + abi.ScratchVarStorage, value._data_storage + ).scratchvar.slot, + ), ] ) @@ -199,7 +231,11 @@ def test_Bool_decode_bit(): pt.TealOp(None, pt.Op.byte, '"encoded"'), pt.TealOp(None, pt.Op.int, 17), pt.TealOp(None, pt.Op.getbit), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -221,7 +257,11 @@ def test_Bool_encode(): [ pt.TealOp(None, pt.Op.byte, "0x00"), pt.TealOp(None, pt.Op.int, 0), - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.setbit), ] ) @@ -401,7 +441,11 @@ class EncodeSeqTest(NamedTuple): setBits = [ [ pt.TealOp(None, pt.Op.int, j), - pt.TealOp(None, pt.Op.load, testType.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, testType._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.setbit), ] for j, testType in enumerate(test.types) diff --git a/pyteal/ast/abi/reference_type.py b/pyteal/ast/abi/reference_type.py index f4882fc97..2ea723b92 100644 --- a/pyteal/ast/abi/reference_type.py +++ b/pyteal/ast/abi/reference_type.py @@ -58,7 +58,7 @@ def referenced_index(self) -> Expr: If this reference type is an application or asset, note that this DOES NOT return the application or asset ID. See :code:`application_id()` or :code:`asset_id()` for that. """ - return self.stored_value.load() + return self._data_storage.load_value() def decode( self, @@ -70,7 +70,7 @@ def decode( ) -> Expr: return uint_decode( self.type_spec().bit_size(), - self.stored_value, + self._data_storage, encoded, start_index, end_index, @@ -107,7 +107,7 @@ def __init__(self) -> None: def address(self) -> Expr: """Get the address of the account.""" - return Txn.accounts[self.stored_value.load()] + return Txn.accounts[self._data_storage.load_value()] def params(self) -> AccountParamObject: """Get information about the account.""" @@ -205,7 +205,7 @@ def __init__(self) -> None: def application_id(self) -> Expr: """Get the ID of the application.""" - return Txn.applications[self.stored_value.load()] + return Txn.applications[self._data_storage.load_value()] def params(self) -> AppParamObject: """Get information about the application's parameters.""" diff --git a/pyteal/ast/abi/reference_type_test.py b/pyteal/ast/abi/reference_type_test.py index 99555ab12..aaa1e5d97 100644 --- a/pyteal/ast/abi/reference_type_test.py +++ b/pyteal/ast/abi/reference_type_test.py @@ -1,4 +1,5 @@ import pytest +from typing import cast import pyteal as pt from pyteal import abi @@ -22,7 +23,11 @@ def test_ReferenceType_referenced_index(): expected = pt.TealSimpleBlock( [ - pt.TealOp(expr, pt.Op.load, value.stored_value.slot), + pt.TealOp( + expr, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) actual, _ = expr.__teal__(options) @@ -56,7 +61,7 @@ def test_ReferenceType_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expected_decoding = value.stored_value.store( + expected_decoding = value._data_storage.store_value( pt.GetByte( encoded, start_index if start_index is not None else pt.Int(0), @@ -109,7 +114,11 @@ def test_Account_address(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.txnas, "Accounts"), ] ) @@ -192,7 +201,11 @@ def test_Asset_asset_id(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.txnas, "Assets"), ] ) @@ -282,7 +295,11 @@ def test_Application_application_id(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.txnas, "Applications"), ] ) diff --git a/pyteal/ast/abi/string.py b/pyteal/ast/abi/string.py index 4c9b31c08..0359aee76 100644 --- a/pyteal/ast/abi/string.py +++ b/pyteal/ast/abi/string.py @@ -4,7 +4,7 @@ from algosdk.abi import ABIType from pyteal.ast.abi.uint import Byte -from pyteal.ast.abi.type import ComputedValue, BaseType +from pyteal.ast.abi.type import ComputedValue, BaseType, DataStorageSchema from pyteal.ast.abi.array_dynamic import DynamicArray, DynamicArrayTypeSpec from pyteal.ast.abi.uint import ByteTypeSpec, Uint16TypeSpec @@ -12,7 +12,6 @@ from pyteal.ast.expr import Expr from pyteal.ast.bytes import Bytes from pyteal.ast.seq import Seq -from pyteal.ast.scratchvar import ScratchVar from pyteal.ast.unaryexpr import Itob, Len from pyteal.ast.substring import Suffix from pyteal.ast.naryexpr import Concat @@ -25,11 +24,15 @@ def _encoded_byte_string(s: bytes | bytearray) -> Expr: return Bytes(prefix + s) -def _store_encoded_expr_byte_string_into_var(value: Expr, location: ScratchVar) -> Expr: +def _store_encoded_expr_byte_string_into_var( + value: Expr, location: DataStorageSchema +) -> Expr: return Seq( - location.store(value), - location.store( - Concat(Suffix(Itob(Len(location.load())), Int(6)), location.load()) + location.store_value(value), + location.store_value( + Concat( + Suffix(Itob(Len(location.load_value())), Int(6)), location.load_value() + ) ), ) @@ -67,7 +70,7 @@ def get(self) -> Expr: The expression will have the type TealType.bytes. """ return Suffix( - self.stored_value.load(), Int(Uint16TypeSpec().byte_length_static()) + self._data_storage.load_value(), Int(Uint16TypeSpec().byte_length_static()) ) def set( @@ -110,18 +113,22 @@ def set( if value.type_spec() == StringTypeSpec() or ( value.type_spec() == DynamicArrayTypeSpec(ByteTypeSpec()) ): - return self.stored_value.store(value.stored_value.load()) + return self._data_storage.store_value( + value._data_storage.load_value() + ) raise TealInputError( f"Got {value} with type spec {value.type_spec()}, expected {StringTypeSpec}" ) case bytes() | bytearray(): - return self.stored_value.store(_encoded_byte_string(value)) + return self._data_storage.store_value(_encoded_byte_string(value)) case str(): - return self.stored_value.store(_encoded_byte_string(value.encode())) + return self._data_storage.store_value( + _encoded_byte_string(value.encode()) + ) case Expr(): return _store_encoded_expr_byte_string_into_var( - value, self.stored_value + value, self._data_storage ) case CollectionSequence(): return super().set(cast(Sequence[Byte], value)) diff --git a/pyteal/ast/abi/string_test.py b/pyteal/ast/abi/string_test.py index 6a600d55a..79a699a4c 100644 --- a/pyteal/ast/abi/string_test.py +++ b/pyteal/ast/abi/string_test.py @@ -1,4 +1,5 @@ import pytest +from typing import cast import pyteal as pt from pyteal import abi @@ -39,7 +40,13 @@ def test_String_encode(): assert expr.has_return() is False expected = pt.TealSimpleBlock( - [pt.TealOp(expr, pt.Op.load, value.stored_value.slot)] + [ + pt.TealOp( + expr, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + ] ) actual, _ = expr.__teal__(options) assert actual == expected @@ -69,7 +76,7 @@ def test_DynamicArray_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expectedExpr = value.stored_value.store( + expectedExpr = value._data_storage.store_value( substring_for_decoding( encoded, start_index=start_index, @@ -97,7 +104,11 @@ def test_String_get(): expected = pt.TealSimpleBlock( [ - pt.TealOp(expr, pt.Op.load, value.stored_value.slot), + pt.TealOp( + expr, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.extract, 2, 0), ] ) @@ -129,7 +140,11 @@ def test_String_set_static(value_to_set, value_encoded): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.byte, "0x" + value_encoded.hex()), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -156,14 +171,30 @@ def test_String_set_expr(): value_start, value_end = value_to_set.__teal__(options) expected_body = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.store, value.stored_value.slot), - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.itob), pt.TealOp(None, pt.Op.extract, 6, 0), - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.concat), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) value_end.setNextBlock(expected_body) @@ -188,8 +219,16 @@ def test_String_set_copy(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, other.stored_value.slot), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -217,7 +256,11 @@ def test_String_set_computed(): expected = pt.TealSimpleBlock( [ byte_ops.ops[0], - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) diff --git a/pyteal/ast/abi/transaction.py b/pyteal/ast/abi/transaction.py index aeb5c7a33..2451a1285 100644 --- a/pyteal/ast/abi/transaction.py +++ b/pyteal/ast/abi/transaction.py @@ -82,16 +82,16 @@ def _set_index( case ComputedValue(): return self._set_with_computed_type(value) case BaseType(): - return self.stored_value.store(self.stored_value.load()) + return self._data_storage.store_value(self._data_storage.load_value()) case int(): - return self.stored_value.store(Int(value)) + return self._data_storage.store_value(Int(value)) case Expr(): - return self.stored_value.store(value) + return self._data_storage.store_value(value) case _: raise TealInputError(f"Cant store a {type(value)} in a Transaction") def index(self) -> Expr: - return self.stored_value.load() + return self._data_storage.load_value() def decode( self, diff --git a/pyteal/ast/abi/transaction_test.py b/pyteal/ast/abi/transaction_test.py index 5803b8f32..573d6f440 100644 --- a/pyteal/ast/abi/transaction_test.py +++ b/pyteal/ast/abi/transaction_test.py @@ -1,5 +1,5 @@ from dataclasses import dataclass -from typing import List +from typing import List, cast import pyteal as pt from pyteal import abi import pytest @@ -131,7 +131,11 @@ def test_Transaction__set_index(): expected = pt.TealSimpleBlock( [ pt.TealOp(expr, pt.Op.int, val_to_set), - pt.TealOp(None, pt.Op.store, tv.t.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, tv.t._data_storage).scratchvar.slot, + ), ] ) actual, _ = expr.__teal__(options) diff --git a/pyteal/ast/abi/tuple.py b/pyteal/ast/abi/tuple.py index bc1966414..2f2dceeab 100644 --- a/pyteal/ast/abi/tuple.py +++ b/pyteal/ast/abi/tuple.py @@ -309,7 +309,7 @@ def decode( extracted = substring_for_decoding( encoded, start_index=start_index, end_index=end_index, length=length ) - return self.stored_value.store(extracted) + return self._data_storage.store_value(extracted) @overload def set(self, *values: BaseType) -> Expr: @@ -352,10 +352,10 @@ def set(self, *values): ) if not all(myTypes[i] == values[i].type_spec() for i in range(len(myTypes))): raise TealInputError("Input values do not match type") - return self.stored_value.store(_encode_tuple(values)) + return self._data_storage.store_value(_encode_tuple(values)) def encode(self) -> Expr: - return self.stored_value.load() + return self._data_storage.load_value() def length(self) -> Expr: """Get the number of values this tuple holds as an Expr.""" diff --git a/pyteal/ast/abi/tuple_test.py b/pyteal/ast/abi/tuple_test.py index 7fc98cdae..8365769cc 100644 --- a/pyteal/ast/abi/tuple_test.py +++ b/pyteal/ast/abi/tuple_test.py @@ -1,4 +1,4 @@ -from typing import NamedTuple, List, Callable, Literal +from typing import NamedTuple, List, Callable, Literal, cast import pytest import pyteal as pt @@ -623,7 +623,7 @@ def test_Tuple_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = tupleValue.stored_value.store( + expectedExpr = tupleValue._data_storage.store_value( substring_for_decoding( encoded, start_index=start_index, @@ -672,7 +672,9 @@ def test_Tuple_set(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = tupleValue.stored_value.store(_encode_tuple([uint8, uint16, uint32])) + expectedExpr = tupleValue._data_storage.store_value( + _encode_tuple([uint8, uint16, uint32]) + ) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) @@ -701,7 +703,11 @@ def test_Tuple_set_Computed(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.byte, '"internal representation"'), - pt.TealOp(None, pt.Op.store, tupleValue.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, tupleValue._data_storage).scratchvar.slot, + ), ] ) actual, _ = expr.__teal__(options) @@ -727,7 +733,13 @@ def test_Tuple_encode(): assert not expr.has_return() expected = pt.TealSimpleBlock( - [pt.TealOp(None, pt.Op.load, tupleValue.stored_value.slot)] + [ + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, tupleValue._data_storage).scratchvar.slot, + ), + ] ) actual, _ = expr.__teal__(options) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index 4b0b1e0f3..67d75cc4b 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -65,6 +65,55 @@ def __str__(self) -> str: TypeSpec.__module__ = "pyteal.abi" +class DataStorageSchema(ABC): + @abstractmethod + def store_value(self, value: Expr) -> Expr: + pass + + @abstractmethod + def load_value(self) -> Expr: + pass + + @abstractmethod + def storage_type(self) -> TealType: + pass + + +class ScratchVarStorage(DataStorageSchema): + def __init__(self, storage_type: TealType) -> None: + super().__init__() + self.scratchvar: Final = ScratchVar(storage_type) + + def load_value(self) -> Expr: + return self.scratchvar.load() + + def store_value(self, value: Expr) -> Expr: + return self.scratchvar.slot.store(value) + + def storage_type(self) -> TealType: + return self.scratchvar.storage_type() + + +class FrameStorage(DataStorageSchema): + def __init__(self, storage_type: TealType, stack_depth: int) -> None: + super().__init__() + self.stack_type = storage_type + self.stack_depth = stack_depth + + def storage_type(self) -> TealType: + return self.stack_type + + def store_value(self, value: Expr) -> Expr: + from pyteal.ast import FrameBury + + return FrameBury(value, self.stack_depth) + + def load_value(self) -> Expr: + from pyteal.ast import FrameDig + + return FrameDig(self.stack_depth) + + class BaseType(ABC): """The abstract base class for all ABI type instances. @@ -77,7 +126,18 @@ def __init__(self, spec: TypeSpec) -> None: """Create a new BaseType.""" super().__init__() self._type_spec: Final = spec - self.stored_value: Final = ScratchVar(spec.storage_type()) + self._data_storage: DataStorageSchema = ScratchVarStorage(spec.storage_type()) + + # self.stored_value: Final = ScratchVar(spec.storage_type()) + + def _set_data_source(self, storage: DataStorageSchema) -> None: + self._data_storage = storage + + def _load_value(self) -> Expr: + return self._data_storage.load_value() + + def _store_value(self, value: Expr) -> Expr: + return self._data_storage.store_value(value) def type_spec(self) -> TypeSpec: """Get the TypeSpec for this ABI type instance.""" @@ -231,7 +291,7 @@ def store_into(self, output: BaseType) -> Expr: f"ABI return subroutine deferred_expr is expected to be typed {output.type_spec().storage_type()}, " f"but has type {declaration.deferred_expr.type_of()}." ) - return output.stored_value.slot.store(self.computation) + return output._data_storage.store_value(self.computation) ReturnedValue.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/type_test.py b/pyteal/ast/abi/type_test.py index 56a9e6c76..b5134ef7d 100644 --- a/pyteal/ast/abi/type_test.py +++ b/pyteal/ast/abi/type_test.py @@ -17,7 +17,7 @@ def store_into(self, output: abi.BaseType) -> pt.Expr: raise pt.TealInputError( f"expected type_spec {self.type_spec} but get {output.type_spec()}" ) - return output.stored_value.store(self.encodings) + return output._data_storage.store_value(self.encodings) def test_ComputedType_use(): diff --git a/pyteal/ast/abi/uint.py b/pyteal/ast/abi/uint.py index 9855c29b9..e34daac9a 100644 --- a/pyteal/ast/abi/uint.py +++ b/pyteal/ast/abi/uint.py @@ -8,7 +8,6 @@ from pyteal.types import TealType from pyteal.errors import TealInputError -from pyteal.ast.scratchvar import ScratchVar from pyteal.ast.expr import Expr from pyteal.ast.seq import Seq from pyteal.ast.assert_ import Assert @@ -18,7 +17,7 @@ from pyteal.ast.unaryexpr import Itob, Btoi from pyteal.ast.binaryexpr import GetByte, ExtractUint16, ExtractUint32, ExtractUint64 from pyteal.ast.ternaryexpr import SetByte -from pyteal.ast.abi.type import ComputedValue, TypeSpec, BaseType +from pyteal.ast.abi.type import ComputedValue, TypeSpec, BaseType, DataStorageSchema NUM_BITS_IN_BYTE = 8 @@ -31,7 +30,9 @@ def uint_storage_type(size: int) -> TealType: return TealType.bytes -def uint_set(size: int, uint_var: ScratchVar, value: Union[int, Expr, "Uint"]) -> Expr: +def uint_set( + size: int, uint_var: DataStorageSchema, value: Union[int, Expr, "Uint"] +) -> Expr: if size > 64: raise NotImplementedError( "Uint operations have not yet been implemented for bit sizes larger than 64" @@ -49,17 +50,17 @@ def uint_set(size: int, uint_var: ScratchVar, value: Union[int, Expr, "Uint"]) - checked = True if checked or size == 64: - return uint_var.store(cast(Expr, value)) + return uint_var.store_value(cast(Expr, value)) return Seq( - uint_var.store(cast(Expr, value)), - Assert(uint_var.load() < Int(2**size)), + uint_var.store_value(cast(Expr, value)), + Assert(uint_var.load_value() < Int(2**size)), ) def uint_decode( size: int, - uint_var: ScratchVar, + uint_var: DataStorageSchema, encoded: Expr, start_index: Optional[Expr], end_index: Optional[Expr], @@ -73,27 +74,27 @@ def uint_decode( if size == 64: if start_index is None: if end_index is None and length is None: - return uint_var.store(Btoi(encoded)) + return uint_var.store_value(Btoi(encoded)) start_index = Int(0) - return uint_var.store(ExtractUint64(encoded, start_index)) + return uint_var.store_value(ExtractUint64(encoded, start_index)) if start_index is None: start_index = Int(0) if size == 8: - return uint_var.store(GetByte(encoded, start_index)) + return uint_var.store_value(GetByte(encoded, start_index)) if size == 16: - return uint_var.store(ExtractUint16(encoded, start_index)) + return uint_var.store_value(ExtractUint16(encoded, start_index)) if size == 32: - return uint_var.store(ExtractUint32(encoded, start_index)) + return uint_var.store_value(ExtractUint32(encoded, start_index)) raise ValueError("Unsupported uint size: {}".format(size)) -def uint_encode(size: int, uint_var: Expr | ScratchVar) -> Expr: +def uint_encode(size: int, uint_var: Expr | DataStorageSchema) -> Expr: - if isinstance(uint_var, ScratchVar): - uint_var = uint_var.load() + if isinstance(uint_var, DataStorageSchema): + uint_var = uint_var.load_value() if size > 64: raise NotImplementedError( @@ -240,7 +241,7 @@ def get(self) -> Expr: The expression will have the type TealType.uint64. """ - return self.stored_value.load() + return self._data_storage.load_value() def set(self, value: Union[int, Expr, "Uint", ComputedValue["Uint"]]) -> Expr: """Set the value of this Uint to the input value. @@ -275,7 +276,7 @@ def set(self, value: Union[int, Expr, "Uint", ComputedValue["Uint"]]) -> Expr: value.type_spec(), self.type_spec() ) ) - return uint_set(self.type_spec().bit_size(), self.stored_value, value) + return uint_set(self.type_spec().bit_size(), self._data_storage, value) def decode( self, @@ -287,7 +288,7 @@ def decode( ) -> Expr: return uint_decode( self.type_spec().bit_size(), - self.stored_value, + self._data_storage, encoded, start_index, end_index, @@ -295,7 +296,7 @@ def decode( ) def encode(self) -> Expr: - return uint_encode(self.type_spec().bit_size(), self.stored_value) + return uint_encode(self.type_spec().bit_size(), self._data_storage) Uint.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/uint_test.py b/pyteal/ast/abi/uint_test.py index 3af64f865..c4659fdb9 100644 --- a/pyteal/ast/abi/uint_test.py +++ b/pyteal/ast/abi/uint_test.py @@ -1,4 +1,4 @@ -from typing import List, Tuple, NamedTuple, Callable, Union, Optional +from typing import List, Tuple, NamedTuple, Callable, Union, Optional, cast from pyteal.ast.abi.type_test import ContainerType import pyteal as pt from pyteal import abi @@ -139,7 +139,13 @@ def test_Uint_set_static(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.int, value_to_set), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast( + abi.ScratchVarStorage, value._data_storage + ).scratchvar.slot, + ), ] ) @@ -167,7 +173,11 @@ def test_Uint_set_expr(): upperBoundCheck = [] if test.checkUpperBound: upperBoundCheck = [ - pt.TealOp(None, pt.Op.load, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), pt.TealOp(None, pt.Op.int, test.maxValue + 1), pt.TealOp(None, pt.Op.lt), pt.TealOp(None, pt.Op.assert_), @@ -178,7 +188,11 @@ def test_Uint_set_expr(): pt.TealOp(None, pt.Op.int, 10), pt.TealOp(None, pt.Op.int, 1), pt.TealOp(None, pt.Op.add), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] + upperBoundCheck ) @@ -201,8 +215,16 @@ def test_Uint_set_copy(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, other.stored_value.slot), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -230,7 +252,11 @@ def test_Uint_set_computed(): expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.int, 0x44), - pt.TealOp(None, pt.Op.store, value.stored_value.slot), + pt.TealOp( + None, + pt.Op.store, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), ] ) @@ -253,7 +279,13 @@ def test_Uint_get(): assert not expr.has_return() expected = pt.TealSimpleBlock( - [pt.TealOp(expr, pt.Op.load, value.stored_value.slot)] + [ + pt.TealOp( + expr, + pt.Op.load, + cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + ), + ] ) actual, _ = expr.__teal__(options) @@ -277,7 +309,7 @@ def test_Uint_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedDecoding = value.stored_value.store( + expectedDecoding = value._data_storage.store_value( test.expectedDecoding(encoded, start_index, end_index, length) ) expected, _ = expectedDecoding.__teal__(options) @@ -326,8 +358,18 @@ def test_ByteUint8_mutual_conversion(): expected = pt.TealSimpleBlock( [ - pt.TealOp(None, pt.Op.load, other.stored_value.slot), - pt.TealOp(None, pt.Op.store, type_b_instance.stored_value.slot), + pt.TealOp( + None, + pt.Op.load, + cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + ), + pt.TealOp( + None, + pt.Op.store, + cast( + abi.ScratchVarStorage, type_b_instance._data_storage + ).scratchvar.slot, + ), ] ) diff --git a/pyteal/ast/comment.py b/pyteal/ast/comment.py index 58c89d63d..361694677 100644 --- a/pyteal/ast/comment.py +++ b/pyteal/ast/comment.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, Tuple +from typing import TYPE_CHECKING from pyteal.errors import TealInputError from pyteal.types import TealType @@ -26,7 +26,7 @@ def __init__(self, single_line_comment: str) -> None: ) self.comment = single_line_comment - def __teal__(self, options: "CompileOptions") -> Tuple[TealBlock, TealSimpleBlock]: + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: op = TealOp(self, Op.comment, self.comment) return TealBlock.FromOp(options, op) diff --git a/pyteal/ast/expr.py b/pyteal/ast/expr.py index c2de1ca32..0f57eebce 100644 --- a/pyteal/ast/expr.py +++ b/pyteal/ast/expr.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from typing import Tuple, List, TYPE_CHECKING +from typing import TYPE_CHECKING from pyteal.types import TealType from pyteal.ir import TealBlock, TealSimpleBlock @@ -16,7 +16,7 @@ def __init__(self): self.trace = traceback.format_stack()[0:-1] - def getDefinitionTrace(self) -> List[str]: + def getDefinitionTrace(self) -> list[str]: return self.trace @abstractmethod @@ -35,7 +35,7 @@ def __str__(self) -> str: pass @abstractmethod - def __teal__(self, options: "CompileOptions") -> Tuple[TealBlock, TealSimpleBlock]: + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: """Assemble TEAL IR for this component and its arguments.""" pass diff --git a/pyteal/ast/router.py b/pyteal/ast/router.py index 5349cfe84..d10204501 100644 --- a/pyteal/ast/router.py +++ b/pyteal/ast/router.py @@ -352,7 +352,7 @@ def wrap_handler( ) # All subroutine arg values, initialize here and use below instead of - # creating new instances on the fly so we dont have to think about splicing + # creating new instances on the fly, so we don't have to think about splicing # back in the transaction types arg_vals = [typespec.new_instance() for typespec in arg_type_specs] diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 0c5e0205f..7fd38bc9d 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -9,7 +9,7 @@ from pyteal.ast.expr import Expr from pyteal.ast.seq import Seq from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar -from pyteal.errors import TealInputError, verifyProgramVersion +from pyteal.errors import TealInputError, TealInternalError, verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.types import TealType @@ -378,7 +378,7 @@ def __init__( elif isinstance(arg, ScratchVar): arg_type = arg.type elif isinstance(arg, abi.BaseType): - arg_type = cast(abi.BaseType, arg).stored_value.type + arg_type = cast(abi.BaseType, arg)._data_storage.storage_type() else: raise TealInputError( f"Subroutine argument {arg} at index {i} was of unexpected Python type {type(arg)}" @@ -420,7 +420,7 @@ def handle_arg(arg: Expr | ScratchVar | abi.BaseType) -> Expr: elif isinstance(arg, Expr): return arg elif isinstance(arg, abi.BaseType): - return arg.stored_value.load() + return arg._data_storage.load_value() else: raise TealInputError( f"cannot handle current arg: {arg} to put it on stack" @@ -595,8 +595,6 @@ def __call__( ) return invoked - self.subroutine.get_declaration() - return abi.ReturnedValue( self.output_kwarg_info.abi_type, invoked, @@ -793,6 +791,8 @@ def evaluate_subroutine(subroutine: SubroutineDefinition) -> SubroutineDeclarati def var_n_loaded( param: str, ) -> tuple[ScratchVar, ScratchVar | abi.BaseType | Expr]: + from pyteal.ast.abi.type import ScratchVarStorage + loaded_var: ScratchVar | abi.BaseType | Expr argument_var: ScratchVar @@ -801,7 +801,11 @@ def var_n_loaded( loaded_var = argument_var elif param in subroutine.abi_args: internal_abi_var = subroutine.abi_args[param].new_instance() - argument_var = internal_abi_var.stored_value + if not isinstance(internal_abi_var._data_storage, ScratchVarStorage): + raise TealInternalError( + "subroutine ABI args must have data schema being ScratchVarStorage" + ) + argument_var = internal_abi_var._data_storage.scratchvar loaded_var = internal_abi_var else: argument_var = ScratchVar(TealType.anytype) @@ -849,7 +853,7 @@ def var_n_loaded( f"ABI returning subroutine definition should evaluate to TealType.none, " f"while evaluate to {subroutine_body.type_of()}." ) - deferred_expr = output_carrying_abi.stored_value.load() + deferred_expr = output_carrying_abi._data_storage.load_value() # Arg usage "A" to be pick up and store in scratch parameters that have been placed on the stack # need to reverse order of argumentVars because the last argument will be on top of the stack From 5ec41244e6db30ac9723cac5ea5b5da35f338177 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Thu, 27 Oct 2022 10:49:51 -0400 Subject: [PATCH 067/157] narrower name, module name --- pyteal/ast/abi/__init__.py | 4 ++-- pyteal/ast/abi/address_test.py | 22 +++++++++++----------- pyteal/ast/abi/array_dynamic_test.py | 20 ++++++++++---------- pyteal/ast/abi/array_static_test.py | 14 +++++++------- pyteal/ast/abi/bool_test.py | 20 ++++++++++---------- pyteal/ast/abi/reference_type_test.py | 8 ++++---- pyteal/ast/abi/string_test.py | 20 ++++++++++---------- pyteal/ast/abi/transaction_test.py | 2 +- pyteal/ast/abi/tuple_test.py | 4 ++-- pyteal/ast/abi/type.py | 13 +++++++++++-- pyteal/ast/abi/uint_test.py | 20 +++++++++----------- pyteal/ast/subroutine.py | 4 ++-- 12 files changed, 79 insertions(+), 72 deletions(-) diff --git a/pyteal/ast/abi/__init__.py b/pyteal/ast/abi/__init__.py index 3113b8d72..3ca3ab290 100644 --- a/pyteal/ast/abi/__init__.py +++ b/pyteal/ast/abi/__init__.py @@ -11,7 +11,7 @@ ReturnedValue, DataStorageSchema, FrameStorage, - ScratchVarStorage, + ScratchStorage, ) from pyteal.ast.abi.bool import BoolTypeSpec, Bool from pyteal.ast.abi.uint import ( @@ -176,7 +176,7 @@ "size_of", "DataStorageSchema", "FrameStorage", - "ScratchVarStorage", + "ScratchStorage", "algosdk_from_annotation", "algosdk_from_type_spec", "contains_type_spec", diff --git a/pyteal/ast/abi/address_test.py b/pyteal/ast/abi/address_test.py index 305046619..dca9136dc 100644 --- a/pyteal/ast/abi/address_test.py +++ b/pyteal/ast/abi/address_test.py @@ -53,7 +53,7 @@ def test_Address_encode(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -117,7 +117,7 @@ def test_Address_get(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -139,12 +139,12 @@ def test_Address_set_StaticArray(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value_to_set._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value_to_set._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -174,7 +174,7 @@ def test_Address_set_str(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -203,7 +203,7 @@ def test_Address_set_bytes(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -236,12 +236,12 @@ def test_Address_set_expr(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.int, AddressLength.Bytes.value), @@ -270,12 +270,12 @@ def test_Address_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -307,7 +307,7 @@ def test_Address_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) diff --git a/pyteal/ast/abi/array_dynamic_test.py b/pyteal/ast/abi/array_dynamic_test.py index fa0e122e1..3e172eeee 100644 --- a/pyteal/ast/abi/array_dynamic_test.py +++ b/pyteal/ast/abi/array_dynamic_test.py @@ -185,12 +185,12 @@ def test_DynamicArray_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, otherArray._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, otherArray._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -218,7 +218,7 @@ def test_DynamicArray_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -268,7 +268,7 @@ def test_DynamicBytes_set_py_bytes(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -299,12 +299,12 @@ def test_DynamicBytes_set_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.itob), @@ -312,13 +312,13 @@ def test_DynamicBytes_set_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.concat), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -343,7 +343,7 @@ def test_DynamicBytes_get(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.extract, 2, 0), ] @@ -365,7 +365,7 @@ def test_DynamicArray_encode(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) diff --git a/pyteal/ast/abi/array_static_test.py b/pyteal/ast/abi/array_static_test.py index 236e2591e..7d0a8ae0a 100644 --- a/pyteal/ast/abi/array_static_test.py +++ b/pyteal/ast/abi/array_static_test.py @@ -237,12 +237,12 @@ def test_StaticArray_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, otherArray._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, otherArray._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -270,7 +270,7 @@ def test_StaticArray_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -317,7 +317,7 @@ def test_StaticBytes_set_py_bytes(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -352,13 +352,13 @@ def test_StaticBytes_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.int, 32), pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.eq), @@ -381,7 +381,7 @@ def test_StaticArray_encode(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) diff --git a/pyteal/ast/abi/bool_test.py b/pyteal/ast/abi/bool_test.py index 411bdf376..4299b72ce 100644 --- a/pyteal/ast/abi/bool_test.py +++ b/pyteal/ast/abi/bool_test.py @@ -56,7 +56,7 @@ def test_Bool_set_static(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -85,7 +85,7 @@ def test_Bool_set_expr(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -110,12 +110,12 @@ def test_Bool_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -144,7 +144,7 @@ def test_Bool_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -171,7 +171,7 @@ def test_Bool_get(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -204,7 +204,7 @@ def test_Bool_decode(): None, pt.Op.store, cast( - abi.ScratchVarStorage, value._data_storage + abi.ScratchStorage, value._data_storage ).scratchvar.slot, ), ] @@ -234,7 +234,7 @@ def test_Bool_decode_bit(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -260,7 +260,7 @@ def test_Bool_encode(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.setbit), ] @@ -444,7 +444,7 @@ class EncodeSeqTest(NamedTuple): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, testType._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, testType._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.setbit), ] diff --git a/pyteal/ast/abi/reference_type_test.py b/pyteal/ast/abi/reference_type_test.py index aaa1e5d97..d3b8aaf93 100644 --- a/pyteal/ast/abi/reference_type_test.py +++ b/pyteal/ast/abi/reference_type_test.py @@ -26,7 +26,7 @@ def test_ReferenceType_referenced_index(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -117,7 +117,7 @@ def test_Account_address(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.txnas, "Accounts"), ] @@ -204,7 +204,7 @@ def test_Asset_asset_id(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.txnas, "Assets"), ] @@ -298,7 +298,7 @@ def test_Application_application_id(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.txnas, "Applications"), ] diff --git a/pyteal/ast/abi/string_test.py b/pyteal/ast/abi/string_test.py index 79a699a4c..fb8de7fb9 100644 --- a/pyteal/ast/abi/string_test.py +++ b/pyteal/ast/abi/string_test.py @@ -44,7 +44,7 @@ def test_String_encode(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -107,7 +107,7 @@ def test_String_get(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.extract, 2, 0), ] @@ -143,7 +143,7 @@ def test_String_set_static(value_to_set, value_encoded): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -174,12 +174,12 @@ def test_String_set_expr(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.itob), @@ -187,13 +187,13 @@ def test_String_set_expr(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.concat), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -222,12 +222,12 @@ def test_String_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -259,7 +259,7 @@ def test_String_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) diff --git a/pyteal/ast/abi/transaction_test.py b/pyteal/ast/abi/transaction_test.py index 573d6f440..e21802950 100644 --- a/pyteal/ast/abi/transaction_test.py +++ b/pyteal/ast/abi/transaction_test.py @@ -134,7 +134,7 @@ def test_Transaction__set_index(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, tv.t._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, tv.t._data_storage).scratchvar.slot, ), ] ) diff --git a/pyteal/ast/abi/tuple_test.py b/pyteal/ast/abi/tuple_test.py index 8365769cc..777d3688e 100644 --- a/pyteal/ast/abi/tuple_test.py +++ b/pyteal/ast/abi/tuple_test.py @@ -706,7 +706,7 @@ def test_Tuple_set_Computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, tupleValue._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, tupleValue._data_storage).scratchvar.slot, ), ] ) @@ -737,7 +737,7 @@ def test_Tuple_encode(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, tupleValue._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, tupleValue._data_storage).scratchvar.slot, ), ] ) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index 67d75cc4b..c505021c0 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -79,7 +79,10 @@ def storage_type(self) -> TealType: pass -class ScratchVarStorage(DataStorageSchema): +DataStorageSchema.__module__ = "pyteal" + + +class ScratchStorage(DataStorageSchema): def __init__(self, storage_type: TealType) -> None: super().__init__() self.scratchvar: Final = ScratchVar(storage_type) @@ -94,6 +97,9 @@ def storage_type(self) -> TealType: return self.scratchvar.storage_type() +ScratchStorage.__module__ = "pyteal" + + class FrameStorage(DataStorageSchema): def __init__(self, storage_type: TealType, stack_depth: int) -> None: super().__init__() @@ -114,6 +120,9 @@ def load_value(self) -> Expr: return FrameDig(self.stack_depth) +FrameStorage.__module__ = "pyteal" + + class BaseType(ABC): """The abstract base class for all ABI type instances. @@ -126,7 +135,7 @@ def __init__(self, spec: TypeSpec) -> None: """Create a new BaseType.""" super().__init__() self._type_spec: Final = spec - self._data_storage: DataStorageSchema = ScratchVarStorage(spec.storage_type()) + self._data_storage: DataStorageSchema = ScratchStorage(spec.storage_type()) # self.stored_value: Final = ScratchVar(spec.storage_type()) diff --git a/pyteal/ast/abi/uint_test.py b/pyteal/ast/abi/uint_test.py index c4659fdb9..d4b7cd137 100644 --- a/pyteal/ast/abi/uint_test.py +++ b/pyteal/ast/abi/uint_test.py @@ -142,9 +142,7 @@ def test_Uint_set_static(): pt.TealOp( None, pt.Op.store, - cast( - abi.ScratchVarStorage, value._data_storage - ).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -176,7 +174,7 @@ def test_Uint_set_expr(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), pt.TealOp(None, pt.Op.int, test.maxValue + 1), pt.TealOp(None, pt.Op.lt), @@ -191,7 +189,7 @@ def test_Uint_set_expr(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] + upperBoundCheck @@ -218,12 +216,12 @@ def test_Uint_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -255,7 +253,7 @@ def test_Uint_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -283,7 +281,7 @@ def test_Uint_get(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchVarStorage, value._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, ), ] ) @@ -361,13 +359,13 @@ def test_ByteUint8_mutual_conversion(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchVarStorage, other._data_storage).scratchvar.slot, + cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, ), pt.TealOp( None, pt.Op.store, cast( - abi.ScratchVarStorage, type_b_instance._data_storage + abi.ScratchStorage, type_b_instance._data_storage ).scratchvar.slot, ), ] diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 7fd38bc9d..70365d756 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -791,7 +791,7 @@ def evaluate_subroutine(subroutine: SubroutineDefinition) -> SubroutineDeclarati def var_n_loaded( param: str, ) -> tuple[ScratchVar, ScratchVar | abi.BaseType | Expr]: - from pyteal.ast.abi.type import ScratchVarStorage + from pyteal.ast.abi.type import ScratchStorage loaded_var: ScratchVar | abi.BaseType | Expr argument_var: ScratchVar @@ -801,7 +801,7 @@ def var_n_loaded( loaded_var = argument_var elif param in subroutine.abi_args: internal_abi_var = subroutine.abi_args[param].new_instance() - if not isinstance(internal_abi_var._data_storage, ScratchVarStorage): + if not isinstance(internal_abi_var._data_storage, ScratchStorage): raise TealInternalError( "subroutine ABI args must have data schema being ScratchVarStorage" ) From 7b60233d11b10cec15f5e9dc69a26f5c4468dc80 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 09:05:09 -0400 Subject: [PATCH 068/157] per review comments, on final type annotation --- pyteal/ast/abi/type.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index c505021c0..dfaa9bd16 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -85,7 +85,7 @@ def storage_type(self) -> TealType: class ScratchStorage(DataStorageSchema): def __init__(self, storage_type: TealType) -> None: super().__init__() - self.scratchvar: Final = ScratchVar(storage_type) + self.scratchvar: Final[ScratchVar] = ScratchVar(storage_type) def load_value(self) -> Expr: return self.scratchvar.load() @@ -134,7 +134,7 @@ class BaseType(ABC): def __init__(self, spec: TypeSpec) -> None: """Create a new BaseType.""" super().__init__() - self._type_spec: Final = spec + self._type_spec: Final[TypeSpec] = spec self._data_storage: DataStorageSchema = ScratchStorage(spec.storage_type()) # self.stored_value: Final = ScratchVar(spec.storage_type()) From 2055ce69affc011dc8992fa0166f753157699be9 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 09:33:35 -0400 Subject: [PATCH 069/157] per review comments, renaem to AbstractVar/FrameVar --- pyteal/ast/abi/__init__.py | 4 ++-- pyteal/ast/abi/address.py | 15 +++++-------- pyteal/ast/abi/address_test.py | 2 +- pyteal/ast/abi/array_base.py | 6 ++--- pyteal/ast/abi/array_dynamic.py | 6 ++--- pyteal/ast/abi/array_dynamic_test.py | 4 ++-- pyteal/ast/abi/array_static.py | 10 ++++----- pyteal/ast/abi/array_static_test.py | 4 ++-- pyteal/ast/abi/bool.py | 8 +++---- pyteal/ast/abi/reference_type.py | 6 ++--- pyteal/ast/abi/reference_type_test.py | 2 +- pyteal/ast/abi/string.py | 24 ++++++++------------ pyteal/ast/abi/string_test.py | 2 +- pyteal/ast/abi/transaction.py | 8 +++---- pyteal/ast/abi/tuple.py | 6 ++--- pyteal/ast/abi/tuple_test.py | 4 ++-- pyteal/ast/abi/type.py | 30 ++++++++++++------------- pyteal/ast/abi/type_test.py | 2 +- pyteal/ast/abi/uint.py | 32 +++++++++++++-------------- pyteal/ast/abi/uint_test.py | 2 +- pyteal/ast/subroutine.py | 4 ++-- 21 files changed, 85 insertions(+), 96 deletions(-) diff --git a/pyteal/ast/abi/__init__.py b/pyteal/ast/abi/__init__.py index 3ca3ab290..4baa3bc16 100644 --- a/pyteal/ast/abi/__init__.py +++ b/pyteal/ast/abi/__init__.py @@ -9,7 +9,7 @@ BaseType, ComputedValue, ReturnedValue, - DataStorageSchema, + AbstractVar, FrameStorage, ScratchStorage, ) @@ -174,7 +174,7 @@ "type_specs_from_signature", "make", "size_of", - "DataStorageSchema", + "AbstractVar", "FrameStorage", "ScratchStorage", "algosdk_from_annotation", diff --git a/pyteal/ast/abi/address.py b/pyteal/ast/abi/address.py index 3165fcd9a..0fea62c8a 100644 --- a/pyteal/ast/abi/address.py +++ b/pyteal/ast/abi/address.py @@ -56,7 +56,7 @@ def get(self) -> Expr: The expression will have the type TealType.bytes. """ - return self._data_storage.load_value() + return self._data_storage.load() def set( self, @@ -108,28 +108,25 @@ def set( or value.type_spec() == StaticArrayTypeSpec(ByteTypeSpec(), AddressLength.Bytes) ): - return self._data_storage.store_value( - value._data_storage.load_value() - ) + return self._data_storage.store(value._data_storage.load()) raise TealInputError( f"Got {value} with type spec {value.type_spec()}, expected AddressTypeSpec" ) case str(): # Addr throws if value is invalid address - return self._data_storage.store_value(Addr(value)) + return self._data_storage.store(Addr(value)) case bytes(): if len(value) == AddressLength.Bytes: - return self._data_storage.store_value(Bytes(value)) + return self._data_storage.store(Bytes(value)) raise TealInputError( f"Got bytes with length {len(value)}, expected {AddressLength.Bytes}" ) case Expr(): return Seq( - self._data_storage.store_value(value), + self._data_storage.store(value), Assert( - Len(self._data_storage.load_value()) - == Int(AddressLength.Bytes.value) + Len(self._data_storage.load()) == Int(AddressLength.Bytes.value) ), ) case CollectionSequence(): diff --git a/pyteal/ast/abi/address_test.py b/pyteal/ast/abi/address_test.py index dca9136dc..ccecb0ecf 100644 --- a/pyteal/ast/abi/address_test.py +++ b/pyteal/ast/abi/address_test.py @@ -86,7 +86,7 @@ def test_Address_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expectedExpr = value._data_storage.store_value( + expectedExpr = value._data_storage.store( substring_for_decoding( encoded, start_index=start_index, diff --git a/pyteal/ast/abi/array_base.py b/pyteal/ast/abi/array_base.py index 4674f1d90..417e401e1 100644 --- a/pyteal/ast/abi/array_base.py +++ b/pyteal/ast/abi/array_base.py @@ -104,7 +104,7 @@ def decode( extracted = substring_for_decoding( encoded, start_index=start_index, end_index=end_index, length=length ) - return self._data_storage.store_value(extracted) + return self._data_storage.store(extracted) def set(self, values: Sequence[T]) -> Expr: """Set the ABI array with a sequence of ABI type variables. @@ -142,7 +142,7 @@ def set(self, values: Sequence[T]) -> Expr: length_prefix = Seq(length_tmp.set(len(values)), length_tmp.encode()) encoded = Concat(length_prefix, encoded) - return self._data_storage.store_value(encoded) + return self._data_storage.store(encoded) def encode(self) -> Expr: """Encode the ABI array to be a byte string. @@ -150,7 +150,7 @@ def encode(self) -> Expr: Returns: A PyTeal expression that encodes this ABI array to a byte string. """ - return self._data_storage.load_value() + return self._data_storage.load() @abstractmethod def length(self) -> Expr: diff --git a/pyteal/ast/abi/array_dynamic.py b/pyteal/ast/abi/array_dynamic.py index 2a5f7367d..a39373324 100644 --- a/pyteal/ast/abi/array_dynamic.py +++ b/pyteal/ast/abi/array_dynamic.py @@ -79,7 +79,7 @@ def set( raise TealInputError( f"Cannot assign type {values.type_spec()} to {self.type_spec()}" ) - return self._data_storage.store_value(values.encode()) + return self._data_storage.store(values.encode()) return super().set(values) def length(self) -> Expr: @@ -165,7 +165,7 @@ def set( match values: case bytes() | bytearray(): - return self._data_storage.store_value(_encoded_byte_string(values)) + return self._data_storage.store(_encoded_byte_string(values)) case Expr(): return _store_encoded_expr_byte_string_into_var( values, self._data_storage @@ -181,7 +181,7 @@ def get(self) -> Expr: Returns: A Pyteal expression that loads byte encoding of this DynamicBytes, and drop the first uint16 DynamicArray length encoding. """ - return Suffix(self._data_storage.load_value(), Int(2)) + return Suffix(self._data_storage.load(), Int(2)) DynamicBytes.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/array_dynamic_test.py b/pyteal/ast/abi/array_dynamic_test.py index 3e172eeee..589d52664 100644 --- a/pyteal/ast/abi/array_dynamic_test.py +++ b/pyteal/ast/abi/array_dynamic_test.py @@ -106,7 +106,7 @@ def test_DynamicArray_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value._data_storage.store_value( + expectedExpr = value._data_storage.store( substring_for_decoding( encoded, start_index=start_index, @@ -141,7 +141,7 @@ def test_DynamicArray_set_values(): assert not expr.has_return() length_tmp = abi.Uint16() - expectedExpr = value._data_storage.store_value( + expectedExpr = value._data_storage.store( pt.Concat( pt.Seq(length_tmp.set(len(values)), length_tmp.encode()), _encode_tuple(values), diff --git a/pyteal/ast/abi/array_static.py b/pyteal/ast/abi/array_static.py index caf2dcc88..a631687f3 100644 --- a/pyteal/ast/abi/array_static.py +++ b/pyteal/ast/abi/array_static.py @@ -109,7 +109,7 @@ def set( raise TealInputError( f"Cannot assign type {values.type_spec()} to {self.type_spec()}" ) - return self._data_storage.store_value(values.encode()) + return self._data_storage.store(values.encode()) if self.type_spec().length_static() != len(values): raise TealInputError( @@ -207,11 +207,11 @@ def set( raise TealInputError( f"Got bytes with length {len(values)}, expect {self.type_spec().length_static()}" ) - return self._data_storage.store_value(Bytes(values)) + return self._data_storage.store(Bytes(values)) case Expr(): return Seq( - self._data_storage.store_value(values), - Assert(self.length() == Len(self._data_storage.load_value())), + self._data_storage.store(values), + Assert(self.length() == Len(self._data_storage.load())), ) return super().set(values) @@ -222,7 +222,7 @@ def get(self) -> Expr: Returns: A Pyteal expression that loads byte encoding of this StaticBytes. """ - return self._data_storage.load_value() + return self._data_storage.load() StaticBytes.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/array_static_test.py b/pyteal/ast/abi/array_static_test.py index 7d0a8ae0a..7174c2ebb 100644 --- a/pyteal/ast/abi/array_static_test.py +++ b/pyteal/ast/abi/array_static_test.py @@ -159,7 +159,7 @@ def test_StaticArray_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value._data_storage.store_value( + expectedExpr = value._data_storage.store( substring_for_decoding( encoded, start_index=start_index, @@ -202,7 +202,7 @@ def test_StaticArray_set_values(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value._data_storage.store_value(_encode_tuple(values)) + expectedExpr = value._data_storage.store(_encode_tuple(values)) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) diff --git a/pyteal/ast/abi/bool.py b/pyteal/ast/abi/bool.py index 2bfbd3aca..6d42c2fdd 100644 --- a/pyteal/ast/abi/bool.py +++ b/pyteal/ast/abi/bool.py @@ -50,7 +50,7 @@ def get(self) -> Expr: expression that evaluates to 0 will be returned. In either case, the expression will have the type TealType.uint64. """ - return self._data_storage.load_value() + return self._data_storage.load() def set(self, value: Union[bool, Expr, "Bool", ComputedValue["Bool"]]) -> Expr: """Set the value of this Bool to the input value. @@ -85,10 +85,10 @@ def set(self, value: Union[bool, Expr, "Bool", ComputedValue["Bool"]]) -> Expr: checked = True if checked: - return self._data_storage.store_value(value) + return self._data_storage.store(value) # Not(Not(value)) coerces all values greater than 0 to 1 - return self._data_storage.store_value(Not(Not(value))) + return self._data_storage.store(Not(Not(value))) def decode( self, @@ -103,7 +103,7 @@ def decode( return self.decode_bit(encoded, start_index * Int(NUM_BITS_IN_BYTE)) def decode_bit(self, encoded, bit_index: Expr) -> Expr: - return self._data_storage.store_value(GetBit(encoded, bit_index)) + return self._data_storage.store(GetBit(encoded, bit_index)) def encode(self) -> Expr: return SetBit(Bytes(b"\x00"), Int(0), self.get()) diff --git a/pyteal/ast/abi/reference_type.py b/pyteal/ast/abi/reference_type.py index 2ea723b92..aa0709ffe 100644 --- a/pyteal/ast/abi/reference_type.py +++ b/pyteal/ast/abi/reference_type.py @@ -58,7 +58,7 @@ def referenced_index(self) -> Expr: If this reference type is an application or asset, note that this DOES NOT return the application or asset ID. See :code:`application_id()` or :code:`asset_id()` for that. """ - return self._data_storage.load_value() + return self._data_storage.load() def decode( self, @@ -107,7 +107,7 @@ def __init__(self) -> None: def address(self) -> Expr: """Get the address of the account.""" - return Txn.accounts[self._data_storage.load_value()] + return Txn.accounts[self._data_storage.load()] def params(self) -> AccountParamObject: """Get information about the account.""" @@ -205,7 +205,7 @@ def __init__(self) -> None: def application_id(self) -> Expr: """Get the ID of the application.""" - return Txn.applications[self._data_storage.load_value()] + return Txn.applications[self._data_storage.load()] def params(self) -> AppParamObject: """Get information about the application's parameters.""" diff --git a/pyteal/ast/abi/reference_type_test.py b/pyteal/ast/abi/reference_type_test.py index d3b8aaf93..edc0a857c 100644 --- a/pyteal/ast/abi/reference_type_test.py +++ b/pyteal/ast/abi/reference_type_test.py @@ -61,7 +61,7 @@ def test_ReferenceType_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expected_decoding = value._data_storage.store_value( + expected_decoding = value._data_storage.store( pt.GetByte( encoded, start_index if start_index is not None else pt.Int(0), diff --git a/pyteal/ast/abi/string.py b/pyteal/ast/abi/string.py index 0359aee76..f91eb272f 100644 --- a/pyteal/ast/abi/string.py +++ b/pyteal/ast/abi/string.py @@ -4,7 +4,7 @@ from algosdk.abi import ABIType from pyteal.ast.abi.uint import Byte -from pyteal.ast.abi.type import ComputedValue, BaseType, DataStorageSchema +from pyteal.ast.abi.type import ComputedValue, BaseType, AbstractVar from pyteal.ast.abi.array_dynamic import DynamicArray, DynamicArrayTypeSpec from pyteal.ast.abi.uint import ByteTypeSpec, Uint16TypeSpec @@ -25,14 +25,12 @@ def _encoded_byte_string(s: bytes | bytearray) -> Expr: def _store_encoded_expr_byte_string_into_var( - value: Expr, location: DataStorageSchema + value: Expr, location: AbstractVar ) -> Expr: return Seq( - location.store_value(value), - location.store_value( - Concat( - Suffix(Itob(Len(location.load_value())), Int(6)), location.load_value() - ) + location.store(value), + location.store( + Concat(Suffix(Itob(Len(location.load())), Int(6)), location.load()) ), ) @@ -70,7 +68,7 @@ def get(self) -> Expr: The expression will have the type TealType.bytes. """ return Suffix( - self._data_storage.load_value(), Int(Uint16TypeSpec().byte_length_static()) + self._data_storage.load(), Int(Uint16TypeSpec().byte_length_static()) ) def set( @@ -113,19 +111,15 @@ def set( if value.type_spec() == StringTypeSpec() or ( value.type_spec() == DynamicArrayTypeSpec(ByteTypeSpec()) ): - return self._data_storage.store_value( - value._data_storage.load_value() - ) + return self._data_storage.store(value._data_storage.load()) raise TealInputError( f"Got {value} with type spec {value.type_spec()}, expected {StringTypeSpec}" ) case bytes() | bytearray(): - return self._data_storage.store_value(_encoded_byte_string(value)) + return self._data_storage.store(_encoded_byte_string(value)) case str(): - return self._data_storage.store_value( - _encoded_byte_string(value.encode()) - ) + return self._data_storage.store(_encoded_byte_string(value.encode())) case Expr(): return _store_encoded_expr_byte_string_into_var( value, self._data_storage diff --git a/pyteal/ast/abi/string_test.py b/pyteal/ast/abi/string_test.py index fb8de7fb9..e335da1a1 100644 --- a/pyteal/ast/abi/string_test.py +++ b/pyteal/ast/abi/string_test.py @@ -76,7 +76,7 @@ def test_DynamicArray_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expectedExpr = value._data_storage.store_value( + expectedExpr = value._data_storage.store( substring_for_decoding( encoded, start_index=start_index, diff --git a/pyteal/ast/abi/transaction.py b/pyteal/ast/abi/transaction.py index 2451a1285..1f3ea9ba2 100644 --- a/pyteal/ast/abi/transaction.py +++ b/pyteal/ast/abi/transaction.py @@ -82,16 +82,16 @@ def _set_index( case ComputedValue(): return self._set_with_computed_type(value) case BaseType(): - return self._data_storage.store_value(self._data_storage.load_value()) + return self._data_storage.store(self._data_storage.load()) case int(): - return self._data_storage.store_value(Int(value)) + return self._data_storage.store(Int(value)) case Expr(): - return self._data_storage.store_value(value) + return self._data_storage.store(value) case _: raise TealInputError(f"Cant store a {type(value)} in a Transaction") def index(self) -> Expr: - return self._data_storage.load_value() + return self._data_storage.load() def decode( self, diff --git a/pyteal/ast/abi/tuple.py b/pyteal/ast/abi/tuple.py index 2f2dceeab..efea10e36 100644 --- a/pyteal/ast/abi/tuple.py +++ b/pyteal/ast/abi/tuple.py @@ -309,7 +309,7 @@ def decode( extracted = substring_for_decoding( encoded, start_index=start_index, end_index=end_index, length=length ) - return self._data_storage.store_value(extracted) + return self._data_storage.store(extracted) @overload def set(self, *values: BaseType) -> Expr: @@ -352,10 +352,10 @@ def set(self, *values): ) if not all(myTypes[i] == values[i].type_spec() for i in range(len(myTypes))): raise TealInputError("Input values do not match type") - return self._data_storage.store_value(_encode_tuple(values)) + return self._data_storage.store(_encode_tuple(values)) def encode(self) -> Expr: - return self._data_storage.load_value() + return self._data_storage.load() def length(self) -> Expr: """Get the number of values this tuple holds as an Expr.""" diff --git a/pyteal/ast/abi/tuple_test.py b/pyteal/ast/abi/tuple_test.py index 777d3688e..ad231784f 100644 --- a/pyteal/ast/abi/tuple_test.py +++ b/pyteal/ast/abi/tuple_test.py @@ -623,7 +623,7 @@ def test_Tuple_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = tupleValue._data_storage.store_value( + expectedExpr = tupleValue._data_storage.store( substring_for_decoding( encoded, start_index=start_index, @@ -672,7 +672,7 @@ def test_Tuple_set(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = tupleValue._data_storage.store_value( + expectedExpr = tupleValue._data_storage.store( _encode_tuple([uint8, uint16, uint32]) ) expected, _ = expectedExpr.__teal__(options) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index dfaa9bd16..3ae5d585c 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -65,13 +65,13 @@ def __str__(self) -> str: TypeSpec.__module__ = "pyteal.abi" -class DataStorageSchema(ABC): +class AbstractVar(ABC): @abstractmethod - def store_value(self, value: Expr) -> Expr: + def store(self, value: Expr) -> Expr: pass @abstractmethod - def load_value(self) -> Expr: + def load(self) -> Expr: pass @abstractmethod @@ -79,18 +79,18 @@ def storage_type(self) -> TealType: pass -DataStorageSchema.__module__ = "pyteal" +AbstractVar.__module__ = "pyteal" -class ScratchStorage(DataStorageSchema): +class ScratchStorage(AbstractVar): def __init__(self, storage_type: TealType) -> None: super().__init__() self.scratchvar: Final[ScratchVar] = ScratchVar(storage_type) - def load_value(self) -> Expr: + def load(self) -> Expr: return self.scratchvar.load() - def store_value(self, value: Expr) -> Expr: + def store(self, value: Expr) -> Expr: return self.scratchvar.slot.store(value) def storage_type(self) -> TealType: @@ -100,7 +100,7 @@ def storage_type(self) -> TealType: ScratchStorage.__module__ = "pyteal" -class FrameStorage(DataStorageSchema): +class FrameStorage(AbstractVar): def __init__(self, storage_type: TealType, stack_depth: int) -> None: super().__init__() self.stack_type = storage_type @@ -109,12 +109,12 @@ def __init__(self, storage_type: TealType, stack_depth: int) -> None: def storage_type(self) -> TealType: return self.stack_type - def store_value(self, value: Expr) -> Expr: + def store(self, value: Expr) -> Expr: from pyteal.ast import FrameBury return FrameBury(value, self.stack_depth) - def load_value(self) -> Expr: + def load(self) -> Expr: from pyteal.ast import FrameDig return FrameDig(self.stack_depth) @@ -135,18 +135,18 @@ def __init__(self, spec: TypeSpec) -> None: """Create a new BaseType.""" super().__init__() self._type_spec: Final[TypeSpec] = spec - self._data_storage: DataStorageSchema = ScratchStorage(spec.storage_type()) + self._data_storage: AbstractVar = ScratchStorage(spec.storage_type()) # self.stored_value: Final = ScratchVar(spec.storage_type()) - def _set_data_source(self, storage: DataStorageSchema) -> None: + def _set_data_source(self, storage: AbstractVar) -> None: self._data_storage = storage def _load_value(self) -> Expr: - return self._data_storage.load_value() + return self._data_storage.load() def _store_value(self, value: Expr) -> Expr: - return self._data_storage.store_value(value) + return self._data_storage.store(value) def type_spec(self) -> TypeSpec: """Get the TypeSpec for this ABI type instance.""" @@ -300,7 +300,7 @@ def store_into(self, output: BaseType) -> Expr: f"ABI return subroutine deferred_expr is expected to be typed {output.type_spec().storage_type()}, " f"but has type {declaration.deferred_expr.type_of()}." ) - return output._data_storage.store_value(self.computation) + return output._data_storage.store(self.computation) ReturnedValue.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/type_test.py b/pyteal/ast/abi/type_test.py index b5134ef7d..30f39e0fc 100644 --- a/pyteal/ast/abi/type_test.py +++ b/pyteal/ast/abi/type_test.py @@ -17,7 +17,7 @@ def store_into(self, output: abi.BaseType) -> pt.Expr: raise pt.TealInputError( f"expected type_spec {self.type_spec} but get {output.type_spec()}" ) - return output._data_storage.store_value(self.encodings) + return output._data_storage.store(self.encodings) def test_ComputedType_use(): diff --git a/pyteal/ast/abi/uint.py b/pyteal/ast/abi/uint.py index e34daac9a..67d3ff428 100644 --- a/pyteal/ast/abi/uint.py +++ b/pyteal/ast/abi/uint.py @@ -17,7 +17,7 @@ from pyteal.ast.unaryexpr import Itob, Btoi from pyteal.ast.binaryexpr import GetByte, ExtractUint16, ExtractUint32, ExtractUint64 from pyteal.ast.ternaryexpr import SetByte -from pyteal.ast.abi.type import ComputedValue, TypeSpec, BaseType, DataStorageSchema +from pyteal.ast.abi.type import ComputedValue, TypeSpec, BaseType, AbstractVar NUM_BITS_IN_BYTE = 8 @@ -30,9 +30,7 @@ def uint_storage_type(size: int) -> TealType: return TealType.bytes -def uint_set( - size: int, uint_var: DataStorageSchema, value: Union[int, Expr, "Uint"] -) -> Expr: +def uint_set(size: int, uint_var: AbstractVar, value: Union[int, Expr, "Uint"]) -> Expr: if size > 64: raise NotImplementedError( "Uint operations have not yet been implemented for bit sizes larger than 64" @@ -50,17 +48,17 @@ def uint_set( checked = True if checked or size == 64: - return uint_var.store_value(cast(Expr, value)) + return uint_var.store(cast(Expr, value)) return Seq( - uint_var.store_value(cast(Expr, value)), - Assert(uint_var.load_value() < Int(2**size)), + uint_var.store(cast(Expr, value)), + Assert(uint_var.load() < Int(2**size)), ) def uint_decode( size: int, - uint_var: DataStorageSchema, + uint_var: AbstractVar, encoded: Expr, start_index: Optional[Expr], end_index: Optional[Expr], @@ -74,27 +72,27 @@ def uint_decode( if size == 64: if start_index is None: if end_index is None and length is None: - return uint_var.store_value(Btoi(encoded)) + return uint_var.store(Btoi(encoded)) start_index = Int(0) - return uint_var.store_value(ExtractUint64(encoded, start_index)) + return uint_var.store(ExtractUint64(encoded, start_index)) if start_index is None: start_index = Int(0) if size == 8: - return uint_var.store_value(GetByte(encoded, start_index)) + return uint_var.store(GetByte(encoded, start_index)) if size == 16: - return uint_var.store_value(ExtractUint16(encoded, start_index)) + return uint_var.store(ExtractUint16(encoded, start_index)) if size == 32: - return uint_var.store_value(ExtractUint32(encoded, start_index)) + return uint_var.store(ExtractUint32(encoded, start_index)) raise ValueError("Unsupported uint size: {}".format(size)) -def uint_encode(size: int, uint_var: Expr | DataStorageSchema) -> Expr: +def uint_encode(size: int, uint_var: Expr | AbstractVar) -> Expr: - if isinstance(uint_var, DataStorageSchema): - uint_var = uint_var.load_value() + if isinstance(uint_var, AbstractVar): + uint_var = uint_var.load() if size > 64: raise NotImplementedError( @@ -241,7 +239,7 @@ def get(self) -> Expr: The expression will have the type TealType.uint64. """ - return self._data_storage.load_value() + return self._data_storage.load() def set(self, value: Union[int, Expr, "Uint", ComputedValue["Uint"]]) -> Expr: """Set the value of this Uint to the input value. diff --git a/pyteal/ast/abi/uint_test.py b/pyteal/ast/abi/uint_test.py index d4b7cd137..d571e7aa6 100644 --- a/pyteal/ast/abi/uint_test.py +++ b/pyteal/ast/abi/uint_test.py @@ -307,7 +307,7 @@ def test_Uint_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedDecoding = value._data_storage.store_value( + expectedDecoding = value._data_storage.store( test.expectedDecoding(encoded, start_index, end_index, length) ) expected, _ = expectedDecoding.__teal__(options) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 70365d756..d509f980b 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -420,7 +420,7 @@ def handle_arg(arg: Expr | ScratchVar | abi.BaseType) -> Expr: elif isinstance(arg, Expr): return arg elif isinstance(arg, abi.BaseType): - return arg._data_storage.load_value() + return arg._data_storage.load() else: raise TealInputError( f"cannot handle current arg: {arg} to put it on stack" @@ -853,7 +853,7 @@ def var_n_loaded( f"ABI returning subroutine definition should evaluate to TealType.none, " f"while evaluate to {subroutine_body.type_of()}." ) - deferred_expr = output_carrying_abi._data_storage.load_value() + deferred_expr = output_carrying_abi._data_storage.load() # Arg usage "A" to be pick up and store in scratch parameters that have been placed on the stack # need to reverse order of argumentVars because the last argument will be on top of the stack From f6899374313f08ae5a852988cebd7c4f056febf1 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 10:42:18 -0400 Subject: [PATCH 070/157] per review comments, move storage model to AbstractVar, rough hack to make returned value type check deactivate --- pyteal/__init__.pyi | 1 + pyteal/ast/__init__.py | 3 ++- pyteal/ast/abi/__init__.py | 2 -- pyteal/ast/abi/address.py | 12 +++++----- pyteal/ast/abi/address_test.py | 24 ++++++++++---------- pyteal/ast/abi/array_base.py | 6 ++--- pyteal/ast/abi/array_dynamic.py | 8 +++---- pyteal/ast/abi/array_dynamic_test.py | 24 ++++++++++---------- pyteal/ast/abi/array_static.py | 10 ++++----- pyteal/ast/abi/array_static_test.py | 18 +++++++-------- pyteal/ast/abi/bool.py | 8 +++---- pyteal/ast/abi/bool_test.py | 22 +++++++++--------- pyteal/ast/abi/reference_type.py | 8 +++---- pyteal/ast/abi/reference_type_test.py | 10 ++++----- pyteal/ast/abi/string.py | 10 ++++----- pyteal/ast/abi/string_test.py | 22 +++++++++--------- pyteal/ast/abi/transaction.py | 8 +++---- pyteal/ast/abi/transaction_test.py | 2 +- pyteal/ast/abi/tuple.py | 6 ++--- pyteal/ast/abi/tuple_test.py | 10 ++++----- pyteal/ast/abi/type.py | 32 ++++++--------------------- pyteal/ast/abi/type_test.py | 2 +- pyteal/ast/abi/uint.py | 8 +++---- pyteal/ast/abi/uint_test.py | 22 +++++++++--------- pyteal/ast/scratchvar.py | 21 +++++++++++++++++- pyteal/ast/subroutine.py | 12 +++++----- 26 files changed, 152 insertions(+), 159 deletions(-) diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 40600d561..ed1d3c1e1 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -35,6 +35,7 @@ from pyteal.config import ( __all__ = [ "ABIReturnSubroutine", + "AbstractVar", "AccountParam", "AccountParamObject", "Add", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 1ca49a2e5..3d2671068 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -165,7 +165,7 @@ ScratchStackStore, ScratchStore, ) -from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar +from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar, AbstractVar from pyteal.ast.maybe import MaybeValue from pyteal.ast.multi import MultiValue from pyteal.ast.opup import OpUp, OpUpMode, OpUpFeeSource @@ -305,6 +305,7 @@ "ScratchStore", "DynamicScratchVar", "ScratchVar", + "AbstractVar", "MaybeValue", "MultiValue", "OpUp", diff --git a/pyteal/ast/abi/__init__.py b/pyteal/ast/abi/__init__.py index 4baa3bc16..bb2a0d1b2 100644 --- a/pyteal/ast/abi/__init__.py +++ b/pyteal/ast/abi/__init__.py @@ -9,7 +9,6 @@ BaseType, ComputedValue, ReturnedValue, - AbstractVar, FrameStorage, ScratchStorage, ) @@ -174,7 +173,6 @@ "type_specs_from_signature", "make", "size_of", - "AbstractVar", "FrameStorage", "ScratchStorage", "algosdk_from_annotation", diff --git a/pyteal/ast/abi/address.py b/pyteal/ast/abi/address.py index 0fea62c8a..d0413cf6c 100644 --- a/pyteal/ast/abi/address.py +++ b/pyteal/ast/abi/address.py @@ -56,7 +56,7 @@ def get(self) -> Expr: The expression will have the type TealType.bytes. """ - return self._data_storage.load() + return self.stored_value.load() def set( self, @@ -108,25 +108,25 @@ def set( or value.type_spec() == StaticArrayTypeSpec(ByteTypeSpec(), AddressLength.Bytes) ): - return self._data_storage.store(value._data_storage.load()) + return self.stored_value.store(value.stored_value.load()) raise TealInputError( f"Got {value} with type spec {value.type_spec()}, expected AddressTypeSpec" ) case str(): # Addr throws if value is invalid address - return self._data_storage.store(Addr(value)) + return self.stored_value.store(Addr(value)) case bytes(): if len(value) == AddressLength.Bytes: - return self._data_storage.store(Bytes(value)) + return self.stored_value.store(Bytes(value)) raise TealInputError( f"Got bytes with length {len(value)}, expected {AddressLength.Bytes}" ) case Expr(): return Seq( - self._data_storage.store(value), + self.stored_value.store(value), Assert( - Len(self._data_storage.load()) == Int(AddressLength.Bytes.value) + Len(self.stored_value.load()) == Int(AddressLength.Bytes.value) ), ) case CollectionSequence(): diff --git a/pyteal/ast/abi/address_test.py b/pyteal/ast/abi/address_test.py index ccecb0ecf..d115082cd 100644 --- a/pyteal/ast/abi/address_test.py +++ b/pyteal/ast/abi/address_test.py @@ -53,7 +53,7 @@ def test_Address_encode(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -86,7 +86,7 @@ def test_Address_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expectedExpr = value._data_storage.store( + expectedExpr = value.stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -117,7 +117,7 @@ def test_Address_get(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -139,12 +139,12 @@ def test_Address_set_StaticArray(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value_to_set._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value_to_set.stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -174,7 +174,7 @@ def test_Address_set_str(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -203,7 +203,7 @@ def test_Address_set_bytes(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -236,12 +236,12 @@ def test_Address_set_expr(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.int, AddressLength.Bytes.value), @@ -270,12 +270,12 @@ def test_Address_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, + cast(pt.ScratchVar, other.stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -307,7 +307,7 @@ def test_Address_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/array_base.py b/pyteal/ast/abi/array_base.py index 417e401e1..aea164c81 100644 --- a/pyteal/ast/abi/array_base.py +++ b/pyteal/ast/abi/array_base.py @@ -104,7 +104,7 @@ def decode( extracted = substring_for_decoding( encoded, start_index=start_index, end_index=end_index, length=length ) - return self._data_storage.store(extracted) + return self.stored_value.store(extracted) def set(self, values: Sequence[T]) -> Expr: """Set the ABI array with a sequence of ABI type variables. @@ -142,7 +142,7 @@ def set(self, values: Sequence[T]) -> Expr: length_prefix = Seq(length_tmp.set(len(values)), length_tmp.encode()) encoded = Concat(length_prefix, encoded) - return self._data_storage.store(encoded) + return self.stored_value.store(encoded) def encode(self) -> Expr: """Encode the ABI array to be a byte string. @@ -150,7 +150,7 @@ def encode(self) -> Expr: Returns: A PyTeal expression that encodes this ABI array to a byte string. """ - return self._data_storage.load() + return self.stored_value.load() @abstractmethod def length(self) -> Expr: diff --git a/pyteal/ast/abi/array_dynamic.py b/pyteal/ast/abi/array_dynamic.py index a39373324..9d53e0559 100644 --- a/pyteal/ast/abi/array_dynamic.py +++ b/pyteal/ast/abi/array_dynamic.py @@ -79,7 +79,7 @@ def set( raise TealInputError( f"Cannot assign type {values.type_spec()} to {self.type_spec()}" ) - return self._data_storage.store(values.encode()) + return self.stored_value.store(values.encode()) return super().set(values) def length(self) -> Expr: @@ -165,10 +165,10 @@ def set( match values: case bytes() | bytearray(): - return self._data_storage.store(_encoded_byte_string(values)) + return self.stored_value.store(_encoded_byte_string(values)) case Expr(): return _store_encoded_expr_byte_string_into_var( - values, self._data_storage + values, self.stored_value ) return super().set(values) @@ -181,7 +181,7 @@ def get(self) -> Expr: Returns: A Pyteal expression that loads byte encoding of this DynamicBytes, and drop the first uint16 DynamicArray length encoding. """ - return Suffix(self._data_storage.load(), Int(2)) + return Suffix(self.stored_value.load(), Int(2)) DynamicBytes.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/array_dynamic_test.py b/pyteal/ast/abi/array_dynamic_test.py index 589d52664..e8e930787 100644 --- a/pyteal/ast/abi/array_dynamic_test.py +++ b/pyteal/ast/abi/array_dynamic_test.py @@ -106,7 +106,7 @@ def test_DynamicArray_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value._data_storage.store( + expectedExpr = value.stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -141,7 +141,7 @@ def test_DynamicArray_set_values(): assert not expr.has_return() length_tmp = abi.Uint16() - expectedExpr = value._data_storage.store( + expectedExpr = value.stored_value.store( pt.Concat( pt.Seq(length_tmp.set(len(values)), length_tmp.encode()), _encode_tuple(values), @@ -185,12 +185,12 @@ def test_DynamicArray_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, otherArray._data_storage).scratchvar.slot, + cast(pt.ScratchVar, otherArray.stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -218,7 +218,7 @@ def test_DynamicArray_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -268,7 +268,7 @@ def test_DynamicBytes_set_py_bytes(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -299,12 +299,12 @@ def test_DynamicBytes_set_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.itob), @@ -312,13 +312,13 @@ def test_DynamicBytes_set_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.concat), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -343,7 +343,7 @@ def test_DynamicBytes_get(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.extract, 2, 0), ] @@ -365,7 +365,7 @@ def test_DynamicArray_encode(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/array_static.py b/pyteal/ast/abi/array_static.py index a631687f3..7744a6edb 100644 --- a/pyteal/ast/abi/array_static.py +++ b/pyteal/ast/abi/array_static.py @@ -109,7 +109,7 @@ def set( raise TealInputError( f"Cannot assign type {values.type_spec()} to {self.type_spec()}" ) - return self._data_storage.store(values.encode()) + return self.stored_value.store(values.encode()) if self.type_spec().length_static() != len(values): raise TealInputError( @@ -207,11 +207,11 @@ def set( raise TealInputError( f"Got bytes with length {len(values)}, expect {self.type_spec().length_static()}" ) - return self._data_storage.store(Bytes(values)) + return self.stored_value.store(Bytes(values)) case Expr(): return Seq( - self._data_storage.store(values), - Assert(self.length() == Len(self._data_storage.load())), + self.stored_value.store(values), + Assert(self.length() == Len(self.stored_value.load())), ) return super().set(values) @@ -222,7 +222,7 @@ def get(self) -> Expr: Returns: A Pyteal expression that loads byte encoding of this StaticBytes. """ - return self._data_storage.load() + return self.stored_value.load() StaticBytes.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/array_static_test.py b/pyteal/ast/abi/array_static_test.py index 7174c2ebb..7c2e914ec 100644 --- a/pyteal/ast/abi/array_static_test.py +++ b/pyteal/ast/abi/array_static_test.py @@ -159,7 +159,7 @@ def test_StaticArray_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value._data_storage.store( + expectedExpr = value.stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -202,7 +202,7 @@ def test_StaticArray_set_values(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value._data_storage.store(_encode_tuple(values)) + expectedExpr = value.stored_value.store(_encode_tuple(values)) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) @@ -237,12 +237,12 @@ def test_StaticArray_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, otherArray._data_storage).scratchvar.slot, + cast(pt.ScratchVar, otherArray.stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -270,7 +270,7 @@ def test_StaticArray_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -317,7 +317,7 @@ def test_StaticBytes_set_py_bytes(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -352,13 +352,13 @@ def test_StaticBytes_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.int, 32), pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.eq), @@ -381,7 +381,7 @@ def test_StaticArray_encode(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/bool.py b/pyteal/ast/abi/bool.py index 6d42c2fdd..13552b6db 100644 --- a/pyteal/ast/abi/bool.py +++ b/pyteal/ast/abi/bool.py @@ -50,7 +50,7 @@ def get(self) -> Expr: expression that evaluates to 0 will be returned. In either case, the expression will have the type TealType.uint64. """ - return self._data_storage.load() + return self.stored_value.load() def set(self, value: Union[bool, Expr, "Bool", ComputedValue["Bool"]]) -> Expr: """Set the value of this Bool to the input value. @@ -85,10 +85,10 @@ def set(self, value: Union[bool, Expr, "Bool", ComputedValue["Bool"]]) -> Expr: checked = True if checked: - return self._data_storage.store(value) + return self.stored_value.store(value) # Not(Not(value)) coerces all values greater than 0 to 1 - return self._data_storage.store(Not(Not(value))) + return self.stored_value.store(Not(Not(value))) def decode( self, @@ -103,7 +103,7 @@ def decode( return self.decode_bit(encoded, start_index * Int(NUM_BITS_IN_BYTE)) def decode_bit(self, encoded, bit_index: Expr) -> Expr: - return self._data_storage.store(GetBit(encoded, bit_index)) + return self.stored_value.store(GetBit(encoded, bit_index)) def encode(self) -> Expr: return SetBit(Bytes(b"\x00"), Int(0), self.get()) diff --git a/pyteal/ast/abi/bool_test.py b/pyteal/ast/abi/bool_test.py index 4299b72ce..1cf881d55 100644 --- a/pyteal/ast/abi/bool_test.py +++ b/pyteal/ast/abi/bool_test.py @@ -56,7 +56,7 @@ def test_Bool_set_static(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -85,7 +85,7 @@ def test_Bool_set_expr(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -110,12 +110,12 @@ def test_Bool_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, + cast(pt.ScratchVar, other.stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -144,7 +144,7 @@ def test_Bool_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -171,7 +171,7 @@ def test_Bool_get(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -203,9 +203,7 @@ def test_Bool_decode(): pt.TealOp( None, pt.Op.store, - cast( - abi.ScratchStorage, value._data_storage - ).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -234,7 +232,7 @@ def test_Bool_decode_bit(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -260,7 +258,7 @@ def test_Bool_encode(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.setbit), ] @@ -444,7 +442,7 @@ class EncodeSeqTest(NamedTuple): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, testType._data_storage).scratchvar.slot, + cast(pt.ScratchVar, testType.stored_value).slot, ), pt.TealOp(None, pt.Op.setbit), ] diff --git a/pyteal/ast/abi/reference_type.py b/pyteal/ast/abi/reference_type.py index aa0709ffe..f4882fc97 100644 --- a/pyteal/ast/abi/reference_type.py +++ b/pyteal/ast/abi/reference_type.py @@ -58,7 +58,7 @@ def referenced_index(self) -> Expr: If this reference type is an application or asset, note that this DOES NOT return the application or asset ID. See :code:`application_id()` or :code:`asset_id()` for that. """ - return self._data_storage.load() + return self.stored_value.load() def decode( self, @@ -70,7 +70,7 @@ def decode( ) -> Expr: return uint_decode( self.type_spec().bit_size(), - self._data_storage, + self.stored_value, encoded, start_index, end_index, @@ -107,7 +107,7 @@ def __init__(self) -> None: def address(self) -> Expr: """Get the address of the account.""" - return Txn.accounts[self._data_storage.load()] + return Txn.accounts[self.stored_value.load()] def params(self) -> AccountParamObject: """Get information about the account.""" @@ -205,7 +205,7 @@ def __init__(self) -> None: def application_id(self) -> Expr: """Get the ID of the application.""" - return Txn.applications[self._data_storage.load()] + return Txn.applications[self.stored_value.load()] def params(self) -> AppParamObject: """Get information about the application's parameters.""" diff --git a/pyteal/ast/abi/reference_type_test.py b/pyteal/ast/abi/reference_type_test.py index edc0a857c..4ec862e66 100644 --- a/pyteal/ast/abi/reference_type_test.py +++ b/pyteal/ast/abi/reference_type_test.py @@ -26,7 +26,7 @@ def test_ReferenceType_referenced_index(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -61,7 +61,7 @@ def test_ReferenceType_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expected_decoding = value._data_storage.store( + expected_decoding = value.stored_value.store( pt.GetByte( encoded, start_index if start_index is not None else pt.Int(0), @@ -117,7 +117,7 @@ def test_Account_address(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.txnas, "Accounts"), ] @@ -204,7 +204,7 @@ def test_Asset_asset_id(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.txnas, "Assets"), ] @@ -298,7 +298,7 @@ def test_Application_application_id(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.txnas, "Applications"), ] diff --git a/pyteal/ast/abi/string.py b/pyteal/ast/abi/string.py index f91eb272f..ac5866cb2 100644 --- a/pyteal/ast/abi/string.py +++ b/pyteal/ast/abi/string.py @@ -68,7 +68,7 @@ def get(self) -> Expr: The expression will have the type TealType.bytes. """ return Suffix( - self._data_storage.load(), Int(Uint16TypeSpec().byte_length_static()) + self.stored_value.load(), Int(Uint16TypeSpec().byte_length_static()) ) def set( @@ -111,18 +111,18 @@ def set( if value.type_spec() == StringTypeSpec() or ( value.type_spec() == DynamicArrayTypeSpec(ByteTypeSpec()) ): - return self._data_storage.store(value._data_storage.load()) + return self.stored_value.store(value.stored_value.load()) raise TealInputError( f"Got {value} with type spec {value.type_spec()}, expected {StringTypeSpec}" ) case bytes() | bytearray(): - return self._data_storage.store(_encoded_byte_string(value)) + return self.stored_value.store(_encoded_byte_string(value)) case str(): - return self._data_storage.store(_encoded_byte_string(value.encode())) + return self.stored_value.store(_encoded_byte_string(value.encode())) case Expr(): return _store_encoded_expr_byte_string_into_var( - value, self._data_storage + value, self.stored_value ) case CollectionSequence(): return super().set(cast(Sequence[Byte], value)) diff --git a/pyteal/ast/abi/string_test.py b/pyteal/ast/abi/string_test.py index e335da1a1..c60ac52f4 100644 --- a/pyteal/ast/abi/string_test.py +++ b/pyteal/ast/abi/string_test.py @@ -44,7 +44,7 @@ def test_String_encode(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -76,7 +76,7 @@ def test_DynamicArray_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expectedExpr = value._data_storage.store( + expectedExpr = value.stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -107,7 +107,7 @@ def test_String_get(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.extract, 2, 0), ] @@ -143,7 +143,7 @@ def test_String_set_static(value_to_set, value_encoded): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -174,12 +174,12 @@ def test_String_set_expr(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.itob), @@ -187,13 +187,13 @@ def test_String_set_expr(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.concat), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -222,12 +222,12 @@ def test_String_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, + cast(pt.ScratchVar, other.stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -259,7 +259,7 @@ def test_String_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/transaction.py b/pyteal/ast/abi/transaction.py index 1f3ea9ba2..aeb5c7a33 100644 --- a/pyteal/ast/abi/transaction.py +++ b/pyteal/ast/abi/transaction.py @@ -82,16 +82,16 @@ def _set_index( case ComputedValue(): return self._set_with_computed_type(value) case BaseType(): - return self._data_storage.store(self._data_storage.load()) + return self.stored_value.store(self.stored_value.load()) case int(): - return self._data_storage.store(Int(value)) + return self.stored_value.store(Int(value)) case Expr(): - return self._data_storage.store(value) + return self.stored_value.store(value) case _: raise TealInputError(f"Cant store a {type(value)} in a Transaction") def index(self) -> Expr: - return self._data_storage.load() + return self.stored_value.load() def decode( self, diff --git a/pyteal/ast/abi/transaction_test.py b/pyteal/ast/abi/transaction_test.py index e21802950..b4c27a97c 100644 --- a/pyteal/ast/abi/transaction_test.py +++ b/pyteal/ast/abi/transaction_test.py @@ -134,7 +134,7 @@ def test_Transaction__set_index(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, tv.t._data_storage).scratchvar.slot, + cast(pt.ScratchVar, tv.t.stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/tuple.py b/pyteal/ast/abi/tuple.py index efea10e36..bc1966414 100644 --- a/pyteal/ast/abi/tuple.py +++ b/pyteal/ast/abi/tuple.py @@ -309,7 +309,7 @@ def decode( extracted = substring_for_decoding( encoded, start_index=start_index, end_index=end_index, length=length ) - return self._data_storage.store(extracted) + return self.stored_value.store(extracted) @overload def set(self, *values: BaseType) -> Expr: @@ -352,10 +352,10 @@ def set(self, *values): ) if not all(myTypes[i] == values[i].type_spec() for i in range(len(myTypes))): raise TealInputError("Input values do not match type") - return self._data_storage.store(_encode_tuple(values)) + return self.stored_value.store(_encode_tuple(values)) def encode(self) -> Expr: - return self._data_storage.load() + return self.stored_value.load() def length(self) -> Expr: """Get the number of values this tuple holds as an Expr.""" diff --git a/pyteal/ast/abi/tuple_test.py b/pyteal/ast/abi/tuple_test.py index ad231784f..a761d88af 100644 --- a/pyteal/ast/abi/tuple_test.py +++ b/pyteal/ast/abi/tuple_test.py @@ -623,7 +623,7 @@ def test_Tuple_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = tupleValue._data_storage.store( + expectedExpr = tupleValue.stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -672,9 +672,7 @@ def test_Tuple_set(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = tupleValue._data_storage.store( - _encode_tuple([uint8, uint16, uint32]) - ) + expectedExpr = tupleValue.stored_value.store(_encode_tuple([uint8, uint16, uint32])) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) @@ -706,7 +704,7 @@ def test_Tuple_set_Computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, tupleValue._data_storage).scratchvar.slot, + cast(pt.ScratchVar, tupleValue.stored_value).slot, ), ] ) @@ -737,7 +735,7 @@ def test_Tuple_encode(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, tupleValue._data_storage).scratchvar.slot, + cast(pt.ScratchVar, tupleValue.stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index 3ae5d585c..2e9027c5d 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -4,7 +4,7 @@ from pyteal.errors import TealInputError from pyteal.types import TealType from pyteal.ast.expr import Expr -from pyteal.ast.scratchvar import ScratchVar +from pyteal.ast.scratchvar import ScratchVar, AbstractVar from pyteal.ast.seq import Seq @@ -65,23 +65,6 @@ def __str__(self) -> str: TypeSpec.__module__ = "pyteal.abi" -class AbstractVar(ABC): - @abstractmethod - def store(self, value: Expr) -> Expr: - pass - - @abstractmethod - def load(self) -> Expr: - pass - - @abstractmethod - def storage_type(self) -> TealType: - pass - - -AbstractVar.__module__ = "pyteal" - - class ScratchStorage(AbstractVar): def __init__(self, storage_type: TealType) -> None: super().__init__() @@ -135,18 +118,16 @@ def __init__(self, spec: TypeSpec) -> None: """Create a new BaseType.""" super().__init__() self._type_spec: Final[TypeSpec] = spec - self._data_storage: AbstractVar = ScratchStorage(spec.storage_type()) - - # self.stored_value: Final = ScratchVar(spec.storage_type()) + self.stored_value: AbstractVar = ScratchVar(spec.storage_type()) def _set_data_source(self, storage: AbstractVar) -> None: - self._data_storage = storage + self.stored_value = storage def _load_value(self) -> Expr: - return self._data_storage.load() + return self.stored_value.load() def _store_value(self, value: Expr) -> Expr: - return self._data_storage.store(value) + return self.stored_value.store(value) def type_spec(self) -> TypeSpec: """Get the TypeSpec for this ABI type instance.""" @@ -300,7 +281,8 @@ def store_into(self, output: BaseType) -> Expr: f"ABI return subroutine deferred_expr is expected to be typed {output.type_spec().storage_type()}, " f"but has type {declaration.deferred_expr.type_of()}." ) - return output._data_storage.store(self.computation) + assert isinstance(output.stored_value, ScratchVar) + return output.stored_value.slot.store(self.computation) ReturnedValue.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/type_test.py b/pyteal/ast/abi/type_test.py index 30f39e0fc..56a9e6c76 100644 --- a/pyteal/ast/abi/type_test.py +++ b/pyteal/ast/abi/type_test.py @@ -17,7 +17,7 @@ def store_into(self, output: abi.BaseType) -> pt.Expr: raise pt.TealInputError( f"expected type_spec {self.type_spec} but get {output.type_spec()}" ) - return output._data_storage.store(self.encodings) + return output.stored_value.store(self.encodings) def test_ComputedType_use(): diff --git a/pyteal/ast/abi/uint.py b/pyteal/ast/abi/uint.py index 67d3ff428..0a99eb27f 100644 --- a/pyteal/ast/abi/uint.py +++ b/pyteal/ast/abi/uint.py @@ -239,7 +239,7 @@ def get(self) -> Expr: The expression will have the type TealType.uint64. """ - return self._data_storage.load() + return self.stored_value.load() def set(self, value: Union[int, Expr, "Uint", ComputedValue["Uint"]]) -> Expr: """Set the value of this Uint to the input value. @@ -274,7 +274,7 @@ def set(self, value: Union[int, Expr, "Uint", ComputedValue["Uint"]]) -> Expr: value.type_spec(), self.type_spec() ) ) - return uint_set(self.type_spec().bit_size(), self._data_storage, value) + return uint_set(self.type_spec().bit_size(), self.stored_value, value) def decode( self, @@ -286,7 +286,7 @@ def decode( ) -> Expr: return uint_decode( self.type_spec().bit_size(), - self._data_storage, + self.stored_value, encoded, start_index, end_index, @@ -294,7 +294,7 @@ def decode( ) def encode(self) -> Expr: - return uint_encode(self.type_spec().bit_size(), self._data_storage) + return uint_encode(self.type_spec().bit_size(), self.stored_value) Uint.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/uint_test.py b/pyteal/ast/abi/uint_test.py index d571e7aa6..26ba3541f 100644 --- a/pyteal/ast/abi/uint_test.py +++ b/pyteal/ast/abi/uint_test.py @@ -142,7 +142,7 @@ def test_Uint_set_static(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -174,7 +174,7 @@ def test_Uint_set_expr(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), pt.TealOp(None, pt.Op.int, test.maxValue + 1), pt.TealOp(None, pt.Op.lt), @@ -189,7 +189,7 @@ def test_Uint_set_expr(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] + upperBoundCheck @@ -216,12 +216,12 @@ def test_Uint_set_copy(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, + cast(pt.ScratchVar, other.stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -253,7 +253,7 @@ def test_Uint_set_computed(): pt.TealOp( None, pt.Op.store, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -281,7 +281,7 @@ def test_Uint_get(): pt.TealOp( expr, pt.Op.load, - cast(abi.ScratchStorage, value._data_storage).scratchvar.slot, + cast(pt.ScratchVar, value.stored_value).slot, ), ] ) @@ -307,7 +307,7 @@ def test_Uint_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedDecoding = value._data_storage.store( + expectedDecoding = value.stored_value.store( test.expectedDecoding(encoded, start_index, end_index, length) ) expected, _ = expectedDecoding.__teal__(options) @@ -359,14 +359,12 @@ def test_ByteUint8_mutual_conversion(): pt.TealOp( None, pt.Op.load, - cast(abi.ScratchStorage, other._data_storage).scratchvar.slot, + cast(pt.ScratchVar, other.stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast( - abi.ScratchStorage, type_b_instance._data_storage - ).scratchvar.slot, + cast(pt.ScratchVar, type_b_instance.stored_value).slot, ), ] ) diff --git a/pyteal/ast/scratchvar.py b/pyteal/ast/scratchvar.py index 81ce27fff..44d422782 100644 --- a/pyteal/ast/scratchvar.py +++ b/pyteal/ast/scratchvar.py @@ -1,3 +1,5 @@ +from abc import ABC, abstractmethod + from pyteal.errors import TealInputError from pyteal.types import TealType, require_type @@ -5,7 +7,24 @@ from pyteal.ast.scratch import ScratchSlot, ScratchLoad, ScratchStore -class ScratchVar: +class AbstractVar(ABC): + @abstractmethod + def store(self, value: Expr) -> Expr: + pass + + @abstractmethod + def load(self) -> Expr: + pass + + @abstractmethod + def storage_type(self) -> TealType: + pass + + +AbstractVar.__module__ = "pyteal" + + +class ScratchVar(AbstractVar): """ Interface around Scratch space, similar to get/put local/global state diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index d509f980b..437c9535d 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -378,7 +378,7 @@ def __init__( elif isinstance(arg, ScratchVar): arg_type = arg.type elif isinstance(arg, abi.BaseType): - arg_type = cast(abi.BaseType, arg)._data_storage.storage_type() + arg_type = cast(abi.BaseType, arg).stored_value.storage_type() else: raise TealInputError( f"Subroutine argument {arg} at index {i} was of unexpected Python type {type(arg)}" @@ -420,7 +420,7 @@ def handle_arg(arg: Expr | ScratchVar | abi.BaseType) -> Expr: elif isinstance(arg, Expr): return arg elif isinstance(arg, abi.BaseType): - return arg._data_storage.load() + return arg.stored_value.load() else: raise TealInputError( f"cannot handle current arg: {arg} to put it on stack" @@ -791,8 +791,6 @@ def evaluate_subroutine(subroutine: SubroutineDefinition) -> SubroutineDeclarati def var_n_loaded( param: str, ) -> tuple[ScratchVar, ScratchVar | abi.BaseType | Expr]: - from pyteal.ast.abi.type import ScratchStorage - loaded_var: ScratchVar | abi.BaseType | Expr argument_var: ScratchVar @@ -801,11 +799,11 @@ def var_n_loaded( loaded_var = argument_var elif param in subroutine.abi_args: internal_abi_var = subroutine.abi_args[param].new_instance() - if not isinstance(internal_abi_var._data_storage, ScratchStorage): + if not isinstance(internal_abi_var.stored_value, ScratchVar): raise TealInternalError( "subroutine ABI args must have data schema being ScratchVarStorage" ) - argument_var = internal_abi_var._data_storage.scratchvar + argument_var = internal_abi_var.stored_value loaded_var = internal_abi_var else: argument_var = ScratchVar(TealType.anytype) @@ -853,7 +851,7 @@ def var_n_loaded( f"ABI returning subroutine definition should evaluate to TealType.none, " f"while evaluate to {subroutine_body.type_of()}." ) - deferred_expr = output_carrying_abi._data_storage.load() + deferred_expr = output_carrying_abi.stored_value.load() # Arg usage "A" to be pick up and store in scratch parameters that have been placed on the stack # need to reverse order of argumentVars because the last argument will be on top of the stack From f362b57542041162a3acb477687e8812e1c529c7 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 10:51:50 -0400 Subject: [PATCH 071/157] better type checking in scratch slot --- pyteal/ast/abi/type.py | 3 +-- pyteal/ast/scratchvar.py | 9 +++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index 2e9027c5d..f9368cbda 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -281,8 +281,7 @@ def store_into(self, output: BaseType) -> Expr: f"ABI return subroutine deferred_expr is expected to be typed {output.type_spec().storage_type()}, " f"but has type {declaration.deferred_expr.type_of()}." ) - assert isinstance(output.stored_value, ScratchVar) - return output.stored_value.slot.store(self.computation) + return output.stored_value.store(self.computation) ReturnedValue.__module__ = "pyteal.abi" diff --git a/pyteal/ast/scratchvar.py b/pyteal/ast/scratchvar.py index 44d422782..7b4962f97 100644 --- a/pyteal/ast/scratchvar.py +++ b/pyteal/ast/scratchvar.py @@ -1,7 +1,7 @@ from abc import ABC, abstractmethod from pyteal.errors import TealInputError -from pyteal.types import TealType, require_type +from pyteal.types import TealType, require_type, types_match from pyteal.ast.expr import Expr from pyteal.ast.scratch import ScratchSlot, ScratchLoad, ScratchStore @@ -61,7 +61,12 @@ def store(self, value: Expr) -> Expr: Args: value: The value to store. Must conform to this ScratchVar's type. """ - require_type(value, self.type) + from pyteal.ast.subroutine import SubroutineCall + + if not isinstance(value, SubroutineCall) or not value.output_kwarg: + require_type(value, self.type) + else: + assert types_match(value.output_kwarg.abi_type.storage_type(), self.type) return self.slot.store(value) def load(self) -> ScratchLoad: From a0f1a813eb435403120b88d8b832ebe8cf55714b Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 10:55:21 -0400 Subject: [PATCH 072/157] reformat imports and class decl for FrameVar and ScratchVar --- pyteal/__init__.pyi | 1 + pyteal/ast/__init__.py | 3 ++- pyteal/ast/abi/__init__.py | 11 +--------- pyteal/ast/abi/type.py | 41 -------------------------------------- pyteal/ast/frame.py | 1 + 5 files changed, 5 insertions(+), 52 deletions(-) diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index ed1d3c1e1..baf5ae050 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -122,6 +122,7 @@ __all__ = [ "For", "FrameBury", "FrameDig", + "FrameStorage", "Ge", "GeneratedID", "GetBit", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 3d2671068..0f2bcaa34 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -155,7 +155,7 @@ from pyteal.ast.for_ import For from pyteal.ast.break_ import Break from pyteal.ast.continue_ import Continue -from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN, Bury +from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN, Bury, FrameStorage # misc from pyteal.ast.scratch import ( @@ -344,6 +344,7 @@ "Bury", "DupN", "PopN", + "FrameStorage", "Router", "CallConfig", "MethodConfig", diff --git a/pyteal/ast/abi/__init__.py b/pyteal/ast/abi/__init__.py index bb2a0d1b2..f1cb3a58c 100644 --- a/pyteal/ast/abi/__init__.py +++ b/pyteal/ast/abi/__init__.py @@ -4,14 +4,7 @@ Address, AddressLength, ) -from pyteal.ast.abi.type import ( - TypeSpec, - BaseType, - ComputedValue, - ReturnedValue, - FrameStorage, - ScratchStorage, -) +from pyteal.ast.abi.type import TypeSpec, BaseType, ComputedValue, ReturnedValue from pyteal.ast.abi.bool import BoolTypeSpec, Bool from pyteal.ast.abi.uint import ( UintTypeSpec, @@ -173,8 +166,6 @@ "type_specs_from_signature", "make", "size_of", - "FrameStorage", - "ScratchStorage", "algosdk_from_annotation", "algosdk_from_type_spec", "contains_type_spec", diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index f9368cbda..b87fe1282 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -65,47 +65,6 @@ def __str__(self) -> str: TypeSpec.__module__ = "pyteal.abi" -class ScratchStorage(AbstractVar): - def __init__(self, storage_type: TealType) -> None: - super().__init__() - self.scratchvar: Final[ScratchVar] = ScratchVar(storage_type) - - def load(self) -> Expr: - return self.scratchvar.load() - - def store(self, value: Expr) -> Expr: - return self.scratchvar.slot.store(value) - - def storage_type(self) -> TealType: - return self.scratchvar.storage_type() - - -ScratchStorage.__module__ = "pyteal" - - -class FrameStorage(AbstractVar): - def __init__(self, storage_type: TealType, stack_depth: int) -> None: - super().__init__() - self.stack_type = storage_type - self.stack_depth = stack_depth - - def storage_type(self) -> TealType: - return self.stack_type - - def store(self, value: Expr) -> Expr: - from pyteal.ast import FrameBury - - return FrameBury(value, self.stack_depth) - - def load(self) -> Expr: - from pyteal.ast import FrameDig - - return FrameDig(self.stack_depth) - - -FrameStorage.__module__ = "pyteal" - - class BaseType(ABC): """The abstract base class for all ABI type instances. diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 8f5e24891..6b94cb2a3 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -1,6 +1,7 @@ from typing import TYPE_CHECKING from pyteal.ast.expr import Expr +from pyteal.ast.scratchvar import AbstractVar from pyteal.types import TealType, require_type from pyteal.errors import TealInputError, verifyProgramVersion from pyteal.ir import TealBlock, TealSimpleBlock, TealOp, Op From 46b886b021052d2b0e34f942f65661d6d7968b0c Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 11:27:24 -0400 Subject: [PATCH 073/157] still thinking about hiding the _stored value --- pyteal/ast/abi/address.py | 12 ++++++------ pyteal/ast/abi/address_test.py | 24 ++++++++++++------------ pyteal/ast/abi/array_base.py | 6 +++--- pyteal/ast/abi/array_dynamic.py | 8 ++++---- pyteal/ast/abi/array_dynamic_test.py | 24 ++++++++++++------------ pyteal/ast/abi/array_static.py | 10 +++++----- pyteal/ast/abi/array_static_test.py | 18 +++++++++--------- pyteal/ast/abi/bool.py | 8 ++++---- pyteal/ast/abi/bool_test.py | 20 ++++++++++---------- pyteal/ast/abi/reference_type.py | 8 ++++---- pyteal/ast/abi/reference_type_test.py | 10 +++++----- pyteal/ast/abi/string.py | 10 +++++----- pyteal/ast/abi/string_test.py | 22 +++++++++++----------- pyteal/ast/abi/transaction.py | 8 ++++---- pyteal/ast/abi/transaction_test.py | 2 +- pyteal/ast/abi/tuple.py | 6 +++--- pyteal/ast/abi/tuple_test.py | 10 ++++++---- pyteal/ast/abi/type.py | 10 +++++----- pyteal/ast/abi/type_test.py | 2 +- pyteal/ast/abi/uint.py | 8 ++++---- pyteal/ast/abi/uint_test.py | 20 ++++++++++---------- pyteal/ast/subroutine.py | 10 +++++----- 22 files changed, 129 insertions(+), 127 deletions(-) diff --git a/pyteal/ast/abi/address.py b/pyteal/ast/abi/address.py index d0413cf6c..d8ad3cbc2 100644 --- a/pyteal/ast/abi/address.py +++ b/pyteal/ast/abi/address.py @@ -56,7 +56,7 @@ def get(self) -> Expr: The expression will have the type TealType.bytes. """ - return self.stored_value.load() + return self._stored_value.load() def set( self, @@ -108,25 +108,25 @@ def set( or value.type_spec() == StaticArrayTypeSpec(ByteTypeSpec(), AddressLength.Bytes) ): - return self.stored_value.store(value.stored_value.load()) + return self._stored_value.store(value._stored_value.load()) raise TealInputError( f"Got {value} with type spec {value.type_spec()}, expected AddressTypeSpec" ) case str(): # Addr throws if value is invalid address - return self.stored_value.store(Addr(value)) + return self._stored_value.store(Addr(value)) case bytes(): if len(value) == AddressLength.Bytes: - return self.stored_value.store(Bytes(value)) + return self._stored_value.store(Bytes(value)) raise TealInputError( f"Got bytes with length {len(value)}, expected {AddressLength.Bytes}" ) case Expr(): return Seq( - self.stored_value.store(value), + self._stored_value.store(value), Assert( - Len(self.stored_value.load()) == Int(AddressLength.Bytes.value) + Len(self._stored_value.load()) == Int(AddressLength.Bytes.value) ), ) case CollectionSequence(): diff --git a/pyteal/ast/abi/address_test.py b/pyteal/ast/abi/address_test.py index d115082cd..c70cbe5ea 100644 --- a/pyteal/ast/abi/address_test.py +++ b/pyteal/ast/abi/address_test.py @@ -53,7 +53,7 @@ def test_Address_encode(): pt.TealOp( expr, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -86,7 +86,7 @@ def test_Address_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expectedExpr = value.stored_value.store( + expectedExpr = value._stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -117,7 +117,7 @@ def test_Address_get(): pt.TealOp( expr, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -139,12 +139,12 @@ def test_Address_set_StaticArray(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value_to_set.stored_value).slot, + cast(pt.ScratchVar, value_to_set._stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -174,7 +174,7 @@ def test_Address_set_str(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -203,7 +203,7 @@ def test_Address_set_bytes(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -236,12 +236,12 @@ def test_Address_set_expr(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.int, AddressLength.Bytes.value), @@ -270,12 +270,12 @@ def test_Address_set_copy(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, other.stored_value).slot, + cast(pt.ScratchVar, other._stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -307,7 +307,7 @@ def test_Address_set_computed(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/array_base.py b/pyteal/ast/abi/array_base.py index aea164c81..8920637bc 100644 --- a/pyteal/ast/abi/array_base.py +++ b/pyteal/ast/abi/array_base.py @@ -104,7 +104,7 @@ def decode( extracted = substring_for_decoding( encoded, start_index=start_index, end_index=end_index, length=length ) - return self.stored_value.store(extracted) + return self._stored_value.store(extracted) def set(self, values: Sequence[T]) -> Expr: """Set the ABI array with a sequence of ABI type variables. @@ -142,7 +142,7 @@ def set(self, values: Sequence[T]) -> Expr: length_prefix = Seq(length_tmp.set(len(values)), length_tmp.encode()) encoded = Concat(length_prefix, encoded) - return self.stored_value.store(encoded) + return self._stored_value.store(encoded) def encode(self) -> Expr: """Encode the ABI array to be a byte string. @@ -150,7 +150,7 @@ def encode(self) -> Expr: Returns: A PyTeal expression that encodes this ABI array to a byte string. """ - return self.stored_value.load() + return self._stored_value.load() @abstractmethod def length(self) -> Expr: diff --git a/pyteal/ast/abi/array_dynamic.py b/pyteal/ast/abi/array_dynamic.py index 9d53e0559..ecbeeb49c 100644 --- a/pyteal/ast/abi/array_dynamic.py +++ b/pyteal/ast/abi/array_dynamic.py @@ -79,7 +79,7 @@ def set( raise TealInputError( f"Cannot assign type {values.type_spec()} to {self.type_spec()}" ) - return self.stored_value.store(values.encode()) + return self._stored_value.store(values.encode()) return super().set(values) def length(self) -> Expr: @@ -165,10 +165,10 @@ def set( match values: case bytes() | bytearray(): - return self.stored_value.store(_encoded_byte_string(values)) + return self._stored_value.store(_encoded_byte_string(values)) case Expr(): return _store_encoded_expr_byte_string_into_var( - values, self.stored_value + values, self._stored_value ) return super().set(values) @@ -181,7 +181,7 @@ def get(self) -> Expr: Returns: A Pyteal expression that loads byte encoding of this DynamicBytes, and drop the first uint16 DynamicArray length encoding. """ - return Suffix(self.stored_value.load(), Int(2)) + return Suffix(self._stored_value.load(), Int(2)) DynamicBytes.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/array_dynamic_test.py b/pyteal/ast/abi/array_dynamic_test.py index e8e930787..91497500a 100644 --- a/pyteal/ast/abi/array_dynamic_test.py +++ b/pyteal/ast/abi/array_dynamic_test.py @@ -106,7 +106,7 @@ def test_DynamicArray_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value.stored_value.store( + expectedExpr = value._stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -141,7 +141,7 @@ def test_DynamicArray_set_values(): assert not expr.has_return() length_tmp = abi.Uint16() - expectedExpr = value.stored_value.store( + expectedExpr = value._stored_value.store( pt.Concat( pt.Seq(length_tmp.set(len(values)), length_tmp.encode()), _encode_tuple(values), @@ -185,12 +185,12 @@ def test_DynamicArray_set_copy(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, otherArray.stored_value).slot, + cast(pt.ScratchVar, otherArray._stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -218,7 +218,7 @@ def test_DynamicArray_set_computed(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -268,7 +268,7 @@ def test_DynamicBytes_set_py_bytes(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -299,12 +299,12 @@ def test_DynamicBytes_set_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.itob), @@ -312,13 +312,13 @@ def test_DynamicBytes_set_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.concat), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -343,7 +343,7 @@ def test_DynamicBytes_get(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.extract, 2, 0), ] @@ -365,7 +365,7 @@ def test_DynamicArray_encode(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/array_static.py b/pyteal/ast/abi/array_static.py index 7744a6edb..3d9d56557 100644 --- a/pyteal/ast/abi/array_static.py +++ b/pyteal/ast/abi/array_static.py @@ -109,7 +109,7 @@ def set( raise TealInputError( f"Cannot assign type {values.type_spec()} to {self.type_spec()}" ) - return self.stored_value.store(values.encode()) + return self._stored_value.store(values.encode()) if self.type_spec().length_static() != len(values): raise TealInputError( @@ -207,11 +207,11 @@ def set( raise TealInputError( f"Got bytes with length {len(values)}, expect {self.type_spec().length_static()}" ) - return self.stored_value.store(Bytes(values)) + return self._stored_value.store(Bytes(values)) case Expr(): return Seq( - self.stored_value.store(values), - Assert(self.length() == Len(self.stored_value.load())), + self._stored_value.store(values), + Assert(self.length() == Len(self._stored_value.load())), ) return super().set(values) @@ -222,7 +222,7 @@ def get(self) -> Expr: Returns: A Pyteal expression that loads byte encoding of this StaticBytes. """ - return self.stored_value.load() + return self._stored_value.load() StaticBytes.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/array_static_test.py b/pyteal/ast/abi/array_static_test.py index 7c2e914ec..7a61e2b65 100644 --- a/pyteal/ast/abi/array_static_test.py +++ b/pyteal/ast/abi/array_static_test.py @@ -159,7 +159,7 @@ def test_StaticArray_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value.stored_value.store( + expectedExpr = value._stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -202,7 +202,7 @@ def test_StaticArray_set_values(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = value.stored_value.store(_encode_tuple(values)) + expectedExpr = value._stored_value.store(_encode_tuple(values)) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) @@ -237,12 +237,12 @@ def test_StaticArray_set_copy(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, otherArray.stored_value).slot, + cast(pt.ScratchVar, otherArray._stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -270,7 +270,7 @@ def test_StaticArray_set_computed(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -317,7 +317,7 @@ def test_StaticBytes_set_py_bytes(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -352,13 +352,13 @@ def test_StaticBytes_expr(test_case: bytes | bytearray): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.int, 32), pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.eq), @@ -381,7 +381,7 @@ def test_StaticArray_encode(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/bool.py b/pyteal/ast/abi/bool.py index 13552b6db..6fa6d72a3 100644 --- a/pyteal/ast/abi/bool.py +++ b/pyteal/ast/abi/bool.py @@ -50,7 +50,7 @@ def get(self) -> Expr: expression that evaluates to 0 will be returned. In either case, the expression will have the type TealType.uint64. """ - return self.stored_value.load() + return self._stored_value.load() def set(self, value: Union[bool, Expr, "Bool", ComputedValue["Bool"]]) -> Expr: """Set the value of this Bool to the input value. @@ -85,10 +85,10 @@ def set(self, value: Union[bool, Expr, "Bool", ComputedValue["Bool"]]) -> Expr: checked = True if checked: - return self.stored_value.store(value) + return self._stored_value.store(value) # Not(Not(value)) coerces all values greater than 0 to 1 - return self.stored_value.store(Not(Not(value))) + return self._stored_value.store(Not(Not(value))) def decode( self, @@ -103,7 +103,7 @@ def decode( return self.decode_bit(encoded, start_index * Int(NUM_BITS_IN_BYTE)) def decode_bit(self, encoded, bit_index: Expr) -> Expr: - return self.stored_value.store(GetBit(encoded, bit_index)) + return self._stored_value.store(GetBit(encoded, bit_index)) def encode(self) -> Expr: return SetBit(Bytes(b"\x00"), Int(0), self.get()) diff --git a/pyteal/ast/abi/bool_test.py b/pyteal/ast/abi/bool_test.py index 1cf881d55..7dfb5c684 100644 --- a/pyteal/ast/abi/bool_test.py +++ b/pyteal/ast/abi/bool_test.py @@ -56,7 +56,7 @@ def test_Bool_set_static(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -85,7 +85,7 @@ def test_Bool_set_expr(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -110,12 +110,12 @@ def test_Bool_set_copy(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, other.stored_value).slot, + cast(pt.ScratchVar, other._stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -144,7 +144,7 @@ def test_Bool_set_computed(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -171,7 +171,7 @@ def test_Bool_get(): pt.TealOp( expr, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -203,7 +203,7 @@ def test_Bool_decode(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -232,7 +232,7 @@ def test_Bool_decode_bit(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -258,7 +258,7 @@ def test_Bool_encode(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.setbit), ] @@ -442,7 +442,7 @@ class EncodeSeqTest(NamedTuple): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, testType.stored_value).slot, + cast(pt.ScratchVar, testType._stored_value).slot, ), pt.TealOp(None, pt.Op.setbit), ] diff --git a/pyteal/ast/abi/reference_type.py b/pyteal/ast/abi/reference_type.py index f4882fc97..e1a228245 100644 --- a/pyteal/ast/abi/reference_type.py +++ b/pyteal/ast/abi/reference_type.py @@ -58,7 +58,7 @@ def referenced_index(self) -> Expr: If this reference type is an application or asset, note that this DOES NOT return the application or asset ID. See :code:`application_id()` or :code:`asset_id()` for that. """ - return self.stored_value.load() + return self._stored_value.load() def decode( self, @@ -70,7 +70,7 @@ def decode( ) -> Expr: return uint_decode( self.type_spec().bit_size(), - self.stored_value, + self._stored_value, encoded, start_index, end_index, @@ -107,7 +107,7 @@ def __init__(self) -> None: def address(self) -> Expr: """Get the address of the account.""" - return Txn.accounts[self.stored_value.load()] + return Txn.accounts[self._stored_value.load()] def params(self) -> AccountParamObject: """Get information about the account.""" @@ -205,7 +205,7 @@ def __init__(self) -> None: def application_id(self) -> Expr: """Get the ID of the application.""" - return Txn.applications[self.stored_value.load()] + return Txn.applications[self._stored_value.load()] def params(self) -> AppParamObject: """Get information about the application's parameters.""" diff --git a/pyteal/ast/abi/reference_type_test.py b/pyteal/ast/abi/reference_type_test.py index 4ec862e66..cbbc45d34 100644 --- a/pyteal/ast/abi/reference_type_test.py +++ b/pyteal/ast/abi/reference_type_test.py @@ -26,7 +26,7 @@ def test_ReferenceType_referenced_index(): pt.TealOp( expr, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -61,7 +61,7 @@ def test_ReferenceType_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expected_decoding = value.stored_value.store( + expected_decoding = value._stored_value.store( pt.GetByte( encoded, start_index if start_index is not None else pt.Int(0), @@ -117,7 +117,7 @@ def test_Account_address(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.txnas, "Accounts"), ] @@ -204,7 +204,7 @@ def test_Asset_asset_id(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.txnas, "Assets"), ] @@ -298,7 +298,7 @@ def test_Application_application_id(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.txnas, "Applications"), ] diff --git a/pyteal/ast/abi/string.py b/pyteal/ast/abi/string.py index ac5866cb2..f142eaa55 100644 --- a/pyteal/ast/abi/string.py +++ b/pyteal/ast/abi/string.py @@ -68,7 +68,7 @@ def get(self) -> Expr: The expression will have the type TealType.bytes. """ return Suffix( - self.stored_value.load(), Int(Uint16TypeSpec().byte_length_static()) + self._stored_value.load(), Int(Uint16TypeSpec().byte_length_static()) ) def set( @@ -111,18 +111,18 @@ def set( if value.type_spec() == StringTypeSpec() or ( value.type_spec() == DynamicArrayTypeSpec(ByteTypeSpec()) ): - return self.stored_value.store(value.stored_value.load()) + return self._stored_value.store(value._stored_value.load()) raise TealInputError( f"Got {value} with type spec {value.type_spec()}, expected {StringTypeSpec}" ) case bytes() | bytearray(): - return self.stored_value.store(_encoded_byte_string(value)) + return self._stored_value.store(_encoded_byte_string(value)) case str(): - return self.stored_value.store(_encoded_byte_string(value.encode())) + return self._stored_value.store(_encoded_byte_string(value.encode())) case Expr(): return _store_encoded_expr_byte_string_into_var( - value, self.stored_value + value, self._stored_value ) case CollectionSequence(): return super().set(cast(Sequence[Byte], value)) diff --git a/pyteal/ast/abi/string_test.py b/pyteal/ast/abi/string_test.py index c60ac52f4..9ebcbfadd 100644 --- a/pyteal/ast/abi/string_test.py +++ b/pyteal/ast/abi/string_test.py @@ -44,7 +44,7 @@ def test_String_encode(): pt.TealOp( expr, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -76,7 +76,7 @@ def test_DynamicArray_decode(): assert expr.type_of() == pt.TealType.none assert expr.has_return() is False - expectedExpr = value.stored_value.store( + expectedExpr = value._stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -107,7 +107,7 @@ def test_String_get(): pt.TealOp( expr, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.extract, 2, 0), ] @@ -143,7 +143,7 @@ def test_String_set_static(value_to_set, value_encoded): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -174,12 +174,12 @@ def test_String_set_expr(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.len), pt.TealOp(None, pt.Op.itob), @@ -187,13 +187,13 @@ def test_String_set_expr(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.concat), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -222,12 +222,12 @@ def test_String_set_copy(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, other.stored_value).slot, + cast(pt.ScratchVar, other._stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -259,7 +259,7 @@ def test_String_set_computed(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/transaction.py b/pyteal/ast/abi/transaction.py index aeb5c7a33..69de7ea29 100644 --- a/pyteal/ast/abi/transaction.py +++ b/pyteal/ast/abi/transaction.py @@ -82,16 +82,16 @@ def _set_index( case ComputedValue(): return self._set_with_computed_type(value) case BaseType(): - return self.stored_value.store(self.stored_value.load()) + return self._stored_value.store(self._stored_value.load()) case int(): - return self.stored_value.store(Int(value)) + return self._stored_value.store(Int(value)) case Expr(): - return self.stored_value.store(value) + return self._stored_value.store(value) case _: raise TealInputError(f"Cant store a {type(value)} in a Transaction") def index(self) -> Expr: - return self.stored_value.load() + return self._stored_value.load() def decode( self, diff --git a/pyteal/ast/abi/transaction_test.py b/pyteal/ast/abi/transaction_test.py index b4c27a97c..3b0cdeae1 100644 --- a/pyteal/ast/abi/transaction_test.py +++ b/pyteal/ast/abi/transaction_test.py @@ -134,7 +134,7 @@ def test_Transaction__set_index(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, tv.t.stored_value).slot, + cast(pt.ScratchVar, tv.t._stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/tuple.py b/pyteal/ast/abi/tuple.py index bc1966414..3149250a6 100644 --- a/pyteal/ast/abi/tuple.py +++ b/pyteal/ast/abi/tuple.py @@ -309,7 +309,7 @@ def decode( extracted = substring_for_decoding( encoded, start_index=start_index, end_index=end_index, length=length ) - return self.stored_value.store(extracted) + return self._stored_value.store(extracted) @overload def set(self, *values: BaseType) -> Expr: @@ -352,10 +352,10 @@ def set(self, *values): ) if not all(myTypes[i] == values[i].type_spec() for i in range(len(myTypes))): raise TealInputError("Input values do not match type") - return self.stored_value.store(_encode_tuple(values)) + return self._stored_value.store(_encode_tuple(values)) def encode(self) -> Expr: - return self.stored_value.load() + return self._stored_value.load() def length(self) -> Expr: """Get the number of values this tuple holds as an Expr.""" diff --git a/pyteal/ast/abi/tuple_test.py b/pyteal/ast/abi/tuple_test.py index a761d88af..b175ce7bd 100644 --- a/pyteal/ast/abi/tuple_test.py +++ b/pyteal/ast/abi/tuple_test.py @@ -623,7 +623,7 @@ def test_Tuple_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = tupleValue.stored_value.store( + expectedExpr = tupleValue._stored_value.store( substring_for_decoding( encoded, start_index=start_index, @@ -672,7 +672,9 @@ def test_Tuple_set(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedExpr = tupleValue.stored_value.store(_encode_tuple([uint8, uint16, uint32])) + expectedExpr = tupleValue._stored_value.store( + _encode_tuple([uint8, uint16, uint32]) + ) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) @@ -704,7 +706,7 @@ def test_Tuple_set_Computed(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, tupleValue.stored_value).slot, + cast(pt.ScratchVar, tupleValue._stored_value).slot, ), ] ) @@ -735,7 +737,7 @@ def test_Tuple_encode(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, tupleValue.stored_value).slot, + cast(pt.ScratchVar, tupleValue._stored_value).slot, ), ] ) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index b87fe1282..adb76ecf3 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -77,16 +77,16 @@ def __init__(self, spec: TypeSpec) -> None: """Create a new BaseType.""" super().__init__() self._type_spec: Final[TypeSpec] = spec - self.stored_value: AbstractVar = ScratchVar(spec.storage_type()) + self._stored_value: AbstractVar = ScratchVar(spec.storage_type()) def _set_data_source(self, storage: AbstractVar) -> None: - self.stored_value = storage + self._stored_value = storage def _load_value(self) -> Expr: - return self.stored_value.load() + return self._stored_value.load() def _store_value(self, value: Expr) -> Expr: - return self.stored_value.store(value) + return self._stored_value.store(value) def type_spec(self) -> TypeSpec: """Get the TypeSpec for this ABI type instance.""" @@ -240,7 +240,7 @@ def store_into(self, output: BaseType) -> Expr: f"ABI return subroutine deferred_expr is expected to be typed {output.type_spec().storage_type()}, " f"but has type {declaration.deferred_expr.type_of()}." ) - return output.stored_value.store(self.computation) + return output._stored_value.store(self.computation) ReturnedValue.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/type_test.py b/pyteal/ast/abi/type_test.py index 56a9e6c76..568ebf94c 100644 --- a/pyteal/ast/abi/type_test.py +++ b/pyteal/ast/abi/type_test.py @@ -17,7 +17,7 @@ def store_into(self, output: abi.BaseType) -> pt.Expr: raise pt.TealInputError( f"expected type_spec {self.type_spec} but get {output.type_spec()}" ) - return output.stored_value.store(self.encodings) + return output._stored_value.store(self.encodings) def test_ComputedType_use(): diff --git a/pyteal/ast/abi/uint.py b/pyteal/ast/abi/uint.py index 0a99eb27f..c3f7c7f98 100644 --- a/pyteal/ast/abi/uint.py +++ b/pyteal/ast/abi/uint.py @@ -239,7 +239,7 @@ def get(self) -> Expr: The expression will have the type TealType.uint64. """ - return self.stored_value.load() + return self._stored_value.load() def set(self, value: Union[int, Expr, "Uint", ComputedValue["Uint"]]) -> Expr: """Set the value of this Uint to the input value. @@ -274,7 +274,7 @@ def set(self, value: Union[int, Expr, "Uint", ComputedValue["Uint"]]) -> Expr: value.type_spec(), self.type_spec() ) ) - return uint_set(self.type_spec().bit_size(), self.stored_value, value) + return uint_set(self.type_spec().bit_size(), self._stored_value, value) def decode( self, @@ -286,7 +286,7 @@ def decode( ) -> Expr: return uint_decode( self.type_spec().bit_size(), - self.stored_value, + self._stored_value, encoded, start_index, end_index, @@ -294,7 +294,7 @@ def decode( ) def encode(self) -> Expr: - return uint_encode(self.type_spec().bit_size(), self.stored_value) + return uint_encode(self.type_spec().bit_size(), self._stored_value) Uint.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abi/uint_test.py b/pyteal/ast/abi/uint_test.py index 26ba3541f..b9a74b64d 100644 --- a/pyteal/ast/abi/uint_test.py +++ b/pyteal/ast/abi/uint_test.py @@ -142,7 +142,7 @@ def test_Uint_set_static(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -174,7 +174,7 @@ def test_Uint_set_expr(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), pt.TealOp(None, pt.Op.int, test.maxValue + 1), pt.TealOp(None, pt.Op.lt), @@ -189,7 +189,7 @@ def test_Uint_set_expr(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] + upperBoundCheck @@ -216,12 +216,12 @@ def test_Uint_set_copy(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, other.stored_value).slot, + cast(pt.ScratchVar, other._stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -253,7 +253,7 @@ def test_Uint_set_computed(): pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -281,7 +281,7 @@ def test_Uint_get(): pt.TealOp( expr, pt.Op.load, - cast(pt.ScratchVar, value.stored_value).slot, + cast(pt.ScratchVar, value._stored_value).slot, ), ] ) @@ -307,7 +307,7 @@ def test_Uint_decode(): assert expr.type_of() == pt.TealType.none assert not expr.has_return() - expectedDecoding = value.stored_value.store( + expectedDecoding = value._stored_value.store( test.expectedDecoding(encoded, start_index, end_index, length) ) expected, _ = expectedDecoding.__teal__(options) @@ -359,12 +359,12 @@ def test_ByteUint8_mutual_conversion(): pt.TealOp( None, pt.Op.load, - cast(pt.ScratchVar, other.stored_value).slot, + cast(pt.ScratchVar, other._stored_value).slot, ), pt.TealOp( None, pt.Op.store, - cast(pt.ScratchVar, type_b_instance.stored_value).slot, + cast(pt.ScratchVar, type_b_instance._stored_value).slot, ), ] ) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 437c9535d..f3bf83a2c 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -378,7 +378,7 @@ def __init__( elif isinstance(arg, ScratchVar): arg_type = arg.type elif isinstance(arg, abi.BaseType): - arg_type = cast(abi.BaseType, arg).stored_value.storage_type() + arg_type = cast(abi.BaseType, arg)._stored_value.storage_type() else: raise TealInputError( f"Subroutine argument {arg} at index {i} was of unexpected Python type {type(arg)}" @@ -420,7 +420,7 @@ def handle_arg(arg: Expr | ScratchVar | abi.BaseType) -> Expr: elif isinstance(arg, Expr): return arg elif isinstance(arg, abi.BaseType): - return arg.stored_value.load() + return arg._stored_value.load() else: raise TealInputError( f"cannot handle current arg: {arg} to put it on stack" @@ -799,11 +799,11 @@ def var_n_loaded( loaded_var = argument_var elif param in subroutine.abi_args: internal_abi_var = subroutine.abi_args[param].new_instance() - if not isinstance(internal_abi_var.stored_value, ScratchVar): + if not isinstance(internal_abi_var._stored_value, ScratchVar): raise TealInternalError( "subroutine ABI args must have data schema being ScratchVarStorage" ) - argument_var = internal_abi_var.stored_value + argument_var = internal_abi_var._stored_value loaded_var = internal_abi_var else: argument_var = ScratchVar(TealType.anytype) @@ -851,7 +851,7 @@ def var_n_loaded( f"ABI returning subroutine definition should evaluate to TealType.none, " f"while evaluate to {subroutine_body.type_of()}." ) - deferred_expr = output_carrying_abi.stored_value.load() + deferred_expr = output_carrying_abi._stored_value.load() # Arg usage "A" to be pick up and store in scratch parameters that have been placed on the stack # need to reverse order of argumentVars because the last argument will be on top of the stack From 0d5eaf3410685f214ad9fe228a47a0d7afff1eab Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 12:06:10 -0400 Subject: [PATCH 074/157] per pr comment, rename to FrameVar --- pyteal/__init__.pyi | 2 +- pyteal/ast/__init__.py | 4 ++-- pyteal/ast/frame.py | 23 +++++++++++++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index baf5ae050..2e03200b2 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -122,7 +122,7 @@ __all__ = [ "For", "FrameBury", "FrameDig", - "FrameStorage", + "FrameVar", "Ge", "GeneratedID", "GetBit", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 0f2bcaa34..f4ebd5f88 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -155,7 +155,7 @@ from pyteal.ast.for_ import For from pyteal.ast.break_ import Break from pyteal.ast.continue_ import Continue -from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN, Bury, FrameStorage +from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN, Bury, FrameVar # misc from pyteal.ast.scratch import ( @@ -344,7 +344,7 @@ "Bury", "DupN", "PopN", - "FrameStorage", + "FrameVar", "Router", "CallConfig", "MethodConfig", diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 6b94cb2a3..c8fb29d53 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -102,6 +102,29 @@ def has_return(self) -> bool: FrameBury.__module__ = "pyteal" +class FrameVar(AbstractVar): + def __init__(self, storage_type: TealType, stack_depth: int) -> None: + super().__init__() + self.stack_type = storage_type + self.stack_depth = stack_depth + + def storage_type(self) -> TealType: + return self.stack_type + + def store(self, value: Expr) -> Expr: + from pyteal.ast import FrameBury + + return FrameBury(value, self.stack_depth) + + def load(self) -> Expr: + from pyteal.ast import FrameDig + + return FrameDig(self.stack_depth) + + +FrameVar.__module__ = "pyteal" + + class DupN(Expr): def __init__(self, value: Expr, repetition: int): super().__init__() From d02d73b888105c62e5194450d36f19db6166a564 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 12:11:45 -0400 Subject: [PATCH 075/157] take bury out --- pyteal/__init__.pyi | 2 -- pyteal/ast/__init__.py | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 2e03200b2..56c22a572 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -72,7 +72,6 @@ __all__ = [ "BoxReplace", "Break", "Btoi", - "Bury", "Bytes", "BytesAdd", "BytesAnd", @@ -181,7 +180,6 @@ __all__ = [ "OptimizeOptions", "Or", "Pop", - "PopN", "Pragma", "Proto", "RETURN_HASH_PREFIX", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index f4ebd5f88..1721ce522 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -155,7 +155,7 @@ from pyteal.ast.for_ import For from pyteal.ast.break_ import Break from pyteal.ast.continue_ import Continue -from pyteal.ast.frame import Proto, FrameDig, FrameBury, PopN, DupN, Bury, FrameVar +from pyteal.ast.frame import Proto, FrameDig, FrameBury, DupN, FrameVar # misc from pyteal.ast.scratch import ( @@ -341,9 +341,7 @@ "Proto", "FrameDig", "FrameBury", - "Bury", "DupN", - "PopN", "FrameVar", "Router", "CallConfig", From 25a98a494523cbd2efbe47f3ddf873b50724b845 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 12:53:59 -0400 Subject: [PATCH 076/157] abstractvar.py --- pyteal/ast/__init__.py | 3 ++- pyteal/ast/abstractvar.py | 20 ++++++++++++++++++++ pyteal/ast/scratchvar.py | 20 +------------------- 3 files changed, 23 insertions(+), 20 deletions(-) create mode 100644 pyteal/ast/abstractvar.py diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 1721ce522..7de5e044a 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -165,7 +165,8 @@ ScratchStackStore, ScratchStore, ) -from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar, AbstractVar +from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar +from pyteal.ast.abstractvar import AbstractVar from pyteal.ast.maybe import MaybeValue from pyteal.ast.multi import MultiValue from pyteal.ast.opup import OpUp, OpUpMode, OpUpFeeSource diff --git a/pyteal/ast/abstractvar.py b/pyteal/ast/abstractvar.py new file mode 100644 index 000000000..59788e001 --- /dev/null +++ b/pyteal/ast/abstractvar.py @@ -0,0 +1,20 @@ +from abc import ABC, abstractmethod +from pyteal.types import TealType +from pyteal.ast.expr import Expr + + +class AbstractVar(ABC): + @abstractmethod + def store(self, value: Expr) -> Expr: + pass + + @abstractmethod + def load(self) -> Expr: + pass + + @abstractmethod + def storage_type(self) -> TealType: + pass + + +AbstractVar.__module__ = "pyteal" diff --git a/pyteal/ast/scratchvar.py b/pyteal/ast/scratchvar.py index 7b4962f97..e97b5d1ef 100644 --- a/pyteal/ast/scratchvar.py +++ b/pyteal/ast/scratchvar.py @@ -1,29 +1,11 @@ -from abc import ABC, abstractmethod - from pyteal.errors import TealInputError from pyteal.types import TealType, require_type, types_match +from pyteal.ast.abstractvar import AbstractVar from pyteal.ast.expr import Expr from pyteal.ast.scratch import ScratchSlot, ScratchLoad, ScratchStore -class AbstractVar(ABC): - @abstractmethod - def store(self, value: Expr) -> Expr: - pass - - @abstractmethod - def load(self) -> Expr: - pass - - @abstractmethod - def storage_type(self) -> TealType: - pass - - -AbstractVar.__module__ = "pyteal" - - class ScratchVar(AbstractVar): """ Interface around Scratch space, similar to get/put local/global state From 2704c5a478318bccfeb0ede4a9059476597935f1 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 14:00:46 -0400 Subject: [PATCH 077/157] unexport FrameVar and AbstractVar --- pyteal/__init__.pyi | 2 -- pyteal/ast/__init__.py | 5 +---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 56c22a572..19dcc01fb 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -35,7 +35,6 @@ from pyteal.config import ( __all__ = [ "ABIReturnSubroutine", - "AbstractVar", "AccountParam", "AccountParamObject", "Add", @@ -121,7 +120,6 @@ __all__ = [ "For", "FrameBury", "FrameDig", - "FrameVar", "Ge", "GeneratedID", "GetBit", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 7de5e044a..4a0b4e181 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -155,7 +155,7 @@ from pyteal.ast.for_ import For from pyteal.ast.break_ import Break from pyteal.ast.continue_ import Continue -from pyteal.ast.frame import Proto, FrameDig, FrameBury, DupN, FrameVar +from pyteal.ast.frame import Proto, FrameDig, FrameBury, DupN # misc from pyteal.ast.scratch import ( @@ -166,7 +166,6 @@ ScratchStore, ) from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar -from pyteal.ast.abstractvar import AbstractVar from pyteal.ast.maybe import MaybeValue from pyteal.ast.multi import MultiValue from pyteal.ast.opup import OpUp, OpUpMode, OpUpFeeSource @@ -306,7 +305,6 @@ "ScratchStore", "DynamicScratchVar", "ScratchVar", - "AbstractVar", "MaybeValue", "MultiValue", "OpUp", @@ -343,7 +341,6 @@ "FrameDig", "FrameBury", "DupN", - "FrameVar", "Router", "CallConfig", "MethodConfig", From 92c46f0d0e74ffacf7754aa93dd8c2f4dbc1405f Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 14:04:58 -0400 Subject: [PATCH 078/157] unexport use of frame ops --- pyteal/__init__.pyi | 4 ---- pyteal/ast/__init__.py | 5 ----- 2 files changed, 9 deletions(-) diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 19dcc01fb..3f69e10bd 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -99,7 +99,6 @@ __all__ = [ "DEFAULT_TEAL_VERSION", "Div", "Divw", - "DupN", "DynamicScratchVar", "EcdsaCurve", "EcdsaDecompress", @@ -118,8 +117,6 @@ __all__ = [ "ExtractUint64", "FRAME_POINTER_VERSION", "For", - "FrameBury", - "FrameDig", "Ge", "GeneratedID", "GetBit", @@ -179,7 +176,6 @@ __all__ = [ "Or", "Pop", "Pragma", - "Proto", "RETURN_HASH_PREFIX", "Reject", "Replace", diff --git a/pyteal/ast/__init__.py b/pyteal/ast/__init__.py index 4a0b4e181..9efe807c5 100644 --- a/pyteal/ast/__init__.py +++ b/pyteal/ast/__init__.py @@ -155,7 +155,6 @@ from pyteal.ast.for_ import For from pyteal.ast.break_ import Break from pyteal.ast.continue_ import Continue -from pyteal.ast.frame import Proto, FrameDig, FrameBury, DupN # misc from pyteal.ast.scratch import ( @@ -337,10 +336,6 @@ "For", "Break", "Continue", - "Proto", - "FrameDig", - "FrameBury", - "DupN", "Router", "CallConfig", "MethodConfig", From 5e256f80f29ca8bfb58bf2c2fe485916b527c7ba Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 14:49:48 -0400 Subject: [PATCH 079/157] remove _set_data_storage --- pyteal/ast/abi/type.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index adb76ecf3..24f396cf3 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -79,9 +79,6 @@ def __init__(self, spec: TypeSpec) -> None: self._type_spec: Final[TypeSpec] = spec self._stored_value: AbstractVar = ScratchVar(spec.storage_type()) - def _set_data_source(self, storage: AbstractVar) -> None: - self._stored_value = storage - def _load_value(self) -> Expr: return self._stored_value.load() From 296f6cf3c12ab136fc677173289555cef838a714 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 15:19:04 -0400 Subject: [PATCH 080/157] rename from stack_depth to frame_index --- pyteal/ast/frame.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index c8fb29d53..9ddcf237a 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -103,23 +103,19 @@ def has_return(self) -> bool: class FrameVar(AbstractVar): - def __init__(self, storage_type: TealType, stack_depth: int) -> None: + def __init__(self, storage_type: TealType, frame_index: int) -> None: super().__init__() self.stack_type = storage_type - self.stack_depth = stack_depth + self.frame_index = frame_index def storage_type(self) -> TealType: return self.stack_type def store(self, value: Expr) -> Expr: - from pyteal.ast import FrameBury - - return FrameBury(value, self.stack_depth) + return FrameBury(value, self.frame_index) def load(self) -> Expr: - from pyteal.ast import FrameDig - - return FrameDig(self.stack_depth) + return FrameDig(self.frame_index) FrameVar.__module__ = "pyteal" From bca1868e71ae5472691762bfed432ac179d902fc Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 17:28:29 -0400 Subject: [PATCH 081/157] hide FRAME_POINTER_VERISON --- pyteal/__init__.py | 2 -- pyteal/__init__.pyi | 2 -- pyteal/compiler/__init__.py | 2 -- 3 files changed, 6 deletions(-) diff --git a/pyteal/__init__.py b/pyteal/__init__.py index ba6e8eead..ac28dd641 100644 --- a/pyteal/__init__.py +++ b/pyteal/__init__.py @@ -8,7 +8,6 @@ MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, - FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -39,7 +38,6 @@ "MIN_TEAL_VERSION", "DEFAULT_TEAL_VERSION", "MAX_PROGRAM_VERSION", - "FRAME_POINTER_VERSION", "MIN_PROGRAM_VERSION", "DEFAULT_PROGRAM_VERSION", "CompileOptions", diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 3f69e10bd..ce347b0eb 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -11,7 +11,6 @@ from pyteal.compiler import ( MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, - FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -115,7 +114,6 @@ __all__ = [ "ExtractUint16", "ExtractUint32", "ExtractUint64", - "FRAME_POINTER_VERSION", "For", "Ge", "GeneratedID", diff --git a/pyteal/compiler/__init__.py b/pyteal/compiler/__init__.py index 9755ead4f..e0d29450d 100644 --- a/pyteal/compiler/__init__.py +++ b/pyteal/compiler/__init__.py @@ -3,7 +3,6 @@ MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, - FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -17,7 +16,6 @@ "MIN_TEAL_VERSION", "DEFAULT_TEAL_VERSION", "MAX_PROGRAM_VERSION", - "FRAME_POINTER_VERSION", "MIN_PROGRAM_VERSION", "DEFAULT_PROGRAM_VERSION", "CompileOptions", From 40ebb8cc0df151a4829be275fee5436c2cad85a5 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 2 Nov 2022 17:37:42 -0400 Subject: [PATCH 082/157] hide FRAME_POINTER_VERISON --- pyteal/__init__.py | 2 -- pyteal/__init__.pyi | 2 -- pyteal/compiler/__init__.py | 2 -- 3 files changed, 6 deletions(-) diff --git a/pyteal/__init__.py b/pyteal/__init__.py index ba6e8eead..ac28dd641 100644 --- a/pyteal/__init__.py +++ b/pyteal/__init__.py @@ -8,7 +8,6 @@ MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, - FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -39,7 +38,6 @@ "MIN_TEAL_VERSION", "DEFAULT_TEAL_VERSION", "MAX_PROGRAM_VERSION", - "FRAME_POINTER_VERSION", "MIN_PROGRAM_VERSION", "DEFAULT_PROGRAM_VERSION", "CompileOptions", diff --git a/pyteal/__init__.pyi b/pyteal/__init__.pyi index 3f69e10bd..ce347b0eb 100644 --- a/pyteal/__init__.pyi +++ b/pyteal/__init__.pyi @@ -11,7 +11,6 @@ from pyteal.compiler import ( MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, - FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -115,7 +114,6 @@ __all__ = [ "ExtractUint16", "ExtractUint32", "ExtractUint64", - "FRAME_POINTER_VERSION", "For", "Ge", "GeneratedID", diff --git a/pyteal/compiler/__init__.py b/pyteal/compiler/__init__.py index 9755ead4f..e0d29450d 100644 --- a/pyteal/compiler/__init__.py +++ b/pyteal/compiler/__init__.py @@ -3,7 +3,6 @@ MIN_TEAL_VERSION, DEFAULT_TEAL_VERSION, MAX_PROGRAM_VERSION, - FRAME_POINTER_VERSION, MIN_PROGRAM_VERSION, DEFAULT_PROGRAM_VERSION, CompileOptions, @@ -17,7 +16,6 @@ "MIN_TEAL_VERSION", "DEFAULT_TEAL_VERSION", "MAX_PROGRAM_VERSION", - "FRAME_POINTER_VERSION", "MIN_PROGRAM_VERSION", "DEFAULT_PROGRAM_VERSION", "CompileOptions", From a1770c4b74b03975742c39d835315325e3a3906b Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Thu, 3 Nov 2022 09:03:59 -0500 Subject: [PATCH 083/157] Validate types option (#590) * experiment with external type validation * revert * passing unit tests * revert --- pyteal/ast/abi/type.py | 19 ++++++++++++++++--- pyteal/ast/abstractvar.py | 2 +- pyteal/ast/frame.py | 10 ++++++++-- pyteal/ast/scratchvar.py | 19 ++++++++++--------- 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index 24f396cf3..1f4fff6d9 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -1,11 +1,11 @@ from typing import TypeVar, Generic, Callable, Final, cast from abc import ABC, abstractmethod -from pyteal.errors import TealInputError -from pyteal.types import TealType from pyteal.ast.expr import Expr from pyteal.ast.scratchvar import ScratchVar, AbstractVar from pyteal.ast.seq import Seq +from pyteal.errors import TealInputError +from pyteal.types import TealType, require_type, types_match class TypeSpec(ABC): @@ -221,6 +221,8 @@ def produced_type_spec(self) -> TypeSpec: return self.type_spec def store_into(self, output: BaseType) -> Expr: + from pyteal.ast.subroutine import SubroutineCall + if output.type_spec() != self.produced_type_spec(): raise TealInputError( f"expected type_spec {self.produced_type_spec()} but get {output.type_spec()}" @@ -237,7 +239,18 @@ def store_into(self, output: BaseType) -> Expr: f"ABI return subroutine deferred_expr is expected to be typed {output.type_spec().storage_type()}, " f"but has type {declaration.deferred_expr.type_of()}." ) - return output._stored_value.store(self.computation) + if ( + isinstance(self.computation, SubroutineCall) + and self.computation.output_kwarg + ): + assert types_match( + self.computation.output_kwarg.abi_type.storage_type(), + output._stored_value.storage_type(), + ) + else: + require_type(self.computation, output._stored_value.storage_type()) + + return output._stored_value.store(self.computation, validate_types=False) ReturnedValue.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abstractvar.py b/pyteal/ast/abstractvar.py index 59788e001..d18a98d70 100644 --- a/pyteal/ast/abstractvar.py +++ b/pyteal/ast/abstractvar.py @@ -5,7 +5,7 @@ class AbstractVar(ABC): @abstractmethod - def store(self, value: Expr) -> Expr: + def store(self, value: Expr, validate_types: bool = True) -> Expr: pass @abstractmethod diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 9ddcf237a..652709fee 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -3,7 +3,7 @@ from pyteal.ast.expr import Expr from pyteal.ast.scratchvar import AbstractVar from pyteal.types import TealType, require_type -from pyteal.errors import TealInputError, verifyProgramVersion +from pyteal.errors import TealInputError, TealInternalError, verifyProgramVersion from pyteal.ir import TealBlock, TealSimpleBlock, TealOp, Op if TYPE_CHECKING: @@ -111,7 +111,13 @@ def __init__(self, storage_type: TealType, frame_index: int) -> None: def storage_type(self) -> TealType: return self.stack_type - def store(self, value: Expr) -> Expr: + def store(self, value: Expr, validate_types: bool = True) -> Expr: + if not validate_types: + # validation always happens inside of FramBury's initializer + raise TealInternalError( + f"DynamicScratchVar's must validate_types but {validate_types=}" + ) + return FrameBury(value, self.frame_index) def load(self) -> Expr: diff --git a/pyteal/ast/scratchvar.py b/pyteal/ast/scratchvar.py index e97b5d1ef..29a938e33 100644 --- a/pyteal/ast/scratchvar.py +++ b/pyteal/ast/scratchvar.py @@ -1,5 +1,5 @@ -from pyteal.errors import TealInputError -from pyteal.types import TealType, require_type, types_match +from pyteal.errors import TealInputError, TealInternalError +from pyteal.types import TealType, require_type from pyteal.ast.abstractvar import AbstractVar from pyteal.ast.expr import Expr @@ -37,18 +37,14 @@ def storage_type(self) -> TealType: """Get the type of expressions that can be stored in this ScratchVar.""" return self.type - def store(self, value: Expr) -> Expr: + def store(self, value: Expr, validate_types: bool = True) -> Expr: """Store value in Scratch Space Args: value: The value to store. Must conform to this ScratchVar's type. """ - from pyteal.ast.subroutine import SubroutineCall - - if not isinstance(value, SubroutineCall) or not value.output_kwarg: + if validate_types: require_type(value, self.type) - else: - assert types_match(value.output_kwarg.abi_type.storage_type(), self.type) return self.slot.store(value) def load(self) -> ScratchLoad: @@ -121,8 +117,13 @@ def storage_type(self) -> TealType: """Get the type of expressions that can be stored in this ScratchVar.""" return self.dynamic_type - def store(self, value: Expr) -> Expr: + def store(self, value: Expr, validate_types: bool = True) -> Expr: """Store the value in the referenced ScratchVar.""" + if not validate_types: + raise TealInternalError( + f"DynamicScratchVar's must validate_types but {validate_types=}" + ) + require_type(value, self.dynamic_type) return ScratchStore(slot=None, value=value, index_expression=self.index()) From 5193635a4d671cb9aac06039fdd65c17f2685546 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Thu, 3 Nov 2022 10:51:51 -0400 Subject: [PATCH 084/157] wrong import, blame my lsp --- pyteal/ast/abi/string.py | 3 ++- pyteal/ast/abi/type.py | 3 ++- pyteal/ast/abi/uint.py | 3 ++- pyteal/ast/frame.py | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pyteal/ast/abi/string.py b/pyteal/ast/abi/string.py index f142eaa55..890e7e149 100644 --- a/pyteal/ast/abi/string.py +++ b/pyteal/ast/abi/string.py @@ -4,10 +4,11 @@ from algosdk.abi import ABIType from pyteal.ast.abi.uint import Byte -from pyteal.ast.abi.type import ComputedValue, BaseType, AbstractVar +from pyteal.ast.abi.type import ComputedValue, BaseType from pyteal.ast.abi.array_dynamic import DynamicArray, DynamicArrayTypeSpec from pyteal.ast.abi.uint import ByteTypeSpec, Uint16TypeSpec +from pyteal.ast.abstractvar import AbstractVar from pyteal.ast.int import Int from pyteal.ast.expr import Expr from pyteal.ast.bytes import Bytes diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index 1f4fff6d9..fcdef3c2a 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -2,7 +2,8 @@ from abc import ABC, abstractmethod from pyteal.ast.expr import Expr -from pyteal.ast.scratchvar import ScratchVar, AbstractVar +from pyteal.ast.abstractvar import AbstractVar +from pyteal.ast.scratchvar import ScratchVar from pyteal.ast.seq import Seq from pyteal.errors import TealInputError from pyteal.types import TealType, require_type, types_match diff --git a/pyteal/ast/abi/uint.py b/pyteal/ast/abi/uint.py index c3f7c7f98..949eb7c40 100644 --- a/pyteal/ast/abi/uint.py +++ b/pyteal/ast/abi/uint.py @@ -8,6 +8,7 @@ from pyteal.types import TealType from pyteal.errors import TealInputError +from pyteal.ast.abstractvar import AbstractVar from pyteal.ast.expr import Expr from pyteal.ast.seq import Seq from pyteal.ast.assert_ import Assert @@ -17,7 +18,7 @@ from pyteal.ast.unaryexpr import Itob, Btoi from pyteal.ast.binaryexpr import GetByte, ExtractUint16, ExtractUint32, ExtractUint64 from pyteal.ast.ternaryexpr import SetByte -from pyteal.ast.abi.type import ComputedValue, TypeSpec, BaseType, AbstractVar +from pyteal.ast.abi.type import ComputedValue, TypeSpec, BaseType NUM_BITS_IN_BYTE = 8 diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 652709fee..5b964ac93 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -1,7 +1,7 @@ from typing import TYPE_CHECKING from pyteal.ast.expr import Expr -from pyteal.ast.scratchvar import AbstractVar +from pyteal.ast.abstractvar import AbstractVar from pyteal.types import TealType, require_type from pyteal.errors import TealInputError, TealInternalError, verifyProgramVersion from pyteal.ir import TealBlock, TealSimpleBlock, TealOp, Op From 2a57388ef28d780fefd5c78395da4357e172d7dd Mon Sep 17 00:00:00 2001 From: Hang Su <87964331+ahangsu@users.noreply.github.com> Date: Thu, 3 Nov 2022 10:52:52 -0400 Subject: [PATCH 085/157] FrameVar error msg fix Co-authored-by: Zeph Grunschlag --- pyteal/ast/frame.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 5b964ac93..e768021f0 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -115,7 +115,7 @@ def store(self, value: Expr, validate_types: bool = True) -> Expr: if not validate_types: # validation always happens inside of FramBury's initializer raise TealInternalError( - f"DynamicScratchVar's must validate_types but {validate_types=}" + f"FrameVar's must validate_types but {validate_types=}" ) return FrameBury(value, self.frame_index) From a895cb9480215e3df9af99fe7498387f801d0a98 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Thu, 3 Nov 2022 14:10:31 -0400 Subject: [PATCH 086/157] scrape down the change of frame pointer from feature/fp-subroutine --- pyteal/ast/frame.py | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index e768021f0..71277a7ed 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -1,8 +1,9 @@ from typing import TYPE_CHECKING from pyteal.ast.expr import Expr +from pyteal.ast.int import Int from pyteal.ast.abstractvar import AbstractVar -from pyteal.types import TealType, require_type +from pyteal.types import TealType, require_type, types_match from pyteal.errors import TealInputError, TealInternalError, verifyProgramVersion from pyteal.ir import TealBlock, TealSimpleBlock, TealOp, Op @@ -11,7 +12,7 @@ class Proto(Expr): - def __init__(self, num_args: int, num_returns: int): + def __init__(self, num_args: int, num_returns: int, /, *, num_allocs: int = 0): super().__init__() if num_args < 0: raise TealInputError( @@ -23,6 +24,7 @@ def __init__(self, num_args: int, num_returns: int): ) self.num_args = num_args self.num_returns = num_returns + self.num_allocs = num_allocs def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: verifyProgramVersion( @@ -31,10 +33,20 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc "Program version too low to use op proto", ) op = TealOp(self, Op.proto, self.num_args, self.num_returns) - return TealBlock.FromOp(options, op) + proto_srt, proto_end = TealBlock.FromOp(options, op) + if self.num_allocs == 0: + return proto_srt, proto_end + elif self.num_allocs == 1: + int_srt, int_end = Int(0).__teal__(options) + proto_end.setNextBlock(int_srt) + return proto_srt, int_end + else: + dupn_srt, dupn_end = DupN(Int(0), self.num_allocs).__teal__(options) + proto_end.setNextBlock(dupn_srt) + return proto_srt, dupn_end def __str__(self) -> str: - return f"(proto: num_args = {self.num_args}, num_returns = {self.num_returns})" + return f"(proto: num_args = {self.num_args}, num_rets = {self.num_returns}, num_allocs = {self.num_allocs})" def type_of(self) -> TealType: return TealType.none @@ -75,8 +87,16 @@ def has_return(self) -> bool: class FrameBury(Expr): def __init__(self, value: Expr, frame_index: int): + from pyteal.ast.subroutine import SubroutineCall + super().__init__() - require_type(value, TealType.anytype) + if not isinstance(value, SubroutineCall) or not value.output_kwarg: + require_type(value, TealType.anytype) + else: + assert types_match( + value.output_kwarg.abi_type.storage_type(), TealType.anytype + ) + self.value = value self.frame_index = frame_index From 630e04673a358c6f06ae72040d5f50ff91dd5950 Mon Sep 17 00:00:00 2001 From: Hang Su <87964331+ahangsu@users.noreply.github.com> Date: Mon, 7 Nov 2022 15:07:43 -0500 Subject: [PATCH 087/157] Memory layout for frame var and frame ops (#593) * memory layout structure in frame var and frame related ops * validate type * minor, error msg * testing for memory layout, need test frame var * kwarg/posarg * simpler condition in check frame mem layout args Co-authored-by: Zeph Grunschlag * Better type check in `__getitem__` return var Co-authored-by: Zeph Grunschlag * vanilla flavored class decl * take away output index * good testcase for succinct repr * better assert for type checking * better error checking in proto, inherit layouts from expr not seq * tie for local type segment invalid none type * take out confusing algorithm * better tie error msg check * super Co-authored-by: Zeph Grunschlag --- pyteal/ast/frame.py | 192 +++++++++++++++++++++++++++++------- pyteal/ast/frame_test.py | 204 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 358 insertions(+), 38 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 71277a7ed..7962d349b 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -1,9 +1,11 @@ -from typing import TYPE_CHECKING +from itertools import groupby +from typing import TYPE_CHECKING, Optional from pyteal.ast.expr import Expr from pyteal.ast.int import Int +from pyteal.ast.bytes import Bytes from pyteal.ast.abstractvar import AbstractVar -from pyteal.types import TealType, require_type, types_match +from pyteal.types import TealType, require_type from pyteal.errors import TealInputError, TealInternalError, verifyProgramVersion from pyteal.ir import TealBlock, TealSimpleBlock, TealOp, Op @@ -11,20 +13,133 @@ from pyteal.compiler import CompileOptions +class LocalTypeSegment(Expr): + def __init__(self, local_type: TealType, count: int): + super().__init__() + self.local_type = local_type + self.count = count + self.auto_instance: Expr + + if self.count <= 0: + raise TealInternalError( + "LocalTypeSegment initialization error: segment length must be strictly greater than 0." + ) + match self.local_type: + case TealType.uint64 | TealType.anytype: + self.auto_instance = Int(0) + case TealType.bytes: + self.auto_instance = Bytes("") + case TealType.none: + raise TealInternalError( + "Local variable in subroutine initialization must be typed." + ) + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + if self.count == 1: + inst_srt, inst_end = self.auto_instance.__teal__(options) + return inst_srt, inst_end + else: + dupn_srt, dupn_end = DupN(self.auto_instance, self.count).__teal__(options) + return dupn_srt, dupn_end + + def __str__(self) -> str: + return f"(LocalTypeSegment: (type: {self.local_type}) (count: {self.count}))" + + def has_return(self) -> bool: + return False + + def type_of(self) -> TealType: + return TealType.none + + +LocalTypeSegment.__module__ = "pyteal" + + +class ProtoStackLayout(Expr): + def __init__( + self, + arg_stack_types: list[TealType], + local_stack_types: list[TealType], + num_returns: int, + ): + super().__init__() + if num_returns < 0: + raise TealInternalError("Return number should be non-negative.") + elif num_returns > len(local_stack_types): + raise TealInternalError( + "ProtoStackLayout initialization error:" + f"return number {num_returns} should not be greater than local allocations {len(local_stack_types)}." + ) + + if not all(map(lambda t: t != TealType.none, arg_stack_types)): + raise TealInternalError("Variables in frame memory layout must be typed.") + + self.num_returns: int = num_returns + self.arg_stack_types: list[TealType] = arg_stack_types + self.local_stack_types: list[TealType] = local_stack_types + + # Type check of local variables are performed over LocalTypeSegments + self.succinct_repr: list[LocalTypeSegment] = [ + LocalTypeSegment(t_type, len(list(dup_seg))) + for t_type, dup_seg in groupby(self.local_stack_types) + ] + + def __getitem__(self, index: int) -> TealType: + if index < 0: + return self.arg_stack_types[len(self.arg_stack_types) + index] + return self.local_stack_types[index] + + def __str__(self) -> str: + return f"(ProtoStackLayout: (args: {self.arg_stack_types}) (locals: {self.local_stack_types}))" + + def has_return(self) -> bool: + return False + + def type_of(self) -> TealType: + return TealType.none + + def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: + seg_srt, seg_end = self.succinct_repr[0].__teal__(options) + for iter_seg in self.succinct_repr[1:]: + srt, end = iter_seg.__teal__(options) + seg_end.setNextBlock(srt) + seg_end = end + return seg_srt, seg_end + + +ProtoStackLayout.__module__ = "pyteal" + + class Proto(Expr): - def __init__(self, num_args: int, num_returns: int, /, *, num_allocs: int = 0): + def __init__( + self, + num_args: int, + num_returns: int, + *, + mem_layout: Optional[ProtoStackLayout] = None, + ): super().__init__() if num_args < 0: raise TealInputError( - f"the number of arguments provided to Proto must be >= 0 but {num_args=}" + f"The number of arguments provided to Proto must be >= 0 but {num_args=}." ) if num_returns < 0: raise TealInputError( - f"the number of return values provided to Proto must be >= 0 but {num_returns=}" + f"The number of returns provided to Proto must be >= 0 but {num_returns=}." ) + if mem_layout: + if mem_layout.num_returns != num_returns: + raise TealInternalError( + f"The number of returns {num_returns} should match with memory layout's number of returns {mem_layout.num_returns}" + ) + if len(mem_layout.arg_stack_types) != num_args: + raise TealInternalError( + f"The number of arguments {num_args} should match with memory layout's number of arguments {len(mem_layout.arg_stack_types)}" + ) + self.num_args = num_args self.num_returns = num_returns - self.num_allocs = num_allocs + self.mem_layout: Optional[ProtoStackLayout] = mem_layout def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: verifyProgramVersion( @@ -34,19 +149,14 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc ) op = TealOp(self, Op.proto, self.num_args, self.num_returns) proto_srt, proto_end = TealBlock.FromOp(options, op) - if self.num_allocs == 0: + if not self.mem_layout: return proto_srt, proto_end - elif self.num_allocs == 1: - int_srt, int_end = Int(0).__teal__(options) - proto_end.setNextBlock(int_srt) - return proto_srt, int_end - else: - dupn_srt, dupn_end = DupN(Int(0), self.num_allocs).__teal__(options) - proto_end.setNextBlock(dupn_srt) - return proto_srt, dupn_end + local_srt, local_end = self.mem_layout.__teal__(options) + proto_end.setNextBlock(local_srt) + return proto_srt, local_end def __str__(self) -> str: - return f"(proto: num_args = {self.num_args}, num_rets = {self.num_returns}, num_allocs = {self.num_allocs})" + return f"(proto: num_args = {self.num_args}, num_rets = {self.num_returns})" def type_of(self) -> TealType: return TealType.none @@ -59,9 +169,10 @@ def has_return(self) -> bool: class FrameDig(Expr): - def __init__(self, frame_index: int): + def __init__(self, frame_index: int, *, inferred_type: Optional[TealType] = None): super().__init__() self.frame_index = frame_index + self.dig_type = inferred_type if inferred_type else TealType.anytype def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: verifyProgramVersion( @@ -76,7 +187,7 @@ def __str__(self) -> str: return f"(frame_dig: dig_from = {self.frame_index})" def type_of(self) -> TealType: - return TealType.anytype + return self.dig_type def has_return(self) -> bool: return False @@ -86,16 +197,19 @@ def has_return(self) -> bool: class FrameBury(Expr): - def __init__(self, value: Expr, frame_index: int): - from pyteal.ast.subroutine import SubroutineCall - + def __init__( + self, + value: Expr, + frame_index: int, + *, + validate_types: bool = True, + inferred_type: Optional[TealType] = None, + ): super().__init__() - if not isinstance(value, SubroutineCall) or not value.output_kwarg: - require_type(value, TealType.anytype) - else: - assert types_match( - value.output_kwarg.abi_type.storage_type(), TealType.anytype - ) + + if validate_types: + target_type = inferred_type if inferred_type else TealType.anytype + require_type(value, target_type) self.value = value self.frame_index = frame_index @@ -123,25 +237,29 @@ def has_return(self) -> bool: class FrameVar(AbstractVar): - def __init__(self, storage_type: TealType, frame_index: int) -> None: + def __init__(self, under_proto: Proto, frame_index: int) -> None: super().__init__() - self.stack_type = storage_type + self.proto = under_proto self.frame_index = frame_index + self.stack_type = ( + self.proto.mem_layout[frame_index] + if self.proto.mem_layout + else TealType.anytype + ) def storage_type(self) -> TealType: return self.stack_type def store(self, value: Expr, validate_types: bool = True) -> Expr: - if not validate_types: - # validation always happens inside of FramBury's initializer - raise TealInternalError( - f"FrameVar's must validate_types but {validate_types=}" - ) - - return FrameBury(value, self.frame_index) + return FrameBury( + value, + self.frame_index, + validate_types=validate_types, + inferred_type=self.stack_type, + ) def load(self) -> Expr: - return FrameDig(self.frame_index) + return FrameDig(self.frame_index, inferred_type=self.stack_type) FrameVar.__module__ = "pyteal" diff --git a/pyteal/ast/frame_test.py b/pyteal/ast/frame_test.py index e4cde2aa4..2182c35b9 100644 --- a/pyteal/ast/frame_test.py +++ b/pyteal/ast/frame_test.py @@ -1,6 +1,14 @@ import pytest import pyteal as pt -from pyteal.ast.frame import FrameBury, FrameDig, Proto, DupN +from dataclasses import dataclass +from pyteal.ast.frame import ( + FrameBury, + FrameDig, + Proto, + DupN, + LocalTypeSegment, + ProtoStackLayout, +) avm7Options = pt.CompileOptions(version=7) avm8Options = pt.CompileOptions(version=8) @@ -105,3 +113,197 @@ def test_dupn_invalid(): with pytest.raises(pt.TealInputError): DupN(pt.Int(1), 1).__teal__(avm7Options) + + +def test_local_type_segment_invalid(): + with pytest.raises(pt.TealInternalError) as tie: + LocalTypeSegment(pt.TealType.anytype, 0) + + assert "segment length must be strictly greater than 0" in str(tie) + + with pytest.raises(pt.TealInternalError) as tie: + LocalTypeSegment(pt.TealType.anytype, -1) + + assert "segment length must be strictly greater than 0" in str(tie) + + with pytest.raises(pt.TealInternalError) as tie: + LocalTypeSegment(pt.TealType.none, 2) + + assert "Local variable in subroutine initialization must be typed." in str(tie) + + +@dataclass +class LocalTypeSegmentTestCase: + local_type_segment: LocalTypeSegment + expected: pt.TealSimpleBlock + + +@pytest.mark.parametrize( + "testcase", + [ + LocalTypeSegmentTestCase( + LocalTypeSegment(pt.TealType.anytype, 1), + pt.TealSimpleBlock([pt.TealOp(None, pt.Op.int, 0)]), + ), + LocalTypeSegmentTestCase( + LocalTypeSegment(pt.TealType.anytype, 5), + pt.TealSimpleBlock( + [ + pt.TealOp(None, pt.Op.int, 0), + pt.TealOp(None, pt.Op.dupn, 5), + ] + ), + ), + LocalTypeSegmentTestCase( + LocalTypeSegment(pt.TealType.uint64, 1), + pt.TealSimpleBlock([pt.TealOp(None, pt.Op.int, 0)]), + ), + LocalTypeSegmentTestCase( + LocalTypeSegment(pt.TealType.uint64, 5), + pt.TealSimpleBlock( + [ + pt.TealOp(None, pt.Op.int, 0), + pt.TealOp(None, pt.Op.dupn, 5), + ] + ), + ), + LocalTypeSegmentTestCase( + LocalTypeSegment(pt.TealType.bytes, 1), + pt.TealSimpleBlock([pt.TealOp(None, pt.Op.byte, '""')]), + ), + LocalTypeSegmentTestCase( + LocalTypeSegment(pt.TealType.bytes, 5), + pt.TealSimpleBlock( + [ + pt.TealOp(None, pt.Op.byte, '""'), + pt.TealOp(None, pt.Op.dupn, 5), + ] + ), + ), + ], +) +def test_local_type_segment_compilation(testcase: LocalTypeSegmentTestCase): + actual, _ = testcase.local_type_segment.__teal__(avm8Options) + actual.addIncoming() + actual = pt.TealBlock.NormalizeBlocks(actual) + + with pt.TealComponent.Context.ignoreExprEquality(): + assert actual == testcase.expected + + +def test_proto_stack_layout_invalid(): + with pytest.raises(pt.TealInternalError) as bad_local_alloc: + ProtoStackLayout([pt.TealType.uint64, pt.TealType.bytes], [], -1) + + assert "Return number should be non-negative." == str(bad_local_alloc.value) + + with pytest.raises(pt.TealInternalError) as bad_local_alloc: + ProtoStackLayout([pt.TealType.uint64, pt.TealType.bytes], [], 1) + + assert "should not be greater than local allocations" in str(bad_local_alloc.value) + + with pytest.raises(pt.TealInternalError) as bad_type_on_stack: + ProtoStackLayout([pt.TealType.bytes, pt.TealType.none], [], 0) + + assert "must be typed" in str(bad_type_on_stack.value) + + with pytest.raises(pt.TealInternalError) as bad_type_on_stack: + ProtoStackLayout( + [pt.TealType.bytes, pt.TealType.uint64], + [pt.TealType.uint64, pt.TealType.none], + 0, + ) + + assert "must be typed" in str(bad_type_on_stack.value) + + +@dataclass +class SuccinctReprTestCase: + local_types: list[pt.TealType] + expected: list[LocalTypeSegment] + + +@pytest.mark.parametrize( + "testcase", + [ + SuccinctReprTestCase([], []), + SuccinctReprTestCase( + [pt.TealType.anytype], [LocalTypeSegment(pt.TealType.anytype, 1)] + ), + SuccinctReprTestCase( + [pt.TealType.anytype, pt.TealType.uint64], + [ + LocalTypeSegment(pt.TealType.anytype, 1), + LocalTypeSegment(pt.TealType.uint64, 1), + ], + ), + SuccinctReprTestCase( + [pt.TealType.bytes, pt.TealType.anytype, pt.TealType.uint64], + [ + LocalTypeSegment(pt.TealType.bytes, 1), + LocalTypeSegment(pt.TealType.anytype, 1), + LocalTypeSegment(pt.TealType.uint64, 1), + ], + ), + SuccinctReprTestCase( + [ + pt.TealType.anytype, + pt.TealType.bytes, + pt.TealType.anytype, + pt.TealType.uint64, + ], + [ + LocalTypeSegment(pt.TealType.anytype, 1), + LocalTypeSegment(pt.TealType.bytes, 1), + LocalTypeSegment(pt.TealType.anytype, 1), + LocalTypeSegment(pt.TealType.uint64, 1), + ], + ), + SuccinctReprTestCase( + [ + pt.TealType.anytype, + pt.TealType.bytes, + pt.TealType.anytype, + pt.TealType.uint64, + pt.TealType.anytype, + ], + [ + LocalTypeSegment(pt.TealType.anytype, 1), + LocalTypeSegment(pt.TealType.bytes, 1), + LocalTypeSegment(pt.TealType.anytype, 1), + LocalTypeSegment(pt.TealType.uint64, 1), + LocalTypeSegment(pt.TealType.anytype, 1), + ], + ), + SuccinctReprTestCase( + [ + pt.TealType.anytype, + pt.TealType.bytes, + pt.TealType.bytes, + pt.TealType.uint64, + pt.TealType.uint64, + pt.TealType.uint64, + pt.TealType.anytype, + pt.TealType.anytype, + pt.TealType.anytype, + pt.TealType.anytype, + pt.TealType.bytes, + pt.TealType.bytes, + pt.TealType.uint64, + pt.TealType.uint64, + pt.TealType.uint64, + ], + [ + LocalTypeSegment(pt.TealType.anytype, 1), + LocalTypeSegment(pt.TealType.bytes, 2), + LocalTypeSegment(pt.TealType.uint64, 3), + LocalTypeSegment(pt.TealType.anytype, 4), + LocalTypeSegment(pt.TealType.bytes, 2), + LocalTypeSegment(pt.TealType.uint64, 3), + ], + ), + ], +) +def test_proto_stack_layout_succinct_repr(testcase: SuccinctReprTestCase): + actual = ProtoStackLayout([], testcase.local_types, False).succinct_repr + assert actual == testcase.expected From e399e09d240c4e5bea80af3e150829919cbeac45 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Mon, 7 Nov 2022 15:24:56 -0500 Subject: [PATCH 088/157] rename arg for mem layout, on return alloc number --- pyteal/ast/frame.py | 20 +++++++++++--------- pyteal/ast/frame_test.py | 16 ++++++++-------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 7962d349b..329922c5c 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -60,21 +60,21 @@ def __init__( self, arg_stack_types: list[TealType], local_stack_types: list[TealType], - num_returns: int, + num_return_allocs: int, ): super().__init__() - if num_returns < 0: - raise TealInternalError("Return number should be non-negative.") - elif num_returns > len(local_stack_types): + if num_return_allocs < 0: + raise TealInternalError("Return allocation number should be non-negative.") + elif num_return_allocs > len(local_stack_types): raise TealInternalError( "ProtoStackLayout initialization error:" - f"return number {num_returns} should not be greater than local allocations {len(local_stack_types)}." + f"return allocation number {num_return_allocs} should not be greater than local allocations {len(local_stack_types)}." ) if not all(map(lambda t: t != TealType.none, arg_stack_types)): raise TealInternalError("Variables in frame memory layout must be typed.") - self.num_returns: int = num_returns + self.num_return_allocs: int = num_return_allocs self.arg_stack_types: list[TealType] = arg_stack_types self.local_stack_types: list[TealType] = local_stack_types @@ -128,13 +128,15 @@ def __init__( f"The number of returns provided to Proto must be >= 0 but {num_returns=}." ) if mem_layout: - if mem_layout.num_returns != num_returns: + if mem_layout.num_return_allocs > num_returns: raise TealInternalError( - f"The number of returns {num_returns} should match with memory layout's number of returns {mem_layout.num_returns}" + f"The number of returns {num_returns} should be greater equal to " + f"memory layout's number of allocations for returns {mem_layout.num_return_allocs}" ) if len(mem_layout.arg_stack_types) != num_args: raise TealInternalError( - f"The number of arguments {num_args} should match with memory layout's number of arguments {len(mem_layout.arg_stack_types)}" + f"The number of arguments {num_args} should match with " + f"memory layout's number of arguments {len(mem_layout.arg_stack_types)}" ) self.num_args = num_args diff --git a/pyteal/ast/frame_test.py b/pyteal/ast/frame_test.py index 2182c35b9..3f62ca35b 100644 --- a/pyteal/ast/frame_test.py +++ b/pyteal/ast/frame_test.py @@ -192,29 +192,29 @@ def test_local_type_segment_compilation(testcase: LocalTypeSegmentTestCase): def test_proto_stack_layout_invalid(): - with pytest.raises(pt.TealInternalError) as bad_local_alloc: + with pytest.raises(pt.TealInternalError) as tie: ProtoStackLayout([pt.TealType.uint64, pt.TealType.bytes], [], -1) - assert "Return number should be non-negative." == str(bad_local_alloc.value) + assert "Return allocation number should be non-negative." == str(tie.value) - with pytest.raises(pt.TealInternalError) as bad_local_alloc: + with pytest.raises(pt.TealInternalError) as tie: ProtoStackLayout([pt.TealType.uint64, pt.TealType.bytes], [], 1) - assert "should not be greater than local allocations" in str(bad_local_alloc.value) + assert "should not be greater than local allocations" in str(tie.value) - with pytest.raises(pt.TealInternalError) as bad_type_on_stack: + with pytest.raises(pt.TealInternalError) as tie: ProtoStackLayout([pt.TealType.bytes, pt.TealType.none], [], 0) - assert "must be typed" in str(bad_type_on_stack.value) + assert "must be typed" in str(tie.value) - with pytest.raises(pt.TealInternalError) as bad_type_on_stack: + with pytest.raises(pt.TealInternalError) as tie: ProtoStackLayout( [pt.TealType.bytes, pt.TealType.uint64], [pt.TealType.uint64, pt.TealType.none], 0, ) - assert "must be typed" in str(bad_type_on_stack.value) + assert "must be typed" in str(tie.value) @dataclass From 0a5b570c55cf50e7ffe49483239bdc8fc04d58f3 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Mon, 7 Nov 2022 16:53:00 -0500 Subject: [PATCH 089/157] if there's nothing to initialize for local... --- pyteal/ast/frame.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 329922c5c..d299b2db0 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -99,12 +99,13 @@ def type_of(self) -> TealType: return TealType.none def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBlock]: - seg_srt, seg_end = self.succinct_repr[0].__teal__(options) - for iter_seg in self.succinct_repr[1:]: - srt, end = iter_seg.__teal__(options) - seg_end.setNextBlock(srt) - seg_end = end - return seg_srt, seg_end + srt = TealSimpleBlock([]) + end = srt + for iter_seg in self.succinct_repr: + seg_srt, seg_end = iter_seg.__teal__(options) + end.setNextBlock(seg_srt) + end = seg_end + return srt, end ProtoStackLayout.__module__ = "pyteal" From b8b6f32a804664787ab4c87251fc2231a97ab6ca Mon Sep 17 00:00:00 2001 From: Hang Su Date: Mon, 7 Nov 2022 18:45:42 -0500 Subject: [PATCH 090/157] update changes from mem layout --- pyteal/ast/abi/type.py | 5 +- pyteal/ast/subroutine.py | 74 ++++++++++++------- .../teal/roundtrip/app_roundtrip_()_v8.teal | 4 +- .../app_roundtrip_(bool)[10]_v8.teal | 6 +- .../roundtrip/app_roundtrip_(bool)_v8.teal | 4 +- ...t64,bool),byte[10],bool[4],uint64)_v8.teal | 12 +-- .../app_roundtrip_(bool,byte)_v8.teal | 4 +- ...undtrip_(bool,byte,address,string)_v8.teal | 8 +- ...yte),uint8)[2],string,bool[]))[]_2_v8.teal | 30 ++++---- ..._(bool,byte,address,string,uint64)_v8.teal | 8 +- ...app_roundtrip_(bool,uint64,uint32)_v8.teal | 4 +- .../roundtrip/app_roundtrip_(byte)_v8.teal | 4 +- .../app_roundtrip_(byte,bool,uint64)_v8.teal | 4 +- ...4],(bool,bool),uint64,address)[]_7_v8.teal | 12 +-- .../roundtrip/app_roundtrip_(uint16)_v8.teal | 4 +- .../app_roundtrip_(uint16,uint8,byte)_v8.teal | 4 +- .../roundtrip/app_roundtrip_(uint32)_v8.teal | 4 +- ...pp_roundtrip_(uint32,uint16,uint8)_v8.teal | 4 +- .../roundtrip/app_roundtrip_(uint64)_v8.teal | 4 +- ...p_roundtrip_(uint64,uint32,uint16)_v8.teal | 4 +- .../roundtrip/app_roundtrip_(uint8)_v8.teal | 4 +- .../app_roundtrip_(uint8,byte,bool)_v8.teal | 4 +- .../app_roundtrip_address[]_10_v8.teal | 6 +- .../roundtrip/app_roundtrip_address_v8.teal | 4 +- .../roundtrip/app_roundtrip_bool[1]_v8.teal | 4 +- .../app_roundtrip_bool[3][]_11_v8.teal | 6 +- .../roundtrip/app_roundtrip_bool[42]_v8.teal | 4 +- .../roundtrip/app_roundtrip_bool[]_0_v8.teal | 4 +- .../roundtrip/app_roundtrip_bool[]_1_v8.teal | 4 +- .../roundtrip/app_roundtrip_bool[]_42_v8.teal | 4 +- .../teal/roundtrip/app_roundtrip_bool_v8.teal | 2 +- .../roundtrip/app_roundtrip_byte[16]_v8.teal | 4 +- .../roundtrip/app_roundtrip_byte[]_36_v8.teal | 4 +- .../teal/roundtrip/app_roundtrip_byte_v8.teal | 2 +- .../roundtrip/app_roundtrip_string_0_v8.teal | 4 +- .../roundtrip/app_roundtrip_string_13_v8.teal | 4 +- .../roundtrip/app_roundtrip_string_1_v8.teal | 4 +- .../roundtrip/app_roundtrip_uint16_v8.teal | 2 +- .../roundtrip/app_roundtrip_uint32_v8.teal | 2 +- .../roundtrip/app_roundtrip_uint64[1]_v8.teal | 4 +- .../app_roundtrip_uint64[42]_v8.teal | 4 +- .../app_roundtrip_uint64[]_0_v8.teal | 4 +- .../app_roundtrip_uint64[]_1_v8.teal | 4 +- .../app_roundtrip_uint64[]_42_v8.teal | 4 +- .../roundtrip/app_roundtrip_uint64_v8.teal | 2 +- .../roundtrip/app_roundtrip_uint8_v8.teal | 2 +- 46 files changed, 159 insertions(+), 140 deletions(-) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index 03a23fe1a..fcdef3c2a 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -251,10 +251,7 @@ def store_into(self, output: BaseType) -> Expr: else: require_type(self.computation, output._stored_value.storage_type()) - return output._stored_value.store( - self.computation, - validate_types=not isinstance(output._stored_value, ScratchVar), - ) + return output._stored_value.store(self.computation, validate_types=False) ReturnedValue.__module__ = "pyteal.abi" diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 31978ad17..50ad7f1e2 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -9,7 +9,7 @@ from pyteal.ast.expr import Expr from pyteal.ast.seq import Seq from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar, ScratchSlot -from pyteal.ast.frame import FrameDig, Proto +from pyteal.ast.frame import FrameDig, Proto, FrameVar, ProtoStackLayout from pyteal.errors import TealInputError, TealInternalError, verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.types import TealType @@ -914,7 +914,7 @@ class SubroutineEval: """ var_n_loaded: Callable[ - [SubroutineDefinition, str], + [SubroutineDefinition, str, Optional[Proto]], tuple[Optional[ScratchVar], ScratchVar | abi.BaseType | Expr], ] use_frame_pt: bool = False @@ -923,6 +923,7 @@ class SubroutineEval: def __var_n_loaded( subroutine: SubroutineDefinition, param: str, + _: Optional[Proto] = None, ) -> tuple[ScratchVar, ScratchVar | abi.BaseType | Expr]: loaded_var: ScratchVar | abi.BaseType | Expr argument_var: ScratchVar @@ -948,8 +949,12 @@ def __var_n_loaded( def __var_n_loaded_fp( subroutine: SubroutineDefinition, param: str, + proto: Optional[Proto], ) -> tuple[Optional[ScratchVar], ScratchVar | abi.BaseType | Expr]: - from pyteal.ast.frame import FrameVar + if not proto: + raise TealInternalError( + "proto should be available for frame pointer based subroutine." + ) loaded_var: ScratchVar | abi.BaseType | Expr argument_var: Optional[ScratchVar] @@ -962,7 +967,7 @@ def __var_n_loaded_fp( dig_index = ( subroutine.arguments().index(param) - subroutine.argument_count() ) - internal_abi_var._stored_value = FrameVar(TealType.anytype, dig_index) + internal_abi_var._stored_value = FrameVar(proto, dig_index) argument_var = None loaded_var = internal_abi_var else: @@ -974,14 +979,49 @@ def __var_n_loaded_fp( return argument_var, loaded_var + @staticmethod + def __proto(subroutine: SubroutineDefinition) -> Proto: + arg_stack_types: list[TealType] = [] + for t in subroutine.expected_arg_types: + if t is Expr: + arg_stack_types.append(TealType.anytype) + elif t is ScratchVar: + arg_stack_types.append(TealType.uint64) + else: + arg_stack_types.append(cast(abi.TypeSpec, t).storage_type()) + + num_return_allocs: int = int(subroutine.has_abi_output) + + local_stack_types: list[TealType] = [] + if subroutine.has_abi_output: + output_info = cast( + OutputKwArgInfo, OutputKwArgInfo.from_dict(subroutine.output_kwarg) + ) + local_stack_types = [output_info.abi_type.storage_type()] + + layout: ProtoStackLayout = ProtoStackLayout( + arg_stack_types, local_stack_types, num_return_allocs + ) + + # if subroutine do not have abi output, then only two cases happen: + # - subroutine is a normal subroutine, then check subroutine body evaluates to something, rather than none + # - subroutine is an ABIReturnSubroutine, the type is void, and its subroutine body type of is always none + num_stack_outputs: int = ( + 1 + if subroutine.has_abi_output + else int(subroutine.return_type != TealType.none) + ) + + return Proto(subroutine.argument_count(), num_stack_outputs, mem_layout=layout) + def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: - from pyteal.ast.frame import FrameVar + proto = self.__proto(subroutine) args = subroutine.arguments() arg_vars: list[ScratchVar] = [] loaded_args: list[ScratchVar | Expr | abi.BaseType] = [] for arg in args: - arg_var, loaded_arg = self.var_n_loaded(subroutine, arg) + arg_var, loaded_arg = self.var_n_loaded(subroutine, arg, proto) if arg_var: arg_vars.append(arg_var) loaded_args.append(loaded_arg) @@ -993,7 +1033,7 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: if output_kwarg_info: output_carrying_abi = output_kwarg_info.abi_type.new_instance() if self.use_frame_pt: - output_carrying_abi._stored_value = FrameVar(TealType.anytype, 0) + output_carrying_abi._stored_value = FrameVar(proto, 0) abi_output_kwargs[output_kwarg_info.name] = output_carrying_abi # Arg usage "B" supplied to build an AST from the user-defined PyTEAL function: @@ -1016,25 +1056,7 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: # Arg usage "A" to be pick up and store in scratch parameters that have been placed on the stack # need to reverse order of argumentVars because the last argument will be on top of the stack - body_ops: list[Expr] = [] - - stack_output_cnt: int - if not subroutine.has_abi_output: - # if subroutine do not have abi output, then only two cases happen: - # - subroutine is a normal subroutine, then check subroutine body evaluates to something, rather than none - # - subroutine is an ABIReturnSubroutine, the type is void, and its subroutine body type of is always none - stack_output_cnt = int(subroutine.return_type != TealType.none) - else: - stack_output_cnt = len(abi_output_kwargs) - - if self.use_frame_pt: - body_ops = [ - Proto( - subroutine.argument_count(), - stack_output_cnt, - num_allocs=int(subroutine.has_abi_output), - ) - ] + body_ops: list[Expr] = [] if not self.use_frame_pt else [proto] body_ops += [var.slot.store() for var in arg_vars[::-1]] body_ops.append(subroutine_body) diff --git a/tests/integration/teal/roundtrip/app_roundtrip_()_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_()_v8.teal index a15a4fc89..6fc43d729 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_()_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_()_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" byte "" frame_bury 0 frame_dig 0 @@ -23,7 +23,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub tuplecomplement_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v8.teal index 3fd706e70..01f03a3df 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbit @@ -33,7 +33,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -160,7 +160,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_1 store 3 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool)_v8.teal index 007dc02ea..4545cae71 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbit @@ -33,7 +33,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub tuplecomplement_0 store 3 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v8.teal index 6f72201c2..500bd48f0 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbit @@ -75,7 +75,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub tuplecomplement_0 store 8 @@ -121,7 +121,7 @@ retsub // array_complement arraycomplement_4: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -576,7 +576,7 @@ retsub // tuple_complement tuplecomplement_5: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 extract_uint64 @@ -620,7 +620,7 @@ retsub // array_complement arraycomplement_7: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -779,7 +779,7 @@ retsub // array_complement arraycomplement_9: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbit diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v8.teal index 7de062794..93a6c2c3b 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbit @@ -45,7 +45,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub tuplecomplement_0 store 4 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v8.teal index c015db7d2..5d4d405aa 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbit @@ -76,7 +76,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub tuplecomplement_0 store 6 @@ -185,7 +185,7 @@ retsub // array_complement arraycomplement_5: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -640,7 +640,7 @@ retsub // string_reverse stringreverse_6: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v8.teal index c7436e670..196bf904e 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbit @@ -109,7 +109,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 0 +byte "" frame_dig -1 frame_dig -1 int 2 @@ -238,7 +238,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_1 store 7 @@ -347,7 +347,7 @@ retsub // array_complement arraycomplement_6: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -802,7 +802,7 @@ retsub // string_reverse stringreverse_7: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -854,7 +854,7 @@ retsub // tuple_complement tuplecomplement_8: proto 1 1 -int 0 +byte "" frame_dig -1 extract 0 32 store 22 @@ -973,7 +973,7 @@ retsub // array_complement arraycomplement_10: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -1428,7 +1428,7 @@ retsub // tuple_complement tuplecomplement_11: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 extract_uint32 @@ -1497,7 +1497,7 @@ retsub // array_complement arraycomplement_12: proto 1 1 -int 0 +byte "" frame_dig -1 frame_dig -1 int 2 @@ -1596,7 +1596,7 @@ retsub // string_reverse stringreverse_13: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -1660,7 +1660,7 @@ retsub // array_complement arraycomplement_15: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 int 16 @@ -1726,7 +1726,7 @@ retsub // string_reverse stringreverse_17: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -1778,7 +1778,7 @@ retsub // array_complement arraycomplement_18: proto 1 1 -int 0 +byte "" frame_dig -1 frame_dig -1 int 2 @@ -1981,7 +1981,7 @@ retsub // array_complement arraycomplement_20: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbit @@ -2010,7 +2010,7 @@ retsub // tuple_complement tuplecomplement_21: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbyte diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v8.teal index b20a2929e..31c7c3c33 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbit @@ -86,7 +86,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub tuplecomplement_0 store 7 @@ -195,7 +195,7 @@ retsub // array_complement arraycomplement_5: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -650,7 +650,7 @@ retsub // string_reverse stringreverse_6: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v8.teal index c6cb8d92a..0fd41ab36 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbit @@ -54,7 +54,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub tuplecomplement_0 store 5 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(byte)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(byte)_v8.teal index ed37a3f74..58b13c2a9 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(byte)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(byte)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbyte @@ -33,7 +33,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub tuplecomplement_0 store 3 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v8.teal index 328541097..833bcf2f8 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbyte @@ -55,7 +55,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub tuplecomplement_0 store 5 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v8.teal index 12e8535c4..a353ed873 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 extract 0 4 store 0 @@ -55,7 +55,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 0 +byte "" frame_dig -1 int 45 int 0 @@ -166,7 +166,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_1 store 6 @@ -248,7 +248,7 @@ retsub // array_complement arraycomplement_4: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -311,7 +311,7 @@ retsub // tuple_complement tuplecomplement_5: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbit @@ -366,7 +366,7 @@ retsub // array_complement arraycomplement_8: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v8.teal index ce75f2421..b20aff3b8 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 extract_uint16 @@ -32,7 +32,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub tuplecomplement_0 store 3 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v8.teal index b2cde5b27..a04b815e8 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 extract_uint16 @@ -56,7 +56,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub tuplecomplement_0 store 5 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v8.teal index 4e9b98403..608ed547c 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 extract_uint32 @@ -32,7 +32,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub tuplecomplement_0 store 3 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v8.teal index fe6043f2f..f520db71c 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 extract_uint32 @@ -55,7 +55,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub tuplecomplement_0 store 5 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v8.teal index 64e19a464..417770e21 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 btoi store 0 @@ -30,7 +30,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub tuplecomplement_0 store 3 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v8.teal index cdbd5954b..8f2803270 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 extract_uint64 @@ -53,7 +53,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub tuplecomplement_0 store 5 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v8.teal index ed37a3f74..58b13c2a9 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbyte @@ -33,7 +33,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub tuplecomplement_0 store 3 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v8.teal index 689248d79..dedc08a8d 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v8.teal @@ -14,7 +14,7 @@ return // tuple_complement tuplecomplement_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbyte @@ -57,7 +57,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub tuplecomplement_0 store 5 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v8.teal index 280f65569..05dff5111 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v8.teal @@ -29,7 +29,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -484,7 +484,7 @@ retsub // array_complement arraycomplement_2: proto 1 1 -int 0 +byte "" frame_dig -1 int 32 int 0 @@ -637,7 +637,7 @@ retsub // round_tripper roundtripper_3: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_2 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_address_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_address_v8.teal index 33347e57b..f71989611 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_address_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_address_v8.teal @@ -29,7 +29,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -484,7 +484,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v8.teal index 35258686a..3acd9d712 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v8.teal @@ -26,7 +26,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbit @@ -45,7 +45,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v8.teal index 07faee81c..2fc9c7774 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v8.teal @@ -26,7 +26,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbit @@ -65,7 +65,7 @@ retsub // array_complement arraycomplement_2: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -232,7 +232,7 @@ retsub // round_tripper roundtripper_3: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_2 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v8.teal index 31fa09e84..5787f99f9 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v8.teal @@ -26,7 +26,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 getbit @@ -455,7 +455,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v8.teal index 67050ca70..89f595322 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v8.teal @@ -14,7 +14,7 @@ return // array_complement arraycomplement_0: proto 1 1 -int 0 +byte "" int 0 store 8 load 8 @@ -29,7 +29,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v8.teal index 61b164f60..61a4806b2 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v8.teal @@ -26,7 +26,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 int 16 @@ -53,7 +53,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v8.teal index a5c7c3d9f..56931159c 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v8.teal @@ -26,7 +26,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 0 +byte "" frame_dig -1 int 0 int 16 @@ -545,7 +545,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool_v8.teal index b241c509d..23e0c659a 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool_v8.teal @@ -30,7 +30,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub boolcomp_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v8.teal index 4d3b6e7c2..a8ca32f63 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v8.teal @@ -29,7 +29,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -260,7 +260,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v8.teal index 731fb06d0..7aa6b4aad 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v8.teal @@ -29,7 +29,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -618,7 +618,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_byte_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_byte_v8.teal index b1ec9822c..91cc0024a 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_byte_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_byte_v8.teal @@ -31,7 +31,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub numericalcomp_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_0_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_0_v8.teal index fb6e4bfeb..c0d9a212c 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_string_0_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_string_0_v8.teal @@ -14,7 +14,7 @@ return // string_reverse stringreverse_0: proto 1 1 -int 0 +byte "" int 0 store 8 load 8 @@ -29,7 +29,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub stringreverse_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_13_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_13_v8.teal index 6b9d3620f..742afe0a0 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_string_13_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_string_13_v8.teal @@ -14,7 +14,7 @@ return // string_reverse stringreverse_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -196,7 +196,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub stringreverse_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_1_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_1_v8.teal index 15bec0ea9..3e6f669d6 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_string_1_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_string_1_v8.teal @@ -14,7 +14,7 @@ return // string_reverse stringreverse_0: proto 1 1 -int 0 +byte "" frame_dig -1 int 1 int 0 @@ -40,7 +40,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub stringreverse_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint16_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint16_v8.teal index 4204c502b..700f8bead 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint16_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint16_v8.teal @@ -31,7 +31,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub numericalcomp_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint32_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint32_v8.teal index 2ed29b2ee..00be1ca95 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint32_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint32_v8.teal @@ -31,7 +31,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub numericalcomp_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v8.teal index fb6a67b3a..6aa863ad2 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v8.teal @@ -25,7 +25,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 0 +byte "" frame_dig -1 int 8 int 0 @@ -44,7 +44,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v8.teal index e82c27443..b995008af 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v8.teal @@ -25,7 +25,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 0 +byte "" frame_dig -1 int 8 int 0 @@ -536,7 +536,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v8.teal index 67050ca70..89f595322 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v8.teal @@ -14,7 +14,7 @@ return // array_complement arraycomplement_0: proto 1 1 -int 0 +byte "" int 0 store 8 load 8 @@ -29,7 +29,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v8.teal index cd6867a22..ce54ebdb6 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v8.teal @@ -25,7 +25,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 0 +byte "" frame_dig -1 int 8 int 0 @@ -52,7 +52,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v8.teal index 0b2bddb45..24dd3f3ff 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v8.teal @@ -25,7 +25,7 @@ retsub // array_complement arraycomplement_1: proto 1 1 -int 0 +byte "" frame_dig -1 int 8 int 0 @@ -626,7 +626,7 @@ retsub // round_tripper roundtripper_2: proto 1 1 -int 0 +byte "" frame_dig -1 callsub arraycomplement_1 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64_v8.teal index 4f6069984..165bcb347 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64_v8.teal @@ -26,7 +26,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub numericalcomp_0 store 2 diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint8_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint8_v8.teal index b1ec9822c..91cc0024a 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint8_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint8_v8.teal @@ -31,7 +31,7 @@ retsub // round_tripper roundtripper_1: proto 1 1 -int 0 +byte "" frame_dig -1 callsub numericalcomp_0 store 2 From f6994ae0f4f37c7d24b0ae696e7fb7447951ca14 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Tue, 8 Nov 2022 10:50:40 -0500 Subject: [PATCH 091/157] minor change in type-check in computed-type --- pyteal/ast/abi/type.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index fcdef3c2a..34351590a 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -6,7 +6,7 @@ from pyteal.ast.scratchvar import ScratchVar from pyteal.ast.seq import Seq from pyteal.errors import TealInputError -from pyteal.types import TealType, require_type, types_match +from pyteal.types import TealType, types_match class TypeSpec(ABC): @@ -240,6 +240,9 @@ def store_into(self, output: BaseType) -> Expr: f"ABI return subroutine deferred_expr is expected to be typed {output.type_spec().storage_type()}, " f"but has type {declaration.deferred_expr.type_of()}." ) + + validate_in_store: bool = True + if ( isinstance(self.computation, SubroutineCall) and self.computation.output_kwarg @@ -248,10 +251,9 @@ def store_into(self, output: BaseType) -> Expr: self.computation.output_kwarg.abi_type.storage_type(), output._stored_value.storage_type(), ) - else: - require_type(self.computation, output._stored_value.storage_type()) + validate_in_store = False - return output._stored_value.store(self.computation, validate_types=False) + return output._stored_value.store(self.computation, validate_types=validate_in_store) ReturnedValue.__module__ = "pyteal.abi" From 21e9350f74c17dc9dbd3b683c350670e2145613e Mon Sep 17 00:00:00 2001 From: Hang Su Date: Tue, 8 Nov 2022 10:50:40 -0500 Subject: [PATCH 092/157] minor change in type-check in computed-type --- pyteal/ast/abi/type.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index fcdef3c2a..4afef8a70 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -6,7 +6,7 @@ from pyteal.ast.scratchvar import ScratchVar from pyteal.ast.seq import Seq from pyteal.errors import TealInputError -from pyteal.types import TealType, require_type, types_match +from pyteal.types import TealType, types_match class TypeSpec(ABC): @@ -240,6 +240,9 @@ def store_into(self, output: BaseType) -> Expr: f"ABI return subroutine deferred_expr is expected to be typed {output.type_spec().storage_type()}, " f"but has type {declaration.deferred_expr.type_of()}." ) + + validate_in_store: bool = True + if ( isinstance(self.computation, SubroutineCall) and self.computation.output_kwarg @@ -248,10 +251,11 @@ def store_into(self, output: BaseType) -> Expr: self.computation.output_kwarg.abi_type.storage_type(), output._stored_value.storage_type(), ) - else: - require_type(self.computation, output._stored_value.storage_type()) + validate_in_store = False - return output._stored_value.store(self.computation, validate_types=False) + return output._stored_value.store( + self.computation, validate_types=validate_in_store + ) ReturnedValue.__module__ = "pyteal.abi" From b0045ec7fa61eff0569b91bdfc1904d5007aad45 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Tue, 8 Nov 2022 11:28:59 -0500 Subject: [PATCH 093/157] linewidth --- pyteal/ast/frame.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index d299b2db0..04d829286 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -67,8 +67,9 @@ def __init__( raise TealInternalError("Return allocation number should be non-negative.") elif num_return_allocs > len(local_stack_types): raise TealInternalError( - "ProtoStackLayout initialization error:" - f"return allocation number {num_return_allocs} should not be greater than local allocations {len(local_stack_types)}." + "ProtoStackLayout initialization error: " + f"return allocation number {num_return_allocs} should not " + f"be greater than local allocations {len(local_stack_types)}." ) if not all(map(lambda t: t != TealType.none, arg_stack_types)): From 9daee52491ee43908a6c11b323c40174b0e0ba42 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Tue, 8 Nov 2022 13:26:42 -0500 Subject: [PATCH 094/157] some minor comments --- pyteal/ast/abstractvar.py | 14 +++++++++++++ pyteal/ast/frame.py | 44 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/pyteal/ast/abstractvar.py b/pyteal/ast/abstractvar.py index d18a98d70..956d4735f 100644 --- a/pyteal/ast/abstractvar.py +++ b/pyteal/ast/abstractvar.py @@ -4,6 +4,20 @@ class AbstractVar(ABC): + """AbstractVar is an abstract class that captures properties of a variable. + + A variable, on an abstract perspective, has following properties: + + * Storing: can be stored to a certain position. + * Loading: can be loaded from a certain position. + * (Strong) Typed: can indicate its own type. + + ScratchVar and FrameVar inherits from this class, representing the load and storage of value + against scratch slots or stack based on frame pointer. + + This class is intentionally hidden because it's too basic to directly expose. + """ + @abstractmethod def store(self, value: Expr, validate_types: bool = True) -> Expr: pass diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 04d829286..8fd972981 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -14,6 +14,12 @@ class LocalTypeSegment(Expr): + """An expression that allocates stack spaces for local variable. + + This class is intentionally hidden because it's too basic to directly expose. + This is only used in ProtoStackLayout internally. + """ + def __init__(self, local_type: TealType, count: int): super().__init__() self.local_type = local_type @@ -56,6 +62,12 @@ def type_of(self) -> TealType: class ProtoStackLayout(Expr): + """An expression that carrys arg types and local types for a subroutine. + + This class is intentionally hidden because it's too basic to directly expose. + This is only used in Proto internally. + """ + def __init__( self, arg_stack_types: list[TealType], @@ -113,6 +125,12 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc class Proto(Expr): + """An expression that prepare top call frame for a retsub that will assume A args and R return values. + + This class is intentionally hidden because it's too basic to directly expose. + It is only used in subroutine, for subrouine declaration computation. + """ + def __init__( self, num_args: int, @@ -173,6 +191,12 @@ def has_return(self) -> bool: class FrameDig(Expr): + """An expression that digs a value from a position around frame pointer. + + This class is intentionally hidden because it's too basic to directly expose. + his is used only internally by FrameVar. + """ + def __init__(self, frame_index: int, *, inferred_type: Optional[TealType] = None): super().__init__() self.frame_index = frame_index @@ -201,6 +225,12 @@ def has_return(self) -> bool: class FrameBury(Expr): + """An expression that burys a value to a position around frame pointer. + + This class is intentionally hidden because it's too basic to directly expose. + his is used only internally by FrameVar. + """ + def __init__( self, value: Expr, @@ -241,6 +271,14 @@ def has_return(self) -> bool: class FrameVar(AbstractVar): + """An instantiation for AbstractVar based on frame pointer. + + FrameVar captures loading, storing and type of variable over stack by frame pointer. + + This class is intentionally hidden because it's too basic to directly expose. + This is used only internally by SubroutineEval in subroutine declaration computation. + """ + def __init__(self, under_proto: Proto, frame_index: int) -> None: super().__init__() self.proto = under_proto @@ -270,6 +308,12 @@ def load(self) -> Expr: class DupN(Expr): + """Duplicate an expression N times. + + This class is intentionally hidden because it's too basic to directly expose. + This is used only by Proto and LocalTypeSegment. + """ + def __init__(self, value: Expr, repetition: int): super().__init__() require_type(value, TealType.anytype) From 6ef76dd88bbc5d75ff706c41f074ab889bfe0799 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Tue, 8 Nov 2022 15:13:16 -0500 Subject: [PATCH 095/157] revert to framevar version --- pyteal/ast/subroutine.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 50ad7f1e2..c562f7a96 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -9,7 +9,7 @@ from pyteal.ast.expr import Expr from pyteal.ast.seq import Seq from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar, ScratchSlot -from pyteal.ast.frame import FrameDig, Proto, FrameVar, ProtoStackLayout +from pyteal.ast.frame import Proto, FrameVar, ProtoStackLayout from pyteal.errors import TealInputError, TealInternalError, verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.types import TealType @@ -975,7 +975,7 @@ def __var_n_loaded_fp( subroutine.arguments().index(param) - subroutine.argument_count() ) argument_var = None - loaded_var = FrameDig(dig_index) + loaded_var = FrameVar(proto, dig_index).load() return argument_var, loaded_var From 19a1fe2ae68f845a76c3ae704baefb87bf44a5f7 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Tue, 8 Nov 2022 15:59:18 -0500 Subject: [PATCH 096/157] use deferred only on scratch slot --- pyteal/ast/subroutine.py | 3 ++- .../teal/roundtrip/app_roundtrip_()_v8.teal | 2 -- .../app_roundtrip_(bool)[10]_v8.teal | 4 ---- .../roundtrip/app_roundtrip_(bool)_v8.teal | 3 --- ...t64,bool),byte[10],bool[4],uint64)_v8.teal | 13 ---------- .../app_roundtrip_(bool,byte)_v8.teal | 4 ---- ...undtrip_(bool,byte,address,string)_v8.teal | 7 ------ ...yte),uint8)[2],string,bool[]))[]_2_v8.teal | 24 ------------------- ..._(bool,byte,address,string,uint64)_v8.teal | 8 ------- ...app_roundtrip_(bool,uint64,uint32)_v8.teal | 5 ---- .../roundtrip/app_roundtrip_(byte)_v8.teal | 3 --- .../app_roundtrip_(byte,bool,uint64)_v8.teal | 5 ---- ...4],(bool,bool),uint64,address)[]_7_v8.teal | 11 --------- .../roundtrip/app_roundtrip_(uint16)_v8.teal | 3 --- .../app_roundtrip_(uint16,uint8,byte)_v8.teal | 5 ---- .../roundtrip/app_roundtrip_(uint32)_v8.teal | 3 --- ...pp_roundtrip_(uint32,uint16,uint8)_v8.teal | 5 ---- .../roundtrip/app_roundtrip_(uint64)_v8.teal | 3 --- ...p_roundtrip_(uint64,uint32,uint16)_v8.teal | 5 ---- .../roundtrip/app_roundtrip_(uint8)_v8.teal | 3 --- .../app_roundtrip_(uint8,byte,bool)_v8.teal | 5 ---- .../app_roundtrip_address[]_10_v8.teal | 4 ---- .../roundtrip/app_roundtrip_address_v8.teal | 3 --- .../roundtrip/app_roundtrip_bool[1]_v8.teal | 3 --- .../app_roundtrip_bool[3][]_11_v8.teal | 4 ---- .../roundtrip/app_roundtrip_bool[42]_v8.teal | 3 --- .../roundtrip/app_roundtrip_bool[]_0_v8.teal | 2 -- .../roundtrip/app_roundtrip_bool[]_1_v8.teal | 3 --- .../roundtrip/app_roundtrip_bool[]_42_v8.teal | 3 --- .../teal/roundtrip/app_roundtrip_bool_v8.teal | 2 -- .../roundtrip/app_roundtrip_byte[16]_v8.teal | 3 --- .../roundtrip/app_roundtrip_byte[]_36_v8.teal | 3 --- .../teal/roundtrip/app_roundtrip_byte_v8.teal | 2 -- .../roundtrip/app_roundtrip_string_0_v8.teal | 2 -- .../roundtrip/app_roundtrip_string_13_v8.teal | 2 -- .../roundtrip/app_roundtrip_string_1_v8.teal | 2 -- .../roundtrip/app_roundtrip_uint16_v8.teal | 2 -- .../roundtrip/app_roundtrip_uint32_v8.teal | 2 -- .../roundtrip/app_roundtrip_uint64[1]_v8.teal | 3 --- .../app_roundtrip_uint64[42]_v8.teal | 3 --- .../app_roundtrip_uint64[]_0_v8.teal | 2 -- .../app_roundtrip_uint64[]_1_v8.teal | 3 --- .../app_roundtrip_uint64[]_42_v8.teal | 3 --- .../roundtrip/app_roundtrip_uint64_v8.teal | 2 -- .../roundtrip/app_roundtrip_uint8_v8.teal | 2 -- 45 files changed, 2 insertions(+), 185 deletions(-) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index c562f7a96..0b5f03337 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -1052,7 +1052,8 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: f"ABI returning subroutine definition should evaluate to TealType.none, " f"while evaluate to {subroutine_body.type_of()}." ) - deferred_expr = output_carrying_abi._stored_value.load() + if not self.use_frame_pt: + deferred_expr = output_carrying_abi._stored_value.load() # Arg usage "A" to be pick up and store in scratch parameters that have been placed on the stack # need to reverse order of argumentVars because the last argument will be on top of the stack diff --git a/tests/integration/teal/roundtrip/app_roundtrip_()_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_()_v8.teal index 6fc43d729..d0ddb9ccf 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_()_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_()_v8.teal @@ -17,7 +17,6 @@ proto 1 1 byte "" byte "" frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -36,5 +35,4 @@ concat load 3 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v8.teal index 01f03a3df..13296df67 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool)[10]_v8.teal @@ -27,7 +27,6 @@ int 0 load 0 setbit frame_bury 0 -frame_dig 0 retsub // array_complement @@ -154,7 +153,6 @@ concat load 14 concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -173,7 +171,6 @@ concat load 4 concat frame_bury 0 -frame_dig 0 retsub // bool_comp @@ -185,5 +182,4 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool)_v8.teal index 4545cae71..72411884c 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool)_v8.teal @@ -27,7 +27,6 @@ int 0 load 0 setbit frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -46,7 +45,6 @@ concat load 4 concat frame_bury 0 -frame_dig 0 retsub // bool_comp @@ -58,5 +56,4 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v8.teal index 500bd48f0..1875b356a 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,address,(uint64,bool),byte[10],bool[4],uint64)_v8.teal @@ -69,7 +69,6 @@ load 5 itob concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -88,7 +87,6 @@ concat load 9 concat frame_bury 0 -frame_dig 0 retsub // bool_comp @@ -100,7 +98,6 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -115,7 +112,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // array_complement @@ -570,7 +566,6 @@ load 43 setbyte concat frame_bury 0 -frame_dig 0 retsub // tuple_complement @@ -599,7 +594,6 @@ load 11 setbit concat frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -614,7 +608,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // array_complement @@ -761,7 +754,6 @@ load 53 setbyte concat frame_bury 0 -frame_dig 0 retsub // bool_comp @@ -773,7 +765,6 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub // array_complement @@ -822,7 +813,6 @@ int 3 load 57 setbit frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -833,7 +823,6 @@ int 18446744073709551615 frame_dig -1 - frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -844,7 +833,6 @@ int 18446744073709551615 frame_dig -1 - frame_bury 0 -frame_dig 0 retsub // bool_comp @@ -856,5 +844,4 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v8.teal index 93a6c2c3b..c91fe2871 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte)_v8.teal @@ -39,7 +39,6 @@ load 1 setbyte concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -58,7 +57,6 @@ concat load 5 concat frame_bury 0 -frame_dig 0 retsub // bool_comp @@ -70,7 +68,6 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -85,5 +82,4 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v8.teal index 5d4d405aa..dbb2b1b5e 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string)_v8.teal @@ -70,7 +70,6 @@ concat load 13 concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -137,7 +136,6 @@ concat load 10 concat frame_bury 0 -frame_dig 0 retsub // bool_comp @@ -149,7 +147,6 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -164,7 +161,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // numerical_comp @@ -179,7 +175,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // array_complement @@ -634,7 +629,6 @@ load 46 setbyte concat frame_bury 0 -frame_dig 0 retsub // string_reverse @@ -686,5 +680,4 @@ setbyte concat concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v8.teal index 196bf904e..ac2ca105f 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,(address,(uint32,string[],bool[2],(byte),uint8)[2],string,bool[]))[]_2_v8.teal @@ -103,7 +103,6 @@ concat load 28 concat frame_bury 0 -frame_dig 0 retsub // array_complement @@ -232,7 +231,6 @@ load 19 concat concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -299,7 +297,6 @@ concat load 11 concat frame_bury 0 -frame_dig 0 retsub // bool_comp @@ -311,7 +308,6 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -326,7 +322,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // numerical_comp @@ -341,7 +336,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // array_complement @@ -796,7 +790,6 @@ load 61 setbyte concat frame_bury 0 -frame_dig 0 retsub // string_reverse @@ -848,7 +841,6 @@ setbyte concat concat frame_bury 0 -frame_dig 0 retsub // tuple_complement @@ -952,7 +944,6 @@ concat load 73 concat frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -967,7 +958,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // array_complement @@ -1422,7 +1412,6 @@ load 106 setbyte concat frame_bury 0 -frame_dig 0 retsub // tuple_complement @@ -1491,7 +1480,6 @@ concat load 115 concat frame_bury 0 -frame_dig 0 retsub // array_complement @@ -1590,7 +1578,6 @@ concat load 111 concat frame_bury 0 -frame_dig 0 retsub // string_reverse @@ -1642,7 +1629,6 @@ setbyte concat concat frame_bury 0 -frame_dig 0 retsub // bool_comp @@ -1654,7 +1640,6 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub // array_complement @@ -1705,7 +1690,6 @@ load 140 setbit concat frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -1720,7 +1704,6 @@ frame_dig 0 int 4294967296 < assert -frame_dig 0 retsub // string_reverse @@ -1772,7 +1755,6 @@ setbyte concat concat frame_bury 0 -frame_dig 0 retsub // array_complement @@ -1963,7 +1945,6 @@ load 125 concat concat frame_bury 0 -frame_dig 0 retsub // bool_comp @@ -1975,7 +1956,6 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub // array_complement @@ -2004,7 +1984,6 @@ int 1 load 133 setbit frame_bury 0 -frame_dig 0 retsub // tuple_complement @@ -2023,7 +2002,6 @@ int 0 load 113 setbyte frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -2038,7 +2016,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // numerical_comp @@ -2053,5 +2030,4 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v8.teal index 31c7c3c33..ac3980f9e 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,byte,address,string,uint64)_v8.teal @@ -80,7 +80,6 @@ concat load 14 concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -147,7 +146,6 @@ concat load 11 concat frame_bury 0 -frame_dig 0 retsub // bool_comp @@ -159,7 +157,6 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -174,7 +171,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // numerical_comp @@ -189,7 +185,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // array_complement @@ -644,7 +639,6 @@ load 47 setbyte concat frame_bury 0 -frame_dig 0 retsub // string_reverse @@ -696,7 +690,6 @@ setbyte concat concat frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -707,5 +700,4 @@ int 18446744073709551615 frame_dig -1 - frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v8.teal index 0fd41ab36..8f04b8ad0 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(bool,uint64,uint32)_v8.teal @@ -48,7 +48,6 @@ itob extract 4 0 concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -67,7 +66,6 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub // bool_comp @@ -79,7 +77,6 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -90,7 +87,6 @@ int 18446744073709551615 frame_dig -1 - frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -105,5 +101,4 @@ frame_dig 0 int 4294967296 < assert -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(byte)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(byte)_v8.teal index 58b13c2a9..4a8d567ff 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(byte)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(byte)_v8.teal @@ -27,7 +27,6 @@ int 0 load 0 setbyte frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -46,7 +45,6 @@ concat load 4 concat frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -61,5 +59,4 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v8.teal index 833bcf2f8..a5fb0355f 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(byte,bool,uint64)_v8.teal @@ -49,7 +49,6 @@ load 2 itob concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -68,7 +67,6 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -83,7 +81,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // bool_comp @@ -95,7 +92,6 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -106,5 +102,4 @@ int 18446744073709551615 frame_dig -1 - frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v8.teal index a353ed873..064b29fc8 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(byte[4],(bool,bool),uint64,address)[]_7_v8.teal @@ -49,7 +49,6 @@ concat load 3 concat frame_bury 0 -frame_dig 0 retsub // array_complement @@ -160,7 +159,6 @@ load 18 concat concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -227,7 +225,6 @@ concat load 10 concat frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -242,7 +239,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // array_complement @@ -305,7 +301,6 @@ load 25 setbyte concat frame_bury 0 -frame_dig 0 retsub // tuple_complement @@ -334,7 +329,6 @@ int 1 load 21 setbit frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -345,7 +339,6 @@ int 18446744073709551615 frame_dig -1 - frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -360,7 +353,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // array_complement @@ -815,7 +807,6 @@ load 57 setbyte concat frame_bury 0 -frame_dig 0 retsub // bool_comp @@ -827,7 +818,6 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub // bool_comp @@ -839,5 +829,4 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v8.teal index b20aff3b8..3a683e4cf 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint16)_v8.teal @@ -26,7 +26,6 @@ load 0 itob extract 6 0 frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -45,7 +44,6 @@ concat load 4 concat frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -60,5 +58,4 @@ frame_dig 0 int 65536 < assert -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v8.teal index a04b815e8..47ddf0b4c 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint16,uint8,byte)_v8.teal @@ -50,7 +50,6 @@ load 2 setbyte concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -69,7 +68,6 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -84,7 +82,6 @@ frame_dig 0 int 65536 < assert -frame_dig 0 retsub // numerical_comp @@ -99,7 +96,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // numerical_comp @@ -114,5 +110,4 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v8.teal index 608ed547c..a4b6b04a2 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint32)_v8.teal @@ -26,7 +26,6 @@ load 0 itob extract 4 0 frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -45,7 +44,6 @@ concat load 4 concat frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -60,5 +58,4 @@ frame_dig 0 int 4294967296 < assert -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v8.teal index f520db71c..8a165cddc 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint32,uint16,uint8)_v8.teal @@ -49,7 +49,6 @@ load 2 setbyte concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -68,7 +67,6 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -83,7 +81,6 @@ frame_dig 0 int 4294967296 < assert -frame_dig 0 retsub // numerical_comp @@ -98,7 +95,6 @@ frame_dig 0 int 65536 < assert -frame_dig 0 retsub // numerical_comp @@ -113,5 +109,4 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v8.teal index 417770e21..5ba9c63c6 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint64)_v8.teal @@ -24,7 +24,6 @@ store 0 load 0 itob frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -43,7 +42,6 @@ concat load 4 concat frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -54,5 +52,4 @@ int 18446744073709551615 frame_dig -1 - frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v8.teal index 8f2803270..33a5fb36c 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint64,uint32,uint16)_v8.teal @@ -47,7 +47,6 @@ itob extract 6 0 concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -66,7 +65,6 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -77,7 +75,6 @@ int 18446744073709551615 frame_dig -1 - frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -92,7 +89,6 @@ frame_dig 0 int 4294967296 < assert -frame_dig 0 retsub // numerical_comp @@ -107,5 +103,4 @@ frame_dig 0 int 65536 < assert -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v8.teal index 58b13c2a9..4a8d567ff 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint8)_v8.teal @@ -27,7 +27,6 @@ int 0 load 0 setbyte frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -46,7 +45,6 @@ concat load 4 concat frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -61,5 +59,4 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v8.teal index dedc08a8d..853a8b269 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_(uint8,byte,bool)_v8.teal @@ -51,7 +51,6 @@ load 2 setbit concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -70,7 +69,6 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub // numerical_comp @@ -85,7 +83,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // numerical_comp @@ -100,7 +97,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // bool_comp @@ -112,5 +108,4 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v8.teal index 05dff5111..d58d71f84 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_address[]_10_v8.teal @@ -23,7 +23,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // array_complement @@ -478,7 +477,6 @@ load 50 setbyte concat frame_bury 0 -frame_dig 0 retsub // array_complement @@ -631,7 +629,6 @@ load 17 concat concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -698,5 +695,4 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_address_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_address_v8.teal index f71989611..0ebe72b72 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_address_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_address_v8.teal @@ -23,7 +23,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // array_complement @@ -478,7 +477,6 @@ load 35 setbyte concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -497,5 +495,4 @@ concat load 3 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v8.teal index 3acd9d712..3458bde41 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[1]_v8.teal @@ -20,7 +20,6 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub // array_complement @@ -39,7 +38,6 @@ int 0 load 4 setbit frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -58,5 +56,4 @@ concat load 3 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v8.teal index 2fc9c7774..64bd1f049 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[3][]_11_v8.teal @@ -20,7 +20,6 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub // array_complement @@ -59,7 +58,6 @@ int 2 load 22 setbit frame_bury 0 -frame_dig 0 retsub // array_complement @@ -226,7 +224,6 @@ load 18 concat concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -293,5 +290,4 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v8.teal index 5787f99f9..a215df488 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[42]_v8.teal @@ -20,7 +20,6 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub // array_complement @@ -449,7 +448,6 @@ int 41 load 45 setbit frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -468,5 +466,4 @@ concat load 3 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v8.teal index 89f595322..87f935c92 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_0_v8.teal @@ -23,7 +23,6 @@ extract 6 0 byte "" concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -90,5 +89,4 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v8.teal index 61a4806b2..9b403483f 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_1_v8.teal @@ -20,7 +20,6 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub // array_complement @@ -47,7 +46,6 @@ load 8 setbit concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -114,5 +112,4 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v8.teal index 56931159c..a2a6821c4 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool[]_42_v8.teal @@ -20,7 +20,6 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub // array_complement @@ -539,7 +538,6 @@ load 49 setbit concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -606,5 +604,4 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_bool_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_bool_v8.teal index 23e0c659a..5e08ac3d2 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_bool_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_bool_v8.teal @@ -24,7 +24,6 @@ frame_dig -1 ! ! frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -48,5 +47,4 @@ int 2 load 3 setbit frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v8.teal index a8ca32f63..86fa73f5a 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_byte[16]_v8.teal @@ -23,7 +23,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // array_complement @@ -254,7 +253,6 @@ load 19 setbyte concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -273,5 +271,4 @@ concat load 3 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v8.teal index 7aa6b4aad..3b92e3e84 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_byte[]_36_v8.teal @@ -23,7 +23,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // array_complement @@ -612,7 +611,6 @@ setbyte concat concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -679,5 +677,4 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_byte_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_byte_v8.teal index 91cc0024a..c7dfcc09f 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_byte_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_byte_v8.teal @@ -25,7 +25,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // round_tripper @@ -53,5 +52,4 @@ load 3 setbyte concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_0_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_0_v8.teal index c0d9a212c..f6742b7c1 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_string_0_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_string_0_v8.teal @@ -23,7 +23,6 @@ extract 6 0 byte "" concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -90,5 +89,4 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_13_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_13_v8.teal index 742afe0a0..4e608a404 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_string_13_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_string_13_v8.teal @@ -190,7 +190,6 @@ setbyte concat concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -257,5 +256,4 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_string_1_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_string_1_v8.teal index 3e6f669d6..8a72badb8 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_string_1_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_string_1_v8.teal @@ -34,7 +34,6 @@ load 8 setbyte concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -101,5 +100,4 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint16_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint16_v8.teal index 700f8bead..2baecd50a 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint16_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint16_v8.teal @@ -25,7 +25,6 @@ frame_dig 0 int 65536 < assert -frame_dig 0 retsub // round_tripper @@ -50,5 +49,4 @@ itob extract 6 0 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint32_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint32_v8.teal index 00be1ca95..d495dae9d 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint32_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint32_v8.teal @@ -25,7 +25,6 @@ frame_dig 0 int 4294967296 < assert -frame_dig 0 retsub // round_tripper @@ -50,5 +49,4 @@ itob extract 4 0 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v8.teal index 6aa863ad2..48d881ec6 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[1]_v8.teal @@ -19,7 +19,6 @@ int 18446744073709551615 frame_dig -1 - frame_bury 0 -frame_dig 0 retsub // array_complement @@ -38,7 +37,6 @@ store 4 load 4 itob frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -57,5 +55,4 @@ concat load 3 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v8.teal index b995008af..9126983f1 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[42]_v8.teal @@ -19,7 +19,6 @@ int 18446744073709551615 frame_dig -1 - frame_bury 0 -frame_dig 0 retsub // array_complement @@ -530,7 +529,6 @@ load 45 itob concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -549,5 +547,4 @@ concat load 3 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v8.teal index 89f595322..87f935c92 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_0_v8.teal @@ -23,7 +23,6 @@ extract 6 0 byte "" concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -90,5 +89,4 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v8.teal index ce54ebdb6..fb4caf8bd 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_1_v8.teal @@ -19,7 +19,6 @@ int 18446744073709551615 frame_dig -1 - frame_bury 0 -frame_dig 0 retsub // array_complement @@ -46,7 +45,6 @@ load 8 itob concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -113,5 +111,4 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v8.teal index 24dd3f3ff..cf61ff80f 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64[]_42_v8.teal @@ -19,7 +19,6 @@ int 18446744073709551615 frame_dig -1 - frame_bury 0 -frame_dig 0 retsub // array_complement @@ -620,7 +619,6 @@ itob concat concat frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -687,5 +685,4 @@ concat load 6 concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint64_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint64_v8.teal index 165bcb347..ce11171f2 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint64_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint64_v8.teal @@ -20,7 +20,6 @@ int 18446744073709551615 frame_dig -1 - frame_bury 0 -frame_dig 0 retsub // round_tripper @@ -42,5 +41,4 @@ load 3 itob concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file diff --git a/tests/integration/teal/roundtrip/app_roundtrip_uint8_v8.teal b/tests/integration/teal/roundtrip/app_roundtrip_uint8_v8.teal index 91cc0024a..c7dfcc09f 100644 --- a/tests/integration/teal/roundtrip/app_roundtrip_uint8_v8.teal +++ b/tests/integration/teal/roundtrip/app_roundtrip_uint8_v8.teal @@ -25,7 +25,6 @@ frame_dig 0 int 256 < assert -frame_dig 0 retsub // round_tripper @@ -53,5 +52,4 @@ load 3 setbyte concat frame_bury 0 -frame_dig 0 retsub \ No newline at end of file From 431026b7b35401c4fa021a123150cca0c513acf9 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Tue, 8 Nov 2022 17:27:55 -0500 Subject: [PATCH 097/157] use deferred only on scratch slot, comments --- pyteal/ast/subroutine.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 0b5f03337..d4a890f26 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -1045,7 +1045,8 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: deferred_expr: Optional[Expr] = None - # if there is an output keyword argument for ABI, place the storing on the stack + # if there is an output keyword argument for ABI + # place the storing on the stack with deferred expr only when compile to scratch var if output_carrying_abi: if subroutine_body.type_of() != TealType.none: raise TealInputError( From 66a6416a06cc89b1abed278a35ef4855a9c6a1d9 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 9 Nov 2022 21:18:40 -0500 Subject: [PATCH 098/157] spellings --- pyteal/ast/frame.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 8fd972981..32436345c 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -62,7 +62,7 @@ def type_of(self) -> TealType: class ProtoStackLayout(Expr): - """An expression that carrys arg types and local types for a subroutine. + """An expression that carries arg types and local types for a subroutine. This class is intentionally hidden because it's too basic to directly expose. This is only used in Proto internally. @@ -128,7 +128,7 @@ class Proto(Expr): """An expression that prepare top call frame for a retsub that will assume A args and R return values. This class is intentionally hidden because it's too basic to directly expose. - It is only used in subroutine, for subrouine declaration computation. + It is only used in subroutine, for subroutine declaration computation. """ def __init__( @@ -225,7 +225,7 @@ def has_return(self) -> bool: class FrameBury(Expr): - """An expression that burys a value to a position around frame pointer. + """An expression that buries a value to a position around frame pointer. This class is intentionally hidden because it's too basic to directly expose. his is used only internally by FrameVar. From 3bd25faab68b312b0d26a47b6136a67b6a60069e Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 9 Nov 2022 21:23:23 -0500 Subject: [PATCH 099/157] remove unused class methods --- pyteal/ast/abi/type.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index 4afef8a70..c686b705c 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -80,12 +80,6 @@ def __init__(self, spec: TypeSpec) -> None: self._type_spec: Final[TypeSpec] = spec self._stored_value: AbstractVar = ScratchVar(spec.storage_type()) - def _load_value(self) -> Expr: - return self._stored_value.load() - - def _store_value(self, value: Expr) -> Expr: - return self._stored_value.store(value) - def type_spec(self) -> TypeSpec: """Get the TypeSpec for this ABI type instance.""" return self._type_spec From 39f6f6b7e94e099d70243d0cf30e6a50cda3da76 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 9 Nov 2022 21:37:52 -0500 Subject: [PATCH 100/157] remove scratchvar type check in var_n_load --- pyteal/ast/subroutine.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index f3bf83a2c..0a3f200d3 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -9,7 +9,7 @@ from pyteal.ast.expr import Expr from pyteal.ast.seq import Seq from pyteal.ast.scratchvar import DynamicScratchVar, ScratchVar -from pyteal.errors import TealInputError, TealInternalError, verifyProgramVersion +from pyteal.errors import TealInputError, verifyProgramVersion from pyteal.ir import TealOp, Op, TealBlock from pyteal.types import TealType @@ -799,11 +799,7 @@ def var_n_loaded( loaded_var = argument_var elif param in subroutine.abi_args: internal_abi_var = subroutine.abi_args[param].new_instance() - if not isinstance(internal_abi_var._stored_value, ScratchVar): - raise TealInternalError( - "subroutine ABI args must have data schema being ScratchVarStorage" - ) - argument_var = internal_abi_var._stored_value + argument_var = cast(ScratchVar, internal_abi_var._stored_value) loaded_var = internal_abi_var else: argument_var = ScratchVar(TealType.anytype) From bb8f9e560758e9057ff20c6d004f2c65fe6d49c4 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 9 Nov 2022 22:08:51 -0500 Subject: [PATCH 101/157] docstring explanation of validate type --- pyteal/ast/abi/type.py | 2 +- pyteal/ast/abstractvar.py | 21 ++++++++++++++++++++- pyteal/ast/scratchvar.py | 4 ++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index c686b705c..75760015d 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -248,7 +248,7 @@ def store_into(self, output: BaseType) -> Expr: validate_in_store = False return output._stored_value.store( - self.computation, validate_types=validate_in_store + self.computation, validate_type=validate_in_store ) diff --git a/pyteal/ast/abstractvar.py b/pyteal/ast/abstractvar.py index 956d4735f..2c4a6d2df 100644 --- a/pyteal/ast/abstractvar.py +++ b/pyteal/ast/abstractvar.py @@ -19,11 +19,30 @@ class AbstractVar(ABC): """ @abstractmethod - def store(self, value: Expr, validate_types: bool = True) -> Expr: + def store(self, value: Expr, validate_type: bool = True) -> Expr: + """Store value in AbstractVar. + + In most cases, we validate the type of the value to store against the type of the :any:`AbstractVar`. + The *only* case we skip type validation is: + we store a :any:`ReturnValue` of an :code:`ABIReturnSubroutine` into an :any:`AbstractVar`. + An :any:`ABIReturnSubroutine` evaluates to :code:`TealType.none`, + while an :any:`AbstractVar` has any concrete type other than :code:`TealType.none`. + A direct type check against :any:`ABIReturnSubroutine` will incur a type error, + while we apply type check against output keyword argument of :any:`ABIReturnSubroutine`, + which is applied and enforced inside of :any:`ReturnedValue`. + + In short, in most scenarios, it is not recommended to let validate_type to be False, + unless one is very clear about the expected behavior. + + Args: + value: An expression that represents the value to store. + validate_type: A bool variable that activate type check in value storage. + """ pass @abstractmethod def load(self) -> Expr: + """Load value from AbstractVar""" pass @abstractmethod diff --git a/pyteal/ast/scratchvar.py b/pyteal/ast/scratchvar.py index 29a938e33..971b717b0 100644 --- a/pyteal/ast/scratchvar.py +++ b/pyteal/ast/scratchvar.py @@ -37,13 +37,13 @@ def storage_type(self) -> TealType: """Get the type of expressions that can be stored in this ScratchVar.""" return self.type - def store(self, value: Expr, validate_types: bool = True) -> Expr: + def store(self, value: Expr, validate_type: bool = True) -> Expr: """Store value in Scratch Space Args: value: The value to store. Must conform to this ScratchVar's type. """ - if validate_types: + if validate_type: require_type(value, self.type) return self.slot.store(value) From 411c57020e34c641c68494ffef08e9a3ba279936 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Wed, 9 Nov 2022 22:33:21 -0500 Subject: [PATCH 102/157] docstring --- pyteal/ast/frame.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 32436345c..a44711259 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -64,6 +64,9 @@ def type_of(self) -> TealType: class ProtoStackLayout(Expr): """An expression that carries arg types and local types for a subroutine. + Proto return value is placed on frame index 0 against frame pointer, + and return type is included in local_stack_types, which is the first element. + This class is intentionally hidden because it's too basic to directly expose. This is only used in Proto internally. """ @@ -127,6 +130,8 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc class Proto(Expr): """An expression that prepare top call frame for a retsub that will assume A args and R return values. + Proto return value is placed from frame index 0 against frame pointer. + This class is intentionally hidden because it's too basic to directly expose. It is only used in subroutine, for subroutine declaration computation. """ From daf877d8ac5a62f38755d811917d2d0be5fffb16 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Thu, 10 Nov 2022 11:21:17 -0500 Subject: [PATCH 103/157] docstring --- pyteal/ast/abstractvar.py | 4 ++-- pyteal/ast/scratchvar.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pyteal/ast/abstractvar.py b/pyteal/ast/abstractvar.py index 2c4a6d2df..1d3220f11 100644 --- a/pyteal/ast/abstractvar.py +++ b/pyteal/ast/abstractvar.py @@ -29,9 +29,9 @@ def store(self, value: Expr, validate_type: bool = True) -> Expr: while an :any:`AbstractVar` has any concrete type other than :code:`TealType.none`. A direct type check against :any:`ABIReturnSubroutine` will incur a type error, while we apply type check against output keyword argument of :any:`ABIReturnSubroutine`, - which is applied and enforced inside of :any:`ReturnedValue`. + which is applied and enforced inside :any:`ReturnedValue`. - In short, in most scenarios, it is not recommended to let validate_type to be False, + In short, in most scenarios, we do not recommended to let validate_type to be False, unless one is very clear about the expected behavior. Args: diff --git a/pyteal/ast/scratchvar.py b/pyteal/ast/scratchvar.py index 971b717b0..79a5258e9 100644 --- a/pyteal/ast/scratchvar.py +++ b/pyteal/ast/scratchvar.py @@ -42,6 +42,7 @@ def store(self, value: Expr, validate_type: bool = True) -> Expr: Args: value: The value to store. Must conform to this ScratchVar's type. + validate_type: A bool variable that activate type check in value storage. """ if validate_type: require_type(value, self.type) From d8b5eb6b18ed4cdfc48f8ceec2f7da1d67591242 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Thu, 10 Nov 2022 14:55:50 -0500 Subject: [PATCH 104/157] collect changes to basis pr --- pyteal/ast/frame.py | 8 ++++---- pyteal/ast/scratchvar.py | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index a44711259..9145b55b7 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -241,12 +241,12 @@ def __init__( value: Expr, frame_index: int, *, - validate_types: bool = True, + validate_type: bool = True, inferred_type: Optional[TealType] = None, ): super().__init__() - if validate_types: + if validate_type: target_type = inferred_type if inferred_type else TealType.anytype require_type(value, target_type) @@ -297,11 +297,11 @@ def __init__(self, under_proto: Proto, frame_index: int) -> None: def storage_type(self) -> TealType: return self.stack_type - def store(self, value: Expr, validate_types: bool = True) -> Expr: + def store(self, value: Expr, validate_type: bool = True) -> Expr: return FrameBury( value, self.frame_index, - validate_types=validate_types, + validate_type=validate_type, inferred_type=self.stack_type, ) diff --git a/pyteal/ast/scratchvar.py b/pyteal/ast/scratchvar.py index 79a5258e9..c5a6bf9be 100644 --- a/pyteal/ast/scratchvar.py +++ b/pyteal/ast/scratchvar.py @@ -118,11 +118,11 @@ def storage_type(self) -> TealType: """Get the type of expressions that can be stored in this ScratchVar.""" return self.dynamic_type - def store(self, value: Expr, validate_types: bool = True) -> Expr: + def store(self, value: Expr, validate_type: bool = True) -> Expr: """Store the value in the referenced ScratchVar.""" - if not validate_types: + if not validate_type: raise TealInternalError( - f"DynamicScratchVar's must validate_types but {validate_types=}" + f"DynamicScratchVar's must validate_type but {validate_type=}" ) require_type(value, self.dynamic_type) From 935cc0c373279b78fff073f77757d21abde9016d Mon Sep 17 00:00:00 2001 From: Hang Su Date: Thu, 10 Nov 2022 15:00:33 -0500 Subject: [PATCH 105/157] wording check --- pyteal/ast/abstractvar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyteal/ast/abstractvar.py b/pyteal/ast/abstractvar.py index 1d3220f11..962e0366e 100644 --- a/pyteal/ast/abstractvar.py +++ b/pyteal/ast/abstractvar.py @@ -6,7 +6,7 @@ class AbstractVar(ABC): """AbstractVar is an abstract class that captures properties of a variable. - A variable, on an abstract perspective, has following properties: + A variable, on an abstract perspective, has the following properties: * Storing: can be stored to a certain position. * Loading: can be loaded from a certain position. From fe3b60dc139c54850f21ab00ee6dd56378f895ea Mon Sep 17 00:00:00 2001 From: Hang Su Date: Sun, 13 Nov 2022 03:21:39 -0500 Subject: [PATCH 106/157] good find on one more dupped stuff --- pyteal/ast/frame.py | 4 +++- pyteal/ast/frame_test.py | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index 9145b55b7..dc6a0c5f4 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -45,7 +45,9 @@ def __teal__(self, options: "CompileOptions") -> tuple[TealBlock, TealSimpleBloc inst_srt, inst_end = self.auto_instance.__teal__(options) return inst_srt, inst_end else: - dupn_srt, dupn_end = DupN(self.auto_instance, self.count).__teal__(options) + dupn_srt, dupn_end = DupN(self.auto_instance, self.count - 1).__teal__( + options + ) return dupn_srt, dupn_end def __str__(self) -> str: diff --git a/pyteal/ast/frame_test.py b/pyteal/ast/frame_test.py index 3f62ca35b..b5fd1e183 100644 --- a/pyteal/ast/frame_test.py +++ b/pyteal/ast/frame_test.py @@ -150,7 +150,7 @@ class LocalTypeSegmentTestCase: pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.int, 0), - pt.TealOp(None, pt.Op.dupn, 5), + pt.TealOp(None, pt.Op.dupn, 4), ] ), ), @@ -163,7 +163,7 @@ class LocalTypeSegmentTestCase: pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.int, 0), - pt.TealOp(None, pt.Op.dupn, 5), + pt.TealOp(None, pt.Op.dupn, 4), ] ), ), @@ -176,7 +176,7 @@ class LocalTypeSegmentTestCase: pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.byte, '""'), - pt.TealOp(None, pt.Op.dupn, 5), + pt.TealOp(None, pt.Op.dupn, 4), ] ), ), From 55a838a6bccb2ab3a3a726d5cc6c592941bed6c9 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Mon, 14 Nov 2022 12:13:21 -0500 Subject: [PATCH 107/157] per Zeph's PR comments --- pyteal/ast/subroutine.py | 146 +++-------------------------- pyteal/ast/subroutine_test.py | 9 +- tests/abi_roundtrip.py | 7 -- tests/integration/graviton_test.py | 12 +-- 4 files changed, 27 insertions(+), 147 deletions(-) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 312df87e7..ce1d5e129 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -39,7 +39,6 @@ def __init__(self, subroutine_def: "SubroutineDefinition") -> None: self.type_of: Optional[TealType] = None def get_declaration(self) -> "SubroutineDeclaration": - # XXX MARK THIS METHOD TO BE DEPRECATED LATER I GUESS return self.get_declaration_by_version(Op.callsub.min_version) def get_declaration_by_version(self, version: int) -> "SubroutineDeclaration": @@ -337,7 +336,6 @@ def _validate_annotation( ) def get_declaration(self) -> "SubroutineDeclaration": - # XXX MARK THIS METHOD TO BE DEPRECATED LATER I GUESS return self.declarations.get_declaration() def get_declaration_by_version(self, version: int) -> "SubroutineDeclaration": @@ -896,31 +894,30 @@ class SubroutineEval: -------------- --- ------------ ----- ------- - ----------------------- Usage (A) "argumentVars" - Storing pre-placed stack variables with frame pointer: - Type 1. (by-value) use None for we can load from stack with FrameDig() - Type 2. (by-reference) ALSO use FrameDig to pick up from the stack + Type 1. (by-value) use None for we can load from stack with FrameDig() from FrameVar abstraction + Type 2. (by-reference) ALSO use FrameDig() from FrameVar abstraction to pick up from the stack NOTE: SubroutineCall.__teal__() has placed the _SLOT INDEX_ on the stack so this is stored into the local scratch space - Type 3. (ABI) use None for we can load from stack with FrameDig() + Type 3. (ABI) use None for we can load from stack with FrameDig() from FrameVar abstraction NOTE: SubroutineCall.__teal__() has placed the ABI encoding on the stack, so ABI set and get methods are working over stack Type 4. (ABI-output-arg) it is not really used here, but we use FrameDig/Bury to interact with it - TODO need to repolish later after merge and rebase Usage (B) "loadedArgs" - Passing through to an invoked PyTEAL subroutine AST: - Type 1. (by-value) use FrameDig() to have an Expr that can be compiled in python by the PyTEAL subroutine + Type 1. (by-value) use FrameDig() from FrameVar absrraction, to have an Expr that can be compiled in python by the PyTEAL subroutine. Type 2. (by-reference) use a DynamicScratchVar as the user will have written the PyTEAL in a way that satisfies the ScratchVar API. I.e., the user will write `x.load()` and `x.store(val)` as opposed to just `x`. - Type 3. (ABI) use abi_value that interface with stack data through FrameDig/FrameBury - Type 4. (ABI-output-arg) generates a new instance of the ABI value, - and appends a return expression of stored value of the ABI keyword value. + Type 3. (ABI) use abi_value that interface with stack data through FrameVar abstraction. + Type 4. (ABI-output-arg) Prepare a FrameVar over the stack with frame-index 0 against current frame pointer, + and set the ABI value's _stored_value to be using FrameVar. """ - var_n_loaded: Callable[ + var_n_loaded_method: Callable[ [SubroutineDefinition, str, Optional[Proto]], tuple[Optional[ScratchVar], ScratchVar | abi.BaseType | Expr], ] use_frame_pt: bool = False @staticmethod - def __var_n_loaded( + def var_n_loaded_scratch( subroutine: SubroutineDefinition, param: str, _: Optional[Proto] = None, @@ -946,7 +943,7 @@ def __var_n_loaded( return argument_var, loaded_var @staticmethod - def __var_n_loaded_fp( + def var_n_loaded_fp( subroutine: SubroutineDefinition, param: str, proto: Optional[Proto], @@ -1021,7 +1018,7 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: arg_vars: list[ScratchVar] = [] loaded_args: list[ScratchVar | Expr | abi.BaseType] = [] for arg in args: - arg_var, loaded_arg = self.var_n_loaded(subroutine, arg, proto) + arg_var, loaded_arg = self.var_n_loaded_method(subroutine, arg, proto) if arg_var: arg_vars.append(arg_var) loaded_args.append(loaded_arg) @@ -1068,128 +1065,11 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: @classmethod def normal_evaluator(cls) -> "SubroutineEval": - return cls(SubroutineEval.__var_n_loaded, False) + return cls(SubroutineEval.var_n_loaded_scratch, False) @classmethod def fp_evaluator(cls) -> "SubroutineEval": - return cls(SubroutineEval.__var_n_loaded_fp, True) + return cls(SubroutineEval.var_n_loaded_fp, True) SubroutineEval.__module__ = "pyteal" - - -def evaluate_subroutine(subroutine: SubroutineDefinition) -> SubroutineDeclaration: - """ - NOTE: THIS METHOD IS DEPRECATED, USE CLASS `SubroutineEval` INSTEAD FOR SUBROUTINE EVALUATOR - - Puts together the data necessary to define the code for a subroutine. - "evaluate" is used here to connote evaluating the PyTEAL AST into a SubroutineDeclaration, - but not actually placing it at call locations. The trickiest part here is managing the subroutine's arguments. - The arguments are needed for two different code-paths, and there are 2 different argument types to consider - for each of the code-paths: - - 2 Argument Usages / Code-Paths - - -------- ------ ---------- - Usage (A) for run-time: "argumentVars" --reverse--> "body_ops" - These are "store" expressions that pick up parameters that have been pre-placed on the stack prior to subroutine invocation. - The argumentVars are stored into local scratch space to be used by the TEAL subroutine. - - Usage (B) for compile-time: "loadedArgs" - These are expressions supplied to the user-defined PyTEAL function. - The loadedArgs are invoked to by the subroutine to create a self-contained AST which will translate into a TEAL subroutine. - - In both usage cases, we need to handle - - 2 Argument Types - - -------- ----- - Type 1 (by-value): these have python type Expr - Type 2 (by-reference): these have python type ScratchVar - Type 3 (ABI): these are ABI typed variables with scratch space storage, and still pass by value - Type 4 (ABI-output-arg): ABI typed variables with scratch space, a new ABI instance is generated inside function body, - not one of the cases in the previous three options - - Usage (A) "argumentVars" - Storing pre-placed stack variables into local scratch space: - Type 1. (by-value) use ScratchVar.store() to pick the actual value into a local scratch space - Type 2. (by-reference) ALSO use ScratchVar.store() to pick up from the stack - NOTE: SubroutineCall.__teal__() has placed the _SLOT INDEX_ on the stack so this is stored into the local scratch space - Type 3. (ABI) abi_value.stored_value.store() to pick from the stack - Type 4. (ABI-output-arg) it is not really used here, since it is only generated internal of the subroutine - - Usage (B) "loadedArgs" - Passing through to an invoked PyTEAL subroutine AST: - Type 1. (by-value) use ScratchVar.load() to have an Expr that can be compiled in python by the PyTEAL subroutine - Type 2. (by-reference) use a DynamicScratchVar as the user will have written the PyTEAL in a way that satisfies - the ScratchVar API. I.e., the user will write `x.load()` and `x.store(val)` as opposed to just `x`. - Type 3. (ABI) use abi_value itself after storing stack value into scratch space. - Type 4. (ABI-output-arg) generates a new instance of the ABI value, - and appends a return expression of stored value of the ABI keyword value. - """ - - def var_n_loaded( - param: str, - ) -> tuple[ScratchVar, ScratchVar | abi.BaseType | Expr]: - loaded_var: ScratchVar | abi.BaseType | Expr - argument_var: ScratchVar - - if param in subroutine.by_ref_args: - argument_var = DynamicScratchVar(TealType.anytype) - loaded_var = argument_var - elif param in subroutine.abi_args: - internal_abi_var = subroutine.abi_args[param].new_instance() - argument_var = cast(ScratchVar, internal_abi_var._stored_value) - loaded_var = internal_abi_var - else: - argument_var = ScratchVar(TealType.anytype) - loaded_var = argument_var.load() - - return argument_var, loaded_var - - if len(subroutine.output_kwarg) > 1: - raise TealInputError( - f"ABI keyword argument num: {len(subroutine.output_kwarg)}. " - f"Exceeding abi output keyword argument max number 1." - ) - - args = subroutine.arguments() - - arg_vars: list[ScratchVar] = [] - loaded_args: list[ScratchVar | Expr | abi.BaseType] = [] - for arg in args: - arg_var, loaded_arg = var_n_loaded(arg) - arg_vars.append(arg_var) - loaded_args.append(loaded_arg) - - abi_output_kwargs: dict[str, abi.BaseType] = {} - output_kwarg_info = OutputKwArgInfo.from_dict(subroutine.output_kwarg) - output_carrying_abi: Optional[abi.BaseType] = None - - if output_kwarg_info: - output_carrying_abi = output_kwarg_info.abi_type.new_instance() - abi_output_kwargs[output_kwarg_info.name] = output_carrying_abi - - # Arg usage "B" supplied to build an AST from the user-defined PyTEAL function: - subroutine_body = subroutine.implementation(*loaded_args, **abi_output_kwargs) - - if not isinstance(subroutine_body, Expr): - raise TealInputError( - f"Subroutine function does not return a PyTeal expression. Got type {type(subroutine_body)}." - ) - - deferred_expr: Optional[Expr] = None - - # if there is an output keyword argument for ABI, place the storing on the stack - if output_carrying_abi: - if subroutine_body.type_of() != TealType.none: - raise TealInputError( - f"ABI returning subroutine definition should evaluate to TealType.none, " - f"while evaluate to {subroutine_body.type_of()}." - ) - deferred_expr = output_carrying_abi._stored_value.load() - - # Arg usage "A" to be pick up and store in scratch parameters that have been placed on the stack - # need to reverse order of argumentVars because the last argument will be on top of the stack - body_ops = [var.slot.store() for var in arg_vars[::-1]] - body_ops.append(subroutine_body) - - sd = SubroutineDeclaration(subroutine, Seq(body_ops), deferred_expr) - sd.trace = subroutine_body.trace - return sd diff --git a/pyteal/ast/subroutine_test.py b/pyteal/ast/subroutine_test.py index c7b7df03a..935657105 100644 --- a/pyteal/ast/subroutine_test.py +++ b/pyteal/ast/subroutine_test.py @@ -5,7 +5,7 @@ from dataclasses import dataclass import pyteal as pt -from pyteal.ast.subroutine import ABIReturnSubroutine, evaluate_subroutine +from pyteal.ast.subroutine import ABIReturnSubroutine, SubroutineEval options = pt.CompileOptions(version=5) @@ -1153,6 +1153,8 @@ def mySubroutine(): return returnValue definition = pt.SubroutineDefinition(mySubroutine, returnType) + evaluate_subroutine = SubroutineEval.normal_evaluator() + declaration = evaluate_subroutine(definition) assert isinstance(declaration, pt.SubroutineDeclaration) @@ -1187,6 +1189,8 @@ def mySubroutine(a1): return returnValue definition = pt.SubroutineDefinition(mySubroutine, returnType) + + evaluate_subroutine = SubroutineEval.normal_evaluator() declaration = evaluate_subroutine(definition) assert isinstance(declaration, pt.SubroutineDeclaration) @@ -1231,6 +1235,7 @@ def mySubroutine(a1, a2): definition = pt.SubroutineDefinition(mySubroutine, returnType) + evaluate_subroutine = SubroutineEval.normal_evaluator() declaration = evaluate_subroutine(definition) assert isinstance(declaration, pt.SubroutineDeclaration) @@ -1277,6 +1282,8 @@ def mySubroutine(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10): return returnValue definition = pt.SubroutineDefinition(mySubroutine, returnType) + + evaluate_subroutine = SubroutineEval.normal_evaluator() declaration = evaluate_subroutine(definition) assert isinstance(declaration, pt.SubroutineDeclaration) diff --git a/tests/abi_roundtrip.py b/tests/abi_roundtrip.py index ba0f4d8c0..5a2f624dc 100644 --- a/tests/abi_roundtrip.py +++ b/tests/abi_roundtrip.py @@ -128,13 +128,6 @@ def array_comp_factory(self) -> pt.ABIReturnSubroutine: elif self.length is None: self.length = DEFAULT_DYNAMIC_ARRAY_LENGTH - # if self.length is not None: - # assert self.type_spec.is_length_dynamic() # type: ignore[attr-defined] - # elif not self.type_spec.is_length_dynamic(): # type: ignore[attr-defined] - # self.length = self.type_spec.length_static() # type: ignore[attr-defined] - # else: - # self.length = DEFAULT_DYNAMIC_ARRAY_LENGTH - internal_type_spec = self.type_spec.value_type_spec() # type: ignore[attr-defined] internal_ann_inst = internal_type_spec.new_instance() comp_func = ABIRoundtrip(internal_ann_inst, length=None).mutator_factory() diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index 8dd141180..d49332214 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -579,13 +579,13 @@ def square(x): x = 9 args = [x] - def evaluate_and_check(_version: int): + def evaluate_and_check(version: int): # evaluate the programs app_result = PyTealDryRunExecutor(square, Mode.Application).dryrun( - args, compiler_version=_version + args, compiler_version=version ) lsig_result = PyTealDryRunExecutor(square, Mode.Signature).dryrun( - args, compiler_version=_version + args, compiler_version=version ) # check to see that x^2 is at the top of the stack as expected @@ -651,10 +651,10 @@ def euclid(x, y): ) ) - def test_and_report(_verison: int): + def test_and_report(version: int): # assert that each result is that same as what Python's math.gcd() computes inspectors = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( - inputs, compiler_version=_verison + inputs, compiler_version=version ) for i, result in enumerate(inspectors): args = inputs[i] @@ -664,7 +664,7 @@ def test_and_report(_verison: int): # save the CSV to ...current working directory.../euclid_v{version}.csv euclid_csv = DryRunInspector.csv_report(inputs, inspectors) - with open(Path.cwd() / f"euclid_v{_verison}.csv", "w") as f: + with open(Path.cwd() / f"euclid_v{version}.csv", "w") as f: f.write(euclid_csv) test_and_report(6) From f1de3ec553d3133f2556a4ce2aa7d5e76111d852 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Mon, 14 Nov 2022 12:35:13 -0500 Subject: [PATCH 108/157] no overshadowing version param --- tests/integration/abi_roundtrip_test.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/integration/abi_roundtrip_test.py b/tests/integration/abi_roundtrip_test.py index ef611f385..fee247b78 100644 --- a/tests/integration/abi_roundtrip_test.py +++ b/tests/integration/abi_roundtrip_test.py @@ -209,13 +209,13 @@ def test_pure_compilation(abi_type): assert [sdk_abi_type] == abi_arg_types assert algosdk.abi.TupleType([sdk_abi_type] * 3) == abi_ret_type - def compile_and_compare(_version: int): - teal = roundtripper.compile(_version) + def compile_and_compare(version: int): + teal = roundtripper.compile(version) filename = ( f"app_roundtrip_{sdk_abi_type}" + ("" if dynamic_length is None else f"_{dynamic_length}") - + f"_v{_version}.teal" + + f"_v{version}.teal" ) tealdir = GENERATED / "roundtrip" tealdir.mkdir(parents=True, exist_ok=True) @@ -256,8 +256,8 @@ def test_roundtrip(abi_type): rand_abi_instance = abi_strat.get_random() args = (rand_abi_instance,) - def dryrun_roundtrip(_version: int): - inspector = roundtripper.dryrun(args, compiler_version=_version) + def dryrun_roundtrip(version: int): + inspector = roundtripper.dryrun(args, compiler_version=version) cost = inspector.cost() passed = inspector.passed() @@ -265,7 +265,7 @@ def dryrun_roundtrip(_version: int): print( f""" -version={_version} +version={version} {abi_type=} {sdk_abi_str=} {dynamic_length=} From 5cf0cf5077ff4785f18b86db1cc36f31227b5543 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Mon, 14 Nov 2022 17:13:03 -0500 Subject: [PATCH 109/157] type_of subroutinecall --- pyteal/ast/abi/type.py | 20 ++------------------ pyteal/ast/abstractvar.py | 3 +-- pyteal/ast/frame.py | 9 +++------ pyteal/ast/subroutine.py | 3 +++ 4 files changed, 9 insertions(+), 26 deletions(-) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index 75760015d..6abed2d80 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -6,7 +6,7 @@ from pyteal.ast.scratchvar import ScratchVar from pyteal.ast.seq import Seq from pyteal.errors import TealInputError -from pyteal.types import TealType, types_match +from pyteal.types import TealType class TypeSpec(ABC): @@ -216,8 +216,6 @@ def produced_type_spec(self) -> TypeSpec: return self.type_spec def store_into(self, output: BaseType) -> Expr: - from pyteal.ast.subroutine import SubroutineCall - if output.type_spec() != self.produced_type_spec(): raise TealInputError( f"expected type_spec {self.produced_type_spec()} but get {output.type_spec()}" @@ -235,21 +233,7 @@ def store_into(self, output: BaseType) -> Expr: f"but has type {declaration.deferred_expr.type_of()}." ) - validate_in_store: bool = True - - if ( - isinstance(self.computation, SubroutineCall) - and self.computation.output_kwarg - ): - assert types_match( - self.computation.output_kwarg.abi_type.storage_type(), - output._stored_value.storage_type(), - ) - validate_in_store = False - - return output._stored_value.store( - self.computation, validate_type=validate_in_store - ) + return output._stored_value.store(self.computation) ReturnedValue.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abstractvar.py b/pyteal/ast/abstractvar.py index 962e0366e..1cc94b517 100644 --- a/pyteal/ast/abstractvar.py +++ b/pyteal/ast/abstractvar.py @@ -19,7 +19,7 @@ class AbstractVar(ABC): """ @abstractmethod - def store(self, value: Expr, validate_type: bool = True) -> Expr: + def store(self, value: Expr) -> Expr: """Store value in AbstractVar. In most cases, we validate the type of the value to store against the type of the :any:`AbstractVar`. @@ -36,7 +36,6 @@ def store(self, value: Expr, validate_type: bool = True) -> Expr: Args: value: An expression that represents the value to store. - validate_type: A bool variable that activate type check in value storage. """ pass diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index dc6a0c5f4..40c32d3cb 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -243,14 +243,12 @@ def __init__( value: Expr, frame_index: int, *, - validate_type: bool = True, inferred_type: Optional[TealType] = None, ): super().__init__() - if validate_type: - target_type = inferred_type if inferred_type else TealType.anytype - require_type(value, target_type) + target_type = inferred_type if inferred_type else TealType.anytype + require_type(value, target_type) self.value = value self.frame_index = frame_index @@ -299,11 +297,10 @@ def __init__(self, under_proto: Proto, frame_index: int) -> None: def storage_type(self) -> TealType: return self.stack_type - def store(self, value: Expr, validate_type: bool = True) -> Expr: + def store(self, value: Expr) -> Expr: return FrameBury( value, self.frame_index, - validate_type=validate_type, inferred_type=self.stack_type, ) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 0a3f200d3..1695d4547 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -438,6 +438,9 @@ def __str__(self): return f'(SubroutineCall {self.subroutine.name()} ({" ".join(arg_str_list)}))' def type_of(self): + output_info = OutputKwArgInfo.from_dict(self.subroutine.output_kwarg) + if output_info: + return output_info.abi_type.storage_type() return self.subroutine.return_type def has_return(self): From 29be7ff298ebf0ffabf11686beabe67eb528284e Mon Sep 17 00:00:00 2001 From: Hang Su Date: Mon, 14 Nov 2022 17:13:03 -0500 Subject: [PATCH 110/157] type_of subroutinecall --- pyteal/ast/abi/type.py | 20 ++------------------ pyteal/ast/abstractvar.py | 15 +-------------- pyteal/ast/frame.py | 9 +++------ pyteal/ast/subroutine.py | 3 +++ 4 files changed, 9 insertions(+), 38 deletions(-) diff --git a/pyteal/ast/abi/type.py b/pyteal/ast/abi/type.py index 75760015d..6abed2d80 100644 --- a/pyteal/ast/abi/type.py +++ b/pyteal/ast/abi/type.py @@ -6,7 +6,7 @@ from pyteal.ast.scratchvar import ScratchVar from pyteal.ast.seq import Seq from pyteal.errors import TealInputError -from pyteal.types import TealType, types_match +from pyteal.types import TealType class TypeSpec(ABC): @@ -216,8 +216,6 @@ def produced_type_spec(self) -> TypeSpec: return self.type_spec def store_into(self, output: BaseType) -> Expr: - from pyteal.ast.subroutine import SubroutineCall - if output.type_spec() != self.produced_type_spec(): raise TealInputError( f"expected type_spec {self.produced_type_spec()} but get {output.type_spec()}" @@ -235,21 +233,7 @@ def store_into(self, output: BaseType) -> Expr: f"but has type {declaration.deferred_expr.type_of()}." ) - validate_in_store: bool = True - - if ( - isinstance(self.computation, SubroutineCall) - and self.computation.output_kwarg - ): - assert types_match( - self.computation.output_kwarg.abi_type.storage_type(), - output._stored_value.storage_type(), - ) - validate_in_store = False - - return output._stored_value.store( - self.computation, validate_type=validate_in_store - ) + return output._stored_value.store(self.computation) ReturnedValue.__module__ = "pyteal.abi" diff --git a/pyteal/ast/abstractvar.py b/pyteal/ast/abstractvar.py index 962e0366e..0ed9bf9b2 100644 --- a/pyteal/ast/abstractvar.py +++ b/pyteal/ast/abstractvar.py @@ -19,24 +19,11 @@ class AbstractVar(ABC): """ @abstractmethod - def store(self, value: Expr, validate_type: bool = True) -> Expr: + def store(self, value: Expr) -> Expr: """Store value in AbstractVar. - In most cases, we validate the type of the value to store against the type of the :any:`AbstractVar`. - The *only* case we skip type validation is: - we store a :any:`ReturnValue` of an :code:`ABIReturnSubroutine` into an :any:`AbstractVar`. - An :any:`ABIReturnSubroutine` evaluates to :code:`TealType.none`, - while an :any:`AbstractVar` has any concrete type other than :code:`TealType.none`. - A direct type check against :any:`ABIReturnSubroutine` will incur a type error, - while we apply type check against output keyword argument of :any:`ABIReturnSubroutine`, - which is applied and enforced inside :any:`ReturnedValue`. - - In short, in most scenarios, we do not recommended to let validate_type to be False, - unless one is very clear about the expected behavior. - Args: value: An expression that represents the value to store. - validate_type: A bool variable that activate type check in value storage. """ pass diff --git a/pyteal/ast/frame.py b/pyteal/ast/frame.py index dc6a0c5f4..40c32d3cb 100644 --- a/pyteal/ast/frame.py +++ b/pyteal/ast/frame.py @@ -243,14 +243,12 @@ def __init__( value: Expr, frame_index: int, *, - validate_type: bool = True, inferred_type: Optional[TealType] = None, ): super().__init__() - if validate_type: - target_type = inferred_type if inferred_type else TealType.anytype - require_type(value, target_type) + target_type = inferred_type if inferred_type else TealType.anytype + require_type(value, target_type) self.value = value self.frame_index = frame_index @@ -299,11 +297,10 @@ def __init__(self, under_proto: Proto, frame_index: int) -> None: def storage_type(self) -> TealType: return self.stack_type - def store(self, value: Expr, validate_type: bool = True) -> Expr: + def store(self, value: Expr) -> Expr: return FrameBury( value, self.frame_index, - validate_type=validate_type, inferred_type=self.stack_type, ) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 0a3f200d3..1695d4547 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -438,6 +438,9 @@ def __str__(self): return f'(SubroutineCall {self.subroutine.name()} ({" ".join(arg_str_list)}))' def type_of(self): + output_info = OutputKwArgInfo.from_dict(self.subroutine.output_kwarg) + if output_info: + return output_info.abi_type.storage_type() return self.subroutine.return_type def has_return(self): From cd7d52c330136a4b2530160e71ac257cea8b2e82 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Mon, 14 Nov 2022 17:47:14 -0500 Subject: [PATCH 111/157] remove all validate_type --- pyteal/ast/scratchvar.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/pyteal/ast/scratchvar.py b/pyteal/ast/scratchvar.py index c5a6bf9be..a7d8a2dfa 100644 --- a/pyteal/ast/scratchvar.py +++ b/pyteal/ast/scratchvar.py @@ -1,4 +1,4 @@ -from pyteal.errors import TealInputError, TealInternalError +from pyteal.errors import TealInputError from pyteal.types import TealType, require_type from pyteal.ast.abstractvar import AbstractVar @@ -37,15 +37,13 @@ def storage_type(self) -> TealType: """Get the type of expressions that can be stored in this ScratchVar.""" return self.type - def store(self, value: Expr, validate_type: bool = True) -> Expr: + def store(self, value: Expr) -> Expr: """Store value in Scratch Space Args: value: The value to store. Must conform to this ScratchVar's type. - validate_type: A bool variable that activate type check in value storage. """ - if validate_type: - require_type(value, self.type) + require_type(value, self.type) return self.slot.store(value) def load(self) -> ScratchLoad: @@ -118,12 +116,8 @@ def storage_type(self) -> TealType: """Get the type of expressions that can be stored in this ScratchVar.""" return self.dynamic_type - def store(self, value: Expr, validate_type: bool = True) -> Expr: + def store(self, value: Expr) -> Expr: """Store the value in the referenced ScratchVar.""" - if not validate_type: - raise TealInternalError( - f"DynamicScratchVar's must validate_type but {validate_type=}" - ) require_type(value, self.dynamic_type) return ScratchStore(slot=None, value=value, index_expression=self.index()) From dcb90dc3c9021c9903b7074b4d3e6b994667273f Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Mon, 14 Nov 2022 19:51:10 -0600 Subject: [PATCH 112/157] Test identical functionality across versions - just a POC and too slow to merge --- requirements.txt | 2 +- tests/integration/graviton_abi_test.py | 58 +++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/requirements.txt b/requirements.txt index 158039a7b..b5e7cf4a9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/algorand/graviton@v0.5.0 +graviton@git+https://github.com/algorand/graviton@f6e9dfa965afd9588bfaf7325afe5f8c8edafae3 mypy==0.950 pytest==7.2.0 pytest-cov==3.0.0 diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index 0806ee96e..e178fbfdc 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -1,7 +1,9 @@ +from itertools import product import random import pytest -from graviton.blackbox import DryRunInspector +from graviton.blackbox import DryRunInspector, DryRunProperty as DRProp +from graviton.invariant import Invariant, PredicateKind as IQ import pyteal as pt from pyteal.ast.subroutine import ABIReturnSubroutine @@ -300,6 +302,10 @@ def conditional_factorial(_factor: pt.abi.Uint64, *, output: pt.abi.Uint64) -> p # ---- integration test functions ---- # +def pynum_to_int65tuple(n): + return (n >= 0, abs(n)) + + @pytest.mark.parametrize("version", [6, 8]) def test_integer65(version: int): bbpt_subtract_slick = PyTealDryRunExecutor(int65_sub, pt.Mode.Application) @@ -312,9 +318,6 @@ def test_integer65(version: int): bbpt_add = PyTealDryRunExecutor(int65_add, pt.Mode.Application) - def pynum_to_tuple(n): - return (n >= 0, abs(n)) - def pytuple_to_num(t): s, x = t return x if s else -x @@ -323,10 +326,10 @@ def pytuple_to_num(t): random.seed(42) choices = range(-9_999, 10_000) - unary_inputs = [(pynum_to_tuple(x),) for x in random.sample(choices, N)] + unary_inputs = [(pynum_to_int65tuple(x),) for x in random.sample(choices, N)] binary_inputs = [ - (pynum_to_tuple(x), pynum_to_tuple(y)) + (pynum_to_int65tuple(x), pynum_to_int65tuple(y)) for x, y in zip(random.sample(choices, N), random.sample(choices, N)) ] @@ -541,3 +544,46 @@ def test_conditional_factorial(version: int): assert inspector.error(), inspector.report( args, f"FAILED: should error for {n=}", row=n + 1 ) + + +xs = list(map(pynum_to_int65tuple, (-1, 1, 3, 5, 7))) +int65_unary_function_inputs = [(x,) for x in xs] +int65_binary_function_inputs = list(product(xs, xs)) +zs = int65_binary_function_inputs +complex130_unary_function_inputs = [(z,) for z in zs] +complex130_binary_function_inputs = list(product(zs, zs)) +VERSIONING_CASES = [ + (int65_minus_cond, int65_binary_function_inputs), + (int65_sub, int65_binary_function_inputs), + (int65_mult, int65_binary_function_inputs), + (int65_negate, int65_unary_function_inputs), + (int65_add, int65_binary_function_inputs), + (complex130_add, complex130_binary_function_inputs), + (complex130_mult, complex130_binary_function_inputs), + (complex130_real, complex130_unary_function_inputs), + (complex130_imag, complex130_unary_function_inputs), + (complex130_conjugate, complex130_unary_function_inputs), + (complex130_norm_squared, complex130_unary_function_inputs), +] + +IDENTITY_PREDICATES = { + DRProp.lastLog: IQ.IdenticalPair, + DRProp.status: IQ.IdenticalPair, + DRProp.error: IQ.IdenticalPair, + DRProp.lastMessage: IQ.IdenticalPair, +} + +min_version = 5 + + +@pytest.mark.parametrize("subroutine, inputs", VERSIONING_CASES) +@pytest.mark.parametrize("mode", pt.Mode) +@pytest.mark.parametrize("version", range(min_version + 1, pt.MAX_PROGRAM_VERSION + 1)) +def test_identical_functionality(subroutine, inputs, mode, version): + ptdre = PyTealDryRunExecutor(subroutine, mode) + inspectors2 = ptdre.dryrun_on_sequence(inputs, compiler_version=min_version) + inspectorsN = ptdre.dryrun_on_sequence(inputs, compiler_version=version) + + Invariant.full_validation( + IDENTITY_PREDICATES, inspectors=inspectors2, identities=inspectorsN + ) From f3476c56e2e79a365cda425398a1a1574d93f87c Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Mon, 14 Nov 2022 19:55:42 -0600 Subject: [PATCH 113/157] bad alias --- tests/integration/graviton_abi_test.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index e178fbfdc..7b33e4b56 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -3,7 +3,7 @@ import pytest from graviton.blackbox import DryRunInspector, DryRunProperty as DRProp -from graviton.invariant import Invariant, PredicateKind as IQ +from graviton.invariant import Invariant, PredicateKind import pyteal as pt from pyteal.ast.subroutine import ABIReturnSubroutine @@ -567,10 +567,10 @@ def test_conditional_factorial(version: int): ] IDENTITY_PREDICATES = { - DRProp.lastLog: IQ.IdenticalPair, - DRProp.status: IQ.IdenticalPair, - DRProp.error: IQ.IdenticalPair, - DRProp.lastMessage: IQ.IdenticalPair, + DRProp.lastLog: PredicateKind.IdenticalPair, + DRProp.status: PredicateKind.IdenticalPair, + DRProp.error: PredicateKind.IdenticalPair, + DRProp.lastMessage: PredicateKind.IdenticalPair, } min_version = 5 From c9d9aa2a4aef868a4f19328ba74709a6c533db20 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Mon, 14 Nov 2022 21:25:02 -0600 Subject: [PATCH 114/157] handle logic sigs and trace compiled teal in the pt dr executor --- tests/blackbox.py | 29 +++++++++++++++++++++----- tests/integration/graviton_abi_test.py | 20 ++++++++++++------ 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/tests/blackbox.py b/tests/blackbox.py index db5eb97b3..e0b60813e 100644 --- a/tests/blackbox.py +++ b/tests/blackbox.py @@ -1,4 +1,4 @@ -from typing import Callable, Generic, Sequence, TypeVar, cast +from typing import Any, Callable, Generic, Optional, Sequence, TypeVar, cast from dataclasses import dataclass import algosdk.abi @@ -144,8 +144,14 @@ def decorator_blackbox(func: SubroutineFnWrapper | ABIReturnSubroutine): @dataclass(frozen=True) class _MatchMode(Generic[Output]): + runner: Optional["PyTealDryRunExecutor"] app_case: Lazy signature_case: Lazy + trace: Any = None + + def __post_init__(self): + if self.runner and self.trace: + self.runner.add_trace(self.trace) def __call__(self, mode: Mode, *args, **kwargs) -> Output: match mode: @@ -159,6 +165,7 @@ def __call__(self, mode: Mode, *args, **kwargs) -> Output: def mode_to_execution_mode(mode: Mode) -> blackbox.ExecutionMode: return _MatchMode( + runner=None, app_case=lambda: blackbox.ExecutionMode.Application, signature_case=lambda: blackbox.ExecutionMode.Signature, )(mode) @@ -192,6 +199,11 @@ def __init__(self, subr: BlackboxWrapper, mode: Mode): self._pyteal_lambda: Callable[..., Expr] = approval + self.traces: list = [] + + def add_trace(self, trace: Any) -> None: + self.traces.append(trace) + def is_abi(self) -> bool: return isinstance(self.subr.subroutine, ABIReturnSubroutine) @@ -389,6 +401,7 @@ def approval(): def compile(self, version: int, assemble_constants: bool = False) -> str: return _MatchMode( + runner=self, app_case=lambda: compileTeal( self.program(), self.mode, @@ -408,21 +421,24 @@ def dryrun_on_sequence( inputs: list[Sequence[PyTypes]], compiler_version=6, ) -> list[DryRunInspector]: + teal = self.compile(compiler_version) return _MatchMode( + self, app_case=lambda: DryRunExecutor.dryrun_app_on_sequence( algod=algod_with_assertion(), - teal=self.compile(compiler_version), + teal=teal, inputs=inputs, abi_argument_types=self.abi_argument_types(), abi_return_type=self.abi_return_type(), ), signature_case=lambda: DryRunExecutor.dryrun_logicsig_on_sequence( algod=algod_with_assertion(), - teal=self.compile(compiler_version), + teal=teal, inputs=inputs, abi_argument_types=self.abi_argument_types(), abi_return_type=self.abi_return_type(), ), + trace=teal, )(self.mode) def dryrun( @@ -430,19 +446,22 @@ def dryrun( args: Sequence[bytes | str | int], compiler_version=6, ) -> DryRunInspector: + teal = self.compile(compiler_version) return _MatchMode( + self, app_case=lambda: DryRunExecutor.dryrun_app( algod_with_assertion(), - self.compile(compiler_version), + teal, args, self.abi_argument_types(), self.abi_return_type(), ), signature_case=lambda: DryRunExecutor.dryrun_logicsig( algod_with_assertion(), - self.compile(compiler_version), + teal, args, self.abi_argument_types(), self.abi_return_type(), ), + trace=teal, )(self.mode) diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index 7b33e4b56..21c7ccb2e 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -566,13 +566,17 @@ def test_conditional_factorial(version: int): (complex130_norm_squared, complex130_unary_function_inputs), ] -IDENTITY_PREDICATES = { +APP_PREDICATES = { DRProp.lastLog: PredicateKind.IdenticalPair, DRProp.status: PredicateKind.IdenticalPair, DRProp.error: PredicateKind.IdenticalPair, DRProp.lastMessage: PredicateKind.IdenticalPair, } - +LSIG_PREDICATES = { + DRProp.status: PredicateKind.IdenticalPair, + DRProp.error: PredicateKind.IdenticalPair, + DRProp.lastMessage: PredicateKind.IdenticalPair, +} min_version = 5 @@ -581,9 +585,13 @@ def test_conditional_factorial(version: int): @pytest.mark.parametrize("version", range(min_version + 1, pt.MAX_PROGRAM_VERSION + 1)) def test_identical_functionality(subroutine, inputs, mode, version): ptdre = PyTealDryRunExecutor(subroutine, mode) - inspectors2 = ptdre.dryrun_on_sequence(inputs, compiler_version=min_version) + inspectors5 = ptdre.dryrun_on_sequence(inputs, compiler_version=min_version) + teal5 = ptdre.traces[-1] + assert teal5.startswith("#pragma version 5") + inspectorsN = ptdre.dryrun_on_sequence(inputs, compiler_version=version) + tealN = ptdre.traces[-1] + assert tealN.startswith(f"#pragma version {version}") - Invariant.full_validation( - IDENTITY_PREDICATES, inspectors=inspectors2, identities=inspectorsN - ) + preds = APP_PREDICATES if mode == pt.Mode.Application else LSIG_PREDICATES + Invariant.full_validation(preds, inspectors=inspectors5, identities=inspectorsN) From 34ec871c7ef4ad8844fdf9b73d38a23280648445 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Tue, 15 Nov 2022 13:38:00 -0600 Subject: [PATCH 115/157] port identity predicates to graviton_test.py --- requirements.txt | 2 +- tests/integration/graviton_abi_test.py | 1 + tests/integration/graviton_test.py | 139 ++++++++++++++++++++----- 3 files changed, 115 insertions(+), 27 deletions(-) diff --git a/requirements.txt b/requirements.txt index b5e7cf4a9..0a5d03d2f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/algorand/graviton@f6e9dfa965afd9588bfaf7325afe5f8c8edafae3 +graviton@git+https://github.com/algorand/graviton@19959cca5a4ca7aaf4736a21c7c23f2083a54233 mypy==0.950 pytest==7.2.0 pytest-cov==3.0.0 diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index 21c7ccb2e..a39310594 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -580,6 +580,7 @@ def test_conditional_factorial(version: int): min_version = 5 +@pytest.mark.skip("Nice test, but too slow. Good to know that it ran once and passed.") @pytest.mark.parametrize("subroutine, inputs", VERSIONING_CASES) @pytest.mark.parametrize("mode", pt.Mode) @pytest.mark.parametrize("version", range(min_version + 1, pt.MAX_PROGRAM_VERSION + 1)) diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index a9e90095f..6c66ea48d 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -23,7 +23,7 @@ mode_has_property, ) -from graviton.invariant import Invariant +from graviton.invariant import Invariant, PredicateKind PATH = Path.cwd() / "tests" / "integration" FIXTURES = PATH / "teal" @@ -487,6 +487,16 @@ def test_stable_teal_generation(subr, mode): }, } +APP_IDENTITICAL_PREDICATES = { + DRProp.lastLog: PredicateKind.IdenticalPair, + DRProp.status: PredicateKind.IdenticalPair, + DRProp.error: PredicateKind.IdenticalPair, +} +LSIG_IDENTICAL_PREDICATES = { + DRProp.status: PredicateKind.IdenticalPair, + DRProp.error: PredicateKind.IdenticalPair, +} + def blackbox_test_runner( subr: pt.SubroutineFnWrapper, @@ -494,7 +504,7 @@ def blackbox_test_runner( scenario: Dict[str, Any], version: int, assemble_constants: bool = True, -): +) -> list[DryRunInspector]: case_name = subr.name() print(f"blackbox test of {case_name} with mode {mode}") exec_mode = mode_to_execution_mode(mode) @@ -541,6 +551,8 @@ def blackbox_test_runner( print(f"{i+1}. Assertion for {case_name}-{mode}: {dr_prop} <<{predicate}>>") invariant.validates(dr_prop, inspectors) + return inspectors + # ---- Graviton / Blackbox tests ---- # @@ -550,8 +562,14 @@ def test_blackbox_subroutines_as_apps( subr: pt.SubroutineFnWrapper, scenario: Dict[str, Any], ): - blackbox_test_runner(subr, pt.Mode.Application, scenario, 6) - blackbox_test_runner(subr, pt.Mode.Application, scenario, 8) + inspectors6 = blackbox_test_runner(subr, pt.Mode.Application, scenario, 6) + inspectors8 = blackbox_test_runner(subr, pt.Mode.Application, scenario, 8) + Invariant.full_validation( + APP_IDENTITICAL_PREDICATES, + inspectors=inspectors6, + identities=inspectors8, + msg=f"{subr.name()=}", + ) @pytest.mark.parametrize("subr, scenario", LOGICSIG_SCENARIOS.items()) @@ -559,8 +577,14 @@ def test_blackbox_subroutines_as_logic_sigs( subr: pt.SubroutineFnWrapper, scenario: Dict[str, Any], ): - blackbox_test_runner(subr, pt.Mode.Signature, scenario, 6) - blackbox_test_runner(subr, pt.Mode.Signature, scenario, 8) + inspectors6 = blackbox_test_runner(subr, pt.Mode.Signature, scenario, 6) + inspectors8 = blackbox_test_runner(subr, pt.Mode.Signature, scenario, 8) + Invariant.full_validation( + LSIG_IDENTICAL_PREDICATES, + inspectors=inspectors6, + identities=inspectors8, + msg=f"{subr.name()=}", + ) def blackbox_pyteal_example1(): @@ -601,8 +625,22 @@ def evaluate_and_check(version: int): args, "last_log() gave unexpected results from app" ) - evaluate_and_check(6) - evaluate_and_check(8) + return (app_result, lsig_result) + + app6, lsig6 = evaluate_and_check(6) + app8, lsig8 = evaluate_and_check(8) + Invariant.full_validation( + APP_IDENTITICAL_PREDICATES, + inspectors=[app6], + identities=[app8], + msg="Mode.Application example 1", + ) + Invariant.full_validation( + LSIG_IDENTICAL_PREDICATES, + inspectors=[lsig6], + identities=[lsig8], + msg="Mode.Signature example 1", + ) def blackbox_pyteal_example2(): @@ -667,8 +705,16 @@ def test_and_report(version: int): with open(Path.cwd() / f"euclid_v{version}.csv", "w") as f: f.write(euclid_csv) - test_and_report(6) - test_and_report(8) + return inspectors + + inspectors6 = test_and_report(6) + inspectors8 = test_and_report(8) + Invariant.full_validation( + APP_IDENTITICAL_PREDICATES, + inspectors=inspectors6, + identities=inspectors8, + msg="example 2", + ) def blackbox_pyteal_example3(): @@ -739,22 +785,29 @@ def euclid(x, y): ) # Execute on the input sequence to get a dry-run inspectors: - inspectors = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( - inputs + inspectors6 = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( + inputs, compiler_version=6 ) # Assert that each invariant holds on the sequences of inputs and dry-runs: for property, predicate in predicates.items(): - Invariant(predicate).validates(property, inspectors) + Invariant(predicate).validates(property, inspectors6) # Execute on the input sequence to get a dry-run inspectors: - inspectors = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( + inspectors8 = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( inputs, compiler_version=8 ) # Assert that each invariant holds on the sequences of inputs and dry-runs: for property, predicate in predicates.items(): - Invariant(predicate).validates(property, inspectors) + Invariant(predicate).validates(property, inspectors8) + + Invariant.full_validation( + APP_IDENTITICAL_PREDICATES, + inspectors=inspectors6, + identities=inspectors8, + msg="Mode.Application example 3", + ) def blackbox_pyteal_example4(): @@ -856,8 +909,22 @@ def report(kind): report("app") report("lsig") - test_and_report_for_app_and_lsig(6) - test_and_report_for_app_and_lsig(8) + return app_inspectors, lsig_inspectors + + app_inspectors6, lsig_inspectors6 = test_and_report_for_app_and_lsig(6) + app_inspectors8, lsig_inspectors8 = test_and_report_for_app_and_lsig(8) + Invariant.full_validation( + APP_IDENTITICAL_PREDICATES, + inspectors=app_inspectors6, + identities=app_inspectors8, + msg=f"Mode.Application example 4 {abi_sum.name()=}", + ) + Invariant.full_validation( + LSIG_IDENTICAL_PREDICATES, + inspectors=lsig_inspectors6, + identities=lsig_inspectors8, + msg=f"Mode.Signature example 4 {abi_sum.name()=}", + ) def blackbox_pyteal_example5(): @@ -898,9 +965,22 @@ def test_app_and_lsig(_version: int): assert inspect.stack_top() == input_var**3, inspect.report( args=inputs[index], msg="stack_top() gave unexpected results from app" ) - - test_app_and_lsig(6) - test_app_and_lsig(8) + return app_inspect, lsig_inspect + + app6, lsig6 = test_app_and_lsig(6) + app8, lsig8 = test_app_and_lsig(8) + Invariant.full_validation( + APP_IDENTITICAL_PREDICATES, + inspectors=[app6], + identities=[app8], + msg="Mode.Application example 5", + ) + Invariant.full_validation( + LSIG_IDENTICAL_PREDICATES, + inspectors=[lsig6], + identities=[lsig8], + msg="Mode.Application example 5", + ) def blackbox_pyteal_while_continue_test(): @@ -1011,14 +1091,21 @@ def named_tuple_field_access( lsig_pytealer = PyTealDryRunExecutor(named_tuple_field_access, Mode.Signature) args = (False, b"1" * 32, (0, False), b"0" * 10, [True] * 4, 0) - inspector = lsig_pytealer.dryrun(args) + inspector6 = lsig_pytealer.dryrun(args, compiler_version=6) - assert inspector.stack_top() == 1 - assert inspector.passed() + assert inspector6.stack_top() == 1 + assert inspector6.passed() - inspector = lsig_pytealer.dryrun(args, compiler_version=8) - assert inspector.passed() - assert inspector.stack_top() == 1 + inspector8 = lsig_pytealer.dryrun(args, compiler_version=8) + assert inspector8.passed() + assert inspector8.stack_top() == 1 + + Invariant.full_validation( + LSIG_IDENTICAL_PREDICATES, + inspectors=inspector6, + identities=inspector8, + msg="Mode.Signature NamedTuple example", + ) @pytest.mark.parametrize( From 2d2666cef00b6d4bfebcaca0702ec5fd1884e4ae Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Tue, 15 Nov 2022 14:19:29 -0600 Subject: [PATCH 116/157] some examples failing. Might be a red herring, or might be related to how dynamic scratchvars are handled --- requirements.txt | 2 +- tests/integration/graviton_test.py | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/requirements.txt b/requirements.txt index 0a5d03d2f..63e086c3b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/algorand/graviton@19959cca5a4ca7aaf4736a21c7c23f2083a54233 +graviton@git+https://github.com/algorand/graviton@91fe1f6f82b2a75601cf28e94b8bb2b5c7186621 mypy==0.950 pytest==7.2.0 pytest-cov==3.0.0 diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index 6c66ea48d..c893250cc 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -967,19 +967,19 @@ def test_app_and_lsig(_version: int): ) return app_inspect, lsig_inspect - app6, lsig6 = test_app_and_lsig(6) - app8, lsig8 = test_app_and_lsig(8) + app_inspectors6, lsig_inspectors6 = test_app_and_lsig(6) + app_inspectors8, lsig_inspectors8 = test_app_and_lsig(8) Invariant.full_validation( APP_IDENTITICAL_PREDICATES, - inspectors=[app6], - identities=[app8], + inspectors=app_inspectors6, + identities=app_inspectors8, msg="Mode.Application example 5", ) Invariant.full_validation( LSIG_IDENTICAL_PREDICATES, - inspectors=[lsig6], - identities=[lsig8], - msg="Mode.Application example 5", + inspectors=lsig_inspectors6, + identities=lsig_inspectors8, + msg="Mode.Signature example 5", ) @@ -1102,8 +1102,8 @@ def named_tuple_field_access( Invariant.full_validation( LSIG_IDENTICAL_PREDICATES, - inspectors=inspector6, - identities=inspector8, + inspectors=[inspector6], + identities=[inspector8], msg="Mode.Signature NamedTuple example", ) From b7d77a2156fa8372dc6703e7d43c872c49ece253 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Tue, 15 Nov 2022 17:37:34 -0500 Subject: [PATCH 117/157] fixing wrong stack mechanism for dynamic scratch var --- pyteal/ast/subroutine.py | 18 +++++++++++++----- tests/integration/graviton_test.py | 4 ++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index b84be28db..9915d0760 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -1014,12 +1014,12 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: proto = self.__proto(subroutine) args = subroutine.arguments() - arg_vars: list[ScratchVar] = [] + arg_vars: list[tuple[ScratchVar, int]] = [] loaded_args: list[ScratchVar | Expr | abi.BaseType] = [] - for arg in args: + for index, arg in enumerate(args): arg_var, loaded_arg = self.var_n_loaded_method(subroutine, arg, proto) if arg_var: - arg_vars.append(arg_var) + arg_vars.append((arg_var, index - subroutine.argument_count())) loaded_args.append(loaded_arg) abi_output_kwargs: dict[str, abi.BaseType] = {} @@ -1054,9 +1054,17 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: # Arg usage "A" to be pick up and store in scratch parameters that have been placed on the stack # need to reverse order of argumentVars because the last argument will be on top of the stack - body_ops: list[Expr] = [] if not self.use_frame_pt else [proto] - body_ops += [var.slot.store() for var in arg_vars[::-1]] + body_ops: list[Expr] + if not self.use_frame_pt: + body_ops = [var.slot.store() for var, _ in arg_vars[::-1]] + else: + body_ops = [proto] + body_ops += [ + var.slot.store(FrameVar(proto, index).load()) + for var, index in arg_vars[::-1] + ] + body_ops.append(subroutine_body) sd = SubroutineDeclaration(subroutine, Seq(body_ops), deferred_expr) sd.trace = subroutine_body.trace diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index c893250cc..a5284e3f0 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -310,7 +310,7 @@ def test_stable_teal_generation(subr, mode): }, }, slow_fibonacci: { - "inputs": [(i,) for i in range(18)], + "inputs": [(i,) for i in range(17)], "assertions": { DRProp.cost: lambda args: (fib_cost(args) if args[0] < 17 else 70_000), DRProp.lastLog: lambda args: ( @@ -625,7 +625,7 @@ def evaluate_and_check(version: int): args, "last_log() gave unexpected results from app" ) - return (app_result, lsig_result) + return app_result, lsig_result app6, lsig6 = evaluate_and_check(6) app8, lsig8 = evaluate_and_check(8) From 273d304c65fa6fb52f9d3ac82b6a673a4de0792e Mon Sep 17 00:00:00 2001 From: Hang Su Date: Tue, 15 Nov 2022 17:47:32 -0500 Subject: [PATCH 118/157] fixing wrong stack mechanism for dynamic scratch var --- pyteal/ast/subroutine.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index b84be28db..9915d0760 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -1014,12 +1014,12 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: proto = self.__proto(subroutine) args = subroutine.arguments() - arg_vars: list[ScratchVar] = [] + arg_vars: list[tuple[ScratchVar, int]] = [] loaded_args: list[ScratchVar | Expr | abi.BaseType] = [] - for arg in args: + for index, arg in enumerate(args): arg_var, loaded_arg = self.var_n_loaded_method(subroutine, arg, proto) if arg_var: - arg_vars.append(arg_var) + arg_vars.append((arg_var, index - subroutine.argument_count())) loaded_args.append(loaded_arg) abi_output_kwargs: dict[str, abi.BaseType] = {} @@ -1054,9 +1054,17 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: # Arg usage "A" to be pick up and store in scratch parameters that have been placed on the stack # need to reverse order of argumentVars because the last argument will be on top of the stack - body_ops: list[Expr] = [] if not self.use_frame_pt else [proto] - body_ops += [var.slot.store() for var in arg_vars[::-1]] + body_ops: list[Expr] + if not self.use_frame_pt: + body_ops = [var.slot.store() for var, _ in arg_vars[::-1]] + else: + body_ops = [proto] + body_ops += [ + var.slot.store(FrameVar(proto, index).load()) + for var, index in arg_vars[::-1] + ] + body_ops.append(subroutine_body) sd = SubroutineDeclaration(subroutine, Seq(body_ops), deferred_expr) sd.trace = subroutine_body.trace From a55052d44e2394444617633dd26f554a0841c006 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Tue, 15 Nov 2022 19:44:30 -0500 Subject: [PATCH 119/157] rename --- pyteal/ast/subroutine.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pyteal/ast/subroutine.py b/pyteal/ast/subroutine.py index 9915d0760..b5cf797b7 100644 --- a/pyteal/ast/subroutine.py +++ b/pyteal/ast/subroutine.py @@ -1014,12 +1014,14 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: proto = self.__proto(subroutine) args = subroutine.arguments() - arg_vars: list[tuple[ScratchVar, int]] = [] + arg_var_n_frame_index_pairs: list[tuple[ScratchVar, int]] = [] loaded_args: list[ScratchVar | Expr | abi.BaseType] = [] for index, arg in enumerate(args): arg_var, loaded_arg = self.var_n_loaded_method(subroutine, arg, proto) if arg_var: - arg_vars.append((arg_var, index - subroutine.argument_count())) + arg_var_n_frame_index_pairs.append( + (arg_var, index - subroutine.argument_count()) + ) loaded_args.append(loaded_arg) abi_output_kwargs: dict[str, abi.BaseType] = {} @@ -1057,12 +1059,14 @@ def __call__(self, subroutine: SubroutineDefinition) -> SubroutineDeclaration: body_ops: list[Expr] if not self.use_frame_pt: - body_ops = [var.slot.store() for var, _ in arg_vars[::-1]] + body_ops = [ + var.slot.store() for var, _ in arg_var_n_frame_index_pairs[::-1] + ] else: body_ops = [proto] body_ops += [ var.slot.store(FrameVar(proto, index).load()) - for var, index in arg_vars[::-1] + for var, index in arg_var_n_frame_index_pairs[::-1] ] body_ops.append(subroutine_body) From 29cd5897b002259a6e434860a19f5c6965a9952a Mon Sep 17 00:00:00 2001 From: Hang Su Date: Tue, 15 Nov 2022 20:11:21 -0500 Subject: [PATCH 120/157] special case notes --- tests/integration/graviton_test.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index a5284e3f0..470adb1e2 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -310,7 +310,7 @@ def test_stable_teal_generation(subr, mode): }, }, slow_fibonacci: { - "inputs": [(i,) for i in range(17)], + "inputs": [(i,) for i in range(18)], "assertions": { DRProp.cost: lambda args: (fib_cost(args) if args[0] < 17 else 70_000), DRProp.lastLog: lambda args: ( @@ -564,6 +564,15 @@ def test_blackbox_subroutines_as_apps( ): inspectors6 = blackbox_test_runner(subr, pt.Mode.Application, scenario, 6) inspectors8 = blackbox_test_runner(subr, pt.Mode.Application, scenario, 8) + + if subr.name() == "slow_fibonacci": + assert len(inspectors6) == len(inspectors8) == 18 + # NOTE the last case of inspector 8 (compilation with frame pointer) + # does not blow up the 70k budget limit, so we skip specifically for this one. + + del inspectors6[-1] + del inspectors8[-1] + Invariant.full_validation( APP_IDENTITICAL_PREDICATES, inspectors=inspectors6, From e5865647c1fb3922cd73381bbcd06e0f9a004822 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Wed, 16 Nov 2022 12:11:35 -0600 Subject: [PATCH 121/157] fix embarassing spelling --- tests/integration/graviton_test.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index 470adb1e2..e92070f70 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -487,7 +487,7 @@ def test_stable_teal_generation(subr, mode): }, } -APP_IDENTITICAL_PREDICATES = { +APP_IDENTICAL_PREDICATES = { DRProp.lastLog: PredicateKind.IdenticalPair, DRProp.status: PredicateKind.IdenticalPair, DRProp.error: PredicateKind.IdenticalPair, @@ -574,7 +574,7 @@ def test_blackbox_subroutines_as_apps( del inspectors8[-1] Invariant.full_validation( - APP_IDENTITICAL_PREDICATES, + APP_IDENTICAL_PREDICATES, inspectors=inspectors6, identities=inspectors8, msg=f"{subr.name()=}", @@ -639,7 +639,7 @@ def evaluate_and_check(version: int): app6, lsig6 = evaluate_and_check(6) app8, lsig8 = evaluate_and_check(8) Invariant.full_validation( - APP_IDENTITICAL_PREDICATES, + APP_IDENTICAL_PREDICATES, inspectors=[app6], identities=[app8], msg="Mode.Application example 1", @@ -719,7 +719,7 @@ def test_and_report(version: int): inspectors6 = test_and_report(6) inspectors8 = test_and_report(8) Invariant.full_validation( - APP_IDENTITICAL_PREDICATES, + APP_IDENTICAL_PREDICATES, inspectors=inspectors6, identities=inspectors8, msg="example 2", @@ -812,7 +812,7 @@ def euclid(x, y): Invariant(predicate).validates(property, inspectors8) Invariant.full_validation( - APP_IDENTITICAL_PREDICATES, + APP_IDENTICAL_PREDICATES, inspectors=inspectors6, identities=inspectors8, msg="Mode.Application example 3", @@ -923,7 +923,7 @@ def report(kind): app_inspectors6, lsig_inspectors6 = test_and_report_for_app_and_lsig(6) app_inspectors8, lsig_inspectors8 = test_and_report_for_app_and_lsig(8) Invariant.full_validation( - APP_IDENTITICAL_PREDICATES, + APP_IDENTICAL_PREDICATES, inspectors=app_inspectors6, identities=app_inspectors8, msg=f"Mode.Application example 4 {abi_sum.name()=}", @@ -979,7 +979,7 @@ def test_app_and_lsig(_version: int): app_inspectors6, lsig_inspectors6 = test_app_and_lsig(6) app_inspectors8, lsig_inspectors8 = test_app_and_lsig(8) Invariant.full_validation( - APP_IDENTITICAL_PREDICATES, + APP_IDENTICAL_PREDICATES, inspectors=app_inspectors6, identities=app_inspectors8, msg="Mode.Application example 5", From 77ca4a588acf20069fe07d203e751ab8dff813a1 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Wed, 23 Nov 2022 17:49:53 -0600 Subject: [PATCH 122/157] remove run-once forever to be skipped slow test --- tests/integration/graviton_abi_test.py | 56 +------------------------- 1 file changed, 1 insertion(+), 55 deletions(-) diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index a39310594..6b2f8bbce 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -1,9 +1,7 @@ -from itertools import product import random import pytest -from graviton.blackbox import DryRunInspector, DryRunProperty as DRProp -from graviton.invariant import Invariant, PredicateKind +from graviton.blackbox import DryRunInspector import pyteal as pt from pyteal.ast.subroutine import ABIReturnSubroutine @@ -544,55 +542,3 @@ def test_conditional_factorial(version: int): assert inspector.error(), inspector.report( args, f"FAILED: should error for {n=}", row=n + 1 ) - - -xs = list(map(pynum_to_int65tuple, (-1, 1, 3, 5, 7))) -int65_unary_function_inputs = [(x,) for x in xs] -int65_binary_function_inputs = list(product(xs, xs)) -zs = int65_binary_function_inputs -complex130_unary_function_inputs = [(z,) for z in zs] -complex130_binary_function_inputs = list(product(zs, zs)) -VERSIONING_CASES = [ - (int65_minus_cond, int65_binary_function_inputs), - (int65_sub, int65_binary_function_inputs), - (int65_mult, int65_binary_function_inputs), - (int65_negate, int65_unary_function_inputs), - (int65_add, int65_binary_function_inputs), - (complex130_add, complex130_binary_function_inputs), - (complex130_mult, complex130_binary_function_inputs), - (complex130_real, complex130_unary_function_inputs), - (complex130_imag, complex130_unary_function_inputs), - (complex130_conjugate, complex130_unary_function_inputs), - (complex130_norm_squared, complex130_unary_function_inputs), -] - -APP_PREDICATES = { - DRProp.lastLog: PredicateKind.IdenticalPair, - DRProp.status: PredicateKind.IdenticalPair, - DRProp.error: PredicateKind.IdenticalPair, - DRProp.lastMessage: PredicateKind.IdenticalPair, -} -LSIG_PREDICATES = { - DRProp.status: PredicateKind.IdenticalPair, - DRProp.error: PredicateKind.IdenticalPair, - DRProp.lastMessage: PredicateKind.IdenticalPair, -} -min_version = 5 - - -@pytest.mark.skip("Nice test, but too slow. Good to know that it ran once and passed.") -@pytest.mark.parametrize("subroutine, inputs", VERSIONING_CASES) -@pytest.mark.parametrize("mode", pt.Mode) -@pytest.mark.parametrize("version", range(min_version + 1, pt.MAX_PROGRAM_VERSION + 1)) -def test_identical_functionality(subroutine, inputs, mode, version): - ptdre = PyTealDryRunExecutor(subroutine, mode) - inspectors5 = ptdre.dryrun_on_sequence(inputs, compiler_version=min_version) - teal5 = ptdre.traces[-1] - assert teal5.startswith("#pragma version 5") - - inspectorsN = ptdre.dryrun_on_sequence(inputs, compiler_version=version) - tealN = ptdre.traces[-1] - assert tealN.startswith(f"#pragma version {version}") - - preds = APP_PREDICATES if mode == pt.Mode.Application else LSIG_PREDICATES - Invariant.full_validation(preds, inspectors=inspectors5, identities=inspectorsN) From f5ef8194c1b3685b161bf2f0ece8ade2d5e1833f Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Mon, 14 Nov 2022 19:51:10 -0600 Subject: [PATCH 123/157] Test identical functionality across versions - just a POC and too slow to merge --- requirements.txt | 2 +- tests/integration/graviton_abi_test.py | 58 +++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/requirements.txt b/requirements.txt index 158039a7b..b5e7cf4a9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/algorand/graviton@v0.5.0 +graviton@git+https://github.com/algorand/graviton@f6e9dfa965afd9588bfaf7325afe5f8c8edafae3 mypy==0.950 pytest==7.2.0 pytest-cov==3.0.0 diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index 0806ee96e..e178fbfdc 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -1,7 +1,9 @@ +from itertools import product import random import pytest -from graviton.blackbox import DryRunInspector +from graviton.blackbox import DryRunInspector, DryRunProperty as DRProp +from graviton.invariant import Invariant, PredicateKind as IQ import pyteal as pt from pyteal.ast.subroutine import ABIReturnSubroutine @@ -300,6 +302,10 @@ def conditional_factorial(_factor: pt.abi.Uint64, *, output: pt.abi.Uint64) -> p # ---- integration test functions ---- # +def pynum_to_int65tuple(n): + return (n >= 0, abs(n)) + + @pytest.mark.parametrize("version", [6, 8]) def test_integer65(version: int): bbpt_subtract_slick = PyTealDryRunExecutor(int65_sub, pt.Mode.Application) @@ -312,9 +318,6 @@ def test_integer65(version: int): bbpt_add = PyTealDryRunExecutor(int65_add, pt.Mode.Application) - def pynum_to_tuple(n): - return (n >= 0, abs(n)) - def pytuple_to_num(t): s, x = t return x if s else -x @@ -323,10 +326,10 @@ def pytuple_to_num(t): random.seed(42) choices = range(-9_999, 10_000) - unary_inputs = [(pynum_to_tuple(x),) for x in random.sample(choices, N)] + unary_inputs = [(pynum_to_int65tuple(x),) for x in random.sample(choices, N)] binary_inputs = [ - (pynum_to_tuple(x), pynum_to_tuple(y)) + (pynum_to_int65tuple(x), pynum_to_int65tuple(y)) for x, y in zip(random.sample(choices, N), random.sample(choices, N)) ] @@ -541,3 +544,46 @@ def test_conditional_factorial(version: int): assert inspector.error(), inspector.report( args, f"FAILED: should error for {n=}", row=n + 1 ) + + +xs = list(map(pynum_to_int65tuple, (-1, 1, 3, 5, 7))) +int65_unary_function_inputs = [(x,) for x in xs] +int65_binary_function_inputs = list(product(xs, xs)) +zs = int65_binary_function_inputs +complex130_unary_function_inputs = [(z,) for z in zs] +complex130_binary_function_inputs = list(product(zs, zs)) +VERSIONING_CASES = [ + (int65_minus_cond, int65_binary_function_inputs), + (int65_sub, int65_binary_function_inputs), + (int65_mult, int65_binary_function_inputs), + (int65_negate, int65_unary_function_inputs), + (int65_add, int65_binary_function_inputs), + (complex130_add, complex130_binary_function_inputs), + (complex130_mult, complex130_binary_function_inputs), + (complex130_real, complex130_unary_function_inputs), + (complex130_imag, complex130_unary_function_inputs), + (complex130_conjugate, complex130_unary_function_inputs), + (complex130_norm_squared, complex130_unary_function_inputs), +] + +IDENTITY_PREDICATES = { + DRProp.lastLog: IQ.IdenticalPair, + DRProp.status: IQ.IdenticalPair, + DRProp.error: IQ.IdenticalPair, + DRProp.lastMessage: IQ.IdenticalPair, +} + +min_version = 5 + + +@pytest.mark.parametrize("subroutine, inputs", VERSIONING_CASES) +@pytest.mark.parametrize("mode", pt.Mode) +@pytest.mark.parametrize("version", range(min_version + 1, pt.MAX_PROGRAM_VERSION + 1)) +def test_identical_functionality(subroutine, inputs, mode, version): + ptdre = PyTealDryRunExecutor(subroutine, mode) + inspectors2 = ptdre.dryrun_on_sequence(inputs, compiler_version=min_version) + inspectorsN = ptdre.dryrun_on_sequence(inputs, compiler_version=version) + + Invariant.full_validation( + IDENTITY_PREDICATES, inspectors=inspectors2, identities=inspectorsN + ) From 7cddccd3f02a2f58907c06f731d15fae1b4fde1f Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Mon, 14 Nov 2022 19:55:42 -0600 Subject: [PATCH 124/157] bad alias --- tests/integration/graviton_abi_test.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index e178fbfdc..7b33e4b56 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -3,7 +3,7 @@ import pytest from graviton.blackbox import DryRunInspector, DryRunProperty as DRProp -from graviton.invariant import Invariant, PredicateKind as IQ +from graviton.invariant import Invariant, PredicateKind import pyteal as pt from pyteal.ast.subroutine import ABIReturnSubroutine @@ -567,10 +567,10 @@ def test_conditional_factorial(version: int): ] IDENTITY_PREDICATES = { - DRProp.lastLog: IQ.IdenticalPair, - DRProp.status: IQ.IdenticalPair, - DRProp.error: IQ.IdenticalPair, - DRProp.lastMessage: IQ.IdenticalPair, + DRProp.lastLog: PredicateKind.IdenticalPair, + DRProp.status: PredicateKind.IdenticalPair, + DRProp.error: PredicateKind.IdenticalPair, + DRProp.lastMessage: PredicateKind.IdenticalPair, } min_version = 5 From 08a51f29e2d897e5a8b2a4d19d10af42b3e588a0 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Mon, 14 Nov 2022 21:25:02 -0600 Subject: [PATCH 125/157] handle logic sigs and trace compiled teal in the pt dr executor --- tests/blackbox.py | 29 +++++++++++++++++++++----- tests/integration/graviton_abi_test.py | 20 ++++++++++++------ 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/tests/blackbox.py b/tests/blackbox.py index db5eb97b3..e0b60813e 100644 --- a/tests/blackbox.py +++ b/tests/blackbox.py @@ -1,4 +1,4 @@ -from typing import Callable, Generic, Sequence, TypeVar, cast +from typing import Any, Callable, Generic, Optional, Sequence, TypeVar, cast from dataclasses import dataclass import algosdk.abi @@ -144,8 +144,14 @@ def decorator_blackbox(func: SubroutineFnWrapper | ABIReturnSubroutine): @dataclass(frozen=True) class _MatchMode(Generic[Output]): + runner: Optional["PyTealDryRunExecutor"] app_case: Lazy signature_case: Lazy + trace: Any = None + + def __post_init__(self): + if self.runner and self.trace: + self.runner.add_trace(self.trace) def __call__(self, mode: Mode, *args, **kwargs) -> Output: match mode: @@ -159,6 +165,7 @@ def __call__(self, mode: Mode, *args, **kwargs) -> Output: def mode_to_execution_mode(mode: Mode) -> blackbox.ExecutionMode: return _MatchMode( + runner=None, app_case=lambda: blackbox.ExecutionMode.Application, signature_case=lambda: blackbox.ExecutionMode.Signature, )(mode) @@ -192,6 +199,11 @@ def __init__(self, subr: BlackboxWrapper, mode: Mode): self._pyteal_lambda: Callable[..., Expr] = approval + self.traces: list = [] + + def add_trace(self, trace: Any) -> None: + self.traces.append(trace) + def is_abi(self) -> bool: return isinstance(self.subr.subroutine, ABIReturnSubroutine) @@ -389,6 +401,7 @@ def approval(): def compile(self, version: int, assemble_constants: bool = False) -> str: return _MatchMode( + runner=self, app_case=lambda: compileTeal( self.program(), self.mode, @@ -408,21 +421,24 @@ def dryrun_on_sequence( inputs: list[Sequence[PyTypes]], compiler_version=6, ) -> list[DryRunInspector]: + teal = self.compile(compiler_version) return _MatchMode( + self, app_case=lambda: DryRunExecutor.dryrun_app_on_sequence( algod=algod_with_assertion(), - teal=self.compile(compiler_version), + teal=teal, inputs=inputs, abi_argument_types=self.abi_argument_types(), abi_return_type=self.abi_return_type(), ), signature_case=lambda: DryRunExecutor.dryrun_logicsig_on_sequence( algod=algod_with_assertion(), - teal=self.compile(compiler_version), + teal=teal, inputs=inputs, abi_argument_types=self.abi_argument_types(), abi_return_type=self.abi_return_type(), ), + trace=teal, )(self.mode) def dryrun( @@ -430,19 +446,22 @@ def dryrun( args: Sequence[bytes | str | int], compiler_version=6, ) -> DryRunInspector: + teal = self.compile(compiler_version) return _MatchMode( + self, app_case=lambda: DryRunExecutor.dryrun_app( algod_with_assertion(), - self.compile(compiler_version), + teal, args, self.abi_argument_types(), self.abi_return_type(), ), signature_case=lambda: DryRunExecutor.dryrun_logicsig( algod_with_assertion(), - self.compile(compiler_version), + teal, args, self.abi_argument_types(), self.abi_return_type(), ), + trace=teal, )(self.mode) diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index 7b33e4b56..21c7ccb2e 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -566,13 +566,17 @@ def test_conditional_factorial(version: int): (complex130_norm_squared, complex130_unary_function_inputs), ] -IDENTITY_PREDICATES = { +APP_PREDICATES = { DRProp.lastLog: PredicateKind.IdenticalPair, DRProp.status: PredicateKind.IdenticalPair, DRProp.error: PredicateKind.IdenticalPair, DRProp.lastMessage: PredicateKind.IdenticalPair, } - +LSIG_PREDICATES = { + DRProp.status: PredicateKind.IdenticalPair, + DRProp.error: PredicateKind.IdenticalPair, + DRProp.lastMessage: PredicateKind.IdenticalPair, +} min_version = 5 @@ -581,9 +585,13 @@ def test_conditional_factorial(version: int): @pytest.mark.parametrize("version", range(min_version + 1, pt.MAX_PROGRAM_VERSION + 1)) def test_identical_functionality(subroutine, inputs, mode, version): ptdre = PyTealDryRunExecutor(subroutine, mode) - inspectors2 = ptdre.dryrun_on_sequence(inputs, compiler_version=min_version) + inspectors5 = ptdre.dryrun_on_sequence(inputs, compiler_version=min_version) + teal5 = ptdre.traces[-1] + assert teal5.startswith("#pragma version 5") + inspectorsN = ptdre.dryrun_on_sequence(inputs, compiler_version=version) + tealN = ptdre.traces[-1] + assert tealN.startswith(f"#pragma version {version}") - Invariant.full_validation( - IDENTITY_PREDICATES, inspectors=inspectors2, identities=inspectorsN - ) + preds = APP_PREDICATES if mode == pt.Mode.Application else LSIG_PREDICATES + Invariant.full_validation(preds, inspectors=inspectors5, identities=inspectorsN) From 8a84f7363631e49ae5e56ece2b39255a245e6cdb Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Tue, 15 Nov 2022 13:38:00 -0600 Subject: [PATCH 126/157] port identity predicates to graviton_test.py --- requirements.txt | 2 +- tests/integration/graviton_abi_test.py | 1 + tests/integration/graviton_test.py | 139 ++++++++++++++++++++----- 3 files changed, 115 insertions(+), 27 deletions(-) diff --git a/requirements.txt b/requirements.txt index b5e7cf4a9..0a5d03d2f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/algorand/graviton@f6e9dfa965afd9588bfaf7325afe5f8c8edafae3 +graviton@git+https://github.com/algorand/graviton@19959cca5a4ca7aaf4736a21c7c23f2083a54233 mypy==0.950 pytest==7.2.0 pytest-cov==3.0.0 diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index 21c7ccb2e..a39310594 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -580,6 +580,7 @@ def test_conditional_factorial(version: int): min_version = 5 +@pytest.mark.skip("Nice test, but too slow. Good to know that it ran once and passed.") @pytest.mark.parametrize("subroutine, inputs", VERSIONING_CASES) @pytest.mark.parametrize("mode", pt.Mode) @pytest.mark.parametrize("version", range(min_version + 1, pt.MAX_PROGRAM_VERSION + 1)) diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index 31f77bb04..cdd40bc15 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -23,7 +23,7 @@ mode_has_property, ) -from graviton.invariant import Invariant +from graviton.invariant import Invariant, PredicateKind PATH = Path.cwd() / "tests" / "integration" FIXTURES = PATH / "teal" @@ -485,6 +485,16 @@ def test_stable_teal_generation(subr, mode): }, } +APP_IDENTITICAL_PREDICATES = { + DRProp.lastLog: PredicateKind.IdenticalPair, + DRProp.status: PredicateKind.IdenticalPair, + DRProp.error: PredicateKind.IdenticalPair, +} +LSIG_IDENTICAL_PREDICATES = { + DRProp.status: PredicateKind.IdenticalPair, + DRProp.error: PredicateKind.IdenticalPair, +} + def blackbox_test_runner( subr: pt.SubroutineFnWrapper, @@ -492,7 +502,7 @@ def blackbox_test_runner( scenario: Dict[str, Any], version: int, assemble_constants: bool = True, -): +) -> list[DryRunInspector]: case_name = subr.name() print(f"blackbox test of {case_name} with mode {mode}") exec_mode = mode_to_execution_mode(mode) @@ -539,6 +549,8 @@ def blackbox_test_runner( print(f"{i+1}. Assertion for {case_name}-{mode}: {dr_prop} <<{predicate}>>") invariant.validates(dr_prop, inspectors) + return inspectors + # ---- Graviton / Blackbox tests ---- # @@ -548,8 +560,14 @@ def test_blackbox_subroutines_as_apps( subr: pt.SubroutineFnWrapper, scenario: Dict[str, Any], ): - blackbox_test_runner(subr, pt.Mode.Application, scenario, 6) - blackbox_test_runner(subr, pt.Mode.Application, scenario, 8) + inspectors6 = blackbox_test_runner(subr, pt.Mode.Application, scenario, 6) + inspectors8 = blackbox_test_runner(subr, pt.Mode.Application, scenario, 8) + Invariant.full_validation( + APP_IDENTITICAL_PREDICATES, + inspectors=inspectors6, + identities=inspectors8, + msg=f"{subr.name()=}", + ) @pytest.mark.parametrize("subr, scenario", LOGICSIG_SCENARIOS.items()) @@ -557,8 +575,14 @@ def test_blackbox_subroutines_as_logic_sigs( subr: pt.SubroutineFnWrapper, scenario: Dict[str, Any], ): - blackbox_test_runner(subr, pt.Mode.Signature, scenario, 6) - blackbox_test_runner(subr, pt.Mode.Signature, scenario, 8) + inspectors6 = blackbox_test_runner(subr, pt.Mode.Signature, scenario, 6) + inspectors8 = blackbox_test_runner(subr, pt.Mode.Signature, scenario, 8) + Invariant.full_validation( + LSIG_IDENTICAL_PREDICATES, + inspectors=inspectors6, + identities=inspectors8, + msg=f"{subr.name()=}", + ) def blackbox_pyteal_example1(): @@ -599,8 +623,22 @@ def evaluate_and_check(version: int): args, "last_log() gave unexpected results from app" ) - evaluate_and_check(6) - evaluate_and_check(8) + return (app_result, lsig_result) + + app6, lsig6 = evaluate_and_check(6) + app8, lsig8 = evaluate_and_check(8) + Invariant.full_validation( + APP_IDENTITICAL_PREDICATES, + inspectors=[app6], + identities=[app8], + msg="Mode.Application example 1", + ) + Invariant.full_validation( + LSIG_IDENTICAL_PREDICATES, + inspectors=[lsig6], + identities=[lsig8], + msg="Mode.Signature example 1", + ) def blackbox_pyteal_example2(): @@ -665,8 +703,16 @@ def test_and_report(version: int): with open(Path.cwd() / f"euclid_v{version}.csv", "w") as f: f.write(euclid_csv) - test_and_report(6) - test_and_report(8) + return inspectors + + inspectors6 = test_and_report(6) + inspectors8 = test_and_report(8) + Invariant.full_validation( + APP_IDENTITICAL_PREDICATES, + inspectors=inspectors6, + identities=inspectors8, + msg="example 2", + ) def blackbox_pyteal_example3(): @@ -737,22 +783,29 @@ def euclid(x, y): ) # Execute on the input sequence to get a dry-run inspectors: - inspectors = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( - inputs + inspectors6 = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( + inputs, compiler_version=6 ) # Assert that each invariant holds on the sequences of inputs and dry-runs: for property, predicate in predicates.items(): - Invariant(predicate).validates(property, inspectors) + Invariant(predicate).validates(property, inspectors6) # Execute on the input sequence to get a dry-run inspectors: - inspectors = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( + inspectors8 = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( inputs, compiler_version=8 ) # Assert that each invariant holds on the sequences of inputs and dry-runs: for property, predicate in predicates.items(): - Invariant(predicate).validates(property, inspectors) + Invariant(predicate).validates(property, inspectors8) + + Invariant.full_validation( + APP_IDENTITICAL_PREDICATES, + inspectors=inspectors6, + identities=inspectors8, + msg="Mode.Application example 3", + ) def blackbox_pyteal_example4(): @@ -854,8 +907,22 @@ def report(kind): report("app") report("lsig") - test_and_report_for_app_and_lsig(6) - test_and_report_for_app_and_lsig(8) + return app_inspectors, lsig_inspectors + + app_inspectors6, lsig_inspectors6 = test_and_report_for_app_and_lsig(6) + app_inspectors8, lsig_inspectors8 = test_and_report_for_app_and_lsig(8) + Invariant.full_validation( + APP_IDENTITICAL_PREDICATES, + inspectors=app_inspectors6, + identities=app_inspectors8, + msg=f"Mode.Application example 4 {abi_sum.name()=}", + ) + Invariant.full_validation( + LSIG_IDENTICAL_PREDICATES, + inspectors=lsig_inspectors6, + identities=lsig_inspectors8, + msg=f"Mode.Signature example 4 {abi_sum.name()=}", + ) def blackbox_pyteal_example5(): @@ -896,9 +963,22 @@ def test_app_and_lsig(_version: int): assert inspect.stack_top() == input_var**3, inspect.report( args=inputs[index], msg="stack_top() gave unexpected results from app" ) - - test_app_and_lsig(6) - test_app_and_lsig(8) + return app_inspect, lsig_inspect + + app6, lsig6 = test_app_and_lsig(6) + app8, lsig8 = test_app_and_lsig(8) + Invariant.full_validation( + APP_IDENTITICAL_PREDICATES, + inspectors=[app6], + identities=[app8], + msg="Mode.Application example 5", + ) + Invariant.full_validation( + LSIG_IDENTICAL_PREDICATES, + inspectors=[lsig6], + identities=[lsig8], + msg="Mode.Application example 5", + ) def blackbox_pyteal_while_continue_test(): @@ -1009,14 +1089,21 @@ def named_tuple_field_access( lsig_pytealer = PyTealDryRunExecutor(named_tuple_field_access, Mode.Signature) args = (False, b"1" * 32, (0, False), b"0" * 10, [True] * 4, 0) - inspector = lsig_pytealer.dryrun(args) + inspector6 = lsig_pytealer.dryrun(args, compiler_version=6) - assert inspector.stack_top() == 1 - assert inspector.passed() + assert inspector6.stack_top() == 1 + assert inspector6.passed() - inspector = lsig_pytealer.dryrun(args, compiler_version=8) - assert inspector.passed() - assert inspector.stack_top() == 1 + inspector8 = lsig_pytealer.dryrun(args, compiler_version=8) + assert inspector8.passed() + assert inspector8.stack_top() == 1 + + Invariant.full_validation( + LSIG_IDENTICAL_PREDICATES, + inspectors=inspector6, + identities=inspector8, + msg="Mode.Signature NamedTuple example", + ) @pytest.mark.parametrize( From 61d1cc69cebc992f8b81bf73104150d9cd1d2f80 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Tue, 15 Nov 2022 14:19:29 -0600 Subject: [PATCH 127/157] some examples failing. Might be a red herring, or might be related to how dynamic scratchvars are handled fixing wrong stack mechanism for dynamic scratch var fixing wrong stack mechanism for dynamic scratch var rename --- requirements.txt | 2 +- tests/integration/graviton_test.py | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/requirements.txt b/requirements.txt index 0a5d03d2f..63e086c3b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/algorand/graviton@19959cca5a4ca7aaf4736a21c7c23f2083a54233 +graviton@git+https://github.com/algorand/graviton@91fe1f6f82b2a75601cf28e94b8bb2b5c7186621 mypy==0.950 pytest==7.2.0 pytest-cov==3.0.0 diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index cdd40bc15..889343ce7 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -308,7 +308,7 @@ def test_stable_teal_generation(subr, mode): }, }, slow_fibonacci: { - "inputs": [(i,) for i in range(18)], + "inputs": [(i,) for i in range(17)], "assertions": { DRProp.cost: lambda args: (fib_cost(args) if args[0] < 17 else 70_000), DRProp.lastLog: lambda args: ( @@ -623,7 +623,7 @@ def evaluate_and_check(version: int): args, "last_log() gave unexpected results from app" ) - return (app_result, lsig_result) + return app_result, lsig_result app6, lsig6 = evaluate_and_check(6) app8, lsig8 = evaluate_and_check(8) @@ -965,19 +965,19 @@ def test_app_and_lsig(_version: int): ) return app_inspect, lsig_inspect - app6, lsig6 = test_app_and_lsig(6) - app8, lsig8 = test_app_and_lsig(8) + app_inspectors6, lsig_inspectors6 = test_app_and_lsig(6) + app_inspectors8, lsig_inspectors8 = test_app_and_lsig(8) Invariant.full_validation( APP_IDENTITICAL_PREDICATES, - inspectors=[app6], - identities=[app8], + inspectors=app_inspectors6, + identities=app_inspectors8, msg="Mode.Application example 5", ) Invariant.full_validation( LSIG_IDENTICAL_PREDICATES, - inspectors=[lsig6], - identities=[lsig8], - msg="Mode.Application example 5", + inspectors=lsig_inspectors6, + identities=lsig_inspectors8, + msg="Mode.Signature example 5", ) @@ -1100,8 +1100,8 @@ def named_tuple_field_access( Invariant.full_validation( LSIG_IDENTICAL_PREDICATES, - inspectors=inspector6, - identities=inspector8, + inspectors=[inspector6], + identities=[inspector8], msg="Mode.Signature NamedTuple example", ) From 6922ac1a504b9d34c9311735aac4e1231e775fd3 Mon Sep 17 00:00:00 2001 From: Hang Su Date: Tue, 15 Nov 2022 20:11:21 -0500 Subject: [PATCH 128/157] special case notes --- tests/integration/graviton_test.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index 889343ce7..34bf8d86c 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -308,7 +308,7 @@ def test_stable_teal_generation(subr, mode): }, }, slow_fibonacci: { - "inputs": [(i,) for i in range(17)], + "inputs": [(i,) for i in range(18)], "assertions": { DRProp.cost: lambda args: (fib_cost(args) if args[0] < 17 else 70_000), DRProp.lastLog: lambda args: ( @@ -562,6 +562,15 @@ def test_blackbox_subroutines_as_apps( ): inspectors6 = blackbox_test_runner(subr, pt.Mode.Application, scenario, 6) inspectors8 = blackbox_test_runner(subr, pt.Mode.Application, scenario, 8) + + if subr.name() == "slow_fibonacci": + assert len(inspectors6) == len(inspectors8) == 18 + # NOTE the last case of inspector 8 (compilation with frame pointer) + # does not blow up the 70k budget limit, so we skip specifically for this one. + + del inspectors6[-1] + del inspectors8[-1] + Invariant.full_validation( APP_IDENTITICAL_PREDICATES, inspectors=inspectors6, From 64172651e13d8d831fc435bca3c2b77f4345b3ab Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Wed, 16 Nov 2022 12:11:35 -0600 Subject: [PATCH 129/157] fix embarassing spelling --- tests/integration/graviton_test.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index 34bf8d86c..3831e3e7d 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -485,7 +485,7 @@ def test_stable_teal_generation(subr, mode): }, } -APP_IDENTITICAL_PREDICATES = { +APP_IDENTICAL_PREDICATES = { DRProp.lastLog: PredicateKind.IdenticalPair, DRProp.status: PredicateKind.IdenticalPair, DRProp.error: PredicateKind.IdenticalPair, @@ -572,7 +572,7 @@ def test_blackbox_subroutines_as_apps( del inspectors8[-1] Invariant.full_validation( - APP_IDENTITICAL_PREDICATES, + APP_IDENTICAL_PREDICATES, inspectors=inspectors6, identities=inspectors8, msg=f"{subr.name()=}", @@ -637,7 +637,7 @@ def evaluate_and_check(version: int): app6, lsig6 = evaluate_and_check(6) app8, lsig8 = evaluate_and_check(8) Invariant.full_validation( - APP_IDENTITICAL_PREDICATES, + APP_IDENTICAL_PREDICATES, inspectors=[app6], identities=[app8], msg="Mode.Application example 1", @@ -717,7 +717,7 @@ def test_and_report(version: int): inspectors6 = test_and_report(6) inspectors8 = test_and_report(8) Invariant.full_validation( - APP_IDENTITICAL_PREDICATES, + APP_IDENTICAL_PREDICATES, inspectors=inspectors6, identities=inspectors8, msg="example 2", @@ -810,7 +810,7 @@ def euclid(x, y): Invariant(predicate).validates(property, inspectors8) Invariant.full_validation( - APP_IDENTITICAL_PREDICATES, + APP_IDENTICAL_PREDICATES, inspectors=inspectors6, identities=inspectors8, msg="Mode.Application example 3", @@ -921,7 +921,7 @@ def report(kind): app_inspectors6, lsig_inspectors6 = test_and_report_for_app_and_lsig(6) app_inspectors8, lsig_inspectors8 = test_and_report_for_app_and_lsig(8) Invariant.full_validation( - APP_IDENTITICAL_PREDICATES, + APP_IDENTICAL_PREDICATES, inspectors=app_inspectors6, identities=app_inspectors8, msg=f"Mode.Application example 4 {abi_sum.name()=}", @@ -977,7 +977,7 @@ def test_app_and_lsig(_version: int): app_inspectors6, lsig_inspectors6 = test_app_and_lsig(6) app_inspectors8, lsig_inspectors8 = test_app_and_lsig(8) Invariant.full_validation( - APP_IDENTITICAL_PREDICATES, + APP_IDENTICAL_PREDICATES, inspectors=app_inspectors6, identities=app_inspectors8, msg="Mode.Application example 5", From b4d930064b294db6c74d450e2e501ce685335bea Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Wed, 23 Nov 2022 17:49:53 -0600 Subject: [PATCH 130/157] remove run-once forever to be skipped slow test --- tests/integration/graviton_abi_test.py | 56 +------------------------- 1 file changed, 1 insertion(+), 55 deletions(-) diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index a39310594..6b2f8bbce 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -1,9 +1,7 @@ -from itertools import product import random import pytest -from graviton.blackbox import DryRunInspector, DryRunProperty as DRProp -from graviton.invariant import Invariant, PredicateKind +from graviton.blackbox import DryRunInspector import pyteal as pt from pyteal.ast.subroutine import ABIReturnSubroutine @@ -544,55 +542,3 @@ def test_conditional_factorial(version: int): assert inspector.error(), inspector.report( args, f"FAILED: should error for {n=}", row=n + 1 ) - - -xs = list(map(pynum_to_int65tuple, (-1, 1, 3, 5, 7))) -int65_unary_function_inputs = [(x,) for x in xs] -int65_binary_function_inputs = list(product(xs, xs)) -zs = int65_binary_function_inputs -complex130_unary_function_inputs = [(z,) for z in zs] -complex130_binary_function_inputs = list(product(zs, zs)) -VERSIONING_CASES = [ - (int65_minus_cond, int65_binary_function_inputs), - (int65_sub, int65_binary_function_inputs), - (int65_mult, int65_binary_function_inputs), - (int65_negate, int65_unary_function_inputs), - (int65_add, int65_binary_function_inputs), - (complex130_add, complex130_binary_function_inputs), - (complex130_mult, complex130_binary_function_inputs), - (complex130_real, complex130_unary_function_inputs), - (complex130_imag, complex130_unary_function_inputs), - (complex130_conjugate, complex130_unary_function_inputs), - (complex130_norm_squared, complex130_unary_function_inputs), -] - -APP_PREDICATES = { - DRProp.lastLog: PredicateKind.IdenticalPair, - DRProp.status: PredicateKind.IdenticalPair, - DRProp.error: PredicateKind.IdenticalPair, - DRProp.lastMessage: PredicateKind.IdenticalPair, -} -LSIG_PREDICATES = { - DRProp.status: PredicateKind.IdenticalPair, - DRProp.error: PredicateKind.IdenticalPair, - DRProp.lastMessage: PredicateKind.IdenticalPair, -} -min_version = 5 - - -@pytest.mark.skip("Nice test, but too slow. Good to know that it ran once and passed.") -@pytest.mark.parametrize("subroutine, inputs", VERSIONING_CASES) -@pytest.mark.parametrize("mode", pt.Mode) -@pytest.mark.parametrize("version", range(min_version + 1, pt.MAX_PROGRAM_VERSION + 1)) -def test_identical_functionality(subroutine, inputs, mode, version): - ptdre = PyTealDryRunExecutor(subroutine, mode) - inspectors5 = ptdre.dryrun_on_sequence(inputs, compiler_version=min_version) - teal5 = ptdre.traces[-1] - assert teal5.startswith("#pragma version 5") - - inspectorsN = ptdre.dryrun_on_sequence(inputs, compiler_version=version) - tealN = ptdre.traces[-1] - assert tealN.startswith(f"#pragma version {version}") - - preds = APP_PREDICATES if mode == pt.Mode.Application else LSIG_PREDICATES - Invariant.full_validation(preds, inspectors=inspectors5, identities=inspectorsN) From 72a749025241f231ef21710129d71d0f5b0a98f4 Mon Sep 17 00:00:00 2001 From: Hang Su <87964331+ahangsu@users.noreply.github.com> Date: Fri, 2 Dec 2022 22:18:05 -0500 Subject: [PATCH 131/157] update test comment --- tests/integration/graviton_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index 3831e3e7d..823e1cb7a 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -565,7 +565,7 @@ def test_blackbox_subroutines_as_apps( if subr.name() == "slow_fibonacci": assert len(inspectors6) == len(inspectors8) == 18 - # NOTE the last case of inspector 8 (compilation with frame pointer) + # NOTE! the last case of inspector 8 (slow_fibonacci compilation with frame pointer) # does not blow up the 70k budget limit, so we skip specifically for this one. del inspectors6[-1] From 9df2c7bebf1a3a7e0c5aace091bd58978fcf5f9a Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Tue, 6 Dec 2022 11:07:41 +0200 Subject: [PATCH 132/157] revert - except for better local function name --- tests/integration/graviton_abi_test.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index 6011ea26b..079bbafce 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -312,6 +312,9 @@ def test_integer65(version: int): bbpt_add = PyTealDryRunExecutor(int65_add, pt.Mode.Application) + def pynum_to_int65tuple(n): + return (n >= 0, abs(n)) + def pytuple_to_num(t): s, x = t return x if s else -x From 4451f3dbf8553512810b1b35710f457096a834c0 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Tue, 6 Dec 2022 11:18:19 +0200 Subject: [PATCH 133/157] Apply suggestions from code review --- tests/integration/graviton_abi_test.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index d613ad444..e827b545f 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -300,10 +300,6 @@ def conditional_factorial(_factor: pt.abi.Uint64, *, output: pt.abi.Uint64) -> p # ---- integration test functions ---- # -def pynum_to_int65tuple(n): - return (n >= 0, abs(n)) - - @pytest.mark.parametrize("version", [6, 8]) def test_integer65(version: int): bbpt_subtract_slick = PyTealDryRunExecutor(int65_sub, pt.Mode.Application) @@ -318,7 +314,6 @@ def test_integer65(version: int): def pynum_to_int65tuple(n): return (n >= 0, abs(n)) - def pytuple_to_num(t): s, x = t return x if s else -x From 2f7a7ac5edd6a7e1cdd07de069d04b347aad9726 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Tue, 6 Dec 2022 11:24:57 +0200 Subject: [PATCH 134/157] black --- tests/integration/graviton_abi_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index e827b545f..cdd6d417b 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -314,6 +314,7 @@ def test_integer65(version: int): def pynum_to_int65tuple(n): return (n >= 0, abs(n)) + def pytuple_to_num(t): s, x = t return x if s else -x From f9aebde355627b0ff18b2ab8cb93f72d26be3fd7 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Tue, 6 Dec 2022 11:26:37 +0200 Subject: [PATCH 135/157] unused var --- tests/integration/graviton_test.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index c2ee65f45..e4350207b 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -818,11 +818,6 @@ def euclid(x, y): msg="Mode.Application example 3", ) - # Execute on the input sequence to get a dry-run inspectors: - inspectors = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( - inputs, compiler_version=8 - ) - # Assert that each invariant holds on the sequences of inputs and dry-runs: for property, predicate in predicates.items(): Invariant(predicate).validates(property, inspectors8) From 4d45f09af7c2067532485e038f11fb81ec6189b8 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Wed, 14 Dec 2022 12:40:32 +0200 Subject: [PATCH 136/157] Update requirements.txt Co-authored-by: Hang Su <87964331+ahangsu@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 63e086c3b..043a9cbf2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/algorand/graviton@91fe1f6f82b2a75601cf28e94b8bb2b5c7186621 +graviton@git+https://github.com/algorand/graviton@v0.6.0 mypy==0.950 pytest==7.2.0 pytest-cov==3.0.0 From 5b4ae3358da3790063dec40a8bb49fabbb79f2eb Mon Sep 17 00:00:00 2001 From: michaeldiamant Date: Thu, 22 Dec 2022 09:42:12 -0500 Subject: [PATCH 137/157] Prove no assertions tested --- tests/integration/graviton_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index 31f77bb04..472ef4ce9 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -513,6 +513,7 @@ def blackbox_test_runner( inputs, predicates = Invariant.inputs_and_invariants( scenario, exec_mode, raw_predicates=True ) + assert predicates, "Must configure >= 1 predicate" # 3. execute dry run sequence: execute = DryRunExecutor.execute_one_dryrun From 3b20a2102b71112bdf038d584b98c5344cf33f99 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Thu, 22 Dec 2022 20:00:37 -0600 Subject: [PATCH 138/157] get the tests to actually run, and nudge invariants to pass both with/out frame pointers --- requirements.txt | 2 +- tests/integration/graviton_test.py | 142 +++++++++++------------------ 2 files changed, 54 insertions(+), 90 deletions(-) diff --git a/requirements.txt b/requirements.txt index 61515780d..08815e16c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/algorand/graviton@v0.6.0 +graviton@git+https://github.com/algorand/graviton@f6f301a5da784cb7d6a38c59745879eb624fa622 mypy==0.991 pytest==7.2.0 pytest-cov==3.0.0 diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index 3a6c93e0e..d69a59037 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -137,13 +137,6 @@ def fib(n): return a -def fib_cost(args): - cost = 17 - for n in range(1, args[0] + 1): - cost += 31 * fib(n - 1) - return cost - - # ---- Blackbox pure unit tests (Skipping for now due to flakiness) ---- # @@ -176,7 +169,7 @@ def test_stable_teal_generation(subr, mode): "inputs": [()], # since only a single input, just assert a constant in each case "assertions": { - DRProp.cost: 11, + DRProp.cost: lambda _, actual: actual in {11, 12}, # int assertions on log outputs need encoding to varuint-hex: DRProp.lastLog: Encoder.hex(2**10), # dicts have a special meaning as assertions. So in the case of "finalScratch" @@ -193,7 +186,7 @@ def test_stable_teal_generation(subr, mode): square_byref: { "inputs": [(i,) for i in range(100)], "assertions": { - DRProp.cost: lambda _, actual: 20 < actual < 22, + DRProp.cost: lambda _, actual: 20 < actual < 24, DRProp.lastLog: Encoder.hex(1337), # due to dry-run artifact of not reporting 0-valued scratchvars, # we have a special case for n=0: @@ -201,7 +194,7 @@ def test_stable_teal_generation(subr, mode): {1, 1337, (args[0] ** 2 if args[0] else 1)} ).issubset(set(actual.values())), DRProp.stackTop: 1337, - DRProp.maxStackHeight: 3, + DRProp.maxStackHeight: lambda _, actual: actual in [3, 4], DRProp.status: "PASS", DRProp.passed: True, DRProp.rejected: False, @@ -214,14 +207,14 @@ def test_stable_teal_generation(subr, mode): DRProp.cost: 14, DRProp.lastLog: { # since execution REJECTS for 0, expect last log for this case to be None - (i,): Encoder.hex(i * i) if i else None + (i,): Encoder.hex(i * i) for i in range(100) }, DRProp.finalScratch: lambda args: ( {0: args[0] ** 2, 1: args[0]} if args[0] else {} ), DRProp.stackTop: lambda args: args[0] ** 2, - DRProp.maxStackHeight: 2, + DRProp.maxStackHeight: lambda _, actual: actual in range(2, 5), DRProp.status: lambda i: "PASS" if i[0] > 0 else "REJECT", DRProp.passed: lambda i: i[0] > 0, DRProp.rejected: lambda i: i[0] == 0, @@ -231,7 +224,7 @@ def test_stable_teal_generation(subr, mode): swap: { "inputs": [(1, 2), (1, "two"), ("one", 2), ("one", "two")], "assertions": { - DRProp.cost: 27, + DRProp.cost: lambda _, actual: actual in [27, 30], DRProp.lastLog: Encoder.hex(1337), DRProp.finalScratch: lambda args: { 0: 1337, @@ -242,7 +235,7 @@ def test_stable_teal_generation(subr, mode): 5: Encoder.hex0x(args[0]), }, DRProp.stackTop: 1337, - DRProp.maxStackHeight: 2, + DRProp.maxStackHeight: lambda _, actual: actual in [2, 4], DRProp.status: "PASS", DRProp.passed: True, DRProp.rejected: False, @@ -252,10 +245,7 @@ def test_stable_teal_generation(subr, mode): string_mult: { "inputs": [("xyzw", i) for i in range(100)], "assertions": { - DRProp.cost: lambda args: 30 + 15 * args[1], - DRProp.lastLog: ( - lambda args: Encoder.hex(args[0] * args[1]) if args[1] else None - ), + DRProp.lastLog: (lambda args: Encoder.hex(args[0] * args[1])), # due to dryrun 0-scratchvar artifact, special case for i == 0: DRProp.finalScratch: lambda args: ( { @@ -274,7 +264,6 @@ def test_stable_teal_generation(subr, mode): } ), DRProp.stackTop: lambda args: len(args[0] * args[1]), - DRProp.maxStackHeight: lambda args: 3 if args[1] else 2, DRProp.status: lambda args: ("PASS" if 0 < args[1] < 45 else "REJECT"), DRProp.passed: lambda args: 0 < args[1] < 45, DRProp.rejected: lambda args: 0 >= args[1] or args[1] >= 45, @@ -284,9 +273,6 @@ def test_stable_teal_generation(subr, mode): oldfac: { "inputs": [(i,) for i in range(25)], "assertions": { - DRProp.cost: lambda args, actual: ( - actual - 40 <= 17 * args[0] <= actual + 40 - ), DRProp.lastLog: lambda args: ( Encoder.hex(fac_with_overflow(args[0])) if args[0] < 21 else None ), @@ -300,7 +286,6 @@ def test_stable_teal_generation(subr, mode): ) ), DRProp.stackTop: lambda args: fac_with_overflow(args[0]), - DRProp.maxStackHeight: lambda args: max(2, 2 * args[0]), DRProp.status: lambda args: "PASS" if args[0] < 21 else "REJECT", DRProp.passed: lambda args: args[0] < 21, DRProp.rejected: lambda args: args[0] >= 21, @@ -310,11 +295,10 @@ def test_stable_teal_generation(subr, mode): }, }, slow_fibonacci: { - "inputs": [(i,) for i in range(18)], + "inputs": [(i,) for i in range(17)], "assertions": { - DRProp.cost: lambda args: (fib_cost(args) if args[0] < 17 else 70_000), - DRProp.lastLog: lambda args: ( - Encoder.hex(fib(args[0])) if 0 < args[0] < 17 else None + DRProp.lastLog: lambda args, actual: ( + Encoder.hex(fib(args[0])) == actual if 0 <= args[0] < 17 else True ), DRProp.finalScratch: lambda args, actual: ( actual == {1: args[0], 0: fib(args[0])} @@ -325,10 +309,6 @@ def test_stable_teal_generation(subr, mode): DRProp.stackTop: lambda args, actual: ( actual == fib(args[0]) if args[0] < 17 else True ), - # similarly, we don't care about max stack height for n >= 17 - DRProp.maxStackHeight: lambda args, actual: ( - actual == max(2, 2 * args[0]) if args[0] < 17 else True - ), DRProp.status: lambda args: "PASS" if 0 < args[0] < 8 else "REJECT", DRProp.passed: lambda args: 0 < args[0] < 8, DRProp.rejected: lambda args: 0 >= args[0] or args[0] >= 8, @@ -361,15 +341,13 @@ def test_stable_teal_generation(subr, mode): square_byref: { "inputs": [(i,) for i in range(100)], "assertions": { - # DRProp.cost: lambda _, actual: 20 < actual < 22, - # DRProp.lastLog: Encoder.hex(1337), # due to dry-run artifact of not reporting 0-valued scratchvars, # we have a special case for n=0: - DRProp.finalScratch: lambda args: ( - {0: 1, 1: args[0] ** 2} if args[0] else {0: 1} - ), + DRProp.finalScratch: lambda args, actual: ( + {1, 1337, (args[0] ** 2 if args[0] else 1)} + ).issubset(set(actual.values())), DRProp.stackTop: 1337, - DRProp.maxStackHeight: 3, + DRProp.maxStackHeight: lambda _, actual: actual in [3, 4], DRProp.status: "PASS", DRProp.passed: True, DRProp.rejected: False, @@ -379,11 +357,11 @@ def test_stable_teal_generation(subr, mode): square: { "inputs": [(i,) for i in range(100)], "assertions": { - # DRProp.cost: 14, - # DRProp.lastLog: {(i,): Encoder.hex(i * i) if i else None for i in range(100)}, - DRProp.finalScratch: lambda args: ({0: args[0]} if args[0] else {}), + DRProp.finalScratch: lambda args: ( + {0: args[0] ** 2, 1: args[0]} if args[0] else {} + ), DRProp.stackTop: lambda args: args[0] ** 2, - DRProp.maxStackHeight: 2, + DRProp.maxStackHeight: lambda _, actual: actual in range(2, 5), DRProp.status: lambda i: "PASS" if i[0] > 0 else "REJECT", DRProp.passed: lambda i: i[0] > 0, DRProp.rejected: lambda i: i[0] == 0, @@ -393,17 +371,16 @@ def test_stable_teal_generation(subr, mode): swap: { "inputs": [(1, 2), (1, "two"), ("one", 2), ("one", "two")], "assertions": { - # DRProp.cost: 27, - # DRProp.lastLog: Encoder.hex(1337), DRProp.finalScratch: lambda args: { - 0: 3, - 1: 4, + 0: 1337, + 1: Encoder.hex0x(args[1]), 2: Encoder.hex0x(args[0]), - 3: Encoder.hex0x(args[1]), - 4: Encoder.hex0x(args[0]), + 3: 1, + 4: 2, + 5: Encoder.hex0x(args[0]), }, DRProp.stackTop: 1337, - DRProp.maxStackHeight: 2, + DRProp.maxStackHeight: lambda _, actual: actual in [2, 4], DRProp.status: "PASS", DRProp.passed: True, DRProp.rejected: False, @@ -413,25 +390,24 @@ def test_stable_teal_generation(subr, mode): string_mult: { "inputs": [("xyzw", i) for i in range(100)], "assertions": { - # DRProp.cost: lambda args: 30 + 15 * args[1], - # DRProp.lastLog: lambda args: Encoder.hex(args[0] * args[1]) if args[1] else None, + # due to dryrun 0-scratchvar artifact, special case for i == 0: DRProp.finalScratch: lambda args: ( { - 0: len(args[0]), - 1: args[1], - 2: args[1] + 1, - 3: Encoder.hex0x(args[0]), - 4: Encoder.hex0x(args[0] * args[1]), + 0: Encoder.hex0x(args[0] * args[1]), + 1: Encoder.hex0x(args[0] * args[1]), + 2: 1, + 3: args[1], + 4: args[1] + 1, + 5: Encoder.hex0x(args[0]), } if args[1] else { - 0: len(args[0]), - 2: args[1] + 1, - 3: Encoder.hex0x(args[0]), + 2: 1, + 4: args[1] + 1, + 5: Encoder.hex0x(args[0]), } ), DRProp.stackTop: lambda args: len(args[0] * args[1]), - DRProp.maxStackHeight: lambda args: 3 if args[1] else 2, DRProp.status: lambda args: "PASS" if args[1] else "REJECT", DRProp.passed: lambda args: bool(args[1]), DRProp.rejected: lambda args: not bool(args[1]), @@ -441,40 +417,36 @@ def test_stable_teal_generation(subr, mode): oldfac: { "inputs": [(i,) for i in range(25)], "assertions": { - # DRProp.cost: lambda args, actual: actual - 40 <= 17 * args[0] <= actual + 40, - # DRProp.lastLog: lambda args, actual: (actual is None) or (int(actual, base=16) == fac_with_overflow(args[0])), DRProp.finalScratch: lambda args: ( - {0: min(args[0], 21)} if args[0] else {} + {1: args[0], 0: fac_with_overflow(args[0])} + if 0 < args[0] < 21 + else ( + {1: min(21, args[0])} + if args[0] + else {0: fac_with_overflow(args[0])} + ) ), DRProp.stackTop: lambda args: fac_with_overflow(args[0]), - DRProp.maxStackHeight: lambda args: max(2, 2 * args[0]), DRProp.status: lambda args: "PASS" if args[0] < 21 else "REJECT", DRProp.passed: lambda args: args[0] < 21, DRProp.rejected: lambda args: args[0] >= 21, DRProp.errorMessage: lambda args, actual: ( - actual is None - if args[0] < 21 - else "logic 0 failed at line 21: * overflowed" in actual + actual is None if args[0] < 21 else "overflowed" in actual ), }, }, slow_fibonacci: { - "inputs": [(i,) for i in range(18)], + "inputs": [(i,) for i in range(17)], "assertions": { - # DRProp.cost: fib_cost, - # DRProp.lastLog: fib_last_log, - # by returning True for n >= 15, we're declaring that we don't care about the scratchvar's for such cases: DRProp.finalScratch: lambda args, actual: ( - actual == {0: args[0]} - if 0 < args[0] < 15 - else (True if args[0] else actual == {}) + actual == {1: args[0], 0: fib(args[0])} + if 0 < args[0] < 17 + else (True if args[0] >= 17 else actual == {}) ), + # we declare to "not care" about the top of the stack for n >= 15 DRProp.stackTop: lambda args, actual: ( actual == fib(args[0]) if args[0] < 15 else True ), - DRProp.maxStackHeight: lambda args, actual: ( - actual == max(2, 2 * args[0]) if args[0] < 15 else True - ), DRProp.status: lambda args: "PASS" if 0 < args[0] < 15 else "REJECT", DRProp.passed: lambda args: 0 < args[0] < 15, DRProp.rejected: lambda args: not (0 < args[0] < 15), @@ -522,10 +494,11 @@ def blackbox_test_runner( algod = algod_with_assertion() # 2. validate dry run scenarios: - inputs, predicates = Invariant.inputs_and_invariants( - scenario, exec_mode, raw_predicates=True - ) + inputs = scenario["inputs"] + predicates = scenario["assertions"] + assert inputs and isinstance(inputs, list) assert predicates, "Must configure >= 1 predicate" + assert isinstance(predicates, dict) # 3. execute dry run sequence: execute = DryRunExecutor.execute_one_dryrun @@ -539,8 +512,7 @@ def blackbox_test_runner( print(f"Saved Dry Run CSV report to {csvpath}") # 5. Sequential assertions (if provided any) - for i, type_n_assertion in enumerate(predicates.items()): - dr_prop, predicate = type_n_assertion + for i, (dr_prop, predicate) in enumerate(predicates.items()): if SKIP_SCRATCH_ASSERTIONS and dr_prop == DRProp.finalScratch: print("skipping scratch assertions because unstable slots produced") @@ -566,14 +538,6 @@ def test_blackbox_subroutines_as_apps( inspectors6 = blackbox_test_runner(subr, pt.Mode.Application, scenario, 6) inspectors8 = blackbox_test_runner(subr, pt.Mode.Application, scenario, 8) - if subr.name() == "slow_fibonacci": - assert len(inspectors6) == len(inspectors8) == 18 - # NOTE! the last case of inspector 8 (slow_fibonacci compilation with frame pointer) - # does not blow up the 70k budget limit, so we skip specifically for this one. - - del inspectors6[-1] - del inspectors8[-1] - Invariant.full_validation( APP_IDENTICAL_PREDICATES, inspectors=inspectors6, From 6e7889d88af60e3bfed16b30b88750fdd7abb52e Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Fri, 23 Dec 2022 20:29:26 -0600 Subject: [PATCH 139/157] absorb the new graviton API --- requirements.txt | 2 +- tests/blackbox.py | 33 +++++++++++++++++++++++++-------- tests/integration/opup_test.py | 2 -- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/requirements.txt b/requirements.txt index 08815e16c..b7f11a0f7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/algorand/graviton@f6f301a5da784cb7d6a38c59745879eb624fa622 +graviton@git+https://github.com/algorand/graviton@6ed2789d6ff81489d2019fbc0840db7fc0233c6c mypy==0.991 pytest==7.2.0 pytest-cov==3.0.0 diff --git a/tests/blackbox.py b/tests/blackbox.py index e0b60813e..50e169342 100644 --- a/tests/blackbox.py +++ b/tests/blackbox.py @@ -207,6 +207,23 @@ def add_trace(self, trace: Any) -> None: def is_abi(self) -> bool: return isinstance(self.subr.subroutine, ABIReturnSubroutine) + def abi_method_signature(self) -> None | str: + if self.is_abi(): + abi_subr = cast(ABIReturnSubroutine, self.subr.subroutine) + return abi_subr.method_signature() + + # create an artificial method signature + # based on the `abi_argument_types()` and `abi_return_type()` + if arg_types := self.abi_argument_types(): + if all(t is None for t in arg_types): + return None + + ret_type = self.abi_return_type() + ret = str(ret_type) if ret_type else "void" + return f"ptdre_foo({','.join(map(str, arg_types))}){ret}" + + return None + def abi_argument_types(self) -> None | list[algosdk.abi.ABIType]: if not (self.input_types or self.is_abi()): return None @@ -428,15 +445,15 @@ def dryrun_on_sequence( algod=algod_with_assertion(), teal=teal, inputs=inputs, - abi_argument_types=self.abi_argument_types(), - abi_return_type=self.abi_return_type(), + abi_method_signature=self.abi_method_signature(), + omit_method_selector=True, ), signature_case=lambda: DryRunExecutor.dryrun_logicsig_on_sequence( algod=algod_with_assertion(), teal=teal, inputs=inputs, - abi_argument_types=self.abi_argument_types(), - abi_return_type=self.abi_return_type(), + abi_method_signature=self.abi_method_signature(), + omit_method_selector=True, ), trace=teal, )(self.mode) @@ -453,15 +470,15 @@ def dryrun( algod_with_assertion(), teal, args, - self.abi_argument_types(), - self.abi_return_type(), + abi_method_signature=self.abi_method_signature(), + omit_method_selector=True, ), signature_case=lambda: DryRunExecutor.dryrun_logicsig( algod_with_assertion(), teal, args, - self.abi_argument_types(), - self.abi_return_type(), + abi_method_signature=self.abi_method_signature(), + omit_method_selector=True, ), trace=teal, )(self.mode) diff --git a/tests/integration/opup_test.py b/tests/integration/opup_test.py index afdb82f1d..7c44cb5db 100644 --- a/tests/integration/opup_test.py +++ b/tests/integration/opup_test.py @@ -27,8 +27,6 @@ def _dryrun( e.compile(pt.compiler.MAX_PROGRAM_VERSION), [], ExecutionMode.Application, - e.abi_argument_types(), - e.abi_return_type(), txn_params=DryRunExecutor.transaction_params( sender=graviton.models.ZERO_ADDRESS, sp=sp, From d8bd2db0b5ac4eb438a897f5299bbafd061c0cc1 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Mon, 26 Dec 2022 17:50:29 -0600 Subject: [PATCH 140/157] update graviton's pin to latest branch commit --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index b7f11a0f7..f697918f6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/algorand/graviton@6ed2789d6ff81489d2019fbc0840db7fc0233c6c +graviton@git+https://github.com/algorand/graviton@26d47e31c3ffb5132cd29251eefcb50db0723d03 mypy==0.991 pytest==7.2.0 pytest-cov==3.0.0 From 479006998b82a667382f48f10e1361cb36d15f2f Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Sat, 31 Dec 2022 10:06:03 -0600 Subject: [PATCH 141/157] Refactor graviton usage --- requirements.txt | 2 +- tests/blackbox.py | 119 +++++++----------------- tests/integration/abi_roundtrip_test.py | 2 +- tests/integration/ecdsa_test.py | 8 +- tests/integration/graviton_abi_test.py | 12 +-- tests/integration/graviton_test.py | 38 ++++---- tests/integration/opup_test.py | 16 +++- tests/integration/pure_logicsig_test.py | 8 +- 8 files changed, 80 insertions(+), 125 deletions(-) diff --git a/requirements.txt b/requirements.txt index f697918f6..b7ba8ca1a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/algorand/graviton@26d47e31c3ffb5132cd29251eefcb50db0723d03 +graviton@git+https://github.com/tzaffi/graviton@exec-multi-dispatch mypy==0.991 pytest==7.2.0 pytest-cov==3.0.0 diff --git a/tests/blackbox.py b/tests/blackbox.py index 50e169342..e1d2942b0 100644 --- a/tests/blackbox.py +++ b/tests/blackbox.py @@ -1,5 +1,4 @@ -from typing import Any, Callable, Generic, Optional, Sequence, TypeVar, cast -from dataclasses import dataclass +from typing import Any, Callable, Sequence, cast import algosdk.abi from algosdk.v2client import algod @@ -138,37 +137,13 @@ def decorator_blackbox(func: SubroutineFnWrapper | ABIReturnSubroutine): # ---- API ---- # -Output = TypeVar("Output") -Lazy = Callable[[], Output] - - -@dataclass(frozen=True) -class _MatchMode(Generic[Output]): - runner: Optional["PyTealDryRunExecutor"] - app_case: Lazy - signature_case: Lazy - trace: Any = None - - def __post_init__(self): - if self.runner and self.trace: - self.runner.add_trace(self.trace) - - def __call__(self, mode: Mode, *args, **kwargs) -> Output: - match mode: - case Mode.Application: - return self.app_case() - case Mode.Signature: - return self.signature_case() - case _: - raise Exception(f"Unknown mode {mode} of type {type(mode)}") - - def mode_to_execution_mode(mode: Mode) -> blackbox.ExecutionMode: - return _MatchMode( - runner=None, - app_case=lambda: blackbox.ExecutionMode.Application, - signature_case=lambda: blackbox.ExecutionMode.Signature, - )(mode) + if mode == Mode.Application: + return blackbox.ExecutionMode.Application + if mode == Mode.Signature: + return blackbox.ExecutionMode.Signature + + raise ValueError(f"Can't handle {mode=}") class PyTealDryRunExecutor: @@ -182,9 +157,11 @@ def __init__(self, subr: BlackboxWrapper, mode: Mode): mode: type of program to produce: logic sig (Mode.Signature) or app (Mode.Application) """ input_types = subr.input_types - assert ( - input_types is not None - ), "please provide input_types in your @Subroutine or @ABIReturnSubroutine annotation (this is crucial for generating proper end-to-end testable PyTeal)" + assert input_types is not None, ( + "please provide input_types in your @Subroutine or @ABIReturnSubroutine " + "annotation " + "(this is crucial for generating proper end-to-end testable PyTeal)" + ) self.subr, self.mode, self.input_types = subr, mode, input_types match subr.subroutine: @@ -417,68 +394,40 @@ def approval(): return approval def compile(self, version: int, assemble_constants: bool = False) -> str: - return _MatchMode( - runner=self, - app_case=lambda: compileTeal( - self.program(), - self.mode, - version=version, - assembleConstants=assemble_constants, - ), - signature_case=lambda: compileTeal( - self.program(), - self.mode, - version=version, - assembleConstants=assemble_constants, - ), - )(self.mode) - - def dryrun_on_sequence( + return compileTeal( + self.program(), + self.mode, + version=version, + assembleConstants=assemble_constants, + ) + + def dryrun_sequence( self, inputs: list[Sequence[PyTypes]], compiler_version=6, ) -> list[DryRunInspector]: teal = self.compile(compiler_version) - return _MatchMode( - self, - app_case=lambda: DryRunExecutor.dryrun_app_on_sequence( + return cast( + list[DryRunInspector], + DryRunExecutor( algod=algod_with_assertion(), + mode=mode_to_execution_mode(self.mode), teal=teal, - inputs=inputs, abi_method_signature=self.abi_method_signature(), omit_method_selector=True, - ), - signature_case=lambda: DryRunExecutor.dryrun_logicsig_on_sequence( - algod=algod_with_assertion(), - teal=teal, - inputs=inputs, - abi_method_signature=self.abi_method_signature(), - omit_method_selector=True, - ), - trace=teal, - )(self.mode) + ).run_sequence(inputs), + ) - def dryrun( + def dryrun_one( self, args: Sequence[bytes | str | int], compiler_version=6, ) -> DryRunInspector: teal = self.compile(compiler_version) - return _MatchMode( - self, - app_case=lambda: DryRunExecutor.dryrun_app( - algod_with_assertion(), - teal, - args, - abi_method_signature=self.abi_method_signature(), - omit_method_selector=True, - ), - signature_case=lambda: DryRunExecutor.dryrun_logicsig( - algod_with_assertion(), - teal, - args, - abi_method_signature=self.abi_method_signature(), - omit_method_selector=True, - ), - trace=teal, - )(self.mode) + return DryRunExecutor( + algod=algod_with_assertion(), + mode=mode_to_execution_mode(self.mode), + teal=teal, + abi_method_signature=self.abi_method_signature(), + omit_method_selector=True, + ).run_one(args) diff --git a/tests/integration/abi_roundtrip_test.py b/tests/integration/abi_roundtrip_test.py index 849d632ed..feda75870 100644 --- a/tests/integration/abi_roundtrip_test.py +++ b/tests/integration/abi_roundtrip_test.py @@ -257,7 +257,7 @@ def test_roundtrip(abi_type): args = (rand_abi_instance,) def dryrun_roundtrip(version: int): - inspector = roundtripper.dryrun(args, compiler_version=version) + inspector = roundtripper.dryrun_one(args, compiler_version=version) cost = inspector.cost() passed = inspector.passed() diff --git a/tests/integration/ecdsa_test.py b/tests/integration/ecdsa_test.py index 4efceccb7..76572e2c8 100644 --- a/tests/integration/ecdsa_test.py +++ b/tests/integration/ecdsa_test.py @@ -46,7 +46,7 @@ def verify(): ) args = [] - app_result = PyTealDryRunExecutor(verify, Mode.Application).dryrun( + app_result = PyTealDryRunExecutor(verify, Mode.Application).dryrun_one( args, compiler_version=5 ) @@ -81,7 +81,7 @@ def verify_fail(): ) args = [] - app_result = PyTealDryRunExecutor(verify_fail, Mode.Application).dryrun( + app_result = PyTealDryRunExecutor(verify_fail, Mode.Application).dryrun_one( args, compiler_version=5 ) @@ -117,7 +117,7 @@ def decompress(): ) args = [] - app_result = PyTealDryRunExecutor(decompress, Mode.Application).dryrun( + app_result = PyTealDryRunExecutor(decompress, Mode.Application).dryrun_one( args, compiler_version=5 ) @@ -158,7 +158,7 @@ def recover(): ) args = [] - app_result = PyTealDryRunExecutor(recover, Mode.Application).dryrun( + app_result = PyTealDryRunExecutor(recover, Mode.Application).dryrun_one( args, compiler_version=5 ) diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index cdd6d417b..b5091f219 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -331,7 +331,7 @@ def pytuple_to_num(t): ] def binary_dryrun(p: PyTealDryRunExecutor) -> list[DryRunInspector]: - return p.dryrun_on_sequence(binary_inputs, compiler_version=version) # type: ignore + return p.dryrun_sequence(binary_inputs, compiler_version=version) # type: ignore # Binary: inspectors_subtract_slick = binary_dryrun(bbpt_subtract_slick) @@ -343,7 +343,7 @@ def binary_dryrun(p: PyTealDryRunExecutor) -> list[DryRunInspector]: inspectors_add = binary_dryrun(bbpt_add) # Unary: - inspectors_negate = bbpt_negate.dryrun_on_sequence( + inspectors_negate = bbpt_negate.dryrun_sequence( unary_inputs, compiler_version=version # type: ignore ) @@ -444,11 +444,11 @@ def pytuple_to_complex(tt): # Binary: def binary_dryrun(p: PyTealDryRunExecutor) -> list[DryRunInspector]: - return p.dryrun_on_sequence(binary_inputs, compiler_version=version) # type: ignore + return p.dryrun_sequence(binary_inputs, compiler_version=version) # type: ignore # Unary: def unary_dryrun(p: PyTealDryRunExecutor) -> list[DryRunInspector]: - return p.dryrun_on_sequence(unary_inputs, compiler_version=version) # type: ignore + return p.dryrun_sequence(unary_inputs, compiler_version=version) # type: ignore inspectors_cplx_add = binary_dryrun(bbpt_cplx_add) @@ -523,7 +523,7 @@ def test_conditional_factorial(version: int): ptdre = PyTealDryRunExecutor(conditional_factorial, pt.Mode.Application) inputs = [(n,) for n in range(20)] - inspectors = ptdre.dryrun_on_sequence(inputs, compiler_version=version) # type: ignore + inspectors = ptdre.dryrun_sequence(inputs, compiler_version=version) # type: ignore for i, args in enumerate(inputs): inspector = inspectors[i] n = args[0] @@ -534,7 +534,7 @@ def test_conditional_factorial(version: int): n = 21 args = (n,) - inspector = ptdre.dryrun(args) + inspector = ptdre.dryrun_one(args) assert inspector.rejected(), inspector.report( args, f"FAILED: should have rejected for {n=}", row=n + 1 ) diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index d69a59037..d947e5713 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -22,7 +22,6 @@ DryRunInspector, mode_has_property, ) - from graviton.invariant import Invariant, PredicateKind PATH = Path.cwd() / "tests" / "integration" @@ -501,8 +500,7 @@ def blackbox_test_runner( assert isinstance(predicates, dict) # 3. execute dry run sequence: - execute = DryRunExecutor.execute_one_dryrun - inspectors = list(map(lambda a: execute(algod, teal, a, exec_mode), inputs)) + inspectors = DryRunExecutor(algod, exec_mode, teal).run_sequence(inputs) # 4. Statistical report: csvpath = GENERATED / "blackbox" / f"{tealfile}_v{version}.csv" @@ -579,10 +577,10 @@ def square(x): def evaluate_and_check(version: int): # evaluate the programs - app_result = PyTealDryRunExecutor(square, Mode.Application).dryrun( + app_result = PyTealDryRunExecutor(square, Mode.Application).dryrun_one( args, compiler_version=version ) - lsig_result = PyTealDryRunExecutor(square, Mode.Signature).dryrun( + lsig_result = PyTealDryRunExecutor(square, Mode.Signature).dryrun_one( args, compiler_version=version ) @@ -665,7 +663,7 @@ def euclid(x, y): def test_and_report(version: int): # assert that each result is that same as what Python's math.gcd() computes - inspectors = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( + inspectors = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_sequence( inputs, compiler_version=version ) for i, result in enumerate(inspectors): @@ -759,7 +757,7 @@ def euclid(x, y): ) # Execute on the input sequence to get a dry-run inspectors: - inspectors6 = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( + inspectors6 = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_sequence( inputs, compiler_version=6 ) @@ -768,7 +766,7 @@ def euclid(x, y): Invariant(predicate).validates(property, inspectors6) # Execute on the input sequence to get a dry-run inspectors: - inspectors8 = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_on_sequence( + inspectors8 = PyTealDryRunExecutor(euclid, Mode.Application).dryrun_sequence( inputs, compiler_version=8 ) @@ -850,10 +848,8 @@ def abi_sum(toSum: abi.DynamicArray[abi.Uint64], *, output: abi.Uint64) -> Expr: inputs.append(tuple([random.sample(choices, n)])) def test_and_report_for_app_and_lsig(_version: int): - app_inspectors = app_pytealer.dryrun_on_sequence( - inputs, compiler_version=_version - ) - lsig_inspectors = lsig_pytealer.dryrun_on_sequence( + app_inspectors = app_pytealer.dryrun_sequence(inputs, compiler_version=_version) + lsig_inspectors = lsig_pytealer.dryrun_sequence( inputs, compiler_version=_version ) for i in range(N): @@ -926,13 +922,11 @@ def cubed(n: abi.Uint64): app_pytealer = PyTealDryRunExecutor(cubed, Mode.Application) lsig_pytealer = PyTealDryRunExecutor(cubed, Mode.Signature) - inputs = [[i] for i in range(1, 11)] + inputs = [(i,) for i in range(1, 11)] def test_app_and_lsig(_version: int): - app_inspect = app_pytealer.dryrun_on_sequence(inputs, compiler_version=_version) - lsig_inspect = lsig_pytealer.dryrun_on_sequence( - inputs, compiler_version=_version - ) + app_inspect = app_pytealer.dryrun_sequence(inputs, compiler_version=_version) + lsig_inspect = lsig_pytealer.dryrun_sequence(inputs, compiler_version=_version) for index, inspect in enumerate(app_inspect): input_var = inputs[index][0] @@ -1001,7 +995,7 @@ def while_continue_accumulation(n): for x in range(30): args = [x] - lsig_result = executor.dryrun(args) + lsig_result = executor.dryrun_one(args) if x == 0: assert not lsig_result.passed() else: @@ -1011,7 +1005,7 @@ def while_continue_accumulation(n): args, "stack_top() gave unexpected results for lsig" ) - lsig_result = executor.dryrun(args, compiler_version=8) + lsig_result = executor.dryrun_one(args, compiler_version=8) if x == 0: assert not lsig_result.passed() else: @@ -1076,12 +1070,12 @@ def named_tuple_field_access( lsig_pytealer = PyTealDryRunExecutor(named_tuple_field_access, Mode.Signature) args = (False, b"1" * 32, (0, False), b"0" * 10, [True] * 4, 0) - inspector6 = lsig_pytealer.dryrun(args, compiler_version=6) + inspector6 = lsig_pytealer.dryrun_one(args, compiler_version=6) assert inspector6.stack_top() == 1 assert inspector6.passed() - inspector8 = lsig_pytealer.dryrun(args, compiler_version=8) + inspector8 = lsig_pytealer.dryrun_one(args, compiler_version=8) assert inspector8.passed() assert inspector8.stack_top() == 1 @@ -1092,7 +1086,7 @@ def named_tuple_field_access( msg="Mode.Signature NamedTuple example", ) - inspector = lsig_pytealer.dryrun(args, compiler_version=8) + inspector = lsig_pytealer.dryrun_one(args, compiler_version=8) assert inspector.passed() assert inspector.stack_top() == 1 diff --git a/tests/integration/opup_test.py b/tests/integration/opup_test.py index 7c44cb5db..f779b7934 100644 --- a/tests/integration/opup_test.py +++ b/tests/integration/opup_test.py @@ -10,7 +10,12 @@ PyTealDryRunExecutor, ) import tests -from graviton.blackbox import DryRunExecutor, DryRunInspector, ExecutionMode +from graviton.blackbox import ( + DryRunExecutor, + DryRunInspector, + ExecutionMode, + DryRunTransactionParams as TxParams, +) from algosdk.v2client.models import Account import algosdk @@ -22,18 +27,19 @@ def _dryrun( accounts: list[Account], ) -> DryRunInspector: e = PyTealDryRunExecutor(bw, pt.Mode.Application) - return DryRunExecutor.execute_one_dryrun( + return DryRunExecutor( tests.blackbox.algod_with_assertion(), + ExecutionMode.Application, e.compile(pt.compiler.MAX_PROGRAM_VERSION), + ).run_one( [], - ExecutionMode.Application, - txn_params=DryRunExecutor.transaction_params( + txn_params=TxParams.for_app( sender=graviton.models.ZERO_ADDRESS, sp=sp, index=DryRunExecutor.EXISTING_APP_CALL, on_complete=algosdk.future.transaction.OnComplete.NoOpOC, + dryrun_accounts=accounts, ), - accounts=accounts, ) diff --git a/tests/integration/pure_logicsig_test.py b/tests/integration/pure_logicsig_test.py index 0fd8e52ff..ef1f4b74d 100644 --- a/tests/integration/pure_logicsig_test.py +++ b/tests/integration/pure_logicsig_test.py @@ -12,6 +12,8 @@ DryRunExecutor as Executor, DryRunInspector as Inspector, DryRunProperty as DRProp, + ExecutionMode, + DryRunTransactionParams as TxParams, ) from graviton.invariant import Invariant @@ -87,7 +89,11 @@ def payment_amount(x, y): for args, amt in zip(inputs, amts): txn = {"amt": amt} txns.append(txn) - inspectors.append(Executor.dryrun_logicsig(ALGOD, compiled, args, **txn)) + inspectors.append( + Executor(ALGOD, ExecutionMode.Signature, compiled).run_one( + args, txn_params=TxParams(**txn) + ), + ) print( f"generating a report for (a,p,q) = {a,p,q} with {M, N} dry-run calls and spreadsheet rows" From 7617c7a61ccb4679ae0df9eff57618f6d381a1bf Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Sat, 31 Dec 2022 20:08:17 -0600 Subject: [PATCH 142/157] new PyTealDryRunExecutor.executor() method --- requirements.txt | 2 +- tests/blackbox.py | 32 ++++++++++++-------------------- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/requirements.txt b/requirements.txt index b7ba8ca1a..a7a9e0254 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/tzaffi/graviton@exec-multi-dispatch +graviton@git+https://github.com/tzaffi/graviton@403278bf4eaa71c45d810099ed2e9fdbd4d9276a mypy==0.991 pytest==7.2.0 pytest-cov==3.0.0 diff --git a/tests/blackbox.py b/tests/blackbox.py index e1d2942b0..5145e895a 100644 --- a/tests/blackbox.py +++ b/tests/blackbox.py @@ -401,33 +401,25 @@ def compile(self, version: int, assemble_constants: bool = False) -> str: assembleConstants=assemble_constants, ) + def executor(self, compiler_version: int = 6) -> DryRunExecutor: + return DryRunExecutor( + algod=algod_with_assertion(), + mode=mode_to_execution_mode(self.mode), + teal=self.compile(compiler_version), + abi_method_signature=self.abi_method_signature(), + omit_method_selector=True, + ) + def dryrun_sequence( self, inputs: list[Sequence[PyTypes]], - compiler_version=6, + compiler_version: int = 6, ) -> list[DryRunInspector]: - teal = self.compile(compiler_version) - return cast( - list[DryRunInspector], - DryRunExecutor( - algod=algod_with_assertion(), - mode=mode_to_execution_mode(self.mode), - teal=teal, - abi_method_signature=self.abi_method_signature(), - omit_method_selector=True, - ).run_sequence(inputs), - ) + return cast(list, self.executor(compiler_version).run_sequence(inputs)) def dryrun_one( self, args: Sequence[bytes | str | int], compiler_version=6, ) -> DryRunInspector: - teal = self.compile(compiler_version) - return DryRunExecutor( - algod=algod_with_assertion(), - mode=mode_to_execution_mode(self.mode), - teal=teal, - abi_method_signature=self.abi_method_signature(), - omit_method_selector=True, - ).run_one(args) + return self.executor(compiler_version).run_one(args) From 5f88771c7a155887187ce6fea550a2737c2418c6 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Sat, 31 Dec 2022 20:30:18 -0600 Subject: [PATCH 143/157] pass txn_params and verbose to graviton's runners --- tests/blackbox.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/tests/blackbox.py b/tests/blackbox.py index 5145e895a..7fae92608 100644 --- a/tests/blackbox.py +++ b/tests/blackbox.py @@ -4,7 +4,11 @@ from algosdk.v2client import algod from graviton import blackbox -from graviton.blackbox import DryRunInspector, DryRunExecutor +from graviton.blackbox import ( + DryRunInspector, + DryRunExecutor, + DryRunTransactionParams as TxParams, +) from graviton.models import PyTypes from pyteal.ast.subroutine import OutputKwArgInfo @@ -413,13 +417,26 @@ def executor(self, compiler_version: int = 6) -> DryRunExecutor: def dryrun_sequence( self, inputs: list[Sequence[PyTypes]], - compiler_version: int = 6, + *, + compiler_version=6, + txn_params: TxParams | None = None, + verbose: bool = False, ) -> list[DryRunInspector]: - return cast(list, self.executor(compiler_version).run_sequence(inputs)) + return cast( + list, + self.executor(compiler_version).run_sequence( + inputs, txn_params=txn_params, verbose=verbose + ), + ) def dryrun_one( self, args: Sequence[bytes | str | int], + *, compiler_version=6, + txn_params: TxParams | None = None, + verbose: bool = False, ) -> DryRunInspector: - return self.executor(compiler_version).run_one(args) + return self.executor(compiler_version).run_one( + args, txn_params=txn_params, verbose=verbose + ) From 97aff37800f0b1217c7111c155e6b86cde16741a Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Sat, 31 Dec 2022 20:30:40 -0600 Subject: [PATCH 144/157] pass txn_params and verbose to graviton's runners --- tests/integration/opup_test.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/tests/integration/opup_test.py b/tests/integration/opup_test.py index f779b7934..6b87661fb 100644 --- a/tests/integration/opup_test.py +++ b/tests/integration/opup_test.py @@ -9,11 +9,9 @@ BlackboxWrapper, PyTealDryRunExecutor, ) -import tests from graviton.blackbox import ( DryRunExecutor, DryRunInspector, - ExecutionMode, DryRunTransactionParams as TxParams, ) @@ -26,13 +24,9 @@ def _dryrun( sp: algosdk.future.transaction.SuggestedParams, accounts: list[Account], ) -> DryRunInspector: - e = PyTealDryRunExecutor(bw, pt.Mode.Application) - return DryRunExecutor( - tests.blackbox.algod_with_assertion(), - ExecutionMode.Application, - e.compile(pt.compiler.MAX_PROGRAM_VERSION), - ).run_one( + return PyTealDryRunExecutor(bw, pt.Mode.Application).dryrun_one( [], + compiler_version=pt.compiler.MAX_PROGRAM_VERSION, txn_params=TxParams.for_app( sender=graviton.models.ZERO_ADDRESS, sp=sp, From 1f97e303e909e0356038532bb145d71aa36c5468 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Sat, 31 Dec 2022 20:43:58 -0600 Subject: [PATCH 145/157] don't re-instantiate the executor at every iteration --- tests/integration/pure_logicsig_test.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/integration/pure_logicsig_test.py b/tests/integration/pure_logicsig_test.py index ef1f4b74d..3a67951de 100644 --- a/tests/integration/pure_logicsig_test.py +++ b/tests/integration/pure_logicsig_test.py @@ -9,7 +9,7 @@ from tests.blackbox import algod_with_assertion from graviton.blackbox import ( - DryRunExecutor as Executor, + DryRunExecutor, DryRunInspector as Inspector, DryRunProperty as DRProp, ExecutionMode, @@ -71,6 +71,8 @@ def factorizer_game_check(a: int, p: int, q: int, M: int, N: int): mode=Mode.Signature, assembleConstants=True, ) + executor = DryRunExecutor(ALGOD, ExecutionMode.Signature, compiled) + inputs = list(inputs_for_coefficients(a, p, q, M, N)) N = len(inputs) @@ -90,9 +92,7 @@ def payment_amount(x, y): txn = {"amt": amt} txns.append(txn) inspectors.append( - Executor(ALGOD, ExecutionMode.Signature, compiled).run_one( - args, txn_params=TxParams(**txn) - ), + executor.run_one(args, txn_params=TxParams(**txn)), ) print( From 315fc23a7708862c2773a8efdddb4e11a1c8914d Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Sun, 1 Jan 2023 11:40:12 -0600 Subject: [PATCH 146/157] remove now unused add_trace() --- tests/blackbox.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/blackbox.py b/tests/blackbox.py index 7fae92608..689068bf3 100644 --- a/tests/blackbox.py +++ b/tests/blackbox.py @@ -180,11 +180,6 @@ def __init__(self, subr: BlackboxWrapper, mode: Mode): self._pyteal_lambda: Callable[..., Expr] = approval - self.traces: list = [] - - def add_trace(self, trace: Any) -> None: - self.traces.append(trace) - def is_abi(self) -> bool: return isinstance(self.subr.subroutine, ABIReturnSubroutine) From 09261e88a9b20168fcd773e20e68d81cbf33dccd Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Sun, 1 Jan 2023 12:02:48 -0600 Subject: [PATCH 147/157] lint --- tests/blackbox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/blackbox.py b/tests/blackbox.py index 689068bf3..3186f8dc9 100644 --- a/tests/blackbox.py +++ b/tests/blackbox.py @@ -1,4 +1,4 @@ -from typing import Any, Callable, Sequence, cast +from typing import Callable, Sequence, cast import algosdk.abi from algosdk.v2client import algod From 18150bc7a4fc97a8373a0e9def6b44e018d072f1 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Sun, 1 Jan 2023 14:40:58 -0600 Subject: [PATCH 148/157] Update to requirements.txt to latest graviton commit --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a7a9e0254..1d80f0cd5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/tzaffi/graviton@403278bf4eaa71c45d810099ed2e9fdbd4d9276a +graviton@git+https://github.com/tzaffi/graviton@a68208e694ee359bd98a504e849017a61c4b14dd mypy==0.991 pytest==7.2.0 pytest-cov==3.0.0 From 69519c59824662bda150acdb8f61acc240149a97 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Tue, 3 Jan 2023 16:24:46 -0600 Subject: [PATCH 149/157] pin to graviton 0.7.0 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 1d80f0cd5..10b65a89e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/tzaffi/graviton@a68208e694ee359bd98a504e849017a61c4b14dd +graviton@git+https://github.com/tzaffi/graviton@v0.7.0 mypy==0.991 pytest==7.2.0 pytest-cov==3.0.0 From 3ad2f2ed4c0eec3cbd0f41f61d490fa746c9ad09 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Tue, 3 Jan 2023 16:26:29 -0600 Subject: [PATCH 150/157] fix gravition pin --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 10b65a89e..b7ba8ca1a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/tzaffi/graviton@v0.7.0 +graviton@git+https://github.com/tzaffi/graviton@exec-multi-dispatch mypy==0.991 pytest==7.2.0 pytest-cov==3.0.0 From 0ee255c8c88418183a2e7487a173fe81d1906712 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Tue, 3 Jan 2023 16:29:29 -0600 Subject: [PATCH 151/157] pin to v0.7.0 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index f697918f6..609ac6e51 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/algorand/graviton@26d47e31c3ffb5132cd29251eefcb50db0723d03 +graviton@git+https://github.com/algorand/graviton@v0.7.0 mypy==0.991 pytest==7.2.0 pytest-cov==3.0.0 From ed1baf46407f8e8812ce1cc9c03a5d23aaffb8ed Mon Sep 17 00:00:00 2001 From: Lemuel Solomon S <49029145+alvorithm@users.noreply.github.com> Date: Wed, 28 Dec 2022 18:35:16 +0200 Subject: [PATCH 152/157] Typo fix in docs (#625) --- docs/overview.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/overview.rst b/docs/overview.rst index b544623f1..54466c08d 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -9,7 +9,7 @@ Below is an example of writing a basic stateless smart contract that allows a sp .. literalinclude:: ../examples/signature/basic.py :language: python -As shown in this exmaple, the logic of smart contract is expressed using PyTeal expressions constructed in Python. PyTeal overloads Python's arithmetic operators +As shown in this example, the logic of smart contract is expressed using PyTeal expressions constructed in Python. PyTeal overloads Python's arithmetic operators such as :code:`<` and :code:`==` (more overloaded operators can be found in :ref:`arithmetic_expressions`), allowing Python developers express smart contract logic more naturally. Lastly, :any:`compileTeal` is called to convert an PyTeal expression From fc06c17afe7e3ce3ff13a6b9d3571a0467789c53 Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Thu, 12 Jan 2023 19:32:09 -0600 Subject: [PATCH 153/157] flake8 --- tests/blackbox.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/blackbox.py b/tests/blackbox.py index 27f1026b4..7fae92608 100644 --- a/tests/blackbox.py +++ b/tests/blackbox.py @@ -1,5 +1,4 @@ -from typing import Any, Callable, Generic, Optional, Sequence, TypeVar, cast -from dataclasses import dataclass +from typing import Any, Callable, Sequence, cast import algosdk.abi from algosdk.v2client import algod From 3232a0905f26269210c76f09410a051bb87cc7db Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Thu, 12 Jan 2023 20:08:57 -0600 Subject: [PATCH 154/157] =?UTF-8?q?=F0=9F=A4=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/integration/graviton_abi_test.py | 2 +- tests/integration/graviton_test.py | 17 +++++------------ tests/integration/opup_test.py | 8 ++++---- tests/integration/pure_logicsig_test.py | 3 +-- 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/tests/integration/graviton_abi_test.py b/tests/integration/graviton_abi_test.py index b5091f219..b73132799 100644 --- a/tests/integration/graviton_abi_test.py +++ b/tests/integration/graviton_abi_test.py @@ -1,7 +1,7 @@ import random import pytest -from graviton.blackbox import DryRunInspector +from graviton.inspector import DryRunInspector import pyteal as pt from pyteal.ast.subroutine import ABIReturnSubroutine diff --git a/tests/integration/graviton_test.py b/tests/integration/graviton_test.py index d947e5713..7f80e70a3 100644 --- a/tests/integration/graviton_test.py +++ b/tests/integration/graviton_test.py @@ -15,14 +15,9 @@ PyTealDryRunExecutor, ) -from graviton.blackbox import ( - DryRunProperty as DRProp, - DryRunEncoder as Encoder, - DryRunExecutor, - DryRunInspector, - mode_has_property, -) -from graviton.invariant import Invariant, PredicateKind +from graviton.blackbox import DryRunEncoder as Encoder, DryRunExecutor +from graviton.inspector import DryRunProperty as DRProp, DryRunInspector +from graviton.invariant import Invariant, PredicateKind, mode_has_property PATH = Path.cwd() / "tests" / "integration" FIXTURES = PATH / "teal" @@ -695,10 +690,8 @@ def blackbox_pyteal_example3(): import math import random - from graviton.blackbox import ( - DryRunEncoder, - DryRunProperty as DRProp, - ) + from graviton.blackbox import DryRunEncoder + from graviton.inspector import DryRunProperty as DRProp from graviton.invariant import Invariant from pyteal import If, Int, Mod, Mode, Subroutine, TealType diff --git a/tests/integration/opup_test.py b/tests/integration/opup_test.py index f47a49b61..b1a02ad5e 100644 --- a/tests/integration/opup_test.py +++ b/tests/integration/opup_test.py @@ -22,7 +22,7 @@ def _dryrun( bw: BlackboxWrapper, sp: algosdk.transaction.SuggestedParams, - accounts: list[Account], + accounts: list[Account | str], ) -> DryRunInspector: return PyTealDryRunExecutor(bw, pt.Mode.Application).dryrun_one( [], @@ -31,7 +31,7 @@ def _dryrun( sender=graviton.models.ZERO_ADDRESS, sp=sp, index=DryRunExecutor.EXISTING_APP_CALL, - on_complete=algosdk.future.transaction.OnComplete.NoOpOC, + on_complete=algosdk.transaction.OnComplete.NoOpOC, dryrun_accounts=accounts, ), ) @@ -60,7 +60,7 @@ def maximize_budget(): ) if with_funding: - accounts = ( + accounts: list[Account | str] = ( [ Account( address=algosdk.logic.get_application_address( @@ -120,7 +120,7 @@ def ensure_budget(): ) if with_funding: - accounts = ( + accounts: list[Account | str] = ( [ Account( address=algosdk.logic.get_application_address( diff --git a/tests/integration/pure_logicsig_test.py b/tests/integration/pure_logicsig_test.py index 3a67951de..510f70f28 100644 --- a/tests/integration/pure_logicsig_test.py +++ b/tests/integration/pure_logicsig_test.py @@ -10,11 +10,10 @@ from tests.blackbox import algod_with_assertion from graviton.blackbox import ( DryRunExecutor, - DryRunInspector as Inspector, - DryRunProperty as DRProp, ExecutionMode, DryRunTransactionParams as TxParams, ) +from graviton.inspector import DryRunInspector as Inspector, DryRunProperty as DRProp from graviton.invariant import Invariant REPORTS_DIR = Path.cwd() / "tests" / "integration" / "reports" From d0331b0f14984c5ecd8884333675295dc15151bd Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Mon, 16 Jan 2023 22:32:45 -0600 Subject: [PATCH 155/157] Trigger a build against head of depending graviton branch --- tests/blackbox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/blackbox.py b/tests/blackbox.py index 7fae92608..00e85e9ef 100644 --- a/tests/blackbox.py +++ b/tests/blackbox.py @@ -163,7 +163,7 @@ def __init__(self, subr: BlackboxWrapper, mode: Mode): input_types = subr.input_types assert input_types is not None, ( "please provide input_types in your @Subroutine or @ABIReturnSubroutine " - "annotation " + "annotation. " "(this is crucial for generating proper end-to-end testable PyTeal)" ) From cf21e180abedb4ad1b3cb3cc43a6cd453d4cfc1c Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Tue, 17 Jan 2023 13:25:25 -0600 Subject: [PATCH 156/157] Update requirements.txt --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index b7ba8ca1a..0745a3261 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/tzaffi/graviton@exec-multi-dispatch +graviton@git+https://github.com/tzaffi/graviton@v0.8.0 mypy==0.991 pytest==7.2.0 pytest-cov==3.0.0 From e355c939261d310fc8e2b0b424317d41a65cec3e Mon Sep 17 00:00:00 2001 From: Zeph Grunschlag Date: Tue, 17 Jan 2023 13:28:40 -0600 Subject: [PATCH 157/157] correct repo --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 0745a3261..ba07a0959 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ black==22.3.0 flake8==5.0.4 flake8-tidy-imports==4.6.0 -graviton@git+https://github.com/tzaffi/graviton@v0.8.0 +graviton@git+https://github.com/algorand/graviton@v0.8.0 mypy==0.991 pytest==7.2.0 pytest-cov==3.0.0