Skip to content
Merged
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
2 changes: 1 addition & 1 deletion raiden/api/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ def api_error(errors, status_code):


@parser.error_handler
def handle_request_parsing_error(err):
def handle_request_parsing_error(err, req, schema):
""" This handles request parsing errors generated for example by schema
field validation failing."""
abort(HTTPStatus.BAD_REQUEST, errors=err.messages)
Expand Down
10 changes: 10 additions & 0 deletions raiden/network/rpc/smartcontract_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,16 @@ def get_transaction_data(abi: Dict, function_name: str, args: List = None):
args=args,
)

def decode_transaction_input(self, transaction_hash: bytes) -> Dict:
"""Return inputs of a method call"""
transaction = self.contract.web3.eth.getTransaction(
transaction_hash,
)

return self.contract.decode_function_input(
transaction['input'],
)

def decode_event(self, log: Dict):
return decode_event(self.contract.abi, log)

Expand Down
7 changes: 5 additions & 2 deletions raiden/raiden_event_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,10 @@ def handle_contract_send_channelsettle(
)
our_balance_proof = channel_settle_event.our_balance_proof
partner_balance_proof = channel_settle_event.partner_balance_proof
channel_details = channel.detail()

if our_balance_proof:
our_balance_hash = channel_details.participants_data.our_details.balance_hash
if our_balance_proof and our_balance_hash != EMPTY_HASH:
our_transferred_amount = our_balance_proof.transferred_amount
our_locked_amount = our_balance_proof.locked_amount
our_locksroot = our_balance_proof.locksroot
Expand All @@ -326,7 +328,8 @@ def handle_contract_send_channelsettle(
our_locked_amount = 0
our_locksroot = EMPTY_HASH

if partner_balance_proof:
partner_balance_hash = channel_details.participants_data.partner_details.balance_hash
if partner_balance_proof and partner_balance_hash != EMPTY_HASH:
partner_transferred_amount = partner_balance_proof.transferred_amount
partner_locked_amount = partner_balance_proof.locked_amount
partner_locksroot = partner_balance_proof.locksroot
Expand Down
146 changes: 146 additions & 0 deletions raiden/tests/integration/test_balance_proof_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import pytest

from raiden import waiting
from raiden.api.python import RaidenAPI
from raiden.constants import EMPTY_HASH, EMPTY_SIGNATURE
from raiden.network.proxies import TokenNetwork
from raiden.tests.utils.events import must_contain_entry
from raiden.tests.utils.network import CHAIN
from raiden.tests.utils.transfer import direct_transfer, get_channelstate
from raiden.transfer import views
from raiden.transfer.state_change import ContractReceiveChannelSettled


@pytest.mark.parametrize('deposit', [10])
@pytest.mark.parametrize('channels_per_node', [CHAIN])
@pytest.mark.parametrize('number_of_nodes', [2])
def test_invalid_close(
raiden_network,
number_of_nodes,
deposit,
token_addresses,
network_wait,
):
app0, app1 = raiden_network
token_address = token_addresses[0]
chain_state = views.state_from_app(app0)
payment_network_id = app0.raiden.default_registry.address
registry_address = app0.raiden.default_registry.address
token_network_identifier = views.get_token_network_identifier_by_token_address(
chain_state=chain_state,
payment_network_id=payment_network_id,
token_address=token_address,
)
channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier

# make a transfer from app0 to app1 so that app1 is supposed to have a non empty balance hash
direct_transfer(
initiator_app=app0,
target_app=app1,
token_network_identifier=token_network_identifier,
amount=1,
timeout=network_wait * number_of_nodes,
)
# stop app1 - the test uses token_network_contract now
app1.stop()
token_network_contract = TokenNetwork(app1.raiden.chain.client, token_network_identifier)

# app1 closes the channel with an empty hash instead of the expected hash
# of the transferred amount from app0
token_network_contract.close(
channel_identifier=channel_identifier,
partner=app0.raiden.address,
balance_hash=EMPTY_HASH,
nonce=0,
additional_hash=EMPTY_HASH,
signature=EMPTY_SIGNATURE,
)
waiting.wait_for_close(
raiden=app0.raiden,
payment_network_id=registry_address,
token_address=token_address,
channel_ids=[channel_identifier],
retry_timeout=app0.raiden.alarm.sleep_time,
)
waiting.wait_for_settle(
raiden=app0.raiden,
payment_network_id=registry_address,
token_address=token_address,
channel_ids=[channel_identifier],
retry_timeout=app0.raiden.alarm.sleep_time,
)
state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier(
from_identifier=0,
to_identifier='latest',
)
assert must_contain_entry(state_changes, ContractReceiveChannelSettled, {
'token_network_identifier': token_network_identifier,
'channel_identifier': channel_identifier,
})


@pytest.mark.parametrize('deposit', [10])
@pytest.mark.parametrize('channels_per_node', [CHAIN])
@pytest.mark.parametrize('number_of_nodes', [2])
def test_invalid_update_transfer(
raiden_network,
number_of_nodes,
deposit,
token_addresses,
network_wait,
chain_id,
):
app0, app1 = raiden_network
token_address = token_addresses[0]
chain_state = views.state_from_app(app0)
payment_network_id = app0.raiden.default_registry.address
registry_address = app0.raiden.default_registry.address
token_network_identifier = views.get_token_network_identifier_by_token_address(
chain_state=chain_state,
payment_network_id=payment_network_id,
token_address=token_address,
)
channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier

# make a transfer
direct_transfer(
initiator_app=app0,
target_app=app1,
token_network_identifier=token_network_identifier,
amount=1,
timeout=network_wait * number_of_nodes,
)
# stop app1 - the test uses token_network_contract now
app1.stop()
# close the channel
RaidenAPI(app0.raiden).channel_close(
registry_address=registry_address,
token_address=token_address,
partner_address=app1.raiden.address,
)
waiting.wait_for_close(
raiden=app0.raiden,
payment_network_id=registry_address,
token_address=token_address,
channel_ids=[channel_identifier],
retry_timeout=app0.raiden.alarm.sleep_time,
)

# app1 won't update the channel

# app0 waits for settle
waiting.wait_for_settle(
raiden=app0.raiden,
payment_network_id=registry_address,
token_address=token_address,
channel_ids=[channel_identifier],
retry_timeout=app0.raiden.alarm.sleep_time,
)
state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier(
from_identifier=0,
to_identifier='latest',
)
assert must_contain_entry(state_changes, ContractReceiveChannelSettled, {
'token_network_identifier': token_network_identifier,
'channel_identifier': channel_identifier,
})