def test_hash(): ping = Ping(nonce=0, current_protocol_version=constants.PROTOCOL_VERSION) ping.sign(PRIVKEY) data = ping.encode() msghash = sha3(data) decoded_ping = decode(data) assert sha3(decoded_ping.encode()) == msghash
def test_mediated_transfer(iterations=ITERATIONS): identifier = 1 amount = 1 expiration = 1 hashlock = sha3(ADDRESS) lock = Lock(amount, expiration, hashlock) nonce = 1 asset = ADDRESS balance = 1 recipient = ADDRESS locksroot = sha3(ADDRESS) target = ADDRESS initiator = ADDRESS msg = MediatedTransfer( identifier, nonce, asset, balance, recipient, locksroot, lock, target, initiator, fee=0, ) msg.sign(PRIVKEY, ADDRESS) run_timeit('MediatedTranfer', msg, iterations=iterations)
def test_three(): hash_0 = b'a' * 32 hash_1 = b'b' * 32 hash_2 = b'c' * 32 leaves = [hash_0, hash_1, hash_2] layers = compute_layers(leaves) tree = MerkleTreeState(layers) root = merkleroot(tree) hash_01 = ( b'me\xef\x9c\xa9=5\x16\xa4\xd3\x8a\xb7\xd9\x89\xc2\xb5\x00' b'\xe2\xfc\x89\xcc\xdc\xf8x\xf9\xc4m\xaa\xf6\xad\r[' ) assert sha3(hash_0 + hash_1) == hash_01 calculated_root = sha3(hash_2 + hash_01) proof0 = compute_merkleproof_for(tree, hash_0) proof1 = compute_merkleproof_for(tree, hash_1) proof2 = compute_merkleproof_for(tree, hash_2) assert proof0 == [hash_1, hash_2] assert root == calculated_root assert validate_proof(proof0, root, hash_0) assert proof1 == [hash_0, hash_2] assert root == calculated_root assert validate_proof(proof1, root, hash_1) # with an odd number of values, the last value wont appear by itself in the # proof since it isn't hashed with another value assert proof2 == [sha3(hash_0 + hash_1)] assert root == calculated_root assert validate_proof(proof2, root, hash_2)
def mediated_transfer(initiator_app, target_app, asset, amount): # pylint: disable=too-many-arguments """ Nice to read shortcut to make a MediatedTransfer. The secret will be revealed and the apps will be synchronized. """ has_channel = target_app.raiden.address in initiator_app.raiden.assetmanagers[asset].channel # api.transfer() would do a DirectTransfer if has_channel: initiator_channel = channel(initiator_app, target_app, asset) secret = sha3('{}{}'.format( initiator_channel.nettingcontract_address, str(initiator_channel.our_state.nonce), )) hashlock = sha3(secret) transfermanager = target_app.raiden.assetmanagers[asset].transfermanager task = MediatedTransferTask( transfermanager, amount, target_app.address, hashlock, expiration=None, originating_transfer=None, secret=secret, ) task.start() task.join() else: initiator_app.raiden.api.transfer(asset, amount, target_app.raiden.address)
def test_hash(): ping = Ping(nonce=0) ping.sign(PRIVKEY) data = ping.encode() msghash = sha3(data) decoded_ping = decode(data) assert sha3(decoded_ping.encode()) == msghash
def unlock(self, ctx, locked_encoded, merkleproof_encoded, secret): if self.settled is not None: raise RuntimeError('Contract is settled.') if self.closed is None: raise RuntimeError('Contract is open.') if ctx['msg.sender'] not in self.participants: raise ValueError('Unknow address.') partner = self.partner(ctx['msg.sender']) state = self.participants[partner] transfer = state.transfer # if partner haven't made a single transfer if transfer is None: return merkle_proof = tuple32(merkleproof_encoded) lock = Lock.from_bytes(locked_encoded) hashlock = lock.hashlock if hashlock != sha3(secret): raise ValueError('Invalid secret') is_valid_proof = check_proof( merkle_proof, transfer.locksroot, sha3(transfer.lock.as_bytes), ) if not is_valid_proof: raise ValueError('Invalid merkle proof') transfer.append(lock)
def withdraw_lock(self, secret): """ A lock was released by the sender, withdraw it's funds and update the state. """ hashlock = sha3(secret) if not self.our_state.balance_proof.is_known(hashlock): msg = 'The secret doesnt withdraw any hashlock. hashlock:{} asset:{}'.format( pex(hashlock), pex(self.asset_address), ) raise ValueError(msg) lock = self.our_state.balance_proof.get_lock_by_hashlock(hashlock) if log.isEnabledFor(logging.DEBUG): log.debug( 'ASSET WITHDRAWED %s < %s asset:%s hashlock:%s lockhash:%s amount:%s', pex(self.our_state.address), pex(self.partner_state.address), pex(self.asset_address), pex(hashlock), pex(sha3(lock.as_bytes)), lock.amount, ) self.our_state.release_lock(self.partner_state, secret)
def test_registry(state, registry, events): asset_address1 = sha3('asset')[:20] asset_address2 = sha3('address')[:20] unregistered_address = sha3('mainz')[:20] contract_address1 = registry.addAsset(asset_address1) contract_address2 = registry.addAsset(asset_address2) with pytest.raises(TransactionFailed): registry.addAsset(asset_address1) channel_manager_address = registry.channelManagerByAsset(asset_address1) assert channel_manager_address == contract_address1 with pytest.raises(TransactionFailed): registry.channelManagerByAsset(unregistered_address) addresses = registry.assetAddresses() assert len(addresses) == 2 assert addresses[0] == asset_address1.encode('hex') assert addresses[1] == asset_address2.encode('hex') assert len(events) == 2 assert events[0]['_event_type'] == 'AssetAdded' assert events[0]['assetAddress'] == asset_address1.encode('hex') assert events[0]['channelManagerAddress'] == contract_address1 assert events[1]['_event_type'] == 'AssetAdded' assert events[1]['assetAddress'] == asset_address2.encode('hex') assert events[1]['channelManagerAddress'] == contract_address2
def make_signed_transfer_from_counter(counter): lock = Lock( amount=next(counter), expiration=next(counter), secrethash=sha3(factories.make_secret(next(counter))), ) signed_transfer = factories.make_signed_transfer( amount=next(counter), initiator=factories.make_address(), target=factories.make_address(), expiration=next(counter), secret=factories.make_secret(next(counter)), payment_identifier=next(counter), message_identifier=next(counter), nonce=next(counter), transferred_amount=next(counter), locked_amount=next(counter), locksroot=sha3(lock.as_bytes), recipient=factories.make_address(), channel_identifier=next(counter), token_network_address=factories.make_address(), token=factories.make_address(), pkey=factories.HOP1_KEY, sender=factories.HOP1, ) return signed_transfer
def secret_request_with_wrong_secrethash(self, previous_action, secret): assume(sha3(secret) != sha3(previous_action.transfer.secret)) self._assume_channel_opened(previous_action) transfer = deepcopy(previous_action.transfer) transfer.secret = secret action = self._receive_secret_request(transfer) return self._unauthentic_secret_request(action)
def test_settlement(raiden_network, settle_timeout): app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking setup_messages_cb() asset_manager0 = app0.raiden.managers_by_asset_address.values()[0] asset_manager1 = app1.raiden.managers_by_asset_address.values()[0] chain0 = app0.raiden.chain channel0 = asset_manager0.partneraddress_channel[app1.raiden.address] channel1 = asset_manager1.partneraddress_channel[app0.raiden.address] balance0 = channel0.balance balance1 = channel1.balance amount = 10 expiration = 5 secret = 'secret' hashlock = sha3(secret) assert app1.raiden.address in asset_manager0.partneraddress_channel assert asset_manager0.asset_address == asset_manager1.asset_address assert channel0.external_state.netting_channel.address == channel1.external_state.netting_channel.address transfermessage = channel0.create_lockedtransfer(amount, expiration, hashlock) app0.raiden.sign(transfermessage) channel0.register_transfer(transfermessage) channel1.register_transfer(transfermessage) assert_synched_channels( channel0, balance0, [transfermessage.lock], channel1, balance1, [] ) # Bob learns the secret, but Alice did not send a signed updated balance to # reflect this Bob wants to settle # get proof, that locked transfermessage was in merkle tree, with locked.root merkle_proof = channel1.our_state.locked.get_proof(transfermessage) root = channel1.our_state.locked.root assert check_proof(merkle_proof, root, sha3(transfermessage.lock.as_bytes)) channel0.external_state.netting_channel.close( app0.raiden.address, transfermessage, None, ) unlocked = [(merkle_proof, transfermessage.lock.as_bytes, secret)] channel0.external_state.netting_channel.unlock( app0.raiden.address, unlocked, ) for _ in range(settle_timeout): chain0.next_block() channel0.external_state.netting_channel.settle()
def test_locked_transfer(): apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1) a0, a1 = apps c0 = a0.raiden.assetmanagers.values()[0].channels.values()[0] c1 = a1.raiden.assetmanagers.values()[0].channels.values()[0] b0, b1 = c0.balance, c1.balance amount = 10 secret = 'secret' expiration = a0.raiden.chain.block_number + 100 hashlock = sha3(secret) t = c0.create_lockedtransfer(amount=amount, expiration=expiration, hashlock=hashlock) c0.raiden.sign(t) c0.register_transfer(t) c1.register_transfer(t) assert hashlock in c1.locked assert hashlock in c0.partner.locked assert len(c0.locked) == 0 assert len(c0.partner.locked) == 1 assert len(c1.locked) == 1 assert len(c1.partner.locked) == 0 assert c0.balance == b0 assert c0.distributable == c0.balance - amount assert c1.balance == c1.distributable == b1 assert c0.locked.outstanding == 0 assert c0.partner.locked.outstanding == amount assert c1.locked.outstanding == amount assert c1.partner.locked.outstanding == 0 assert c0.locked.root == '' assert c1.partner.locked.root == '' assert c1.locked.root == merkleroot( [sha3(tx.lock.asstring) for tx in c1.locked.locked.values()]) assert c0.partner.locked.root == c1.locked.root # reveal secret c0.claim_locked(secret) c1.claim_locked(secret) assert c0.balance == b0 - amount assert c0.distributable == c0.balance assert c1.balance == c1.distributable == b1 + amount assert c0.locked.outstanding == 0 assert c0.partner.locked.outstanding == 0 assert c1.locked.outstanding == 0 assert c1.partner.locked.outstanding == 0 assert len(c0.locked) == 0 assert len(c0.partner.locked) == 0 assert len(c1.locked) == 0 assert len(c1.partner.locked) == 0 assert c0.locked.root == '' assert c1.partner.locked.root == '' assert c1.locked.root == '' assert c0.partner.locked.root == ''
def generate_accounts(seeds): """Create private keys and addresses for all seeds. """ return { seed: dict( privatekey=encode_hex(sha3(seed)), address=encode_hex(privatekey_to_address(sha3(seed))) ) for seed in seeds}
def test_settle_with_locked_mediated_transfer_for_counterparty( deposit, settle_timeout, reveal_timeout, tester_chain, tester_channels, tester_token): """ Test settle with a locked mediated transfer for the counter party. """ pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0] address0 = privatekey_to_address(pkey0) address1 = privatekey_to_address(pkey1) initial0 = tester_token.balanceOf(address0, sender=pkey0) initial1 = tester_token.balanceOf(address1, sender=pkey0) transferred_amount0 = 30 increase_transferred_amount(channel0, channel1, transferred_amount0) expiration0 = tester_chain.block.number + reveal_timeout + 5 new_block = Block(tester_chain.block.number) channel0.state_transition(new_block) channel1.state_transition(new_block) lock0 = Lock(amount=29, expiration=expiration0, hashlock=sha3(b'lock1')) mediated0 = make_mediated_transfer( channel0, channel1, address0, address1, lock0, pkey0, tester_chain.block.number, ) nettingchannel.close(sender=pkey0) mediated0_hash = sha3(mediated0.packed().data[:-65]) nettingchannel.updateTransfer( mediated0.nonce, mediated0.transferred_amount, mediated0.locksroot, mediated0_hash, mediated0.signature, sender=pkey1, ) tester_chain.mine(number_of_blocks=settle_timeout + 1) nettingchannel.settle(sender=pkey1) # the balances only change by transferred_amount because the lock was /not/ unlocked balance0 = initial0 + deposit - transferred_amount0 balance1 = initial1 + transferred_amount0 assert tester_token.balanceOf(nettingchannel.address, sender=pkey0) == 0 assert tester_token.balanceOf(address0, sender=pkey0) == balance0 assert tester_token.balanceOf(address1, sender=pkey0) == balance1
def make_signed_transfer( amount, initiator, target, expiration, secret, payment_identifier=1, message_identifier=None, nonce=1, transferred_amount=0, locked_amount=None, locksroot=EMPTY_MERKLE_ROOT, recipient=UNIT_TRANSFER_TARGET, channel_identifier=UNIT_CHANNEL_ID, token=UNIT_TOKEN_ADDRESS, pkey=UNIT_TRANSFER_PKEY, sender=UNIT_TRANSFER_SENDER, ): if message_identifier is None: message_identifier = random.randint(0, UINT64_MAX) secrethash = sha3(secret) lock = Lock( amount, expiration, secrethash, ) if locksroot == EMPTY_MERKLE_ROOT: locksroot = sha3(lock.as_bytes) if locked_amount is None: locked_amount = amount else: assert locked_amount >= amount transfer = LockedTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=message_identifier, payment_identifier=payment_identifier, nonce=nonce, token_network_address=UNIT_TOKEN_NETWORK_ADDRESS, token=token, channel_identifier=channel_identifier, transferred_amount=transferred_amount, locked_amount=locked_amount, recipient=recipient, locksroot=locksroot, lock=lock, target=target, initiator=initiator, ) transfer.sign(pkey) assert transfer.sender == sender return lockedtransfersigned_from_message(transfer)
def test_compute_layers_duplicated(): hash_0 = sha3(b'x') hash_1 = sha3(b'y') with pytest.raises(ValueError): compute_layers([hash_0, hash_0]) with pytest.raises(ValueError): compute_layers([hash_0, hash_1, hash_0])
def transfer_speed(num_transfers=100, max_locked=100): # pylint: disable=too-many-locals channels_per_node = 1 deposit = 100 num_nodes = 2 num_assets = 1 private_keys = [ sha3('speed:{}'.format(position)) for position in range(num_nodes) ] assets = [ sha3('asset:{}'.format(number))[:20] for number in range(num_assets) ] apps = create_network( private_keys, assets, MOCK_REGISTRY_ADDRESS, channels_per_node, deposit, DEFAULT_SETTLE_TIMEOUT, UDPTransport, BlockChainServiceMock ) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.assetmanagers.values()[0].channels.values()[0] channel1 = app1.raiden.assetmanagers.values()[0].channels.values()[0] amounts = [a % 100 + 1 for a in range(1, num_transfers + 1)] secrets = [str(i) for i in range(num_transfers)] expiration = app0.raiden.chain.block_number + 100 start = time.time() for i, amount in enumerate(amounts): hashlock = sha3(secrets[i]) locked_transfer = channel0.create_lockedtransfer( amount=amount, expiration=expiration, hashlock=hashlock, ) app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) if i > max_locked: idx = i - max_locked secret = secrets[idx] channel0.claim_locked(secret) channel1.claim_locked(secret) elapsed = time.time() - start print('%d transfers per second' % (num_transfers / elapsed))
def generate_accounts(seeds): """Create private keys and addresses for all seeds. """ return { seed: { 'privatekey': encode_hex(sha3(seed)), 'address': encode_hex(privatekey_to_address(sha3(seed))), } for seed in seeds }
def test_ack(): echo = sha3(privkey) msg = Ack(address, echo) assert msg.echo == echo d = msg.encode() msghash = sha3(d) msg2 = decode(d) assert msg2.echo == echo assert msg2.sender == address assert sha3(msg2.encode()) == msghash
def test_ack(): echo = sha3(PRIVKEY) ack = Ack(ADDRESS, echo) assert ack.echo == echo data = ack.encode() msghash = sha3(data) decoded_ack = decode(data) assert decoded_ack.echo == ack.echo assert decoded_ack.sender == ack.sender assert sha3(decoded_ack.encode()) == msghash
def pending_mediated_transfer(app_chain, token, amount, identifier, expiration): """ Nice to read shortcut to make a MediatedTransfer were the secret is _not_ revealed. While the secret is not revealed all apps will be synchronized, meaning they are all going to receive the MediatedTransfer message. Returns: The secret used to generate the MediatedTransfer """ # pylint: disable=too-many-locals if len(app_chain) < 2: raise ValueError('Cannot make a MediatedTransfer with less than two apps') fee = 0 secret = None hashlock = None initiator_app = app_chain[0] target_app = app_chain[0] for from_app, to_app in zip(app_chain[:-1], app_chain[1:]): from_channel = channel(from_app, to_app, token) to_channel = channel(to_app, from_app, token) # use the initiator channel to generate a secret if secret is None: address = from_channel.external_state.netting_channel.address nonce = str(from_channel.our_state.nonce) secret = sha3(address + nonce.encode()) hashlock = sha3(secret) transfer_ = from_channel.create_mediatedtransfer( initiator_app.raiden.address, target_app.raiden.address, fee, amount, identifier, expiration, hashlock, ) from_app.raiden.sign(transfer_) from_channel.register_transfer( from_app.raiden.get_block_number(), transfer_, ) to_channel.register_transfer( to_app.raiden.get_block_number(), transfer_, ) return secret
def test_locked_transfer(iterations=ITERATIONS): amount = 1 expiration = 1 hashlock = sha3(ADDRESS) lock = Lock(amount, expiration, hashlock) nonce = 1 asset = ADDRESS balance = 1 recipient = ADDRESS locksroot = sha3(ADDRESS) msg = LockedTransfer(nonce, asset, balance, recipient, locksroot, lock).sign(PRIVKEY) run_timeit('LockedTransfer', msg, iterations=iterations)
def test_event_operators(): a = EventPaymentSentSuccess(1, 4, 2, 5, sha3(b'target')) b = EventPaymentSentSuccess(1, 4, 2, 5, sha3(b'target')) c = EventPaymentSentSuccess(2, 7, 3, 4, sha3(b'target')) d = EventPaymentSentSuccess(2, 7, 3, 4, sha3(b'differenttarget')) # 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 test_event_operators(): a = EventTransferSentSuccess(2, 5, sha3(b'target')) b = EventTransferSentSuccess(2, 5, sha3(b'target')) c = EventTransferSentSuccess(3, 4, sha3(b'target')) d = EventTransferSentSuccess(3, 4, sha3(b'differenttarget')) assert a == b assert not a != b assert a != c assert not a == c assert not c == d a = EventTransferSentFailed(2, 'BECAUSE') b = EventTransferSentFailed(2, 'BECAUSE') c = EventTransferSentFailed(3, 'UNKNOWN') assert a == b assert not a != b assert a != c assert not a == c a = EventTransferReceivedSuccess(2, 5, sha3(b'initiator')) b = EventTransferReceivedSuccess(2, 5, sha3(b'initiator')) c = EventTransferReceivedSuccess(3, 5, sha3(b'initiator')) d = EventTransferReceivedSuccess(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 test_withdraw_twice(reveal_timeout, tester_channels, tester_chain): """ A lock can be withdrawn only once, the second try must fail. """ pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0] lock_expiration = tester_chain.block.number + reveal_timeout + 5 secret = b'secretsecretsecretsecretsecretse' new_block = Block(tester_chain.block.number) channel0.state_transition(new_block) channel1.state_transition(new_block) lock = Lock(17, lock_expiration, sha3(secret)) mediated0 = make_mediated_transfer( channel1, channel0, privatekey_to_address(pkey1), privatekey_to_address(pkey0), lock, pkey1, tester_chain.block.number, secret, ) mediated0_hash = sha3(mediated0.packed().data[:-65]) nettingchannel.close( mediated0.nonce, mediated0.transferred_amount, mediated0.locksroot, mediated0_hash, mediated0.signature, sender=pkey0, ) unlock_proofs = list(channel0.partner_state.get_known_unlocks()) proof = unlock_proofs[0] nettingchannel.withdraw( proof.lock_encoded, b''.join(proof.merkle_proof), proof.secret, sender=pkey0, ) with pytest.raises(TransactionFailed): nettingchannel.withdraw( proof.lock_encoded, b''.join(proof.merkle_proof), proof.secret, sender=pkey0, )
def test_automatic_secret_registration(raiden_chain, token_addresses): app0, app1 = raiden_chain token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) amount = 100 identifier = 1 hold_event_handler = HoldOffChainSecretRequest() app1.raiden.raiden_event_handler = hold_event_handler target = app1.raiden.address secret = sha3(target) secrethash = sha3(secret) hold_event_handler.hold_secretrequest_for(secrethash=secrethash) app0.raiden.start_mediated_transfer_with_secret( token_network_identifier, amount, target, identifier, secret, ) gevent.sleep(1) # wait for the messages to be exchanged # Stop app0 to avoid sending the unlock app0.raiden.transport.stop() reveal_secret = RevealSecret( random.randint(0, UINT64_MAX), secret, ) app0.raiden.sign(reveal_secret) message_handler.MessageHandler().on_message(app1.raiden, reveal_secret) chain_state = views.state_from_app(app1) secrethash = sha3(secret) target_task = chain_state.payment_mapping.secrethashes_to_task[secrethash] lock_expiration = target_task.target_state.transfer.lock.expiration wait_until_block(app1.raiden.chain, lock_expiration) assert app1.raiden.default_secret_registry.check_registered(secrethash)
def test_processed(): message_identifier = random.randint(0, constants.UINT64_MAX) processed_message = Processed(message_identifier) processed_message.sign(PRIVKEY) assert processed_message.sender == ADDRESS assert processed_message.message_identifier == message_identifier data = processed_message.encode() decoded_processed_message = decode(data) assert decoded_processed_message.message_identifier == message_identifier assert processed_message.message_identifier == message_identifier assert decoded_processed_message.sender == processed_message.sender assert sha3(decoded_processed_message.encode()) == sha3(data)
def mk_app(chain, discovery, transport_class, port, host='127.0.0.1'): ''' Instantiates an Raiden app with the given configuration. ''' config = copy.deepcopy(App.default_config) config['port'] = port config['host'] = host config['privkey'] = sha3('{}:{}'.format(host, config['port'])) return App(config, chain, discovery, transport_class)
def hostport_to_privkeyaddr(host, port): """ Return `(private key, address)` deterministically generated. """ myip_port = '{}:{}'.format(host, port) privkey = sha3(myip_port.encode()) addr = privatekey_to_address(privkey) return privkey, addr
def register_secret(self, secret: bytes): """ Register the secret with any channel that has a hashlock on it. This must search through all channels registered for a given hashlock and ignoring the tokens. Useful for refund transfer, split transfer, and token swaps. Raises: TypeError: If secret is unicode data. """ if not isinstance(secret, bytes): raise TypeError('secret must be bytes') hashlock = sha3(secret) revealsecret_message = RevealSecret(secret) self.sign(revealsecret_message) for hash_channel in self.token_to_hashlock_to_channels.values(): for channel in hash_channel[hashlock]: channel.register_secret(secret) # The protocol ignores duplicated messages. self.send_async( channel.partner_state.address, revealsecret_message, )
def test_end_state(): netting_channel = NettingChannelMock() token_address = make_address() privkey1, address1 = make_privkey_address() address2 = make_address() balance1 = 70 balance2 = 110 lock_secret = sha3('test_end_state') lock_amount = 30 lock_expiration = 10 lock_hashlock = sha3(lock_secret) state1 = ChannelEndState(address1, balance1, netting_channel.opened()) state2 = ChannelEndState(address2, balance2, netting_channel.opened()) assert state1.contract_balance == balance1 assert state2.contract_balance == balance2 assert state1.balance(state2) == balance1 assert state2.balance(state1) == balance2 assert state1.distributable(state2) == balance1 assert state2.distributable(state1) == balance2 assert state1.locked() == 0 assert state2.locked() == 0 assert state1.balance_proof.is_pending(lock_hashlock) is False assert state2.balance_proof.is_pending(lock_hashlock) is False assert state1.balance_proof.merkleroot_for_unclaimed() == '' assert state2.balance_proof.merkleroot_for_unclaimed() == '' lock = Lock( lock_amount, lock_expiration, lock_hashlock, ) lock_hash = sha3(lock.as_bytes) transferred_amount = 0 locksroot = state2.compute_merkleroot_with(lock) locked_transfer = LockedTransfer( 1, # TODO: fill in identifier nonce=state1.nonce, token=token_address, transferred_amount=transferred_amount, recipient=state2.address, locksroot=locksroot, lock=lock, ) transfer_target = make_address() transfer_initiator = make_address() fee = 0 mediated_transfer = locked_transfer.to_mediatedtransfer( transfer_target, transfer_initiator, fee, ) mediated_transfer.sign(privkey1, address1) state2.register_locked_transfer(mediated_transfer) assert state1.contract_balance == balance1 assert state2.contract_balance == balance2 assert state1.balance(state2) == balance1 assert state2.balance(state1) == balance2 assert state1.distributable(state2) == balance1 - lock_amount assert state2.distributable(state1) == balance2 assert state1.locked() == 0 assert state2.locked() == lock_amount assert state1.balance_proof.is_pending(lock_hashlock) is False assert state2.balance_proof.is_pending(lock_hashlock) is True assert state1.balance_proof.merkleroot_for_unclaimed() == '' assert state2.balance_proof.merkleroot_for_unclaimed() == lock_hash with pytest.raises(ValueError): state1.update_contract_balance(balance1 - 10) state1.update_contract_balance(balance1 + 10) assert state1.contract_balance == balance1 + 10 assert state2.contract_balance == balance2 assert state1.balance(state2) == balance1 + 10 assert state2.balance(state1) == balance2 assert state1.distributable(state2) == balance1 - lock_amount + 10 assert state2.distributable(state1) == balance2 assert state1.locked() == 0 assert state2.locked() == lock_amount assert state1.balance_proof.is_pending(lock_hashlock) is False assert state2.balance_proof.is_pending(lock_hashlock) is True assert state1.balance_proof.merkleroot_for_unclaimed() == '' assert state2.balance_proof.merkleroot_for_unclaimed() == lock_hash # registering the secret should not change the locked amount state2.register_secret(lock_secret) assert state1.contract_balance == balance1 + 10 assert state2.contract_balance == balance2 assert state1.balance(state2) == balance1 + 10 assert state2.balance(state1) == balance2 assert state1.distributable(state2) == balance1 - lock_amount + 10 assert state2.distributable(state1) == balance2 assert state1.locked() == 0 assert state2.locked() == lock_amount assert state1.balance_proof.is_pending(lock_hashlock) is False assert state2.balance_proof.is_pending(lock_hashlock) is False assert state1.balance_proof.merkleroot_for_unclaimed() == '' assert state2.balance_proof.merkleroot_for_unclaimed() == lock_hash state2.release_lock(state1, lock_secret) assert state1.contract_balance == balance1 + 10 assert state2.contract_balance == balance2 assert state1.balance(state2) == balance1 + 10 - lock_amount assert state2.balance(state1) == balance2 + lock_amount assert state1.distributable(state2) == balance1 + 10 - lock_amount assert state2.distributable(state1) == balance2 + lock_amount assert state1.locked() == 0 assert state2.locked() == 0 assert state1.balance_proof.is_pending(lock_hashlock) is False assert state2.balance_proof.is_pending(lock_hashlock) is False assert state1.balance_proof.merkleroot_for_unclaimed() == '' assert state2.balance_proof.merkleroot_for_unclaimed() == ''
GenesisDescription, run_private_blockchain, ) from raiden.utils import privatekey_to_address, sha3 from raiden_contracts.constants import NETWORKNAME_TO_ID NUM_GETH_NODES = 3 NUM_RAIDEN_ACCOUNTS = 10 START_PORT = 30301 START_RPCPORT = 8101 DEFAULT_ACCOUNTS_SEEDS = [ "127.0.0.1:{}".format(START_PORT + i).encode() for i in range(NUM_RAIDEN_ACCOUNTS) ] DEFAULT_ACCOUNTS_KEYS = [sha3(seed) for seed in DEFAULT_ACCOUNTS_SEEDS] DEFAULT_ACCOUNTS = [privatekey_to_address(key) for key in DEFAULT_ACCOUNTS_KEYS] def main(): tmpdir = tempfile.mkdtemp() geth_nodes = [] for i in range(NUM_GETH_NODES): is_miner = i == 0 node_key = sha3(f"node:{i}".encode()) p2p_port = START_PORT + i rpc_port = START_RPCPORT + i description = EthNodeDescription( private_key=node_key,
def main(): import argparse parser = argparse.ArgumentParser() parser.add_argument('--transfers', default=100, type=int) parser.add_argument('--nodes', default=10, type=int) parser.add_argument('--tokens', default=1, type=int) parser.add_argument('--channels-per-node', default=2, type=int) parser.add_argument('-p', '--profile', default=False, action='store_true') parser.add_argument('--pdb', default=False, action='store_true') parser.add_argument('--throughput', dest='throughput', action='store_true', default=True) parser.add_argument('--latency', dest='throughput', action='store_false') parser.add_argument('--log', action='store_true', default=False) args = parser.parse_args() if args.log: slogging.configure(':DEBUG') if args.profile: import GreenletProfiler GreenletProfiler.set_clock_type('cpu') GreenletProfiler.start() tokens = [ sha3('token:{}'.format(number).encode())[:20] for number in range(args.tokens) ] amount = 10 apps = setup_apps( amount, tokens, args.transfers, args.nodes, args.channels_per_node, ) if args.pdb: from raiden.utils.debug import enable_greenlet_debugger enable_greenlet_debugger() try: if args.throughput: test_throughput(apps, tokens, args.transfers, amount) else: test_latency(apps, tokens, args.transfers, amount) except: # noqa import pdb pdb.xpm() else: if args.throughput: test_throughput(apps, tokens, args.transfers, amount) else: test_latency(apps, tokens, args.transfers, amount) if args.profile: GreenletProfiler.stop() stats = GreenletProfiler.get_func_stats() pstats = GreenletProfiler.convert2pstats(stats) print_serialization(pstats) print_slow_path(pstats) print_slow_function(pstats) pstats.sort_stats('time').print_stats()
def test_settled_lock(tokens_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 = tokens_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, token, amount, identifier, expiration, ) hashlock = sha3(secret) # get a proof for the pending transfer back_channel = channel(app1, app0, token) 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) forward_channel = channel(app0, app1, token) 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, ) # 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.partner_state.get_lock_by_hashlock(hashlock) unlock_proof = attack_channel.partner_state.compute_proof_for_lock( secret, lock) # start the settle counter attack_balance_proof = attack_transfer.to_balanceproof() attack_channel.netting_channel.close(attack_balance_proof) # 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_interwoven_transfers(number_of_transfers, raiden_network, settle_timeout): """ Can keep doing transactions even if not all secrets have been released. """ def log_state(): unclaimed = [ transfer.lock.amount for pos, transfer in enumerate(transfers_list) if not transfers_claimed[pos] ] claimed = [ transfer.lock.amount for pos, transfer in enumerate(transfers_list) if transfers_claimed[pos] ] log.info( 'interwoven', claimed_amount=claimed_amount, distributed_amount=distributed_amount, claimed=claimed, unclaimed=unclaimed, ) app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking graph0 = app0.raiden.channelgraphs.values()[0] graph1 = app1.raiden.channelgraphs.values()[0] channel0 = graph0.partneraddress_channel.values()[0] channel1 = graph1.partneraddress_channel.values()[0] contract_balance0 = channel0.contract_balance contract_balance1 = channel1.contract_balance unclaimed_locks = [] transfers_list = [] transfers_claimed = [] # start at 1 because we can't use amount=0 transfers_amount = [i for i in range(1, number_of_transfers + 1)] transfers_secret = [str(i) for i in range(number_of_transfers)] claimed_amount = 0 distributed_amount = 0 for i, (amount, secret) in enumerate(zip(transfers_amount, transfers_secret)): block_number = app0.raiden.chain.block_number() expiration = block_number + settle_timeout - 1 mediated_transfer = channel0.create_mediatedtransfer( transfer_initiator=app0.raiden.address, transfer_target=app1.raiden.address, fee=0, amount=amount, identifier=1, expiration=expiration, hashlock=sha3(secret), ) # synchronized registration app0.raiden.sign(mediated_transfer) channel0.register_transfer(mediated_transfer) channel1.register_transfer(mediated_transfer) # update test state distributed_amount += amount transfers_claimed.append(False) transfers_list.append(mediated_transfer) unclaimed_locks.append(mediated_transfer.lock) log_state() # test the synchronization and values assert_synched_channels( channel0, contract_balance0 - claimed_amount, [], channel1, contract_balance1 + claimed_amount, unclaimed_locks, ) assert channel0.distributable == contract_balance0 - distributed_amount # claim a transaction at every other iteration, leaving the current one # in place if i > 0 and i % 2 == 0: transfer = transfers_list[i - 1] secret = transfers_secret[i - 1] # synchronized clamining channel0.release_lock(secret) channel1.withdraw_lock(secret) # update test state claimed_amount += transfer.lock.amount transfers_claimed[i - 1] = True unclaimed_locks = [ unclaimed_transfer.lock for pos, unclaimed_transfer in enumerate(transfers_list) if not transfers_claimed[pos] ] log_state() # test the state of the channels after the claim assert_synched_channels( channel0, contract_balance0 - claimed_amount, [], channel1, contract_balance1 + claimed_amount, unclaimed_locks, ) assert channel0.distributable == contract_balance0 - distributed_amount
def secrethash(self): return sha3(self.secret)
def run_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_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token ) 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 = sha3(target) secrethash = sha3(secret) hold_event_handler.hold_secretrequest_for(secrethash=secrethash) app0.raiden.start_mediated_transfer_with_secret( token_network_identifier=token_network_identifier, amount=amount, fee=0, target=target, identifier=identifier, payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE, secret=secret, ) gevent.sleep(1) # wait for the messages to be exchanged attack_channel = get_channelstate(app2, app1, token_network_identifier) attack_transfer = None # TODO attack_contract = attack_channel.external_state.netting_channel.address hub_contract = get_channelstate( app1, app0, token_network_identifier ).external_state.netting_channel.address # the attacker can create a merkle proof of the locked transfer # <the commented code below is left for documentation purposes> # lock = attack_channel.partner_state.get_lock_by_secrethash(secrethash) # unlock_proof = attack_channel.partner_state.compute_proof_for_lock(secret, lock) # start the settle counter attack_balance_proof = attack_transfer.to_balanceproof() attack_channel.netting_channel.channel_close(attack_balance_proof) # wait until the last block to reveal the secret, hopefully we are not # missing a block during the test app2.raiden.chain.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.chain.next_block() attack_channel.netting_channel.settle(token, attack_contract) # at this point the attacker 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. 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.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 run_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_identifier = views.get_token_network_identifier_by_token_address( chain_state=views.state_from_app(alice_app), payment_network_id=alice_app.raiden.default_registry.address, token_address=token_address, ) timeout = 10 token_network = views.get_token_network_by_identifier( chain_state=views.state_from_app(alice_app), token_network_id=token_network_identifier ) channel_identifier = get_channelstate(alice_app, bob_app, token_network_identifier).identifier assert ( channel_identifier in token_network.partneraddresses_to_channelidentifiers[bob_app.raiden.address] ) alice_to_bob_amount = 10 identifier = 1 alice_transfer_secret = sha3(alice_app.raiden.address) alice_transfer_secrethash = sha3(alice_transfer_secret) bob_transfer_secret = sha3(bob_app.raiden.address) bob_transfer_secrethash = sha3(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_identifier=token_network_identifier, amount=alice_to_bob_amount, fee=0, target=bob_app.raiden.address, identifier=identifier, payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE, secret=alice_transfer_secret, ) bob_app.raiden.start_mediated_transfer_with_secret( token_network_identifier=token_network_identifier, amount=alice_to_bob_amount, fee=0, target=alice_app.raiden.address, identifier=identifier + 1, payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE, 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_identifier) 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) # This is the current state of protocol: # # A -> B LockedTransfer # - protocol didn't continue assert_synced_channel_state( token_network_identifier=token_network_identifier, 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, payment_network_id=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_identifier, "channel_identifier": alice_bob_channel_state.identifier, } }, ) settle_max_wait_block = ( 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, payment_network_id=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_id=token_network_identifier, participant=alice_bob_channel_state.partner_state.address, partner=alice_bob_channel_state.our_state.address, ) alice_app.start() with gevent.Timeout(timeout): wait_for_batch_unlock( app=alice_app, token_network_id=token_network_identifier, participant=alice_bob_channel_state.partner_state.address, partner=alice_bob_channel_state.our_state.address, )
def run_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 = 30 token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_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.chain.token(token_address) initial_balance0 = token_proxy.balance_of(address0) initial_balance1 = token_proxy.balance_of(address1) identifier = 1 target = app1.raiden.address secret = sha3(target) secrethash = sha3(secret) secret_available = hold_event_handler.hold_secretrequest_for(secrethash=secrethash) app0.raiden.start_mediated_transfer_with_secret( token_network_identifier=token_network_identifier, amount=amount, fee=0, target=target, identifier=identifier, payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE, secret=secret, ) secret_available.wait() # wait for the messages to be exchanged # Save the merkle tree leaves from the pending transfer, used to test the unlock channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier) 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=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, ) netting_channel = app1.raiden.chain.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( merkle_tree_leaves=batch_unlock, participant=channelstate_0_1.our_state.address, partner=channelstate_0_1.partner_state.address, ) 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 run_test_batch_unlock( raiden_network, token_addresses, secret_registry_address, deposit, blockchain_type ): """Batch unlock can be called after the channel is settled.""" alice_app, bob_app = raiden_network registry_address = alice_app.raiden.default_registry.address token_address = token_addresses[0] token_proxy = alice_app.raiden.chain.token(token_address) token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(alice_app), alice_app.raiden.default_registry.address, token_address ) hold_event_handler = bob_app.raiden.raiden_event_handler # Take a snapshot early on alice_app.raiden.wal.snapshot() token_network = views.get_token_network_by_identifier( views.state_from_app(alice_app), token_network_identifier ) channel_identifier = get_channelstate(alice_app, bob_app, token_network_identifier).identifier assert ( channel_identifier in token_network.partneraddresses_to_channelidentifiers[bob_app.raiden.address] ) alice_initial_balance = token_proxy.balance_of(alice_app.raiden.address) bob_initial_balance = token_proxy.balance_of(bob_app.raiden.address) # Take snapshot before transfer alice_app.raiden.wal.snapshot() alice_to_bob_amount = 10 identifier = 1 target = bob_app.raiden.address secret = sha3(target) secrethash = sha3(secret) secret_request_event = hold_event_handler.hold_secretrequest_for(secrethash=secrethash) alice_app.raiden.start_mediated_transfer_with_secret( token_network_identifier=token_network_identifier, amount=alice_to_bob_amount, fee=0, target=target, identifier=identifier, payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE, secret=secret, ) secret_request_event.get() # wait for the messages to be exchanged alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier) lock = channel.get_lock(alice_bob_channel_state.our_state, secrethash) # This is the current state of the protocol: # # A -> B LockedTransfer # B -> A SecretRequest # - protocol didn't continue assert_synced_channel_state( token_network_identifier, alice_app, deposit, [lock], bob_app, deposit, [] ) # Take a snapshot early on alice_app.raiden.wal.snapshot() our_balance_proof = alice_bob_channel_state.our_state.balance_proof # Test WAL restore to return the latest channel state restored_channel_state = channel_state_until_state_change( raiden=alice_app.raiden, canonical_identifier=alice_bob_channel_state.canonical_identifier, state_change_identifier="latest", ) our_restored_balance_proof = restored_channel_state.our_state.balance_proof assert our_balance_proof == our_restored_balance_proof # 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, token_address, alice_app.raiden.address ) secret_registry_proxy = alice_app.raiden.chain.secret_registry(secret_registry_address) secret_registry_proxy.register_secret(secret=secret) assert lock, "the lock must still be part of the node state" msg = "the secret must be registered before the lock expires" assert lock.expiration > alice_app.raiden.get_block_number(), msg assert lock.secrethash == sha3(secret) waiting.wait_for_settle( alice_app.raiden, registry_address, token_address, [alice_bob_channel_state.identifier], alice_app.raiden.alarm.sleep_time, ) token_network = views.get_token_network_by_identifier( views.state_from_app(bob_app), token_network_identifier ) assert ( channel_identifier in token_network.partneraddresses_to_channelidentifiers[alice_app.raiden.address] ) # Wait for both nodes to call batch unlock timeout = 30 if blockchain_type == "parity" else 10 with gevent.Timeout(timeout): wait_for_batch_unlock( app=bob_app, token_network_id=token_network_identifier, participant=alice_bob_channel_state.partner_state.address, partner=alice_bob_channel_state.our_state.address, ) token_network = views.get_token_network_by_identifier( views.state_from_app(bob_app), token_network_identifier ) assert ( channel_identifier not in token_network.partneraddresses_to_channelidentifiers[alice_app.raiden.address] ) alice_new_balance = alice_initial_balance + deposit - alice_to_bob_amount bob_new_balance = bob_initial_balance + deposit + alice_to_bob_amount assert token_proxy.balance_of(alice_app.raiden.address) == alice_new_balance assert token_proxy.balance_of(bob_app.raiden.address) == bob_new_balance
def test_regression_multiple_revealsecret(raiden_network, token_addresses): """ Multiple RevealSecret messages arriving at the same time must be handled properly. Secret handling followed these steps: The Secret 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 hashlock The step marked with an asterisk above introduced a context-switch, this allowed a second Reveal Secret message to be handled before the channel was unregistered, because the channel was already updated an exception was raised for an unknown secret. """ app0, app1 = raiden_network token = token_addresses[0] identifier = 1 secret = sha3('test_regression_multiple_revealsecret') hashlock = sha3(secret) expiration = app0.raiden.get_block_number() + 100 amount = 10 mediated_transfer = channel(app0, app1, token).create_mediatedtransfer( transfer_initiator=app0.raiden.address, transfer_target=app1.raiden.address, fee=0, amount=amount, identifier=identifier, expiration=expiration, hashlock=hashlock, ) app0.raiden.sign(mediated_transfer) message_data = mediated_transfer.encode() app1.raiden.protocol.receive(message_data) reveal_secret = RevealSecret(secret) app0.raiden.sign(reveal_secret) reveal_secret_data = reveal_secret.encode() secret = Secret( identifier=identifier, nonce=mediated_transfer.nonce + 1, channel=channel(app0, app1, token).channel_address, transferred_amount=amount, locksroot=EMPTY_MERKLE_ROOT, secret=secret, ) app0.raiden.sign(secret) secret_data = secret.encode() messages = [ secret_data, reveal_secret_data, ] wait = [ gevent.spawn_later( .1, app1.raiden.protocol.receive, data, ) for data in messages ] gevent.joinall(wait)
def hashlock(self): if self._hashlock is None: self._hashlock = sha3(self.secret) return self._hashlock
def hash(self): packed = self.packed() return sha3(packed.data)
def test_settlement(raiden_network, settle_timeout, reveal_timeout): alice_app, bob_app = raiden_network # pylint: disable=unbalanced-tuple-unpacking setup_messages_cb() alice_graph = alice_app.raiden.token_to_channelgraph.values()[0] bob_graph = bob_app.raiden.token_to_channelgraph.values()[0] assert alice_graph.token_address == bob_graph.token_address alice_bob_channel = alice_graph.partneraddress_to_channel[ bob_app.raiden.address] bob_alice_channel = bob_graph.partneraddress_to_channel[ alice_app.raiden.address] alice_deposit = alice_bob_channel.balance bob_deposit = bob_alice_channel.balance token = alice_app.raiden.chain.token(alice_bob_channel.token_address) alice_balance = token.balance_of(alice_app.raiden.address) bob_balance = token.balance_of(bob_app.raiden.address) alice_chain = alice_app.raiden.chain alice_to_bob_amount = 10 expiration = alice_app.raiden.chain.block_number() + reveal_timeout + 1 secret = 'secretsecretsecretsecretsecretse' hashlock = sha3(secret) assert bob_app.raiden.address in alice_graph.partneraddress_to_channel nettingaddress0 = alice_bob_channel.external_state.netting_channel.address nettingaddress1 = bob_alice_channel.external_state.netting_channel.address assert nettingaddress0 == nettingaddress1 identifier = 1 fee = 0 transfermessage = alice_bob_channel.create_mediatedtransfer( alice_app.raiden.address, bob_app.raiden.address, fee, alice_to_bob_amount, identifier, expiration, hashlock, ) alice_app.raiden.sign(transfermessage) alice_bob_channel.register_transfer( alice_app.raiden.get_block_number(), transfermessage, ) bob_alice_channel.register_transfer( bob_app.raiden.get_block_number(), transfermessage, ) assert_synched_channels( alice_bob_channel, alice_deposit, [], bob_alice_channel, bob_deposit, [transfermessage.lock], ) # At this point we are assuming the following: # # A -> B MediatedTransfer # B -> A SecretRequest # A -> B RevealSecret # - protocol didn't continue # # B knowns the secret but doesn't have an updated balance proof, B needs to # call settle. # get proof, that locked transfermessage was in merkle tree, with locked.root lock = bob_alice_channel.partner_state.get_lock_by_hashlock(hashlock) assert sha3(secret) == hashlock unlock_proof = bob_alice_channel.partner_state.compute_proof_for_lock( secret, lock) root = merkleroot(bob_alice_channel.partner_state.merkletree) assert validate_proof( unlock_proof.merkle_proof, root, sha3(transfermessage.lock.as_bytes), ) assert unlock_proof.lock_encoded == transfermessage.lock.as_bytes assert unlock_proof.secret == secret # a ChannelClose event will be generated, this will be polled by both apps # and each must start a task for calling settle balance_proof = transfermessage.to_balanceproof() bob_alice_channel.external_state.close(balance_proof) wait_until_block(alice_chain, alice_chain.block_number() + 1) assert alice_bob_channel.external_state.close_event.wait(timeout=15) assert bob_alice_channel.external_state.close_event.wait(timeout=15) assert alice_bob_channel.external_state.closed_block != 0 assert bob_alice_channel.external_state.closed_block != 0 assert alice_bob_channel.external_state.settled_block == 0 assert bob_alice_channel.external_state.settled_block == 0 # unlock will not be called by Channel.channel_closed because we did not # register the secret assert lock.expiration > alice_app.raiden.chain.block_number() assert lock.hashlock == sha3(secret) bob_alice_channel.external_state.netting_channel.withdraw([unlock_proof]) settle_expiration = alice_chain.block_number() + settle_timeout + 2 wait_until_block(alice_chain, settle_expiration) assert alice_bob_channel.external_state.settle_event.wait(timeout=15) assert bob_alice_channel.external_state.settle_event.wait(timeout=15) # settle must be called by the apps triggered by the ChannelClose event, # and the channels must update it's state based on the ChannelSettled event assert alice_bob_channel.external_state.settled_block != 0 assert bob_alice_channel.external_state.settled_block != 0 address0 = alice_app.raiden.address address1 = bob_app.raiden.address alice_netted_balance = alice_balance + alice_deposit - alice_to_bob_amount bob_netted_balance = bob_balance + bob_deposit + alice_to_bob_amount assert token.balance_of(address0) == alice_netted_balance assert token.balance_of(address1) == bob_netted_balance # Now let's query the WAL to see if the state changes were logged as expected state_changes = [ change[1] for change in get_all_state_changes(alice_app.raiden.transaction_log) if not isinstance(change[1], Block) ] assert must_contain_entry( state_changes, ContractReceiveClosed, { 'channel_address': nettingaddress0, 'closing_address': bob_app.raiden.address, 'block_number': alice_bob_channel.external_state.closed_block, }) assert must_contain_entry(state_changes, ReceiveSecretReveal, { 'secret': secret, 'sender': bob_app.raiden.address, }) assert must_contain_entry( state_changes, ContractReceiveWithdraw, { 'channel_address': nettingaddress0, 'secret': secret, 'receiver': bob_app.raiden.address, }) assert must_contain_entry( state_changes, ContractReceiveSettled, { 'channel_address': nettingaddress0, 'block_number': bob_alice_channel.external_state.settled_block, })
def address_from_key(key): return sha3(key[1:])[-20:]
def test_python_channel(): netting_channel = NettingChannelMock() token_address = make_address() privkey1, address1 = make_privkey_address() address2 = make_address() balance1 = 70 balance2 = 110 reveal_timeout = 5 settle_timeout = 15 block_number = 10 our_state = ChannelEndState(address1, balance1, netting_channel.opened()) partner_state = ChannelEndState(address2, balance2, netting_channel.opened()) external_state = make_external_state() test_channel = Channel( our_state, partner_state, external_state, token_address, reveal_timeout, settle_timeout, block_number, ) assert test_channel.contract_balance == our_state.contract_balance assert test_channel.balance == our_state.balance(partner_state) assert test_channel.transferred_amount == our_state.transferred_amount assert test_channel.distributable == our_state.distributable(partner_state) assert test_channel.outstanding == our_state.locked() assert test_channel.outstanding == 0 assert test_channel.locked == partner_state.locked() assert test_channel.our_state.locked() == 0 assert test_channel.partner_state.locked() == 0 with pytest.raises(ValueError): test_channel.create_directtransfer( -10, identifier=1, ) with pytest.raises(ValueError): test_channel.create_directtransfer( balance1 + 10, identifier=1, ) amount1 = 10 directtransfer = test_channel.create_directtransfer( amount1, identifier=1, ) directtransfer.sign(privkey1, address1) test_channel.register_transfer(directtransfer) assert test_channel.contract_balance == balance1 assert test_channel.balance == balance1 - amount1 assert test_channel.transferred_amount == amount1 assert test_channel.distributable == balance1 - amount1 assert test_channel.outstanding == 0 assert test_channel.locked == 0 assert test_channel.our_state.locked() == 0 assert test_channel.partner_state.locked() == 0 secret = sha3('test_channel') hashlock = sha3(secret) amount2 = 10 fee = 0 expiration = block_number + settle_timeout - 5 identifier = 1 mediatedtransfer = test_channel.create_mediatedtransfer( address1, address2, fee, amount2, identifier, expiration, hashlock, ) mediatedtransfer.sign(privkey1, address1) test_channel.register_transfer(mediatedtransfer) assert test_channel.contract_balance == balance1 assert test_channel.balance == balance1 - amount1 assert test_channel.transferred_amount == amount1 assert test_channel.distributable == balance1 - amount1 - amount2 assert test_channel.outstanding == 0 assert test_channel.locked == amount2 assert test_channel.our_state.locked() == 0 assert test_channel.partner_state.locked() == amount2 test_channel.release_lock(secret) assert test_channel.contract_balance == balance1 assert test_channel.balance == balance1 - amount1 - amount2 assert test_channel.transferred_amount == amount1 + amount2 assert test_channel.distributable == balance1 - amount1 - amount2 assert test_channel.outstanding == 0 assert test_channel.locked == 0 assert test_channel.our_state.locked() == 0 assert test_channel.partner_state.locked() == 0
def test_register_invalid_transfer(raiden_network, settle_timeout): """ Regression test for registration of invalid transfer. The bug occurred if a transfer with an invalid allowance but a valid secret was registered, when the local end registered the transfer it would "unlock" the partners' token, but the transfer wouldn't be sent because the allowance check failed, leaving the channel in an inconsistent state. """ app0, app1 = raiden_network # pylint: disable=unbalanced-tuple-unpacking graph0 = app0.raiden.channelgraphs.values()[0] graph1 = app1.raiden.channelgraphs.values()[0] channel0 = graph0.partneraddress_channel.values()[0] channel1 = graph1.partneraddress_channel.values()[0] balance0 = channel0.balance balance1 = channel1.balance amount = 10 block_number = app0.raiden.chain.block_number() expiration = block_number + settle_timeout - 1 secret = 'secret' hashlock = sha3(secret) transfer1 = channel0.create_mediatedtransfer( transfer_initiator=app0.raiden.address, transfer_target=app1.raiden.address, fee=0, amount=amount, identifier=1, expiration=expiration, hashlock=hashlock, ) # register a locked transfer app0.raiden.sign(transfer1) channel0.register_transfer(transfer1) channel1.register_transfer(transfer1) # assert the locked transfer is registered assert_synched_channels( channel0, balance0, [], channel1, balance1, [transfer1.lock], ) # handcrafted transfer because channel.create_transfer won't create it transfer2 = DirectTransfer( 1, # TODO: fill in identifier nonce=channel0.our_state.nonce, token=channel0.token_address, transferred_amount=channel1.balance + balance0 + amount, recipient=channel0.partner_state.address, locksroot=channel0.partner_state.balance_proof. merkleroot_for_unclaimed(), ) app0.raiden.sign(transfer2) # this need to fail because the allowance is incorrect with pytest.raises(Exception): channel0.register_transfer(transfer2) with pytest.raises(Exception): channel1.register_transfer(transfer2) # the registration of a bad transfer need fail equaly on both channels assert_synched_channels( channel0, balance0, [], channel1, balance1, [transfer1.lock], )
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 pending_mediated_transfer(app_chain, token_network_identifier, amount, identifier): """ Nice to read shortcut to make a LockedTransfer where the secret is _not_ revealed. While the secret is not revealed all apps will be synchronized, meaning they are all going to receive the LockedTransfer message. Returns: The secret used to generate the LockedTransfer """ # pylint: disable=too-many-locals if len(app_chain) < 2: raise ValueError( 'Cannot make a LockedTransfer with less than two apps') target = app_chain[-1].raiden.address # Generate a secret initiator_channel = views.get_channelstate_by_token_network_and_partner( views.state_from_app(app_chain[0]), token_network_identifier, app_chain[1].raiden.address, ) address = initiator_channel.identifier nonce_int = channel.get_next_nonce(initiator_channel.our_state) nonce_bytes = nonce_int.to_bytes(2, 'big') secret = sha3(address + nonce_bytes) initiator_app = app_chain[0] init_initiator_statechange = initiator_init( initiator_app.raiden, identifier, amount, secret, token_network_identifier, target, ) events = initiator_app.raiden.wal.log_and_dispatch( init_initiator_statechange, initiator_app.raiden.get_block_number(), ) send_transfermessage = must_contain_entry(events, SendLockedTransfer, {}) transfermessage = LockedTransfer.from_event(send_transfermessage) initiator_app.raiden.sign(transfermessage) for mediator_app in app_chain[1:-1]: mediator_init_statechange = mediator_init(mediator_app.raiden, transfermessage) events = mediator_app.raiden.wal.log_and_dispatch( mediator_init_statechange, mediator_app.raiden.get_block_number(), ) send_transfermessage = must_contain_entry(events, SendLockedTransfer, {}) transfermessage = LockedTransfer.from_event(send_transfermessage) mediator_app.raiden.sign(transfermessage) target_app = app_chain[-1] mediator_init_statechange = target_init(transfermessage) events = target_app.raiden.wal.log_and_dispatch( mediator_init_statechange, target_app.raiden.get_block_number(), ) return secret
def send_and_wait_valid(self, raiden, mediated_transfer, maker_payer_hop): """ Start the second half of the exchange and wait for the SecretReveal for it. This will send the taker mediated transfer with the maker as a target, once the maker receives the transfer he is expected to send a RevealSecret backwards. """ # the taker cannot discard the transfer since the secret is controlled # by another node (the maker), so we have no option but to wait for a # valid response until the lock expires response_iterator = self._send_and_wait_block( raiden, mediated_transfer.recipient, mediated_transfer, mediated_transfer.lock.expiration, ) # Usually the RevealSecret for the MediatedTransfer from this node to # the maker should arrive first, but depending on the number of hops # and if the maker-path is optimistically revealing the Secret, then # the Secret message might arrive first. secret = None for response in response_iterator: valid_reveal = ( isinstance(response, RevealSecret) and response.hashlock == mediated_transfer.lock.hashlock and response.sender == maker_payer_hop ) valid_refund = ( isinstance(response, RefundTransfer) and response.sender == maker_payer_hop and response.lock.amount == mediated_transfer.lock.amount and response.lock.expiration <= mediated_transfer.lock.expiration and response.token == mediated_transfer.token ) if response is None: log.error( 'TAKER SWAP TIMED OUT node:%s hashlock:%s', pex(raiden.address), pex(mediated_transfer.lock.hashlock), ) return (response, secret) elif isinstance(response, Secret): if sha3(response.secret) != mediated_transfer.lock.hashlock: log.error("Secret doesn't match the hashlock, ignoring.") continue secret = response elif valid_reveal: return (response, secret) elif valid_refund: return (response, secret) elif log.isEnabledFor(logging.ERROR): log.error( 'Invalid message [%s] supplied to the task, ignoring.', repr(response), ) return (None, secret)
import gevent import networkx from raiden.settings import DEFAULT_SETTLE_TIMEOUT from raiden.app import App from raiden.network.blockchain_service import BlockChainService from raiden.network.discovery import Discovery from raiden.network.rpc import JSONRPCClient from raiden.utils import sha3, privatekey_to_address from raiden.settings import ( GAS_LIMIT, GAS_PRICE, ) TRANSFER_AMOUNT = 1 TOKEN_ADDRESS = sha3('tps')[:20] def hostport_to_privkeyaddr(host, port): """ Return `(private key, address)` deterministically generated. """ myip_port = '{}:{}'.format(host, port) privkey = sha3(myip_port) addr = privatekey_to_address(privkey) return privkey, addr def random_raiden_network(token_address, blockchain_service, node_addresses, deposit, settle_timeout): """ Creates random channels among the test nodes until we have a connected graph. """ graph = networkx.Graph()
def transfer_speed(num_transfers=100, max_locked=100): # pylint: disable=too-many-locals channels_per_node = 1 num_nodes = 2 num_tokens = 1 private_keys = [ sha3('speed:{}'.format(position)) for position in range(num_nodes) ] tokens = [ sha3('token:{}'.format(number))[:20] for number in range(num_tokens) ] amounts = [a % 100 + 1 for a in range(1, num_transfers + 1)] deposit = sum(amounts) secrets = [str(i) for i in range(num_transfers)] BlockChainServiceMock._instance = True blockchain_service = BlockChainServiceMock(None, MOCK_REGISTRY_ADDRESS) BlockChainServiceMock._instance = blockchain_service # pylint: disable=redefined-variable-type registry = blockchain_service.registry(MOCK_REGISTRY_ADDRESS) for token in tokens: registry.add_token(token) apps = create_network(private_keys, tokens, MOCK_REGISTRY_ADDRESS, channels_per_node, deposit, DEFAULT_SETTLE_TIMEOUT, DEFAULT_POLL_TIMEOUT, UDPTransport, BlockChainServiceMock) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.get_manager_by_token_address( tokens[0]).address_channel.values()[0] channel1 = app1.raiden.get_manager_by_token_address( tokens[0]).address_channel.values()[0] expiration = app0.raiden.chain.block_number() + DEFAULT_REVEAL_TIMEOUT + 3 start = time.time() for i, amount in enumerate(amounts): hashlock = sha3(secrets[i]) locked_transfer = channel0.create_lockedtransfer( amount=amount, identifier=1, # TODO: fill in identifier expiration=expiration, hashlock=hashlock, ) app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) if i > max_locked: idx = i - max_locked secret = secrets[idx] channel0.register_secret(secret) channel1.register_secret(secret) elapsed = time.time() - start print('%d transfers per second' % (num_transfers / elapsed))
def hash(self): warnings.warn('Expensive comparison called') packed = self.packed() return sha3(packed.data)
merkleroot, compute_merkleproof_for, ) from raiden.utils import get_project_root, sha3 # The computeMerkleRoot function only computes the proof regardless of what the # hashes are encoding, so just use some arbitrary data to produce a merkle tree. ARBITRARY_DATA = [letter * 32 for letter in string.ascii_uppercase[:7]] FAKE_TREE = [ ARBITRARY_DATA[:1], ARBITRARY_DATA[:2], ARBITRARY_DATA[:3], ARBITRARY_DATA[:7], ] HASH = sha3('muchcodingsuchwow_______________') def deploy_auxiliary_tester(tester_state, tester_nettingchannel_library_address): contracts_path = os.path.join(get_project_root(), 'smart_contracts') raiden_remap = 'raiden={}'.format(contracts_path) auxiliary = tester_state.abi_contract( None, path=get_relative_contract(__file__, 'AuxiliaryTester.sol'), language='solidity', libraries={ 'NettingChannelLibrary': tester_nettingchannel_library_address.encode('hex') },
def lockhash(self): return sha3(self.as_bytes)
def run_test_mediated_transfer_messages_out_of_order(raiden_network, deposit, token_addresses, network_wait): """Raiden must properly handle repeated locked transfer messages.""" app0, app1, app2 = raiden_network app1_wait_for_message = WaitForMessage() app2_wait_for_message = WaitForMessage() app1.raiden.message_handler = app1_wait_for_message app2.raiden.message_handler = app2_wait_for_message secret = factories.make_secret(0) secrethash = sha3(secret) # Save the messages, these will be processed again app1_mediatedtransfer = app1_wait_for_message.wait_for_message( LockedTransfer, {"lock": { "secrethash": secrethash }}) app2_mediatedtransfer = app2_wait_for_message.wait_for_message( LockedTransfer, {"lock": { "secrethash": secrethash }}) # Wait until the node receives a reveal secret to redispatch the locked # transfer message app1_revealsecret = app1_wait_for_message.wait_for_message( RevealSecret, {"secret": secret}) app2_revealsecret = app2_wait_for_message.wait_for_message( RevealSecret, {"secret": secret}) token_address = token_addresses[0] chain_state = views.state_from_app(app0) payment_network_id = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state, payment_network_id, token_address) amount = 10 identifier = 1 transfer_received = app0.raiden.start_mediated_transfer_with_secret( token_network_identifier=token_network_identifier, amount=amount, fee=0, target=app2.raiden.address, identifier=identifier, secret=secret, ) # - Wait until reveal secret is received to replay the message # - The secret is revealed backwards, app2 should be first # - The locked transfer is sent before the secret reveal, so the mediated # transfers async results must be set and `get_nowait` can be used app2_revealsecret.get(timeout=network_wait) mediated_transfer_msg = app2_mediatedtransfer.get_nowait() app2.raiden.message_handler.handle_message_lockedtransfer( app2.raiden, mediated_transfer_msg) app1_revealsecret.get(timeout=network_wait) app1.raiden.message_handler.handle_message_lockedtransfer( app1.raiden, app1_mediatedtransfer.get_nowait()) transfer_received.payment_done.wait() with gevent.Timeout(network_wait): wait_assert( assert_synced_channel_state, token_network_identifier, app0, deposit - amount, [], app1, deposit + amount, [], ) with gevent.Timeout(network_wait): wait_assert( assert_synced_channel_state, token_network_identifier, app1, deposit - amount, [], app2, deposit + amount, [], )
def run_test_mediated_transfer_with_node_consuming_more_than_allocated_fee( raiden_network, number_of_nodes, deposit, token_addresses, network_wait): app0, app1, app2 = raiden_network token_address = token_addresses[0] chain_state = views.state_from_app(app0) payment_network_id = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state, payment_network_id, token_address) fee = 5 amount = 10 app1_app2_channel_state = views.get_channelstate_by_token_network_and_partner( chain_state=views.state_from_raiden(app1.raiden), token_network_id=token_network_identifier, partner_address=app2.raiden.address, ) # Let app1 consume all of the allocated mediation fee action_set_fee = ActionChannelSetFee( canonical_identifier=app1_app2_channel_state.canonical_identifier, mediation_fee=fee * 2) app1.raiden.handle_state_change(state_change=action_set_fee) secret = factories.make_secret(0) secrethash = sha3(secret) wait_message_handler = WaitForMessage() app0.raiden.message_handler = wait_message_handler secret_request_received = wait_message_handler.wait_for_message( SecretRequest, {"secrethash": secrethash}) app0.raiden.start_mediated_transfer_with_secret( token_network_identifier=token_network_identifier, amount=amount, fee=fee, target=app2.raiden.address, identifier=1, secret=secret, ) app0_app1_channel_state = views.get_channelstate_by_token_network_and_partner( chain_state=views.state_from_raiden(app0.raiden), token_network_id=token_network_identifier, partner_address=app1.raiden.address, ) msg = "App0 should have the transfer in secrethashes_to_lockedlocks" assert secrethash in app0_app1_channel_state.our_state.secrethashes_to_lockedlocks, msg msg = "App0 should have locked the amount + fee" lock_amount = app0_app1_channel_state.our_state.secrethashes_to_lockedlocks[ secrethash].amount assert lock_amount == amount + fee, msg secret_request_received.wait() app0_chain_state = views.state_from_app(app0) initiator_task = app0_chain_state.payment_mapping.secrethashes_to_task[ secrethash] msg = "App0 should have never revealed the secret" assert initiator_task.manager_state.initiator_transfers[ secrethash].revealsecret is None
def run_test_lock_expiry(raiden_network, token_addresses, deposit): alice_app, bob_app = raiden_network token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(alice_app), alice_app.raiden.default_registry.address, token_address ) hold_event_handler = bob_app.raiden.raiden_event_handler wait_message_handler = bob_app.raiden.message_handler token_network = views.get_token_network_by_identifier( views.state_from_app(alice_app), token_network_identifier ) channel_state = get_channelstate(alice_app, bob_app, token_network_identifier) channel_identifier = channel_state.identifier assert ( channel_identifier in token_network.partneraddresses_to_channelidentifiers[bob_app.raiden.address] ) alice_to_bob_amount = 10 identifier = 1 target = bob_app.raiden.address transfer_1_secret = factories.make_secret(0) transfer_1_secrethash = sha3(transfer_1_secret) transfer_2_secret = factories.make_secret(1) transfer_2_secrethash = sha3(transfer_2_secret) hold_event_handler.hold_secretrequest_for(secrethash=transfer_1_secrethash) transfer1_received = wait_message_handler.wait_for_message( LockedTransfer, {"lock": {"secrethash": transfer_1_secrethash}} ) transfer2_received = wait_message_handler.wait_for_message( LockedTransfer, {"lock": {"secrethash": transfer_2_secrethash}} ) remove_expired_lock_received = wait_message_handler.wait_for_message( LockExpired, {"secrethash": transfer_1_secrethash} ) alice_app.raiden.start_mediated_transfer_with_secret( token_network_identifier=token_network_identifier, amount=alice_to_bob_amount, fee=0, target=target, identifier=identifier, payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE, secret=transfer_1_secret, ) transfer1_received.wait() alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier) lock = channel.get_lock(alice_bob_channel_state.our_state, transfer_1_secrethash) # This is the current state of the protocol: # # A -> B LockedTransfer # B -> A SecretRequest # - protocol didn't continue assert_synced_channel_state( token_network_identifier, alice_app, deposit, [lock], bob_app, deposit, [] ) # Verify lock is registered in both channel states alice_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier) assert transfer_1_secrethash in alice_channel_state.our_state.secrethashes_to_lockedlocks bob_channel_state = get_channelstate(bob_app, alice_app, token_network_identifier) assert transfer_1_secrethash in bob_channel_state.partner_state.secrethashes_to_lockedlocks alice_chain_state = views.state_from_raiden(alice_app.raiden) assert transfer_1_secrethash in alice_chain_state.payment_mapping.secrethashes_to_task remove_expired_lock_received.wait() alice_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier) assert transfer_1_secrethash not in alice_channel_state.our_state.secrethashes_to_lockedlocks # Verify Bob received the message and processed the LockExpired message bob_channel_state = get_channelstate(bob_app, alice_app, token_network_identifier) assert transfer_1_secrethash not in bob_channel_state.partner_state.secrethashes_to_lockedlocks alice_chain_state = views.state_from_raiden(alice_app.raiden) assert transfer_1_secrethash not in alice_chain_state.payment_mapping.secrethashes_to_task # Make another transfer alice_to_bob_amount = 10 identifier = 2 hold_event_handler.hold_secretrequest_for(secrethash=transfer_2_secrethash) alice_app.raiden.start_mediated_transfer_with_secret( token_network_identifier=token_network_identifier, amount=alice_to_bob_amount, fee=0, target=target, identifier=identifier, payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE, secret=transfer_2_secret, ) transfer2_received.wait() # Make sure the other transfer still exists alice_chain_state = views.state_from_raiden(alice_app.raiden) assert transfer_2_secrethash in alice_chain_state.payment_mapping.secrethashes_to_task bob_channel_state = get_channelstate(bob_app, alice_app, token_network_identifier) assert transfer_2_secrethash in bob_channel_state.partner_state.secrethashes_to_lockedlocks
from raiden.messages 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 import sha3 ADDRESS = sha3(b'foo')[:20] ADDRESS2 = sha3(b'boo')[:20] ADDRESS3 = sha3(b'coo')[:20] ADDRESS4 = sha3(b'goo')[:20] SECRET = b'secret' HASH = sha3(SECRET) HASH2 = sha3(b'joo') 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,