Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Changes to avm8 docs #546

Merged
merged 1 commit into from
Sep 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 37 additions & 26 deletions docs/state.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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`
ahangsu marked this conversation as resolved.
Show resolved Hide resolved
================== ======================= ======================== ======================== ===================== =======================

Global State
Expand Down Expand Up @@ -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."))

Expand Down Expand Up @@ -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.
Expand All @@ -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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -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::

Expand Down
42 changes: 23 additions & 19 deletions pyteal/ast/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -232,19 +238,21 @@ 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.
"""
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.
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -277,18 +283,16 @@ 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.
"""
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.
Expand Down
16 changes: 8 additions & 8 deletions pyteal/ast/box_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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]),
ahangsu marked this conversation as resolved.
Show resolved Hide resolved
]
)
actual, _ = expr.__teal__(avm8Options)
Expand Down
4 changes: 2 additions & 2 deletions pyteal/ast/maybe.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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]
Expand Down