def test_channel_must_accept_expired_locks(): """ A node may go offline for an undetermined period of time, and when it comes back online it must accept the messages that are waiting, otherwise the partner node won't make progress with its queue. If a N node goes offline for a number B of blocks, and the partner does not close the channel, when N comes back online some of the messages from its partner may become expired. Neverthless these messages are ordered and must be accepted for the partner to make progress with its queue. Note: Accepting a message with an expired lock does *not* imply the token transfer happened, and the receiver node must *not* forward the transfer, only accept the message allowing the partner to progress with its message queue. """ balance1 = 70 balance2 = 110 reveal_timeout = 5 settle_timeout = 15 privkey1, address1 = make_privkey_address() privkey2, address2 = make_privkey_address() token_address = make_address() our_state = ChannelEndState( address1, balance1, None, EMPTY_MERKLE_TREE, ) partner_state = ChannelEndState( address2, balance2, None, EMPTY_MERKLE_TREE, ) external_state = make_external_state() test_channel = Channel( our_state, partner_state, external_state, token_address, reveal_timeout, settle_timeout, ) block_number = 10 transfer = make_mediated_transfer( nonce=test_channel.get_next_nonce(), token=test_channel.token_address, channel=test_channel.channel_address, expiration=block_number + settle_timeout, recipient=address1, ) transfer.sign(privkey2, address2) test_channel.register_transfer( block_number + settle_timeout + 1, transfer, )
def test_channel_to_api_dict(): channel_address = b'\x00' * 20 token_address = b'\x01' * 20 our_address = b'\x02' * 20 partner_address = b'\x03' * 20 reveal_timeout = 10 settle_timeout = 50 opened_block = 900 our_balance = 13 partner_balance = 21 our_state = ChannelEndState( our_address, our_balance, BalanceProof(None), ) partner_state = ChannelEndState( partner_address, partner_balance, BalanceProof(None), ) # mock external state to provide the channel address class NettingChannel(object): address = channel_address class ExternalState(object): def __init__(self, opened_block): self.netting_channel = NettingChannel() self.settled_block = 0 self.closed_block = 0 self.opened_block = opened_block channel = Channel( our_state, partner_state, ExternalState(opened_block), token_address, reveal_timeout, settle_timeout, ) result = channel_to_api_dict(channel) expected_result = { 'channel_address': channel_address, 'token_address': token_address, 'partner_address': partner_address, 'settle_timeout': settle_timeout, 'reveal_timeout': reveal_timeout, 'balance': our_balance, 'state': CHANNEL_STATE_OPENED } assert result == expected_result
def test_channel_close_called_only_once(): class MockCheckCallsToClose(): def __init__(self): self.address = 'mockcheckcallstoclosemockcheckcallstoclo' self.close_calls = 0 def opened(self): return 1 def closed(self): return 0 def settled(self): return 0 def close(self, nonce, transferred_amount, locksroot, extra_hash, signature): self.close_calls += 1 netting_channel = NettingChannelMock() token_address = make_address() privkey1, address1 = make_privkey_address() address2 = make_address() balance1 = 70 balance2 = 110 reveal_timeout = 5 settle_timeout = 15 our_state = ChannelEndState(address1, balance1, BalanceProof(None)) partner_state = ChannelEndState(address2, balance2, BalanceProof(None)) channel_for_hashlock = list() netting_channel = MockCheckCallsToClose() external_state = ChannelExternalState( lambda *args: channel_for_hashlock.append(args), netting_channel, ) test_channel = Channel( our_state, partner_state, external_state, token_address, reveal_timeout, settle_timeout, ) test_channel.external_state.close(None) test_channel.external_state.close(None) assert netting_channel.close_calls == 1
def channel_from_nettingcontract( our_key, netting_contract, external_state, reveal_timeout, block_number): """ Create a `channel.Channel` for the `netting_contract`. Use this to make sure that both implementations (the smart contract and the python code) work in tandem. """ our_address = privatekey_to_address(our_key) token_address_hex = netting_contract.tokenAddress(sender=our_key) settle_timeout = netting_contract.settleTimeout(sender=our_key) address_balance = netting_contract.addressAndBalance(sender=our_key) address1_hex, balance1, address2_hex, balance2 = address_balance token_address = decode_hex(token_address_hex) address1 = decode_hex(address1_hex) address2 = decode_hex(address2_hex) if our_address == address1: our_balance = balance1 partner_address = address2 partner_balance = balance2 else: our_balance = balance2 partner_address = address1 partner_balance = balance1 our_state = ChannelEndState( our_address, our_balance, external_state.opened_block, ) partner_state = ChannelEndState( partner_address, partner_balance, external_state.opened_block, ) channel = Channel( our_state, partner_state, external_state, token_address, reveal_timeout, settle_timeout, ) return channel
def add_channel(self, details, block_number): channel_address = details.channel_address partner_state = details.partner_state channel = Channel( details.our_state, partner_state, details.external_state, self.token_address, details.reveal_timeout, details.settle_timeout, block_number, ) self.partneraddress_channel[partner_state.address] = channel self.address_channel[channel_address] = channel
def test_channel_increase_nonce_and_transferred_amount(): """ The nonce must increase with each new transfer. """ token_address = make_address() privkey1, address1 = make_privkey_address() address2 = make_address() balance1 = 70 balance2 = 110 reveal_timeout = 5 settle_timeout = 15 our_state = ChannelEndState(address1, balance1, None, EMPTY_MERKLE_TREE) partner_state = ChannelEndState(address2, balance2, None, EMPTY_MERKLE_TREE) external_state = make_external_state() test_channel = Channel( our_state, partner_state, external_state, token_address, reveal_timeout, settle_timeout, ) previous_nonce = test_channel.get_next_nonce() previous_transferred = test_channel.transferred_amount amount = 7 block_number = 1 for _ in range(10): direct_transfer = test_channel.create_directtransfer(amount, identifier=1) direct_transfer.sign(privkey1, address1) test_channel.register_transfer(block_number, direct_transfer) new_nonce = test_channel.get_next_nonce() new_transferred = test_channel.transferred_amount assert new_nonce == previous_nonce + 1 assert new_transferred == previous_transferred + amount previous_nonce = new_nonce previous_transferred = new_transferred
def make_channel( self, token_address=make_address(), partner_address=make_address(), reveal_timeout=20, settle_timeout=800, balance=0, block_number=1): our_address = make_address() our_balance = balance partner_balance = balance our_state = ChannelEndState( our_address, our_balance, None, EMPTY_MERKLE_TREE, ) partner_state = ChannelEndState( partner_address, partner_balance, None, EMPTY_MERKLE_TREE, ) channel_for_hashlock = list() netting_channel = NettingChannelMock(make_address()) external_state = ChannelExternalState( lambda *args: channel_for_hashlock.append(args), netting_channel, ) self.tokens.add(token_address) return Channel( our_state, partner_state, external_state, token_address, reveal_timeout, settle_timeout, )
def register_channel(self, netting_channel, reveal_timeout): """ Register a new channel. Args: netting_channel (network.rpc.client.NettingChannel): The netting channel proxy. reveal_timeout (int): Minimum number of blocks required by this node to see a secret. Raises: ValueError: - If raiden.address is not one of the participants in the netting channel. - If the contract's settle_timeout is smaller than the reveal_timeout. """ # pylint: disable=too-many-locals translator = ContractTranslator(NETTING_CHANNEL_ABI) # Race condition: # - If the filter is installed after the call to `details` a deposit # can be missed, to avoid this the listener is installed first. # - Because of the above a `ChannelNewBalance` event can be polled # after the `details` calls succeds so the effects must be # idempotent. netting_channel_events = netting_channel.all_events_filter() channel_details = netting_channel.detail(self.raiden.address) our_state = ChannelEndState( channel_details['our_address'], channel_details['our_balance'], netting_channel.opened, ) partner_state = ChannelEndState( channel_details['partner_address'], channel_details['partner_balance'], netting_channel.opened, ) external_state = ChannelExternalState( self.raiden.alarm.register_callback, self.register_channel_for_hashlock, self.raiden.get_block_number, netting_channel, ) channel = Channel( our_state, partner_state, external_state, self.token_address, reveal_timeout, channel_details['settle_timeout'], ) self.partneraddress_channel[partner_state.address] = channel self.address_channel[netting_channel.address] = channel self.raiden.start_event_listener( 'NettingChannel Event {}'.format(pex(netting_channel.address)), netting_channel_events, translator, )
def test_python_channel(): netting_channel = NettingChannelMock() token_address = make_address() privkey1, address1 = make_privkey_address() address2 = make_address() balance1 = 70 balance2 = 110 reveal_timeout = 5 settle_timeout = 15 our_state = ChannelEndState(address1, balance1, netting_channel.opened) partner_state = ChannelEndState(address2, balance2, netting_channel.opened) external_state = make_external_state() test_channel = Channel( our_state, partner_state, external_state, token_address, reveal_timeout, settle_timeout, ) assert test_channel.contract_balance == our_state.contract_balance assert test_channel.balance == our_state.balance(partner_state) assert test_channel.transferred_amount == our_state.transferred_amount assert test_channel.distributable == our_state.distributable(partner_state) assert test_channel.outstanding == our_state.locked() assert test_channel.outstanding == 0 assert test_channel.locked == partner_state.locked() assert test_channel.our_state.locked() == 0 assert test_channel.partner_state.locked() == 0 with pytest.raises(ValueError): test_channel.create_directtransfer( -10, 1 # TODO: fill in identifier ) with pytest.raises(ValueError): test_channel.create_directtransfer( balance1 + 10, 1 # TODO: fill in identifier ) amount1 = 10 directtransfer = test_channel.create_directtransfer( amount1, 1 # TODO: fill in identifier ) directtransfer.sign(privkey1, address1) test_channel.register_transfer(directtransfer) assert test_channel.contract_balance == balance1 assert test_channel.balance == balance1 - amount1 assert test_channel.transferred_amount == amount1 assert test_channel.distributable == balance1 - amount1 assert test_channel.outstanding == 0 assert test_channel.locked == 0 assert test_channel.our_state.locked() == 0 assert test_channel.partner_state.locked() == 0 secret = sha3('test_channel') hashlock = sha3(secret) amount2 = 10 fee = 0 expiration = settle_timeout - 5 mediatedtransfer = test_channel.create_mediatedtransfer( address1, address2, fee, amount2, 1, # TODO: fill in identifier expiration, hashlock, ) mediatedtransfer.sign(privkey1, address1) test_channel.register_transfer(mediatedtransfer) assert test_channel.contract_balance == balance1 assert test_channel.balance == balance1 - amount1 assert test_channel.transferred_amount == amount1 assert test_channel.distributable == balance1 - amount1 - amount2 assert test_channel.outstanding == 0 assert test_channel.locked == amount2 assert test_channel.our_state.locked() == 0 assert test_channel.partner_state.locked() == amount2 test_channel.release_lock(secret) assert test_channel.contract_balance == balance1 assert test_channel.balance == balance1 - amount1 - amount2 assert test_channel.transferred_amount == amount1 + amount2 assert test_channel.distributable == balance1 - amount1 - amount2 assert test_channel.outstanding == 0 assert test_channel.locked == 0 assert test_channel.our_state.locked() == 0 assert test_channel.partner_state.locked() == 0
def test_python_channel(): token_address = make_address() privkey1, address1 = make_privkey_address() address2 = make_address() balance1 = 70 balance2 = 110 reveal_timeout = 5 settle_timeout = 15 block_number = 10 our_state = ChannelEndState(address1, balance1, None, EMPTY_MERKLE_TREE) partner_state = ChannelEndState(address2, balance2, None, EMPTY_MERKLE_TREE) external_state = make_external_state() test_channel = Channel( our_state, partner_state, external_state, token_address, reveal_timeout, settle_timeout, ) assert test_channel.contract_balance == our_state.contract_balance assert test_channel.transferred_amount == our_state.transferred_amount assert test_channel.distributable == our_state.contract_balance assert test_channel.outstanding == our_state.amount_locked assert test_channel.outstanding == 0 assert test_channel.locked == partner_state.amount_locked assert test_channel.our_state.amount_locked == 0 assert test_channel.partner_state.amount_locked == 0 assert test_channel.get_next_nonce() == 1 with pytest.raises(ValueError): test_channel.create_directtransfer( -10, identifier=1, ) with pytest.raises(ValueError): test_channel.create_directtransfer( balance1 + 10, identifier=1, ) amount1 = 10 directtransfer = test_channel.create_directtransfer( amount1, identifier=1, ) directtransfer.sign(privkey1, address1) test_channel.register_transfer( block_number, directtransfer, ) assert test_channel.contract_balance == balance1 assert test_channel.balance == balance1 - amount1 assert test_channel.transferred_amount == amount1 assert test_channel.distributable == balance1 - amount1 assert test_channel.outstanding == 0 assert test_channel.locked == 0 assert test_channel.our_state.amount_locked == 0 assert test_channel.partner_state.amount_locked == 0 assert test_channel.get_next_nonce() == 2 secret = sha3('test_channel') hashlock = sha3(secret) amount2 = 10 fee = 0 expiration = block_number + settle_timeout - 5 identifier = 1 mediatedtransfer = test_channel.create_mediatedtransfer( address1, address2, fee, amount2, identifier, expiration, hashlock, ) mediatedtransfer.sign(privkey1, address1) test_channel.register_transfer( block_number, mediatedtransfer, ) assert test_channel.contract_balance == balance1 assert test_channel.balance == balance1 - amount1 assert test_channel.transferred_amount == amount1 assert test_channel.distributable == balance1 - amount1 - amount2 assert test_channel.outstanding == 0 assert test_channel.locked == amount2 assert test_channel.our_state.amount_locked == amount2 assert test_channel.partner_state.amount_locked == 0 assert test_channel.get_next_nonce() == 3 secret_message = test_channel.create_secret(identifier, secret) secret_message.sign(privkey1, address1) test_channel.register_transfer(block_number, secret_message) assert test_channel.contract_balance == balance1 assert test_channel.balance == balance1 - amount1 - amount2 assert test_channel.transferred_amount == amount1 + amount2 assert test_channel.distributable == balance1 - amount1 - amount2 assert test_channel.outstanding == 0 assert test_channel.locked == 0 assert test_channel.our_state.amount_locked == 0 assert test_channel.partner_state.amount_locked == 0 assert test_channel.get_next_nonce() == 4
def test_receiver_cannot_spend_locked_amount(): token_address = make_address() privkey1, address1 = make_privkey_address() privkey2, address2 = make_privkey_address() balance1 = 33 balance2 = 11 reveal_timeout = 7 settle_timeout = 21 block_number = 7 our_state = ChannelEndState(address1, balance1, None, EMPTY_MERKLE_TREE) partner_state = ChannelEndState(address2, balance2, None, EMPTY_MERKLE_TREE) external_state = make_external_state() test_channel = Channel( our_state, partner_state, external_state, token_address, reveal_timeout, settle_timeout, ) amount1 = balance2 expiration = block_number + settle_timeout receive_mediated_transfer0 = test_channel.create_mediatedtransfer( address1, address2, fee=0, amount=amount1, identifier=1, expiration=expiration, hashlock=sha3('test_locked_amount_cannot_be_spent'), ) receive_mediated_transfer0.sign(privkey2, address2) test_channel.register_transfer( block_number, receive_mediated_transfer0, ) # trying to send one unit of the locked token amount2 = balance1 + 1 lock2 = Lock( amount=amount2, expiration=expiration, hashlock=sha3('test_locked_amount_cannot_be_spent2'), ) layers = compute_layers([sha3(lock2.as_bytes)]) tree2 = MerkleTreeState(layers) locksroot2 = merkleroot(tree2) send_mediated_transfer0 = MediatedTransfer( identifier=1, nonce=1, token=token_address, channel=test_channel.channel_address, transferred_amount=0, recipient=address2, locksroot=locksroot2, lock=lock2, target=address2, initiator=address1, fee=0, ) send_mediated_transfer0.sign(privkey1, address1) # address1 balance is all locked with pytest.raises(InsufficientBalance): test_channel.register_transfer( block_number, send_mediated_transfer0, )
def test_sender_cannot_overspend(): token_address = make_address() privkey1, address1 = make_privkey_address() address2 = make_address() balance1 = 70 balance2 = 110 reveal_timeout = 5 settle_timeout = 15 block_number = 10 our_state = ChannelEndState(address1, balance1, None, EMPTY_MERKLE_TREE) partner_state = ChannelEndState(address2, balance2, None, EMPTY_MERKLE_TREE) external_state = make_external_state() test_channel = Channel( our_state, partner_state, external_state, token_address, reveal_timeout, settle_timeout, ) amount = balance1 expiration = block_number + settle_timeout sent_mediated_transfer0 = test_channel.create_mediatedtransfer( address1, address2, fee=0, amount=amount, identifier=1, expiration=expiration, hashlock=sha3('test_locked_amount_cannot_be_spent'), ) sent_mediated_transfer0.sign(privkey1, address1) test_channel.register_transfer( block_number, sent_mediated_transfer0, ) lock2 = Lock( amount=amount, expiration=expiration, hashlock=sha3('test_locked_amount_cannot_be_spent2'), ) leaves = [ sha3(sent_mediated_transfer0.lock.as_bytes), sha3(lock2.as_bytes), ] tree2 = MerkleTreeState(compute_layers(leaves)) locksroot2 = merkleroot(tree2) sent_mediated_transfer1 = MediatedTransfer( identifier=2, nonce=sent_mediated_transfer0.nonce + 1, token=token_address, channel=test_channel.channel_address, transferred_amount=0, recipient=address2, locksroot=locksroot2, lock=lock2, target=address2, initiator=address1, fee=0, ) sent_mediated_transfer1.sign(privkey1, address1) # address1 balance is all locked with pytest.raises(InsufficientBalance): test_channel.register_transfer( block_number, sent_mediated_transfer1, )
def test_python_channel(): asset_address = make_address() privkey1, address1 = make_privkey_address() address2 = make_address() balance1 = 70 balance2 = 110 reveal_timeout = 5 settle_timeout = 15 our_state = ChannelEndState(address1, balance1) partner_state = ChannelEndState(address2, balance2) external_state = make_external_state() test_channel = Channel( our_state, partner_state, external_state, asset_address, reveal_timeout, settle_timeout, ) assert test_channel.contract_balance == our_state.contract_balance assert test_channel.balance == our_state.balance(partner_state) assert test_channel.transferred_amount == our_state.transferred_amount assert test_channel.distributable == our_state.distributable(partner_state) assert test_channel.outstanding == our_state.locked() assert test_channel.outstanding == 0 assert test_channel.locked == partner_state.locked() assert test_channel.our_state.locked() == 0 assert test_channel.partner_state.locked() == 0 with pytest.raises(ValueError): test_channel.create_directtransfer( -10, 1 # TODO: fill in identifier ) with pytest.raises(ValueError): test_channel.create_directtransfer( balance1 + 10, 1 # TODO: fill in identifier ) amount1 = 10 directtransfer = test_channel.create_directtransfer( amount1, 1 # TODO: fill in identifier ) directtransfer.sign(privkey1, address1) test_channel.register_transfer(directtransfer) assert test_channel.contract_balance == balance1 assert test_channel.balance == balance1 - amount1 assert test_channel.transferred_amount == amount1 assert test_channel.distributable == balance1 - amount1 assert test_channel.outstanding == 0 assert test_channel.locked == 0 assert test_channel.our_state.locked() == 0 assert test_channel.partner_state.locked() == 0 secret = sha3('test_channel') hashlock = sha3(secret) amount2 = 10 fee = 0 expiration = settle_timeout - 5 mediatedtransfer = test_channel.create_mediatedtransfer( address1, address2, fee, amount2, 1, # TODO: fill in identifier expiration, hashlock, ) mediatedtransfer.sign(privkey1, address1) test_channel.register_transfer(mediatedtransfer) assert test_channel.contract_balance == balance1 assert test_channel.balance == balance1 - amount1 assert test_channel.transferred_amount == amount1 assert test_channel.distributable == balance1 - amount1 - amount2 assert test_channel.outstanding == 0 assert test_channel.locked == amount2 assert test_channel.our_state.locked() == 0 assert test_channel.partner_state.locked() == amount2 test_channel.release_lock(secret) assert test_channel.contract_balance == balance1 assert test_channel.balance == balance1 - amount1 - amount2 assert test_channel.transferred_amount == amount1 + amount2 assert test_channel.distributable == balance1 - amount1 - amount2 assert test_channel.outstanding == 0 assert test_channel.locked == 0 assert test_channel.our_state.locked() == 0 assert test_channel.partner_state.locked() == 0
def register_channel(self, netting_channel, reveal_timeout): """ Register a new channel. Args: netting_channel (network.rpc.client.NettingChannel): The netting channel proxy. reveal_timeout (int): Minimum number of blocks required by this node to see a secret. Raises: ValueError: If raiden.address is not one of the participants in the netting channel. """ translator = ContractTranslator(NETTING_CHANNEL_ABI) # Race condition: # - If the filter is installed after the call to `details` a deposit # could be missed in the meantime, to avoid this we first install the # filter listener and then call `deposit`. # - Because of the above strategy a `deposit` event could be handled # twice, for this reason we must not use `deposit` in the events but # the resulting `balance`. task_name = 'ChannelNewBalance {}'.format(pex(netting_channel.address)) newbalance = netting_channel.channelnewbalance_filter() newbalance_listener = LogListenerTask( task_name, newbalance, self.raiden.on_event, translator, ) task_name = 'ChannelSecretRevelead {}'.format( pex(netting_channel.address)) secretrevealed = netting_channel.channelsecretrevealed_filter() secretrevealed_listener = LogListenerTask( task_name, secretrevealed, self.raiden.on_event, translator, ) task_name = 'ChannelClosed {}'.format(pex(netting_channel.address)) close = netting_channel.channelclosed_filter() close_listener = LogListenerTask( task_name, close, self.raiden.on_event, translator, ) task_name = 'ChannelSettled {}'.format(pex(netting_channel.address)) settled = netting_channel.channelsettled_filter() settled_listener = LogListenerTask( task_name, settled, self.raiden.on_event, translator, ) channel_details = netting_channel.detail(self.raiden.address) our_state = ChannelEndState( channel_details['our_address'], channel_details['our_balance'], ) partner_state = ChannelEndState( channel_details['partner_address'], channel_details['partner_balance'], ) external_state = ChannelExternalState( self.raiden.alarm.register_callback, self.register_channel_for_hashlock, self.raiden.chain.block_number, netting_channel, ) channel = Channel( our_state, partner_state, external_state, self.asset_address, reveal_timeout, channel_details['settle_timeout'], ) self.partneraddress_channel[partner_state.address] = channel self.address_channel[netting_channel.address] = channel newbalance_listener.start() secretrevealed_listener.start() close_listener.start() settled_listener.start() self.raiden.event_listeners.append(newbalance_listener) self.raiden.event_listeners.append(secretrevealed_listener) self.raiden.event_listeners.append(close_listener) self.raiden.event_listeners.append(settled_listener)
def test_receiver_cannot_spend_locked_amount(): token_address = make_address() privkey1, address1 = make_privkey_address() privkey2, address2 = make_privkey_address() balance1 = 33 balance2 = 11 reveal_timeout = 7 settle_timeout = 21 block_number = 7 our_state = ChannelEndState(address1, balance1, None, EMPTY_MERKLE_TREE) partner_state = ChannelEndState(address2, balance2, None, EMPTY_MERKLE_TREE) external_state = make_external_state() test_channel = Channel( our_state, partner_state, external_state, token_address, reveal_timeout, settle_timeout, ) amount1 = balance2 expiration = block_number + settle_timeout receive_mediated_transfer0 = test_channel.create_mediatedtransfer( address1, address2, fee=0, amount=amount1, identifier=1, expiration=expiration, hashlock=sha3(b'test_locked_amount_cannot_be_spent'), ) receive_mediated_transfer0.sign(privkey2, address2) test_channel.register_transfer( block_number, receive_mediated_transfer0, ) # trying to send one unit of the locked token amount2 = balance1 + 1 lock2 = Lock( amount=amount2, expiration=expiration, hashlock=sha3(b'test_locked_amount_cannot_be_spent2'), ) layers = compute_layers([sha3(lock2.as_bytes)]) tree2 = MerkleTreeState(layers) locksroot2 = merkleroot(tree2) send_mediated_transfer0 = MediatedTransfer( identifier=1, nonce=1, token=token_address, channel=test_channel.channel_address, transferred_amount=0, recipient=address2, locksroot=locksroot2, lock=lock2, target=address2, initiator=address1, fee=0, ) send_mediated_transfer0.sign(privkey1, address1) # address1 balance is all locked with pytest.raises(InsufficientBalance): test_channel.register_transfer( block_number, send_mediated_transfer0, )
def test_sender_cannot_overspend(): token_address = make_address() privkey1, address1 = make_privkey_address() address2 = make_address() balance1 = 70 balance2 = 110 reveal_timeout = 5 settle_timeout = 15 block_number = 10 our_state = ChannelEndState(address1, balance1, None, EMPTY_MERKLE_TREE) partner_state = ChannelEndState(address2, balance2, None, EMPTY_MERKLE_TREE) external_state = make_external_state() test_channel = Channel( our_state, partner_state, external_state, token_address, reveal_timeout, settle_timeout, ) amount = balance1 expiration = block_number + settle_timeout sent_mediated_transfer0 = test_channel.create_mediatedtransfer( address1, address2, fee=0, amount=amount, identifier=1, expiration=expiration, hashlock=sha3(b'test_locked_amount_cannot_be_spent'), ) sent_mediated_transfer0.sign(privkey1, address1) test_channel.register_transfer( block_number, sent_mediated_transfer0, ) lock2 = Lock( amount=amount, expiration=expiration, hashlock=sha3(b'test_locked_amount_cannot_be_spent2'), ) leaves = [ sha3(sent_mediated_transfer0.lock.as_bytes), sha3(lock2.as_bytes), ] tree2 = MerkleTreeState(compute_layers(leaves)) locksroot2 = merkleroot(tree2) sent_mediated_transfer1 = MediatedTransfer( identifier=2, nonce=sent_mediated_transfer0.nonce + 1, token=token_address, channel=test_channel.channel_address, transferred_amount=0, recipient=address2, locksroot=locksroot2, lock=lock2, target=address2, initiator=address1, fee=0, ) sent_mediated_transfer1.sign(privkey1, address1) # address1 balance is all locked with pytest.raises(InsufficientBalance): test_channel.register_transfer( block_number, sent_mediated_transfer1, )
def register_channel(self, netting_channel, reveal_timeout): """ Register a new channel. Args: netting_channel (network.rpc.client.NettingChannel): The netting channel proxy. reveal_timeout (int): Minimum number of blocks required by this node to see a secret. Raises: ValueError: If raiden.address is not one of the participants in the netting channel. """ translator = ContractTranslator(NETTING_CHANNEL_ABI) # race condition: # - if the filter is installed after a deposit is made it could be # missed, to avoid that we first install the filter, then request the # state from the node and then poll the filter. # - with the above strategy the same deposit could be handled twice, # once from the status received from the netting contract and once from # the event, to avoid problems the we use the balance instead of the # deposit is used. newbalance = netting_channel.channelnewbalance_filter() newbalance_listener = LogListenerTask( newbalance, self.raiden.on_event, translator, ) secretrevealed = netting_channel.channelsecretrevealed_filter() secretrevealed_listener = LogListenerTask( secretrevealed, self.raiden.on_event, translator, ) close = netting_channel.channelclosed_filter() close_listener = LogListenerTask( close, self.raiden.on_event, translator, ) settled = netting_channel.channelsettled_filter() settled_listener = LogListenerTask( settled, self.raiden.on_event, translator, ) channel_details = netting_channel.detail(self.raiden.address) our_state = ChannelEndState( channel_details['our_address'], channel_details['our_balance'], ) partner_state = ChannelEndState( channel_details['partner_address'], channel_details['partner_balance'], ) external_state = ChannelExternalState( self.register_channel_for_hashlock, self.raiden.chain.block_number, netting_channel, ) channel = Channel( our_state, partner_state, external_state, self.asset_address, reveal_timeout, channel_details['settle_timeout'], ) self.partneraddress_channel[partner_state.address] = channel self.address_channel[netting_channel.address] = channel self.channelgraph.add_path( channel_details['our_address'], channel_details['partner_address'], ) newbalance_listener.start() secretrevealed_listener.start() close_listener.start() settled_listener.start() self.raiden.event_listeners.append(newbalance_listener) self.raiden.event_listeners.append(secretrevealed_listener) self.raiden.event_listeners.append(close_listener) self.raiden.event_listeners.append(settled_listener)
def test_channel(): class NettingChannelMock(object): def opened(self): return 1 def closed(self): return 0 def settled(self): return 0 asset_address = make_address() privkey1, address1 = make_privkey_address() address2 = make_address() balance1 = 70 balance2 = 110 reveal_timeout = 5 settle_timeout = 15 our_state = ChannelEndState(address1, balance1) partner_state = ChannelEndState(address2, balance2) block_alarm = list() channel_for_hashlock = list() netting_channel = NettingChannelMock() external_state = ChannelExternalState( block_alarm.append, lambda *args: channel_for_hashlock.append(args), lambda: 1, netting_channel, ) channel = Channel( our_state, partner_state, external_state, asset_address, reveal_timeout, settle_timeout, ) assert channel.contract_balance == our_state.contract_balance assert channel.balance == our_state.balance(partner_state) assert channel.transfered_amount == our_state.transfered_amount assert channel.distributable == our_state.distributable(partner_state) assert channel.outstanding == our_state.locked() assert channel.outstanding == 0 assert channel.locked == partner_state.locked() assert channel.our_state.locked() == 0 assert channel.partner_state.locked() == 0 with pytest.raises(ValueError): channel.create_directtransfer(-10) with pytest.raises(ValueError): channel.create_directtransfer(balance1 + 10) amount1 = 10 directtransfer = channel.create_directtransfer(amount1) directtransfer.sign(privkey1, address1) channel.register_transfer(directtransfer) assert channel.contract_balance == balance1 assert channel.balance == balance1 - amount1 assert channel.transfered_amount == amount1 assert channel.distributable == balance1 - amount1 assert channel.outstanding == 0 assert channel.locked == 0 assert channel.our_state.locked() == 0 assert channel.partner_state.locked() == 0 secret = sha3('test_channel') hashlock = sha3(secret) amount2 = 10 fee = 0 expiration = settle_timeout - 5 mediatedtransfer = channel.create_mediatedtransfer( address1, address2, fee, amount2, expiration, hashlock, ) mediatedtransfer.sign(privkey1, address1) channel.register_transfer(mediatedtransfer) assert channel.contract_balance == balance1 assert channel.balance == balance1 - amount1 assert channel.transfered_amount == amount1 assert channel.distributable == balance1 - amount1 - amount2 assert channel.outstanding == 0 assert channel.locked == amount2 assert channel.our_state.locked() == 0 assert channel.partner_state.locked() == amount2 channel.claim_lock(secret) assert channel.contract_balance == balance1 assert channel.balance == balance1 - amount1 - amount2 assert channel.transfered_amount == amount1 + amount2 assert channel.distributable == balance1 - amount1 - amount2 assert channel.outstanding == 0 assert channel.locked == 0 assert channel.our_state.locked() == 0 assert channel.partner_state.locked() == 0
def test_python_channel(): token_address = make_address() privkey1, address1 = make_privkey_address() address2 = make_address() balance1 = 70 balance2 = 110 reveal_timeout = 5 settle_timeout = 15 block_number = 10 our_state = ChannelEndState(address1, balance1, None, EMPTY_MERKLE_TREE) partner_state = ChannelEndState(address2, balance2, None, EMPTY_MERKLE_TREE) external_state = make_external_state() test_channel = Channel( our_state, partner_state, external_state, token_address, reveal_timeout, settle_timeout, ) assert test_channel.contract_balance == our_state.contract_balance assert test_channel.transferred_amount == our_state.transferred_amount assert test_channel.distributable == our_state.contract_balance assert test_channel.outstanding == our_state.amount_locked assert test_channel.outstanding == 0 assert test_channel.locked == partner_state.amount_locked assert test_channel.our_state.amount_locked == 0 assert test_channel.partner_state.amount_locked == 0 assert test_channel.get_next_nonce() == 1 with pytest.raises(ValueError): test_channel.create_directtransfer( -10, identifier=1, ) with pytest.raises(ValueError): test_channel.create_directtransfer( balance1 + 10, identifier=1, ) amount1 = 10 directtransfer = test_channel.create_directtransfer( amount1, identifier=1, ) directtransfer.sign(privkey1, address1) test_channel.register_transfer( block_number, directtransfer, ) assert test_channel.contract_balance == balance1 assert test_channel.balance == balance1 - amount1 assert test_channel.transferred_amount == amount1 assert test_channel.distributable == balance1 - amount1 assert test_channel.outstanding == 0 assert test_channel.locked == 0 assert test_channel.our_state.amount_locked == 0 assert test_channel.partner_state.amount_locked == 0 assert test_channel.get_next_nonce() == 2 secret = sha3(b'test_channel') hashlock = sha3(secret) amount2 = 10 fee = 0 expiration = block_number + settle_timeout - 5 identifier = 1 mediatedtransfer = test_channel.create_mediatedtransfer( address1, address2, fee, amount2, identifier, expiration, hashlock, ) mediatedtransfer.sign(privkey1, address1) test_channel.register_transfer( block_number, mediatedtransfer, ) assert test_channel.contract_balance == balance1 assert test_channel.balance == balance1 - amount1 assert test_channel.transferred_amount == amount1 assert test_channel.distributable == balance1 - amount1 - amount2 assert test_channel.outstanding == 0 assert test_channel.locked == amount2 assert test_channel.our_state.amount_locked == amount2 assert test_channel.partner_state.amount_locked == 0 assert test_channel.get_next_nonce() == 3 secret_message = test_channel.create_secret(identifier, secret) secret_message.sign(privkey1, address1) test_channel.register_transfer(block_number, secret_message) assert test_channel.contract_balance == balance1 assert test_channel.balance == balance1 - amount1 - amount2 assert test_channel.transferred_amount == amount1 + amount2 assert test_channel.distributable == balance1 - amount1 - amount2 assert test_channel.outstanding == 0 assert test_channel.locked == 0 assert test_channel.our_state.amount_locked == 0 assert test_channel.partner_state.amount_locked == 0 assert test_channel.get_next_nonce() == 4