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

template bug fixes #71

Merged
merged 15 commits into from
Feb 12, 2020
7 changes: 3 additions & 4 deletions algosdk/encoding.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import base64
import msgpack
from collections import OrderedDict
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
from Cryptodome.Hash import SHA512
from . import transaction, error, auction, constants


Expand Down Expand Up @@ -168,6 +167,6 @@ def checksum(data):
Returns:
bytes: checksum of the data
"""
chksum = hashes.Hash(hashes.SHA512_256(), default_backend())
chksum = SHA512.new(truncate="256")
chksum.update(data)
return chksum.finalize()
return chksum.digest()
64 changes: 64 additions & 0 deletions algosdk/template.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import math
import random
from . import error, encoding, constants, transaction, logic, account
from Cryptodome.Hash import SHA256, keccak
import base64


Expand Down Expand Up @@ -91,6 +92,7 @@ def get_split_funds_transaction(contract, amount: int, fee: int, first_valid,
rat_1 = ints[6]
rat_2 = ints[5]
min_pay = ints[7]
max_fee = ints[1]
receiver_1 = encoding.encode_address(bytearrays[1])
receiver_2 = encoding.encode_address(bytearrays[2])

Expand Down Expand Up @@ -124,6 +126,9 @@ def get_split_funds_transaction(contract, amount: int, fee: int, first_valid,
stx_1 = transaction.LogicSigTransaction(txn_1, lsig)
stx_2 = transaction.LogicSigTransaction(txn_2, lsig)

if txn_1.fee > max_fee or txn_2.fee > max_fee:
raise error.TemplateInputError("the transaction fee should not be greater than " + str(max_fee))

return [stx_1, stx_2]


Expand Down Expand Up @@ -179,6 +184,56 @@ def get_program(self):
types = [int, int, "address", "base64", "address", int]
return inject(orig, offsets, values, types)

@staticmethod
def get_transaction(contract, preimage, first_valid, last_valid, gh, fee):
"""
Return a transaction which will release funds if a matching preimage is used.

Args:
contract (bytes): the contract containing information, should be
received from payer
preimage (str): the preimage of the hash in base64
first_valid (int): first valid round for the transactions
last_valid (int): last valid round for the transactions
gh (str): genesis hash in base64
fee (int): fee per byte

Returns:
LogicSigTransaction: transaction to claim algos from
contract account
"""
_, ints, bytearrays = logic.read_program(contract)
if not (len(ints) == 4 and len(bytearrays) == 3):
raise error.WrongContractError("split")
max_fee = ints[0]
hash_function = contract[-15]
mjiang102628 marked this conversation as resolved.
Show resolved Hide resolved
expected_hash_image = bytearrays[1]
if hash_function == 1:
hash_image = SHA256.new()
hash_image.update(base64.b64decode(preimage))
if hash_image.digest() != expected_hash_image:
raise error.TemplateInputError("the hash of the preimage does not match the expected hash image using hash function sha256")
elif hash_function == 2:
hash_image = keccak.new(digest_bits=256)
hash_image.update(base64.b64decode(preimage))
print(hash_image.digest())
print(expected_hash_image)
if hash_image.digest() != expected_hash_image:
raise error.TemplateInputError("the hash of the preimage does not match the expected hash image using hash function keccak256")
else:
raise error.TemplateInputError("an invalid hash function was provided in the contract")

receiver = encoding.encode_address(bytearrays[0])

lsig = transaction.LogicSig(contract, [base64.b64decode(preimage)])
txn = transaction.PaymentTxn(logic.address(contract), fee, first_valid, last_valid, gh, None, 0, close_remainder_to=receiver)

if txn.fee > max_fee:
raise error.TemplateInputError("the transaction fee should not be greater than " + str(max_fee))
mjiang102628 marked this conversation as resolved.
Show resolved Hide resolved

ltxn = transaction.LogicSigTransaction(txn, lsig)
return ltxn


class DynamicFee(Template):
"""
Expand Down Expand Up @@ -345,6 +400,7 @@ def get_withdrawal_transaction(contract, first_valid, gh, fee):
amount = ints[5]
withdrawing_window = ints[4]
period = ints[2]
max_fee = ints[1]
lease_value = bytearrays[0]
receiver = encoding.encode_address(bytearrays[1])

Expand All @@ -354,6 +410,9 @@ def get_withdrawal_transaction(contract, first_valid, gh, fee):
address, fee, first_valid, first_valid + withdrawing_window, gh,
receiver, amount, lease=lease_value)

if txn.fee > max_fee:
raise error.TemplateInputError("the transaction fee should not be greater than " + str(max_fee))

lsig = transaction.LogicSig(contract)
stx = transaction.LogicSigTransaction(txn, lsig)
return stx
Expand Down Expand Up @@ -433,6 +492,7 @@ def get_swap_assets_transactions(contract: bytes, asset_amount: int,
asset_id = ints[6]
ratn = ints[8]
ratd = ints[7]
max_fee = ints[2]
owner = encoding.encode_address(bytearrays[0])

if microalgo_amount < min_trade:
Expand All @@ -453,6 +513,10 @@ def get_swap_assets_transactions(contract: bytes, asset_amount: int,
account.address_from_private_key(private_key), fee,
first_valid, last_valid, gh, owner, asset_amount, asset_id)

if txn_1.fee > max_fee or txn_2.fee > max_fee:
raise error.TemplateInputError("the transaction fee should not be greater than " + str(max_fee))


transaction.assign_group_id([txn_1, txn_2])

lsig = transaction.LogicSig(contract)
Expand Down
8 changes: 5 additions & 3 deletions algosdk/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ def dictify(self):
d["amt"] = self.amt
if self.close_remainder_to:
d["close"] = encoding.decode_address(self.close_remainder_to)
d["rcv"] = encoding.decode_address(self.receiver)
if self.receiver:
d["rcv"] = encoding.decode_address(self.receiver)

d.update(super(PaymentTxn, self).dictify())
od = OrderedDict(sorted(d.items()))
Expand All @@ -218,7 +219,8 @@ def _undictify(d):
"close_remainder_to": encoding.encode_address(
d["close"]) if "close" in d else None,
"amt": d["amt"] if "amt" in d else 0,
"receiver": encoding.encode_address(d["rcv"])
"receiver": encoding.encode_address(
d["rcv"]) if "rcv" in d else None
}
return args

Expand Down Expand Up @@ -1067,9 +1069,9 @@ def __init__(self, program, args=None):

def dictify(self):
od = OrderedDict()
od["l"] = self.logic
if self.args:
od["arg"] = self.args
od["l"] = self.logic
if self.sig:
od["sig"] = base64.b64decode(self.sig)
elif self.msig:
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
project_urls={
"Source": "https://github.com/algorand/py-algorand-sdk",
},
install_requires=["pynacl", "cryptography>=2.7", "msgpack"],
install_requires=["pynacl", "pycryptodomex>=3.6.0", "msgpack"],
packages=["algosdk"],
python_requires=">=3.5",
package_data={'': ['data/langspec.json']},
Expand Down
53 changes: 32 additions & 21 deletions test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -1216,19 +1216,31 @@ def test_split(self):
def test_HTLC(self):
addr1 = "726KBOYUJJNE5J5UHCSGQGWIBZWKCBN4WYD7YVSTEXEVNFPWUIJ7TAEOPM"
addr2 = "42NJMHTPFVPXVSDGA6JGKUV6TARV5UZTMPFIREMLXHETRKIVW34QFSDFRE"
s = template.HTLC(addr1, addr2, "sha256",
"f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk=",
600000, 1000)
golden_addr = ("KNBD7ATNUVQ4NTLOI72EEUWBVMBNK" +
"MPHWVBCETERV2W7T2YO6CVMLJRBM4")

golden = ("ASAE6AcBAMDPJCYDIOaalh5vLV96yGYHkmVSvpgjXtMzY8qIkYu5yTip" +
"Fbb5IH+DsWV/8fxTuS3BgUih1l38LUsfo9Z3KErd0gASbZBpIP68oLsU" +
"SlpOp7Q4pGgayA5soQW8tgf8VlMlyVaV9qITMQEiDjEQIxIQMQcyAxIQ" +
"MQgkEhAxCSgSLQEpEhAxCSoSMQIlDRAREA==")
preimage = "cHJlaW1hZ2U="
hash_image = "EHZhE08h/HwCIj1Qq56zYAvD/8NxJCOh5Hux+anb9V8="
s = template.HTLC(addr1, addr2, "sha256", hash_image, 600000, 1000)
golden_addr = (
"FBZIR3RWVT2BTGVOG25H3VAOLVD54RTCRNRLQCCJJO6SVSCT5IVDYKNCSU")

golden = (
"ASAE6AcBAMDPJCYDIOaalh5vLV96yGYHkmVSvpgjXtMzY8qIkYu5yTipFbb5IB" +
"B2YRNPIfx8AiI9UKues2ALw//DcSQjoeR7sfmp2/VfIP68oLsUSlpOp7Q4pGga" +
"yA5soQW8tgf8VlMlyVaV9qITMQEiDjEQIxIQMQcyAxIQMQgkEhAxCSgSLQEpEh" +
"AxCSoSMQIlDRAREA==")
p = s.get_program()
self.assertEqual(p, base64.b64decode(golden))
self.assertEqual(s.get_address(), golden_addr)
golden_ltxn = (
"gqRsc2lngqNhcmeRxAhwcmVpbWFnZaFsxJcBIAToBwEAwM8kJgMg5pqWHm8tX3" +
"rIZgeSZVK+mCNe0zNjyoiRi7nJOKkVtvkgEHZhE08h/HwCIj1Qq56zYAvD/8Nx" +
"JCOh5Hux+anb9V8g/ryguxRKWk6ntDikaBrIDmyhBby2B/xWUyXJVpX2ohMxAS" +
"IOMRAjEhAxBzIDEhAxCCQSEDEJKBItASkSEDEJKhIxAiUNEBEQo3R4boelY2xv" +
"c2XEIOaalh5vLV96yGYHkmVSvpgjXtMzY8qIkYu5yTipFbb5o2ZlZc0D6KJmdg" +
"GiZ2jEIH+DsWV/8fxTuS3BgUih1l38LUsfo9Z3KErd0gASbZBpomx2ZKNzbmTE" +
"IChyiO42rPQZmq42un3UDl1H3kZii2K4CElLvSrIU+oqpHR5cGWjcGF5")
ltxn = template.HTLC.get_transaction(p, preimage, 1,
100, "f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk=", 0)
self.assertEqual(golden_ltxn, encoding.msgpack_encode(ltxn))

def test_dynamic_fee(self):
addr1 = "726KBOYUJJNE5J5UHCSGQGWIBZWKCBN4WYD7YVSTEXEVNFPWUIJ7TAEOPM"
Expand Down Expand Up @@ -1304,17 +1316,16 @@ def test_periodic_payment(self):
self.assertEqual(p, base64.b64decode(golden))
self.assertEqual(s.get_address(), golden_addr)
gh = "f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk="
ltxn = s.get_withdrawal_transaction(p, 1200, gh, 1000)
golden_ltxn = ("gqRsc2lngaFsxJkBIAcB6AdkAF+gwh68o5UBJgIgAQIDBAUGBwg" +
"BAgMEBQYHCAECAwQFBgcIAQIDBAUGBwggkq+RhOQTPAl/ZqvMk7" +
"ERGxKiAb2dDMo+SkihzhPM9MUxECISMQEjDhAxAiQYJRIQMQQhB" +
"DECCBIQMQYoEhAxCTIDEjEHKRIQMQghBRIQMQkpEjEHMgMSEDEC" +
"IQYNEDEIJRIQERCjdHhuiaNhbXTOAAehIKNmZWXOAAQDWKJmds0" +
"EsKJnaMQgf4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkG" +
"mibHbNBQ+ibHjEIAECAwQFBgcIAQIDBAUGBwgBAgMEBQYHCAECA" +
"wQFBgcIo3JjdsQgkq+RhOQTPAl/ZqvMk7ERGxKiAb2dDMo+Skih" +
"zhPM9MWjc25kxCBLJbVxcjvosDUorAMyDf1+VeOdg4S45R0MPTO" +
"fOQvDtqR0eXBlo3BheQ==")
ltxn = s.get_withdrawal_transaction(p, 1200, gh, 0)
golden_ltxn = (
"gqRsc2lngaFsxJkBIAcB6AdkAF+gwh68o5UBJgIgAQIDBAUGBwgBAgMEBQYHCA" +
"ECAwQFBgcIAQIDBAUGBwggkq+RhOQTPAl/ZqvMk7ERGxKiAb2dDMo+SkihzhPM" +
"9MUxECISMQEjDhAxAiQYJRIQMQQhBDECCBIQMQYoEhAxCTIDEjEHKRIQMQghBR" +
"IQMQkpEjEHMgMSEDECIQYNEDEIJRIQERCjdHhuiaNhbXTOAAehIKNmZWXNA+ii" +
"ZnbNBLCiZ2jEIH+DsWV/8fxTuS3BgUih1l38LUsfo9Z3KErd0gASbZBpomx2zQ" +
"UPomx4xCABAgMEBQYHCAECAwQFBgcIAQIDBAUGBwgBAgMEBQYHCKNyY3bEIJKv" +
"kYTkEzwJf2arzJOxERsSogG9nQzKPkpIoc4TzPTFo3NuZMQgSyW1cXI76LA1KK" +
"wDMg39flXjnYOEuOUdDD0znzkLw7akdHlwZaNwYXk=")
self.assertEqual(golden_ltxn,
encoding.msgpack_encode(ltxn))

Expand Down