Skip to content

Commit

Permalink
Merge pull request raiden-network#3298 from hackaugusto/added_bp_checks
Browse files Browse the repository at this point in the history
Added asserts on balance proofs
  • Loading branch information
rakanalh authored Jan 23, 2019
2 parents b5f6e04 + b9cfedb commit 6b2c998
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,46 @@ def test_initiator_lock_expired():
assert transfer3_lock.secrethash in channel1.our_state.secrethashes_to_lockedlocks


def test_initiator_lock_expired_must_not_be_sent_if_channel_is_closed():
""" If the channel is closed there is no rason to send balance proofs
off-chain, so a remove expired lock must not be sent when the channel is
closed.
"""
block_number = 10
setup = setup_initiator_tests(amount=UNIT_TRANSFER_AMOUNT * 2, block_number=block_number)

channel_closed = ContractReceiveChannelClosed(
transaction_hash=factories.make_transaction_hash(),
transaction_from=factories.make_address(),
token_network_identifier=setup.channel.token_network_identifier,
channel_identifier=setup.channel.identifier,
block_number=block_number,
)
channel_close_transition = channel.state_transition(
channel_state=setup.channel,
state_change=channel_closed,
pseudo_random_generator=setup.prng,
block_number=block_number,
)
channel_state = channel_close_transition.new_state

expiration_block_number = setup.lock.expiration + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS * 2
block = Block(
block_number=expiration_block_number,
gas_limit=1,
block_hash=factories.make_transaction_hash(),
)
channel_map = {channel_state.identifier: channel_state}
iteration = initiator_manager.state_transition(
setup.current_state,
block,
channel_map,
setup.prng,
expiration_block_number,
)
assert events.must_contain_entry(iteration.events, SendLockExpired, {}) is None


def test_initiator_handle_contract_receive_secret_reveal():
""" Initiator must unlock off-chain if the secret is revealed on-chain and
the channel is open.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@
CHANNEL_STATE_SETTLED,
message_identifier_from_prng,
)
from raiden.transfer.state_change import Block, ContractReceiveSecretReveal
from raiden.transfer.state_change import (
Block,
ContractReceiveChannelClosed,
ContractReceiveSecretReveal,
)
from raiden.utils import random_secret


Expand Down Expand Up @@ -1417,6 +1421,70 @@ def test_mediator_lock_expired_with_new_block():
assert transfer.lock.secrethash not in channels[1].our_state.secrethashes_to_lockedlocks


def test_mediator_must_not_send_lock_expired_when_channel_is_closed():
block_number = 5
pseudo_random_generator = random.Random()

channels = mediator_make_channel_pair()
channel_state = channels[0]

payer_transfer = factories.make_signed_transfer_for(
channel_state,
LockedTransferSignedStateProperties(
transfer=LockedTransferProperties(
initiator=HOP1,
expiration=30,
),
),
)

mediator_state = MediatorTransferState(UNIT_SECRETHASH)
iteration = mediator.mediate_transfer(
state=mediator_state,
possible_routes=channels.get_routes(1),
payer_channel=channels[0],
channelidentifiers_to_channels=channels.channel_map,
pseudo_random_generator=pseudo_random_generator,
payer_transfer=payer_transfer,
block_number=block_number,
)

send_transfer = must_contain_entry(iteration.events, SendLockedTransfer, {})
transfer = send_transfer.transfer

channel_closed = ContractReceiveChannelClosed(
transaction_hash=factories.make_transaction_hash(),
transaction_from=factories.make_address(),
token_network_identifier=channel_state.token_network_identifier,
channel_identifier=channel_state.identifier,
block_number=block_number,
)
channel_close_transition = channel.state_transition(
channel_state=channel_state,
state_change=channel_closed,
pseudo_random_generator=pseudo_random_generator,
block_number=block_number,
)
channel_state = channel_close_transition.new_state

block_expiration_number = transfer.lock.expiration + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS * 2
block = Block(
block_number=block_expiration_number,
gas_limit=1,
block_hash=factories.make_transaction_hash(),
)
iteration = mediator.state_transition(
mediator_state=mediator_state,
state_change=block,
channelidentifiers_to_channels={channel_state.identifier: channel_state},
pseudo_random_generator=pseudo_random_generator,
block_number=block_expiration_number,
)

assert iteration.events
assert must_contain_entry(iteration.events, SendLockExpired, {}) is None


def test_mediator_lock_expired_with_receive_lock_expired():
expiration = 30
pseudo_random_generator = random.Random()
Expand Down
6 changes: 6 additions & 0 deletions raiden/transfer/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,9 @@ def send_refundtransfer(
msg = 'Refunds are only valid for *known and pending* transfers'
assert secrethash in channel_state.partner_state.secrethashes_to_lockedlocks, msg

msg = 'caller must make sure the channel is open'
assert get_status(channel_state) == CHANNEL_STATE_OPENED, msg

send_mediated_transfer, merkletree = create_sendlockedtransfer(
channel_state,
initiator,
Expand Down Expand Up @@ -1409,6 +1412,9 @@ def events_for_expired_lock(
locked_lock: HashTimeLockState,
pseudo_random_generator: random.Random,
) -> List[SendLockExpired]:
msg = 'caller must make sure the channel is open'
assert get_status(channel_state) == CHANNEL_STATE_OPENED, msg

send_lock_expired, merkletree = create_sendexpiredlock(
sender_end_state=channel_state.our_state,
locked_lock=locked_lock,
Expand Down
22 changes: 14 additions & 8 deletions raiden/transfer/mediated_transfer/initiator.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,18 @@ def handle_block(
lock_expiration_threshold=lock_expiration_threshold,
)

events: List[Event] = list()

if lock_has_expired:
expired_lock_events = channel.events_for_expired_lock(
channel_state=channel_state,
locked_lock=locked_lock,
pseudo_random_generator=pseudo_random_generator,
)
is_channel_open = channel.get_status(channel_state) == CHANNEL_STATE_OPENED
if is_channel_open:
expired_lock_events = channel.events_for_expired_lock(
channel_state=channel_state,
locked_lock=locked_lock,
pseudo_random_generator=pseudo_random_generator,
)
events.extend(expired_lock_events)

transfer_description = initiator_state.transfer_description
# TODO: When we introduce multiple transfers per payment this needs to be
# reconsidered. As we would want to try other routes once a route
Expand All @@ -126,7 +132,7 @@ def handle_block(
target=transfer_description.target,
reason="transfer's lock has expired",
)
expired_lock_events.append(transfer_failed)
events.append(transfer_failed)
lock_exists = channel.lock_exists_in_either_channel_side(
channel_state=channel_state,
secrethash=secrethash,
Expand All @@ -137,10 +143,10 @@ def handle_block(
# task around to wait for the LockExpired messages to sync.
# Check https://github.com/raiden-network/raiden/issues/3183
initiator_state if lock_exists else None,
cast(List[Event], expired_lock_events),
events,
)
else:
return TransitionResult(initiator_state, list())
return TransitionResult(initiator_state, events)


def get_initial_lock_expiration(
Expand Down
4 changes: 3 additions & 1 deletion raiden/transfer/mediated_transfer/mediator.py
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,9 @@ def events_to_remove_expired_locks(
lock_expiration_threshold=lock_expiration_threshold,
)

if has_lock_expired:
is_channel_open = channel.get_status(channel_state) == CHANNEL_STATE_OPENED

if has_lock_expired and is_channel_open:
transfer_pair.payee_state = 'payee_expired'
expired_lock_events = channel.events_for_expired_lock(
channel_state=channel_state,
Expand Down

0 comments on commit 6b2c998

Please sign in to comment.