def create_sendlockedtransfer(channel_state, initiator, target, amount, identifier, expiration, secrethash): our_state = channel_state.our_state partner_state = channel_state.partner_state our_balance_proof = our_state.balance_proof msg = 'caller must make sure there is enough balance' assert amount <= get_distributable(our_state, partner_state), msg msg = 'caller must make sure the channel is open' assert get_status(channel_state) == CHANNEL_STATE_OPENED, msg lock = HashTimeLockState( amount, expiration, secrethash, ) merkletree = compute_merkletree_with( channel_state.our_state.merkletree, lock.lockhash, ) # The caller must ensure the same lock is not being used twice assert merkletree, 'lock is already registered' locksroot = merkleroot(merkletree) if our_balance_proof: transferred_amount = our_balance_proof.transferred_amount else: transferred_amount = 0 token = channel_state.token_address nonce = get_next_nonce(channel_state.our_state) recipient = channel_state.partner_state.address balance_proof = BalanceProofUnsignedState( nonce, transferred_amount, locksroot, channel_state.identifier, ) locked_transfer = LockedTransferUnsignedState( identifier, token, balance_proof, lock, initiator, target, ) lockedtransfer = SendLockedTransfer( locked_transfer, recipient, ) return lockedtransfer, merkletree
def test_get_event_with_balance_proof(): """ All events which contain a balance proof must be found by when querying the database. """ serializer = JSONSerializer storage = SQLiteStorage(':memory:', serializer) counter = itertools.count() lock_expired = SendLockExpired( recipient=factories.make_address(), message_identifier=next(counter), balance_proof=make_balance_proof_from_counter(counter), secrethash=sha3(factories.make_secret(next(counter))), ) locked_transfer = SendLockedTransfer( recipient=factories.make_address(), channel_identifier=factories.make_channel_identifier(), message_identifier=next(counter), transfer=make_transfer_from_counter(counter), ) balance_proof = SendBalanceProof( recipient=factories.make_address(), channel_identifier=factories.make_channel_identifier(), message_identifier=next(counter), payment_identifier=next(counter), token_address=factories.make_address(), secret=factories.make_secret(next(counter)), balance_proof=make_balance_proof_from_counter(counter), ) refund_transfer = SendRefundTransfer( recipient=factories.make_address(), channel_identifier=factories.make_channel_identifier(), message_identifier=next(counter), transfer=make_transfer_from_counter(counter), ) events_balanceproofs = [ (lock_expired, lock_expired.balance_proof), (locked_transfer, locked_transfer.balance_proof), (balance_proof, balance_proof.balance_proof), (refund_transfer, refund_transfer.transfer.balance_proof), ] timestamp = datetime.utcnow().isoformat(timespec='milliseconds') state_change = '' for event, _ in events_balanceproofs: state_change_identifier = storage.write_state_change( state_change, timestamp, ) storage.write_events( state_change_identifier=state_change_identifier, events=[event], log_time=timestamp, ) for event, balance_proof in events_balanceproofs: event_record = get_event_with_balance_proof( storage=storage, chain_id=balance_proof.chain_id, token_network_identifier=balance_proof.token_network_identifier, channel_identifier=balance_proof.channel_identifier, balance_hash=balance_proof.balance_hash, ) assert event_record.data == event
def create_sendlockedtransfer( channel_state: NettingChannelState, initiator: typing.InitiatorAddress, target: typing.TargetAddress, amount: typing.PaymentAmount, message_identifier: typing.MessageID, payment_identifier: typing.PaymentID, expiration: typing.BlockExpiration, secrethash: typing.SecretHash, ) -> SendLockedTransfer: our_state = channel_state.our_state partner_state = channel_state.partner_state our_balance_proof = our_state.balance_proof msg = 'caller must make sure there is enough balance' assert amount <= get_distributable(our_state, partner_state), msg msg = 'caller must make sure the channel is open' assert get_status(channel_state) == CHANNEL_STATE_OPENED, msg lock = HashTimeLockState( amount, expiration, secrethash, ) merkletree = compute_merkletree_with( channel_state.our_state.merkletree, lock.lockhash, ) # The caller must ensure the same lock is not being used twice assert merkletree, 'lock is already registered' locksroot = merkleroot(merkletree) if our_balance_proof: transferred_amount = our_balance_proof.transferred_amount else: transferred_amount = 0 token = channel_state.token_address nonce = get_next_nonce(channel_state.our_state) recipient = channel_state.partner_state.address locked_amount = get_amount_locked( our_state) + amount # the new lock is not registered yet balance_proof = BalanceProofUnsignedState( nonce, transferred_amount, locked_amount, locksroot, channel_state.token_network_identifier, channel_state.identifier, ) locked_transfer = LockedTransferUnsignedState( payment_identifier, token, balance_proof, lock, initiator, target, ) queue_name = channel_state.identifier lockedtransfer = SendLockedTransfer( recipient, queue_name, message_identifier, locked_transfer, ) return lockedtransfer, merkletree
def test_get_event_with_balance_proof(): """ All events which contain a balance proof must be found by when querying the database. """ serializer = JSONSerializer() storage = SerializedSQLiteStorage(":memory:", serializer) counter = itertools.count(1) partner_address = factories.make_address() balance_proof = make_balance_proof_from_counter(counter) lock_expired = SendLockExpired( recipient=partner_address, message_identifier=MessageID(next(counter)), balance_proof=balance_proof, secrethash=factories.make_secret_hash(next(counter)), canonical_identifier=balance_proof.canonical_identifier, ) locked_transfer = SendLockedTransfer( recipient=partner_address, message_identifier=MessageID(next(counter)), transfer=make_transfer_from_counter(counter), canonical_identifier=factories.make_canonical_identifier(), ) send_balance_proof = SendBalanceProof( recipient=partner_address, message_identifier=MessageID(next(counter)), payment_identifier=factories.make_payment_id(), token_address=factories.make_token_address(), secret=factories.make_secret(next(counter)), balance_proof=make_balance_proof_from_counter(counter), canonical_identifier=factories.make_canonical_identifier(), ) refund_transfer = SendRefundTransfer( recipient=partner_address, message_identifier=MessageID(next(counter)), transfer=make_transfer_from_counter(counter), canonical_identifier=factories.make_canonical_identifier(), ) events_balanceproofs = [ (lock_expired, lock_expired.balance_proof), (locked_transfer, locked_transfer.balance_proof), (send_balance_proof, send_balance_proof.balance_proof), (refund_transfer, refund_transfer.transfer.balance_proof), ] state_change = Block(BlockNumber(1), BlockGasLimit(1), factories.make_block_hash()) for event, _ in events_balanceproofs: state_change_identifiers = storage.write_state_changes([state_change]) storage.write_events(events=[(state_change_identifiers[0], event)]) for event, balance_proof in events_balanceproofs: event_record = get_event_with_balance_proof_by_balance_hash( storage=storage, canonical_identifier=balance_proof.canonical_identifier, balance_hash=balance_proof.balance_hash, recipient=partner_address, ) assert event_record assert event_record.data == event event_record = get_event_with_balance_proof_by_locksroot( storage=storage, canonical_identifier=balance_proof.canonical_identifier, recipient=event.recipient, locksroot=balance_proof.locksroot, ) assert event_record assert event_record.data == event # Checking that balance proof attribute can be accessed for all events. # Issue https://github.com/raiden-network/raiden/issues/3179 assert event_record.data.balance_proof == event.balance_proof storage.close()
def test_pfs_global_messages( matrix_transports, monkeypatch, ): """ Test that `update_pfs` from `RaidenEventHandler` sends balance proof updates to the global PATH_FINDING_BROADCASTING_ROOM room on Send($BalanceProof)* events, i.e. events, that send a new balance proof to the channel partner. """ transport = matrix_transports[0] transport._client.api.retry_timeout = 0 transport._send_raw = MagicMock() raiden_service = MockRaidenService(None) transport.start( raiden_service, raiden_service.message_handler, None, ) pfs_room_name = make_room_alias(transport.network_id, PATH_FINDING_BROADCASTING_ROOM) pfs_room = transport._global_rooms.get(pfs_room_name) assert isinstance(pfs_room, Room) pfs_room.send_text = MagicMock(spec=pfs_room.send_text) raiden_service.transport = transport transport.log = MagicMock() # create mock events that should trigger a send lock = make_lock() hash_time_lock = HashTimeLockState(lock.amount, lock.expiration, lock.secrethash) def make_unsigned_balance_proof(nonce): return BalanceProofUnsignedState.from_dict( make_balance_proof(nonce=nonce, signer=LocalSigner(HOP1_KEY), amount=1).to_dict(), ) transfer1 = LockedTransferUnsignedState( balance_proof=make_unsigned_balance_proof(nonce=1), payment_identifier=1, token=b'1', lock=hash_time_lock, target=HOP1, initiator=HOP1, ) transfer2 = LockedTransferUnsignedState( balance_proof=make_unsigned_balance_proof(nonce=2), payment_identifier=1, token=b'1', lock=hash_time_lock, target=HOP1, initiator=HOP1, ) send_balance_proof_events = [ SendLockedTransfer(HOP1, 1, 1, transfer1), SendRefundTransfer(HOP1, 1, 1, transfer2), SendBalanceProof(HOP1, 1, 1, 1, b'1', b'x' * 32, make_unsigned_balance_proof(nonce=3)), SendLockExpired(HOP1, 1, make_unsigned_balance_proof(nonce=4), b'x' * 32), ] for num, event in enumerate(send_balance_proof_events): assert event.balance_proof.nonce == num + 1 # make sure we cover all configured event types assert all(event in [type(event) for event in send_balance_proof_events] for event in SEND_BALANCE_PROOF_EVENTS) event_handler = raiden_event_handler.RaidenEventHandler() # let our mock objects pass validation channelstate_mock = Mock() channelstate_mock.reveal_timeout = 1 monkeypatch.setattr( raiden_event_handler, 'get_channelstate_by_token_network_and_partner', lambda *args, **kwargs: channelstate_mock, ) monkeypatch.setattr(raiden_event_handler, 'state_from_raiden', lambda *args, **kwargs: 1) monkeypatch.setattr(event_handler, 'handle_send_lockedtransfer', lambda *args, **kwargs: 1) monkeypatch.setattr(event_handler, 'handle_send_refundtransfer', lambda *args, **kwargs: 1) # handle the events for event in send_balance_proof_events: event_handler.on_raiden_event( raiden_service, event, ) gevent.idle() # ensure all events triggered a send for their respective balance_proof # matrix transport may concatenate multiple messages send in one interval assert pfs_room.send_text.call_count >= 1 concatenated_call_args = ' '.join( str(arg) for arg in pfs_room.send_text.call_args_list) assert all(f'"nonce": {i + 1}' in concatenated_call_args for i in range(len(SEND_BALANCE_PROOF_EVENTS))) transport.stop() transport.get()
def test_get_event_with_balance_proof(): """ All events which contain a balance proof must be found by when querying the database. """ serializer = JSONSerializer storage = SerializedSQLiteStorage(":memory:", serializer) counter = itertools.count() lock_expired = SendLockExpired( recipient=factories.make_address(), message_identifier=next(counter), balance_proof=make_balance_proof_from_counter(counter), secrethash=sha3(factories.make_secret(next(counter))), ) locked_transfer = SendLockedTransfer( recipient=factories.make_address(), channel_identifier=factories.make_channel_identifier(), message_identifier=next(counter), transfer=make_transfer_from_counter(counter), ) balance_proof = SendBalanceProof( recipient=factories.make_address(), channel_identifier=factories.make_channel_identifier(), message_identifier=next(counter), payment_identifier=next(counter), token_address=factories.make_address(), secret=factories.make_secret(next(counter)), balance_proof=make_balance_proof_from_counter(counter), ) refund_transfer = SendRefundTransfer( recipient=factories.make_address(), channel_identifier=factories.make_channel_identifier(), message_identifier=next(counter), transfer=make_transfer_from_counter(counter), ) events_balanceproofs = [ (lock_expired, lock_expired.balance_proof), (locked_transfer, locked_transfer.balance_proof), (balance_proof, balance_proof.balance_proof), (refund_transfer, refund_transfer.transfer.balance_proof), ] timestamp = datetime.utcnow().isoformat(timespec="milliseconds") state_change = "" for event, _ in events_balanceproofs: state_change_identifier = storage.write_state_change( state_change, timestamp) storage.write_events(state_change_identifier=state_change_identifier, events=[event], log_time=timestamp) for event, balance_proof in events_balanceproofs: event_record = get_event_with_balance_proof_by_balance_hash( storage=storage, canonical_identifier=balance_proof.canonical_identifier, balance_hash=balance_proof.balance_hash, ) assert event_record.data == event # Checking that balance proof attribute can be accessed for all events. # Issue https://github.com/raiden-network/raiden/issues/3179 assert event_record.data.balance_proof == event.balance_proof