Skip to content

Commit

Permalink
ABI Data Schema (#584)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahangsu committed Nov 14, 2022
1 parent a3b5b29 commit 2d65bb6
Show file tree
Hide file tree
Showing 29 changed files with 902 additions and 159 deletions.
12 changes: 6 additions & 6 deletions pyteal/ast/abi/address.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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():
Expand Down
73 changes: 61 additions & 12 deletions pyteal/ast/abi/address_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pytest
from typing import cast
import pyteal as pt
from pyteal import abi

Expand Down Expand Up @@ -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(pt.ScratchVar, value._stored_value).slot,
),
]
)
actual, _ = expr.__teal__(options)
assert actual == expected
Expand Down Expand Up @@ -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._stored_value.store(
substring_for_decoding(
encoded,
start_index=start_index,
Expand All @@ -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(pt.ScratchVar, value._stored_value).slot,
),
]
)
actual, _ = expr.__teal__(options)
assert actual == expected
Expand All @@ -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(pt.ScratchVar, value_to_set._stored_value).slot,
),
pt.TealOp(
None,
pt.Op.store,
cast(pt.ScratchVar, value._stored_value).slot,
),
]
)

Expand All @@ -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(pt.ScratchVar, value._stored_value).slot,
),
]
)

Expand All @@ -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(pt.ScratchVar, value._stored_value).slot,
),
]
)

Expand Down Expand Up @@ -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(pt.ScratchVar, value._stored_value).slot,
),
pt.TealOp(
None,
pt.Op.load,
cast(pt.ScratchVar, value._stored_value).slot,
),
pt.TealOp(None, pt.Op.len),
pt.TealOp(None, pt.Op.int, AddressLength.Bytes.value),
pt.TealOp(None, pt.Op.eq),
Expand All @@ -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(pt.ScratchVar, other._stored_value).slot,
),
pt.TealOp(
None,
pt.Op.store,
cast(pt.ScratchVar, value._stored_value).slot,
),
]
)

Expand Down Expand Up @@ -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(pt.ScratchVar, value._stored_value).slot,
),
]
)

Expand Down
6 changes: 3 additions & 3 deletions pyteal/ast/abi/array_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -142,15 +142,15 @@ 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.
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:
Expand Down
8 changes: 4 additions & 4 deletions pyteal/ast/abi/array_dynamic.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand All @@ -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"
68 changes: 55 additions & 13 deletions pyteal/ast/abi/array_dynamic_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List
from typing import List, cast

import pytest
import pyteal as pt
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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(pt.ScratchVar, otherArray._stored_value).slot,
),
pt.TealOp(
None,
pt.Op.store,
cast(pt.ScratchVar, value._stored_value).slot,
),
]
)

Expand All @@ -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(pt.ScratchVar, value._stored_value).slot,
),
]
)
actual, _ = expr.__teal__(options)
Expand Down Expand Up @@ -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(pt.ScratchVar, value._stored_value).slot,
),
]
)

Expand All @@ -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(pt.ScratchVar, value._stored_value).slot,
),
pt.TealOp(
None,
pt.Op.load,
cast(pt.ScratchVar, value._stored_value).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(pt.ScratchVar, value._stored_value).slot,
),
pt.TealOp(None, pt.Op.concat),
pt.TealOp(None, pt.Op.store, value.stored_value.slot),
pt.TealOp(
None,
pt.Op.store,
cast(pt.ScratchVar, value._stored_value).slot,
),
]
)

Expand All @@ -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(pt.ScratchVar, value._stored_value).slot,
),
pt.TealOp(None, pt.Op.extract, 2, 0),
]
)
Expand All @@ -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(pt.ScratchVar, value._stored_value).slot,
),
]
)

actual, _ = expr.__teal__(options)
Expand Down

0 comments on commit 2d65bb6

Please sign in to comment.