def handle_offchain_secretreveal_light( initiator_state: InitiatorTransferState, state_change: ReceiveSecretRevealLight, channel_state: NettingChannelState, pseudo_random_generator: random.Random ) -> TransitionResult[InitiatorTransferState]: """ Once the next hop proves it knows the secret, the initiator can unlock the mediated transfer. This will validate the secret, and if valid a new balance proof is sent to the next hop with the current lock removed from the merkle tree and the transferred amount updated. """ iteration: TransitionResult[InitiatorTransferState] valid_reveal = is_valid_secret_reveal( state_change=state_change, transfer_secrethash=initiator_state.transfer_description.secrethash, secret=state_change.secret, ) sent_by_partner = state_change.sender == channel_state.partner_state.address is_channel_open = channel.get_status(channel_state) == CHANNEL_STATE_OPENED if valid_reveal and is_channel_open and sent_by_partner: unlock_events = events_for_unlock_base( initiator_state=initiator_state, channel_state=channel_state, secret=state_change.secret, ) transfer_description = initiator_state.transfer_description message_identifier = message_identifier_from_prng(pseudo_random_generator) unlock_lock = channel.send_unlock( channel_state=channel_state, message_identifier=message_identifier, payment_identifier=transfer_description.payment_identifier, secret=state_change.secret, secrethash=state_change.secrethash, ) unlock_msg = Unlock.from_event(unlock_lock) store_received_secret_reveal_event = StoreMessageEvent(state_change.secret_reveal_message.message_identifier, transfer_description.payment_identifier, 9, state_change.secret_reveal_message, True) store_created_unlock_event = StoreMessageEvent(message_identifier, transfer_description.payment_identifier, 11, unlock_msg, False) events = list() events.append(store_received_secret_reveal_event) events.append(store_created_unlock_event) events.extend(unlock_events) iteration = TransitionResult(None, events) else: events = list() iteration = TransitionResult(initiator_state, events) return iteration
def run_test_receive_secrethashtransfer_unknown(raiden_network, token_addresses): app0 = raiden_network[0] 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, ) other_key = HOP1_KEY other_signer = LocalSigner(other_key) channel_identifier = make_channel_identifier() amount = 10 refund_transfer_message = make_refund_transfer( payment_identifier=1, nonce=1, token_network_address=token_network_identifier, token=token_address, channel_identifier=channel_identifier, transferred_amount=amount, recipient=app0.raiden.address, locksroot=UNIT_SECRETHASH, amount=amount, secrethash=UNIT_SECRETHASH, ) sign_and_inject(refund_transfer_message, other_signer, app0) unlock = Unlock( chain_id=UNIT_CHAIN_ID, message_identifier=random.randint(0, UINT64_MAX), payment_identifier=1, nonce=1, channel_identifier=channel_identifier, token_network_address=token_network_identifier, transferred_amount=amount, locked_amount=0, locksroot=UNIT_SECRETHASH, secret=UNIT_SECRET, ) sign_and_inject(unlock, other_signer, app0) secret_request_message = SecretRequest( message_identifier=random.randint(0, UINT64_MAX), payment_identifier=1, secrethash=UNIT_SECRETHASH, amount=1, expiration=refund_transfer_message.lock.expiration, ) sign_and_inject(secret_request_message, other_signer, app0) reveal_secret_message = RevealSecret( message_identifier=random.randint(0, UINT64_MAX), secret=UNIT_SECRET, ) sign_and_inject(reveal_secret_message, other_signer, app0)
def test_balance_proof_11(): dict_data = { "type": "Secret", "chain_id": 33, "message_identifier": 4334089825906208294, "payment_identifier": 15193824610622741555, "secret": "0x8c45240e576c4befd51d063549ce18859c5a2b3c356035884588a65c3dfcef4b", "nonce": 2, "token_network_address": "0x7351ed719de72db92a54c99ef2c4d287f69672a1", "channel_identifier": 1, "transferred_amount": 1000000000000000, "locked_amount": 0, "locksroot": "0x0000000000000000000000000000000000000000000000000000000000000000" } message = Unlock(chain_id=dict_data["chain_id"], message_identifier=dict_data["message_identifier"], payment_identifier=dict_data["payment_identifier"], secret=decode_hex(dict_data["secret"]), nonce=dict_data["nonce"], token_network_address=decode_hex( dict_data["token_network_address"]), channel_identifier=dict_data["channel_identifier"], transferred_amount=dict_data["transferred_amount"], locked_amount=dict_data["locked_amount"], locksroot=decode_hex(dict_data["locksroot"])) message.sign(signer) data_was_signed = message._data_to_sign() print("Balance Proof signature: " + message.signature.hex()) assert recover(data_was_signed, message.signature) == to_canonical_address( "0x7ca28d3d760b4aa2b79e8d42cbdc187c7df9af40")
def test_update_non_closing_balance_proof(): dict_data = { "type": "Secret", "chain_id": 33, "message_identifier": 4174357123961474742, "payment_identifier": 5100335212362582814, "secret": "0xd1b2cb5b175436f60b6e59be64f4c7b59b3569b8f877c55f66c8f8a6ba8055f4", "nonce": 2, "token_network_address": "0x013b47e5eb40a476dc0e9a212d376899288561a2", "channel_identifier": 14, "transferred_amount": 20000000, "locked_amount": 0, "locksroot": "0x0000000000000000000000000000000000000000000000000000000000000000", "signature": "0x94d6dba985096b6259151664367443bcd83c5e8cc1913c34bd3542b4ac1b4e7772696e145445625eef4167080fddb3ebe730c71319bee66235864661d9dddc2b1c" } # dict_data = {"type": "Secret", "chain_id": 33, "message_identifier": 18237677588114994956, "payment_identifier": 1322351847924173620, "secret": "0xa4678d1f1db376f20854619fc8aa8021f88f318e14ff600aa051e8e4ded5d023", "nonce": 2, "token_network_address": "0x7351ed719de72db92a54c99ef2c4d287f69672a1", "channel_identifier": 3, "transferred_amount": 100000000000000000, "locked_amount": 0, "locksroot": "0x0000000000000000000000000000000000000000000000000000000000000000", "signature": "0x5c805ba51ac4776d879c276d54c1ed97905399e227e7b9ef50aa4f36605ac25e5ab707641c4bd85a0d89549841beaf4f0e06c839ad5460aaf26d4c68b9af822c1b"} balance_proof_msg = Unlock.from_dict(dict_data) balance_proof = balanceproof_from_envelope(balance_proof_msg) non_closing_signature = create_balance_proof_update_signature( "0x013b47e5eb40a476dc0e9a212d376899288561a2", 14, balance_proof.balance_hash, 2, balance_proof.message_hash, decode_hex( "0x94d6dba985096b6259151664367443bcd83c5e8cc1913c34bd3542b4ac1b4e7772696e145445625eef4167080fddb3ebe730c71319bee66235864661d9dddc2b1c" )) our_signed_data = pack_balance_proof_update( nonce=balance_proof.nonce, balance_hash=balance_proof.balance_hash, additional_hash=balance_proof.message_hash, canonical_identifier=balance_proof.canonical_identifier, partner_signature=Signature( decode_hex( "0x94d6dba985096b6259151664367443bcd83c5e8cc1913c34bd3542b4ac1b4e7772696e145445625eef4167080fddb3ebe730c71319bee66235864661d9dddc2b1c" ))) print("Update non consling blanace proof signature " + non_closing_signature.hex()) our_recovered_address = recover(data=our_signed_data, signature=Signature(non_closing_signature)) assert our_recovered_address == to_canonical_address( "0x7ca28d3d760b4aa2b79e8d42cbdc187c7df9af40")
def get_latest_light_client_non_closing_balance_proof( cls, channel_id: int, storage: SerializedSQLiteStorage): latest_update_balance_proof_data = storage.get_latest_light_client_non_closing_balance_proof( channel_id) if latest_update_balance_proof_data: balance_proof = Unlock.from_dict( json.loads(latest_update_balance_proof_data[7])) return LightClientNonClosingBalanceProof( latest_update_balance_proof_data[1], latest_update_balance_proof_data[2], latest_update_balance_proof_data[3], latest_update_balance_proof_data[4], latest_update_balance_proof_data[5], latest_update_balance_proof_data[6], balance_proof, latest_update_balance_proof_data[8], latest_update_balance_proof_data[0]) return None
def message_from_sendevent(send_event: SendMessageEvent) -> Message: if type(send_event) == SendLockedTransfer: assert isinstance(send_event, SendLockedTransfer), MYPY_ANNOTATION message = LockedTransfer.from_event(send_event) elif type(send_event) == SendLockedTransferLight: assert isinstance(send_event, SendLockedTransferLight), MYPY_ANNOTATION message = send_event.signed_locked_transfer elif type(send_event) == SendSecretReveal: assert isinstance(send_event, SendSecretReveal), MYPY_ANNOTATION message = RevealSecret.from_event(send_event) elif type(send_event) == SendSecretRevealLight: assert isinstance(send_event, SendSecretRevealLight), MYPY_ANNOTATION message = send_event.signed_secret_reveal elif type(send_event) == SendBalanceProof: assert isinstance(send_event, SendBalanceProof), MYPY_ANNOTATION message = Unlock.from_event(send_event) elif type(send_event) == SendBalanceProofLight: assert isinstance(send_event, SendBalanceProofLight), MYPY_ANNOTATION message = send_event.signed_balance_proof elif type(send_event) == SendSecretRequest: assert isinstance(send_event, SendSecretRequest), MYPY_ANNOTATION message = SecretRequest.from_event(send_event) elif type(send_event) == SendSecretRequestLight: assert isinstance(send_event, SendSecretRequestLight), MYPY_ANNOTATION message = send_event.signed_secret_request elif type(send_event) == SendRefundTransfer: assert isinstance(send_event, SendRefundTransfer), MYPY_ANNOTATION message = RefundTransfer.from_event(send_event) elif type(send_event) == SendLockExpired: assert isinstance(send_event, SendLockExpired), MYPY_ANNOTATION message = LockExpired.from_event(send_event) elif type(send_event) == SendProcessed: assert isinstance(send_event, SendProcessed), MYPY_ANNOTATION message = Processed.from_event(send_event) else: raise ValueError(f"Unknown event type {send_event}") return message
def test_regression_multiple_revealsecret(raiden_network, token_addresses, transport_protocol): """ Multiple RevealSecret messages arriving at the same time must be handled properly. Unlock handling followed these steps: The Unlock message arrives The secret is registered The channel is updated and the correspoding lock is removed * A balance proof for the new channel state is created and sent to the payer The channel is unregistered for the given secrethash The step marked with an asterisk above introduced a context-switch. This allowed a second Reveal Unlock message to be handled before the channel was unregistered. And because the channel was already updated an exception was raised for an unknown secret. """ app0, app1 = raiden_network token = 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, ) channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier) payment_identifier = 1 secret = sha3(b'test_regression_multiple_revealsecret') secrethash = sha3(secret) expiration = app0.raiden.get_block_number() + 100 lock_amount = 10 lock = Lock( lock_amount, expiration, secrethash, ) nonce = 1 transferred_amount = 0 mediated_transfer = LockedTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=random.randint(0, UINT64_MAX), payment_identifier=payment_identifier, nonce=nonce, token_network_address=app0.raiden.default_registry.address, token=token, channel_identifier=channelstate_0_1.identifier, transferred_amount=transferred_amount, locked_amount=lock_amount, recipient=app1.raiden.address, locksroot=lock.secrethash, lock=lock, target=app1.raiden.address, initiator=app0.raiden.address, ) app0.raiden.sign(mediated_transfer) if transport_protocol is TransportProtocol.UDP: message_data = mediated_transfer.encode() host_port = None app1.raiden.transport.receive(message_data, host_port) elif transport_protocol is TransportProtocol.MATRIX: app1.raiden.transport._receive_message(mediated_transfer) else: raise TypeError('Unknown TransportProtocol') reveal_secret = RevealSecret( random.randint(0, UINT64_MAX), secret, ) app0.raiden.sign(reveal_secret) token_network_identifier = channelstate_0_1.token_network_identifier unlock = Unlock( chain_id=UNIT_CHAIN_ID, message_identifier=random.randint(0, UINT64_MAX), payment_identifier=payment_identifier, nonce=mediated_transfer.nonce + 1, token_network_address=token_network_identifier, channel_identifier=channelstate_0_1.identifier, transferred_amount=lock_amount, locked_amount=0, locksroot=EMPTY_MERKLE_ROOT, secret=secret, ) app0.raiden.sign(unlock) if transport_protocol is TransportProtocol.UDP: messages = [ unlock.encode(), reveal_secret.encode(), ] host_port = None receive_method = app1.raiden.transport.receive wait = [ gevent.spawn_later( .1, receive_method, data, host_port, ) for data in messages ] elif transport_protocol is TransportProtocol.MATRIX: messages = [ unlock, reveal_secret, ] receive_method = app1.raiden.transport._receive_message wait = [ gevent.spawn_later( .1, receive_method, data, ) for data in messages ] else: raise TypeError('Unknown TransportProtocol') gevent.joinall(wait)
def run_test_regression_multiple_revealsecret(raiden_network, token_addresses, transport_protocol): app0, app1 = raiden_network token = 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) channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier) payment_identifier = 1 secret = sha3(b"test_regression_multiple_revealsecret") secrethash = sha3(secret) expiration = app0.raiden.get_block_number() + 100 lock_amount = 10 lock = Lock(amount=lock_amount, expiration=expiration, secrethash=secrethash) nonce = 1 transferred_amount = 0 mediated_transfer = LockedTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=random.randint(0, UINT64_MAX), payment_identifier=payment_identifier, nonce=nonce, token_network_address=app0.raiden.default_registry.address, token=token, channel_identifier=channelstate_0_1.identifier, transferred_amount=transferred_amount, locked_amount=lock_amount, recipient=app1.raiden.address, locksroot=lock.secrethash, lock=lock, target=app1.raiden.address, initiator=app0.raiden.address, ) app0.raiden.sign(mediated_transfer) if transport_protocol is TransportProtocol.UDP: message_data = mediated_transfer.encode() host_port = None app1.raiden.transport.receive(message_data, host_port) elif transport_protocol is TransportProtocol.MATRIX: app1.raiden.transport._receive_message(mediated_transfer) else: raise TypeError("Unknown TransportProtocol") reveal_secret = RevealSecret(message_identifier=random.randint( 0, UINT64_MAX), secret=secret) app0.raiden.sign(reveal_secret) token_network_identifier = channelstate_0_1.token_network_identifier unlock = Unlock( chain_id=UNIT_CHAIN_ID, message_identifier=random.randint(0, UINT64_MAX), payment_identifier=payment_identifier, nonce=mediated_transfer.nonce + 1, token_network_address=token_network_identifier, channel_identifier=channelstate_0_1.identifier, transferred_amount=lock_amount, locked_amount=0, locksroot=EMPTY_MERKLE_ROOT, secret=secret, ) app0.raiden.sign(unlock) if transport_protocol is TransportProtocol.UDP: messages = [unlock.encode(), reveal_secret.encode()] host_port = None receive_method = app1.raiden.transport.receive wait = set( gevent.spawn_later(0.1, receive_method, data, host_port) for data in messages) elif transport_protocol is TransportProtocol.MATRIX: messages = [unlock, reveal_secret] receive_method = app1.raiden.transport._receive_message wait = set( gevent.spawn_later(0.1, receive_method, data) for data in messages) else: raise TypeError("Unknown TransportProtocol") gevent.joinall(wait)