Example #1
0
 def register_payment(self, sender: str, open_block_number: int, balance: int, signature: str):
     """Register a payment.
     Method will try to reconstruct (verify) balance update data
     with a signature sent by the client.
     If verification is succesfull, an internal payment state is updated.
     Parameters:
         sender (str):               sender of the balance proof
         open_block_number (int):    block the channel was opened in
         balance (int):              updated balance
         signature(str):             balance proof to verify
     """
     assert is_checksum_address(sender)
     c = self.verify_balance_proof(sender, open_block_number, balance, signature)
     if balance <= c.balance:
         raise InvalidBalanceAmount('The balance must not decrease.')
     if balance > c.deposit:
         raise InvalidBalanceProof('Balance must not be greater than deposit')
     received = balance - c.balance
     c.balance = balance
     c.last_signature = signature
     c.mtime = time.time()
     self.state.set_channel(c)
     self.log.debug('registered payment (sender %s, block number %s, new balance %s)',
                    c.sender, open_block_number, balance)
     return c.sender, received
Example #2
0
 def sign_close(self, sender: str, open_block_number: int, balance: int):
     """Sign an agreement for a channel closing.
     Returns:
         channel close signature (str): a signature that can be used client-side to close
         the channel by directly calling contract's close method on-chain.
     """
     assert is_checksum_address(sender)
     if (sender, open_block_number) not in self.channels:
         raise NoOpenChannel('Channel does not exist or has been closed'
                             '(sender=%s, open_block_number=%d)' % (sender, open_block_number))
     c = self.channels[sender, open_block_number]
     if c.is_closed:
         raise NoOpenChannel('Channel closing has been requested already.')
     assert balance is not None
     if c.last_signature is None:
         raise NoBalanceProofReceived('Payment has not been registered.')
     if balance != c.balance:
         raise InvalidBalanceProof('Requested closing balance does not match latest one.')
     c.is_closed = True
     c.mtime = time.time()
     receiver_sig = sign_close(
         self.private_key,
         sender,
         open_block_number,
         c.balance,
         self.channel_manager_contract.address
     )
     self.state.set_channel(c)
     self.log.info('signed cooperative closing message (sender %s, block number %s)',
                   sender, open_block_number)
     return receiver_sig
Example #3
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
Example #4
0
def test_eth_account_privateKeyToAccount_properties(acct, PRIVATE_BYTES):
    account = acct.privateKeyToAccount(PRIVATE_BYTES)
    assert callable(account.signHash)
    assert callable(account.signTransaction)
    assert is_checksum_address(account.address)
    assert account.address == '0xa79F6f349C853F9Ea0B29636779ae3Cb4E3BA729'
    assert account.privateKey == PRIVATE_BYTES
Example #5
0
 def event_channel_close_requested(
     self,
     sender: str,
     open_block_number: int,
     balance: int,
     settle_timeout: int
 ):
     """Notify the channel manager that a the closing of a channel has been requested.
     Params:
         settle_timeout (int):   settle timeout in blocks"""
     assert is_checksum_address(sender)
     assert settle_timeout >= 0
     if (sender, open_block_number) not in self.channels:
         self.log.warning(
             'attempt to close a non existing channel (sender %ss, block_number %ss)',
             sender,
             open_block_number
         )
         return
     c = self.channels[sender, open_block_number]
     if c.balance > balance:
         self.log.warning('sender tried to cheat, sending challenge '
                          '(sender %s, block number %s)',
                          sender, open_block_number)
         self.close_channel(sender, open_block_number)  # dispute by closing the channel
     else:
         self.log.info('valid channel close request received '
                       '(sender %s, block number %s, timeout %d)',
                       sender, open_block_number, settle_timeout)
         c.settle_timeout = settle_timeout
         c.is_closed = True
         c.confirmed = True
         c.mtime = time.time()
     self.state.set_channel(c)
Example #6
0
def validate_address(value):
    """
    Helper function for validating an address
    """
    if is_bytes(value):
        if not is_binary_address(value):
            raise InvalidAddress("Address must be 20 bytes when input type is bytes", value)
        return

    if not isinstance(value, str):
        raise TypeError('Address {} must be provided as a string'.format(value))
    if not is_hex_address(value):
        raise InvalidAddress("Address must be 20 bytes, as a hex string with a 0x prefix", value)
    if not is_checksum_address(value):
        if value == value.lower():
            raise InvalidAddress(
                "Web3.py only accepts checksum addresses. "
                "The software that gave you this non-checksum address should be considered unsafe, "
                "please file it as a bug on their platform. "
                "Try using an ENS name instead. Or, if you must accept lower safety, "
                "use Web3.toChecksumAddress(lower_case_address).",
                value,
            )
        else:
            raise InvalidAddress(
                "Address has an invalid EIP-55 checksum. "
                "After looking up the address from the original source, try again.",
                value,
            )
Example #7
0
    def setup_address(self, name, address=default, transact={}):
        '''
        Set up the name to point to the supplied address.
        The sender of the transaction must own the name, or
        its parent name.

        Example: If the caller owns ``parentname.eth`` with no subdomains
        and calls this method with ``sub.parentname.eth``,
        then ``sub`` will be created as part of this call.

        :param str name: ENS name to set up, in checksum format
        :param str address: name will point to this address. If ``None``, erase the record.
            If not specified, name will point to the owner's address.
        :param dict transact: the transaction configuration, like in
            :meth:`~web3.eth.Eth.sendTransaction`
        :raises InvalidName: if ``name`` has invalid syntax
        :raises UnauthorizedError: if ``'from'`` in `transact` does not own `name`
        '''
        owner = self.setup_owner(name, transact=transact)
        self._assert_control(owner, name)
        if not address or address == EMPTY_ADDR_HEX:
            address = None
        elif address is default:
            address = owner
        elif not is_checksum_address(address):
            raise ValueError("You must supply the address in checksum format")
        if self.address(name) == address:
            return None
        if address is None:
            address = EMPTY_ADDR_HEX
        transact['from'] = owner
        resolver = self._set_resolver(name, transact=transact)
        return resolver.setAddr(dot_eth_namehash(name), address, transact=transact)
Example #8
0
 def test_personal_listAccounts(self, web3):
     accounts = web3.personal.listAccounts
     assert is_list_like(accounts)
     assert len(accounts) > 0
     assert all((
         is_checksum_address(item)
         for item
         in accounts
     ))
Example #9
0
    def estimateGas(self, transaction):
        # TODO: move to middleware
        if 'from' not in transaction and is_checksum_address(self.defaultAccount):
            transaction = assoc(transaction, 'from', self.defaultAccount)

        return self.web3.manager.request_blocking(
            "eth_estimateGas",
            [transaction],
        )
Example #10
0
def validate_address(value):
    """
    Helper function for validating an address
    """
    if not isinstance(value, str):
        raise TypeError('Address {} must be provided as a string'.format(value))
    if not is_hex_address(value):
        raise InvalidAddress("Address must be 20 bytes, as a hex string with a 0x prefix", value)
    if not is_checksum_address(value):
        raise InvalidAddress("Address has an invalid EIP checksum", value)
Example #11
0
def deploy_contract(web3, name, factory):
    web3.personal.unlockAccount(web3.eth.coinbase, KEYFILE_PW)
    deploy_txn_hash = factory.constructor().transact({'from': web3.eth.coinbase})
    print('{0}_CONTRACT_DEPLOY_HASH: '.format(name.upper()), deploy_txn_hash)
    deploy_receipt = mine_transaction_hash(web3, deploy_txn_hash)
    print('{0}_CONTRACT_DEPLOY_TRANSACTION_MINED'.format(name.upper()))
    contract_address = deploy_receipt['contractAddress']
    assert is_checksum_address(contract_address)
    print('{0}_CONTRACT_ADDRESS:'.format(name.upper()), contract_address)
    return deploy_receipt
Example #12
0
 def force_close_channel(self, sender: str, open_block_number: int):
     """Forcibly remove a channel from our channel state"""
     assert is_checksum_address(sender)
     try:
         self.close_channel(sender, open_block_number)
         return
     except NoBalanceProofReceived:
         c = self.channels[sender, open_block_number]
         c.is_closed = True
         self.state.set_channel(c)
Example #13
0
 def test_eth_accounts(self, web3):
     accounts = web3.eth.accounts
     assert is_list_like(accounts)
     assert len(accounts) != 0
     assert all((
         is_checksum_address(account)
         for account
         in accounts
     ))
     assert web3.eth.coinbase in accounts
Example #14
0
 def event_channel_opened(self, sender: str, open_block_number: int, deposit: int):
     """Notify the channel manager of a new confirmed channel opening."""
     assert is_checksum_address(sender)
     if (sender, open_block_number) in self.channels:
         return  # ignore event if already provessed
     c = Channel(self.state.receiver, sender, deposit, open_block_number)
     c.confirmed = True
     c.state = ChannelState.OPEN
     self.log.info('new channel opened (sender %s, block number %s)', sender, open_block_number)
     self.state.set_channel(c)
Example #15
0
def test_register_token(api_backend, token_amount, token_addresses, raiden_network):
    app0 = raiden_network[0]
    new_token_address = deploy_contract_web3(
        CONTRACT_HUMAN_STANDARD_TOKEN,
        app0.raiden.chain.client,
        num_confirmations=None,
        constructor_arguments=(
            token_amount,
            2,
            'raiden',
            'Rd',
        ),
    )
    other_token_address = deploy_contract_web3(
        CONTRACT_HUMAN_STANDARD_TOKEN,
        app0.raiden.chain.client,
        num_confirmations=None,
        constructor_arguments=(
            token_amount,
            2,
            'raiden',
            'Rd',
        ),
    )

    register_request = grequests.put(api_url_for(
        api_backend,
        'registertokenresource',
        token_address=to_checksum_address(new_token_address),
    ))
    register_response = register_request.send().response
    assert_proper_response(register_response, status_code=HTTPStatus.CREATED)
    response_json = register_response.json()
    assert 'token_network_address' in response_json
    assert is_checksum_address(response_json['token_network_address'])

    # now try to reregister it and get the error
    conflict_request = grequests.put(api_url_for(
        api_backend,
        'registertokenresource',
        token_address=to_checksum_address(new_token_address),
    ))
    conflict_response = conflict_request.send().response
    assert_response_with_error(conflict_response, HTTPStatus.CONFLICT)

    # Burn all the eth and then make sure we get the appropriate API error
    burn_all_eth(app0.raiden)
    poor_request = grequests.put(api_url_for(
        api_backend,
        'registertokenresource',
        token_address=to_checksum_address(other_token_address),
    ))
    poor_response = poor_request.send().response
    assert_response_with_error(poor_response, HTTPStatus.PAYMENT_REQUIRED)
Example #16
0
    def traceCall(self, transaction, mode=['trace'], block_identifier=None):
        # TODO: move to middleware
        if 'from' not in transaction and is_checksum_address(self.defaultAccount):
            transaction = assoc(transaction, 'from', self.defaultAccount)

        # TODO: move to middleware
        if block_identifier is None:
            block_identifier = self.defaultBlock
        return self.web3.manager.request_blocking(
            "trace_call",
            [transaction, mode, block_identifier],
        )
Example #17
0
    def to_python(self, value):
        if not is_0x_prefixed(value):
            raise InvalidEndpoint('Not a valid hex address, 0x prefix missing.')

        if not is_checksum_address(value):
            raise InvalidEndpoint('Not a valid EIP55 encoded address.')

        try:
            value = to_canonical_address(value)
        except ValueError:
            raise InvalidEndpoint('Could not decode hex.')

        return value
Example #18
0
    def close_channel(self, sender: str, open_block_number: int):
        """Close and settle a channel.
        Params:
            sender (str):               sender address
            open_block_number (int):    block the channel was open in
        """
        assert is_checksum_address(sender)
        if not (sender, open_block_number) in self.channels:
            self.log.warning(
                "attempt to close a non-registered channel (sender=%s open_block=%s" %
                (sender, open_block_number)
            )
            return
        c = self.channels[sender, open_block_number]
        if c.last_signature is None:
            raise NoBalanceProofReceived('Cannot close a channel without a balance proof.')
        # send closing tx
        closing_sig = sign_close(
            self.private_key,
            sender,
            open_block_number,
            c.balance,
            self.channel_manager_contract.address
        )

        raw_tx = create_signed_contract_transaction(
            self.private_key,
            self.channel_manager_contract,
            'cooperativeClose',
            [
                self.state.receiver,
                open_block_number,
                c.balance,
                decode_hex(c.last_signature),
                closing_sig
            ]
        )

        # update local state
        c.is_closed = True
        c.mtime = time.time()
        self.state.set_channel(c)

        try:
            txid = self.blockchain.web3.eth.sendRawTransaction(raw_tx)
            self.log.info('sent channel close(sender %s, block number %s, tx %s)',
                          sender, open_block_number, txid)
        except InsufficientBalance:
            c.state = ChannelState.CLOSE_PENDING
            self.state.set_channel(c)
            raise
Example #19
0
    def estimateGas(self, transaction, block_identifier=None):
        # TODO: move to middleware
        if 'from' not in transaction and is_checksum_address(self.defaultAccount):
            transaction = assoc(transaction, 'from', self.defaultAccount)

        if block_identifier is None:
            params = [transaction]
        else:
            params = [transaction, block_identifier]

        return self.web3.manager.request_blocking(
            "eth_estimateGas",
            params,
        )
Example #20
0
 def unconfirmed_event_channel_opened(self, sender: str, open_block_number: int, deposit: int):
     """Notify the channel manager of a new channel opening that has not been confirmed yet."""
     assert is_checksum_address(sender)
     assert deposit >= 0
     assert open_block_number > 0
     event_already_processed = (sender, open_block_number) in self.unconfirmed_channels
     channel_already_confirmed = (sender, open_block_number) in self.channels
     if event_already_processed or channel_already_confirmed:
         return
     c = Channel(self.state.receiver, sender, deposit, open_block_number)
     c.confirmed = False
     c.state = ChannelState.OPEN
     self.state.set_channel(c)
     self.log.info('unconfirmed channel event received (sender %s, block_number %s)',
                   sender, open_block_number)
Example #21
0
def address_checksum_and_decode(addr: str) -> typing.Address:
    """ Accepts a string address and turns it into binary.

        Makes sure that the string address provided starts is 0x prefixed and
        checksummed according to EIP55 specification
    """
    if addr[:2] != '0x':
        raise InvalidAddress('Address must be 0x prefixed')

    if not is_checksum_address(addr):
        raise InvalidAddress('Address must be EIP55 checksummed')

    addr = unhexlify(addr[2:])
    assert len(addr) in (20, 0)
    return addr
Example #22
0
    def _deserialize(self, value, attr, data):
        if not is_0x_prefixed(value):
            self.fail('missing_prefix')

        if not is_checksum_address(value):
            self.fail('invalid_checksum')

        try:
            value = to_canonical_address(value)
        except ValueError:
            self.fail('invalid_data')

        if len(value) != 20:
            self.fail('invalid_size')

        return value
Example #23
0
 def unconfirmed_event_channel_topup(
         self, sender, open_block_number, txhash, added_deposit
 ):
     """Notify the channel manager of a topup with not enough confirmations yet."""
     assert is_checksum_address(sender)
     if (sender, open_block_number) not in self.channels:
         assert (sender, open_block_number) in self.unconfirmed_channels
         self.log.info('Ignoring unconfirmed topup of unconfirmed channel '
                       '(sender %s, block number %s, added %s)',
                       sender, open_block_number, added_deposit)
         return
     self.log.info('Registering unconfirmed deposit top up '
                   '(sender %s, block number %s, added %s)',
                   sender, open_block_number, added_deposit)
     c = self.channels[sender, open_block_number]
     c.unconfirmed_topups[txhash] = added_deposit
     self.state.set_channel(c)
Example #24
0
    def sendTransaction(self, transaction):
        # TODO: move to middleware
        if 'from' not in transaction and is_checksum_address(self.defaultAccount):
            transaction = assoc(transaction, 'from', self.defaultAccount)

        # TODO: move gas estimation in middleware
        if 'gas' not in transaction:
            transaction = assoc(
                transaction,
                'gas',
                get_buffered_gas_estimate(self.web3, transaction),
            )

        return self.web3.manager.request_blocking(
            "eth_sendTransaction",
            [transaction],
        )
Example #25
0
def patched_web3_eth_estimate_gas(self, transaction, block_identifier=None):
    """ Temporary workaround until next web3.py release (5.X.X)

    Current master of web3.py has this implementation already:
    https://github.com/ethereum/web3.py/blob/2a67ea9f0ab40bb80af2b803dce742d6cad5943e/web3/eth.py#L311
    """
    if 'from' not in transaction and is_checksum_address(self.defaultAccount):
        transaction = assoc(transaction, 'from', self.defaultAccount)

    if block_identifier is None:
        params = [transaction]
    else:
        params = [transaction, block_identifier]

    return self.web3.manager.request_blocking(
        'eth_estimateGas',
        params,
    )
Example #26
0
 def event_channel_topup(self, sender, open_block_number, txhash, added_deposit):
     """Notify the channel manager that the deposit of a channel has been topped up."""
     assert is_checksum_address(sender)
     self.log.info(
         'Registering deposit top up (sender %s, block number %s, added deposit %s)',
         sender, open_block_number, added_deposit
     )
     assert (sender, open_block_number) in self.channels
     c = self.channels[sender, open_block_number]
     if c.is_closed is True:
         self.log.warning(
             "Topup of an already closed channel (sender=%s open_block=%d)" %
             (sender, open_block_number)
         )
         return None
     c.deposit += added_deposit
     c.unconfirmed_topups.pop(txhash, None)
     c.mtime = time.time()
     self.state.set_channel(c)
Example #27
0
    def setup_name(self, name, address=None, transact={}):
        '''
        Set up the address for reverse lookup, aka "caller ID".
        After successful setup, the method :meth:`~ens.main.ENS.name` will return
        `name` when supplied with `address`.

        :param str name: ENS name that address will point to
        :param str address: to set up, in checksum format
        :param dict transact: the transaction configuration, like in
            :meth:`~web3.eth.sendTransaction`
        :raises AddressMismatch: if the name does not already point to the address
        :raises InvalidName: if `name` has invalid syntax
        :raises UnauthorizedError: if ``'from'`` in `transact` does not own `name`
        :raises UnownedName: if no one owns `name`
        '''
        if not name:
            self._assert_control(address, 'the reverse record')
            return self._setup_reverse(None, address, transact=transact)
        else:
            resolved = self.address(name)
            if not address:
                address = resolved
            elif resolved and address != resolved:
                raise AddressMismatch(
                    "Could not set address %r to point to name, because the name resolves to %r. "
                    "To change the name for an existing address, call setup_address() first." % (
                        address, resolved
                    )
                )
            if not address:
                address = self.owner(name)
            if not address:
                raise UnownedName("claim subdomain using setup_address() first")
            if is_binary_address(address):
                address = to_checksum_address(address)
            if not is_checksum_address(address):
                raise ValueError("You must supply the address in checksum format")
            self._assert_control(address, name)
            if not resolved:
                self.setup_address(name, address, transact=transact)
            return self._setup_reverse(name, address, transact=transact)
Example #28
0
 def test_eth_accounts(self, web3):
     accounts = web3.eth.accounts
     assert is_list_like(accounts)
     assert len(accounts) != 0
     assert all((is_checksum_address(account) for account in accounts))
     assert web3.eth.coinbase in accounts
Example #29
0
 def test_personal_list_accounts(self, web3: "Web3") -> None:
     accounts = web3.geth.personal.list_accounts()
     assert is_list_like(accounts)
     assert len(accounts) > 0
     assert all((is_checksum_address(item) for item in accounts))
Example #30
0
 def convert(self, value, param, ctx):
     if is_checksum_address(value):
         return value
     self.fail('{} is not a valid EIP-55 checksum address'.format(
         value, param, ctx))
Example #31
0
def test_pubkeytoaddr():
    pubkey = encode_hex(os.urandom(64))
    addr = utils.pubkeytoaddr(pubkey)
    assert is_checksum_address(addr)
Example #32
0
 def siphon_invalid_entries(candidate):
     address_is_valid = eth_utils.is_checksum_address(candidate.address)
     if not address_is_valid:
         invalid_addresses.append(candidate.address)
     return address_is_valid
Example #33
0
def is_not_address_string(value: Any) -> bool:
    return (is_string(value) and not is_bytes(value)
            and not is_checksum_address(value) and not is_hex_address(value))
Example #34
0
def currencynetwork(
    name: str,
    symbol: str,
    decimals: int,
    jsonrpc: str,
    fee_rate: float,
    default_interest_rate: float,
    custom_interests: bool,
    prevent_mediator_interests: bool,
    exchange_contract: str,
    currency_network_contract_name: str,
    expiration_time: int,
    expiration_date: pendulum.DateTime,
    gas: int,
    gas_price: int,
    nonce: int,
    auto_nonce: bool,
    keystore: str,
):
    """Deploy a currency network contract with custom settings and optionally connect it to an exchange contract"""
    if exchange_contract is not None and not is_checksum_address(
            exchange_contract):
        raise click.BadParameter(
            "{} is not a valid address.".format(exchange_contract))

    if custom_interests and default_interest_rate != 0.0:
        raise click.BadParameter("Custom interests can only be set without a"
                                 " default interest rate, but was {}%.".format(
                                     default_interest_rate))

    if prevent_mediator_interests and not custom_interests:
        raise click.BadParameter(
            "Prevent mediator interests is not necessary if custom interests are disabled."
        )

    if expiration_date is not None and expiration_time is not None:
        raise click.BadParameter(
            "Both --expiration-date and --expiration-times have been specified."
        )

    if expiration_date is None and expiration_time is None:
        expiration_time = 0

    if expiration_date is not None:
        expiration_time = int(expiration_date.timestamp())

    fee_divisor = 1 / fee_rate * 100 if fee_rate != 0 else 0
    if int(fee_divisor) != fee_divisor:
        raise click.BadParameter("This fee rate is not usable")
    fee_divisor = int(fee_divisor)

    default_interest_rate = default_interest_rate * 100
    if int(default_interest_rate) != default_interest_rate:
        raise click.BadParameter("This default interest rate is not usable")
    default_interest_rate = int(default_interest_rate)

    web3 = connect_to_json_rpc(jsonrpc)
    private_key = retrieve_private_key(keystore)
    nonce = get_nonce(web3=web3,
                      nonce=nonce,
                      auto_nonce=auto_nonce,
                      private_key=private_key)
    transaction_options = build_transaction_options(gas=gas,
                                                    gas_price=gas_price,
                                                    nonce=nonce)

    network_settings = NetworkSettings(
        name=name,
        symbol=symbol,
        decimals=decimals,
        fee_divisor=fee_divisor,
        default_interest_rate=default_interest_rate,
        custom_interests=custom_interests,
        prevent_mediator_interests=prevent_mediator_interests,
        expiration_time=expiration_time,
    )

    contract = deploy_network(
        web3,
        network_settings,
        exchange_address=exchange_contract,
        currency_network_contract_name=currency_network_contract_name,
        transaction_options=transaction_options,
        private_key=private_key,
    )

    click.echo("CurrencyNetwork(name={name}, symbol={symbol}, "
               "decimals={decimals}, fee_divisor={fee_divisor}, "
               "default_interest_rate={default_interest_rate}, "
               "custom_interests={custom_interests}, "
               "prevent_mediator_interests={prevent_mediator_interests}, "
               "exchange_address={exchange_address}): {address}".format(
                   name=name,
                   symbol=symbol,
                   decimals=decimals,
                   fee_divisor=fee_divisor,
                   default_interest_rate=default_interest_rate,
                   custom_interests=custom_interests,
                   prevent_mediator_interests=prevent_mediator_interests,
                   exchange_address=exchange_contract,
                   address=to_checksum_address(contract.address),
               ))
Example #35
0
def main(
    eth_rpc,
    registry_address,
    start_block,
    port,
    confirmations,
):
    # setup logging
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        datefmt='%m-%d %H:%M:%S',
    )

    logging.getLogger('web3').setLevel(logging.INFO)
    logging.getLogger('urllib3.connectionpool').setLevel(logging.ERROR)

    log.info("Starting Raiden Metrics Server")
    try:
        log.info(f'Starting Web3 client for node at {eth_rpc}')
        web3 = Web3(HTTPProvider(eth_rpc))
        web3.middleware_stack.inject(geth_poa_middleware, layer=0)
    except ConnectionError:
        log.error(
            'Can not connect to the Ethereum client. Please check that it is running and that '
            'your settings are correct.')
        sys.exit()

    with no_ssl_verification():
        valid_params_given = is_checksum_address(
            registry_address) and start_block >= 0
        if not valid_params_given:
            try:
                chain_id = int(web3.net.version)
                # use limits for mainnet, pre limits for testnets
                is_mainnet = chain_id == 1
                version = None if is_mainnet else 'pre_limits'
                contract_data = get_contracts_deployed(int(web3.net.version),
                                                       version)
                token_network_registry_info = contract_data['contracts'][
                    CONTRACT_TOKEN_NETWORK_REGISTRY]  # noqa
                registry_address = token_network_registry_info['address']
                start_block = max(
                    0, token_network_registry_info['block_number'] - 100)
            except ValueError:
                log.error(
                    'Provided registry address or start block are not valid and '
                    'no deployed contracts were found')
                sys.exit(1)

        try:
            service = MetricsService(
                web3=web3,
                contract_manager=ContractManager(contracts_precompiled_path()),
                registry_address=registry_address,
                sync_start_block=start_block,
                required_confirmations=confirmations,
            )

            # re-enable once deployment works
            # gevent.spawn(write_topology_task, service)

            api = NetworkInfoAPI(service)
            api.run(port=port)
            print(f'Running metrics endpoint at http://localhost:{port}/json')

            print('Raiden Status Page backend running...')
            service.run()

        except (KeyboardInterrupt, SystemExit):
            print('Exiting...')
        finally:
            if service:
                log.info('Stopping Raiden Metrics Backend')
                service.stop()

    return 0
Example #36
0
 def test_personal_listAccounts(self, web3):
     accounts = web3.parity.personal.listAccounts()
     assert is_list_like(accounts)
     assert len(accounts) > 0
     assert all((is_checksum_address(item) for item in accounts))
Example #37
0
 def test_personal_newAccount(self, web3):
     new_account = web3.parity.personal.newAccount(PASSWORD)
     assert is_checksum_address(new_account)
Example #38
0
 def test_eth_coinbase(self, web3: "Web3") -> None:
     coinbase = web3.eth.coinbase
     assert is_checksum_address(coinbase)
Example #39
0
def ursula(config, action, rest_port, rest_host, db_name, checksum_address,
           debug, teacher_uri, min_stake) -> None:
    """
    Manage and run an Ursula node

    Here is the procedure to "spin-up" an Ursula node.

    \b
        0. Validate CLI Input
        1. Initialize UrsulaConfiguration (from configuration file or inline)
        2. Initialize Ursula with Passphrase
        3. Initialize Staking Loop
        4. Run TLS deployment (Learning Loop + Reactor)

    """
    log = Logger("ursula/launch")

    # NOTE: Requires ~1GB free memory
    password = os.environ.get(config._KEYRING_PASSPHRASE_ENVVAR, None)
    if not password:
        password = click.prompt("Password to unlock Ursula's keyring",
                                hide_input=True)

    if debug:

        # Sentry
        globalLogPublisher.removeObserver(logToSentry)
        config.log_to_sentry = False

        # Print
        globalLogPublisher.addObserver(simpleObserver)

    def __make_ursula():
        if not checksum_address and not config.dev:
            raise click.BadArgumentUsage(
                "No Configuration file found, and no --checksum address <addr> was provided."
            )
        if not checksum_address and not config.dev:
            raise click.BadParameter(
                message="No account specified. pass --checksum-address, --dev, "
                "or use a configuration file with --config-file <path>")

        return UrsulaConfiguration(temp=config.dev,
                                   auto_initialize=config.dev,
                                   is_me=True,
                                   rest_host=rest_host,
                                   rest_port=rest_port,
                                   db_name=db_name,
                                   federated_only=config.federated_only,
                                   registry_filepath=config.registry_filepath,
                                   provider_uri=config.provider_uri,
                                   checksum_address=checksum_address,
                                   poa=config.poa,
                                   save_metadata=False,
                                   load_metadata=True,
                                   start_learning_now=True,
                                   learn_on_same_thread=False,
                                   abort_on_learning_error=config.dev)

    #
    # Configure
    #
    overrides = dict()
    if config.dev:
        ursula_config = __make_ursula()
    else:
        try:
            filepath = config.config_file or UrsulaConfiguration.DEFAULT_CONFIG_FILE_LOCATION
            click.secho(
                "Reading Ursula node configuration file {}".format(filepath),
                fg='blue')
            ursula_config = UrsulaConfiguration.from_configuration_file(
                filepath=filepath)

        except FileNotFoundError:

            # Continue without a configuration file
            ursula_config = __make_ursula()

    config.operating_mode = "federated" if ursula_config.federated_only else "decentralized"
    click.secho("Running in {} mode".format(config.operating_mode), fg='blue')

    #
    # Seed
    #
    teacher_nodes = list()
    if teacher_uri:

        if '@' in teacher_uri:
            checksum_address, teacher_uri = teacher_uri.split("@")
            if not is_checksum_address(checksum_address):
                raise click.BadParameter(
                    "{} is not a valid checksum address.".format(
                        checksum_address))
        else:
            checksum_address = None  # federated

        # HTTPS Explicit Required
        parsed_teacher_uri = urlparse(teacher_uri)
        if not parsed_teacher_uri.scheme == "https":
            raise click.BadParameter(
                "Invalid teacher URI. Is the hostname prefixed with 'https://' ?"
            )

        port = parsed_teacher_uri.port or UrsulaConfiguration.DEFAULT_REST_PORT
        while not teacher_nodes:
            try:
                teacher = Ursula.from_seed_and_stake_info(
                    host=parsed_teacher_uri.hostname,
                    port=port,
                    federated_only=ursula_config.federated_only,
                    checksum_address=checksum_address,
                    minimum_stake=min_stake,
                    certificates_directory=ursula_config.known_certificates_dir
                )
                teacher_nodes.append(teacher)
            except (socket.gaierror, requests.exceptions.ConnectionError,
                    ConnectionRefusedError):
                log.warn("Can't connect to seed node.  Will retry.")
                time.sleep(5)

    #
    # Produce
    #
    try:
        URSULA = ursula_config.produce(passphrase=password,
                                       known_nodes=teacher_nodes,
                                       **overrides)  # 2
    except CryptoError:
        click.secho("Invalid keyring passphrase")
        return

    click.secho("Initialized Ursula {}".format(URSULA), fg='green')

    #
    # Run
    #
    if action == 'run':
        try:

            # GO!
            click.secho("Running Ursula on {}".format(URSULA.rest_interface),
                        fg='green',
                        bold=True)
            if not debug:
                stdio.StandardIO(UrsulaCommandProtocol(ursula=URSULA))
            URSULA.get_deployer().run()

        except Exception as e:
            config.log.critical(str(e))
            click.secho("{} {}".format(e.__class__.__name__, str(e)), fg='red')
            raise  # Crash

        finally:
            click.secho("Stopping Ursula")
            ursula_config.cleanup()
            click.secho("Ursula Stopped", fg='red')

    elif action == "save-metadata":
        metadata_path = URSULA.write_node_metadata(node=URSULA)
        click.secho(
            "Successfully saved node metadata to {}.".format(metadata_path),
            fg='green')

    else:
        raise click.BadArgumentUsage
Example #40
0
 def test_personal_listAccounts_deprecated(self, web3: "Web3") -> None:
     with pytest.warns(DeprecationWarning):
         accounts = web3.geth.personal.listAccounts()
         assert is_list_like(accounts)
         assert len(accounts) > 0
         assert all((is_checksum_address(item) for item in accounts))
Example #41
0
def math_contract(web3, math_contract_factory, math_contract_deploy_txn_hash):
    deploy_receipt = web3.eth.waitForTransactionReceipt(math_contract_deploy_txn_hash)
    assert is_dict(deploy_receipt)
    contract_address = deploy_receipt['contractAddress']
    assert is_checksum_address(contract_address)
    return math_contract_factory(contract_address)
def test_read_beneficiary(testerchain, agent):
    deployer_address, beneficiary_address, *everybody_else = testerchain.client.accounts
    beneficiary = agent.beneficiary
    assert beneficiary == beneficiary_address
    assert is_checksum_address(beneficiary)
Example #43
0
def funded_account_for_raw_txn(geth_fixture_data):
    account = geth_fixture_data['raw_txn_account']
    assert is_checksum_address(account)
    return account
Example #44
0
    def generate(cls,
                 password: str,
                 encrypting: bool,
                 rest: bool,
                 host: str = None,
                 curve: EllipticCurve = None,
                 keyring_root: str = None,
                 checksum_address: str = None) -> 'NucypherKeyring':
        """
        Generates new encrypting, signing, and wallet keys encrypted with the password,
        respectively saving keyfiles on the local filesystem from *default* paths,
        returning the corresponding Keyring instance.
        """

        failures = cls.validate_password(password)
        if failures:
            raise cls.AuthenticationFailed(
                ", ".join(failures)
            )  # TODO: Ensure this scope is seperable from the scope containing the password

        if not any((encrypting, rest)):
            raise ValueError(
                'Either "encrypting", "wallet", or "tls" must be True '
                'to generate new keys, or set "no_keys" to True to skip generation.'
            )

        if curve is None:
            curve = cls.__DEFAULT_TLS_CURVE

        if checksum_address is not None and not is_checksum_address(
                checksum_address):
            raise ValueError(
                f"{checksum_address} is not a valid ethereum checksum address")

        _base_filepaths = cls._generate_base_filepaths(
            keyring_root=keyring_root)
        _public_key_dir = _base_filepaths['public_key_dir']
        _private_key_dir = _base_filepaths['private_key_dir']

        # Write to disk
        if not os.path.isdir(_public_key_dir):
            os.mkdir(_public_key_dir, mode=0o744)  # public dir

        if not os.path.isdir(_private_key_dir):
            os.mkdir(_private_key_dir, mode=0o700)  # private dir

        #
        # Generate New Keypairs
        #

        keyring_args = dict()

        if encrypting is True:
            signing_private_key, signing_public_key = _generate_signing_keys()

            if checksum_address is None:
                uncompressed_bytes = signing_public_key.to_bytes(
                    is_compressed=False)
                without_prefix = uncompressed_bytes[1:]
                verifying_key_as_eth_key = EthKeyAPI.PublicKey(without_prefix)
                checksum_address = verifying_key_as_eth_key.to_checksum_address(
                )

        __key_filepaths = cls._generate_key_filepaths(
            account=checksum_address,
            private_key_dir=_private_key_dir,
            public_key_dir=_public_key_dir)
        if encrypting is True:
            encrypting_private_key, encrypting_public_key = _generate_encryption_keys(
            )
            delegating_keying_material = UmbralKeyingMaterial().to_bytes()

            # Derive Wrapping Keys
            password_salt, encrypting_salt, signing_salt, delegating_salt = (
                os.urandom(32) for _ in range(4))

            cls.log.info("About to derive key from password.")
            derived_key_material = derive_key_from_password(
                salt=password_salt, password=password.encode())
            encrypting_wrap_key = _derive_wrapping_key_from_key_material(
                salt=encrypting_salt, key_material=derived_key_material)
            signature_wrap_key = _derive_wrapping_key_from_key_material(
                salt=signing_salt, key_material=derived_key_material)
            delegating_wrap_key = _derive_wrapping_key_from_key_material(
                salt=delegating_salt, key_material=derived_key_material)

            # Encapsulate Private Keys
            encrypting_key_data = encrypting_private_key.to_bytes(
                wrapping_key=encrypting_wrap_key)
            signing_key_data = signing_private_key.to_bytes(
                wrapping_key=signature_wrap_key)
            delegating_key_data = bytes(
                SecretBox(delegating_wrap_key).encrypt(
                    delegating_keying_material))

            # Assemble Private Keys
            encrypting_key_metadata = _assemble_key_data(
                key_data=encrypting_key_data,
                master_salt=password_salt,
                wrap_salt=encrypting_salt)
            signing_key_metadata = _assemble_key_data(
                key_data=signing_key_data,
                master_salt=password_salt,
                wrap_salt=signing_salt)
            delegating_key_metadata = _assemble_key_data(
                key_data=delegating_key_data,
                master_salt=password_salt,
                wrap_salt=delegating_salt)

            # Write Private Keys
            rootkey_path = _write_private_keyfile(
                keypath=__key_filepaths['root'],
                key_data=encrypting_key_metadata,
                serializer=cls._private_key_serializer)
            sigkey_path = _write_private_keyfile(
                keypath=__key_filepaths['signing'],
                key_data=signing_key_metadata,
                serializer=cls._private_key_serializer)
            delegating_key_path = _write_private_keyfile(
                keypath=__key_filepaths['delegating'],
                key_data=delegating_key_metadata,
                serializer=cls._private_key_serializer)

            # Write Public Keys
            root_keypath = _write_public_keyfile(
                __key_filepaths['root_pub'], encrypting_public_key.to_bytes())
            signing_keypath = _write_public_keyfile(
                __key_filepaths['signing_pub'], signing_public_key.to_bytes())

            # Commit
            keyring_args.update(
                keyring_root=keyring_root or cls.__default_keyring_root,
                root_key_path=rootkey_path,
                pub_root_key_path=root_keypath,
                signing_key_path=sigkey_path,
                pub_signing_key_path=signing_keypath,
                delegating_key_path=delegating_key_path,
            )

        if rest is True:
            if not all(
                (host, curve, checksum_address)
            ):  # TODO: Do we want to allow showing up with an old wallet and generating a new cert?  Probably.
                raise ValueError(
                    "host, checksum_address and curve are required to make a new keyring TLS certificate. Got {}, {}"
                    .format(host, curve))
            private_key, cert = _generate_tls_keys(
                host=host, checksum_address=checksum_address, curve=curve)

            def __serialize_pem(pk):
                return pk.private_bytes(
                    encoding=serialization.Encoding.PEM,
                    format=serialization.PrivateFormat.TraditionalOpenSSL,
                    encryption_algorithm=serialization.BestAvailableEncryption(
                        password=derived_key_material))

            tls_key_path = _write_private_keyfile(
                keypath=__key_filepaths['tls'],
                key_data=__serialize_pem(pk=private_key),
                serializer=None)
            certificate_filepath = _write_tls_certificate(
                full_filepath=__key_filepaths['tls_certificate'],
                certificate=cert)
            keyring_args.update(tls_certificate_path=certificate_filepath,
                                tls_key_path=tls_key_path)

        keyring_instance = cls(account=checksum_address, **keyring_args)
        return keyring_instance
Example #45
0
def validate_address(ctx, param, value):
    if not is_checksum_address(value):
        raise click.BadParameter("Not a valid checksum address")
    return to_canonical_address(value)
Example #46
0
 def test_personal_newAccount(self, web3):
     new_account = web3.personal.newAccount(PASSWORD)
     assert is_checksum_address(new_account)
def assert_checksum_address_in_url(url):
    message = "URL does not contain properly encoded address."
    assert any(is_checksum_address(token) for token in url.split("/")), message
Example #48
0
 def test_personal_new_account(self, web3: "Web3") -> None:
     new_account = web3.geth.personal.new_account(PASSWORD)
     assert is_checksum_address(new_account)
def main(chain, hot_wallet_address, csv_file, limit, start_from,
         address_column, amount_column, id_column, state_file):
    """Distribute ETh refunds.

    Reads in funds distribution data as CSV. Then sends funds from a local address.

    The refund status is stored as a JSON file.

    Example:

        refund --chain=kovan --hot-wallet-address=0x001fc7d7e506866aeab82c11da515e9dd6d02c25 --csv-file=refunds.csv --address-column="Refund address" --amount-column="ETH" --id-column="Email" --start-from=0 --limit=2 --state-file=refund-state.json

    Example CSV data:

    .. code-block:: csv

        Email,ETH,Refund address
        [email protected],61.52,0x0078EF811B6564c996fD10012579633B1a518b9D
        [email protected],111.21,0xf0b91641CCe2ADB4c0D7B90c54E7eE96CCCBc3d1
        [email protected],61.52,0x0dAbC71Faa8982bF23eE2c4979d22536F5101065
        [email protected],61.52,0x0B8EceBc18153166Beec1b568D510B55B560789D
    """

    # Make a backup of the state file
    if os.path.exists(state_file):
        assert state_file.endswith(".json")
        backup_name = state_file.replace(
            ".json",
            "." + datetime.datetime.utcnow().isoformat() + ".bak.json")
        print("Backing up state file to", backup_name)
        shutil.copy(state_file, backup_name)

    project = Project()

    with project.get_chain(chain) as c:

        web3 = c.web3
        print("Web3 provider is", web3.providers[0])
        print("Hot wallet address is", hot_wallet_address)
        print("Hot wallet balance is",
              from_wei(web3.eth.getBalance(hot_wallet_address), "ether"),
              "ETH")

        # Goes through geth account unlock process if needed
        if is_account_locked(web3, hot_wallet_address):
            request_account_unlock(c, hot_wallet_address, timeout=3600 * 6)
            assert not is_account_locked(web3, hot_wallet_address)

        print("Reading data", csv_file)
        with open(csv_file, "rt", encoding='utf-8-sig') as inp:
            reader = csv.DictReader(inp)
            rows = [row for row in reader]

        # Check that we have unique addresses
        uniq_ids = set()
        for row in rows:
            print(row)
            id = row[id_column].strip()
            if id in uniq_ids:
                raise RuntimeError("Id appears twice in input data", id)
            uniq_ids.add(id)

            addr = row[address_column]
            if not is_checksum_address(addr):
                print("Not a checksummed address", addr)

        # Start distribution
        start_time = time.time()
        start_balance = from_wei(web3.eth.getBalance(hot_wallet_address),
                                 "ether")

        print("Total rows", len(rows))

        if os.path.exists(state_file):
            with open(state_file, "rt") as inp:
                state = json.load(inp)
        else:
            state = {}

        for i in range(start_from, min(start_from + limit, len(rows))):
            data = rows[i]
            addr = data[address_column].strip()
            id = data[id_column].strip()
            amount = Decimal(data[amount_column].strip())
            amount_wei = to_wei(amount, "ether")

            if id in state:
                print("Already refunded", id, addr, amount)
                continue

            # Use non-default gas price for speedier processing
            gas_price = int(web3.eth.gasPrice * 3)

            txid = web3.eth.sendTransaction({
                "from": hot_wallet_address,
                "to": addr,
                "value": amount_wei,
                "gasPrice": gas_price
            })
            duration = time.time() - start_time
            print("Transferring", id, amount_wei, "to", addr, "txid", txid,
                  "duration", duration)

            state[id] = txid
            with open(state_file, "wt") as out:
                json.dump(state, out)

            check_succesful_tx(web3, txid, timeout=300)

        end_balance = from_wei(web3.eth.getBalance(hot_wallet_address),
                               "ether")
        print("Refund cost is", start_balance - end_balance, "ETH")
        print("All done! Enjoy your decentralized future.")
Example #50
0
def emitter_contract(web3, emitter_contract_factory, emitter_contract_deploy_txn_hash):
    deploy_receipt = web3.eth.wait_for_transaction_receipt(emitter_contract_deploy_txn_hash)
    assert is_dict(deploy_receipt)
    contract_address = deploy_receipt['contractAddress']
    assert is_checksum_address(contract_address)
    return emitter_contract_factory(contract_address)
Example #51
0
 def test_wallet_address_is_checksummed(self):
     self.assertTrue(is_checksum_address(self.wallet.address))
Example #52
0
def check_balance_proof(bp):
    assert bp['channel_id'] > 0
    assert is_checksum_address(bp['contract_address'])
    assert is_checksum_address(bp['participant1'])
    assert is_checksum_address(bp['participant2'])
Example #53
0
 def func_wrapper(self, partner_address, *args, **kwargs):
     assert is_checksum_address(partner_address)
     assert partner_address in self.partner_to_channel_id
     return func(self, partner_address, *args, **kwargs)
def test_eth_account_create_properties(acct):
    account = acct.create()
    assert callable(account.signHash)
    assert callable(account.signTransaction)
    assert is_checksum_address(account.address)
    assert isinstance(account.privateKey, bytes) and len(account.privateKey) == 32
Example #55
0
def funded_account_for_raw_txn(parity_fixture_data):
    account = parity_fixture_data['raw_txn_account']
    assert is_checksum_address(account)
    return account
def test_to_checksum_address_from_public_key(private_key):
    address = private_key.public_key.to_checksum_address()
    assert is_checksum_address(address)
    assert is_same_address(address, ADDRESS)
Example #57
0
 def test_eth_coinbase(self, web3):
     coinbase = web3.eth.coinbase
     assert is_checksum_address(coinbase)
Example #58
0
 def test_personal_newAccount_deprecated(self, web3: "Web3") -> None:
     with pytest.warns(DeprecationWarning):
         new_account = web3.geth.personal.newAccount(PASSWORD)
         assert is_checksum_address(new_account)
Example #59
0
def test_eth_account_create_properties(acct):
    account = acct.create()
    assert callable(account.signHash)
    assert callable(account.signTransaction)
    assert is_checksum_address(account.address)
    assert isinstance(account.privateKey, bytes) and len(account.privateKey) == 32
Example #60
0
    def follows_token_network(self, token_network_address: Address) -> bool:
        """ Checks if a token network is followed by the pathfinding service. """
        assert is_checksum_address(token_network_address)

        return token_network_address in self.token_networks.keys()