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

Simulation: Lift log limits option in SimulateRequest #469

Merged
merged 23 commits into from
Apr 28, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion .test-env
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Configs for testing repo download:
SDK_TESTING_URL="https://github.com/algorand/algorand-sdk-testing"
SDK_TESTING_BRANCH="master"
SDK_TESTING_BRANCH="simulate-request-log-option"
ahangsu marked this conversation as resolved.
Show resolved Hide resolved
SDK_TESTING_HARNESS="test-harness"

INSTALL_ONLY=0
Expand Down
73 changes: 73 additions & 0 deletions algosdk/atomic_transaction_composer.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from algosdk.transaction import GenericSignedTransaction
from algosdk.abi.address_type import AddressType
from algosdk.v2client import algod
from algosdk.v2client import models
ahangsu marked this conversation as resolved.
Show resolved Hide resolved

# The first four bytes of an ABI method call return must have this hash
ABI_RETURN_HASH = b"\x15\x1f\x7c\x75"
Expand Down Expand Up @@ -266,6 +267,34 @@ def __init__(
self.missing_signature = missing_signature


class SimulateEvalOverrides:
def __init__(
self,
*,
max_log_calls: Optional[int] = None,
ahangsu marked this conversation as resolved.
Show resolved Hide resolved
max_log_size: Optional[int] = None,
) -> None:
self.max_log_calls = max_log_calls
self.max_log_size = max_log_size

@staticmethod
def from_simulation_result(
simulation_result: Dict[str, Any]
) -> Optional["SimulateEvalOverrides"]:
if "eval-overrides" not in simulation_result:
return None

eval_override_dict = simulation_result.get("eval-overrides", dict())
eval_override = SimulateEvalOverrides()

if "max-log-calls" in eval_override_dict:
eval_override.max_log_calls = eval_override_dict["max-log-calls"]
if "max-log-size" in eval_override_dict:
eval_override.max_log_size = eval_override_dict["max-log-size"]

return eval_override


class SimulateAtomicTransactionResponse:
def __init__(
self,
Expand All @@ -276,6 +305,7 @@ def __init__(
simulate_response: Dict[str, Any],
tx_ids: List[str],
results: List[SimulateABIResult],
eval_overrides: Optional[SimulateEvalOverrides] = None,
) -> None:
self.version = version
self.would_succeed = would_succeed
Expand All @@ -284,6 +314,7 @@ def __init__(
self.simulate_response = simulate_response
self.tx_ids = tx_ids
self.abi_results = results
self.eval_overrides = eval_overrides


class AtomicTransactionComposer:
Expand Down Expand Up @@ -716,6 +747,9 @@ def simulate(
simulation_result = cast(
Dict[str, Any], client.simulate_raw_transactions(self.signed_txns)
)
return self.__report_simulation_response(simulation_result)

def __report_simulation_response(self, simulation_result: Dict[str, Any]):
# Only take the first group in the simulate response
txn_group: Dict[str, Any] = simulation_result["txn-groups"][0]

Expand Down Expand Up @@ -766,7 +800,46 @@ def simulate(
simulate_response=simulation_result,
tx_ids=self.tx_ids,
results=sim_results,
eval_overrides=SimulateEvalOverrides.from_simulation_result(
simulation_result
),
)

def simulate_with_request(
ahangsu marked this conversation as resolved.
Show resolved Hide resolved
self,
client: algod.AlgodClient,
request: models.SimulateRequest = models.SimulateRequest(
ahangsu marked this conversation as resolved.
Show resolved Hide resolved
txn_groups=list()
),
):
current_simulation_request = request

if (
self.status < AtomicTransactionComposerStatus.BUILT
or self.status > AtomicTransactionComposerStatus.SUBMITTED
):
raise error.AtomicTransactionComposerError(
"AtomicTransactionComposerStatus must be in range [BUILT, SUBMITTED] "
"to simulate a group"
)
elif self.status == AtomicTransactionComposerStatus.BUILT:
unsigned_txn: List[transaction.GenericSignedTransaction] = [
transaction.SignedTransaction(txn_with_signer.txn, "")
for txn_with_signer in self.txn_list
]
current_simulation_request.txn_groups = [
models.SimulateRequestTransactionGroup(txns=unsigned_txn)
]
else:
current_simulation_request.txn_groups = [
models.SimulateRequestTransactionGroup(txns=self.signed_txns)
]

simulation_result = cast(
Dict[str, Any],
client.simulate_transactions(current_simulation_request),
)
return self.__report_simulation_response(simulation_result)

def execute(
self, client: algod.AlgodClient, wait_rounds: int
Expand Down
10 changes: 8 additions & 2 deletions algosdk/v2client/models/simulate_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,21 @@ def dictify(self) -> Dict[str, Any]:

class SimulateRequest(object):
txn_groups: List[SimulateRequestTransactionGroup]
lift_log_limits: bool

def __init__(
self, *, txn_groups: List[SimulateRequestTransactionGroup]
self,
*,
txn_groups: List[SimulateRequestTransactionGroup],
lift_log_limits: bool = False,
) -> None:
self.txn_groups = txn_groups
self.lift_log_limits = lift_log_limits

def dictify(self) -> Dict[str, Any]:
return {
"txn-groups": [
txn_group.dictify() for txn_group in self.txn_groups
]
],
"lift-log-limits": self.lift_log_limits,
}
1 change: 1 addition & 0 deletions tests/integration.tags
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@
@send
@send.keyregtxn
@simulate
@simulate.lift_log_limits
6 changes: 6 additions & 0 deletions tests/steps/other_v2_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
ApplicationLocalState,
DryrunRequest,
DryrunSource,
SimulateRequest,
)
from tests.steps.steps import algod_port, indexer_port
from tests.steps.steps import token as daemon_token
Expand Down Expand Up @@ -1474,6 +1475,11 @@ def simulate_atc_failure(context, group, path, message):
assert message in resp.failure_message


@when("I make a new simulate request")
def make_simulate_request(context):
context.simulate_request = SimulateRequest(txn_groups=[])


@when("I prepare the transaction without signatures for simulation")
def step_impl(context):
context.stx = transaction.SignedTransaction(context.txn, None)
Expand Down