def populate_token_network_random(token_network_model: TokenNetwork, private_keys: List[str]) -> None: # seed for pseudo-randomness from config constant, that changes from time to time random.seed(NUMBER_OF_CHANNELS) for channel_id_int in range(NUMBER_OF_CHANNELS): channel_id = ChannelID(channel_id_int) private_key1, private_key2 = random.sample(private_keys, 2) address1 = Address(private_key_to_address(private_key1)) address2 = Address(private_key_to_address(private_key2)) settle_timeout = 15 token_network_model.handle_channel_opened_event( channel_id, address1, address2, settle_timeout) # deposit to channels deposit1 = TokenAmount(random.randint(0, 1000)) deposit2 = TokenAmount(random.randint(0, 1000)) address1, address2 = token_network_model.channel_id_to_addresses[ channel_id] token_network_model.handle_channel_new_deposit_event( channel_id, address1, deposit1) token_network_model.handle_channel_new_deposit_event( channel_id, address2, deposit2) token_network_model.handle_channel_balance_update_message( UpdatePFS( canonical_identifier=CanonicalIdentifier( chain_identifier=ChainID(1), channel_identifier=channel_id, token_network_address=TokenNetworkAddressBytes( decode_hex(token_network_model.address)), ), updating_participant=decode_hex(address1), other_participant=decode_hex(address2), updating_nonce=Nonce(1), other_nonce=Nonce(1), updating_capacity=deposit1, other_capacity=deposit2, reveal_timeout=2, mediation_fee=FeeAmount(0), )) token_network_model.handle_channel_balance_update_message( UpdatePFS( canonical_identifier=CanonicalIdentifier( chain_identifier=ChainID(1), channel_identifier=channel_id, token_network_address=TokenNetworkAddressBytes( decode_hex(token_network_model.address)), ), updating_participant=decode_hex(address2), other_participant=decode_hex(address1), updating_nonce=Nonce(2), other_nonce=Nonce(1), updating_capacity=deposit2, other_capacity=deposit1, reveal_timeout=2, mediation_fee=FeeAmount(0), ))
def make_signed_balance_proof( nonce: typing.Nonce = EMPTY, transferred_amount: typing.TokenAmount = EMPTY, locked_amount: typing.TokenAmount = EMPTY, token_network_address: typing.TokenNetworkID = EMPTY, channel_identifier: typing.ChannelID = EMPTY, locksroot: typing.Locksroot = EMPTY, extra_hash: typing.Keccak256 = EMPTY, private_key: bytes = EMPTY, sender_address: typing.Address = EMPTY, ) -> BalanceProofSignedState: nonce = if_empty(nonce, make_uint256()) transferred_amount = if_empty(transferred_amount, make_uint256()) locked_amount = if_empty(locked_amount, make_uint256()) token_network_address = if_empty(token_network_address, make_address()) channel_identifier = if_empty(channel_identifier, make_uint256()) locksroot = if_empty(locksroot, make_32bytes()) extra_hash = if_empty(extra_hash, make_keccak_hash()) private_key = if_empty(private_key, make_privatekey()) sender_address = if_empty(sender_address, make_address()) signer = LocalSigner(private_key) balance_hash = hash_balance_data( transferred_amount=transferred_amount, locked_amount=locked_amount, locksroot=locksroot, ) data_to_sign = balance_proof.pack_balance_proof( nonce=nonce, balance_hash=balance_hash, additional_hash=extra_hash, canonical_identifier=CanonicalIdentifier( chain_identifier=UNIT_CHAIN_ID, token_network_address=token_network_address, channel_identifier=channel_identifier, ), ) signature = signer.sign(data=data_to_sign) return BalanceProofSignedState( nonce=nonce, transferred_amount=transferred_amount, locked_amount=locked_amount, locksroot=locksroot, message_hash=extra_hash, signature=signature, sender=sender_address, canonical_identifier=CanonicalIdentifier( chain_identifier=UNIT_CHAIN_ID, token_network_address=token_network_address, channel_identifier=channel_identifier, ), )
def _get_onchain_locksroots( raiden: RaidenService, storage: SQLiteStorage, token_network: Dict[str, Any], channel: Dict[str, Any], ) -> Tuple[Locksroot, Locksroot]: channel_new_state_change = _find_channel_new_state_change( storage=storage, token_network_address=token_network['address'], channel_identifier=channel['identifier'], ) if not channel_new_state_change: raise RaidenUnrecoverableError( f'Could not find the state change for channel {channel["identifier"]}, ' f'token network address: {token_network["address"]} being created. ', ) canonical_identifier = CanonicalIdentifier( chain_identifier=CHAIN_ID_UNSPECIFIED, token_network_address=to_canonical_address(token_network['address']), channel_identifier=int(channel['identifier']), ) our_locksroot, partner_locksroot = get_onchain_locksroots( chain=raiden.chain, canonical_identifier=canonical_identifier, participant1=to_canonical_address(channel['our_state']['address']), participant2=to_canonical_address(channel['partner_state']['address']), block_identifier='latest', ) return our_locksroot, partner_locksroot
def get_updatepfs_message( updating_participant: Address, other_participant: Address, chain_identifier=ChainID(1), channel_identifier=ChannelID(0), token_network_address: TokenNetworkAddressBytes = DEFAULT_TOKEN_NETWORK_ADDRESS_BYTES, updating_nonce=Nonce(1), other_nonce=Nonce(0), updating_capacity=TokenAmount(90), other_capacity=TokenAmount(110), reveal_timeout: int = 2, mediation_fee: FeeAmount = FeeAmount(0), privkey_signer: bytes = PRIVAT_KEY_EXAMPLE_1, ) -> UpdatePFS: updatepfs_message = UpdatePFS( canonical_identifier=CanonicalIdentifier( chain_identifier=chain_identifier, channel_identifier=channel_identifier, token_network_address=token_network_address, ), updating_participant=decode_hex(updating_participant), other_participant=decode_hex(other_participant), updating_nonce=updating_nonce, other_nonce=other_nonce, updating_capacity=updating_capacity, other_capacity=other_capacity, reveal_timeout=reveal_timeout, mediation_fee=mediation_fee, ) updatepfs_message.sign(LocalSigner(privkey_signer)) return updatepfs_message
def _(properties, defaults=None) -> LockedTransferUnsignedState: defaults = defaults or LOCKED_TRANSFER_DEFAULTS parameters = _properties_to_dict(properties, defaults) lock = HashTimeLockState( amount=parameters.pop('amount'), expiration=parameters.pop('expiration'), secrethash=sha3(parameters.pop('secret')), ) balance_proof_parameters = _properties_to_dict( parameters.pop('balance_proof'), defaults.balance_proof, ) balance_proof_parameters['canonical_identifier'] = CanonicalIdentifier( chain_identifier=balance_proof_parameters.pop('chain_id'), token_network_address=balance_proof_parameters.pop( 'token_network_identifier'), channel_identifier=balance_proof_parameters.pop('channel_identifier'), ) if balance_proof_parameters['locksroot'] == EMPTY_MERKLE_ROOT: balance_proof_parameters['locksroot'] = lock.lockhash balance_proof = BalanceProofUnsignedState(**balance_proof_parameters) return LockedTransferUnsignedState(balance_proof=balance_proof, lock=lock, **parameters)
def handle_channel_batch_unlock(raiden: 'RaidenService', event: Event): token_network_identifier = event.originating_contract data = event.event_data args = data['args'] block_number = data['block_number'] block_hash = data['block_hash'] transaction_hash = data['transaction_hash'] chain_state = views.state_from_raiden(raiden) unlock_state_change = ContractReceiveChannelBatchUnlock( transaction_hash=transaction_hash, canonical_identifier=CanonicalIdentifier( chain_identifier=chain_state.chain_id, token_network_address=token_network_identifier, # FIXME: we will resolve the channel identifier only further down in # raiden.transfer.token_network::handle_batch_unlock # can/should we do it here already? channel_identifier=CHANNEL_ID_UNSPECIFIED, ), participant=args['participant'], partner=args['partner'], locksroot=args['locksroot'], unlocked_amount=args['unlocked_amount'], returned_tokens=args['returned_tokens'], block_number=block_number, block_hash=block_hash, ) raiden.handle_and_track_state_change(unlock_state_change)
def handle_channel_update_transfer(raiden: 'RaidenService', event: Event): token_network_identifier = event.originating_contract data = event.event_data args = data['args'] channel_identifier = args['channel_identifier'] transaction_hash = data['transaction_hash'] block_number = data['block_number'] block_hash = data['block_hash'] chain_state = views.state_from_raiden(raiden) channel_state = views.get_channelstate_by_canonical_identifier( chain_state=chain_state, canonical_identifier=CanonicalIdentifier( chain_identifier=chain_state.chain_id, token_network_address=token_network_identifier, channel_identifier=channel_identifier, ), ) if channel_state: channel_transfer_updated = ContractReceiveUpdateTransfer( transaction_hash=transaction_hash, canonical_identifier=channel_state.canonical_identifier, nonce=args['nonce'], block_number=block_number, block_hash=block_hash, ) raiden.handle_and_track_state_change(channel_transfer_updated)
def handle_contract_send_channelclose( raiden: 'RaidenService', channel_close_event: ContractSendChannelClose, ): balance_proof = channel_close_event.balance_proof if balance_proof: nonce = balance_proof.nonce balance_hash = balance_proof.balance_hash signature = balance_proof.signature message_hash = balance_proof.message_hash else: nonce = 0 balance_hash = EMPTY_HASH signature = EMPTY_SIGNATURE message_hash = EMPTY_HASH channel_proxy = raiden.chain.payment_channel( canonical_identifier=CanonicalIdentifier( chain_identifier=state_from_raiden(raiden).chain_id, token_network_address=channel_close_event. token_network_identifier, channel_identifier=channel_close_event.channel_identifier, ), ) channel_proxy.close( nonce=nonce, balance_hash=balance_hash, additional_hash=message_hash, signature=signature, block_identifier=channel_close_event.triggered_by_block_hash, )
def get_updatepfs_message( chain_identifier: ChainID = 1, channel_identifier: ChannelID = 0, token_network_address: TokenNetworkAddress = DEFAULT_TOKEN_NETWORK_ADDRESS_BYTES, updating_participant: Address = None, other_participant: Address = None, updating_nonce: Nonce = 1, other_nonce: Nonce = 0, updating_capacity: TokenAmount = 90, other_capacity: TokenAmount = 110, reveal_timeout: int = 2, signature: Signature = '', ) -> UpdatePFS: return UpdatePFS( canonical_identifier=CanonicalIdentifier( chain_identifier=chain_identifier, channel_identifier=channel_identifier, token_network_address=token_network_address, ), updating_participant=updating_participant, other_participant=other_participant, updating_nonce=updating_nonce, other_nonce=other_nonce, updating_capacity=updating_capacity, other_capacity=other_capacity, reveal_timeout=reveal_timeout, signature=signature, )
def _(properties: BalanceProofSignedStateProperties, defaults=None) -> BalanceProofSignedState: defaults = defaults or BALANCE_PROOF_SIGNED_STATE_DEFAULTS params = _properties_to_dict(properties, defaults) params.update( _properties_to_dict(params.pop('balance_proof'), defaults.balance_proof), ) signer = LocalSigner(params.pop('pkey')) if params['signature'] is EMPTY: keys = ('transferred_amount', 'locked_amount', 'locksroot') balance_hash = hash_balance_data(**_partial_dict(params, *keys)) canonical_identifier = CanonicalIdentifier( chain_identifier=params.pop('chain_id'), token_network_address=params.pop('token_network_identifier'), channel_identifier=params.pop('channel_identifier'), ) params['canonical_identifier'] = canonical_identifier data_to_sign = balance_proof.pack_balance_proof( balance_hash=balance_hash, additional_hash=params['message_hash'], canonical_identifier=canonical_identifier, nonce=params.get('nonce'), ) params['signature'] = signer.sign(data=data_to_sign) return BalanceProofSignedState(**params)
def from_dict(cls, data): return cls( canonical_identifier=CanonicalIdentifier( chain_identifier=CHAIN_ID_UNSPECIFIED, token_network_address=to_canonical_address(data['token_network_identifier']), channel_identifier=int(data['channel_identifier']), ), )
def subdispatch_targettask( chain_state: ChainState, state_change: StateChange, token_network_identifier: TokenNetworkID, channel_identifier: ChannelID, secrethash: SecretHash, ) -> TransitionResult[ChainState]: block_number = chain_state.block_number sub_task = chain_state.payment_mapping.secrethashes_to_task.get(secrethash) if not sub_task: is_valid_subtask = True target_state = None elif sub_task and isinstance(sub_task, TargetTask): is_valid_subtask = ( token_network_identifier == sub_task.token_network_identifier) target_state = sub_task.target_state else: is_valid_subtask = False events = list() channel_state = None if is_valid_subtask: channel_state = views.get_channelstate_by_canonical_identifier( chain_state=chain_state, canonical_identifier=CanonicalIdentifier( chain_identifier=chain_state.chain_id, token_network_address=token_network_identifier, channel_identifier=channel_identifier, ), ) if channel_state: pseudo_random_generator = chain_state.pseudo_random_generator iteration = target.state_transition( target_state, state_change, channel_state, pseudo_random_generator, block_number, ) events = iteration.events if iteration.new_state: sub_task = TargetTask( token_network_identifier, channel_identifier, iteration.new_state, ) chain_state.payment_mapping.secrethashes_to_task[ secrethash] = sub_task elif secrethash in chain_state.payment_mapping.secrethashes_to_task: del chain_state.payment_mapping.secrethashes_to_task[secrethash] return TransitionResult(chain_state, events)
def handle_channel_closed(raiden: 'RaidenService', event: Event): token_network_identifier = event.originating_contract data = event.event_data block_number = data['block_number'] args = data['args'] channel_identifier = args['channel_identifier'] transaction_hash = data['transaction_hash'] block_hash = data['block_hash'] chain_state = views.state_from_raiden(raiden) channel_state = views.get_channelstate_by_canonical_identifier( chain_state=chain_state, canonical_identifier=CanonicalIdentifier( chain_identifier=chain_state.chain_id, token_network_address=token_network_identifier, channel_identifier=channel_identifier, ), ) channel_closed: StateChange if channel_state: # The from address is included in the ChannelClosed event as the # closing_participant field channel_closed = ContractReceiveChannelClosed( transaction_hash=transaction_hash, transaction_from=args['closing_participant'], canonical_identifier=channel_state.canonical_identifier, block_number=block_number, block_hash=block_hash, ) raiden.handle_and_track_state_change(channel_closed) else: # This is a channel close event of a channel we're not a participant of route_closed = ContractReceiveRouteClosed( transaction_hash=transaction_hash, canonical_identifier=CanonicalIdentifier( chain_identifier=chain_state.chain_id, token_network_address=token_network_identifier, channel_identifier=channel_identifier, ), block_number=block_number, block_hash=block_hash, ) raiden.handle_and_track_state_change(route_closed)
def wait_for_channel_in_states( raiden: RaidenService, payment_network_id: typing.PaymentNetworkID, token_address: typing.TokenAddress, channel_ids: typing.List[typing.ChannelID], retry_timeout: float, target_states: typing.Tuple[str], ) -> None: """Wait until all channels are in `target_states`. Raises: ValueError: If the token_address is not registered in the payment_network. Note: This does not time out, use gevent.Timeout. """ chain_state = views.state_from_raiden(raiden) token_network = views.get_token_network_by_token_address( chain_state=chain_state, payment_network_id=payment_network_id, token_address=token_address, ) if token_network is None: raise ValueError( f'The token {token_address} is not registered on the network {payment_network_id}.', ) token_network_address = token_network.address list_cannonical_ids = [ CanonicalIdentifier( chain_identifier=chain_state.chain_id, token_network_address=token_network_address, channel_identifier=channel_identifier, ) for channel_identifier in channel_ids ] while list_cannonical_ids: canonical_id = list_cannonical_ids[-1] chain_state = views.state_from_raiden(raiden) channel_state = views.get_channelstate_by_canonical_identifier( chain_state=chain_state, canonical_identifier=canonical_id, ) channel_is_settled = (channel_state is None or channel.get_status(channel_state) in target_states) if channel_is_settled: list_cannonical_ids.pop() else: gevent.sleep(retry_timeout)
def make_canonical_identifier( chain_identifier=UNIT_CHAIN_ID, token_network_address=UNIT_TOKEN_NETWORK_ADDRESS, channel_identifier=UNIT_CHANNEL_ID, ) -> CanonicalIdentifier: return CanonicalIdentifier( chain_identifier=chain_identifier, token_network_address=token_network_address, channel_identifier=channel_identifier, )
def from_dict(cls, data: Dict[str, Any]) -> 'ContractSendChannelSettle': restored = cls( canonical_identifier=CanonicalIdentifier( chain_identifier=CHAIN_ID_UNSPECIFIED, token_network_address=to_canonical_address(data['token_network_identifier']), channel_identifier=ChannelID(int(data['channel_identifier'])), ), triggered_by_block_hash=BlockHash(deserialize_bytes(data['triggered_by_block_hash'])), ) return restored
def from_dict(cls, data: Dict[str, Any]) -> 'ContractReceiveRouteClosed': return cls( transaction_hash=deserialize_transactionhash(data['transaction_hash']), canonical_identifier=CanonicalIdentifier( chain_identifier=CHAIN_ID_UNSPECIFIED, token_network_address=to_canonical_address(data['token_network_identifier']), channel_identifier=ChannelID(int(data['channel_identifier'])), ), block_number=BlockNumber(int(data['block_number'])), block_hash=BlockHash(deserialize_bytes(data['block_hash'])), )
def make_balance_proof_from_counter(counter) -> BalanceProofUnsignedState: return BalanceProofUnsignedState( nonce=next(counter), transferred_amount=next(counter), locked_amount=next(counter), locksroot=sha3(next(counter).to_bytes(1, 'big')), canonical_identifier=CanonicalIdentifier( chain_identifier=next(counter), token_network_address=factories.make_address(), channel_identifier=next(counter), ), )
def handle_channel_new_balance(raiden: 'RaidenService', event: Event): data = event.event_data args = data['args'] block_number = data['block_number'] block_hash = data['block_hash'] channel_identifier = args['channel_identifier'] token_network_identifier = event.originating_contract participant_address = args['participant'] total_deposit = args['total_deposit'] transaction_hash = data['transaction_hash'] chain_state = views.state_from_raiden(raiden) previous_channel_state = views.get_channelstate_by_canonical_identifier( chain_state=chain_state, canonical_identifier=CanonicalIdentifier( chain_identifier=chain_state.chain_id, token_network_address=token_network_identifier, channel_identifier=channel_identifier, ), ) # Channels will only be registered if this node is a participant if previous_channel_state is not None: previous_balance = previous_channel_state.our_state.contract_balance balance_was_zero = previous_balance == 0 deposit_transaction = TransactionChannelNewBalance( participant_address, total_deposit, block_number, ) newbalance_statechange = ContractReceiveChannelNewBalance( transaction_hash=transaction_hash, canonical_identifier=previous_channel_state.canonical_identifier, deposit_transaction=deposit_transaction, block_number=block_number, block_hash=block_hash, ) raiden.handle_and_track_state_change(newbalance_statechange) if balance_was_zero and participant_address != raiden.address: connection_manager = raiden.connection_manager_for_token_network( token_network_identifier, ) join_channel = gevent.spawn( connection_manager.join_channel, participant_address, total_deposit, ) raiden.add_pending_greenlet(join_channel)
def payment_channel_open_and_deposit(app0, app1, token_address, deposit, settle_timeout): """ Open a new channel with app0 and app1 as participants """ assert token_address token_network_address = app0.raiden.default_registry.get_token_network( token_address) token_network_proxy = app0.raiden.chain.token_network( token_network_address) channel_identifier = token_network_proxy.new_netting_channel( partner=app1.raiden.address, settle_timeout=settle_timeout, given_block_identifier='latest', ) assert channel_identifier canonical_identifier = CanonicalIdentifier( chain_identifier=state_from_raiden(app0.raiden).chain_id, token_network_address=token_network_proxy.address, channel_identifier=channel_identifier, ) for app in [app0, app1]: # Use each app's own chain because of the private key / local signing token = app.raiden.chain.token(token_address) payment_channel_proxy = app.raiden.chain.payment_channel( canonical_identifier=canonical_identifier, ) # This check can succeed and the deposit still fail, if channels are # openned in parallel previous_balance = token.balance_of(app.raiden.address) assert previous_balance >= deposit # the payment channel proxy will call approve # token.approve(token_network_proxy.address, deposit) payment_channel_proxy.set_total_deposit(total_deposit=deposit, block_identifier='latest') # Balance must decrease by at least but not exactly `deposit` amount, # because channels can be openned in parallel new_balance = token.balance_of(app.raiden.address) assert new_balance <= previous_balance - deposit check_channel( app0, app1, token_network_proxy.address, channel_identifier, settle_timeout, deposit, )
def from_dict(cls, data: Dict[str, Any]) -> 'ContractReceiveChannelBatchUnlock': return cls( transaction_hash=deserialize_transactionhash(data['transaction_hash']), canonical_identifier=CanonicalIdentifier( chain_identifier=CHAIN_ID_UNSPECIFIED, token_network_address=to_canonical_address(data['token_network_identifier']), channel_identifier=CHANNEL_ID_UNSPECIFIED, ), participant=to_canonical_address(data['participant']), partner=to_canonical_address(data['partner']), locksroot=deserialize_locksroot(data['locksroot']), unlocked_amount=TokenAmount(int(data['unlocked_amount'])), returned_tokens=TokenAmount(int(data['returned_tokens'])), block_number=BlockNumber(int(data['block_number'])), block_hash=deserialize_blockhash(data['block_hash']), )
def check_channel( app1, app2, token_network_identifier, channel_identifier, settle_timeout, deposit_amount, ): canonical_identifier = CanonicalIdentifier( chain_identifier=state_from_raiden(app1.raiden).chain_id, token_network_address=token_network_identifier, channel_identifier=channel_identifier, ) netcontract1 = app1.raiden.chain.payment_channel( canonical_identifier=canonical_identifier, ) netcontract2 = app2.raiden.chain.payment_channel( canonical_identifier=canonical_identifier, ) # Check a valid settle timeout was used, the netting contract has an # enforced minimum and maximum assert settle_timeout == netcontract1.settle_timeout() assert settle_timeout == netcontract2.settle_timeout() if deposit_amount > 0: assert netcontract1.can_transfer('latest') assert netcontract2.can_transfer('latest') app1_details = netcontract1.detail('latest') app2_details = netcontract2.detail('latest') assert (app1_details.participants_data.our_details.address == app2_details.participants_data.partner_details.address) assert (app1_details.participants_data.partner_details.address == app2_details.participants_data.our_details.address) assert (app1_details.participants_data.our_details.deposit == app2_details.participants_data.partner_details.deposit) assert (app1_details.participants_data.partner_details.deposit == app2_details.participants_data.our_details.deposit) assert app1_details.chain_id == app2_details.chain_id assert app1_details.participants_data.our_details.deposit == deposit_amount assert app1_details.participants_data.partner_details.deposit == deposit_amount assert app2_details.participants_data.our_details.deposit == deposit_amount assert app2_details.participants_data.partner_details.deposit == deposit_amount assert app2_details.chain_id == UNIT_CHAIN_ID
def channel_state_until_state_change( raiden, payment_network_identifier: typing.PaymentNetworkID, token_address: typing.TokenAddress, channel_identifier: typing.ChannelID, state_change_identifier: int, ) -> typing.Optional[NettingChannelState]: """ Go through WAL state changes until a certain balance hash is found. """ wal = restore_to_state_change( transition_function=node.state_transition, storage=raiden.wal.storage, state_change_identifier=state_change_identifier, ) msg = 'There is a state change, therefore the state must not be None' assert wal.state_manager.current_state is not None, msg chain_state = wal.state_manager.current_state token_network = views.get_token_network_by_token_address( chain_state=chain_state, payment_network_id=payment_network_identifier, token_address=token_address, ) if not token_network: return None token_network_address = token_network.address canonical_identifier = CanonicalIdentifier( chain_identifier=chain_state.chain_id, token_network_address=token_network_address, channel_identifier=channel_identifier, ) channel_state = views.get_channelstate_by_canonical_identifier( chain_state=wal.state_manager.current_state, canonical_identifier=canonical_identifier, ) if not channel_state: raise RaidenUnrecoverableError( f"Channel was not found before state_change {state_change_identifier}", ) return channel_state
def handle_contract_send_channelupdate( raiden: RaidenService, channel_update_event: ContractSendChannelUpdateTransfer, ): balance_proof = channel_update_event.balance_proof if balance_proof: channel = raiden.chain.payment_channel( token_network_address=channel_update_event. token_network_identifier, channel_id=channel_update_event.channel_identifier, ) non_closing_data = pack_balance_proof_update( nonce=balance_proof.nonce, balance_hash=balance_proof.balance_hash, additional_hash=balance_proof.message_hash, canonical_identifier=CanonicalIdentifier( chain_identifier=balance_proof.chain_id, token_network_address=balance_proof. token_network_identifier, channel_identifier=balance_proof.channel_identifier, ), partner_signature=balance_proof.signature, ) our_signature = raiden.signer.sign(data=non_closing_data) try: channel.update_transfer( nonce=balance_proof.nonce, balance_hash=balance_proof.balance_hash, additional_hash=balance_proof.message_hash, partner_signature=balance_proof.signature, signature=our_signature, block_identifier=channel_update_event. triggered_by_block_hash, ) except ChannelOutdatedError as e: log.error( str(e), node=pex(raiden.address), )
def handle_contract_receive_channel_closed( chain_state: ChainState, state_change: ContractReceiveChannelClosed, ) -> TransitionResult[ChainState]: # cleanup queue for channel channel_state = views.get_channelstate_by_canonical_identifier( chain_state=chain_state, canonical_identifier=CanonicalIdentifier( chain_identifier=chain_state.chain_id, token_network_address=state_change.token_network_identifier, channel_identifier=state_change.channel_identifier, ), ) if channel_state: queue_id = QueueIdentifier( recipient=channel_state.partner_state.address, channel_identifier=state_change.channel_identifier, ) if queue_id in chain_state.queueids_to_queues: chain_state.queueids_to_queues.pop(queue_id) return handle_token_network_action(chain_state=chain_state, state_change=state_change)
def test_request_monitoring(): partner_signer = LocalSigner(PARTNER_PRIVKEY) balance_proof = make_balance_proof(signer=partner_signer, amount=1) partner_signed_balance_proof = SignedBlindedBalanceProof.from_balance_proof_signed_state( balance_proof, ) request_monitoring = RequestMonitoring( onchain_balance_proof=partner_signed_balance_proof, reward_amount=55, ) assert request_monitoring with pytest.raises(ValueError): request_monitoring.to_dict() request_monitoring.sign(signer) as_dict = request_monitoring.to_dict() assert RequestMonitoring.from_dict(as_dict) == request_monitoring packed = request_monitoring.pack(request_monitoring.packed()) assert RequestMonitoring.unpack(packed) == request_monitoring # RequestMonitoring can be created directly from BalanceProofSignedState direct_created = RequestMonitoring.from_balance_proof_signed_state( balance_proof, reward_amount=55, ) with pytest.raises(ValueError): # equality test uses `validated` packed format assert direct_created == request_monitoring direct_created.sign(signer) # Instances created from same balance proof are equal assert direct_created == request_monitoring other_balance_proof = make_balance_proof(signer=partner_signer, amount=2) other_instance = RequestMonitoring.from_balance_proof_signed_state( other_balance_proof, reward_amount=55, ) other_instance.sign(signer) # different balance proof ==> non-equality assert other_instance != request_monitoring # test signature verification reward_proof_data = pack_reward_proof( request_monitoring.balance_proof.channel_identifier, request_monitoring.reward_amount, request_monitoring.balance_proof.token_network_address, request_monitoring.balance_proof.chain_id, request_monitoring.balance_proof.nonce, ) assert recover(reward_proof_data, request_monitoring.reward_proof_signature) == ADDRESS blinded_data = pack_balance_proof_update( nonce=request_monitoring.balance_proof.nonce, balance_hash=request_monitoring.balance_proof.balance_hash, additional_hash=request_monitoring.balance_proof.additional_hash, canonical_identifier=CanonicalIdentifier( chain_identifier=request_monitoring.balance_proof.chain_id, token_network_address=request_monitoring.balance_proof. token_network_address, channel_identifier=request_monitoring.balance_proof. channel_identifier, ), partner_signature=request_monitoring.balance_proof.signature, ) assert recover(blinded_data, request_monitoring.non_closing_signature) == ADDRESS balance_proof_data = pack_balance_proof( nonce=request_monitoring.balance_proof.nonce, balance_hash=request_monitoring.balance_proof.balance_hash, additional_hash=request_monitoring.balance_proof.additional_hash, canonical_identifier=CanonicalIdentifier( chain_identifier=request_monitoring.balance_proof.chain_id, token_network_address=request_monitoring.balance_proof. token_network_address, channel_identifier=request_monitoring.balance_proof. channel_identifier, ), ) assert recover( balance_proof_data, request_monitoring.balance_proof.signature, ) == PARTNER_ADDRESS assert request_monitoring.verify_request_monitoring( PARTNER_ADDRESS, ADDRESS)
def run_test_secret_revealed_on_chain( raiden_chain, deposit, settle_timeout, token_addresses, retry_interval, ): """ A node must reveal the secret on-chain if it's known and the channel is closed. """ app0, app1, app2 = raiden_chain token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) amount = 10 identifier = 1 target = app2.raiden.address secret = sha3(target) secrethash = sha3(secret) # Reveal the secret, but do not unlock it off-chain app1_hold_event_handler = HoldOffChainSecretRequest() app1.raiden.raiden_event_handler = app1_hold_event_handler app1_hold_event_handler.hold_unlock_for(secrethash=secrethash) app0.raiden.start_mediated_transfer_with_secret( token_network_identifier=token_network_identifier, amount=amount, fee=0, target=target, identifier=identifier, secret=secret, ) with gevent.Timeout(10): wait_for_state_change( app2.raiden, ReceiveSecretReveal, {'secrethash': secrethash}, retry_interval, ) channel_state2_1 = get_channelstate(app2, app1, token_network_identifier) pending_lock = channel_state2_1.partner_state.secrethashes_to_unlockedlocks.get( secrethash) msg = "The lock must be registered in unlocked locks since the secret is known" assert pending_lock is not None, msg # The channels are out-of-sync. app1 has sent the unlock, however we are # intercepting it and app2 has not received the updated balance proof # Close the channel. This must register the secret on chain channel_close_event = ContractSendChannelClose( canonical_identifier=CanonicalIdentifier( chain_identifier=channel_state2_1.chain_id, token_network_address=token_network_identifier, channel_identifier=channel_state2_1.identifier, ), token_address=channel_state2_1.token_address, balance_proof=channel_state2_1.partner_state.balance_proof, triggered_by_block_hash=app0.raiden.chain.block_hash(), ) app2.raiden.raiden_event_handler.on_raiden_event(app2.raiden, channel_close_event) settle_expiration = (app0.raiden.chain.block_number() + settle_timeout + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS) app0.raiden.chain.wait_until_block(target_block_number=settle_expiration) # TODO: # - assert on the transferred amounts on-chain (for settle and unlock) # The channel app0-app1 should continue with the protocol off-chain, once # the secret is released on-chain by app2 assert_synced_channel_state( token_network_identifier, app0, deposit - amount, [], app1, deposit + amount, [], ) with gevent.Timeout(10): wait_for_state_change( app2.raiden, ContractReceiveSecretReveal, {'secrethash': secrethash}, retry_interval, )
def populate_token_network(token_network: TokenNetwork, addresses: List[Address], channel_descriptions: List): for ( channel_id, ( p1_index, p1_deposit, p1_capacity, _p1_fee, p1_reveal_timeout, p2_index, p2_deposit, p2_capacity, _p2_fee, p2_reveal_timeout, settle_timeout, ), ) in enumerate(channel_descriptions): token_network.handle_channel_opened_event( ChannelID(channel_id), addresses[p1_index], addresses[p2_index], settle_timeout=settle_timeout, ) token_network.handle_channel_new_deposit_event( ChannelID(channel_id), addresses[p1_index], p1_deposit) token_network.handle_channel_new_deposit_event( ChannelID(channel_id), addresses[p2_index], p2_deposit) token_network.handle_channel_balance_update_message( UpdatePFS( canonical_identifier=CanonicalIdentifier( chain_identifier=ChainID(1), channel_identifier=ChannelID(channel_id), token_network_address=TokenNetworkAddressBytes( decode_hex(token_network.address)), ), updating_participant=decode_hex(addresses[p1_index]), other_participant=decode_hex(addresses[p2_index]), updating_nonce=Nonce(1), other_nonce=Nonce(1), updating_capacity=p1_capacity, other_capacity=p2_capacity, reveal_timeout=p1_reveal_timeout, mediation_fee=FeeAmount(0), )) token_network.handle_channel_balance_update_message( UpdatePFS( canonical_identifier=CanonicalIdentifier( chain_identifier=ChainID(1), channel_identifier=ChannelID(channel_id), token_network_address=TokenNetworkAddressBytes( decode_hex(token_network.address)), ), updating_participant=decode_hex(addresses[p2_index]), other_participant=decode_hex(addresses[p1_index]), updating_nonce=Nonce(2), other_nonce=Nonce(1), updating_capacity=p2_capacity, other_capacity=p1_capacity, reveal_timeout=p2_reveal_timeout, mediation_fee=FeeAmount(0), ))
def handle_contract_send_channelunlock( raiden: 'RaidenService', channel_unlock_event: ContractSendChannelBatchUnlock, ): token_network_identifier = channel_unlock_event.token_network_identifier channel_identifier = channel_unlock_event.channel_identifier canonical_identifier = CanonicalIdentifier( chain_identifier=raiden.chain.network_id, token_network_address=token_network_identifier, channel_identifier=channel_identifier, ) participant = channel_unlock_event.participant token_address = channel_unlock_event.token_address payment_channel: PaymentChannel = raiden.chain.payment_channel( canonical_identifier=canonical_identifier, ) channel_state = get_channelstate_by_token_network_and_partner( chain_state=state_from_raiden(raiden), token_network_id=token_network_identifier, partner_address=participant, ) if not channel_state: # channel was cleaned up already due to an unlock raise RaidenUnrecoverableError( f'Failed to find channel state with partner ' f'{participant}, token_network:pex(token_network_identifier)', ) our_address = channel_state.our_state.address our_locksroot = channel_state.our_state.onchain_locksroot partner_address = channel_state.partner_state.address partner_locksroot = channel_state.partner_state.onchain_locksroot # we want to unlock because there are on-chain unlocked locks search_events = our_locksroot != EMPTY_HASH # we want to unlock, because there are unlocked/unclaimed locks search_state_changes = partner_locksroot != EMPTY_HASH if not search_events and not search_state_changes: # In the case that someone else sent the unlock we do nothing # Check https://github.com/raiden-network/raiden/issues/3152 # for more details log.warning( 'Onchain unlock already mined', token_address=token_address, channel_identifier=canonical_identifier.channel_identifier, participant=participant, ) return if search_state_changes: state_change_record = get_state_change_with_balance_proof_by_locksroot( storage=raiden.wal.storage, canonical_identifier=canonical_identifier, locksroot=partner_locksroot, sender=partner_address, ) state_change_identifier = state_change_record.state_change_identifier if not state_change_identifier: raise RaidenUnrecoverableError( f'Failed to find state that matches the current channel locksroots. ' f'chain_id:{raiden.chain.network_id} ' f'token:{to_checksum_address(token_address)} ' f'token_network:{to_checksum_address(token_network_identifier)} ' f'channel:{channel_identifier} ' f'participant:{to_checksum_address(participant)} ' f'our_locksroot:{to_hex(our_locksroot)} ' f'partner_locksroot:{to_hex(partner_locksroot)} ', ) restored_channel_state = channel_state_until_state_change( raiden=raiden, payment_network_identifier=raiden.default_registry.address, token_address=token_address, channel_identifier=channel_identifier, state_change_identifier=state_change_identifier, ) gain = get_batch_unlock_gain(restored_channel_state, ) skip_unlock = (restored_channel_state.partner_state.address == participant and gain.from_partner_locks == 0) if not skip_unlock: unlock( raiden=raiden, payment_channel=payment_channel, end_state=restored_channel_state.partner_state, participant=our_address, partner=partner_address, ) if search_events: event_record = get_event_with_balance_proof_by_locksroot( storage=raiden.wal.storage, canonical_identifier=canonical_identifier, locksroot=our_locksroot, recipient=partner_address, ) state_change_identifier = event_record.state_change_identifier if not state_change_identifier: raise RaidenUnrecoverableError( f'Failed to find event that match current channel locksroots. ' f'chain_id:{raiden.chain.network_id} ' f'token:{to_checksum_address(token_address)} ' f'token_network:{to_checksum_address(token_network_identifier)} ' f'channel:{channel_identifier} ' f'participant:{to_checksum_address(participant)} ' f'our_locksroot:{to_hex(our_locksroot)} ' f'partner_locksroot:{to_hex(partner_locksroot)} ', ) restored_channel_state = channel_state_until_state_change( raiden=raiden, payment_network_identifier=raiden.default_registry.address, token_address=token_address, channel_identifier=canonical_identifier.channel_identifier, state_change_identifier=state_change_identifier, ) gain = get_batch_unlock_gain(restored_channel_state, ) skip_unlock = (restored_channel_state.our_state.address == participant and gain.from_our_locks == 0) if not skip_unlock: unlock( raiden=raiden, payment_channel=payment_channel, end_state=restored_channel_state.our_state, participant=partner_address, partner=our_address, )
def handle_contract_send_channelsettle( raiden: 'RaidenService', channel_settle_event: ContractSendChannelSettle, ): canonical_identifier = CanonicalIdentifier( chain_identifier=raiden.chain.network_id, token_network_address=channel_settle_event. token_network_identifier, channel_identifier=channel_settle_event.channel_identifier, ) triggered_by_block_hash = channel_settle_event.triggered_by_block_hash payment_channel: PaymentChannel = raiden.chain.payment_channel( canonical_identifier=canonical_identifier, ) token_network_proxy: TokenNetwork = payment_channel.token_network if not token_network_proxy.client.can_query_state_for_block( triggered_by_block_hash): # The only time this can happen is during restarts after a long time # when the triggered block ends up getting pruned # In that case it's safe to just use the latest view of the chain to # query the on-chain participant/channel details triggered_by_block_hash = token_network_proxy.client.blockhash_from_blocknumber( 'latest', ) participants_details = token_network_proxy.detail_participants( participant1=payment_channel.participant1, participant2=payment_channel.participant2, block_identifier=triggered_by_block_hash, channel_identifier=channel_settle_event.channel_identifier, ) our_details = participants_details.our_details partner_details = participants_details.partner_details log_details = { 'chain_id': canonical_identifier.chain_identifier, 'token_network_identifier': canonical_identifier.token_network_address, 'channel_identifier': canonical_identifier.channel_identifier, 'node': pex(raiden.address), 'partner': to_checksum_address(partner_details.address), 'our_deposit': our_details.deposit, 'our_withdrawn': our_details.withdrawn, 'our_is_closer': our_details.is_closer, 'our_balance_hash': to_hex(our_details.balance_hash), 'our_nonce': our_details.nonce, 'our_locksroot': to_hex(our_details.locksroot), 'our_locked_amount': our_details.locked_amount, 'partner_deposit': partner_details.deposit, 'partner_withdrawn': partner_details.withdrawn, 'partner_is_closer': partner_details.is_closer, 'partner_balance_hash': to_hex(partner_details.balance_hash), 'partner_nonce': partner_details.nonce, 'partner_locksroot': to_hex(partner_details.locksroot), 'partner_locked_amount': partner_details.locked_amount, } if our_details.balance_hash != EMPTY_HASH: event_record = get_event_with_balance_proof_by_balance_hash( storage=raiden.wal.storage, canonical_identifier=canonical_identifier, balance_hash=our_details.balance_hash, ) if event_record.data is None: log.critical( 'our balance proof not found', **log_details, ) raise RaidenUnrecoverableError( 'Our balance proof could not be found in the database', ) our_balance_proof = event_record.data.balance_proof our_transferred_amount = our_balance_proof.transferred_amount our_locked_amount = our_balance_proof.locked_amount our_locksroot = our_balance_proof.locksroot else: our_transferred_amount = 0 our_locked_amount = 0 our_locksroot = EMPTY_HASH if partner_details.balance_hash != EMPTY_HASH: state_change_record = get_state_change_with_balance_proof_by_balance_hash( storage=raiden.wal.storage, canonical_identifier=canonical_identifier, balance_hash=partner_details.balance_hash, sender=participants_details.partner_details.address, ) if state_change_record.data is None: log.critical( 'partner balance proof not found', **log_details, ) raise RaidenUnrecoverableError( 'Partner balance proof could not be found in the database', ) partner_balance_proof = state_change_record.data.balance_proof partner_transferred_amount = partner_balance_proof.transferred_amount partner_locked_amount = partner_balance_proof.locked_amount partner_locksroot = partner_balance_proof.locksroot else: partner_transferred_amount = 0 partner_locked_amount = 0 partner_locksroot = EMPTY_HASH payment_channel.settle( transferred_amount=our_transferred_amount, locked_amount=our_locked_amount, locksroot=our_locksroot, partner_transferred_amount=partner_transferred_amount, partner_locked_amount=partner_locked_amount, partner_locksroot=partner_locksroot, block_identifier=triggered_by_block_hash, )