def test_secret_revealed(deployed_network, deposit): app0, app1, app2 = deployed_network asset_address = app0.raiden.chain.default_registry.asset_addresses()[0] amount = 10 secret = pending_mediated_transfer(deployed_network, asset_address, amount) mediated_transfer = get_received_transfer( channel(app2, app1, asset_address), 0, ) merkle_proof = channel(app2, app1, asset_address).our_state.locked.get_proof(mediated_transfer) channel(app2, app1, asset_address).netting_contract.unlock( [(merkle_proof, mediated_transfer.lock, secret)], ) gevent.sleep(0.1) # let the task run assert_synched_channels( channel(app1, app2, asset_address), deposit - amount, [], channel(app2, app1, asset_address), deposit + amount, [], ) assert_synched_channels( channel(app0, app1, asset_address), deposit - amount, [], channel(app1, app2, asset_address), deposit + amount, [], )
def test_settled_lock(token_addresses, raiden_network, settle_timeout, reveal_timeout): """ Any transfer following a secret revealed must update the locksroot, so that an attacker cannot reuse a secret to double claim a lock. """ token = token_addresses[0] amount = 30 app0, app1, app2, _ = raiden_network # pylint: disable=unbalanced-tuple-unpacking address0 = app0.raiden.address address1 = app1.raiden.address forward_channel = channel(app0, app1, token) back_channel = channel(app1, app0, token) deposit0 = forward_channel.contract_balance deposit1 = back_channel.contract_balance token_contract = app0.raiden.chain.token(token) balance0 = token_contract.balance_of(address0) balance1 = token_contract.balance_of(address1) # A pending mediated transfer identifier = 1 expiration = app0.raiden.chain.block_number() + settle_timeout - reveal_timeout secret = pending_mediated_transfer( raiden_network, token, amount, identifier, expiration, ) hashlock = sha3(secret) # Get the proof to unlock the pending lock secret_transfer = get_received_transfer(back_channel, 0) lock = back_channel.partner_state.get_lock_by_hashlock(hashlock) unlock_proof = back_channel.partner_state.compute_proof_for_lock(secret, lock) # Update the hashlock claim_lock(raiden_network, identifier, token, secret) direct_transfer(app0, app1, token, amount, identifier=1) # The direct transfer locksroot must remove the unlocked lock and update # the transferred amount, the withdraw must fail. balance_proof = back_channel.partner_state.balance_proof back_channel.external_state.close(balance_proof) with pytest.raises(Exception): back_channel.external_state.netting_channel.withdraw( [(unlock_proof, secret_transfer.lock.as_bytes, secret)], ) settle_expiration = app2.raiden.chain.block_number() + settle_timeout wait_until_block(app2.raiden.chain, settle_expiration) back_channel.external_state.netting_channel.settle() assert token_contract.balance_of(address0) == balance0 + deposit0 - amount * 2 assert token_contract.balance_of(address1) == balance1 + deposit1 + amount * 2
def test_settled_lock(assets_addresses, raiden_network, settle_timeout): """ Any transfer following a secret revealed must update the locksroot, so that an attacker cannot reuse a secret to double claim a lock. """ asset = assets_addresses[0] amount = 30 app0, app1, app2, app3 = raiden_network # pylint: disable=unbalanced-tuple-unpacking # mediated transfer secret = pending_mediated_transfer(raiden_network, asset, amount) hashlock = sha3(secret) # get a proof for the pending transfer back_channel = channel(app1, app0, asset) secret_transfer = get_received_transfer(back_channel, 0) lock = back_channel.our_state.balance_proof.get_lock_by_hashlock(hashlock) unlock_proof = back_channel.our_state.balance_proof.compute_proof_for_lock( secret, lock) # reveal the secret claim_lock(raiden_network, asset, secret) # a new transfer to update the hashlock direct_transfer(app0, app1, asset, amount) forward_channel = channel(app0, app1, asset) last_transfer = get_sent_transfer(forward_channel, 1) # call close giving the secret for a transfer that has being revealed back_channel.external_state.netting_channel.close(app1.raiden.address, last_transfer, None) # check that the double unlock will failed with pytest.raises(Exception): back_channel.external_state.netting_channel.unlock( app1.raiden.address, [(unlock_proof, secret_transfer.lock.as_bytes, secret)], ) # forward the block number to allow settle settle_expiration = app2.raiden.chain.block_number() + settle_timeout wait_until_block(app2.raiden.chain, settle_expiration) back_channel.external_state.netting_channel.settle() participant0 = back_channel.external_state.netting_channel.contract.participants[ app0.raiden.address] participant1 = back_channel.external_state.netting_channel.contract.participants[ app1.raiden.address] assert participant0.netted == participant0.deposit - amount * 2 assert participant1.netted == participant1.deposit + amount * 2
def test_settled_lock(): """ After a lock has it's secret revealed and a transfer happened, the lock cannot be used to net any value with the contract. """ deposit = 100 asset = sha3('test_settled_lock')[:20] amount = 30 # pylint: disable=unbalanced-tuple-unpacking apps = create_sequential_network(num_nodes=4, deposit=deposit, asset=asset) # mediated transfer with the secret revealed transfer(apps[0], apps[3], asset, amount) # create the latest transfer direct_transfer(apps[0], apps[1], asset, amount) secret = '' # need to get the secret attack_channel = channel(apps[2], apps[1], asset) secret_transfer = get_received_transfer(attack_channel, 0) last_transfer = get_received_transfer(attack_channel, 1) nettingcontract_address = attack_channel.nettingcontract_address # create a fake proof merkle_proof = attack_channel.our_state.locked.get_proof(secret_transfer) # call close giving the secret for a transfer that has being revealed apps[1].raiden.chain.close( asset, nettingcontract_address, apps[1].raiden.address, [last_transfer], [(merkle_proof, secret_transfer.lock, secret)], ) # forward the block number to allow settle for _ in range(NettingChannelContract.locked_time): apps[2].raiden.chain.next_block() apps[1].raiden.chain.settle(asset, nettingcontract_address)
def test_settled_lock(): """ After a lock has it's secret revealed and a transfer happened, the lock cannot be used to net any value with the contract. """ deposit = 100 asset = sha3('test_settled_lock')[:20] amount = 30 # pylint: disable=unbalanced-tuple-unpacking apps = create_sequential_network(num_nodes=4, deposit=deposit, asset=asset) # mediated transfer with the secret revealed transfer(apps[0], apps[3], asset, amount) # create the latest transfer direct_transfer(apps[0], apps[1], asset, amount) secret = '' # need to get the secret attack_channel = channel(apps[2], apps[1], asset) secret_transfer = get_received_transfer(attack_channel, 0) last_transfer = get_received_transfer(attack_channel, 1) nettingcontract_address = attack_channel.nettingcontract_address # create a fake proof merkle_proof = attack_channel.our_state.locked.get_proof(secret_transfer) # call close giving the secret for a transfer that has being revealed apps[1].raiden.chain.close( asset, nettingcontract_address, apps[1].raiden.address, [last_transfer], [(merkle_proof, secret_transfer.lock, secret)], ) # forward the block number to allow settle for _ in range(NettingChannelContract.settle_timeout): apps[2].raiden.chain.next_block() apps[1].raiden.chain.settle(asset, nettingcontract_address)
def test_settled_lock(assets_addresses, raiden_network, settle_timeout): """ Any transfer following a secret revealed must update the locksroot, so that an attacker cannot reuse a secret to double claim a lock. """ asset = assets_addresses[0] amount = 30 app0, app1, app2, app3 = raiden_network # pylint: disable=unbalanced-tuple-unpacking # mediated transfer secret = pending_mediated_transfer(raiden_network, asset, amount) # get a proof for the pending transfer back_channel = channel(app1, app0, asset) secret_transfer = get_received_transfer(back_channel, 0) merkle_proof = back_channel.our_state.locked.get_proof(secret_transfer) # reveal the secret register_secret(raiden_network, asset, secret) # a new transfer to update the hashlock direct_transfer(app0, app1, asset, amount) forward_channel = channel(app0, app1, asset) last_transfer = get_sent_transfer(forward_channel, 1) # call close giving the secret for a transfer that has being revealed back_channel.external_state.netting_channel.close( app1.raiden.address, last_transfer, None ) # check that the double unlock will failed with pytest.raises(Exception): back_channel.external_state.netting_channel.unlock( app1.raiden.address, [(merkle_proof, secret_transfer.lock.as_bytes, secret)], ) # forward the block number to allow settle for _ in range(settle_timeout): app2.raiden.chain.next_block() back_channel.external_state.netting_channel.settle() participant0 = back_channel.external_state.netting_channel.contract.participants[app0.raiden.address] participant1 = back_channel.external_state.netting_channel.contract.participants[app1.raiden.address] assert participant0.netted == participant0.deposit - amount * 2 assert participant1.netted == participant1.deposit + amount * 2
def test_secret_revealed(deployed_network, deposit): app0, app1, app2 = deployed_network asset_address = app0.raiden.chain.default_registry.asset_addresses()[0] amount = 10 secret = pending_mediated_transfer(deployed_network, asset_address, amount) mediated_transfer = get_received_transfer( channel(app2, app1, asset_address), 0, ) merkle_proof = channel( app2, app1, asset_address).our_state.locked.get_proof(mediated_transfer) channel(app2, app1, asset_address).netting_contract.unlock( [(merkle_proof, mediated_transfer.lock, secret)], ) gevent.sleep(0.1) # let the task run assert_synched_channels( channel(app1, app2, asset_address), deposit - amount, [], channel(app2, app1, asset_address), deposit + amount, [], ) assert_synched_channels( channel(app0, app1, asset_address), deposit - amount, [], channel(app1, app2, asset_address), deposit + amount, [], )
def test_start_end_attack(asset_address, raiden_chain, deposit): """ An attacker can try to steal assets 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 it's know secret and reveal to close and settles the channel H-A2, without revealing the secret to H's raiden node. The intention is to make the hub transfer the asset but for him to be unable to require the asset A1. """ amount = 30 asset = asset_address[0] app0, app1, app2 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking # the attacker owns app0 and app2 and creates a transfer throught app1 secret = pending_mediated_transfer( raiden_chain, asset, amount, 1 # TODO: fill in identifier ) hashlock = sha3(secret) attack_channel = channel(app2, app1, asset) attack_transfer = get_received_transfer(attack_channel, 0) attack_contract = attack_channel.external_state.netting_channel.address hub_contract = channel(app1, app0, asset).external_state.netting_channel.address # the attacker can create a merkle proof of the locked transfer lock = attack_channel.our_state.balance_proof.get_lock_by_hashlock(hashlock) unlock_proof = attack_channel.our_state.balance_proof.compute_proof_for_lock(secret, lock) # start the settle counter attack_channel.netting_channel.close( app2.raiden.address, attack_transfer, None ) # wait until the last block to reveal the secret, hopefully we are not # missing a block during the test wait_until_block(app2.raiden.chain, attack_transfer.lock.expiration - 1) # since the attacker knows the secret he can net the lock attack_channel.netting_channel.unlock( [(unlock_proof, attack_transfer.lock, secret)], ) # XXX: verify that the secret was publicized # at this point the hub might not know yet the secret, and won't be able to # claim the asset from the channel A1 - H # the attacker settle the contract app2.raiden.chain.next_block() attack_channel.netting_channel.settle(asset, attack_contract) # at this point the attack has the "stolen" funds attack_contract = app2.raiden.chain.asset_hashchannel[asset][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.chain.asset_hashchannel[asset][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, since for A2 to acquire the asset # it needs to make the secret public in the block chain we publish the # secret through an event and the Hub will be able to require it's funds app1.raiden.chain.next_block() # XXX: verify that the Hub has found the secret, close and settle the channel # the hub has acquired it's asset hub_contract = app1.raiden.chain.asset_hashchannel[asset][hub_contract] assert hub_contract.participants[app0.raiden.address]['netted'] == deposit + amount assert hub_contract.participants[app1.raiden.address]['netted'] == deposit - amount
def test_settled_lock(assets_addresses, raiden_network, settle_timeout, reveal_timeout): """ Any transfer following a secret revealed must update the locksroot, so that an attacker cannot reuse a secret to double claim a lock. """ asset = assets_addresses[0] amount = 30 app0, app1, app2, _ = raiden_network # pylint: disable=unbalanced-tuple-unpacking address0 = app0.raiden.address address1 = app1.raiden.address # mediated transfer identifier = 1 expiration = app0.raiden.chain.block_number() + settle_timeout - reveal_timeout secret = pending_mediated_transfer( raiden_network, asset, amount, identifier, expiration, ) hashlock = sha3(secret) # get a proof for the pending transfer back_channel = channel(app1, app0, asset) secret_transfer = get_received_transfer(back_channel, 0) lock = back_channel.our_state.balance_proof.get_lock_by_hashlock(hashlock) unlock_proof = back_channel.our_state.balance_proof.compute_proof_for_lock(secret, lock) # reveal the secret claim_lock(raiden_network, asset, secret) # a new transfer to update the hashlock direct_transfer(app0, app1, asset, amount) forward_channel = channel(app0, app1, asset) last_transfer = get_sent_transfer(forward_channel, 1) # call close giving the secret for a transfer that has being revealed back_channel.external_state.netting_channel.close( app1.raiden.address, last_transfer, None ) # check that the double unlock will failed with pytest.raises(Exception): back_channel.external_state.netting_channel.unlock( app1.raiden.address, [(unlock_proof, secret_transfer.lock.as_bytes, secret)], ) # forward the block number to allow settle settle_expiration = app2.raiden.chain.block_number() + settle_timeout wait_until_block(app2.raiden.chain, settle_expiration) back_channel.external_state.netting_channel.settle() participant0 = back_channel.external_state.netting_channel.contract.participants[address0] participant1 = back_channel.external_state.netting_channel.contract.participants[address1] assert participant0.netted == participant0.deposit - amount * 2 assert participant1.netted == participant1.deposit + amount * 2
def test_start_end_attack(token_addresses, raiden_chain, deposit, reveal_timeout): """ 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 settles 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 # the attacker owns app0 and app2 and creates a transfer through app1 identifier = 1 expiration = reveal_timeout + 5 secret = pending_mediated_transfer(raiden_chain, token, amount, identifier, expiration) hashlock = sha3(secret) attack_channel = channel(app2, app1, token) attack_transfer = get_received_transfer(attack_channel, 0) attack_contract = attack_channel.external_state.netting_channel.address hub_contract = channel(app1, app0, token).external_state.netting_channel.address # the attacker can create a merkle proof of the locked transfer lock = attack_channel.our_state.balance_proof.get_lock_by_hashlock( hashlock) unlock_proof = attack_channel.our_state.balance_proof.compute_proof_for_lock( secret, lock) # start the settle counter attack_channel.netting_channel.close(attack_transfer) # wait until the last block to reveal the secret, hopefully we are not # missing a block during the test wait_until_block(app2.raiden.chain, attack_transfer.lock.expiration - 1) # since the attacker knows the secret he can net the lock attack_channel.netting_channel.withdraw( [(unlock_proof, attack_transfer.lock, secret)], ) # XXX: verify that the secret was publicized # at this point the hub might not know yet the secret, and won't be able to # claim the token from the channel A1 - H # the attacker settle the contract app2.raiden.chain.next_block() attack_channel.netting_channel.settle(token, attack_contract) # at this point the attack has the "stolen" funds attack_contract = app2.raiden.chain.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.chain.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, since for A2 to acquire the token # it needs to make the secret public in the block chain we publish the # secret through an event and the Hub will be able to require it's funds app1.raiden.chain.next_block() # XXX: verify that the Hub has found the secret, close and settle the channel # the hub has acquired its token hub_contract = app1.raiden.chain.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 test_settled_lock(token_addresses, raiden_network, settle_timeout, reveal_timeout): """ Any transfer following a secret revealed must update the locksroot, so that an attacker cannot reuse a secret to double claim a lock. """ token = token_addresses[0] amount = 30 app0, app1, app2, _ = raiden_network # pylint: disable=unbalanced-tuple-unpacking address0 = app0.raiden.address address1 = app1.raiden.address forward_channel = channel(app0, app1, token) back_channel = channel(app1, app0, token) deposit0 = forward_channel.contract_balance deposit1 = back_channel.contract_balance token_contract = app0.raiden.chain.token(token) balance0 = token_contract.balance_of(address0) balance1 = token_contract.balance_of(address1) # mediated transfer identifier = 1 expiration = app0.raiden.chain.block_number( ) + settle_timeout - reveal_timeout secret = pending_mediated_transfer( raiden_network, token, amount, identifier, expiration, ) hashlock = sha3(secret) # get a proof for the pending transfer secret_transfer = get_received_transfer(back_channel, 0) lock = back_channel.our_state.balance_proof.get_lock_by_hashlock(hashlock) unlock_proof = back_channel.our_state.balance_proof.compute_proof_for_lock( secret, lock) # reveal the secret claim_lock(raiden_network, token, secret) # a new transfer to update the hashlock direct_transfer(app0, app1, token, amount) last_transfer = get_sent_transfer(forward_channel, 1) # call close giving the secret for a transfer that has being revealed back_channel.external_state.netting_channel.close(last_transfer) # check that the double unlock will fail with pytest.raises(Exception): back_channel.external_state.netting_channel.withdraw( [(unlock_proof, secret_transfer.lock.as_bytes, secret)], ) # forward the block number to allow settle settle_expiration = app2.raiden.chain.block_number() + settle_timeout wait_until_block(app2.raiden.chain, settle_expiration) back_channel.external_state.netting_channel.settle() assert token_contract.balance_of( address0) == balance0 + deposit0 - amount * 2 assert token_contract.balance_of( address1) == balance1 + deposit1 + amount * 2
def test_start_end_attack(): """ An attacker can try to steal assets 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 it's know secret and reveal to close and settles the channel H-A2, without revealing the secret to H's raiden node. The intention is to make the hub transfer the asset but for him to be unable to require the asset A1. """ asset = sha3('test_two_attack')[:20] deposit = 100 amount = 30 apps = create_sequential_network(num_nodes=3, deposit=deposit, asset=asset) # The attacker creates a mediated transfer from it's account A1, to it's # account A2, throught the hub H secret = hidden_mediated_transfer(apps, asset, amount) attack_channel = channel(apps[2], apps[1], asset) attack_transfer = get_received_transfer(attack_channel, 0) attack_contract = attack_channel.nettingcontract_address hub_contract = channel(apps[1], apps[0], asset).nettingcontract_address # the attacker can create a merkle proof of the locked transfer merkle_proof = attack_channel.our_state.locked.get_proof(attack_transfer) # start the settle counter apps[2].raiden.chain.close( asset, attack_contract, apps[2].raiden.address, [attack_transfer], [], ) # wait until the last block to reveal the secret for _ in range(attack_transfer.lock.expiration - 1): apps[2].raiden.chain.next_block() # since the attacker knows the secret he can net the lock apps[2].raiden.chain.close( asset, attack_contract, apps[2].raiden.address, [attack_transfer], [(merkle_proof, attack_transfer.lock, secret)], ) # XXX: verify that the secret was publicized # at this point the hub might not know yet the secret, and won't be able to # claim the asset from the channel A1 - H # the attacker settle the contract apps[2].raiden.chain.next_block() apps[2].raiden.chain.settle(asset, attack_contract) # at this point the attack has the "stolen" funds attack_contract = apps[2].raiden.chain.asset_hashchannel[asset][attack_contract] assert attack_contract.participants[apps[2].raiden.address]['netted'] == deposit + amount assert attack_contract.participants[apps[1].raiden.address]['netted'] == deposit - amount # and the hub's channel A1-H doesn't hub_contract = apps[1].raiden.chain.asset_hashchannel[asset][hub_contract] assert hub_contract.participants[apps[0].raiden.address]['netted'] == deposit assert hub_contract.participants[apps[1].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, since for A2 to acquire the asset # it needs to make the secret public in the block chain we publish the # secret through an event and the Hub will be able to require it's funds apps[1].raiden.chain.next_block() # XXX: verify that the Hub has found the secret, close and settle the channel # the hub has acquired it's asset hub_contract = apps[1].raiden.chain.asset_hashchannel[asset][hub_contract] assert hub_contract.participants[apps[0].raiden.address]['netted'] == deposit + amount assert hub_contract.participants[apps[1].raiden.address]['netted'] == deposit - amount
def test_start_end_attack(asset_address, raiden_chain, deposit): """ An attacker can try to steal assets 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 it's know secret and reveal to close and settles the channel H-A2, without revealing the secret to H's raiden node. The intention is to make the hub transfer the asset but for him to be unable to require the asset A1. """ amount = 30 asset = asset_address[0] app0, app1, app2 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking # The attacker creates a mediated transfer from it's account A1, to it's # account A2, throught the hub H secret = pending_mediated_transfer(raiden_chain, asset, amount) attack_channel = channel(app2, app1, asset) attack_transfer = get_received_transfer(attack_channel, 0) attack_contract = attack_channel.external_state.netting_channel.address hub_contract = channel(app1, app0, asset).external_state.netting_channel.address # the attacker can create a merkle proof of the locked transfer merkle_proof = attack_channel.our_state.locked.get_proof(attack_transfer) # start the settle counter attack_channel.netting_channel.close( app2.raiden.address, attack_transfer, None ) # wait until the last block to reveal the secret for _ in range(attack_transfer.lock.expiration - 1): app2.raiden.chain.next_block() # since the attacker knows the secret he can net the lock attack_channel.netting_channel.unlock( [(merkle_proof, attack_transfer.lock, secret)], ) # XXX: verify that the secret was publicized # at this point the hub might not know yet the secret, and won't be able to # claim the asset from the channel A1 - H # the attacker settle the contract app2.raiden.chain.next_block() attack_channel.netting_channel.settle(asset, attack_contract) # at this point the attack has the "stolen" funds attack_contract = app2.raiden.chain.asset_hashchannel[asset][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.chain.asset_hashchannel[asset][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, since for A2 to acquire the asset # it needs to make the secret public in the block chain we publish the # secret through an event and the Hub will be able to require it's funds app1.raiden.chain.next_block() # XXX: verify that the Hub has found the secret, close and settle the channel # the hub has acquired it's asset hub_contract = app1.raiden.chain.asset_hashchannel[asset][hub_contract] assert hub_contract.participants[app0.raiden.address]['netted'] == deposit + amount assert hub_contract.participants[app1.raiden.address]['netted'] == deposit - amount
def test_settled_lock(token_addresses, raiden_network, settle_timeout, reveal_timeout): """ Any transfer following a secret revealed must update the locksroot, so that an attacker cannot reuse a secret to double claim a lock. """ token = token_addresses[0] amount = 30 app0, app1, app2, _ = raiden_network # pylint: disable=unbalanced-tuple-unpacking address0 = app0.raiden.address address1 = app1.raiden.address forward_channel = channel(app0, app1, token) back_channel = channel(app1, app0, token) deposit0 = forward_channel.contract_balance deposit1 = back_channel.contract_balance token_contract = app0.raiden.chain.token(token) balance0 = token_contract.balance_of(address0) balance1 = token_contract.balance_of(address1) # A pending mediated transfer identifier = 1 expiration = app0.raiden.chain.block_number( ) + settle_timeout - reveal_timeout secret = pending_mediated_transfer( raiden_network, token, amount, identifier, expiration, ) hashlock = sha3(secret) # Get the proof to unlock the pending lock secret_transfer = get_received_transfer(back_channel, 0) lock = back_channel.partner_state.balance_proof.get_lock_by_hashlock( hashlock) unlock_proof = back_channel.partner_state.balance_proof.compute_proof_for_lock( secret, lock) # Update the hashlock claim_lock(raiden_network, identifier, token, secret) direct_transfer(app0, app1, token, amount, identifier=1) # The direct transfer locksroot must remove the unlocked lock and update # the transferred amount, the withdraw must fail. balance_proof = back_channel.partner_state.balance_proof.balance_proof back_channel.external_state.close(balance_proof) with pytest.raises(Exception): back_channel.external_state.netting_channel.withdraw( [(unlock_proof, secret_transfer.lock.as_bytes, secret)], ) settle_expiration = app2.raiden.chain.block_number() + settle_timeout wait_until_block(app2.raiden.chain, settle_expiration) back_channel.external_state.netting_channel.settle() assert token_contract.balance_of( address0) == balance0 + deposit0 - amount * 2 assert token_contract.balance_of( address1) == balance1 + deposit1 + amount * 2