From 2ed7ab9277f5d3b4924911a8fe78ab00c642a786 Mon Sep 17 00:00:00 2001 From: algochoi <86622919+algochoi@users.noreply.github.com> Date: Mon, 26 Jun 2023 09:56:12 -0400 Subject: [PATCH 1/5] other: Ignore formatting commits in git blame (#485) * Add git blame ignore revs file for black formatting changes * Update .git-blame-ignore-revs * Spacing * Update ubuntu image --- .circleci/config.yml | 2 +- .git-blame-ignore-revs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 .git-blame-ignore-revs diff --git a/.circleci/config.yml b/.circleci/config.yml index 258dcdf9..1cc46bde 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -33,7 +33,7 @@ jobs: python-version: type: string machine: - image: "ubuntu-2004:202104-01" + image: "ubuntu-2204:2022.04.2" steps: - checkout - run: PYTHON_VERSION=<< parameters.python-version >> make docker-test diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000..00235de1 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,8 @@ +# .git-blame-ignore-revs +# Exclude formatting commits made by black +# more black formatting Aug 17, 2021 +a9facdf30ca467b6e16d13ce88d8889bba7f2e1c +# formatting Aug 16, 2021 +ea81ba259216b8be7fb86ef5d3e9c151a94edf87 +# apply black Aug 11, 2021 +81fe44f0dd9785b1665bbbea047aed591912534b From 6153f44d6bfb1483a6eed0bbd80484820a39bf12 Mon Sep 17 00:00:00 2001 From: algobarb <78746954+algobarb@users.noreply.github.com> Date: Fri, 30 Jun 2023 11:05:38 -0400 Subject: [PATCH 2/5] CICD: Fix typos and add team label to release PR workflow (#504) * fix typos and add team label to PR * increase machine size to large for integration-test * remove resource_class * remove py-algorand-sdk references in favor of git context variable * capitalize step name * modify build-changelog method and add check_version in bump_version * remove hyphens from the check python package version * harden checkout actions version --- .github/workflows/create-release-pr.yml | 74 ++++++++----------------- scripts/bump_version.py | 9 +++ 2 files changed, 32 insertions(+), 51 deletions(-) diff --git a/.github/workflows/create-release-pr.yml b/.github/workflows/create-release-pr.yml index 2324bf21..7c3b64fc 100644 --- a/.github/workflows/create-release-pr.yml +++ b/.github/workflows/create-release-pr.yml @@ -43,7 +43,7 @@ jobs: fi - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v3.5.3 with: fetch-depth: 0 @@ -78,52 +78,25 @@ jobs: fi - name: Build Changelog - uses: mikepenz/release-changelog-builder-action@v3.7.2 id: build-changelog env: PREVIOUS_VERSION: ${{ steps.get-release.outputs.latest-tag }} - with: - fromTag: ${{ env.PREVIOUS_VERSION }} - toTag: ${{ env.RELEASE_BRANCH }} - failOnError: true - configurationJson: | - { - "categories": [ - { - "title": "## New Features", - "labels": [ - "New Feature" - ] - }, - { - "title": "## Enhancement", - "labels": [ - "Enhancement" - ] - }, - { - "title": "## Bug Fixes", - "labels": [ - "Bug-Fix" - ] - }, - { - "title": "## Not Yet Enabled", - "labels": [ - "Not-Yet-Enabled" - ] - } - ], - "ignore_labels": [ - "Skip-Release-Notes" - ], - "sort": { - "order": "ASC", - "on_property": "mergedAt" - }, - "template": "#{{CHANGELOG}}", - "pr_template": "- #{{TITLE}} by #{{AUTHOR}} in ##{{NUMBER}}" - } + run: | + CHANGELOG=$(curl -L \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ github.token }}"\ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/${{ github.repository }}/releases/generate-notes \ + -d '{"tag_name":"${{ env.RELEASE_VERSION }}","target_commitish":"${{ env.RELEASE_BRANCH }}","previous_tag_name":"${{ env.PREVIOUS_VERSION }}","configuration_file_path":".github/release.yml"}' \ + | jq -r '.body') + + # The EOF steps are used to save multiline string in github: + # https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#example-of-a-multiline-string + EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) + echo "changelog<<$EOF" >> $GITHUB_OUTPUT + echo -e "${CHANGELOG}" >> $GITHUB_OUTPUT + echo "$EOF" >> $GITHUB_OUTPUT - name: Update Changelog if: ${{ env.PRE_RELEASE_VERSION == '' }} @@ -132,7 +105,7 @@ jobs: PREVIOUS_VERSION: ${{ steps.get-release.outputs.latest-tag }} run: | echo "$(tail -n +2 CHANGELOG.md)" > CHANGELOG.md - echo -e "# Changelog\n\n# ${RELEASE_VERSION}\n\n${CHANGELOG_CONTENT}**Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREVIOUS_VERSION}...${RELEASE_VERSION}" | cat - CHANGELOG.md > temp && mv temp CHANGELOG.md + echo -e "# Changelog\n\n# ${RELEASE_VERSION}\n\n${CHANGELOG_CONTENT}" | cat - CHANGELOG.md > temp && mv temp CHANGELOG.md - name: Update version in setup.py env: @@ -154,14 +127,12 @@ jobs: GH_TOKEN: ${{ github.token }} RELEASE_TAG: ${{ steps.set-release.outputs.release-tag }} run: | - echo -e "# ${RELEASE_TAG}\n\n${CHANGELOG_CONTENT}**Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREVIOUS_VERSION}...${RELEASE_TAG}" > tmp_msg_body.txt - export msg_body=$(cat tmp_msg_body.txt) - rm tmp_msg_body.txt # Note: There's an issue adding teams as reviewers, see https://github.com/cli/cli/issues/6395 PULL_REQUEST_URL=$(gh pr create --base "master" \ - --title "FOR REVIEW ONLY: py-algorand-sdk $RELEASE_TAG" \ + --title "FOR REVIEW ONLY: ${{ github.event.repository.name }} $RELEASE_TAG" \ --label "Skip-Release-Notes" \ - --body "$msg_body" | tail -n 1) + --label "Team Hyper Flow" \ + --body "${CHANGELOG_CONTENT}" | tail -n 1) if [[ $PULL_REQUEST_URL =~ ^https://github.com/${{ github.repository }}/pull/[0-9]+$ ]]; then PULL_REQUEST_NUM=$(echo $PULL_REQUEST_URL | sed 's:.*/::') echo "pull-request-master=$PULL_REQUEST_URL" >> $GITHUB_ENV @@ -180,8 +151,9 @@ jobs: run: | # Note: There's an issue adding teams as reviewers, see https://github.com/cli/cli/issues/6395 PULL_REQUEST_URL=$(gh pr create --base "develop" \ - --title "FOR REVIEW ONLY: Merge back py-algorand-sdk $RELEASE_TAG to develop" \ + --title "FOR REVIEW ONLY: Merge back ${{ github.event.repository.name }} $RELEASE_TAG to develop" \ --label "Skip-Release-Notes" \ + --label "Team Hyper Flow" \ --body "Merge back version changes to develop." | tail -n 1) if [[ $PULL_REQUEST_URL =~ ^https://github.com/${{ github.repository }}/pull/[0-9]+$ ]]; then echo "Pull request to Develop created: $PULL_REQUEST_URL" diff --git a/scripts/bump_version.py b/scripts/bump_version.py index cd388da3..9714903f 100755 --- a/scripts/bump_version.py +++ b/scripts/bump_version.py @@ -3,6 +3,14 @@ import argparse import re +import sys + + +def check_version(new_version): + if not re.fullmatch(r"[0-9]+\.[0-9]+\.[a-z.0-9]+", new_version): + sys.exit( + "The version does not match the regex(major.minor.patch): [0-9]+\.[0-9]+\.[a-z.0-9]+" + ) def bump_version(new_version, setup_py_path): @@ -31,4 +39,5 @@ def bump_version(new_version, setup_py_path): args = parser.parse_args() + check_version(args.new_version) bump_version(args.new_version, args.setup_py_path) From 1d1368b4a60406e19c39a855be909166f91004c5 Mon Sep 17 00:00:00 2001 From: shiqizng <80276844+shiqizng@users.noreply.github.com> Date: Tue, 8 Aug 2023 11:20:29 -0400 Subject: [PATCH 3/5] bug-fix: include currency-greater-than param for 0 value (#508) * include currency-greater-than param for 0 value --- .test-env | 2 +- algosdk/v2client/indexer.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.test-env b/.test-env index 049289d7..a321a7f1 100644 --- a/.test-env +++ b/.test-env @@ -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="V2" SDK_TESTING_HARNESS="test-harness" INSTALL_ONLY=0 diff --git a/algosdk/v2client/indexer.py b/algosdk/v2client/indexer.py index d5cf67e8..c666b902 100644 --- a/algosdk/v2client/indexer.py +++ b/algosdk/v2client/indexer.py @@ -152,7 +152,7 @@ def accounts( query["limit"] = limit if next_page: query["next"] = next_page - if min_balance: + if min_balance is not None: query["currency-greater-than"] = min_balance if max_balance: query["currency-less-than"] = max_balance @@ -204,7 +204,7 @@ def asset_balances( query["limit"] = limit if next_page: query["next"] = next_page - if min_balance: + if min_balance is not None: query["currency-greater-than"] = min_balance if max_balance: query["currency-less-than"] = max_balance @@ -548,7 +548,7 @@ def search_transactions( query["before-time"] = end_time if start_time: query["after-time"] = start_time - if min_amount: + if min_amount is not None: query["currency-greater-than"] = min_amount if max_amount: query["currency-less-than"] = max_amount @@ -650,7 +650,7 @@ def search_transactions_by_address( query["before-time"] = end_time if start_time: query["after-time"] = start_time - if min_amount: + if min_amount is not None: query["currency-greater-than"] = min_amount if max_amount: query["currency-less-than"] = max_amount @@ -752,7 +752,7 @@ def search_asset_transactions( query["before-time"] = end_time if start_time: query["after-time"] = start_time - if min_amount: + if min_amount is not None: query["currency-greater-than"] = min_amount if max_amount: query["currency-less-than"] = max_amount From 8f9721bba793f4b5af13888bd38c03ddd02ddf03 Mon Sep 17 00:00:00 2001 From: Hang Su <87964331+ahangsu@users.noreply.github.com> Date: Thu, 10 Aug 2023 10:29:24 -0400 Subject: [PATCH 4/5] Simulation: Execution trace (PC/Stack/Scratch) support (#505) --- algosdk/atomic_transaction_composer.py | 13 ++- algosdk/v2client/models/__init__.py | 2 + algosdk/v2client/models/simulate_request.py | 44 +++++++- tests/integration.tags | 1 + tests/steps/other_v2_steps.py | 106 ++++++++++++++++++++ 5 files changed, 161 insertions(+), 5 deletions(-) diff --git a/algosdk/atomic_transaction_composer.py b/algosdk/atomic_transaction_composer.py index 24d325aa..4df0985b 100644 --- a/algosdk/atomic_transaction_composer.py +++ b/algosdk/atomic_transaction_composer.py @@ -315,6 +315,7 @@ def __init__( tx_ids: List[str], results: List[SimulateABIResult], eval_overrides: Optional[SimulateEvalOverrides] = None, + exec_trace_config: Optional[models.SimulateTraceConfig] = None, ) -> None: self.version = version self.failure_message = failure_message @@ -323,6 +324,7 @@ def __init__( self.tx_ids = tx_ids self.abi_results = results self.eval_overrides = eval_overrides + self.exec_trace_config = exec_trace_config class AtomicTransactionComposer: @@ -796,8 +798,6 @@ def simulate( # build up data structure with fields we'd want sim_results = [] for idx, result in enumerate(method_results): - sim_txn: Dict[str, Any] = txn_group["txn-results"][idx] - sim_results.append( SimulateABIResult( tx_id=result.tx_id, @@ -809,6 +809,14 @@ def simulate( ) ) + exec_trace_config: Optional[models.SimulateTraceConfig] = ( + None + if "exec-trace-config" not in simulation_result + else models.SimulateTraceConfig.undictify( + simulation_result["exec-trace-config"] + ) + ) + return SimulateAtomicTransactionResponse( version=simulation_result.get("version", 0), failure_message=txn_group.get("failure-message", ""), @@ -819,6 +827,7 @@ def simulate( eval_overrides=SimulateEvalOverrides.from_simulation_result( simulation_result ), + exec_trace_config=exec_trace_config, ) def execute( diff --git a/algosdk/v2client/models/__init__.py b/algosdk/v2client/models/__init__.py index c9625b4f..8a005972 100644 --- a/algosdk/v2client/models/__init__.py +++ b/algosdk/v2client/models/__init__.py @@ -34,6 +34,7 @@ from algosdk.v2client.models.simulate_request import ( SimulateRequest, SimulateRequestTransactionGroup, + SimulateTraceConfig, ) __all__ = [ @@ -52,4 +53,5 @@ "TealValue", "SimulateRequest", "SimulateRequestTransactionGroup", + "SimulateTraceConfig", ] diff --git a/algosdk/v2client/models/simulate_request.py b/algosdk/v2client/models/simulate_request.py index 3bdd651d..5d008cba 100644 --- a/algosdk/v2client/models/simulate_request.py +++ b/algosdk/v2client/models/simulate_request.py @@ -1,10 +1,10 @@ -from typing import List, Dict, Any, TYPE_CHECKING +from typing import List, Dict, Any, TYPE_CHECKING, Optional if TYPE_CHECKING: from algosdk import transaction -class SimulateRequestTransactionGroup(object): +class SimulateRequestTransactionGroup: txns: "List[transaction.GenericSignedTransaction]" def __init__( @@ -16,11 +16,44 @@ def dictify(self) -> Dict[str, Any]: return {"txns": [txn.dictify() for txn in self.txns]} -class SimulateRequest(object): +class SimulateTraceConfig: + enable: bool + stack_change: bool + scratch_change: bool + + def __init__( + self, + *, + enable: bool = False, + stack_change: bool = False, + scratch_change: bool = False, + ) -> None: + self.enable = enable + self.stack_change = stack_change + self.scratch_change = scratch_change + + def dictify(self) -> Dict[str, Any]: + return { + "enable": self.enable, + "stack-change": self.stack_change, + "scratch-change": self.scratch_change, + } + + @staticmethod + def undictify(d: Dict[str, Any]) -> "SimulateTraceConfig": + return SimulateTraceConfig( + enable="enable" in d and d["enable"], + stack_change="stack-change" in d and d["stack-change"], + scratch_change="scratch-change" in d and d["scratch-change"], + ) + + +class SimulateRequest: txn_groups: List[SimulateRequestTransactionGroup] allow_more_logs: bool allow_empty_signatures: bool extra_opcode_budget: int + exec_trace_config: SimulateTraceConfig def __init__( self, @@ -29,11 +62,15 @@ def __init__( allow_more_logs: bool = False, allow_empty_signatures: bool = False, extra_opcode_budget: int = 0, + exec_trace_config: Optional[SimulateTraceConfig] = None, ) -> None: self.txn_groups = txn_groups self.allow_more_logs = allow_more_logs self.allow_empty_signatures = allow_empty_signatures self.extra_opcode_budget = extra_opcode_budget + self.exec_trace_config = ( + exec_trace_config if exec_trace_config else SimulateTraceConfig() + ) def dictify(self) -> Dict[str, Any]: return { @@ -43,4 +80,5 @@ def dictify(self) -> Dict[str, Any]: "allow-more-logging": self.allow_more_logs, "allow-empty-signatures": self.allow_empty_signatures, "extra-opcode-budget": self.extra_opcode_budget, + "exec-trace-config": self.exec_trace_config.dictify(), } diff --git a/tests/integration.tags b/tests/integration.tags index a3bbdd24..660f858b 100644 --- a/tests/integration.tags +++ b/tests/integration.tags @@ -17,3 +17,4 @@ @simulate @simulate.lift_log_limits @simulate.extra_opcode_budget +@simulate.exec_trace_with_stack_scratch \ No newline at end of file diff --git a/tests/steps/other_v2_steps.py b/tests/steps/other_v2_steps.py index 1b128ef2..1064e4cf 100644 --- a/tests/steps/other_v2_steps.py +++ b/tests/steps/other_v2_steps.py @@ -32,6 +32,7 @@ DryrunRequest, DryrunSource, SimulateRequest, + SimulateTraceConfig, ) from tests.steps.steps import algod_port, indexer_port from tests.steps.steps import token as daemon_token @@ -1530,6 +1531,111 @@ def power_pack_simulation_should_have_extra_budget(context, budget): ) +@then( + 'I allow exec trace options "{options:MaybeString}" on that simulate request.' +) +def exec_trace_config_in_simulation(context, options: str): + option_list = options.split(",") + context.simulate_request.exec_trace_config = SimulateTraceConfig( + enable=True, + stack_change="stack" in option_list, + scratch_change="scratch" in option_list, + ) + + +@then( + '{unit_index}th unit in the "{trace_type}" trace at txn-groups path "{group_path}" should add value "{stack_addition:MaybeString}" to stack, pop {pop_count} values from stack, write value "{scratch_var:MaybeString}" to scratch slot "{scratch_index:MaybeString}".' +) +def exec_trace_unit_in_simulation_check_stack_scratch( + context, + unit_index, + trace_type, + group_path, + stack_addition: str, + pop_count, + scratch_var, + scratch_index, +): + assert context.atomic_transaction_composer_return + assert context.atomic_transaction_composer_return.simulate_response + + simulation_response = ( + context.atomic_transaction_composer_return.simulate_response + ) + assert "txn-groups" in simulation_response + + assert simulation_response["txn-groups"] + + group_path = list(map(int, group_path.split(","))) + traces = simulation_response["txn-groups"][0]["txn-results"][ + group_path[0] + ]["exec-trace"] + assert traces + + for i in range(1, len(group_path)): + traces = traces["inner-trace"][group_path[i]] + assert traces + + trace = [] + if trace_type == "approval": + trace = traces["approval-program-trace"] + elif trace_type == "clearState": + trace = traces["clear-state-program-trace"] + elif trace_type == "logic": + trace = traces["logic-sig-trace"] + + assert trace + + unit_index = int(unit_index) + unit = trace[unit_index] + + def compare_avm_value_with_string_literal(string_literal, avm_value): + [avm_type, value] = string_literal.split(":") + assert avm_type in ["uint64", "bytes"] + assert "type" in avm_value + if avm_type == "uint64": + assert avm_value["type"] == 2 + if int(value) > 0: + assert avm_value["uint"] == int(value) + else: + assert "uint" not in avm_value + elif avm_value == "bytes": + assert avm_value["type"] == 1 + if len(value) > 0: + assert avm_value["bytes"] == base64.b64decode(bytearray(value)) + else: + assert "bytes" not in avm_value + + pop_count = int(pop_count) + if pop_count > 0: + assert unit["stack-pop-count"] + assert unit["stack-pop-count"] == pop_count + else: + assert "stack-pop-count" not in unit + + stack_additions = list( + filter(lambda x: len(x) > 0, stack_addition.split(",")) + ) + if len(stack_additions) > 0: + for i in range(0, len(stack_additions)): + compare_avm_value_with_string_literal( + stack_additions[i], unit["stack-additions"][i] + ) + else: + assert "stack-additions" not in unit + + if len(scratch_index) > 0: + scratch_index = int(scratch_index) + assert unit["scratch-changes"] + assert len(unit["scratch-changes"]) == 1 + assert unit["scratch-changes"][0]["slot"] == scratch_index + compare_avm_value_with_string_literal( + scratch_var, unit["scratch-changes"][0]["new-value"] + ) + else: + assert len(scratch_var) == 0 + + @when("we make a SetSyncRound call against round {round}") def set_sync_round_call(context, round): context.response = context.acl.set_sync_round(round) From 0265b9b968a87687f50695ba93a84e7000657883 Mon Sep 17 00:00:00 2001 From: bbroder-algo Date: Wed, 16 Aug 2023 19:31:27 +0000 Subject: [PATCH 5/5] bump up version to v2.4.0 --- CHANGELOG.md | 15 +++++++++++++++ setup.py | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8955c02e..89cd11c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +# v2.4.0 + + + +## What's Changed +### Bugfixes +* bug-fix: include currency-greater-than param for 0 value by @shiqizng in https://github.com/algorand/py-algorand-sdk/pull/508 +### New Features +* Simulation: Execution trace (PC/Stack/Scratch) support by @ahangsu in https://github.com/algorand/py-algorand-sdk/pull/505 +### Enhancements +* other: Ignore formatting commits in git blame by @algochoi in https://github.com/algorand/py-algorand-sdk/pull/485 + + +**Full Changelog**: https://github.com/algorand/py-algorand-sdk/compare/v2.3.0...v2.4.0 + # v2.3.0 ## New Features diff --git a/setup.py b/setup.py index 19296aa6..c06215bf 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ description="Algorand SDK in Python", author="Algorand", author_email="pypiservice@algorand.com", - version="2.3.0", + version="2.4.0", long_description=long_description, long_description_content_type="text/markdown", url="https://github.com/algorand/py-algorand-sdk",