Skip to content

Commit

Permalink
Merge branch 'release/v1.17.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
algolucky committed Sep 2, 2022
2 parents 9964004 + d59f89b commit e831740
Show file tree
Hide file tree
Showing 21 changed files with 724 additions and 829 deletions.
14 changes: 14 additions & 0 deletions .test-env
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Configs for testing repo download:
SDK_TESTING_URL="https://github.com/algorand/algorand-sdk-testing"
SDK_TESTING_BRANCH="master"
SDK_TESTING_HARNESS="test-harness"

VERBOSE_HARNESS=0

# WARNING: If set to 1, new features will be LOST when downloading the test harness.
# REGARDLESS: modified features are ALWAYS overwritten.
REMOVE_LOCAL_FEATURES=0

# WARNING: Be careful when turning on the next variable.
# In that case you'll need to provide all variables expected by `algorand-sdk-testing`'s `.env`
OVERWRITE_TESTING_ENVIRONMENT=0
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,33 @@
# Changelog

## What's Changed
### Bugfixes
* Bug-fix: Pass verbosity through to testing harness by @tzaffi in https://github.com/algorand/py-algorand-sdk/pull/373
### Enhancements
* Enhancement: Trim the indexer images and use the sandbox instead of custom dockers by @tzaffi in https://github.com/algorand/py-algorand-sdk/pull/367
* Enhancement: Add State Proof support by @shiqizng in https://github.com/algorand/py-algorand-sdk/pull/370
* Enhancement: Deprecating use of langspec by @ahangsu in https://github.com/algorand/py-algorand-sdk/pull/371

## New Contributors
* @ahangsu made their first contribution in https://github.com/algorand/py-algorand-sdk/pull/371

**Full Changelog**: https://github.com/algorand/py-algorand-sdk/compare/v1.16.1...v1.17.0

# v1.17.0b1
## What's Changed
### Bugfixes
* Bug-fix: Pass verbosity through to testing harness by @tzaffi in https://github.com/algorand/py-algorand-sdk/pull/373
### Enhancements
* Enhancement: Trim the indexer images and use the sandbox instead of custom dockers by @tzaffi in https://github.com/algorand/py-algorand-sdk/pull/367
* Enhancement: Add State Proof support by @shiqizng in https://github.com/algorand/py-algorand-sdk/pull/370
* Enhancement: Deprecating use of langspec by @ahangsu in https://github.com/algorand/py-algorand-sdk/pull/371

## New Contributors
* @ahangsu made their first contribution in https://github.com/algorand/py-algorand-sdk/pull/371

**Full Changelog**: https://github.com/algorand/py-algorand-sdk/compare/v1.16.1...v1.17.0b1


# v1.16.1
### Bugfixes
* bug-fix: add check to desc so we dont output null if undefined by @barnjamin in https://github.com/algorand/py-algorand-sdk/pull/368
Expand Down
3 changes: 1 addition & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@ RUN pip install . -q \
&& pip install -r requirements.txt -q

# Run integration tests
CMD ["/bin/bash", "-c", "make unit && make integration"]

CMD ["/bin/bash", "-c", "python --version && make unit && make integration"]
25 changes: 19 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
UNITS = "@unit.abijson or @unit.abijson.byname or @unit.algod or @unit.algod.ledger_refactoring or @unit.applications or @unit.atc_method_args or @unit.atomic_transaction_composer or @unit.dryrun or @unit.dryrun.trace.application or @unit.feetest or @unit.indexer or @unit.indexer.ledger_refactoring or @unit.indexer.logs or @unit.offline or @unit.rekey or @unit.transactions.keyreg or @unit.responses or @unit.responses.231 or @unit.tealsign or @unit.transactions or @unit.transactions.payment or @unit.responses.unlimited_assets or @unit.sourcemap"
UNIT_TAGS := "$(subst :, or ,$(shell awk '{print $2}' tests/unit.tags | paste -s -d: -))"
INTEGRATION_TAGS := "$(subst :, or ,$(shell awk '{print $2}' tests/integration.tags | paste -s -d: -))"

unit:
behave --tags=$(UNITS) tests -f progress2
behave --tags=$(UNIT_TAGS) tests -f progress2

INTEGRATIONS = "@abi or @algod or @applications or @applications.verified or @assets or @auction or @c2c or @compile or @dryrun or @dryrun.testing or @indexer or @indexer.231 or @indexer.applications or @kmd or @rekey_v1 or @send.keyregtxn or @send or @compile.sourcemap"
integration:
behave --tags=$(INTEGRATIONS) tests -f progress2
behave --tags=$(INTEGRATION_TAGS) tests -f progress2 --no-capture

display-all-python-steps:
find tests/steps -name "*.py" | xargs grep "behave" 2>/dev/null | cut -d: -f1 | sort | uniq | xargs awk "/@(given|step|then|when)/,/[)]/" | grep -E "(\".+\"|\'.+\')"

harness:
./test-harness.sh

PYTHON_VERSION ?= 3.8
docker-test:
PYTHON_VERSION='$(PYTHON_VERSION)' ./run_integration.sh
docker-pysdk-build:
docker build -t py-sdk-testing --build-arg PYTHON_VERSION="${PYTHON_VERSION}" .

docker-pysdk-run:
docker ps -a
docker run -it --network host py-sdk-testing:latest

docker-test: harness docker-pysdk-build docker-pysdk-run
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,37 @@ Run `$ pip3 install py-algorand-sdk` to install the package.
Alternatively, choose a [distribution file](https://pypi.org/project/py-algorand-sdk/#files), and run `$ pip3 install [file name]`.

## Supported Python versions

py-algorand-sdk's minimum Python version policy attempts to balance several constraints.

* Make it easy for the community to use py-algorand-sdk by minimizing or excluding the need to customize Python installations.
* Provide maintainers with access to newer language features that produce more robust software.

Given these constraints, the minimum Python version policy is:
Target Python version on newest [Ubuntu LTS](https://wiki.ubuntu.com/Releases) released >= 6 months ago.

The rationale is:

* If a major Linux OS distribution bumps a Python version, then it's sufficiently available to the community for us to upgrade.
* The 6 month time buffer ensures we delay upgrades until the community starts using a recently released LTS version.

## SDK Development

Install dependencies

- `pip3 install -r requirements.txt`
* `pip3 install -r requirements.txt`

Run tests

- `make docker-test`
* `make docker-test`

Set up the Algorand Sandbox based test-harness without running the tests

* `make harness`

Format code:

- `black .`
* `black .`

## Quick start

Expand All @@ -61,6 +68,7 @@ else:
## Node setup

Follow the instructions in Algorand's [developer resources](https://developer.algorand.org/docs/run-a-node/setup/install/) to install a node on your computer.
You can also set up a local [Algorand Sandbox](https://github.com/algorand/sandbox) with `make harness`.

## Running examples/example.py

Expand Down
3 changes: 3 additions & 0 deletions algosdk/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
"""str: indicates an asset transfer transaction"""
APPCALL_TXN = "appl"
"""str: indicates an app call transaction, allows creating, deleting, and interacting with an application"""
STATEPROOF_TXN = "stpf"
"""str: indicates an state proof transaction"""

# note field types
NOTE_FIELD_TYPE_DEPOSIT = "d"
Expand Down Expand Up @@ -134,3 +136,4 @@
logic_sig_max_cost = LOGIC_SIG_MAX_COST
logic_sig_max_size = LOGIC_SIG_MAX_SIZE
app_page_max_size = APP_PAGE_MAX_SIZE
stateproof_txn = STATEPROOF_TXN
131 changes: 128 additions & 3 deletions algosdk/future/transaction.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import List, Union
import base64
import binascii
from enum import IntEnum
import msgpack
from collections import OrderedDict
Expand Down Expand Up @@ -260,6 +261,11 @@ def undictify(d):
elif txn_type == constants.appcall_txn:
args.update(ApplicationCallTxn._undictify(d))
txn = ApplicationCallTxn(**args)
elif txn_type == constants.stateproof_txn:
# a state proof txn does not have these fields
args.pop("note"), args.pop("rekey_to"), args.pop("lease")
args.update(StateProofTxn._undictify(d))
txn = StateProofTxn(**args)
if "grp" in d:
txn.group = d["grp"]
return txn
Expand Down Expand Up @@ -2505,13 +2511,54 @@ class LogicSig:
"""

def __init__(self, program, args=None):
if not program or not logic.check_program(program, args):
raise error.InvalidProgram()
self._sanity_check_program(program)
self.logic = program
self.args = args
self.sig = None
self.msig = None

@staticmethod
def _sanity_check_program(program):
"""
Performs heuristic program validation:
check if passed in bytes are Algorand address, or they are B64 encoded, rather than Teal bytes
Args:
program (bytes): compiled program
"""

def is_ascii_printable(program_bytes):
return all(
map(
lambda x: x == ord("\n") or (ord(" ") <= x <= ord("~")),
program_bytes,
)
)

if not program:
raise error.InvalidProgram("empty program")

if is_ascii_printable(program):
try:
encoding.decode_address(program.decode("utf-8"))
raise error.InvalidProgram(
"requesting program bytes, get Algorand address"
)
except error.WrongChecksumError:
pass
except error.WrongKeyLengthError:
pass

try:
base64.b64decode(program.decode("utf-8"))
raise error.InvalidProgram("program should not be b64 encoded")
except binascii.Error:
pass

raise error.InvalidProgram(
"program bytes are all ASCII printable characters, not looking like Teal byte code"
)

def dictify(self):
od = OrderedDict()
if self.args:
Expand Down Expand Up @@ -2548,7 +2595,7 @@ def verify(self, public_key):
return False

try:
logic.check_program(self.logic, self.args)
self._sanity_check_program(self.logic)
except error.InvalidProgram:
return False

Expand Down Expand Up @@ -2906,6 +2953,84 @@ def __eq__(self, other):
return False


class StateProofTxn(Transaction):
"""
Represents a state proof transaction
Arguments:
sender (str): address of the sender
state_proof (dict(), optional)
state_proof_message (dict(), optional)
state_proof_type (str, optional): state proof type
sp (SuggestedParams): suggested params from algod
Attributes:
sender (str)
sprf (dict())
sprfmsg (dict())
sprf_type (str)
first_valid_round (int)
last_valid_round (int)
genesis_id (str)
genesis_hash (str)
type (str)
"""

def __init__(
self,
sender,
sp,
state_proof=None,
state_proof_message=None,
state_proof_type=None,
):
Transaction.__init__(
self, sender, sp, None, None, constants.stateproof_txn, None
)

self.sprf_type = state_proof_type
self.sprf = state_proof
self.sprfmsg = state_proof_message

def dictify(self):
d = dict()
if self.sprf_type:
d["sptype"] = self.sprf_type
if self.sprfmsg:
d["spmsg"] = self.sprfmsg
if self.sprf:
d["sp"] = self.sprf
d.update(super(StateProofTxn, self).dictify())
od = OrderedDict(sorted(d.items()))

return od

@staticmethod
def _undictify(d):
args = {}
if "sptype" in d:
args["state_proof_type"] = d["sptype"]
if "sp" in d:
args["state_proof"] = d["sp"]
if "spmsg" in d:
args["state_proof_message"] = d["spmsg"]

return args

def __eq__(self, other):
if not isinstance(other, StateProofTxn):
return False
return (
super(StateProofTxn, self).__eq__(other)
and self.sprf_type == other.sprf_type
and self.sprf == other.sprf
and self.sprfmsg == other.sprfmsg
)

return False


def write_to_file(txns, path, overwrite=True):
"""
Write signed or unsigned transactions to a file.
Expand Down
Loading

0 comments on commit e831740

Please sign in to comment.