Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
51 changes: 51 additions & 0 deletions testing/unit/tp/account/test_transfer.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

ACCOUNT_FROM_BALANCE = NODE_ACCOUNT_FROM_BALANCE = 10000
ACCOUNT_TO_BALANCE = NODE_ACCOUNT_TO_BALANCE = 1000
MAX_UINT64 = 2**64-1

ACCOUNT_ADDRESS_FROM = '112007d71fa7e120c60fb392a64fd69de891a60c667d9ea9e5d9d9d617263be6c20202'
ACCOUNT_ADDRESS_TO = '1120071db7c02f5731d06df194dc95465e9b277c19e905ce642664a9a0d504a3909e31'
Expand Down Expand Up @@ -323,6 +324,56 @@ def test_account_transfer_from_address():
assert state_as_dict.get(ACCOUNT_ADDRESS_TO, Account()).balance == expected_account_to_balance


def test_account_transfer_integer_overflow():
"""
Case: transfer tokens from address to address such that on receiver address will be more then max uint64 tokens.
Expect: exception ValueError is raised.
"""
account_from_balance = 1
tokens_amount_to_send = 1
account_to_balance = MAX_UINT64
expected_account_from_balance = account_from_balance - tokens_amount_to_send
expected_account_to_balance = account_to_balance + tokens_amount_to_send

transfer_payload = TransferPayload()
transfer_payload.address_to = ACCOUNT_ADDRESS_TO
transfer_payload.value = tokens_amount_to_send

transaction_payload = TransactionPayload()
transaction_payload.method = AccountMethod.TRANSFER
transaction_payload.data = transfer_payload.SerializeToString()

serialized_transaction_payload = transaction_payload.SerializeToString()

transaction_header = TransactionHeader(
signer_public_key=ACCOUNT_FROM_PUBLIC_KEY,
family_name=TRANSACTION_REQUEST_ACCOUNT_HANDLER_PARAMS.get('family_name'),
family_version=TRANSACTION_REQUEST_ACCOUNT_HANDLER_PARAMS.get('family_version'),
inputs=INPUTS,
outputs=OUTPUTS,
dependencies=[],
payload_sha512=hash512(data=serialized_transaction_payload),
batcher_public_key=RANDOM_NODE_PUBLIC_KEY,
nonce=time.time().hex().encode(),
)

serialized_header = transaction_header.SerializeToString()

transaction_request = TpProcessRequest(
header=transaction_header,
payload=serialized_transaction_payload,
signature=create_signer(private_key=ACCOUNT_FROM_PRIVATE_KEY).sign(serialized_header),
)

mock_context = create_context(account_from_balance=account_from_balance, account_to_balance=account_to_balance)


with pytest.raises(ValueError) as error:
AccountHandler().apply(transaction=transaction_request, context=mock_context)

assert str(error.value).startswith('Value out of range')


def test_account_transfer_from_address_zero_amount():
"""
Case: transfer zero tokens from address to address.
Expand Down
2 changes: 2 additions & 0 deletions testing/unit/tp/node_account/shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
'family_version': NodeAccountHandler().family_versions[0],
}

MAX_UINT64 = 2**64-1


def create_context(account_from_balance, node_state=NodeAccount.NEW, frozen=0, unfrozen=0):
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
INPUTS,
OUTPUTS,
TRANSACTION_REQUEST_ACCOUNT_HANDLER_PARAMS,
MAX_UINT64,
create_context,
)

Expand Down Expand Up @@ -93,6 +94,53 @@ def test_transfer_from_unfrozen_to_operational():
assert node_account.reputation.unfrozen == unfrozen - tokens_to_transfer


def test_transfer_from_unfrozen_to_operational_integer_overflow():
"""
Case: transfer from unfrozen to operational such that it will cause integer overflow.
Expect: integer overflow exception is raised.
"""
unfrozen = 1
operational = MAX_UINT64
tokens_to_transfer = 1

internal_transfer_payload = NodeAccountInternalTransferPayload()
internal_transfer_payload.value = tokens_to_transfer

transaction_payload = TransactionPayload()
transaction_payload.method = NodeAccountMethod.TRANSFER_FROM_UNFROZEN_TO_OPERATIONAL
transaction_payload.data = internal_transfer_payload.SerializeToString()

serialized_transaction_payload = transaction_payload.SerializeToString()

transaction_header = TransactionHeader(
signer_public_key=RANDOM_NODE_PUBLIC_KEY,
family_name=TRANSACTION_REQUEST_ACCOUNT_HANDLER_PARAMS.get('family_name'),
family_version=TRANSACTION_REQUEST_ACCOUNT_HANDLER_PARAMS.get('family_version'),
inputs=INPUTS,
outputs=OUTPUTS,
dependencies=[],
payload_sha512=hash512(data=serialized_transaction_payload),
batcher_public_key=RANDOM_NODE_PUBLIC_KEY,
nonce=time.time().hex().encode(),
)

serialized_header = transaction_header.SerializeToString()

transaction_request = TpProcessRequest(
header=transaction_header,
payload=serialized_transaction_payload,
signature=create_signer(private_key=NODE_ACCOUNT_FROM_PRIVATE_KEY).sign(serialized_header),
)

mock_context = create_context(account_from_balance=operational, node_state=NodeAccount.OPENED,
unfrozen=unfrozen)

with pytest.raises(ValueError) as error:
NodeAccountHandler().apply(transaction=transaction_request, context=mock_context)

assert str(error.value).startswith('Value out of range')


def test_transfer_invalid_amount_from_unfrozen_to_operational():
"""
Case: transfer from unfrozen to operational with more tokens than on unfrozen account.
Expand Down
45 changes: 45 additions & 0 deletions testing/unit/tp/node_account/test_transfer_frozen_to_unfrozen.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
from testing.conftest import create_signer
from testing.mocks.stub import StubContext
from testing.utils.client import proto_error_msg
from .shared import (
MAX_UINT64
)

RANDOM_NODE_PUBLIC_KEY = '039d6881f0a71d05659e1f40b443684b93c7b7c504ea23ea8949ef5216a2236940'

Expand Down Expand Up @@ -178,6 +181,48 @@ def test_transfer_from_frozen_to_unfrozen():
assert node_account_reputation.frozen == FROZEN - transfer_value
assert node_account_reputation.unfrozen == UNFROZEN + transfer_value

def test_transfer_from_frozen_to_unfrozen_integer_overflow():
"""
Case: transfer from frozen to unfrozen such that it will cause integer overflow.
Expect: integer overflow exception is raised.
"""
transfer_value = 1

internal_transfer_payload = NodeAccountInternalTransferPayload()
internal_transfer_payload.value = transfer_value

transaction_payload = TransactionPayload()
transaction_payload.method = NodeAccountMethod.TRANSFER_FROM_FROZEN_TO_UNFROZEN
transaction_payload.data = internal_transfer_payload.SerializeToString()

serialized_transaction_payload = transaction_payload.SerializeToString()

transaction_header = TransactionHeader(
signer_public_key=RANDOM_NODE_PUBLIC_KEY,
family_name=TRANSACTION_REQUEST_ACCOUNT_HANDLER_PARAMS.get('family_name'),
family_version=TRANSACTION_REQUEST_ACCOUNT_HANDLER_PARAMS.get('family_version'),
inputs=INPUTS,
outputs=OUTPUTS,
dependencies=[],
payload_sha512=hash512(data=serialized_transaction_payload),
batcher_public_key=RANDOM_NODE_PUBLIC_KEY,
nonce=time.time().hex().encode(),
)

serialized_header = transaction_header.SerializeToString()

transaction_request = TpProcessRequest(
header=transaction_header,
payload=serialized_transaction_payload,
signature=create_signer(private_key=NODE_ACCOUNT_FROM_PRIVATE_KEY).sign(serialized_header),
)

mock_context = create_context(account_from_frozen_balance=MINIMUM_STAKE+1, account_to_unfrozen_balance=MAX_UINT64)

with pytest.raises(ValueError) as error:
NodeAccountHandler().apply(transaction=transaction_request, context=mock_context)

assert str(error.value).startswith('Value out of range')

def test_transfer_from_frozen_to_unfrozen_low_frozen_balance():
"""
Expand Down