def test_event_operators(): a = EventPaymentSentSuccess(1, 4, 2, 5, sha3(b"target"), b"0", []) b = EventPaymentSentSuccess(1, 4, 2, 5, sha3(b"target"), b"0", []) c = EventPaymentSentSuccess(2, 7, 3, 4, sha3(b"target"), b"0", []) d = EventPaymentSentSuccess(2, 7, 3, 4, sha3(b"differenttarget"), b"0", []) # pylint: disable=unneeded-not assert a == b assert not a != b assert a != c assert not a == c assert not c == d a = EventPaymentSentFailed(1, 7, 2, "target", "BECAUSE") b = EventPaymentSentFailed(1, 7, 2, "target", "BECAUSE") c = EventPaymentSentFailed(3, 3, 3, "target", "UNKNOWN") assert a == b assert not a != b assert a != c assert not a == c a = EventPaymentReceivedSuccess(4, 4, 2, 5, sha3(b"initiator")) b = EventPaymentReceivedSuccess(4, 4, 2, 5, sha3(b"initiator")) c = EventPaymentReceivedSuccess(1, 2, 3, 5, sha3(b"initiator")) d = EventPaymentReceivedSuccess(1, 2, 3, 5, sha3(b"other initiator")) assert a == b assert not a != b assert a != c assert not a == c assert c != d assert not c == d
def make_signed_transfer_from_counter(counter): lock = Lock( amount=next(counter), expiration=next(counter), secrethash=factories.make_secret_hash(next(counter)), ) signed_transfer = factories.create( factories.LockedTransferSignedStateProperties( amount=next(counter), initiator=factories.make_initiator_address(), target=factories.make_target_address(), expiration=next(counter), secret=factories.make_secret(next(counter)), payment_identifier=next(counter), token=factories.make_token_address(), nonce=next(counter), transferred_amount=next(counter), locked_amount=next(counter), locksroot=sha3(lock.as_bytes), canonical_identifier=factories.make_canonical_identifier( token_network_address=factories.make_address(), channel_identifier=next(counter)), recipient=factories.make_address(), sender=factories.HOP1, pkey=factories.HOP1_KEY, )) return signed_transfer
def test_privatekey_to_publickey(): privkey = sha3(b"secret") pubkey = ( "c283b0507c4ec6903a49fac84a5aead951f3c38b2c72b69da8a70a5bac91e9c" "705f70c7554b26e82b90d2d1bbbaf711b10c6c8b807077f4070200a8fb4c6b771") assert pubkey == privatekey_to_publickey(privkey).hex()
def make_from_route_from_counter(counter): from_channel = factories.create( factories.NettingChannelStateProperties( canonical_identifier=factories.make_canonical_identifier(), token_address=factories.make_token_address(), partner_state=factories.NettingChannelEndStateProperties( balance=next(counter), address=factories.HOP1), )) from_hop = factories.make_hop_from_channel(from_channel) expiration = BlockExpiration(factories.UNIT_REVEAL_TIMEOUT + 1) from_transfer = factories.make_signed_transfer_for( from_channel, factories.LockedTransferSignedStateProperties( transferred_amount=TokenAmount(0), canonical_identifier=factories.make_canonical_identifier( token_network_address=from_channel.token_network_address), amount=TokenAmount(1), expiration=expiration, secret=sha3(factories.make_secret(next(counter))), initiator=factories.make_initiator_address(), target=factories.make_target_address(), payment_identifier=next(counter), sender=factories.HOP1, pkey=factories.HOP1_KEY, ), ) return from_hop, from_transfer
def blockchain_private_keys(blockchain_number_of_nodes, blockchain_key_seed): """ The private keys for the each private chain node, not the same as the raiden's private key. """ return [ sha3(blockchain_key_seed.format(position).encode()) for position in range(blockchain_number_of_nodes) ]
def random_payment_hash_invoice() -> PaymentHashInvoice: """ Return a random 32 byte secret except the 0 secret since it's not accepted in the contracts """ while True: secret = os.urandom(constants.SECRETHASH_LENGTH) if secret != constants.EMPTY_HASH: secret = Secret(secret) return sha3(secret)
def message_hash(self) -> bytes: return sha3( pack_data( (self.cmdid.value, "uint8"), (self.message_identifier, "uint64"), (self.recipient, "address"), (self.secrethash, "bytes32"), ))
def message_hash(self) -> bytes: return sha3( pack_data( (self.cmdid.value, "uint8"), (self.message_identifier, "uint64"), (self.payment_identifier, "uint64"), (self.secret, "bytes32"), ))
def test_channel_withdraw(raiden_network, number_of_nodes, token_addresses, deposit, network_wait, retry_timeout): """ Withdraw funds after a mediated transfer.""" alice_app, bob_app = raiden_network token_address = token_addresses[0] token_network_address = views.get_token_network_address_by_token_address( views.state_from_app(alice_app), alice_app.raiden.default_registry.address, token_address) assert token_network_address token_proxy = bob_app.raiden.proxy_manager.token(token_address) bob_initial_balance = token_proxy.balance_of(bob_app.raiden.address) message_handler = WaitForMessage() bob_app.raiden.message_handler = message_handler alice_to_bob_amount = 10 identifier = 1 target = bob_app.raiden.address secret = sha3(target) payment_status = alice_app.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=alice_to_bob_amount, target=target, identifier=identifier, secret=secret, ) wait_for_unlock = bob_app.raiden.message_handler.wait_for_message( Unlock, {"payment_identifier": identifier}) timeout = network_wait * number_of_nodes with Timeout(seconds=timeout): wait_for_unlock.get() msg = ( f"transfer from {to_checksum_address(alice_app.raiden.address)} " f"to {to_checksum_address(bob_app.raiden.address)} failed.") assert payment_status.payment_done.get(), msg total_withdraw = deposit + alice_to_bob_amount bob_alice_channel_state = get_channelstate(bob_app, alice_app, token_network_address) bob_app.raiden.withdraw( canonical_identifier=bob_alice_channel_state.canonical_identifier, total_withdraw=total_withdraw, ) waiting.wait_for_withdraw_complete( raiden=bob_app.raiden, canonical_identifier=bob_alice_channel_state.canonical_identifier, total_withdraw=total_withdraw, retry_timeout=retry_timeout, ) bob_balance_after_withdraw = token_proxy.balance_of(bob_app.raiden.address) assert bob_initial_balance + total_withdraw == bob_balance_after_withdraw
def test_automatic_secret_registration(raiden_chain, token_addresses): app0, app1 = raiden_chain token_address = token_addresses[0] token_network_address = views.get_token_network_address_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address) hold_event_handler = app1.raiden.raiden_event_handler amount = 100 identifier = 1 message_handler = WaitForMessage() app1.raiden.message_handler = message_handler target = app1.raiden.address secret = Secret(sha3(target)) secrethash = sha256_secrethash(secret) hold_event_handler.hold_secretrequest_for(secrethash=secrethash) locked_transfer_received = message_handler.wait_for_message( LockedTransfer, {}) app0.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=amount, target=target, identifier=identifier, secret=secret, ) # Wait for app1 to receive the locked transfer. locked_transfer_received.wait() # Stop app0 to avoid sending the unlock, this must be done after the locked # transfer is sent. app0.raiden.transport.stop() reveal_secret = RevealSecret( message_identifier=MessageID(random.randint(0, UINT64_MAX)), secret=secret, signature=EMPTY_SIGNATURE, ) app0.raiden.sign(reveal_secret) message_handler.on_messages(app1.raiden, [reveal_secret]) chain_state = views.state_from_app(app1) secrethash = sha256_secrethash(secret) target_task = chain_state.payment_mapping.secrethashes_to_task[secrethash] lock_expiration = target_task.target_state.transfer.lock.expiration # type: ignore app1.raiden.proxy_manager.client.wait_until_block( target_block_number=lock_expiration) assert app1.raiden.default_secret_registry.is_secret_registered( secrethash=secrethash, block_identifier="latest")
def test_signer_sign(): privkey = sha3(b"secret") # 0x38e959391dD8598aE80d5d6D114a7822A09d313A message = b"message" # generated with Metamask's web3.personal.sign signature = decode_hex( "0x1eff8317c59ab169037f5063a5129bb1bab0299fef0b5621d866b07be59e2c0a" "6a404e88d3360fb58bd13daf577807c2cf9b6b26d80fc929c52e952769a460981c") signer: Signer = LocalSigner(privkey) assert signer.sign(message) == signature
def make_balance_proof_from_counter(counter) -> BalanceProofUnsignedState: return BalanceProofUnsignedState( nonce=next(counter), transferred_amount=next(counter), locked_amount=next(counter), locksroot=Locksroot(sha3(next(counter).to_bytes(1, "big"))), canonical_identifier=factories.make_canonical_identifier( chain_identifier=next(counter), token_network_address=factories.make_address(), channel_identifier=next(counter), ), )
def make_signed_balance_proof_from_counter(counter): lock = Lock( amount=next(counter), expiration=next(counter), secrethash=factories.make_secret_hash(next(counter)), ) lock_expired_balance_proof = factories.create( factories.BalanceProofSignedStateProperties( nonce=next(counter), transferred_amount=next(counter), locked_amount=next(counter), canonical_identifier=factories.make_canonical_identifier( token_network_address=factories.make_address(), channel_identifier=next(counter)), locksroot=Locksroot(sha3(lock.as_bytes)), message_hash=AdditionalHash(sha3(b"")), sender=factories.HOP1, pkey=factories.HOP1_KEY, )) return lock_expired_balance_proof
def private_keys(number_of_nodes, privatekey_seed): """ Private keys for each raiden node. """ # Note: The fixtures depend on the order of the private keys result = [ sha3(privatekey_seed.format(position).encode()) for position in range(number_of_nodes) ] # this must not happen, otherwise the keys and addresses will be equal! assert len(set( result)) == number_of_nodes, "`privatekey_seed` generate repeated keys" return result
def test_get_secret(): secret1 = factories.make_secret() secret2 = factories.make_secret() secrethash3 = factories.make_keccak_hash() secrethash4 = factories.make_keccak_hash() lock_state = HashTimeLockState(amount=10, expiration=10, secrethash=factories.UNIT_SECRETHASH) end_state = factories.create(factories.NettingChannelEndStateProperties()) end_state = factories.replace( end_state, secrethashes_to_lockedlocks={secrethash3: lock_state}, secrethashes_to_unlockedlocks={ sha3(secret1): UnlockPartialProofState(lock=lock_state, secret=secret1) }, secrethashes_to_onchain_unlockedlocks={ sha3(secret2): UnlockPartialProofState(lock=lock_state, secret=secret2) }, ) assert get_secret(end_state, sha3(secret1)) == secret1 # known secret from offchain unlock assert get_secret(end_state, sha3(secret2)) == secret2 # known secret from offchain unlock assert get_secret(end_state, secrethash3) is None # known lock but not unlocked yet assert get_secret(end_state, secrethash4) is None # unknown secrethash
def test_regression_register_secret_once(secret_registry_address, proxy_manager): """Register secret transaction must not be sent if the secret is already registered""" # pylint: disable=protected-access secret_registry = proxy_manager.secret_registry(secret_registry_address) secret = sha3(b"test_regression_register_secret_once") secret_registry.register_secret(secret=secret) previous_nonce = proxy_manager.client._available_nonce secret_registry.register_secret(secret=secret) assert previous_nonce == proxy_manager.client._available_nonce previous_nonce = proxy_manager.client._available_nonce secret_registry.register_secret_batch(secrets=[secret]) assert previous_nonce == proxy_manager.client._available_nonce
def main() -> None: tmpdir = tempfile.mkdtemp() geth_nodes = [] for i in range(NUM_GETH_NODES): is_miner = i == 0 node_key = PrivateKey(sha3(f"node:{i}".encode())) p2p_port = Port(START_PORT + i) rpc_port = Port(START_RPCPORT + i) description = EthNodeDescription( private_key=node_key, rpc_port=rpc_port, p2p_port=p2p_port, miner=is_miner, extra_config={}, ) geth_nodes.append(description) rpc_endpoint = f"http://127.0.0.1:{START_RPCPORT}" web3 = Web3(HTTPProvider(rpc_endpoint)) random_marker = remove_0x_prefix(hex(random.getrandbits(100))) genesis_description = GenesisDescription( prefunded_accounts=DEFAULT_ACCOUNTS, random_marker=random_marker, chain_id=ChainID(NETWORKNAME_TO_ID["smoketest"]), ) private_chain: ContextManager[ List[JSONRPCExecutor]] = run_private_blockchain( web3=web3, eth_nodes=geth_nodes, base_datadir=tmpdir, log_dir=tmpdir, verbosity="info", genesis_description=genesis_description, ) with private_chain: from IPython import embed embed()
def _channel_and_transfer(num_pending_locks): our_model, _ = create_model(700) partner_model, privkey = create_model(700, num_pending_locks) reverse_channel_state = create_channel_from_models(partner_model, our_model, privkey) lock_secret = sha3(b"some secret seed") lock = HashTimeLockState(30, 10, sha256(lock_secret).digest()) mediated_transfer = make_receive_transfer_mediated( reverse_channel_state, privkey, nonce=partner_model.next_nonce, transferred_amount=0, lock=lock, pending_locks=PendingLocksState(partner_model.pending_locks + [bytes(lock.encoded)]), locked_amount=lock.amount, ) channel_state = deepcopy(reverse_channel_state) channel_state.our_state = reverse_channel_state.partner_state channel_state.partner_state = reverse_channel_state.our_state return channel_state, mediated_transfer
def test_start_end_attack(token_addresses, raiden_chain, deposit): """ An attacker can try to steal tokens from a hub or the last node in a path. The attacker needs to use two addresses (A1 and A2) and connect both to the hub H. Once connected a mediated transfer is initialized from A1 to A2 through H. Once the node A2 receives the mediated transfer the attacker uses the known secret and reveal to close and settle the channel H-A2, without revealing the secret to H's raiden node. The intention is to make the hub transfer the token but for him to be unable to require the token A1.""" amount = 30 token = token_addresses[0] app0, app1, app2 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking token_network_address = views.get_token_network_address_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token) assert token_network_address hold_event_handler = app2.raiden.raiden_event_handler # the attacker owns app0 and app2 and creates a transfer through app1 identifier = 1 target = app2.raiden.address secret = Secret(sha3(target)) secrethash = sha256_secrethash(secret) hold_event_handler.hold_secretrequest_for(secrethash=secrethash) app0.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=amount, target=target, identifier=identifier, secret=secret, ) attack_channel = get_channelstate(app2, app1, token_network_address) attack_transfer = None # TODO attack_contract = attack_channel.external_state.netting_channel.address # type: ignore hub_contract = get_channelstate( # type: ignore app1, app0, token_network_address).external_state.netting_channel.address # start the settle counter attack_balance_proof = attack_transfer.to_balanceproof() # type: ignore attack_channel.netting_channel.channel_close( attack_balance_proof) # type: ignore # wait until the last block to reveal the secret, hopefully we are not # missing a block during the test assert attack_transfer app2.raiden.rpc_client.wait_until_block( target_block_number=attack_transfer.lock.expiration - 1) # since the attacker knows the secret he can net the lock # <the commented code below is left for documentation purposes> # attack_channel.netting_channel.unlock( # UnlockProofState(unlock_proof, attack_transfer.lock, secret) # ) # XXX: verify that the secret was publicized # at this point the hub might not know the secret yet, and won't be able to # claim the token from the channel A1 - H # the attacker settles the contract app2.raiden.rpc_client.wait_until_block( target_block_number=app2.raiden.rpc_client.block_number() + 1) attack_channel.netting_channel.settle(token, attack_contract) # at this point the attacker has the "stolen" funds attack_contract = app2.raiden.proxy_manager.token_hashchannel[token][ attack_contract] assert attack_contract.participants[ app2.raiden.address]["netted"] == deposit + amount assert attack_contract.participants[ app1.raiden.address]["netted"] == deposit - amount # and the hub's channel A1-H doesn't hub_contract = app1.raiden.proxy_manager.token_hashchannel[token][ hub_contract] assert hub_contract.participants[app0.raiden.address]["netted"] == deposit assert hub_contract.participants[app1.raiden.address]["netted"] == deposit # to mitigate the attack the Hub _needs_ to use a lower expiration for the # locked transfer between H-A2 than A1-H. For A2 to acquire the token # it needs to make the secret public in the blockchain so it publishes the # secret through an event and the Hub is able to require its funds app1.raiden.rpc_client.wait_until_block( target_block_number=app1.raiden.rpc_client.block_number() + 1) # XXX: verify that the Hub has found the secret, close and settle the channel # the hub has acquired its token hub_contract = app1.raiden.proxy_manager.token_hashchannel[token][ hub_contract] assert hub_contract.participants[ app0.raiden.address]["netted"] == deposit + amount assert hub_contract.participants[ app1.raiden.address]["netted"] == deposit - amount
def hash(self) -> bytes: return sha3(rlp.encode(self.route))
def test_multiple_channel_states(chain_state, token_network_state, channel_properties): open_block_number = 10 open_block_hash = factories.make_block_hash() pseudo_random_generator = random.Random() properties, pkey = channel_properties channel_state = factories.create(properties) channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state, block_number=open_block_number, block_hash=open_block_hash, ) channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change, block_number=open_block_number, block_hash=open_block_hash, pseudo_random_generator=pseudo_random_generator, ) lock_amount = 30 lock_expiration = 20 lock_secret = sha3(b"test_end_state") lock_secrethash = sha256(lock_secret).digest() lock = HashTimeLockState(lock_amount, lock_expiration, lock_secrethash) mediated_transfer = make_receive_transfer_mediated( channel_state=channel_state, privkey=pkey, nonce=1, transferred_amount=0, lock=lock) from_hop = factories.make_hop_from_channel(channel_state) init_target = ActionInitTarget( from_hop=from_hop, transfer=mediated_transfer, balance_proof=mediated_transfer.balance_proof, sender=mediated_transfer.balance_proof.sender, # pylint: disable=no-member ) node.state_transition(chain_state, init_target) closed_block_number = open_block_number + 10 closed_block_hash = factories.make_block_hash() channel_close_state_change = ContractReceiveChannelClosed( transaction_hash=factories.make_transaction_hash(), transaction_from=channel_state.partner_state.address, canonical_identifier=channel_state.canonical_identifier, block_number=closed_block_number, block_hash=closed_block_hash, ) channel_closed_iteration = token_network.state_transition( token_network_state=channel_new_iteration.new_state, state_change=channel_close_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) settle_block_number = closed_block_number + channel_state.settle_timeout + 1 channel_settled_state_change = ContractReceiveChannelSettled( transaction_hash=factories.make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, block_number=settle_block_number, block_hash=factories.make_block_hash(), our_onchain_locksroot=factories.make_32bytes(), partner_onchain_locksroot=LOCKSROOT_OF_NO_LOCKS, ) channel_settled_iteration = token_network.state_transition( token_network_state=channel_closed_iteration.new_state, state_change=channel_settled_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) token_network_state_after_settle = channel_settled_iteration.new_state ids_to_channels = token_network_state_after_settle.channelidentifiers_to_channels assert len(ids_to_channels) == 1 assert channel_state.identifier in ids_to_channels # Create new channel while the previous one is pending unlock new_channel_properties = factories.create_properties( factories.NettingChannelStateProperties( canonical_identifier=factories.make_canonical_identifier()), defaults=properties, ) new_channel_state = factories.create(new_channel_properties) channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=new_channel_state, block_number=closed_block_number + 1, block_hash=factories.make_block_hash(), ) channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change, block_number=open_block_number, block_hash=open_block_hash, pseudo_random_generator=pseudo_random_generator, ) token_network_state_after_new_open = channel_new_iteration.new_state ids_to_channels = token_network_state_after_new_open.channelidentifiers_to_channels assert len(ids_to_channels) == 2 assert channel_state.identifier in ids_to_channels
def publickey_to_address(publickey: bytes) -> typing.Address: return typing.Address(sha3(publickey[1:])[12:])
def publickey_to_address(publickey: bytes) -> typing.Address: return typing.Address(sha3(publickey[1:])[12:])
from raiden.constants import EMPTY_SIGNATURE from raiden.messages.synchronization import Processed from raiden.tests.utils import factories from raiden.transfer.events import ( EventPaymentReceivedSuccess, EventPaymentSentFailed, EventPaymentSentSuccess, ) from raiden.transfer.state_change import ActionCancelPayment, Block from raiden.utils.signing import sha3 ADDRESS = sha3(b"foo")[:20] SECRET = b"secret" def test_transfer_statechange_operators(): # pylint: disable=unneeded-not block_hash = factories.make_transaction_hash() a = Block(block_number=2, gas_limit=1, block_hash=block_hash) b = Block(block_number=2, gas_limit=1, block_hash=block_hash) c = Block(block_number=3, gas_limit=1, block_hash=factories.make_transaction_hash()) assert a == b assert not a != b assert a != c assert not a == c a = ActionCancelPayment(2) b = ActionCancelPayment(2)
def test_get_state_change_with_balance_proof(): """ All state changes which contain a balance proof must be found when querying the database. """ serializer = JSONSerializer() storage = SerializedSQLiteStorage(":memory:", serializer) counter = itertools.count() balance_proof = make_signed_balance_proof_from_counter(counter) lock_expired = ReceiveLockExpired( sender=balance_proof.sender, balance_proof=balance_proof, secrethash=factories.make_secret_hash(next(counter)), message_identifier=MessageID(next(counter)), ) received_balance_proof = make_signed_balance_proof_from_counter(counter) unlock = ReceiveUnlock( sender=received_balance_proof.sender, message_identifier=MessageID(next(counter)), secret=factories.make_secret(next(counter)), balance_proof=received_balance_proof, ) transfer = make_signed_transfer_from_counter(counter) transfer_refund = ReceiveTransferRefund( transfer=transfer, balance_proof=transfer.balance_proof, sender=transfer.balance_proof.sender, # pylint: disable=no-member ) transfer = make_signed_transfer_from_counter(counter) transfer_reroute = ActionTransferReroute( transfer=transfer, balance_proof=transfer.balance_proof, sender=transfer.balance_proof.sender, # pylint: disable=no-member secret=sha3(factories.make_secret(next(counter))), ) mediator_from_route, mediator_signed_transfer = make_from_route_from_counter( counter) action_init_mediator = ActionInitMediator( route_states=[ RouteState( route=[factories.make_address(), factories.make_address()], forward_channel_id=factories.make_channel_identifier(), ) ], from_hop=mediator_from_route, from_transfer=mediator_signed_transfer, balance_proof=mediator_signed_transfer.balance_proof, sender=mediator_signed_transfer.balance_proof.sender, # pylint: disable=no-member ) target_from_route, target_signed_transfer = make_from_route_from_counter( counter) action_init_target = ActionInitTarget( from_hop=target_from_route, transfer=target_signed_transfer, balance_proof=target_signed_transfer.balance_proof, sender=target_signed_transfer.balance_proof.sender, # pylint: disable=no-member ) statechanges_balanceproofs = [ (lock_expired, lock_expired.balance_proof), (unlock, unlock.balance_proof), (transfer_refund, transfer_refund.transfer.balance_proof), (transfer_reroute, transfer_reroute.transfer.balance_proof), (action_init_mediator, action_init_mediator.from_transfer.balance_proof), (action_init_target, action_init_target.transfer.balance_proof), ] assert storage.count_state_changes() == 0 state_change_ids = storage.write_state_changes( [state_change for state_change, _ in statechanges_balanceproofs]) assert storage.count_state_changes() == len(statechanges_balanceproofs) msg_in_order = "Querying must return state changes in order" stored_statechanges_records = storage.get_statechanges_records_by_range( RANGE_ALL_STATE_CHANGES) assert len(stored_statechanges_records) == 6, msg_in_order pair_elements = zip(statechanges_balanceproofs, state_change_ids, stored_statechanges_records) for statechange_balanceproof, statechange_id, record in pair_elements: assert record.data == statechange_balanceproof[0], msg_in_order assert record.state_change_identifier == statechange_id, msg_in_order # Make sure state changes are returned in the correct order in which they were stored stored_statechanges = storage.get_statechanges_by_range( Range( stored_statechanges_records[1].state_change_identifier, stored_statechanges_records[2].state_change_identifier, )) assert len(stored_statechanges) == 2 assert isinstance(stored_statechanges[0], ReceiveUnlock) assert isinstance(stored_statechanges[1], ReceiveTransferRefund) for state_change, balance_proof in statechanges_balanceproofs: state_change_record = get_state_change_with_balance_proof_by_balance_hash( storage=storage, canonical_identifier=balance_proof.canonical_identifier, sender=balance_proof.sender, balance_hash=balance_proof.balance_hash, ) assert state_change_record assert state_change_record.data == state_change state_change_record = get_state_change_with_balance_proof_by_locksroot( storage=storage, canonical_identifier=balance_proof.canonical_identifier, sender=balance_proof.sender, locksroot=balance_proof.locksroot, ) assert state_change_record assert state_change_record.data == state_change storage.close()
def test_mediator_clear_pairs_after_batch_unlock(chain_state, token_network_state, our_address, channel_properties): """ Regression test for https://github.com/raiden-network/raiden/issues/2932 The mediator must also clear the transfer pairs once a ReceiveBatchUnlock where he is a participant is received. """ open_block_number = 10 open_block_hash = factories.make_block_hash() pseudo_random_generator = random.Random() properties, pkey = channel_properties address = properties.partner_state.address channel_state = factories.create(properties) channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state, block_number=open_block_number, block_hash=open_block_hash, ) channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change, block_number=open_block_number, block_hash=open_block_hash, pseudo_random_generator=pseudo_random_generator, ) lock_amount = 30 lock_expiration = 20 lock_secret = sha3(b"test_end_state") lock_secrethash = sha256(lock_secret).digest() lock = HashTimeLockState(lock_amount, lock_expiration, lock_secrethash) mediated_transfer = make_receive_transfer_mediated( channel_state=channel_state, privkey=pkey, nonce=1, transferred_amount=0, lock=lock) route_state = RouteState( route=[ channel_state.our_state.address, channel_state.partner_state.address ], forward_channel_id=channel_state.canonical_identifier. channel_identifier, ) from_hop = factories.make_hop_from_channel(channel_state) init_mediator = ActionInitMediator( route_states=[route_state], from_hop=from_hop, from_transfer=mediated_transfer, balance_proof=mediated_transfer.balance_proof, sender=mediated_transfer.balance_proof.sender, # pylint: disable=no-member ) node.state_transition(chain_state, init_mediator) closed_block_number = open_block_number + 10 closed_block_hash = factories.make_block_hash() channel_close_state_change = ContractReceiveChannelClosed( transaction_hash=factories.make_transaction_hash(), transaction_from=channel_state.partner_state.address, canonical_identifier=channel_state.canonical_identifier, block_number=closed_block_number, block_hash=closed_block_hash, ) channel_closed_iteration = token_network.state_transition( token_network_state=channel_new_iteration.new_state, state_change=channel_close_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) settle_block_number = closed_block_number + channel_state.settle_timeout + 1 channel_settled_state_change = ContractReceiveChannelSettled( transaction_hash=factories.make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, block_number=settle_block_number, block_hash=factories.make_block_hash(), our_onchain_locksroot=factories.make_32bytes(), partner_onchain_locksroot=LOCKSROOT_OF_NO_LOCKS, ) channel_settled_iteration = token_network.state_transition( token_network_state=channel_closed_iteration.new_state, state_change=channel_settled_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) token_network_state_after_settle = channel_settled_iteration.new_state ids_to_channels = token_network_state_after_settle.channelidentifiers_to_channels assert len(ids_to_channels) == 1 assert channel_state.identifier in ids_to_channels block_number = closed_block_number + 1 channel_batch_unlock_state_change = ContractReceiveChannelBatchUnlock( transaction_hash=factories.make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, receiver=address, sender=our_address, locksroot=compute_locksroot(PendingLocksState([bytes(lock.encoded)])), unlocked_amount=lock_amount, returned_tokens=0, block_number=block_number, block_hash=factories.make_block_hash(), ) channel_unlock_iteration = node.state_transition( chain_state=chain_state, state_change=channel_batch_unlock_state_change) chain_state = channel_unlock_iteration.new_state token_network_state = views.get_token_network_by_address( chain_state=chain_state, token_network_address=token_network_state.address) ids_to_channels = token_network_state.channelidentifiers_to_channels assert len(ids_to_channels) == 0 # Make sure that all is fine in the next block block = Block(block_number=block_number + 1, gas_limit=1, block_hash=factories.make_transaction_hash()) iteration = node.state_transition(chain_state=chain_state, state_change=block) assert iteration.new_state # Make sure that mediator task was cleared during the next block processing # since the channel was removed mediator_task = chain_state.payment_mapping.secrethashes_to_task.get( lock_secrethash) assert not mediator_task
def hash(self) -> bytes: return sha3(rlp.encode([r.hash for r in self.routes]))
def test_batch_unlock_after_restart(raiden_network, token_addresses, deposit): """Simulate the case where: - A sends B a transfer - B sends A a transfer - Secrets were never revealed - B closes channel - A crashes - Wait for settle - Wait for unlock from B - Restart A At this point, the current unlock logic will try to unlock iff the node gains from unlocking. Which means that the node will try to unlock either side. In the above scenario, each node will unlock its side. This test makes sure that we do NOT invalidate A's unlock transaction based on the ContractReceiveChannelBatchUnlock caused by B's unlock. """ alice_app, bob_app = raiden_network registry_address = alice_app.raiden.default_registry.address token_address = token_addresses[0] token_network_address = views.get_token_network_address_by_token_address( chain_state=views.state_from_app(alice_app), token_network_registry_address=alice_app.raiden.default_registry. address, token_address=token_address, ) assert token_network_address timeout = 10 token_network = views.get_token_network_by_address( chain_state=views.state_from_app(alice_app), token_network_address=token_network_address) assert token_network channel_identifier = get_channelstate(alice_app, bob_app, token_network_address).identifier assert (channel_identifier in token_network.partneraddresses_to_channelidentifiers[ bob_app.raiden.address]) alice_to_bob_amount = 10 identifier = 1 alice_transfer_secret = Secret(sha3(alice_app.raiden.address)) alice_transfer_secrethash = sha256_secrethash(alice_transfer_secret) bob_transfer_secret = Secret(sha3(bob_app.raiden.address)) bob_transfer_secrethash = sha256_secrethash(bob_transfer_secret) alice_transfer_hold = bob_app.raiden.raiden_event_handler.hold_secretrequest_for( secrethash=alice_transfer_secrethash) bob_transfer_hold = alice_app.raiden.raiden_event_handler.hold_secretrequest_for( secrethash=bob_transfer_secrethash) alice_app.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=alice_to_bob_amount, target=bob_app.raiden.address, identifier=identifier, secret=alice_transfer_secret, ) bob_app.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=alice_to_bob_amount, target=alice_app.raiden.address, identifier=identifier + 1, secret=bob_transfer_secret, ) alice_transfer_hold.wait(timeout=timeout) bob_transfer_hold.wait(timeout=timeout) alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_address) alice_lock = channel.get_lock(alice_bob_channel_state.our_state, alice_transfer_secrethash) bob_lock = channel.get_lock(alice_bob_channel_state.partner_state, bob_transfer_secrethash) assert alice_lock assert bob_lock # This is the current state of protocol: # # A -> B LockedTransfer # - protocol didn't continue assert_synced_channel_state( token_network_address=token_network_address, app0=alice_app, balance0=deposit, pending_locks0=[alice_lock], app1=bob_app, balance1=deposit, pending_locks1=[bob_lock], ) # A ChannelClose event will be generated, this will be polled by both apps # and each must start a task for calling settle RaidenAPI(bob_app.raiden).channel_close( registry_address=registry_address, token_address=token_address, partner_address=alice_app.raiden.address, ) # wait for the close transaction to be mined, this is necessary to compute # the timeout for the settle with gevent.Timeout(timeout): waiting.wait_for_close( raiden=alice_app.raiden, token_network_registry_address=registry_address, token_address=token_address, channel_ids=[alice_bob_channel_state.identifier], retry_timeout=alice_app.raiden.alarm.sleep_time, ) channel_closed = raiden_state_changes_search_for_item( bob_app.raiden, ContractReceiveChannelClosed, { "canonical_identifier": { "token_network_address": token_network_address, "channel_identifier": alice_bob_channel_state.identifier, } }, ) assert isinstance(channel_closed, ContractReceiveChannelClosed) settle_max_wait_block = BlockNumber( channel_closed.block_number + alice_bob_channel_state.settle_timeout * 2) settle_timeout = BlockTimeout( RuntimeError("settle did not happen"), bob_app.raiden, settle_max_wait_block, alice_app.raiden.alarm.sleep_time, ) with settle_timeout: waiting.wait_for_settle( raiden=alice_app.raiden, token_network_registry_address=registry_address, token_address=token_address, channel_ids=[alice_bob_channel_state.identifier], retry_timeout=alice_app.raiden.alarm.sleep_time, ) with gevent.Timeout(timeout): wait_for_batch_unlock( app=bob_app, token_network_address=token_network_address, receiver=alice_bob_channel_state.partner_state.address, sender=alice_bob_channel_state.our_state.address, ) alice_app.start() with gevent.Timeout(timeout): wait_for_batch_unlock( app=alice_app, token_network_address=token_network_address, receiver=alice_bob_channel_state.partner_state.address, sender=alice_bob_channel_state.our_state.address, )
def test_settled_lock(token_addresses, raiden_network, deposit): """ Any transfer following a secret reveal must update the locksroot, so that an attacker cannot reuse a secret to double claim a lock. """ app0, app1 = raiden_network registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] amount = PaymentAmount(30) token_network_address = views.get_token_network_address_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address) assert token_network_address hold_event_handler = app1.raiden.raiden_event_handler address0 = app0.raiden.address address1 = app1.raiden.address deposit0 = deposit deposit1 = deposit token_proxy = app0.raiden.proxy_manager.token(token_address) initial_balance0 = token_proxy.balance_of(address0) initial_balance1 = token_proxy.balance_of(address1) identifier = 1 target = app1.raiden.address secret = Secret(sha3(target)) secrethash = sha256_secrethash(secret) secret_available = hold_event_handler.hold_secretrequest_for( secrethash=secrethash) app0.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=amount, target=target, identifier=identifier, secret=secret, ) secret_available.wait() # wait for the messages to be exchanged # Save the pending locks from the pending transfer, used to test the unlock channelstate_0_1 = get_channelstate(app0, app1, token_network_address) batch_unlock = channel.get_batch_unlock(channelstate_0_1.our_state) assert batch_unlock hold_event_handler.release_secretrequest_for(app1.raiden, secrethash) transfer( initiator_app=app0, target_app=app1, token_address=token_address, amount=amount, identifier=PaymentID(2), ) RaidenAPI(app1.raiden).channel_close(registry_address, token_address, app0.raiden.address) waiting.wait_for_settle( app1.raiden, app1.raiden.default_registry.address, token_address, [channelstate_0_1.identifier], app1.raiden.alarm.sleep_time, ) current_block = app0.raiden.rpc_client.block_number() netting_channel = app1.raiden.proxy_manager.payment_channel( canonical_identifier=channelstate_0_1.canonical_identifier) # The transfer locksroot must not contain the unlocked lock, the # unlock must fail. with pytest.raises(RaidenUnrecoverableError): netting_channel.unlock( sender=channelstate_0_1.our_state.address, receiver=channelstate_0_1.partner_state.address, pending_locks=batch_unlock, given_block_identifier=current_block, ) expected_balance0 = initial_balance0 + deposit0 - amount * 2 expected_balance1 = initial_balance1 + deposit1 + amount * 2 assert token_proxy.balance_of(address0) == expected_balance0 assert token_proxy.balance_of(address1) == expected_balance1
def test_channel_withdraw_expired(raiden_network, number_of_nodes, token_addresses, deposit, network_wait, retry_timeout): """ Tests withdraw expiration. """ alice_app, bob_app = raiden_network token_address = token_addresses[0] token_network_address = views.get_token_network_address_by_token_address( views.state_from_app(alice_app), alice_app.raiden.default_registry.address, token_address) assert token_network_address # Prevent withdraw confirmation from being sent send_withdraw_confirmation_event = alice_app.raiden.raiden_event_handler.hold( SendWithdrawConfirmation, {}) alice_to_bob_amount = 10 total_withdraw = deposit + alice_to_bob_amount wait_for_withdraw_expired_message = alice_app.raiden.message_handler.wait_for_message( WithdrawExpired, {"total_withdraw": total_withdraw}) identifier = 1 target = bob_app.raiden.address secret = sha3(target) payment_status = alice_app.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=alice_to_bob_amount, target=target, identifier=identifier, secret=secret, ) wait_for_unlock = bob_app.raiden.message_handler.wait_for_message( Unlock, {"payment_identifier": identifier}) timeout = network_wait * number_of_nodes with Timeout(seconds=timeout): wait_for_unlock.get() msg = ( f"transfer from {to_checksum_address(alice_app.raiden.address)} " f"to {to_checksum_address(bob_app.raiden.address)} failed.") assert payment_status.payment_done.get(), msg bob_alice_channel_state = get_channelstate(bob_app, alice_app, token_network_address) bob_app.raiden.withdraw( canonical_identifier=bob_alice_channel_state.canonical_identifier, total_withdraw=total_withdraw, ) with Timeout(seconds=timeout): send_withdraw_confirmation_event.wait() # Make sure proper withdraw state is set in both channel states bob_alice_channel_state = get_channelstate(bob_app, alice_app, token_network_address) assert bob_alice_channel_state.our_total_withdraw == total_withdraw assert bob_alice_channel_state.our_state.withdraws_pending.get( total_withdraw) is not None alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_address) assert alice_bob_channel_state.partner_total_withdraw == total_withdraw assert alice_bob_channel_state.partner_state.withdraws_pending.get( total_withdraw) is not None withdraw_expiration = bob_alice_channel_state.our_state.withdraws_pending[ total_withdraw].expiration expiration_threshold = channel.get_sender_expiration_threshold( withdraw_expiration) waiting.wait_for_block( raiden=bob_app.raiden, block_number=BlockNumber(expiration_threshold + 1), retry_timeout=retry_timeout, ) bob_alice_channel_state = get_channelstate(bob_app, alice_app, token_network_address) assert bob_alice_channel_state.our_total_withdraw == 0 assert bob_alice_channel_state.our_state.withdraws_pending.get( total_withdraw) is None with Timeout(seconds=timeout): wait_for_withdraw_expired_message.wait() alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_address) assert alice_bob_channel_state.partner_total_withdraw == 0 assert alice_bob_channel_state.partner_state.withdraws_pending.get( total_withdraw) is None
def test_channel_data_removed_after_unlock(chain_state, token_network_state, our_address, channel_properties): open_block_number = 10 open_block_hash = factories.make_block_hash() pseudo_random_generator = random.Random() properties, pkey = channel_properties address = properties.partner_state.address channel_state = factories.create(properties) channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state, block_number=open_block_number, block_hash=open_block_hash, ) channel_new_iteration = token_network.state_transition( token_network_state=token_network_state, state_change=channel_new_state_change, block_number=open_block_number, block_hash=open_block_hash, pseudo_random_generator=pseudo_random_generator, ) lock_amount = 30 lock_expiration = 20 lock_secret = sha3(b"test_end_state") lock_secrethash = sha256(lock_secret).digest() lock = HashTimeLockState(lock_amount, lock_expiration, lock_secrethash) mediated_transfer = make_receive_transfer_mediated( channel_state=channel_state, privkey=pkey, nonce=1, transferred_amount=0, lock=lock) from_hop = factories.make_hop_from_channel(channel_state) init_target = ActionInitTarget( sender=mediated_transfer.balance_proof.sender, # pylint: disable=no-member balance_proof=mediated_transfer.balance_proof, from_hop=from_hop, transfer=mediated_transfer, ) node.state_transition(chain_state, init_target) closed_block_number = open_block_number + 10 closed_block_hash = factories.make_block_hash() channel_close_state_change = ContractReceiveChannelClosed( transaction_hash=factories.make_transaction_hash(), transaction_from=channel_state.partner_state.address, canonical_identifier=channel_state.canonical_identifier, block_number=closed_block_number, block_hash=closed_block_hash, ) channel_closed_iteration = token_network.state_transition( token_network_state=channel_new_iteration.new_state, state_change=channel_close_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) channel_state_after_closed = channel_closed_iteration.new_state.channelidentifiers_to_channels[ channel_state.identifier] settle_block_number = closed_block_number + channel_state.settle_timeout + 1 channel_settled_state_change = ContractReceiveChannelSettled( transaction_hash=factories.make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, block_number=settle_block_number, block_hash=factories.make_block_hash(), our_onchain_locksroot=compute_locksroot( channel_state_after_closed.our_state.pending_locks), partner_onchain_locksroot=compute_locksroot( channel_state_after_closed.partner_state.pending_locks), ) channel_settled_iteration = token_network.state_transition( token_network_state=channel_closed_iteration.new_state, state_change=channel_settled_state_change, block_number=closed_block_number, block_hash=closed_block_hash, pseudo_random_generator=pseudo_random_generator, ) token_network_state_after_settle = channel_settled_iteration.new_state ids_to_channels = token_network_state_after_settle.channelidentifiers_to_channels assert len(ids_to_channels) == 1 assert channel_state.identifier in ids_to_channels unlock_blocknumber = settle_block_number + 5 channel_batch_unlock_state_change = ContractReceiveChannelBatchUnlock( transaction_hash=factories.make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, receiver=our_address, sender=address, locksroot=compute_locksroot(PendingLocksState([bytes(lock.encoded)])), unlocked_amount=lock_amount, returned_tokens=0, block_number=closed_block_number + 1, block_hash=factories.make_block_hash(), ) channel_unlock_iteration = token_network.state_transition( token_network_state=channel_settled_iteration.new_state, state_change=channel_batch_unlock_state_change, block_number=unlock_blocknumber, block_hash=factories.make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) token_network_state_after_unlock = channel_unlock_iteration.new_state ids_to_channels = token_network_state_after_unlock.channelidentifiers_to_channels assert len(ids_to_channels) == 0