Skip to content
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
45 changes: 40 additions & 5 deletions tests/blackbox.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
from typing import Callable
from typing import Callable, Sequence

import algosdk.abi
from algosdk.v2client import algod

from graviton import blackbox
from graviton.blackbox import DryRunInspector, DryRunExecutor
from graviton.dryrun import ZERO_ADDRESS

from pyteal import (
abi,
Arg,
Btoi,
Bytes,
compileTeal,
Expr,
Int,
Itob,
Expand Down Expand Up @@ -140,12 +143,12 @@ def mode_to_execution_mode(mode: Mode) -> blackbox.ExecutionMode:

def blackbox_pyteal(subr: BlackboxWrapper, mode: Mode) -> Expr:
"""
cf. BlackboxPyTealer.program() for futher details
cf. PyTealDryRunExecutor.program() for futher details
"""
return BlackboxPyTealer(subr, mode).program()
return PyTealDryRunExecutor(subr, mode).program()


class BlackboxPyTealer:
class PyTealDryRunExecutor:
def __init__(self, subr: BlackboxWrapper, mode: Mode):
"""
Args:
Expand Down Expand Up @@ -252,7 +255,7 @@ def program(self) -> Expr:
* `blackbox_pyteal_example1()`: Using blackbox_pyteal() for a simple test of both an app and logic sig
* `blackbox_pyteal_example2()`: Using blackbox_pyteal() to make 400 assertions and generate a CSV report with 400 dryrun rows
* `blackbox_pyteal_example3()`: declarative Test Driven Development approach through Invariant's
* `blackbox_pyteal_example4()`: Using BlackboxPyTealer.program() to debug an ABIReturnSubroutine with an app, logic sig and csv report
* `blackbox_pyteal_example4()`: Using PyTealDryRunExecutor to debug an ABIReturnSubroutine with an app, logic sig and csv report
"""

return self._pyteal_lambda()
Expand Down Expand Up @@ -374,3 +377,35 @@ def approval():
return Seq(*(preps + results))

return approval

def dryrun_on_sequence(
self,
inputs: list[Sequence[str | int]],
compiler_version=6,
sender: str = ZERO_ADDRESS,
) -> list[DryRunInspector]:
match self.mode:
case Mode.Application:
return DryRunExecutor.dryrun_app_on_sequence(
algod_with_assertion(),
compileTeal(
self.program(), Mode.Application, version=compiler_version
),
inputs,
self.abi_argument_types(),
self.abi_return_type(),
sender,
)
case Mode.Signature:
return DryRunExecutor.dryrun_logicsig_on_sequence(
algod_with_assertion(),
compileTeal(
self.program(), Mode.Signature, version=compiler_version
),
inputs,
self.abi_argument_types(),
self.abi_return_type(),
sender,
)
case _:
raise Exception(f"Unknown mode {self.mode} of type {type(self.mode)}")
8 changes: 4 additions & 4 deletions tests/integration/abi_roundtrip_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from pyteal import abi
import pyteal as pt

from tests.blackbox import Blackbox, BlackboxPyTealer
from tests.blackbox import Blackbox, PyTealDryRunExecutor

T = TypeVar("T", bound=abi.BaseType)

Expand Down Expand Up @@ -95,9 +95,9 @@ def round_tripper(x: t, *, output: abi.Tuple2[t, t]):
return round_tripper


def roundtrip_pytealer(t: type[T], dynamic_length: int):
roundtrip = roundtrip_factory(t, dynamic_length)
return BlackboxPyTealer(roundtrip, pt.Mode.Application)
def roundtrip_pytealer(t: type[T]):
roundtrip = roundtrip_factory(t)
return PyTealDryRunExecutor(roundtrip, pt.Mode.Application)


ABI_TYPES = [
Expand Down
156 changes: 35 additions & 121 deletions tests/integration/graviton_abi_test.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import random

from graviton.blackbox import DryRunExecutor
from graviton.blackbox import DryRunInspector

import pyteal as pt
from pyteal.ast.subroutine import ABIReturnSubroutine

from tests.blackbox import (
Blackbox,
BlackboxPyTealer,
algod_with_assertion,
PyTealDryRunExecutor,
)


Expand Down Expand Up @@ -249,34 +248,15 @@ def complex130_norm_squared(x: Complex130, *, output: Int65):


def test_integer65():
bbpt_subtract_slick = BlackboxPyTealer(int65_sub, pt.Mode.Application)
approval_subtract_slick = bbpt_subtract_slick.program()
teal_subtract_slick = pt.compileTeal(
approval_subtract_slick, pt.Mode.Application, version=6
)

bbpt_subtract_cond = BlackboxPyTealer(int65_minus_cond, pt.Mode.Application)
approval_subtract_cond = bbpt_subtract_cond.program()
teal_subtract_cond = pt.compileTeal(
approval_subtract_cond, pt.Mode.Application, version=6
)
bbpt_subtract_slick = PyTealDryRunExecutor(int65_sub, pt.Mode.Application)

bbpt_mult = BlackboxPyTealer(int65_mult, pt.Mode.Application)
approval_mult = bbpt_mult.program()
teal_mult = pt.compileTeal(approval_mult, pt.Mode.Application, version=6)
bbpt_subtract_cond = PyTealDryRunExecutor(int65_minus_cond, pt.Mode.Application)

bbpt_negate = BlackboxPyTealer(int65_negate, pt.Mode.Application)
approval_negate = bbpt_negate.program()
teal_negate = pt.compileTeal(approval_negate, pt.Mode.Application, version=6)
bbpt_mult = PyTealDryRunExecutor(int65_mult, pt.Mode.Application)

bbpt_add = BlackboxPyTealer(int65_add, pt.Mode.Application)
approval_add = bbpt_add.program()
teal_add = pt.compileTeal(approval_add, pt.Mode.Application, version=6)
bbpt_negate = PyTealDryRunExecutor(int65_negate, pt.Mode.Application)

# same types, so no need to dupe:
unary_abi_argument_types = bbpt_negate.abi_argument_types()
binary_abi_argument_types = bbpt_subtract_slick.abi_argument_types()
abi_return_type = bbpt_subtract_slick.abi_return_type()
bbpt_add = PyTealDryRunExecutor(int65_add, pt.Mode.Application)

def pynum_to_tuple(n):
return (n >= 0, abs(n))
Expand All @@ -296,34 +276,20 @@ def pytuple_to_num(t):
for x, y in zip(random.sample(choices, N), random.sample(choices, N))
]

algod = algod_with_assertion()
def binary_dryrun(p: PyTealDryRunExecutor) -> list[DryRunInspector]:
return p.dryrun_on_sequence(binary_inputs)

# Binary:
inspectors_subtract_slick = DryRunExecutor.dryrun_app_on_sequence(
algod,
teal_subtract_slick,
binary_inputs,
binary_abi_argument_types,
abi_return_type,
)
inspectors_subtract_cond = DryRunExecutor.dryrun_app_on_sequence(
algod,
teal_subtract_cond,
binary_inputs,
binary_abi_argument_types,
abi_return_type,
)
inspectors_mult = DryRunExecutor.dryrun_app_on_sequence(
algod, teal_mult, binary_inputs, binary_abi_argument_types, abi_return_type
)
inspectors_add = DryRunExecutor.dryrun_app_on_sequence(
algod, teal_add, binary_inputs, binary_abi_argument_types, abi_return_type
)
inspectors_subtract_slick = binary_dryrun(bbpt_subtract_slick)

inspectors_subtract_cond = binary_dryrun(bbpt_subtract_cond)

inspectors_mult = binary_dryrun(bbpt_mult)

inspectors_add = binary_dryrun(bbpt_add)

# Unary:
inspectors_negate = DryRunExecutor.dryrun_app_on_sequence(
algod, teal_negate, unary_inputs, unary_abi_argument_types, abi_return_type
)
inspectors_negate = bbpt_negate.dryrun_on_sequence(unary_inputs)

for i in range(N):
binary_args = binary_inputs[i]
Expand Down Expand Up @@ -367,43 +333,23 @@ def pytuple_to_num(t):
def test_complex130():
# Binary:

bbpt_cplx_add = BlackboxPyTealer(complex130_add, pt.Mode.Application)
approval_cplx_add = bbpt_cplx_add.program()
teal_cplx_add = pt.compileTeal(approval_cplx_add, pt.Mode.Application, version=6)
bbpt_cplx_add = PyTealDryRunExecutor(complex130_add, pt.Mode.Application)

bbpt_cplx_mult = BlackboxPyTealer(complex130_mult, pt.Mode.Application)
approval_cplx_mult = bbpt_cplx_mult.program()
teal_cplx_mult = pt.compileTeal(approval_cplx_mult, pt.Mode.Application, version=6)
bbpt_cplx_mult = PyTealDryRunExecutor(complex130_mult, pt.Mode.Application)

# Unary:

bbpt_complex_real = BlackboxPyTealer(complex130_real, pt.Mode.Application)
approval_cplx_real = bbpt_complex_real.program()
teal_cplx_real = pt.compileTeal(approval_cplx_real, pt.Mode.Application, version=6)
bbpt_complex_real = PyTealDryRunExecutor(complex130_real, pt.Mode.Application)

bbpt_complex_imag = BlackboxPyTealer(complex130_imag, pt.Mode.Application)
approval_cplx_imag = bbpt_complex_imag.program()
teal_cplx_imag = pt.compileTeal(approval_cplx_imag, pt.Mode.Application, version=6)
bbpt_complex_imag = PyTealDryRunExecutor(complex130_imag, pt.Mode.Application)

bbpt_complex_conjugate = BlackboxPyTealer(complex130_conjugate, pt.Mode.Application)
approval_cplx_conjugate = bbpt_complex_conjugate.program()
teal_cplx_conjugate = pt.compileTeal(
approval_cplx_conjugate, pt.Mode.Application, version=6
bbpt_complex_conjugate = PyTealDryRunExecutor(
complex130_conjugate, pt.Mode.Application
)

bbpt_complex_norm_squared = BlackboxPyTealer(
bbpt_complex_norm_squared = PyTealDryRunExecutor(
complex130_norm_squared, pt.Mode.Application
)
approval_cplx_norm_squared = bbpt_complex_norm_squared.program()
teal_cplx_norm_squared = pt.compileTeal(
approval_cplx_norm_squared, pt.Mode.Application, version=6
)

unary_abi_argument_types = bbpt_complex_real.abi_argument_types()
binary_abi_argument_types = bbpt_cplx_add.abi_argument_types()

real_abi_return_type = bbpt_complex_real.abi_return_type()
complex_abi_return_type = bbpt_cplx_add.abi_return_type()

def pyint_to_tuple(n):
return (n >= 0, abs(n))
Expand Down Expand Up @@ -439,57 +385,25 @@ def pytuple_to_complex(tt):
)
]

algod = algod_with_assertion()
def binary_dryrun(p: PyTealDryRunExecutor) -> list[DryRunInspector]:
return p.dryrun_on_sequence(binary_inputs)

# Binary:
inspectors_cplx_add = DryRunExecutor.dryrun_app_on_sequence(
algod,
teal_cplx_add,
binary_inputs,
binary_abi_argument_types,
complex_abi_return_type,
)
inspectors_cplx_add = binary_dryrun(bbpt_cplx_add)

inspectors_cplx_mult = DryRunExecutor.dryrun_app_on_sequence(
algod,
teal_cplx_mult,
binary_inputs,
binary_abi_argument_types,
complex_abi_return_type,
)
inspectors_cplx_mult = binary_dryrun(bbpt_cplx_mult)

def unary_dryrun(p: PyTealDryRunExecutor) -> list[DryRunInspector]:
return p.dryrun_on_sequence(unary_inputs)

# Unary:
inspectors_cplx_real = DryRunExecutor.dryrun_app_on_sequence(
algod,
teal_cplx_real,
unary_inputs,
unary_abi_argument_types,
real_abi_return_type,
)
inspectors_cplx_real = unary_dryrun(bbpt_complex_real)

inspectors_cplx_imag = DryRunExecutor.dryrun_app_on_sequence(
algod,
teal_cplx_imag,
unary_inputs,
unary_abi_argument_types,
real_abi_return_type,
)
inspectors_cplx_imag = unary_dryrun(bbpt_complex_imag)

inspectors_cplx_conjugate = DryRunExecutor.dryrun_app_on_sequence(
algod,
teal_cplx_conjugate,
unary_inputs,
unary_abi_argument_types,
complex_abi_return_type,
)
inspectors_cplx_conjugate = unary_dryrun(bbpt_complex_conjugate)

inspectors_cplx_norm_squared = DryRunExecutor.dryrun_app_on_sequence(
algod,
teal_cplx_norm_squared,
unary_inputs,
unary_abi_argument_types,
real_abi_return_type,
)
inspectors_cplx_norm_squared = unary_dryrun(bbpt_complex_norm_squared)

for i in range(N):
binary_args = binary_inputs[i]
Expand Down
35 changes: 9 additions & 26 deletions tests/integration/graviton_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -758,15 +758,14 @@ def euclid(x, y):


def blackbox_pyteal_example4():
# Example 4: Using BlackboxPyTealer.program() to debug an ABIReturnSubroutine with an app, logic sig and csv report
# Example 4: Using PyTealDryRunExecutor to debug an ABIReturnSubroutine with an app, logic sig and csv report
from pathlib import Path
import random

from graviton.blackbox import DryRunExecutor, DryRunInspector
from graviton.blackbox import DryRunInspector

from pyteal import (
abi,
compileTeal,
ABIReturnSubroutine,
Expr,
For,
Expand All @@ -777,7 +776,7 @@ def blackbox_pyteal_example4():
TealType,
)

from tests.blackbox import Blackbox, BlackboxPyTealer, algod_with_assertion
from tests.blackbox import Blackbox, PyTealDryRunExecutor

# Sum a dynamic uint64 array
@Blackbox(input_types=[None])
Expand All @@ -799,21 +798,10 @@ def abi_sum(toSum: abi.DynamicArray[abi.Uint64], *, output: abi.Uint64) -> Expr:
),
)

# instantiate BlackboxPyTealer objects for the app and lsig:
app_pytealer = BlackboxPyTealer(abi_sum, Mode.Application)
lsig_pytealer = BlackboxPyTealer(abi_sum, Mode.Signature)

# create approval PyTeal app and lsig:
pyteal_abi_sum_app = app_pytealer.program()
pyteal_abi_sum_lsig = lsig_pytealer.program()
# instantiate PyTealDryRunExecutor objects for the app and lsig:
app_pytealer = PyTealDryRunExecutor(abi_sum, Mode.Application)
lsig_pytealer = PyTealDryRunExecutor(abi_sum, Mode.Signature)

# compile the PyTeal's to Teal's:
teal_abi_sum_app = compileTeal(pyteal_abi_sum_app, Mode.Application, version=6)
teal_abi_sum_lsig = compileTeal(pyteal_abi_sum_lsig, Mode.Signature, version=6)

# infer the abi types for encoding/decoding dry runs:
abi_argument_types = app_pytealer.abi_argument_types()
abi_return_type = app_pytealer.abi_return_type()
# generate reports with the same random inputs (fix the randomness with a seed):
random.seed(42)

Expand All @@ -823,15 +811,10 @@ def abi_sum(toSum: abi.DynamicArray[abi.Uint64], *, output: abi.Uint64) -> Expr:
for n in range(N):
inputs.append(tuple([random.sample(choices, n)]))

# execute the dry-run sequence:
algod = algod_with_assertion()
app_inspectors = app_pytealer.dryrun_on_sequence(inputs)

lsig_inspectors = lsig_pytealer.dryrun_on_sequence(inputs)

app_inspectors = DryRunExecutor.dryrun_app_on_sequence(
algod, teal_abi_sum_app, inputs, abi_argument_types, abi_return_type
)
lsig_inspectors = DryRunExecutor.dryrun_logicsig_on_sequence(
algod, teal_abi_sum_lsig, inputs, abi_argument_types, abi_return_type
)
for i in range(N):
app_inspector = app_inspectors[i]
lsig_inspector = lsig_inspectors[i]
Expand Down
Loading