示例#1
0
def main(
        rpc_provider: HTTPProvider,
        private_key: str,
        private_key_password_file: str,
        state_file: str,
        channel_manager_address: str,
        minimum_amount: int,
        gas_price: int,
):
    if minimum_amount <= 0:
        click.echo('Minimum amount need to be at least 1')
        sys.exit(1)
    private_key = utils.get_private_key(private_key, private_key_password_file)
    if private_key is None:
        sys.exit(1)

    receiver_address = utils.privkey_to_addr(private_key)

    web3 = Web3(HTTPProvider(rpc_provider, request_kwargs={'timeout': 60}))
    config.NETWORK_CFG.set_defaults(int(web3.version.network))
    web3.eth.defaultAccount = receiver_address
    channel_manager_address = (
        channel_manager_address or config.NETWORK_CFG.channel_manager_address
    )
    channel_manager_contract = make_channel_manager_contract(web3, channel_manager_address)

    if not state_file:
        state_file_name = "%s_%s.db" % (
            channel_manager_address[:10],
            receiver_address[:10]
        )
        app_dir = click.get_app_dir('microraiden')
        if not os.path.exists(app_dir):
            click.echo('No state file or directory found!')
            sys.exit(1)
        state_file = os.path.join(app_dir, state_file_name)

    try:
        click.echo('Loading state file from {}'.format(state_file))
        state = ChannelManagerState.load(state_file)
    except StateFileException:
        click.echo('Error reading state file')
        traceback.print_exc()
        sys.exit(1)
    if not is_same_address(state.receiver, receiver_address):
        click.echo('Private key does not match receiver address in state file')
        sys.exit(1)
    elif not is_same_address(state.contract_address, channel_manager_address):
        click.echo('Channel manager contract address mismatch')
        sys.exit(1)

    click.echo('Withdrawing all paid tokens with at least {} due from '
               'receiver {}'.format(minimum_amount, receiver_address))
    withdraw_from_channels(
        private_key,
        state,
        channel_manager_contract,
        minimum_amount,
        gas_price * denoms.gwei if gas_price else None,
    )
示例#2
0
    def __init__(
            self,
            web3: Web3,
            channel_manager_contract: Contract,
            token_contract: Contract,
            private_key: str,
            state_filename: str = None,
            n_confirmations=1
    ) -> None:
        gevent.Greenlet.__init__(self)
        self.blockchain = Blockchain(
            web3,
            channel_manager_contract,
            self,
            n_confirmations=n_confirmations
        )
        self.receiver = privkey_to_addr(private_key)
        self.private_key = private_key
        self.channel_manager_contract = channel_manager_contract
        self.token_contract = token_contract
        self.n_confirmations = n_confirmations
        self.log = logging.getLogger('channel_manager')
        network_id = int(web3.version.network)
        assert is_same_address(privkey_to_addr(self.private_key), self.receiver)

        # check contract version
        self.check_contract_version()

        if state_filename not in (None, ':memory:') and os.path.isfile(state_filename):
            self.state = ChannelManagerState.load(state_filename)
        else:
            self.state = ChannelManagerState(state_filename)
            self.state.setup_db(
                network_id,
                channel_manager_contract.address,
                self.receiver
            )

        assert self.state is not None
        if state_filename not in (None, ':memory:'):
            self.lock_state = filelock.FileLock(state_filename + '.lock')
            try:
                self.lock_state.acquire(timeout=0)
            except filelock.Timeout:
                raise StateFileLocked("state file %s is locked by another process" %
                                      state_filename)

        if network_id != self.state.network_id:
            raise NetworkIdMismatch("Network id mismatch: state=%d, backend=%d" % (
                                    self.state.network_id, network_id))

        if not is_same_address(self.receiver, self.state.receiver):
            raise StateReceiverAddrMismatch('%s != %s' %
                                            (self.receiver, self.state.receiver))
        if not is_same_address(self.state.contract_address, channel_manager_contract.address):
            raise StateContractAddrMismatch('%s != %s' % (
                channel_manager_contract.address, self.state.contract_address))

        self.log.debug('setting up channel manager, receiver=%s channel_contract=%s' %
                       (self.receiver, channel_manager_contract.address))
def test_cooperative(
        channel_manager: ChannelManager,
        confirmed_open_channel: Channel,
        receiver_address: str,
        web3: Web3,
        token_contract: Contract,
        wait_for_blocks,
        sender_address: str
):
    blockchain = channel_manager.blockchain
    channel_id = (confirmed_open_channel.sender, confirmed_open_channel.block)

    sig1 = encode_hex(confirmed_open_channel.create_transfer(5))
    channel_manager.register_payment(sender_address, confirmed_open_channel.block, 5, sig1)

    receiver_sig = channel_manager.sign_close(sender_address, confirmed_open_channel.block, 5)
    channel_rec = channel_manager.channels[channel_id]
    assert channel_rec.is_closed is True
    block_before = web3.eth.blockNumber
    confirmed_open_channel.close_cooperatively(receiver_sig)
    wait_for_blocks(blockchain.n_confirmations)
    gevent.sleep(blockchain.poll_interval)
    logs = get_logs(token_contract, 'Transfer', from_block=block_before - 1)
    assert len([l for l in logs
                if is_same_address(l['args']['_to'], receiver_address) and
                l['args']['_value'] == 5]) == 1
    assert len([l for l in logs
                if is_same_address(l['args']['_to'], sender_address) and
                l['args']['_value'] == 5]) == 1
    wait_for_blocks(blockchain.n_confirmations)
    gevent.sleep(blockchain.poll_interval)
    assert channel_id not in channel_manager.channels
def test_cooperative_close_call_receiver(
        channel_params,
        get_accounts,
        uraiden_instance,
        get_channel,
        print_gas):
    (sender, receiver, open_block_number, balance_msg_sig, closing_sig) = get_channel()
    balance = channel_params['balance']

    sender_verified = uraiden_instance.call().extractBalanceProofSignature(
        receiver,
        open_block_number,
        balance,
        balance_msg_sig
    )
    assert is_same_address(sender_verified, sender)

    receiver_verified = uraiden_instance.call().extractClosingSignature(
        sender,
        open_block_number,
        balance,
        closing_sig
    )
    assert is_same_address(receiver_verified, receiver)

    # Cooperative close can be called by anyone
    txn_hash = uraiden_instance.transact({"from": receiver}).cooperativeClose(
        receiver,
        open_block_number,
        balance,
        balance_msg_sig,
        closing_sig
    )

    print_gas(txn_hash, 'cooperativeClose')
def test_cooperative_close_call_delegate(
        channel_params,
        get_accounts,
        uraiden_instance,
        get_channel):
    A = get_accounts(1, 5)[0]
    (sender, receiver, open_block_number, balance_msg_sig, closing_sig) = get_channel()
    balance = channel_params['balance']

    sender_verified = uraiden_instance.call().extractBalanceProofSignature(
        receiver,
        open_block_number,
        balance,
        balance_msg_sig
    )
    assert is_same_address(sender_verified, sender)

    receiver_verified = uraiden_instance.call().extractClosingSignature(
        sender,
        open_block_number,
        balance,
        closing_sig
    )
    assert is_same_address(receiver_verified, receiver)

    # Cooperative close can be called by anyone
    uraiden_instance.transact({"from": A}).cooperativeClose(
        receiver,
        open_block_number,
        balance,
        balance_msg_sig,
        closing_sig
    )
示例#6
0
def test_variable_access(owner, uraiden_contract, token_instance, contract_params):
    uraiden = uraiden_contract(token_instance)
    assert is_same_address(uraiden.call().owner_address(), owner)
    assert is_same_address(uraiden.call().token(), token_instance.address)
    assert uraiden.call().challenge_period() == contract_params['challenge_period']
    assert uraiden.call().version() == uraiden_contract_version
    assert uraiden.call().channel_deposit_bugbounty_limit() == channel_deposit_bugbounty_limit
示例#7
0
def test_set_address_equivalence(ens, name, equivalent, TEST_ADDRESS):
    assert ens.address(name) is None

    ens.setup_address(name, TEST_ADDRESS)
    assert is_same_address(ens.address(name), TEST_ADDRESS)
    assert is_same_address(ens.address(equivalent), TEST_ADDRESS)

    ens.setup_address(name, None)
    assert ens.address(name) is None
def test_pre_EIP155_transaction_sender_extraction(transaction_class, txn_fixture):
    if txn_fixture['chainId'] is not None:
        pytest.skip("Only testng non-EIP155 transactions")
    key = keys.PrivateKey(decode_hex(txn_fixture['key']))
    transaction = rlp.decode(decode_hex(txn_fixture['signed']), sedes=transaction_class)
    sender = extract_transaction_sender(transaction)

    assert is_same_address(sender, transaction.sender)
    assert is_same_address(sender, key.public_key.to_canonical_address())
def test_token_network_registry(
        deploy_client,
        contract_manager,
        token_network_registry_proxy: TokenNetworkRegistry,
):

    assert token_network_registry_proxy.settlement_timeout_min() == TEST_SETTLE_TIMEOUT_MIN
    assert token_network_registry_proxy.settlement_timeout_max() == TEST_SETTLE_TIMEOUT_MAX

    bad_token_address = make_address()
    # try to register non-existing token network
    with pytest.raises(RaidenUnrecoverableError):
        token_network_registry_proxy.add_token(bad_token_address)
    # create token network & register it
    test_token = deploy_token(
        deploy_client=deploy_client,
        contract_manager=contract_manager,
        initial_amount=1000,
        decimals=0,
        token_name='TKN',
        token_symbol='TKN',
    )
    test_token_address = to_canonical_address(test_token.contract.address)
    event_filter = token_network_registry_proxy.tokenadded_filter()
    token_network_address = token_network_registry_proxy.add_token(
        test_token_address,
    )

    with pytest.raises(RaidenRecoverableError) as exc:
        token_network_address = token_network_registry_proxy.add_token(
            test_token_address,
        )

        assert 'Token already registered' in str(exc)

    logs = event_filter.get_all_entries()
    assert len(logs) == 1
    decoded_event = token_network_registry_proxy.proxy.decode_event(logs[0])
    assert is_same_address(decoded_event['args']['token_address'], test_token.contract.address)
    assert is_same_address(
        decoded_event['args']['token_network_address'],
        token_network_address,
    )
    # test other getters
    assert token_network_registry_proxy.get_token_network(bad_token_address) is None
    assert is_same_address(
        token_network_registry_proxy.get_token_network(test_token_address),
        token_network_address,
    )

    with pytest.raises(ValueError):
        assert token_network_registry_proxy.get_token_network(None) is None

    assert token_network_registry_proxy.get_token_network(bad_token_address) is None
    assert token_network_registry_proxy.get_token_network(token_network_address) is None
    assert token_network_registry_proxy.get_token_network(test_token_address) is not None
def test_balance_remaining_big(
        channel_params,
        get_accounts,
        uraiden_instance,
        get_channel):
    (sender, receiver, open_block_number) = get_channel()[:3]
    balance1 = 30
    balance2_big = channel_params['deposit'] + 1
    balance2_ok = channel_params['deposit']

    balance_message_hash1 = balance_proof_hash(
        receiver,
        open_block_number,
        balance1,
        uraiden_instance.address
    )
    balance_msg_sig1, addr = sign.check(balance_message_hash1, tester.k2)
    assert is_same_address(addr, sender)

    balance_message_hash2_big = balance_proof_hash(
        receiver,
        open_block_number,
        balance2_big,
        uraiden_instance.address
    )
    balance_msg_sig2_big, addr = sign.check(balance_message_hash2_big, tester.k2)
    assert is_same_address(addr, sender)

    balance_message_hash2_ok = balance_proof_hash(
        receiver,
        open_block_number,
        balance2_ok,
        uraiden_instance.address
    )
    balance_msg_sig2_ok, addr = sign.check(balance_message_hash2_ok, tester.k2)
    assert is_same_address(addr, sender)

    uraiden_instance.transact({"from": receiver}).withdraw(
        open_block_number,
        balance1,
        balance_msg_sig1
    )

    with pytest.raises(tester.TransactionFailed):
        uraiden_instance.transact({"from": receiver}).withdraw(
            open_block_number,
            balance2_big,
            balance_msg_sig2_big
        )

    uraiden_instance.transact({"from": receiver}).withdraw(
        open_block_number,
        balance2_ok,
        balance_msg_sig2_ok
    )
示例#11
0
 def get_open_channels(self, receiver: str = None) -> List[Channel]:
     """
     Returns all open channels to the given receiver. If no receiver is specified, all open
     channels are returned.
     """
     return [
         c for c in self.channels
         if is_same_address(c.sender, self.context.address) and
         (not receiver or is_same_address(c.receiver, receiver)) and
         c.state == Channel.State.open
     ]
def test_challenge(
        channel_manager: ChannelManager,
        confirmed_open_channel: Channel,
        receiver_address: str,
        sender_address: str,
        wait_for_blocks,
        web3: Web3,
        client: Client
):
    blockchain = channel_manager.blockchain
    channel_id = (confirmed_open_channel.sender, confirmed_open_channel.block)
    sig = encode_hex(confirmed_open_channel.create_transfer(5))
    channel_manager.register_payment(sender_address, confirmed_open_channel.block, 5, sig)
    # hack channel to decrease balance
    confirmed_open_channel.update_balance(0)
    sig = confirmed_open_channel.create_transfer(3)
    block_before = web3.eth.blockNumber
    confirmed_open_channel.close()
    # should challenge and immediately settle
    for waited_blocks in count():
        logs = get_logs(client.context.token, 'Transfer', from_block=block_before - 1)
        if logs:
            break
        wait_for_blocks(1)
        assert waited_blocks < 10

    assert len([l for l in logs
                if is_same_address(l['args']['_to'], receiver_address) and
                l['args']['_value'] == 5]) == 1
    assert len([l for l in logs
                if is_same_address(l['args']['_to'], sender_address) and
                l['args']['_value'] == 5]) == 1
    wait_for_blocks(blockchain.n_confirmations)
    gevent.sleep(blockchain.poll_interval)
    assert channel_id not in channel_manager.channels

    # update channel state so that it will not be closed twice
    client.sync_channels()
    new_state = None
    for channel in client.channels:
        if all(channel.sender == confirmed_open_channel.sender,
               channel.receiver == confirmed_open_channel.receiver,
               channel.block == confirmed_open_channel.block):
            new_state = channel.state
    if new_state is None:
        confirmed_open_channel.state = confirmed_open_channel.State.closed
    else:
        confirmed_open_channel.state = new_state
def test_withdraw_event(
        channel_params,
        uraiden_instance,
        get_channel,
        event_handler):
    (sender, receiver, open_block_number) = get_channel()[:3]
    ev_handler = event_handler(uraiden_instance)
    balance = 30

    balance_message_hash = balance_proof_hash(
        receiver,
        open_block_number,
        balance,
        uraiden_instance.address
    )
    balance_msg_sig, addr = sign.check(balance_message_hash, tester.k2)
    assert is_same_address(addr, sender)

    txn_hash = uraiden_instance.transact({"from": receiver}).withdraw(
        open_block_number,
        balance,
        balance_msg_sig
    )

    ev_handler.add(txn_hash, uraiden_events['withdraw'], checkWithdrawEvent(
        sender,
        receiver,
        open_block_number,
        balance)
    )
    ev_handler.check()
def test_dynamic_length_argument_extraction(web3,
                                            emitter,
                                            wait_for_transaction,
                                            emitter_log_topics,
                                            emitter_event_ids):
    string_0 = "this-is-the-first-string-which-exceeds-32-bytes-in-length"
    string_1 = "this-is-the-second-string-which-exceeds-32-bytes-in-length"
    txn_hash = emitter.functions.logDynamicArgs(string_0, string_1).transact()
    txn_receipt = wait_for_transaction(web3, txn_hash)

    assert len(txn_receipt['logs']) == 1
    log_entry = txn_receipt['logs'][0]

    event_abi = emitter._find_matching_event_abi('LogDynamicArgs')

    event_topic = emitter_log_topics.LogDynamicArgs
    assert event_topic in log_entry['topics']

    string_0_topic = web3.keccak(text=string_0)
    assert string_0_topic in log_entry['topics']

    event_data = get_event_data(event_abi, log_entry)

    expected_args = {
        "arg0": string_0_topic,
        "arg1": string_1,
    }

    assert event_data['args'] == expected_args
    assert event_data['blockHash'] == txn_receipt['blockHash']
    assert event_data['blockNumber'] == txn_receipt['blockNumber']
    assert event_data['transactionIndex'] == txn_receipt['transactionIndex']
    assert is_same_address(event_data['address'], emitter.address)
    assert event_data['event'] == 'LogDynamicArgs'
def test_event_data_extraction(web3,
                               emitter,
                               wait_for_transaction,
                               emitter_log_topics,
                               emitter_event_ids,
                               contract_fn,
                               event_name,
                               call_args,
                               expected_args):
    emitter_fn = emitter.functions[contract_fn]
    event_id = getattr(emitter_event_ids, event_name)
    txn_hash = emitter_fn(event_id, *call_args).transact()
    txn_receipt = wait_for_transaction(web3, txn_hash)

    assert len(txn_receipt['logs']) == 1
    log_entry = txn_receipt['logs'][0]

    event_abi = emitter._find_matching_event_abi(event_name)

    event_topic = getattr(emitter_log_topics, event_name)
    is_anonymous = event_abi['anonymous']

    if is_anonymous:
        assert event_topic not in log_entry['topics']
    else:
        assert event_topic in log_entry['topics']

    event_data = get_event_data(event_abi, log_entry)

    assert event_data['args'] == expected_args
    assert event_data['blockHash'] == txn_receipt['blockHash']
    assert event_data['blockNumber'] == txn_receipt['blockNumber']
    assert event_data['transactionIndex'] == txn_receipt['transactionIndex']
    assert is_same_address(event_data['address'], emitter.address)
    assert event_data['event'] == event_name
示例#16
0
def test_ecrecover_output(web3, ecverify_test_contract):
    (A, B) = web3.eth.accounts[:2]
    block = 4804175
    balance = 22000000000000000000

    balance_message_hash = balance_proof_hash(B, block, balance, ecverify_test_contract.address)
    balance_msg_sig, addr = sign.check(balance_message_hash, tester.k0)
    assert is_same_address(addr, A)

    r = bytes.fromhex('12d99ba7bd20ac17bac65bfd646146c1ddbeb607519db6e7935684334d891ed6')
    s = bytes.fromhex('5d4ea3a13697c1d506f7bdb8cd672b944e2053d6d6bd87d4aa512fdc29ed9ae4')
    v = 28

    with pytest.raises(tester.TransactionFailed):
        ecverify_test_contract.call().verify_ecrecover_output(balance_message_hash, r, s, 0)

    # We have to simulate mining because ecrecover consumes a lot of gas for precompiled contracts
    # on private chains.
    web3.testing.mine(30)

    ecverify_test_contract.call().verify_ecrecover_output(
        balance_message_hash,
        r,
        s,
        v
    )
def test_withdraw_fail_in_challenge_period(
        channel_params,
        get_accounts,
        uraiden_instance,
        get_channel):
    (sender, receiver, open_block_number) = get_channel()[:3]
    balance = 30

    balance_message_hash = balance_proof_hash(
        receiver,
        open_block_number,
        balance,
        uraiden_instance.address
    )
    balance_msg_sig, addr = sign.check(balance_message_hash, tester.k2)
    assert is_same_address(addr, sender)

    # Should fail if the channel is already in a challenge period
    uraiden_instance.transact({"from": sender}).uncooperativeClose(
        receiver,
        open_block_number,
        balance
    )

    channel_info = uraiden_instance.call().getChannelInfo(sender, receiver, open_block_number)
    assert channel_info[2] > 0  # settle_block_number

    with pytest.raises(tester.TransactionFailed):
        uraiden_instance.transact({"from": receiver}).withdraw(
            open_block_number,
            balance,
            balance_msg_sig
        )
示例#18
0
def test_verify_balance_proof(channel_manager_address: str):
    sig = sign_balance_proof(
        SENDER_PRIVATE_KEY, RECEIVER_ADDR, 315123, 8, channel_manager_address
    )
    assert is_same_address(verify_balance_proof(
        RECEIVER_ADDR, 315123, 8, sig, channel_manager_address
    ), SENDER_ADDR)
示例#19
0
    def test_eth_sendTransaction(self, web3, unlocked_account):
        txn_params = {
            'from': unlocked_account,
            'to': unlocked_account,
            'value': 1,
            'gas': 21000,
            'gas_price': web3.eth.gasPrice,
        }
        txn_hash = web3.eth.sendTransaction(txn_params)
        txn = web3.eth.getTransaction(txn_hash)

        assert is_same_address(txn['from'], txn_params['from'])
        assert is_same_address(txn['to'], txn_params['to'])
        assert txn['value'] == 1
        assert txn['gas'] == 21000
        assert txn['gasPrice'] == txn_params['gas_price']
示例#20
0
    def verify_balance_proof(self, sender, open_block_number, balance, signature):
        """Verify that a balance proof is valid and return the sender.

        This method just verifies if the balance proof is valid - no state update is performed.

        :returns: Channel, if it exists
        """
        assert is_checksum_address(sender)
        if (sender, open_block_number) in self.unconfirmed_channels:
            raise InsufficientConfirmations(
                'Insufficient confirmations for the channel '
                '(sender=%s, open_block_number=%d)' % (sender, open_block_number))
        try:
            c = self.channels[sender, open_block_number]
        except KeyError:
            raise NoOpenChannel('Channel does not exist or has been closed'
                                '(sender=%s, open_block_number=%s)' % (sender, open_block_number))
        if c.is_closed:
            raise NoOpenChannel('Channel closing has been requested already.')

        if not is_same_address(
                verify_balance_proof(
                    self.receiver,
                    open_block_number,
                    balance,
                    decode_hex(signature),
                    self.channel_manager_contract.address
                ),
                sender
        ):
            raise InvalidBalanceProof('Recovered signer does not match the sender')
        return c
示例#21
0
def test_extract_closing_signature(get_accounts, token_instance, uraiden_instance):
    (A, B) = get_accounts(2)
    token = token_instance
    uraiden = uraiden_instance

    sender = '0x5601Ea8445A5d96EEeBF89A67C4199FbB7a43Fbb'
    block = 4804175
    balance = 22000000000000000000

    message_hash = closing_message_hash(sender, block, balance, uraiden.address)
    balance_msg_sig, signer = sign.check(message_hash, tester.k2)
    assert is_same_address(signer, A)

    signature_address = uraiden.call().extractClosingSignature(
        sender,
        block,
        balance,
        balance_msg_sig
    )
    assert is_same_address(signature_address, signer)

    # Wrong sender
    signature_address = uraiden.call().extractClosingSignature(
        B,
        block,
        balance,
        balance_msg_sig
    )
    assert not is_same_address(signature_address, signer)

    # Wrong block
    signature_address = uraiden.call().extractClosingSignature(
        sender,
        10,
        balance,
        balance_msg_sig
    )
    assert not is_same_address(signature_address, signer)

    # Wrong balance
    signature_address = uraiden.call().extractClosingSignature(
        sender,
        block,
        20,
        balance_msg_sig
    )
    assert not is_same_address(signature_address, signer)
示例#22
0
def test_sign_balance_proof_contract(channel_manager_contract: Contract):
    sig = sign_balance_proof(
        SENDER_PRIVATE_KEY, RECEIVER_ADDR, 37, 15, channel_manager_contract.address
    )
    sender_recovered = channel_manager_contract.call().extractBalanceProofSignature(
        RECEIVER_ADDR, 37, 15, sig
    )
    assert is_same_address(sender_recovered, SENDER_ADDR)
示例#23
0
def test_sign():
    msg = b'32' * 16
    assert len(msg) == 32
    sig = sign(SENDER_PRIVATE_KEY, msg)
    pubkey = PublicKey.from_signature_and_message(sig, msg, hasher=None)
    pubkey = pubkey.format(compressed=False)
    assert len(sig) == 65
    assert is_same_address(pubkey_to_addr(pubkey), SENDER_ADDR)
示例#24
0
def test_sign_close_contract(channel_manager_contract: Contract):
    sig = sign_close(
        RECEIVER_PRIVATE_KEY, SENDER_ADDR, 315832, 13, channel_manager_contract.address
    )
    receiver_recovered = channel_manager_contract.call().extractClosingSignature(
        SENDER_ADDR, 315832, 13, sig
    )
    assert is_same_address(receiver_recovered, RECEIVER_ADDR)
def test_personal_importRawKey_as_bytes(web3, account_private_key,
                                        account_password, account_public_key):
    address = web3.personal.importRawKey(account_private_key, account_password)

    # sanity check
    assert is_same_address(address, account_public_key)

    assert web3.personal.unlockAccount(address, account_password) is True
示例#26
0
def test_verify_balance_proof_v0(channel_manager_address: str):
    sig = sign_balance_proof(
        SENDER_PRIVATE_KEY, RECEIVER_ADDR, 312524, 11, channel_manager_address
    )
    sig = sig[:-1] + bytes([sig[-1] % 27])
    assert is_same_address(verify_balance_proof(
        RECEIVER_ADDR, 312524, 11, sig, channel_manager_address
    ), SENDER_ADDR)
示例#27
0
 def test_personal_sign_and_ecrecover(self,
                                      web3,
                                      unlockable_account,
                                      unlockable_account_pw):
     message = 'test-web3-personal-sign'
     signature = web3.personal.sign(message, unlockable_account, unlockable_account_pw)
     signer = web3.personal.ecRecover(message, signature)
     assert is_same_address(signer, unlockable_account)
def test_withdraw_fail_no_channel(
        channel_params,
        get_accounts,
        uraiden_instance,
        get_channel):
    A = get_accounts(1, 5)[0]
    (sender, receiver, open_block_number) = get_channel()[:3]
    balance = 10

    balance_message_hash_A = balance_proof_hash(
        A,
        open_block_number,
        balance,
        uraiden_instance.address
    )
    balance_msg_sig_A, addr = sign.check(balance_message_hash_A, tester.k5)
    assert is_same_address(addr, A)

    balance_message_hash = balance_proof_hash(
        receiver,
        open_block_number,
        balance,
        uraiden_instance.address
    )
    balance_msg_sig, addr = sign.check(balance_message_hash, tester.k2)
    assert is_same_address(addr, sender)

    with pytest.raises(tester.TransactionFailed):
        uraiden_instance.transact({"from": sender}).withdraw(
            open_block_number,
            balance,
            balance_msg_sig
        )
    with pytest.raises(tester.TransactionFailed):
        uraiden_instance.transact({"from": A}).withdraw(
            open_block_number,
            balance,
            balance_msg_sig
        )
    with pytest.raises(tester.TransactionFailed):
        uraiden_instance.transact({"from": receiver}).withdraw(
            open_block_number,
            balance,
            balance_msg_sig_A
        )
示例#29
0
def is_account_locked(web3, account):
    if isinstance(web3.providers[0], (EthereumTesterProvider, TestRPCProvider)):
        return not any((is_same_address(account, a) for a in web3.eth.accounts[:10]))
    try:
        web3.eth.sign(account, 'simple-test-data')
    except ValueError as err:
        return 'account is locked' in str(err)
    else:
        return False
示例#30
0
 def assert_contains_log(result):
     assert len(result) == 1
     log_entry = result[0]
     assert log_entry['blockNumber'] == block_with_txn_with_log['number']
     assert log_entry['blockHash'] == block_with_txn_with_log['hash']
     assert log_entry['logIndex'] == 0
     assert is_same_address(log_entry['address'], emitter_contract.address)
     assert log_entry['transactionIndex'] == 0
     assert log_entry['transactionHash'] == HexBytes(txn_hash_with_log)
示例#31
0
def test_blockchain(
        init_blockchain,
        web3,
        blockchain_rpc_ports,
        private_keys,
        poll_timeout):
    # pylint: disable=too-many-locals

    addresses = [
        privatekey_to_address(priv)
        for priv in private_keys
    ]

    privatekey = private_keys[0]
    address = privatekey_to_address(privatekey)
    total_token = 100

    host = '127.0.0.1'
    jsonrpc_client = JSONRPCClient(
        host,
        blockchain_rpc_ports[0],
        privatekey,
        web3=web3,
    )

    humantoken_path = get_contract_path('HumanStandardToken.sol')
    humantoken_contracts = compile_files_cwd([humantoken_path])
    token_proxy = jsonrpc_client.deploy_solidity_contract(
        'HumanStandardToken',
        humantoken_contracts,
        list(),
        (total_token, 'raiden', 2, 'Rd'),
        contract_path=humantoken_path,
        timeout=poll_timeout,
    )
    token_proxy = Token(jsonrpc_client, to_canonical_address(token_proxy.contract.address))

    registry_path = get_contract_path('Registry.sol')
    registry_contracts = compile_files_cwd([registry_path])
    registry_proxy = jsonrpc_client.deploy_solidity_contract(
        'Registry',
        registry_contracts,
        list(),
        tuple(),
        contract_path=registry_path,
        timeout=poll_timeout,
    )
    registry_proxy = Registry(
        jsonrpc_client,
        to_canonical_address(registry_proxy.contract.address),
    )

    log_list = jsonrpc_client.web3.eth.getLogs(
        {
            'fromBlock': 0,
            'toBlock': 'latest',
            'topics': [],
        },
    )
    assert not log_list

    assert token_proxy.balance_of(address) == total_token
    manager_address = registry_proxy.add_token(
        to_canonical_address(token_proxy.proxy.contract.address),
    )
    assert is_address(manager_address)
    assert len(registry_proxy.token_addresses()) == 1

    log_list = jsonrpc_client.web3.eth.getLogs(
        {
            'fromBlock': 0,
            'toBlock': 'latest',
            'topics': [],
        },
    )
    assert len(log_list) == 1

    channel_manager_address_encoded = registry_proxy.manager_address_by_token(
        token_proxy.proxy.contract.address,
    )
    channel_manager_address = to_canonical_address(channel_manager_address_encoded)

    log = log_list[0]
    event = decode_event(CONTRACT_MANAGER.get_contract_abi(CONTRACT_REGISTRY), log)
    event_args = event['args']

    assert channel_manager_address == to_canonical_address(event_args['channel_manager_address'])
    assert is_same_address(token_proxy.proxy.contract.address, event_args['token_address'])

    channel_manager_proxy = jsonrpc_client.new_contract_proxy(
        CONTRACT_MANAGER.get_contract_abi(CONTRACT_CHANNEL_MANAGER),
        channel_manager_address,
    )
    channel_manager_proxy = ChannelManager(
        jsonrpc_client,
        to_canonical_address(channel_manager_proxy.contract.address),
    )

    channel_address = channel_manager_proxy.new_netting_channel(
        addresses[1],
        10,
    )
    assert is_address(channel_address)

    log_list = jsonrpc_client.web3.eth.getLogs(
        {
            'fromBlock': 0,
            'toBlock': 'latest',
            'topics': [],
        },
    )
    assert len(log_list) == 2
示例#32
0
def test_sign_v0():
    msg = keccak256('hello v=0')
    sig = sign(SENDER_PRIVATE_KEY, msg)
    assert sig[-1] == 1
    assert is_same_address(addr_from_sig(sig, msg), SENDER_ADDR)
示例#33
0
def test_sign(web3, ecverify_test_contract):
    (A, B) = web3.eth.accounts[:2]
    block = 4804175
    balance = 22000000000000000000

    balance_message_hash = balance_proof_hash(B, block, balance, ecverify_test_contract.address)
    balance_message_hash2 = balance_proof_hash(B, block, balance + 1000, ecverify_test_contract.address)
    signed_message, addr = sign.check(balance_message_hash, tester.k0)
    signed_message_false, addr1 = sign.check(balance_message_hash, tester.k1)
    assert is_same_address(addr, A)
    assert is_same_address(addr1, B)
    assert len(signed_message) == 65
    assert len(signed_message_false) == 65

    with pytest.raises(tester.TransactionFailed):
        verified_address = ecverify_test_contract.call().verify(
            balance_message_hash,
            encode_hex(bytearray())
        )

    web3.testing.mine(30)
    with pytest.raises(tester.TransactionFailed):
        verified_address = ecverify_test_contract.call().verify(
            balance_message_hash,
            encode_hex(bytearray(64))
        )

    web3.testing.mine(30)
    with pytest.raises(tester.TransactionFailed):
        verified_address = ecverify_test_contract.call().verify(
            balance_message_hash,
            encode_hex(bytearray(66))
        )

    web3.testing.mine(30)
    verified_address = ecverify_test_contract.call().verify(
        balance_message_hash2,
        signed_message
    )
    assert not is_same_address(verified_address, A)

    verified_address = ecverify_test_contract.call().verify(
        balance_message_hash,
        signed_message
    )
    assert is_same_address(verified_address, A)

    verified_address_false = ecverify_test_contract.call().verify(
        balance_message_hash,
        signed_message_false
    )
    assert not is_same_address(verified_address_false, A)
    assert is_same_address(verified_address_false, B)

    signer = '0x5601Ea8445A5d96EEeBF89A67C4199FbB7a43Fbb'
    value = 1000
    value2 = 2000
    _address = '0x5601Ea8445A5d96EEeBF89A67C4199FbB7a43Fbb'

    signed_message = '0x0adc437691e266072e9aa1763329062a6b2fa1d7f94034f1b1e691218fe9fd285f4f20132fa00230f591571a3575456bb382040e02e93ff0f32544907748a9821c'
    signed_message = bytes.fromhex(signed_message[2:])
    verified_address = ecverify_test_contract.call().verifyEthSignedTypedData(
        _address,
        value,
        value2,
        signed_message
    )
    assert is_same_address(verified_address, signer)
示例#34
0
    def on_new_balance_sig(self, command: str, customer: str, sender: str,
                           open_block_number: int, balance_message_hash: bytes,
                           round_number: int, signature: str,
                           customer_sig: str):
        #print('\nbalance sig')
        #debug_print([customer, sender, open_block_number, balance_message_hash, signature])
        customer = to_checksum_address(customer)
        sender = to_checksum_address(sender)

        if not self.verify_customer_deposit(customer):
            return NO_CONTRACT_DEPOSIT

        current_round_number = self.jobs[customer, sender,
                                         open_block_number].round_number
        try:
            assert self.jobs[
                customer, sender,
                open_block_number].round_number == round_number - 1
        except AssertionError:
            print(
                bcolors.OKBLUE +
                'gave incorrent monitor number (current %d, expected %d, received %d)'
                % (current_round_number, current_round_number + 1,
                   round_number) + bcolors.ENDC)
            return
        try:
            assert self.jobs[customer, sender,
                             open_block_number].last_signature != signature
            self.log.info('Signature is different')
            self.log.info(
                'Current round number %d, state hash round number %d',
                self.jobs[customer, sender,
                          open_block_number].round_number, round_number)
            final_hash = monitor_balance_message_from_state(
                balance_message_hash, round_number)

            #self.log.info('Monitors hash: (balanace message hash %s)', encode_hex(balance_message_hash))
            self.log.info(
                'Monitors hash: (round number %s, balanace message hash %s, final hash %s)',
                round_number, encode_hex(balance_message_hash),
                encode_hex(final_hash))
            """regular"""
            #sig_addr = addr_from_sig(decode_hex(signature), balance_message_hash)
            """with receipt"""
            sig_addr = addr_from_sig(decode_hex(signature), final_hash)
            if not is_same_address(sig_addr, sender):
                self.log.info('balance message not signed by correct sender')
                return BALANCE_SIG_NOT_ACCEPTED
            """regular"""
            #customer_sig_addr = addr_from_sig(decode_hex(customer_sig), balance_message_hash)
            """with receipt"""
            customer_sig_addr = addr_from_sig(decode_hex(customer_sig),
                                              final_hash)
            if not is_same_address(customer_sig_addr, customer):
                self.log.info('customers balance sig is wrong. address: %s',
                              customer_sig_addr)
                return BALANCE_SIG_NOT_ACCEPTED

            self.jobs[customer, sender, open_block_number].round_number += 1

            receipt = self.create_signed_receipt(customer, sender,
                                                 open_block_number,
                                                 balance_message_hash,
                                                 signature, round_number)
            #receipt = self.create_signed_receipt(customer, sender, open_block_number, balance_message_hash, round_number, signature)
            #self.customer_fair_exchange(customer, sender, open_block_number, balance_message_hash, signature)
            self.jobs[customer, sender,
                      open_block_number].last_signature = signature
            self.jobs[customer, sender,
                      open_block_number].last_hash = balance_message_hash
            self.jobs[customer, sender,
                      open_block_number].last_customer_sig = customer_sig
            self.jobs[customer, sender,
                      open_block_number].last_round_number = round_number

            self.jobs[customer, sender,
                      open_block_number].all_signatures.append(signature)
            self.jobs[customer, sender,
                      open_block_number].all_customer_signatures.append(
                          customer_sig)
            self.jobs[customer, sender, open_block_number].all_hashes.append(
                balance_message_hash)
            self.jobs[customer, sender,
                      open_block_number].all_round_numbers.append(round_number)

            self.log.info(
                'Accepting new balance signature (customer %s, sender %s, open block number %d)',
                customer, sender, open_block_number)

            #            self.log.info('Accepting new balance signature (customer %s, sender %s, open block number %d, \n\told hash %s, \n\tnew hash %s)',
            #                customer,
            #                sender,
            #                open_block_number,
            #                encode_hex(self.jobs[customer,sender,open_block_number].last_hash),
            #                encode_hex(balance_message_hash)
            #            )

            self.jobs[customer, sender, open_block_number].sent_receipt = True

            self.log.debug(
                'accepted balance signature (customer %s, sender %s, open_block_number %s\n',
                customer, sender, open_block_number)
            #            self.log.info('TYPE OF RECEIPT %s', str(type(receipt)))
            #            self.log.info('RECEIPT %s', str(receipt))
            return receipt
        except KeyError:
            self.log.info('balance sig for job not being watched\n')
            return IGNORE_BALANCE_SIG
        except AssertionError:
            self.log.info('customer sent the same signature as before: %s\n',
                          encode_hex(signature))
            return IGNORE_SAME_BALANCE_SIG
示例#35
0
    def __init__(
            self,
            privkey: str = None,
            key_path: str = None,
            key_password_path: str = None,
            datadir: str = click.get_app_dir('microraiden'),
            channel_manager_address: str = CHANNEL_MANAGER_ADDRESS,
            web3: Web3 = None,
            channel_manager_proxy: ChannelContractProxy = None,
            token_proxy: ContractProxy = None,
            contract_metadata: dict = CONTRACT_METADATA
    ) -> None:
        assert privkey or key_path
        assert not privkey or isinstance(privkey, str)

        # Plain copy initializations.
        self.privkey = privkey
        self.datadir = datadir
        self.channel_manager_address = channel_manager_address
        self.web3 = web3
        self.channel_manager_proxy = channel_manager_proxy
        self.token_proxy = token_proxy

        # Load private key from file if none is specified on command line.
        if not privkey:
            self.privkey = get_private_key(key_path, key_password_path)
            assert self.privkey is not None

        os.makedirs(datadir, exist_ok=True)
        assert os.path.isdir(datadir)

        self.account = privkey_to_addr(self.privkey)
        self.channels = []  # type: List[Channel]

        # Create web3 context if none is provided, either by using the proxies' context or creating
        # a new one.
        if not web3:
            if channel_manager_proxy:
                self.web3 = channel_manager_proxy.web3
                self.channel_manager_address = channel_manager_proxy.address
            elif token_proxy:
                self.web3 = token_proxy.web3
            else:
                self.web3 = Web3(RPCProvider())

        # Create missing contract proxies.
        if not channel_manager_proxy:
            channel_manager_abi = contract_metadata[CHANNEL_MANAGER_ABI_NAME]['abi']
            self.channel_manager_proxy = ChannelContractProxy(
                self.web3,
                self.privkey,
                channel_manager_address,
                channel_manager_abi,
                GAS_PRICE,
                GAS_LIMIT
            )

        token_address = self.channel_manager_proxy.contract.call().token()
        if not token_proxy:
            token_abi = contract_metadata[TOKEN_ABI_NAME]['abi']
            self.token_proxy = ContractProxy(
                self.web3, self.privkey, token_address, token_abi, GAS_PRICE, GAS_LIMIT
            )
        else:
            assert is_same_address(self.token_proxy.address, token_address)

        assert self.web3
        assert self.channel_manager_proxy
        assert self.token_proxy
        assert self.channel_manager_proxy.web3 == self.web3 == self.token_proxy.web3

        netid = self.web3.version.network
        self.balances_filename = 'balances_{}_{}.json'.format(
            NETWORK_NAMES.get(netid, netid), self.account[:10]
        )

        self.filelock = filelock.FileLock(os.path.join(self.datadir, self.balances_filename))
        self.filelock.acquire(timeout=0)

        self.load_channels()
        self.sync_channels()
示例#36
0
def address_in(address, addresses):
    return any(is_same_address(address, item) for item in addresses)
示例#37
0
def test_configure_pfs(service_registry_address, private_keys, web3, contract_manager):
    chain_id = ChainID(int(web3.net.version))
    service_registry, urls = deploy_service_registry_and_set_urls(
        private_keys=private_keys,
        web3=web3,
        contract_manager=contract_manager,
        service_registry_address=service_registry_address,
    )
    json_data = {
        "price_info": 0,
        "network_info": {
            "chain_id": chain_id,
            "token_network_registry_address": to_checksum_address(
                token_network_registry_address_test_default
            ),
            "user_deposit_address": to_checksum_address(privatekey_to_address(private_keys[1])),
        },
        "message": "This is your favorite pathfinding service",
        "operator": "John Doe",
        "version": "0.0.1",
        "payment_address": to_checksum_address(privatekey_to_address(private_keys[0])),
    }

    response = mocked_json_response(response_data=json_data)

    # With local routing configure_pfs should raise assertion
    with pytest.raises(AssertionError):
        _ = configure_pfs_or_exit(
            pfs_url="",
            routing_mode=RoutingMode.LOCAL,
            service_registry=service_registry,
            node_network_id=chain_id,
            token_network_registry_address=token_network_registry_address_test_default,
            pathfinding_max_fee=DEFAULT_PATHFINDING_MAX_FEE,
        )

    # With private routing configure_pfs should raise assertion
    with pytest.raises(AssertionError):
        _ = configure_pfs_or_exit(
            pfs_url="",
            routing_mode=RoutingMode.PRIVATE,
            service_registry=service_registry,
            node_network_id=chain_id,
            token_network_registry_address=token_network_registry_address_test_default,
            pathfinding_max_fee=DEFAULT_PATHFINDING_MAX_FEE,
        )

    # Asking for auto address
    # To make this deterministic we need to patch the random selection function
    patch_random = patch("raiden.network.pathfinding.get_random_pfs", return_value="http://foo")
    with patch.object(requests, "get", return_value=response), patch_random:
        config = configure_pfs_or_exit(
            pfs_url="auto",
            routing_mode=RoutingMode.PFS,
            service_registry=service_registry,
            node_network_id=chain_id,
            token_network_registry_address=token_network_registry_address_test_default,
            pathfinding_max_fee=DEFAULT_PATHFINDING_MAX_FEE,
        )
    assert config.url in urls
    assert is_canonical_address(config.payment_address)

    # Configuring a valid given address
    given_address = "http://foo"
    with patch.object(requests, "get", return_value=response):
        config = configure_pfs_or_exit(
            pfs_url=given_address,
            routing_mode=RoutingMode.PFS,
            service_registry=service_registry,
            node_network_id=chain_id,
            token_network_registry_address=token_network_registry_address_test_default,
            pathfinding_max_fee=DEFAULT_PATHFINDING_MAX_FEE,
        )
    assert config.url == given_address
    assert is_same_address(config.payment_address, json_data["payment_address"])
    assert config.price == json_data["price_info"]

    # Bad address, should exit the program
    bad_address = "http://badaddress"
    with pytest.raises(RaidenError):
        with patch.object(requests, "get", side_effect=requests.RequestException()):
            # Configuring a given address
            _ = configure_pfs_or_exit(
                pfs_url=bad_address,
                routing_mode=RoutingMode.PFS,
                service_registry=service_registry,
                node_network_id=chain_id,
                token_network_registry_address=token_network_registry_address_test_default,
                pathfinding_max_fee=DEFAULT_PATHFINDING_MAX_FEE,
            )

    # Addresses of token network registries of pfs and client conflict, should exit the client
    response = mocked_json_response(response_data=json_data)
    with pytest.raises(RaidenError):
        with patch.object(requests, "get", return_value=response):
            _ = configure_pfs_or_exit(
                pfs_url="http://foo",
                routing_mode=RoutingMode.PFS,
                service_registry=service_registry,
                node_network_id=chain_id,
                token_network_registry_address=TokenNetworkRegistryAddress(
                    to_canonical_address("0x2222222222222222222222222222222222222221")
                ),
                pathfinding_max_fee=DEFAULT_PATHFINDING_MAX_FEE,
            )

    # ChainIDs of pfs and client conflict, should exit the client
    response = mocked_json_response(response_data=json_data)
    with pytest.raises(RaidenError):
        with patch.object(requests, "get", return_value=response):
            configure_pfs_or_exit(
                pfs_url="http://foo",
                routing_mode=RoutingMode.PFS,
                service_registry=service_registry,
                node_network_id=ChainID(chain_id + 1),
                token_network_registry_address=token_network_registry_address_test_default,
                pathfinding_max_fee=DEFAULT_PATHFINDING_MAX_FEE,
            )
示例#38
0
def test_eth_sign_v27():
    sig = eth_sign(SENDER_PRIVATE_KEY, 'hello v=27')
    assert sig[-1] == 27
    assert is_same_address(eth_verify(sig, 'hello v=27'), SENDER_ADDR)
示例#39
0
 def is_signature_valid(self) -> bool:
     try:
         recovered_address = recover(self.packed_data(), self.signature)
     except InvalidSignature:
         return False
     return is_same_address(recovered_address, self.sender)
def test_EIP155_transaction_sender_extraction(txn_fixture):
    key = keys.PrivateKey(decode_hex(txn_fixture['key']))
    transaction = rlp.decode(decode_hex(txn_fixture['signed']), sedes=SpuriousDragonTransaction)
    sender = extract_transaction_sender(transaction)
    assert is_same_address(sender, transaction.sender)
    assert is_same_address(sender, key.public_key.to_canonical_address())
示例#41
0
def test_get_authorized_address(keyfile, keyfile_auth):
    _, expected_address, _ = keyfile_auth
    actual_address = get_authorized_address()
    assert is_same_address(actual_address, expected_address)
def test_token_network_registry(
    deploy_client,
    contract_manager,
    token_network_registry_address,
):
    registry_address = to_canonical_address(token_network_registry_address)

    token_network_registry_proxy = TokenNetworkRegistry(
        jsonrpc_client=deploy_client,
        registry_address=registry_address,
        contract_manager=contract_manager,
    )

    assert token_network_registry_proxy.settlement_timeout_min(
    ) == TEST_SETTLE_TIMEOUT_MIN
    assert token_network_registry_proxy.settlement_timeout_max(
    ) == TEST_SETTLE_TIMEOUT_MAX

    bad_token_address = make_address()
    # try to register non-existing token network
    with pytest.raises(AddressWithoutCode):
        token_network_registry_proxy.add_token_with_limits(
            token_address=bad_token_address,
            channel_participant_deposit_limit=
            RED_EYES_PER_CHANNEL_PARTICIPANT_LIMIT,
            token_network_deposit_limit=RED_EYES_PER_TOKEN_NETWORK_LIMIT,
        )
    # create token network & register it
    test_token = deploy_token(
        deploy_client=deploy_client,
        contract_manager=contract_manager,
        initial_amount=1000,
        decimals=0,
        token_name='TKN',
        token_symbol='TKN',
    )

    test_token_address = to_canonical_address(test_token.contract.address)
    # try to register a token network not following ERC20 protocol

    with patch.object(Token, 'total_supply', return_value=''):
        with pytest.raises(InvalidToken):
            token_network_registry_proxy.add_token_with_limits(
                token_address=test_token_address,
                channel_participant_deposit_limit=
                RED_EYES_PER_CHANNEL_PARTICIPANT_LIMIT,
                token_network_deposit_limit=RED_EYES_PER_TOKEN_NETWORK_LIMIT,
            )

    event_filter = token_network_registry_proxy.tokenadded_filter()
    token_network_address = token_network_registry_proxy.add_token_with_limits(
        token_address=test_token_address,
        channel_participant_deposit_limit=
        RED_EYES_PER_CHANNEL_PARTICIPANT_LIMIT,
        token_network_deposit_limit=RED_EYES_PER_TOKEN_NETWORK_LIMIT,
    )

    with pytest.raises(RaidenRecoverableError) as exc:
        token_network_address = token_network_registry_proxy.add_token_with_limits(
            token_address=test_token_address,
            channel_participant_deposit_limit=
            RED_EYES_PER_CHANNEL_PARTICIPANT_LIMIT,
            token_network_deposit_limit=RED_EYES_PER_TOKEN_NETWORK_LIMIT,
        )

        assert 'Token already registered' in str(exc)

    logs = event_filter.get_all_entries()
    assert len(logs) == 1
    decoded_event = token_network_registry_proxy.proxy.decode_event(logs[0])
    assert is_same_address(decoded_event['args']['token_address'],
                           test_token.contract.address)
    assert is_same_address(
        decoded_event['args']['token_network_address'],
        token_network_address,
    )
    # test other getters
    assert token_network_registry_proxy.get_token_network(
        bad_token_address) is None
    assert is_same_address(
        token_network_registry_proxy.get_token_network(test_token_address),
        token_network_address,
    )

    with pytest.raises(ValueError):
        assert token_network_registry_proxy.get_token_network(None) is None

    assert token_network_registry_proxy.get_token_network(
        bad_token_address) is None
    assert token_network_registry_proxy.get_token_network(
        token_network_address) is None
    assert token_network_registry_proxy.get_token_network(
        test_token_address) is not None
示例#43
0
def setup_chain_state(web3):
    coinbase = web3.eth.coinbase

    assert is_same_address(coinbase, common.COINBASE)

    #
    # Math Contract
    #
    math_contract_factory = web3.eth.contract(
        abi=MATH_ABI,
        bytecode=MATH_BYTECODE,
    )
    math_deploy_receipt = common.deploy_contract(web3, 'math',
                                                 math_contract_factory)
    assert is_dict(math_deploy_receipt)

    #
    # Emitter Contract
    #
    emitter_contract_factory = web3.eth.contract(
        abi=EMITTER_ABI,
        bytecode=EMITTER_BYTECODE,
    )
    emitter_deploy_receipt = common.deploy_contract(web3, 'emitter',
                                                    emitter_contract_factory)
    emitter_contract = emitter_contract_factory(
        emitter_deploy_receipt['contractAddress'])

    txn_hash_with_log = emitter_contract.functions.logDouble(
        which=EMITTER_ENUM['LogDoubleWithIndex'],
        arg0=12345,
        arg1=54321,
    ).transact({
        'from': web3.eth.coinbase,
    })
    print('TXN_HASH_WITH_LOG:', txn_hash_with_log)
    txn_receipt_with_log = common.mine_transaction_hash(
        web3, txn_hash_with_log)
    block_with_log = web3.eth.getBlock(txn_receipt_with_log['blockHash'])
    print('BLOCK_HASH_WITH_LOG:', block_with_log['hash'])

    #
    # Empty Block
    #
    empty_block_number = common.mine_block(web3)
    print('MINED_EMPTY_BLOCK')
    empty_block = web3.eth.getBlock(empty_block_number)
    assert is_dict(empty_block)
    assert not empty_block['transactions']
    print('EMPTY_BLOCK_HASH:', empty_block['hash'])

    #
    # Block with Transaction
    #
    web3.personal.unlockAccount(coinbase, common.KEYFILE_PW)
    web3.miner.start(1)
    mined_txn_hash = web3.eth.sendTransaction({
        'from': coinbase,
        'to': coinbase,
        'value': 1,
        'gas': 21000,
        'gas_price': web3.eth.gasPrice,
    })
    mined_txn_receipt = common.mine_transaction_hash(web3, mined_txn_hash)
    print('MINED_TXN_HASH:', mined_txn_hash)
    block_with_txn = web3.eth.getBlock(mined_txn_receipt['blockHash'])
    print('BLOCK_WITH_TXN_HASH:', block_with_txn['hash'])

    geth_fixture = {
        'math_deploy_txn_hash': math_deploy_receipt['transactionHash'],
        'math_address': math_deploy_receipt['contractAddress'],
        'emitter_deploy_txn_hash': emitter_deploy_receipt['transactionHash'],
        'emitter_address': emitter_deploy_receipt['contractAddress'],
        'txn_hash_with_log': txn_hash_with_log,
        'block_hash_with_log': block_with_log['hash'],
        'empty_block_hash': empty_block['hash'],
        'mined_txn_hash': mined_txn_hash,
        'block_with_txn_hash': block_with_txn['hash'],
    }
    return geth_fixture
示例#44
0
def test_verify_balance_proof(channel_manager_address: str):
    sig = sign_balance_proof(SENDER_PRIVATE_KEY, RECEIVER_ADDR, 315123, 8,
                             channel_manager_address)
    assert is_same_address(
        verify_balance_proof(RECEIVER_ADDR, 315123, 8, sig,
                             channel_manager_address), SENDER_ADDR)
示例#45
0
def test_channel_lifecycle(raiden_network, token_addresses, deposit,
                           transport_protocol):
    node1, node2 = raiden_network
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(node1),
        node1.raiden.default_registry.address,
        token_address,
    )

    api1 = RaidenAPI(node1.raiden)
    api2 = RaidenAPI(node2.raiden)

    registry_address = node1.raiden.default_registry.address

    # nodes don't have a channel, so they are not healthchecking
    assert api1.get_node_network_state(api2.address) == NODE_NETWORK_UNKNOWN
    assert api2.get_node_network_state(api1.address) == NODE_NETWORK_UNKNOWN
    assert not api1.get_channel_list(registry_address, token_address,
                                     api2.address)

    # Make sure invalid arguments to get_channel_list are caught
    with pytest.raises(UnknownTokenAddress):
        api1.get_channel_list(
            registry_address=registry_address,
            token_address=None,
            partner_address=api2.address,
        )

    # open is a synchronous api
    api1.channel_open(node1.raiden.default_registry.address, token_address,
                      api2.address)
    channels = api1.get_channel_list(registry_address, token_address,
                                     api2.address)
    assert len(channels) == 1

    channel12 = get_channelstate(node1, node2, token_network_identifier)
    assert channel.get_status(channel12) == CHANNEL_STATE_OPENED

    event_list1 = api1.get_blockchain_events_channel(
        token_address,
        channel12.partner_state.address,
    )
    assert any((event['event'] == ChannelEvent.OPENED and is_same_address(
        event['args']['participant1'],
        to_normalized_address(api1.address),
    ) and is_same_address(
        event['args']['participant2'],
        to_normalized_address(api2.address),
    )) for event in event_list1)

    token_events = api1.get_blockchain_events_token_network(token_address, )
    assert token_events[0]['event'] == ChannelEvent.OPENED

    registry_address = api1.raiden.default_registry.address
    # Check that giving a 0 total deposit is not accepted
    with pytest.raises(DepositMismatch):
        api1.set_total_channel_deposit(
            registry_address=registry_address,
            token_address=token_address,
            partner_address=api2.address,
            total_deposit=0,
        )
    # Load the new state with the deposit
    api1.set_total_channel_deposit(
        registry_address=registry_address,
        token_address=token_address,
        partner_address=api2.address,
        total_deposit=deposit,
    )

    # let's make sure it's idempotent. Same deposit should raise deposit mismatch limit
    with pytest.raises(DepositMismatch):
        api1.set_total_channel_deposit(
            registry_address,
            token_address,
            api2.address,
            deposit,
        )

    channel12 = get_channelstate(node1, node2, token_network_identifier)

    assert channel.get_status(channel12) == CHANNEL_STATE_OPENED
    assert channel.get_balance(channel12.our_state,
                               channel12.partner_state) == deposit
    assert channel12.our_state.contract_balance == deposit
    assert api1.get_channel_list(registry_address, token_address,
                                 api2.address) == [channel12]

    # there is a channel open, they must be healthchecking each other
    assert api1.get_node_network_state(api2.address) == NODE_NETWORK_REACHABLE
    assert api2.get_node_network_state(api1.address) == NODE_NETWORK_REACHABLE

    event_list2 = api1.get_blockchain_events_channel(
        token_address,
        channel12.partner_state.address,
    )
    assert any((event['event'] == ChannelEvent.DEPOSIT and is_same_address(
        event['args']['participant'],
        to_normalized_address(api1.address),
    ) and event['args']['total_deposit'] == deposit) for event in event_list2)

    api1.channel_close(registry_address, token_address, api2.address)

    # Load the new state with the channel closed
    channel12 = get_channelstate(node1, node2, token_network_identifier)

    event_list3 = api1.get_blockchain_events_channel(
        token_address,
        channel12.partner_state.address,
    )
    assert len(event_list3) > len(event_list2)
    assert any((event['event'] == ChannelEvent.CLOSED and is_same_address(
        event['args']['closing_participant'],
        to_normalized_address(api1.address),
    )) for event in event_list3)
    assert channel.get_status(channel12) == CHANNEL_STATE_CLOSED

    settlement_block = (
        channel12.close_transaction.finished_block_number +
        channel12.settle_timeout +
        10  # arbitrary number of additional blocks, used to wait for the settle() call
    )
    node1.raiden.chain.wait_until_block(
        target_block_number=settlement_block +
        DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS, )

    state_changes = node1.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )

    assert search_for_item(
        state_changes, ContractReceiveChannelSettled, {
            'token_network_identifier': token_network_identifier,
            'channel_identifier': channel12.identifier,
        })
示例#46
0
    def _update(self):
        #print(bcolors.BOLD + 'manager: block number %d' % (self.web3.eth.blockNumber) + bcolors.ENDC)
        current_block = self.web3.eth.blockNumber
        # reset unconfirmed channels in case of reorg
        if self.wait_sync_event.is_set():  # but not on first sync
            if current_block < self.cm.state.unconfirmed_head_number:
                self.log.info(
                    'chain reorganization detected. '
                    'Resyncing unconfirmed events (unconfirmed_head=%d) [@%d]'
                    % (self.cm.state.unconfirmed_head_number,
                       self.web3.eth.blockNumber))
                self.cm.reset_unconfirmed()
            try:
                # raises if hash doesn't exist (i.e. block has been replaced)
                self.web3.eth.getBlock(self.cm.state.unconfirmed_head_hash)
            except ValueError:
                self.log.info(
                    'chain reorganization detected. '
                    'Resyncing unconfirmed events (unconfirmed_head=%d) [@%d]. '
                    '(getBlock() raised ValueError)' %
                    (self.cm.state.unconfirmed_head_number, current_block))
                self.cm.reset_unconfirmed()

            # in case of reorg longer than confirmation number fail
            try:
                self.web3.eth.getBlock(self.cm.state.confirmed_head_hash)
            except ValueError:
                self.log.critical(
                    'events considered confirmed have been reorganized')
                assert False  # unreachable as long as confirmation level is set high enough

        if self.cm.state.confirmed_head_number is None:
            self.cm.state.update_sync_state(
                confirmed_head_number=self.sync_start_block)
        if self.cm.state.unconfirmed_head_number is None:
            self.cm.state.update_sync_state(
                unconfirmed_head_number=self.sync_start_block)
        new_unconfirmed_head_number = self.cm.state.unconfirmed_head_number + self.sync_chunk_size
        new_unconfirmed_head_number = min(new_unconfirmed_head_number,
                                          current_block)
        new_confirmed_head_number = max(
            new_unconfirmed_head_number - self.n_confirmations, 0)

        # return if blocks have already been processed
        if (self.cm.state.confirmed_head_number >= new_confirmed_head_number
                and self.cm.state.unconfirmed_head_number >=
                new_unconfirmed_head_number):
            return

        # filter for events after block_number
        filters_confirmed = {
            'from_block': self.cm.state.confirmed_head_number + 1,
            'to_block': new_confirmed_head_number,
            'argument_filters': {
                '_receiver_address': self.cm.state.receiver
            }
        }
        filters_unconfirmed = {
            'from_block': self.cm.state.unconfirmed_head_number + 1,
            'to_block': new_unconfirmed_head_number,
            'argument_filters': {
                '_receiver_address': self.cm.state.receiver
            }
        }
        self.log.debug('filtering for events u:%s-%s c:%s-%s @%d',
                       filters_unconfirmed['from_block'],
                       filters_unconfirmed['to_block'],
                       filters_confirmed['from_block'],
                       filters_confirmed['to_block'], current_block)

        # unconfirmed channel created
        logs = get_logs(self.channel_manager_contract, 'ChannelCreated',
                        **filters_unconfirmed)
        for log in logs:
            assert is_same_address(log['args']['_receiver_address'],
                                   self.cm.state.receiver)
            sender = log['args']['_sender_address']
            sender = to_checksum_address(sender)
            deposit = log['args']['_deposit']
            open_block_number = log['blockNumber']
            self.log.debug(
                'received unconfirmed ChannelCreated event (sender %s, block number %s)',
                sender, open_block_number)
            self.cm.unconfirmed_event_channel_opened(sender, open_block_number,
                                                     deposit)

        # channel created
        logs = get_logs(self.channel_manager_contract, 'ChannelCreated',
                        **filters_confirmed)
        for log in logs:
            assert is_same_address(log['args']['_receiver_address'],
                                   self.cm.state.receiver)
            sender = log['args']['_sender_address']
            sender = to_checksum_address(sender)
            deposit = log['args']['_deposit']
            open_block_number = log['blockNumber']
            self.log.debug(
                'received ChannelOpened event (sender %s, block number %s)',
                sender, open_block_number)
            self.cm.event_channel_opened(sender, open_block_number, deposit)

        # unconfirmed channel top ups
        logs = get_logs(self.channel_manager_contract, 'ChannelToppedUp',
                        **filters_unconfirmed)
        for log in logs:
            assert is_same_address(log['args']['_receiver_address'],
                                   self.cm.state.receiver)
            txhash = log['transactionHash']
            sender = log['args']['_sender_address']
            sender = to_checksum_address(sender)
            open_block_number = log['args']['_open_block_number']
            added_deposit = log['args']['_added_deposit']
            self.log.debug(
                'received top up event (sender %s, block number %s, deposit %s)',
                sender, open_block_number, added_deposit)
            self.cm.unconfirmed_event_channel_topup(sender, open_block_number,
                                                    txhash, added_deposit)

        # confirmed channel top ups
        logs = get_logs(self.channel_manager_contract, 'ChannelToppedUp',
                        **filters_confirmed)
        for log in logs:
            assert is_same_address(log['args']['_receiver_address'],
                                   self.cm.state.receiver)
            txhash = log['transactionHash']
            sender = log['args']['_sender_address']
            sender = to_checksum_address(sender)
            open_block_number = log['args']['_open_block_number']
            added_deposit = log['args']['_added_deposit']
            self.log.debug(
                'received top up event (sender %s, block number %s, added deposit %s)',
                sender, open_block_number, added_deposit)
            self.cm.event_channel_topup(sender, open_block_number, txhash,
                                        added_deposit)

        # channel settled event
        logs = get_logs(self.channel_manager_contract, 'ChannelSettled',
                        **filters_confirmed)
        for log in logs:
            assert is_same_address(log['args']['_receiver_address'],
                                   self.cm.state.receiver)
            sender = log['args']['_sender_address']
            sender = to_checksum_address(sender)
            open_block_number = log['args']['_open_block_number']
            self.log.debug(
                'received ChannelSettled event (sender %s, block number %s)',
                sender, open_block_number)
            self.cm.event_channel_settled(sender, open_block_number)

        # channel close requested
        logs = get_logs(self.channel_manager_contract, 'ChannelCloseRequested',
                        **filters_confirmed)
        for log in logs:
            assert is_same_address(log['args']['_receiver_address'],
                                   self.cm.state.receiver)
            sender = log['args']['_sender_address']
            sender = to_checksum_address(sender)
            open_block_number = log['args']['_open_block_number']
            if (sender, open_block_number) not in self.cm.channels:
                continue
            balance = log['args']['_balance']
            try:
                #self.log.info('params to get info: %s, %s, %d', sender, self.cm.state.receiver, open_block_number)
                mtimeout, timeout = self.channel_manager_contract.call(
                ).getChannelInfo(sender, self.cm.state.receiver,
                                 open_block_number)[2:4]

                print(bcolors.OKGREEN + 'Channel close request:' +
                      '\n\tsender %s' % sender +
                      '\n\tmonitor timeout %d' % mtimeout +
                      '\n\tsettle timeout %d' % timeout + bcolors.ENDC)

            except BadFunctionCallOutput:
                self.log.warning(
                    'received ChannelCloseRequested event for a channel that doesn\'t '
                    'exist or has been closed already (sender=%s open_block_number=%d)'
                    % (sender, open_block_number))
                self.cm.force_close_channel(sender, open_block_number)
                continue
            self.log.debug(
                'received ChannelCloseRequested event (sender %s, block number %s)',
                sender, open_block_number)
            self.log.info(
                'received ChannelCloseRequested event (blocknumber %s, monitor period %s, timeout %s)',
                self.cm.state.confirmed_head_number, mtimeout, timeout)

            self.wait_to_dispute[int(mtimeout)] = (sender, open_block_number,
                                                   balance, mtimeout, timeout)

            #try:
            #    self.cm.event_channel_close_requested(sender, open_block_number, balance, mtimeout, timeout)
            #except InsufficientBalance:
            #    self.log.fatal('Insufficient ETH balance of the receiver. '
            #                   "Can't close the channel. "
            #                   'Will retry once the balance is sufficient')
            #    self.insufficient_balance = True
            # TODO: recover

        logs = get_logs(self.channel_manager_contract, 'MonitorInterference',
                        **filters_unconfirmed)

        for log in logs:
            sender = log['args']['_sender_address']
            sender = to_checksum_address(sender)
            open_block_number = log['args']['open_block_number']
            if (sender, open_block_number) not in self.cm.channels:
                self.log.debug(
                    "monitor interfered in channel that wasn't outsourced (sender %s open_block_number %s)",
                    sender, open_block_number)

            self.cm.event_monitor_interference(sender, open_block_number)

        logs = get_logs(self.channel_monitor_contract, 'CustomerDeposit',
                        **filters_unconfirmed)

        for log in logs:
            sender = to_checksum_address(log['args']['_sender_address'])
            deposit = log['args']['_sender_deposit']

            if sender == self.cm.receiver:
                self.cm.event_deposit_unconfirmed(sender, deposit)

        logs = get_logs(self.channel_monitor_contract, 'CustomerDeposit',
                        **filters_confirmed)

        for log in logs:
            sender = to_checksum_address(log['args']['_sender_address'])
            deposit = log['args']['_sender_deposit']

            if sender == self.cm.receiver:
                self.cm.event_deposit(sender, deposit)

        logs = get_logs(self.channel_monitor_contract, 'RecourseResult',
                        **filters_unconfirmed)

        for log in logs:
            #            monitor_balance = log['args']['_monitor_balance']
            #            closing_balance = log['args']['_closing_balance']
            round_number = int(log['args']['_round_number'])
            receipt_hash = log['args']['_receipt_hash']
            cheated = log['args']['_cheated']

            self.log.info(
                'RECOURSE RESULT: detected unconfirmed recourse result (round_number %d, receipt hash %s), did he cheat? %r',
                round_number, receipt_hash, cheated)
            print(
                bcolors.OKBLUE, 'Recourse result detected',
                '\n\tCheated: %r' % cheated, '\n\tnew balance: %s' %
                int(self.web3.eth.getBalance(self.cm.receiver)), bcolors.ENDC)

        logs = get_logs(self.channel_manager_contract, 'ExtractHash',
                        **filters_unconfirmed)

        for log in logs:
            message_hash = log['args']['message_hash']
            state_hash = log['args']['state_hash']
            signer = to_checksum_address(log['args']['signer'])

            self.log.info('\n\tmessage_hash %s\n\tstate_hash %s\n\tsigner %s',
                          message_hash, state_hash, signer)

        logs = get_logs(self.channel_monitor_contract, 'Dispute',
                        **filters_unconfirmed)

        for log in logs:
            customer = log['args']['_customer_address']
            open_block_number = log['args']['_open_block_number']
            sender = log['args']['_sender_address']
            self.log.info(
                'DETECTED UNCONFIMED DISPUTE from monitor contract (customer %s, sender %s, open_block_number %d)',
                customer, sender, open_block_number)

        logs = get_logs(self.channel_monitor_contract, 'Dispute',
                        **filters_confirmed)

        for log in logs:
            customer = to_checksum_address(log['args']['_customer_address'])
            open_block_number = log['args']['_open_block_number']
            sender = to_checksum_address(log['args']['_sender_address'])
            settle_timeout = int(log['data'], 16)
            self.log.info(
                'DETECTED CONFIMED DISPUTE from monitor contract (customer %s, sender %s, open_block_number %d, settle timeout %d, current block %d)',
                customer, sender, open_block_number, settle_timeout,
                self.cm.blockchain.web3.eth.blockNumber)

            self.wait_to_resolve[settle_timeout + 1] = (customer, sender,
                                                        open_block_number)
            self.resolve_timeouts[sender,
                                  open_block_number] = settle_timeout + 1

        logs = get_logs(self.channel_monitor_contract, 'Resolve',
                        **filters_confirmed)

        for log in logs:
            customer = to_checksum_address(log['args']['_sender_address'])
            self.log.info('successfully resolved channel (customer %s)',
                          customer)
            print(bcolors.OKGREEN + 'Channel successfully resolved....' +
                  bcolors.ENDC)
            print(bcolors.OKGREEN + '\n\tServer balance: %d' %
                  (self.web3.eth.getBalance(self.cm.receiver)))

        logs = get_logs(self.channel_monitor_contract, 'Evidence',
                        **filters_confirmed)

        for log in logs:
            customer = to_checksum_address(log['args']['_customer_address'])
            sender = to_checksum_address(log['args']['_sender_address'])
            pre_image = log['args']['_pre_image']
            open_block_number = int(log['data'], 16)

            if (sender, open_block_number
                ) not in self.cm.channels or customer != self.cm.receiver:
                self.log.info('received SET STATE for unknown channel')
            else:
                self.log.info(
                    'Monitor called SET STATE (sender %s, open_block_number %d, pre_image %d)',
                    sender, open_block_number, pre_image)
                self.cm.event_set_state(customer, sender, open_block_number,
                                        pre_image)

        logs = get_logs(self.channel_manager_contract, 'DebugVerify',
                        **filters_unconfirmed)

        for log in logs:
            signer = to_checksum_address(log['args']['_sender'])
            self.log.info('Signer of customer evidence: %s', signer)

        logs = get_logs(self.channel_manager_contract, 'RevealHash',
                        **filters_unconfirmed)

        for log in logs:
            evidence = encode_hex(log['args']['_evidence'])
            resolved = encode_hex(log['args']['_resolved'])
            balance = int(log['args']['_balance'])
            self.log.info(
                bcolors.BOLD +
                "Reveal (balance %s, evidence %s, resolved %s)" + bcolors.ENDC,
                balance, evidence, resolved)

        # See which close requests are ready to be responded to
        # and process them normally.
        disputed = []
        for mtimeout in self.wait_to_dispute:
            if self.cm.state.confirmed_head_number > mtimeout:
                try:
                    #print(self.cm.monitor_channels)
                    sender, open_block_number = self.wait_to_dispute[mtimeout][
                        0], self.wait_to_dispute[mtimeout][1]
                    self.log.info(
                        'Processing close request at block %s, mtimeout %s',
                        self.cm.state.confirmed_head_number, mtimeout)
                    self.cm.reveal_monitor_submission(
                        *self.wait_to_dispute[mtimeout])
                    self.cm.event_channel_close_requested(
                        *self.wait_to_dispute[mtimeout])
                except InsufficientBalance:
                    self.log.fatal('Insufficient ETH balance of the receiver. '
                                   "Can't close the channel. "
                                   'Will retry once the balance is sufficient')
                    self.insufficient_balance = True
                    # TODO: recover
                disputed.append(mtimeout)

        for dispute in disputed:
            del self.wait_to_dispute[dispute]

        resolved = []
        for stimeout in self.wait_to_resolve:
            if self.cm.blockchain.web3.eth.blockNumber > stimeout:
                self.log.info(
                    'Processing DISPUTE request at block %s, stimeout %s',
                    self.cm.blockchain.web3.eth.blockNumber, stimeout)
                customer, sender, open_block_number = self.wait_to_resolve[
                    stimeout]
                self.cm.event_dispute(customer, sender, open_block_number)
                resolved.append(stimeout)

        for resolve in resolved:
            del self.wait_to_resolve[resolve]

        # update head hash and number
        try:
            new_unconfirmed_head_hash = self.web3.eth.getBlock(
                new_unconfirmed_head_number).hash
            new_confirmed_head_hash = self.web3.eth.getBlock(
                new_confirmed_head_number).hash
        except AttributeError:
            self.log.critical(
                "RPC endpoint didn't return proper info for an existing block "
                "(%d,%d)" %
                (new_unconfirmed_head_number, new_confirmed_head_number))
            self.log.critical(
                "It is possible that the blockchain isn't fully synced. "
                "This often happens when Parity is run with --fast or --warp sync."
            )
            self.log.critical(
                "Can't continue - check status of the ethereum node.")
            sys.exit(1)
        self.cm.set_head(new_unconfirmed_head_number,
                         new_unconfirmed_head_hash, new_confirmed_head_number,
                         new_confirmed_head_hash)
        if not self.wait_sync_event.is_set(
        ) and new_unconfirmed_head_number == current_block:
            self.wait_sync_event.set()
示例#47
0
def process_payment(  # pylint: disable=too-many-branches
    iou: Optional[IOU],
    pathfinding_service: PathfindingService,
    service_fee: TokenAmount,
    one_to_n_address: Address,
) -> None:
    if service_fee == 0:
        return
    if iou is None:
        raise exceptions.MissingIOU

    # Basic IOU validity checks
    if not is_same_address(iou.receiver, pathfinding_service.address):
        raise exceptions.WrongIOURecipient(
            expected=pathfinding_service.address)
    if iou.chain_id != pathfinding_service.chain_id:
        raise exceptions.UnsupportedChainID(
            expected=pathfinding_service.chain_id)
    if iou.one_to_n_address != one_to_n_address:
        raise exceptions.WrongOneToNAddress(expected=one_to_n_address,
                                            got=iou.one_to_n_address)
    if not iou.is_signature_valid():
        raise exceptions.InvalidSignature

    # Compare with known IOU
    active_iou = pathfinding_service.database.get_iou(sender=iou.sender,
                                                      claimed=False)
    if active_iou:
        if active_iou.expiration_block != iou.expiration_block:
            raise exceptions.UseThisIOU(iou=active_iou)

        expected_amount = active_iou.amount + service_fee
    else:
        claimed_iou = pathfinding_service.database.get_iou(
            sender=iou.sender,
            expiration_block=iou.expiration_block,
            claimed=True)
        if claimed_iou:
            raise exceptions.IOUAlreadyClaimed

        min_expiry = pathfinding_service.web3.eth.blockNumber + MIN_IOU_EXPIRY
        if iou.expiration_block < min_expiry:
            raise exceptions.IOUExpiredTooEarly(min_expiry=min_expiry)
        expected_amount = service_fee
    if iou.amount < expected_amount:
        raise exceptions.InsufficientServicePayment(
            expected_amount=expected_amount)

    # Check client's deposit in UserDeposit contract
    udc = pathfinding_service.user_deposit_contract
    latest_block = pathfinding_service.web3.eth.blockNumber
    udc_balance = get_pessimistic_udc_balance(
        udc=udc,
        address=iou.sender,
        from_block=latest_block - pathfinding_service.required_confirmations,
        to_block=latest_block,
    )
    required_deposit = round(expected_amount * UDC_SECURITY_MARGIN_FACTOR_PFS)
    if udc_balance < required_deposit:
        raise exceptions.DepositTooLow(required_deposit=required_deposit)

    log.info(
        "Received service fee",
        sender=iou.sender,
        expected_amount=expected_amount,
        total_amount=iou.amount,
        added_amount=expected_amount - service_fee,
    )

    # Save latest IOU
    iou.claimed = False
    pathfinding_service.database.upsert_iou(iou)
示例#48
0
    def open_channel(self, receiver_address: str, deposit: int):
        """
        Attempts to open a new channel to the receiver with the given deposit. Blocks until the
        creation transaction is found in a pending block or timeout is reached. The new channel
        state is returned.
        """
        assert isinstance(receiver_address, str)
        assert isinstance(deposit, int)
        assert deposit > 0

        token_balance = self.context.token.call().balanceOf(self.context.address)
        if token_balance < deposit:
            log.error(
                'Insufficient tokens available for the specified deposit ({}/{})'
                .format(token_balance, deposit)
            )
            return None

        current_block = self.context.web3.eth.blockNumber
        log.info('Creating channel to {} with an initial deposit of {} @{}'.format(
            receiver_address, deposit, current_block
        ))

        data = decode_hex(self.context.address) + decode_hex(receiver_address)
        tx = create_signed_contract_transaction(
            self.context.private_key,
            self.context.token,
            'transfer',
            [
                self.context.channel_manager.address,
                deposit,
                data
            ]
        )
        self.context.web3.eth.sendRawTransaction(tx)

        log.debug('Waiting for channel creation event on the blockchain...')
        filters = {
            '_sender_address': self.context.address,
            '_receiver_address': receiver_address
        }
        event = get_event_blocking(
            self.context.channel_manager,
            'ChannelCreated',
            from_block=current_block + 1,
            to_block='latest',
            argument_filters=filters
        )

        if event:
            log.debug('Event received. Channel created in block {}.'.format(event['blockNumber']))
            assert is_same_address(event['args']['_sender_address'], self.context.address)
            assert is_same_address(event['args']['_receiver_address'], receiver_address)
            channel = Channel(
                self.context,
                self.context.address,
                receiver_address,
                event['blockNumber'],
                event['args']['_deposit'],
                on_settle=lambda c: self.channels.remove(c)
            )
            self.channels.append(channel)
        else:
            log.error('Error: No event received.')
            channel = None

        return channel
示例#49
0
def test_get_contract_instance(deployed_safe_math):
    safe_math_package, address = deployed_safe_math
    contract_instance = safe_math_package.get_contract_instance(
        "SafeMathLib", address)
    assert contract_instance.abi is not False
    assert is_same_address(contract_instance.address, address)
示例#50
0
def test_sign_close_contract(channel_manager_contract: Contract):
    sig = sign_close(RECEIVER_PRIVATE_KEY, SENDER_ADDR, 315832, 13,
                     channel_manager_contract.address)
    receiver_recovered = channel_manager_contract.call(
    ).extractClosingSignature(SENDER_ADDR, 315832, 13, sig)
    assert is_same_address(receiver_recovered, RECEIVER_ADDR)
示例#51
0
def test_sign_balance_proof_contract(channel_manager_contract: Contract):
    sig = sign_balance_proof(SENDER_PRIVATE_KEY, RECEIVER_ADDR, 37, 15,
                             channel_manager_contract.address)
    sender_recovered = channel_manager_contract.call(
    ).extractBalanceProofSignature(RECEIVER_ADDR, 37, 15, sig)
    assert is_same_address(sender_recovered, SENDER_ADDR)
示例#52
0
    def sync_channels(self):
        """
        Merges locally available channel information, including their current balance signatures,
        with channel information available on the blockchain to make up for local data loss.
        Naturally, balance signatures cannot be recovered from the blockchain.
        """
        filters = {'_sender_address': self.context.address}
        create = get_logs(
            self.context.channel_manager,
            'ChannelCreated',
            argument_filters=filters
        )
        topup = get_logs(
            self.context.channel_manager,
            'ChannelToppedUp',
            argument_filters=filters
        )
        close = get_logs(
            self.context.channel_manager,
            'ChannelCloseRequested',
            argument_filters=filters
        )
        settle = get_logs(
            self.context.channel_manager,
            'ChannelSettled',
            argument_filters=filters
        )

        channel_key_to_channel = {}

        def get_channel(event) -> Channel:
            sender = to_checksum_address(event['args']['_sender_address'])
            receiver = to_checksum_address(event['args']['_receiver_address'])
            block = event['args'].get('_open_block_number', event['blockNumber'])
            assert is_same_address(sender, self.context.address)
            return channel_key_to_channel.get((sender, receiver, block), None)

        for c in self.channels:
            channel_key_to_channel[(c.sender, c.receiver, c.block)] = c

        for e in create:
            c = get_channel(e)
            if c:
                c.deposit = e['args']['_deposit']
            else:
                c = Channel(
                    self.context,
                    to_checksum_address(e['args']['_sender_address']),
                    to_checksum_address(e['args']['_receiver_address']),
                    e['blockNumber'],
                    e['args']['_deposit'],
                    on_settle=lambda channel: self.channels.remove(channel)
                )
                assert is_same_address(c.sender, self.context.address)
                channel_key_to_channel[(c.sender, c.receiver, c.block)] = c

        for e in topup:
            c = get_channel(e)
            c.deposit += e['args']['_added_deposit']

        for e in close:
            # Requested closed, not actual closed.
            c = get_channel(e)

            c.update_balance(e['args']['_balance'])
            c.state = Channel.State.settling

        for e in settle:
            c = get_channel(e)
            c.state = Channel.State.closed

        # Forget closed channels.
        self.channels = [
            c for c in channel_key_to_channel.values() if c.state != Channel.State.closed
        ]

        log.debug('Synced a total of {} channels.'.format(len(self.channels)))
 def is_suitable_channel(channel: Channel, receiver: str, value: int):
     return (channel.deposit - channel.balance >= value
             and is_same_address(channel.receiver, receiver))
示例#54
0
 def get_channel(event) -> Channel:
     sender = to_checksum_address(event['args']['_sender_address'])
     receiver = to_checksum_address(event['args']['_receiver_address'])
     block = event['args'].get('_open_block_number', event['blockNumber'])
     assert is_same_address(sender, self.context.address)
     return channel_key_to_channel.get((sender, receiver, block), None)
示例#55
0
def test_withdraw_state(contract_params, channel_params, uraiden_instance,
                        token_instance, get_channel, get_block, print_gas):
    (sender, receiver, open_block_number) = get_channel()[:3]
    deposit = channel_params['deposit']
    balance1 = 20
    balance2 = deposit

    balance_message_hash = balance_proof_hash(receiver, open_block_number,
                                              balance1,
                                              uraiden_instance.address)
    balance_msg_sig, addr = sign.check(balance_message_hash, tester.k2)
    assert is_same_address(addr, sender)

    # Memorize balances for tests
    uraiden_pre_balance = token_instance.call().balanceOf(
        uraiden_instance.address)
    sender_pre_balance = token_instance.call().balanceOf(sender)
    receiver_pre_balance = token_instance.call().balanceOf(receiver)

    txn_hash = uraiden_instance.transact({
        "from": receiver
    }).withdraw(open_block_number, balance1, balance_msg_sig)

    # Check channel info
    channel_info = uraiden_instance.call().getChannelInfo(
        sender, receiver, open_block_number)
    # deposit
    assert channel_info[1] == deposit
    assert channel_info[2] == 0
    assert channel_info[3] == 0
    assert channel_info[4] == balance1

    # Check token balances post withrawal
    uraiden_balance = uraiden_pre_balance - balance1
    assert token_instance.call().balanceOf(
        uraiden_instance.address) == uraiden_balance
    assert token_instance.call().balanceOf(sender) == sender_pre_balance
    assert token_instance.call().balanceOf(
        receiver) == receiver_pre_balance + balance1

    print_gas(txn_hash, 'withdraw')

    balance_message_hash = balance_proof_hash(receiver, open_block_number,
                                              balance2,
                                              uraiden_instance.address)
    balance_msg_sig, addr = sign.check(balance_message_hash, tester.k2)
    assert is_same_address(addr, sender)

    txn_hash = uraiden_instance.transact({
        "from": receiver
    }).withdraw(open_block_number, balance2, balance_msg_sig)

    channel_info = uraiden_instance.call().getChannelInfo(
        sender, receiver, open_block_number)
    # deposit
    assert channel_info[1] == deposit
    assert channel_info[2] == 0
    assert channel_info[3] == 0
    assert channel_info[4] == balance2

    # Check token balances post withrawal
    uraiden_balance = uraiden_pre_balance - deposit
    assert token_instance.call().balanceOf(
        uraiden_instance.address) == uraiden_balance
    assert token_instance.call().balanceOf(sender) == sender_pre_balance
    assert token_instance.call().balanceOf(
        receiver) == receiver_pre_balance + deposit

    print_gas(txn_hash, 'withdraw')
示例#56
0
def test_channel_lifecycle(raiden_network, token_addresses, deposit,
                           transport_config):
    node1, node2 = raiden_network
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(node1),
        node1.raiden.default_registry.address,
        token_address,
    )

    api1 = RaidenAPI(node1.raiden)
    api2 = RaidenAPI(node2.raiden)

    registry_address = node1.raiden.default_registry.address

    # nodes don't have a channel, so they are not healthchecking
    assert api1.get_node_network_state(api2.address) == NODE_NETWORK_UNKNOWN
    assert api2.get_node_network_state(api1.address) == NODE_NETWORK_UNKNOWN
    assert not api1.get_channel_list(registry_address, token_address,
                                     api2.address)

    # open is a synchronous api
    api1.channel_open(node1.raiden.default_registry.address, token_address,
                      api2.address)
    channels = api1.get_channel_list(registry_address, token_address,
                                     api2.address)
    assert len(channels) == 1

    channel12 = get_channelstate(node1, node2, token_network_identifier)
    assert channel.get_status(channel12) == CHANNEL_STATE_OPENED

    event_list1 = api1.get_channel_events(
        channel12.identifier,
        channel12.open_transaction.finished_block_number,
    )
    assert event_list1 == []

    token_events = api1.get_token_network_events(
        token_address,
        channel12.open_transaction.finished_block_number,
    )
    assert token_events[0]['event'] == EVENT_CHANNEL_NEW

    registry_address = api1.raiden.default_registry.address
    # Load the new state with the deposit
    api1.set_total_channel_deposit(
        registry_address,
        token_address,
        api2.address,
        deposit,
    )
    # let's make sure it's idempotent
    api1.set_total_channel_deposit(
        registry_address,
        token_address,
        api2.address,
        deposit,
    )

    channel12 = get_channelstate(node1, node2, token_network_identifier)

    assert channel.get_status(channel12) == CHANNEL_STATE_OPENED
    assert channel.get_balance(channel12.our_state,
                               channel12.partner_state) == deposit
    assert channel12.our_state.contract_balance == deposit
    assert api1.get_channel_list(registry_address, token_address,
                                 api2.address) == [channel12]

    # there is a channel open, they must be healthchecking each other
    assert api1.get_node_network_state(api2.address) == NODE_NETWORK_REACHABLE
    assert api2.get_node_network_state(api1.address) == NODE_NETWORK_REACHABLE

    event_list2 = api1.get_channel_events(
        channel12.identifier,
        channel12.open_transaction.finished_block_number,
    )
    assert any(
        (event['event'] == EVENT_CHANNEL_NEW_BALANCE and is_same_address(
            event['args']['registry_address'],
            to_normalized_address(registry_address),
        ) and is_same_address(
            event['args']['participant'],
            to_normalized_address(api1.address),
        )) for event in event_list2)

    api1.channel_close(registry_address, token_address, api2.address)

    # Load the new state with the channel closed
    channel12 = get_channelstate(node1, node2, token_network_identifier)

    event_list3 = api1.get_channel_events(
        channel12.identifier,
        channel12.open_transaction.finished_block_number,
    )
    assert len(event_list3) > len(event_list2)
    assert any((event['event'] == EVENT_CHANNEL_CLOSED and is_same_address(
        event['args']['registry_address'],
        to_normalized_address(registry_address),
    ) and is_same_address(
        event['args']['closing_address'],
        to_normalized_address(api1.address),
    )) for event in event_list3)
    assert channel.get_status(channel12) == CHANNEL_STATE_CLOSED

    settlement_block = (
        channel12.close_transaction.finished_block_number +
        channel12.settle_timeout +
        10  # arbitrary number of additional blocks, used to wait for the settle() call
    )
    wait_until_block(node1.raiden.chain, settlement_block)

    # Load the new state with the channel settled
    channel12 = get_channelstate(node1, node2, token_network_identifier)

    assert channel.get_status(channel12) == CHANNEL_STATE_SETTLED
def test_token_network_registry(
    deploy_client: JSONRPCClient,
    contract_manager: ContractManager,
    token_network_registry_address: TokenNetworkRegistryAddress,
    token_contract_name: str,
) -> None:
    proxy_manager = ProxyManager(
        rpc_client=deploy_client,
        contract_manager=contract_manager,
        metadata=ProxyManagerMetadata(
            token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER,
            filters_start_at=GENESIS_BLOCK_NUMBER,
        ),
    )

    confirmed_block_identifier = deploy_client.get_confirmed_blockhash()

    token_network_registry_proxy = proxy_manager.token_network_registry(
        token_network_registry_address,
        block_identifier=confirmed_block_identifier)

    assert (token_network_registry_proxy.settlement_timeout_min(
        BLOCK_ID_LATEST) == TEST_SETTLE_TIMEOUT_MIN)
    assert (token_network_registry_proxy.settlement_timeout_max(
        BLOCK_ID_LATEST) == TEST_SETTLE_TIMEOUT_MAX)
    assert (token_network_registry_proxy.get_token_network_created(
        block_identifier=BLOCK_ID_LATEST) == 0)

    bad_token_address = make_token_address()

    # Registering a non-existing token network should fail
    with pytest.raises(AddressWithoutCode):
        token_network_registry_proxy.add_token(
            token_address=bad_token_address,
            channel_participant_deposit_limit=TokenAmount(UINT256_MAX),
            token_network_deposit_limit=TokenAmount(UINT256_MAX),
            given_block_identifier=confirmed_block_identifier,
        )

    test_token = deploy_token(
        deploy_client=deploy_client,
        contract_manager=contract_manager,
        initial_amount=TokenAmount(1000),
        decimals=0,
        token_name="TKN",
        token_symbol="TKN",
        token_contract_name=token_contract_name,
    )
    test_token_address = TokenAddress(to_canonical_address(test_token.address))

    # Check the proper exception is raised if the token does not comply to the
    # ERC20 interface. In this case the token does not have the totalSupply()
    # function implemented #3697 which is validated in the smart contract.
    with patch.object(Token, "total_supply", return_value=None):
        with pytest.raises(InvalidToken):
            token_network_registry_proxy.add_token(
                token_address=test_token_address,
                channel_participant_deposit_limit=TokenAmount(UINT256_MAX),
                token_network_deposit_limit=TokenAmount(UINT256_MAX),
                given_block_identifier=deploy_client.get_confirmed_blockhash(),
            )

    # Register a valid token
    preblockhash = deploy_client.get_confirmed_blockhash()
    token_network_address = token_network_registry_proxy.add_token(
        token_address=test_token_address,
        channel_participant_deposit_limit=TokenAmount(UINT256_MAX),
        token_network_deposit_limit=TokenAmount(UINT256_MAX),
        given_block_identifier=preblockhash,
    )
    assert token_network_address is not None
    assert (token_network_registry_proxy.get_token_network_created(
        block_identifier=BLOCK_ID_LATEST) == 1)

    # Re-registering the same token should fail with a recoverable error
    # because it is a race condition.
    with pytest.raises(RaidenRecoverableError):
        token_network_registry_proxy.add_token(
            token_address=test_token_address,
            channel_participant_deposit_limit=TokenAmount(UINT256_MAX),
            token_network_deposit_limit=TokenAmount(UINT256_MAX),
            given_block_identifier=preblockhash,
        )

    logs = token_network_registry_proxy.filter_token_added_events()
    assert is_same_address(logs[0]["args"]["token_address"],
                           test_token.address)
    assert is_same_address(logs[0]["args"]["token_network_address"],
                           token_network_address)
    assert (token_network_registry_proxy.get_token_network(
        bad_token_address, BLOCK_ID_LATEST) is None)

    result_address = token_network_registry_proxy.get_token_network(
        test_token_address, BLOCK_ID_LATEST)

    assert result_address
    assert to_normalized_address(result_address) == to_normalized_address(
        token_network_address)

    with pytest.raises(ValueError):
        assert token_network_registry_proxy.get_token_network(
            None,
            BLOCK_ID_LATEST  # type: ignore
        )

    # These are not registered token addresses
    assert (token_network_registry_proxy.get_token_network(
        bad_token_address, BLOCK_ID_LATEST) is None)
    assert (token_network_registry_proxy.get_token_network(
        test_token_address, BLOCK_ID_LATEST) is not None)
    address = token_network_registry_proxy.get_token_network(
        TokenAddress(token_network_address), BLOCK_ID_LATEST)
    assert address is None
示例#58
0
def test_channel_opening(
        client: Client,
        web3: Web3,
        make_account,
        channel_manager_contract,
        token_contract,
        mine_sync_event,
        wait_for_blocks,
        use_tester,
        state_db_path
):
    receiver1_privkey = make_account(RECEIVER_ETH_ALLOWANCE, RECEIVER_TOKEN_ALLOWANCE)
    receiver2_privkey = make_account(RECEIVER_ETH_ALLOWANCE, RECEIVER_TOKEN_ALLOWANCE)
    receiver_address = privkey_to_addr(receiver1_privkey)
    # make sure channel_manager1 is terminated properly, otherwise Blockchain will be running
    #  in the background, ruining other tests' results
    channel_manager1 = ChannelManager(
        web3,
        channel_manager_contract,
        token_contract,
        receiver1_privkey,
        n_confirmations=5,
        state_filename=state_db_path
    )
    start_channel_manager(channel_manager1, use_tester, mine_sync_event)

    channel_manager2 = ChannelManager(
        web3,
        channel_manager_contract,
        token_contract,
        receiver2_privkey,
        n_confirmations=5,
        state_filename=state_db_path
    )
    start_channel_manager(channel_manager2, use_tester, mine_sync_event)
    channel_manager1.wait_sync()
    channel_manager2.wait_sync()
    blockchain = channel_manager1.blockchain
    channel = client.open_channel(receiver_address, 10)
    # should be in unconfirmed channels
    wait_for_blocks(1)
    gevent.sleep(blockchain.poll_interval)
    assert (channel.sender, channel.block) not in channel_manager1.channels
    assert (channel.sender, channel.block) in channel_manager1.unconfirmed_channels
    channel_rec = channel_manager1.unconfirmed_channels[channel.sender, channel.block]
    assert is_same_address(channel_rec.receiver, receiver_address)
    assert is_same_address(channel_rec.sender, channel.sender)
    assert channel_rec.mtime == channel_rec.ctime

    # should be confirmed after n blocks
    wait_for_blocks(blockchain.n_confirmations)
    gevent.sleep(blockchain.poll_interval)
    assert (channel.sender, channel.block) in channel_manager1.channels
    channel_rec = channel_manager1.channels[channel.sender, channel.block]
    assert is_same_address(channel_rec.receiver, receiver_address)
    assert is_same_address(channel_rec.sender, channel.sender)
    assert channel_rec.balance == 0
    assert channel_rec.last_signature is None
    assert channel_rec.is_closed is False
    assert channel_rec.settle_timeout == -1

    # should not appear in other channel manager
    assert (channel.sender, channel.block) not in channel_manager2.channels
    assert (channel.sender, channel.block) not in channel_manager2.unconfirmed_channels
    channel_manager1.stop()
    channel_manager2.stop()
def test_EIP2930_transaction_sender_extraction(typed_txn_fixture):
    transaction = BerlinTransactionBuilder.deserialize(decode_hex(typed_txn_fixture['signed']))
    key = keys.PrivateKey(typed_txn_fixture['key'])
    signer_by_key = key.public_key.to_canonical_address()
    assert is_same_address(transaction.sender, signer_by_key)
示例#60
0
def test_verify_closing_sign(channel_manager_address: str):
    sig = sign_close(RECEIVER_PRIVATE_KEY, SENDER_ADDR, 315832, 13,
                     channel_manager_address)
    receiver_recovered = verify_closing_sig(SENDER_ADDR, 315832, 13, sig,
                                            channel_manager_address)
    assert is_same_address(receiver_recovered, RECEIVER_ADDR)