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
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
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
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
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)
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, )
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)
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 ))
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], )
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)
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
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)
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
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)
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)
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], )
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
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
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, )
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)
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
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
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)
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], )
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, )
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)
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)
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
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))
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))
def test_pubkeytoaddr(): pubkey = encode_hex(os.urandom(64)) addr = utils.pubkeytoaddr(pubkey) assert is_checksum_address(addr)
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
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))
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), ))
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
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))
def test_personal_newAccount(self, web3): new_account = web3.parity.personal.newAccount(PASSWORD) assert is_checksum_address(new_account)
def test_eth_coinbase(self, web3: "Web3") -> None: coinbase = web3.eth.coinbase assert is_checksum_address(coinbase)
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
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))
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)
def funded_account_for_raw_txn(geth_fixture_data): account = geth_fixture_data['raw_txn_account'] assert is_checksum_address(account) return account
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
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)
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
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.")
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)
def test_wallet_address_is_checksummed(self): self.assertTrue(is_checksum_address(self.wallet.address))
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'])
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
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)
def test_eth_coinbase(self, web3): coinbase = web3.eth.coinbase assert is_checksum_address(coinbase)
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)
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()