Skip to content

Commit

Permalink
Merge pull request #24 from janezpodhostnik/janez/add-more-unit-tests
Browse files Browse the repository at this point in the history
Add more unit tests
  • Loading branch information
janezpodhostnik authored Aug 12, 2021
2 parents e154d36 + ced03d7 commit 716c169
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 66 deletions.
4 changes: 2 additions & 2 deletions docs/scripts.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ examples [here](https://github.com/janezpodhostnik/flow-py-sdk/blob/master/examp

## Sending scripts

To following code can be used to send a script to an access ot the emulator.
To following code can be used to send a script to an access node or the emulator.

```py
from flow_py_sdk import flow_client, Script
Expand All @@ -27,7 +27,7 @@ async with flow_client(host=access_node_host, port=access_node_port) as client:
await client.execute_script(script)
```

If this script is sent to the emulator, the log will be visible in the emulator output.
When sending this script to an emulator, the log output will be visible in the emulator output.

## Getting script results

Expand Down
24 changes: 20 additions & 4 deletions flow_py_sdk/account_key.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from __future__ import annotations
from typing import Optional

import rlp

from flow_py_sdk import frlp
from flow_py_sdk.frlp import rlp_encode_uint64
from flow_py_sdk.proto.flow import entities
from flow_py_sdk.signer import SignAlgo, HashAlgo


Expand Down Expand Up @@ -30,11 +32,25 @@ def rlp(self) -> bytes:
return rlp.encode(
[
self.public_key,
frlp.rlp_encode_uint64(self.sign_algo.value),
frlp.rlp_encode_uint64(self.hash_algo.value),
frlp.rlp_encode_uint64(self.weight),
rlp_encode_uint64(self.sign_algo.value),
rlp_encode_uint64(self.hash_algo.value),
rlp_encode_uint64(self.weight),
]
)

def hex(self):
return self.rlp().hex()

@classmethod
def from_proto(cls, k: entities.AccountKey) -> AccountKey:
ak = AccountKey(
public_key=k.public_key,
hash_algo=HashAlgo(k.hash_algo),
sign_algo=SignAlgo(k.sign_algo),
weight=k.weight,
)
ak.index = k.index
ak.revoked = k.revoked
ak.sequence_number = k.sequence_number

return ak
37 changes: 2 additions & 35 deletions flow_py_sdk/client/entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,11 @@
from datetime import datetime
from typing import Dict, List

from flow_py_sdk import cadence
from flow_py_sdk.cadence import Value, cadence_object_hook
from flow_py_sdk.account_key import AccountKey
from flow_py_sdk.cadence import cadence_object_hook
from flow_py_sdk.proto.flow import entities, access


class AccountKey(object):
def __init__(
self,
index: int,
public_key: bytes,
sign_algo: int,
hash_algo: int,
weight: int,
sequence_number: int,
revoked: bool,
) -> None:
super().__init__()
self.index: int = index
self.public_key: bytes = public_key
self.sign_algo: int = sign_algo
self.hash_algo: int = hash_algo
self.weight: int = weight
self.sequence_number: int = sequence_number
self.revoked: bool = revoked

@classmethod
def from_proto(cls, proto: entities.AccountKey) -> "AccountKey":
return AccountKey(
index=proto.index,
public_key=proto.public_key,
sign_algo=proto.sign_algo,
hash_algo=proto.hash_algo,
weight=proto.weight,
sequence_number=proto.sequence_number,
revoked=proto.revoked,
)


class Account(object):
def __init__(
self,
Expand Down
4 changes: 3 additions & 1 deletion flow_py_sdk/signer/in_memory_signer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Optional

import ecdsa

from flow_py_sdk.signer.hash_algo import HashAlgo
Expand All @@ -17,7 +19,7 @@ def __init__(
bytes.fromhex(private_key_hex), curve=sign_algo.get_signing_curve()
)

def sign(self, message: bytes, tag: bytes) -> bytes:
def sign(self, message: bytes, tag: Optional[bytes] = None) -> bytes:
m = self.hash_algo.create_hasher()
if tag:
m.update(tag + message)
Expand Down
3 changes: 2 additions & 1 deletion flow_py_sdk/signer/signer.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from abc import ABC, abstractmethod
from typing import Optional


class Signer(ABC):
Expand All @@ -11,7 +12,7 @@ def __init__(self) -> None:
super().__init__()

@abstractmethod
def sign(self, message: bytes, tag: bytes) -> bytes:
def sign(self, message: bytes, tag: Optional[bytes] = None) -> bytes:
"""The signe method signs a message with a tag and returns the signature
Parameters
Expand Down
1 change: 0 additions & 1 deletion flow_py_sdk/tx.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ def _padded_domain_tag(s: str) -> bytes:
raise PySDKError(
f"domain tag {s} cannot be longer than {DomainTagLength} bytes"
)
log.warning((encoded + bytearray(DomainTagLength - len(s))).hex())
return encoded + bytearray(DomainTagLength - len(s))


Expand Down
2 changes: 1 addition & 1 deletion tests/cadence/encode_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class _EncodeTestParams:
expected: str


class TestTx(unittest.TestCase):
class TestEncode(unittest.TestCase):
"""
Cadence encoding/decoding tests were adapted from: https://github.com/onflow/cadence/blob/master/encoding/json/encoding_test.go
"""
Expand Down
53 changes: 32 additions & 21 deletions tests/signer/test_in_memory_signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,37 @@ def test_sign(self):
# HashAlgo.SHA3_384,
]

tags = [True, False]

for sign_algo in s:
for hash_algo in h:
with self.subTest(f"sign_algo: {sign_algo}, hash_algo: {hash_algo}"):
private_key = ecdsa.SigningKey.generate(
curve=sign_algo.get_signing_curve()
)

signer = InMemorySigner(
sign_algo=sign_algo,
hash_algo=hash_algo,
private_key_hex=private_key.to_string().hex(),
)

signature = signer.sign(b"some_message", b"some_tag")
hasher = hash_algo.create_hasher()
hasher.update(b"some_tagsome_message")
_hash = hasher.digest()

valid = private_key.get_verifying_key().verify_digest(
signature, _hash
)

self.assertTrue(valid)
for tag in tags:
with self.subTest(
f"sign_algo: {sign_algo}, hash_algo: {hash_algo}, tag: {tag}"
):
private_key = ecdsa.SigningKey.generate(
curve=sign_algo.get_signing_curve()
)

signer = InMemorySigner(
sign_algo=sign_algo,
hash_algo=hash_algo,
private_key_hex=private_key.to_string().hex(),
)
if tag:
signature = signer.sign(b"some_message", b"some_tag")
else:
signature = signer.sign(b"some_message")

hasher = hash_algo.create_hasher()
if tag:
hasher.update(b"some_tagsome_message")
else:
hasher.update(b"some_message")
_hash = hasher.digest()

valid = private_key.get_verifying_key().verify_digest(
signature, _hash
)

self.assertTrue(valid)
43 changes: 43 additions & 0 deletions tests/test_account_key.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from unittest import TestCase

from flow_py_sdk import AccountKey, SignAlgo, HashAlgo
from flow_py_sdk.proto.flow.entities import AccountKey as ProtoAccountKey


class TestAccountKey(TestCase):
def test_rlp(self):
expected_rlp_hex = "f847b840c51c02aa382d8d382a121178de8ac97eb6a562a1008660669ab6a220c96fce76e1d392b0c156380ae713b0aa18ad9cff7b85bcc44a9eb43fcddb467f456f0ec803038203e8"

key = AccountKey(
public_key=bytes.fromhex(
"c51c02aa382d8d382a121178de8ac97eb6a562a1008660669ab6a220c96fce76e1d392b0c156380ae713b0aa18ad9cff7b85bcc44a9eb43fcddb467f456f0ec8"
),
sign_algo=SignAlgo.ECDSA_secp256k1,
hash_algo=HashAlgo.SHA3_256,
weight=AccountKey.weight_threshold,
)
rlp = key.rlp()

self.assertEqual(expected_rlp_hex, rlp.hex())

def test_hex(self):
expected_rlp_hex = "f847b840c51c02aa382d8d382a121178de8ac97eb6a562a1008660669ab6a220c96fce76e1d392b0c156380ae713b0aa18ad9cff7b85bcc44a9eb43fcddb467f456f0ec803038203e8"

key = AccountKey(
public_key=bytes.fromhex(
"c51c02aa382d8d382a121178de8ac97eb6a562a1008660669ab6a220c96fce76e1d392b0c156380ae713b0aa18ad9cff7b85bcc44a9eb43fcddb467f456f0ec8"
),
sign_algo=SignAlgo.ECDSA_secp256k1,
hash_algo=HashAlgo.SHA3_256,
weight=AccountKey.weight_threshold,
)
rlp_hex = key.hex()

self.assertEqual(expected_rlp_hex, rlp_hex)

def test_from_proto(self):
proto_account_key = ProtoAccountKey()
proto_account_key.sign_algo = 2
proto_account_key.hash_algo = 1

AccountKey.from_proto(proto_account_key)

0 comments on commit 716c169

Please sign in to comment.