def test_test_privkeys(): try: _services_orig = hydrachain.app.services hydrachain.app.services = services config = default_config() config['data_dir'] = tempfile.mktemp() konfig.setup_data_dir(config['data_dir']) config['node']['privkey_hex'] = '1' * 64 privkeys = [str(i) * 32 for i in range(5)] config['test_privkeys'] = privkeys config['hdc']['validators'] = [privtoaddr(privkeys[0])] app = hydrachain.app.start_app(config, accounts=[]) g = app.services.chain.chain.genesis for p in privkeys: a = privtoaddr(p) assert len(a) == 20 assert g.get_balance(a) > 0 assert a in app.services.accounts account = app.services.accounts[a] assert account.address == a app.stop() finally: hydrachain.app.services = _services_orig
def send_transaction(self, sender, to, value=0, data='', startgas=0, gasprice=10 * denoms.szabo, nonce=None): """ Helper to send signed messages. This method will use the `privkey` provided in the constructor to locally sign the transaction. This requires an extended server implementation that accepts the variables v, r, and s. """ if not self.privkey and not sender: raise ValueError('Either privkey or sender needs to be supplied.') if self.privkey and not sender: sender = privtoaddr(self.privkey) if nonce is None: nonce = self.nonce(sender) elif self.privkey: if sender != privtoaddr(self.privkey): raise ValueError('sender for a different privkey.') if nonce is None: nonce = self.nonce(sender) else: if nonce is None: nonce = 0 if not startgas: startgas = self.gaslimit() - 1 tx = Transaction(nonce, gasprice, startgas, to=to, value=value, data=data) if self.privkey: # add the fields v, r and s tx.sign(self.privkey) tx_dict = tx.to_dict() # rename the fields to match the eth_sendTransaction signature tx_dict.pop('hash') tx_dict['sender'] = sender tx_dict['gasPrice'] = tx_dict.pop('gasprice') tx_dict['gas'] = tx_dict.pop('startgas') res = self.eth_sendTransaction(**tx_dict) assert len(res) in (20, 32) return res.encode('hex')
def test_lock(account, password, privkey): assert not account.locked assert account.address == privtoaddr(privkey) assert account.privkey == privkey assert account.pubkey is not None account.unlock(password + 'fdsa') account.lock() assert account.locked assert account.address == privtoaddr(privkey) assert account.privkey is None assert account.pubkey is None with pytest.raises(ValueError): account.unlock(password + 'fdsa') account.unlock(password)
def rundummy(ctx, num_validators, node_num, seed): # reduce key derivation iterations PBKDF2_CONSTANTS['c'] = 100 config = ctx.obj['config'] # create bootstrap node priv_key and enode bootstrap_node_privkey = mk_privkey('%d:udp:%d' % (seed, 0)) bootstrap_node_pubkey = privtopub_raw(bootstrap_node_privkey) assert len(bootstrap_node_pubkey) == 64, len(bootstrap_node_pubkey) base_port = 29870 host = b'0.0.0.0' bootstrap_node = host_port_pubkey_to_uri(host, base_port, bootstrap_node_pubkey) config['discovery']['bootstrap_nodes'] = [bootstrap_node] # create this node priv_key config['node']['privkey_hex'] = mk_privkey('%d:udp:%d' % (seed, node_num)).encode('hex') # create validator addresses validators = [privtoaddr(mk_privkey('%d:account:%d' % (seed, i))) for i in range(num_validators)] config['hdc']['validators'] = validators # create this node account account = Account.new(password='', key=mk_privkey('%d:account:%d' % (seed, node_num))) # set ports based on node config['discovery']['listen_port'] = base_port + node_num config['p2p']['listen_port'] = base_port + node_num config['p2p']['min_peers'] = 2 config['jsonrpc']['listen_port'] += node_num _start_app(account, config)
def send_transaction(self, sender, to, value=0, data='', startgas=0, gasprice=10 * denoms.szabo): "can send a locally signed transaction if privkey is given" assert self.privkey or sender if self.privkey: _sender = sender sender = privtoaddr(self.privkey) assert sender == _sender assert sender # fetch nonce nonce = self.nonce(sender) if not startgas: startgas = quantity_decoder(self.call('eth_gasLimit')) - 1 # create transaction tx = Transaction(nonce, gasprice, startgas, to=to, value=value, data=data) if self.privkey: tx.sign(self.privkey) tx_dict = tx.to_dict() tx_dict.pop('hash') for k, v in dict(gasprice='gasPrice', startgas='gas').items(): tx_dict[v] = tx_dict.pop(k) tx_dict['sender'] = sender res = self.eth_sendTransaction(**tx_dict) assert len(res) in (20, 32) return res.encode('hex')
class Faucet(object): PRIVKEY = "{:32}".format("Golem Faucet") assert len(PRIVKEY) == 32 PUBKEY = privtopub(PRIVKEY) ADDR = privtoaddr(PRIVKEY) @staticmethod def gimme_money(ethnode, addr, value): nonce = ethnode.get_transaction_count(Faucet.ADDR.encode('hex')) addr = normalize_address(addr) tx = Transaction(nonce, 1, 21000, addr, value, '') tx.sign(Faucet.PRIVKEY) h = ethnode.send(tx) log.info("Faucet --({} ETH)--> {} ({})".format(float(value) / 10**18, addr.encode('hex'), h)) h = h[2:].decode('hex') assert h == tx.hash return h @staticmethod def deploy_contract(ethnode, init_code): nonce = ethnode.get_transaction_count(Faucet.ADDR.encode('hex')) tx = Transaction(nonce, 0, 3141592, to='', value=0, data=init_code) tx.sign(Faucet.PRIVKEY) ethnode.send(tx) return tx.creates
def test_unlock(keystore, password, privkey, uuid): account = Account(keystore) assert account.locked account.unlock(password) assert not account.locked assert account.privkey == privkey assert account.address == privtoaddr(privkey)
def discovery_blockchain(request, private_keys, geth_cluster, poll_timeout): gevent.sleep(2) privatekey = private_keys[0] address = privtoaddr(privatekey) jsonrpc_client = JSONRPCClient( host='0.0.0.0', privkey=privatekey, print_communication=False, ) patch_send_transaction(jsonrpc_client) # deploy discovery contract discovery_contract_path = get_contract_path('EndpointRegistry.sol') discovery_contracts = compile_file(discovery_contract_path, libraries=dict()) discovery_contract_proxy = jsonrpc_client.deploy_solidity_contract( address, 'EndpointRegistry', discovery_contracts, dict(), tuple(), timeout=poll_timeout, ) discovery_contract_address = discovery_contract_proxy.address # initialize and return ContractDiscovery object from raiden.network.discovery import ContractDiscovery return ContractDiscovery(jsonrpc_client, discovery_contract_address), address
def sendout(self): log.debug("Sendout ping") if not self.__awaiting: return payments = self.__awaiting # FIXME: Should this list be synchronized? self.__awaiting = [] addr = keys.privtoaddr(self.__privkey) # TODO: Should be done once? nonce = self.__client.get_transaction_count(addr.encode('hex')) p, value = _encode_payments(payments) data = bank_contract.encode('transfer', [p]) gas = 21000 + len(p) * 30000 tx = Transaction(nonce, self.GAS_PRICE, gas, to=self.BANK_ADDR, value=value, data=data) tx.sign(self.__privkey) h = tx.hash log.info("Batch payments: {}".format(h.encode('hex'))) # Firstly write transaction hash to database. We need the hash to be # remembered before sending the transaction to the Ethereum node in # case communication with the node is interrupted and it will be not # known if the transaction has been sent or not. with Payment._meta.database.transaction(): for payment in payments: assert payment.status == PaymentStatus.awaiting payment.status = PaymentStatus.sent payment.details['tx'] = h.encode('hex') payment.save() tx_hash = self.__client.send(tx) assert tx_hash[2:].decode('hex') == h # FIXME: Improve Client. self.__inprogress[h] = payments
def balance(self, refresh=False): # FIXME: The balance must be actively monitored! if self.__balance is None or refresh: addr = keys.privtoaddr(self.__privkey) # TODO: Hack RPC client to allow using raw address. self.__balance = self.__client.get_balance(addr.encode('hex')) log.info("Balance: {}".format(self.__balance / float(10**18))) return self.__balance
def sender(self): if self.privkey: return privtoaddr(self.privkey) if self._sender is None: self._sender = self.coinbase return self._sender
def test_address(keystore, password, privkey): keystore_wo_address = keystore.copy() keystore_wo_address.pop('address') account = Account(keystore_wo_address) assert account.address is None account.unlock(password) account.lock() assert account.address == privtoaddr(privkey)
def eth_balance(self, refresh=False): # FIXME: The balance must be actively monitored! if self.__eth_balance is None or refresh: addr = keys.privtoaddr(self.__privkey) # TODO: Hack RPC client to allow using raw address. addr = '0x' + addr.encode('hex') self.__eth_balance = self.__client.get_balance(addr) log.info("ETH: {}".format(self.__eth_balance / denoms.ether)) return self.__eth_balance
def __init__(self, datadir): keyfile = path.join(datadir, 'ethkey.json') if path.exists(keyfile): data = json.load(open(keyfile, 'r')) self.priv = keys.decode_keystore_json(data, "FIXME: password!") else: self.priv = os.urandom(32) data = keys.make_keystore_json(self.priv, "FIXME: password!") json.dump(data, open(keyfile, 'w')) self.address = keys.privtoaddr(self.priv)
def sendout(self): if not self._awaiting: return False now = int(time.time()) if self.deadline > now: log.info("Next sendout in {} s".format(self.deadline - now)) return False payments = self._awaiting # FIXME: Should this list be synchronized? self._awaiting = [] self.deadline = sys.maxsize addr = keys.privtoaddr(self.__privkey) # TODO: Should be done once? nonce = self.__client.get_transaction_count('0x' + addr.encode('hex')) p, value = _encode_payments(payments) data = gnt_contract.encode('batchTransfer', [p]) gas = 21000 + 800 + len(p) * 30000 tx = Transaction(nonce, self.GAS_PRICE, gas, to=self.TESTGNT_ADDR, value=0, data=data) tx.sign(self.__privkey) h = tx.hash log.info("Batch payments: {:.6}, value: {:.6f}".format( h.encode('hex'), value / denoms.ether)) # Firstly write transaction hash to database. We need the hash to be # remembered before sending the transaction to the Ethereum node in # case communication with the node is interrupted and it will be not # known if the transaction has been sent or not. with Payment._meta.database.transaction(): for payment in payments: payment.status = PaymentStatus.sent payment.details['tx'] = h.encode('hex') payment.save() log.debug("- {} send to {} ({:.6f})".format( payment.subtask, payment.payee.encode('hex'), payment.value / denoms.ether)) tx_hash = self.__client.send(tx) if tx_hash[2:].decode('hex') != h: # FIXME: Improve Client. raise RuntimeError( "Incorrect tx hash: {}, should be: {}".format( tx_hash[2:].decode('hex'), h)) self._inprogress[h] = payments # Remove from reserved, because we monitor the pending block. # TODO: Maybe we should only monitor the latest block? self.__gnt_reserved -= value return True
def setUp(self): DatabaseFixture.setUp(self) self.privkey = urandom(32) self.addr = privtoaddr(self.privkey) self.client = mock.MagicMock(spec=Client) self.client.get_balance.return_value = 0 self.client.send.side_effect = lambda tx: "0x" + tx.hash.encode('hex') self.nonce = random.randint(0, 9999) self.client.get_transaction_count.return_value = self.nonce # FIXME: PaymentProcessor should be started and stopped! self.pp = PaymentProcessor(self.client, self.privkey) self.pp._loopingCall.clock = Clock() # Disable looping call.
def start_app(config, accounts): # create app app = HPCApp(config) # development mode if False: gevent.get_hub().SYSTEM_ERROR = BaseException if config['test_privkeys']: # init accounts first, as we need (and set by copy) the coinbase early FIXME genesis_config = dict(alloc=dict()) for privkey in config['test_privkeys']: assert len(privkey) == 32 address = privtoaddr(privkey) account = Account.new(password='', key=privkey) accounts.append(account) # add to genesis alloc genesis_config['alloc'][address] = {'wei': config['test_privkeys_endowment']} if config['test_privkeys'] and config['eth'].get('genesis_hash'): del config['eth']['genesis_hash'] konfig.update_config_from_genesis_json(config, genesis_config) # dump config pyethapp_app.dump_config(config) if AccountsService in services: AccountsService.register_with_app(app) # add account for account in accounts: app.services.accounts.add_account(account, store=False) if config['hdc']['validators']: assert app.services.accounts.coinbase in config['hdc']['validators'] # register services for service in services: assert issubclass(service, BaseService) if service.name not in app.config['deactivated_services'] + [AccountsService.name]: assert service.name not in app.services service.register_with_app(app) assert hasattr(app.services, service.name) # start app log.info('starting') app.start() for cb in config['post_app_start_callbacks']: cb(app) return app
def address(self): """The account's address or `None` if the address is not stored in the key file and cannot be reconstructed (because the account is locked) """ if self._address: pass elif 'address' in self.keystore: self._address = self.keystore['address'].decode('hex') elif not self.locked: self._address = keys.privtoaddr(self.privkey) else: return None return self._address
def geth_wait_and_check(privatekeys): """ Wait until the geth cluster is ready. """ address = address_encoder(privtoaddr(privatekeys[0])) jsonrpc_running = False tries = 5 jsonrpc_client = JSONRPCClient( host='0.0.0.0', privkey=privatekeys[0], print_communication=False, ) while not jsonrpc_running and tries > 0: try: jsonrpc_client.call('eth_getBalance', address, 'latest') jsonrpc_running = True except ConnectionError: gevent.sleep(0.5) tries -= 1 if jsonrpc_running is False: raise ValueError('geth didnt start the jsonrpc interface') for key in set(privatekeys): address = address_encoder(privtoaddr(key)) jsonrpc_client = JSONRPCClient( host='0.0.0.0', privkey=key, print_communication=False, ) tries = 10 balance = '0x0' while balance == '0x0' and tries > 0: balance = jsonrpc_client.call('eth_getBalance', address, 'latest') gevent.sleep(1) tries -= 1 if balance == '0x0': raise ValueError('account is with a balance of 0')
def gnt_balance(self, refresh=False): if self.__gnt_balance is None or refresh: addr = keys.privtoaddr(self.__privkey) data = self.__testGNT.encode('balanceOf', (addr, )) r = self.__client.call(_from='0x' + addr.encode('hex'), to='0x' + self.TESTGNT_ADDR.encode('hex'), data='0x' + data.encode('hex'), block='pending') if r is None or r == '0x': self.__gnt_balance = 0 else: self.__gnt_balance = int(r, 16) log.info("GNT: {}".format(self.__gnt_balance / denoms.ether)) return self.__gnt_balance
class Faucet(object): PRIVKEY = "{:32}".format("Golem Faucet") PUBKEY = privtopub(PRIVKEY) ADDR = privtoaddr(PRIVKEY) @staticmethod def gimme_money(ethnode, addr, value): nonce = ethnode.get_transaction_count('0x' + Faucet.ADDR.encode('hex')) addr = normalize_address(addr) tx = Transaction(nonce, 1, 21000, addr, value, '') tx.sign(Faucet.PRIVKEY) h = ethnode.send(tx) log.info("Faucet --({} ETH)--> {} ({})".format( value / denoms.ether, '0x' + addr.encode('hex'), h)) h = h[2:].decode('hex') return h
def new_contract_proxy(self, contract_interface, address): """ Return a proxy for interacting with a smart contract. Args: contract_interface: The contract interface as defined by the json. address: The contract's address. """ sender = self.sender or privtoaddr(self.privkey) return ContractProxy( sender, contract_interface, address, self.eth_call, self.send_transaction, )
def _configure_node_network(config, num_validators, node_num, seed): assert node_num < num_validators # reduce key derivation iterations PBKDF2_CONSTANTS["c"] = 100 # create this node priv_key config["node"]["privkey_hex"] = mk_privkey("%d:udp:%d" % (seed, node_num)).encode("hex") # create validator addresses validators = [privtoaddr(mk_privkey("%d:account:%d" % (seed, i))) for i in range(num_validators)] config["hdc"]["validators"] = validators # create this node account account = Account.new(password="", key=mk_privkey("%d:account:%d" % (seed, node_num))) assert account.address in validators return config, account
def get_gnt_from_faucet(self): if self.__faucet and self.gnt_balance(True) < 100 * denoms.ether: log.info("Requesting tGNT") addr = keys.privtoaddr(self.__privkey) nonce = self.__client.get_transaction_count('0x' + addr.encode('hex')) data = self.__testGNT.encode_function_call('create', ()) tx = Transaction(nonce, self.GAS_PRICE, 90000, to=self.TESTGNT_ADDR, value=0, data=data) tx.sign(self.__privkey) self.__client.send(tx) return False return True
def _configure_node_network(config, num_validators, node_num, seed): assert node_num < num_validators # reduce key derivation iterations PBKDF2_CONSTANTS['c'] = 100 # create this node priv_key config['node']['privkey_hex'] = mk_privkey('%d:udp:%d' % (seed, node_num)).encode('hex') # create validator addresses validators = [privtoaddr(mk_privkey('%d:account:%d' % (seed, i))) for i in range(num_validators)] config['hdc']['validators'] = validators # create this node account account = Account.new(password='', key=mk_privkey('%d:account:%d' % (seed, node_num))) assert account.address in validators return config, account
def __init__(self, datadir, node_priv_key): """ Create new transaction system instance for node with given id :param node_priv_key str: node's private key for Ethereum account (32b) """ super(EthereumTransactionSystem, self).__init__() # FIXME: Passing private key all around might be a security issue. # Proper account managment is needed. if not isinstance(node_priv_key, basestring)\ or len(node_priv_key) != 32: raise ValueError("Invalid private key: {}".format(node_priv_key)) self.__node_address = keys.privtoaddr(node_priv_key) log.info("Node Ethereum address: " + self.get_payment_address()) self.__eth_node = Client(datadir) self.__proc = PaymentProcessor(self.__eth_node, node_priv_key, faucet=True) self.__proc.start()
def __init__(self, client, privkey, faucet=False): self.__client = client self.__privkey = privkey self.__balance = None self.__reserved = 0 self.__awaiting = [] # Awaiting individual payments self.__inprogress = {} # Sent transactions. # Very simple sendout scheduler. # TODO: Maybe it should not be the part of this class # TODO: Allow seting timeout # TODO: Defer a call only if payments waiting scheduler = LoopingCall(self.run) scheduler.start(self.SENDOUT_TIMEOUT) if faucet and self.balance() == 0: value = 100 log.info("Requesting {} ETH from Golem Faucet".format(value)) addr = keys.privtoaddr(self.__privkey) Faucet.gimme_money(client, addr, value * 10**18)
def runlocal(ctx, num_validators, node_num, seed): assert node_num < num_validators # reduce key derivation iterations PBKDF2_CONSTANTS['c'] = 100 config = ctx.obj['config'] # create this node priv_key config['node']['privkey_hex'] = mk_privkey('%d:udp:%d' % (seed, node_num)).encode('hex') # create validator addresses validators = [privtoaddr(mk_privkey('%d:account:%d' % (seed, i))) for i in range(num_validators)] config['hdc']['validators'] = validators # create this node account account = Account.new(password='', key=mk_privkey('%d:account:%d' % (seed, node_num))) assert account.address in validators config['p2p']['min_peers'] = 2 _start_app(account, config, validators)
def addr(seed): return privtoaddr(privkey(seed))
def create_geth_cluster(private_keys, geth_private_keys, p2p_base_port, base_datadir): # pylint: disable=too-many-locals,too-many-statements # TODO: handle better the errors cases: # - cant bind, port in use start_rpcport = 4000 account_addresses = [ privtoaddr(key) for key in set(private_keys) ] alloc = { address_encoder(address): { 'balance': DEFAULT_BALANCE, } for address in account_addresses } genesis = { 'config': { 'homesteadBlock': 0, }, 'nonce': '0x0000000000000042', 'mixhash': '0x0000000000000000000000000000000000000000000000000000000000000000', 'difficulty': '0x40', 'coinbase': '0x0000000000000000000000000000000000000000', 'timestamp': '0x00', 'parentHash': '0x0000000000000000000000000000000000000000000000000000000000000000', 'extraData': 'raiden', 'gasLimit': GAS_LIMIT_HEX, 'alloc': alloc, } nodes_configuration = [] for pos, key in enumerate(geth_private_keys): config = dict() # make the first node miner if pos == 0: config['minerthreads'] = 1 # conservative config['unlock'] = 0 config['nodekey'] = key config['nodekeyhex'] = encode_hex(key) config['pub'] = encode_hex(privtopub(key)) config['address'] = privtoaddr(key) config['port'] = p2p_base_port + pos config['rpcport'] = start_rpcport + pos config['enode'] = 'enode://{pub}@127.0.0.1:{port}'.format( pub=config['pub'], port=config['port'], ) config['bootnodes'] = ','.join(node['enode'] for node in nodes_configuration) nodes_configuration.append(config) cmds = [] for i, config in enumerate(nodes_configuration): nodedir = os.path.join(base_datadir, config['nodekeyhex']) os.makedirs(nodedir) geth_init_datadir(genesis, nodedir) if 'minerthreads' in config: geth_create_account(nodedir, private_keys[i]) cmds.append(geth_to_cmd(config, nodedir)) # save current term settings before running geth if isinstance(sys.stdin, file): # check that the test is running on non-capture mode term_settings = termios.tcgetattr(sys.stdin) processes_list = [] for cmd in cmds: if '--unlock' in cmd: process = subprocess.Popen(cmd, universal_newlines=True, stdin=subprocess.PIPE) # --password wont work, write password to unlock process.stdin.write(DEFAULT_PASSPHRASE + os.linesep) # Passphrase: process.stdin.write(DEFAULT_PASSPHRASE + os.linesep) # Repeat passphrase: else: process = subprocess.Popen(cmd) processes_list.append(process) assert process.returncode is None geth_wait_and_check(private_keys) # reenter echo mode (disabled by geth pasphrase prompt) if isinstance(sys.stdin, file): termios.tcsetattr(sys.stdin, termios.TCSADRAIN, term_settings) return processes_list
def test_blockchain(request): # pylint: disable=too-many-locals from hydrachain import app app.slogging.configure(':ERROR') quantity = 3 base_port = 29870 timeout = 3 # seconds tmp_datadir = tempfile.mktemp() private_keys = [ mk_privkey('raidentest:{}'.format(position)) for position in range(quantity) ] addresses = [ privtoaddr(priv) for priv in private_keys ] hydrachain_apps = hydrachain_network(private_keys, base_port, tmp_datadir) privatekey = private_keys[0] address = privtoaddr(privatekey) jsonrpc_client = JSONRPCClient(privkey=private_keys[0], print_communication=False) humantoken_path = get_contract_path('HumanStandardToken.sol') humantoken_contracts = compile_file(humantoken_path, libraries=dict()) token_abi = jsonrpc_client.deploy_solidity_contract( address, 'HumanStandardToken', humantoken_contracts, dict(), (9999, 'raiden', 2, 'Rd'), timeout=timeout, ) registry_path = get_contract_path('Registry.sol') registry_contracts = compile_file(registry_path, libraries=dict()) registry_abi = jsonrpc_client.deploy_solidity_contract( address, 'Registry', registry_contracts, dict(), tuple(), timeout=timeout, ) log_list = jsonrpc_client.call( 'eth_getLogs', { 'fromBlock': '0x0', 'toBlock': 'latest', 'topics': [], }, ) assert len(log_list) == 0 # pylint: disable=no-member assert token_abi.balanceOf(address) == 9999 transaction_hash = registry_abi.addAsset(token_abi.address) jsonrpc_client.poll(transaction_hash.decode('hex'), timeout=timeout) log_list = jsonrpc_client.call( 'eth_getLogs', { 'fromBlock': '0x0', 'toBlock': 'latest', 'topics': [], }, ) assert len(log_list) == 1 channel_manager_address_encoded = registry_abi.channelManagerByAsset.call(token_abi.address) channel_manager_address = channel_manager_address_encoded.decode('hex') log_channel_manager_address_encoded = log_list[0]['data'] log_channel_manager_address = log_channel_manager_address_encoded[2:].lstrip('0').rjust(40, '0').decode('hex') assert channel_manager_address == log_channel_manager_address channel_manager_abi = jsonrpc_client.new_contract_proxy( registry_contracts['ChannelManagerContract']['abi'], channel_manager_address, ) transaction_hash = channel_manager_abi.newChannel(addresses[1], 10) jsonrpc_client.poll(transaction_hash.decode('hex'), timeout=timeout) log_list = jsonrpc_client.call( 'eth_getLogs', { 'fromBlock': '0x0', 'toBlock': 'latest', 'topics': [], }, ) assert len(log_list) == 2 channel_manager_abi.get.call( address.encode('hex'), addresses[1].encode('hex'), )
def create_hydrachain_cluster(private_keys, hydrachain_private_keys, p2p_base_port, base_datadir): """ Initializes a hydrachain network used for testing. """ # pylint: disable=too-many-locals from hydrachain.app import services, start_app, HPCApp import pyethapp.config as konfig def privkey_to_uri(private_key): host = b'0.0.0.0' pubkey = privtopub(private_key) return host_port_pubkey_to_uri(host, p2p_base_port, pubkey) account_addresses = [ privtoaddr(priv) for priv in private_keys ] alloc = { encode_hex(address): { 'balance': DEFAULT_BALANCE, } for address in account_addresses } genesis = { 'nonce': '0x00006d6f7264656e', 'difficulty': '0x20000', 'mixhash': '0x00000000000000000000000000000000000000647572616c65787365646c6578', 'coinbase': '0x0000000000000000000000000000000000000000', 'timestamp': '0x00', 'parentHash': '0x0000000000000000000000000000000000000000000000000000000000000000', 'extraData': '0x', 'gasLimit': GAS_LIMIT_HEX, 'alloc': alloc, } bootstrap_nodes = [ privkey_to_uri(hydrachain_private_keys[0]), ] validators_addresses = [ privtoaddr(private_key) for private_key in hydrachain_private_keys ] all_apps = [] for number, private_key in enumerate(hydrachain_private_keys): config = konfig.get_default_config(services + [HPCApp]) config = update_config_from_genesis_json(config, genesis) datadir = os.path.join(base_datadir, str(number)) konfig.setup_data_dir(datadir) account = Account.new( password='', key=private_key, ) config['data_dir'] = datadir config['hdc']['validators'] = validators_addresses config['node']['privkey_hex'] = encode_hex(private_key) config['jsonrpc']['listen_port'] += number config['client_version_string'] = 'NODE{}'.format(number) # setting to 0 so that the CALLCODE opcode works at the start of the # network config['eth']['block']['HOMESTEAD_FORK_BLKNUM'] = 0 config['discovery']['bootstrap_nodes'] = bootstrap_nodes config['discovery']['listen_port'] = p2p_base_port + number config['p2p']['listen_port'] = p2p_base_port + number config['p2p']['min_peers'] = min(10, len(hydrachain_private_keys) - 1) config['p2p']['max_peers'] = len(hydrachain_private_keys) * 2 # only one of the nodes should have the Console service running if number != 0 and Console.name not in config['deactivated_services']: config['deactivated_services'].append(Console.name) hydrachain_app = start_app(config, accounts=[account]) all_apps.append(hydrachain_app) hydrachain_wait(private_keys, len(hydrachain_private_keys) - 1) return all_apps
def create_sequential_network(private_keys, asset_address, registry_address, # pylint: disable=too-many-arguments channels_per_node, deposit, settle_timeout, poll_timeout, transport_class, blockchain_service_class): """ Create a fully connected network with `num_nodes`, the nodes are connect sequentially. Returns: A list of apps of size `num_nodes`, with the property that every sequential pair in the list has an open channel with `deposit` for each participant. """ # pylint: disable=too-many-locals random.seed(42) host = '127.0.0.1' num_nodes = len(private_keys) if num_nodes < 2: raise ValueError('cannot create a network with less than two nodes') if channels_per_node not in (0, 1, 2, CHAIN): raise ValueError('can only create networks with 0, 1, 2 or CHAIN channels') discovery = Discovery() blockchain_service_class = blockchain_service_class or BlockChainServiceMock apps = [] for idx, privatekey_bin in enumerate(private_keys): port = INITIAL_PORT + idx nodeid = privtoaddr(privatekey_bin) discovery.register(nodeid, host, port) jsonrpc_client = JSONRPCClient( privkey=privatekey_bin, print_communication=False, ) blockchain_service = blockchain_service_class( jsonrpc_client, registry_address, poll_timeout=poll_timeout, ) app = create_app( privatekey_bin, blockchain_service, discovery, transport_class, port=port, host=host, ) apps.append(app) if channels_per_node == 0: app_channels = list() if channels_per_node == 1: every_two = iter(apps) app_channels = list(zip(every_two, every_two)) if channels_per_node == 2: app_channels = list(zip(apps, apps[1:] + [apps[0]])) if channels_per_node == CHAIN: app_channels = list(zip(apps[:-1], apps[1:])) setup_channels( asset_address, app_channels, deposit, settle_timeout, ) for app in apps: app.raiden.register_registry(app.raiden.chain.default_registry) return apps
def deployed_network(request, private_keys, channels_per_node, deposit, number_of_assets, settle_timeout, poll_timeout, transport_class, geth_cluster): gevent.sleep(2) assert channels_per_node in (0, 1, 2, CHAIN), ( 'deployed_network uses create_sequential_network that can only work ' 'with 0, 1 or 2 channels') privatekey = private_keys[0] address = privtoaddr(privatekey) blockchain_service_class = BlockChainService jsonrpc_client = JSONRPCClient( host='0.0.0.0', privkey=privatekey, print_communication=False, ) patch_send_transaction(jsonrpc_client) humantoken_path = get_contract_path('HumanStandardToken.sol') registry_path = get_contract_path('Registry.sol') humantoken_contracts = compile_file(humantoken_path, libraries=dict()) registry_contracts = compile_file(registry_path, libraries=dict()) registry_proxy = jsonrpc_client.deploy_solidity_contract( address, 'Registry', registry_contracts, dict(), tuple(), timeout=poll_timeout, ) registry_address = registry_proxy.address # Using 3 * deposit because we assume that is the maximum number of # channels that will be created. # `total_per_node = channels_per_node * deposit` total_per_node = 3 * deposit total_asset = total_per_node * len(private_keys) asset_addresses = [] for _ in range(number_of_assets): token_proxy = jsonrpc_client.deploy_solidity_contract( address, 'HumanStandardToken', humantoken_contracts, dict(), (total_asset, 'raiden', 2, 'Rd'), timeout=poll_timeout, ) asset_address = token_proxy.address assert len(asset_address) asset_addresses.append(asset_address) transaction_hash = registry_proxy.addAsset(asset_address) # pylint: disable=no-member jsonrpc_client.poll(transaction_hash.decode('hex'), timeout=poll_timeout) # only the creator of the token starts with a balance, transfer from # the creator to the other nodes for transfer_to in private_keys: if transfer_to != jsonrpc_client.privkey: transaction_hash = token_proxy.transfer( # pylint: disable=no-member privtoaddr(transfer_to), total_per_node, startgas=GAS_LIMIT, ) jsonrpc_client.poll(transaction_hash.decode('hex')) for key in private_keys: assert token_proxy.balanceOf(privtoaddr(key)) == total_per_node # pylint: disable=no-member raiden_apps = create_sequential_network( private_keys, asset_addresses[0], registry_address, channels_per_node, deposit, settle_timeout, poll_timeout, transport_class, blockchain_service_class, ) _raiden_cleanup(request, raiden_apps) return raiden_apps
def get_ether_from_faucet(self): if self.__faucet and self.eth_balance(True) < 10**15: addr = keys.privtoaddr(self.__privkey) ropsten_faucet_donate(addr) return False return True
def test_blockchain(private_keys, number_of_nodes, cluster, poll_timeout): # pylint: disable=too-many-locals addresses = [ privtoaddr(priv) for priv in private_keys ] privatekey = private_keys[0] address = privtoaddr(privatekey) total_asset = 100 jsonrpc_client = JSONRPCClient( privkey=privatekey, print_communication=False, ) patch_send_transaction(jsonrpc_client) humantoken_path = get_contract_path('HumanStandardToken.sol') humantoken_contracts = compile_file(humantoken_path, libraries=dict()) token_proxy = jsonrpc_client.deploy_solidity_contract( address, 'HumanStandardToken', humantoken_contracts, dict(), (total_asset, 'raiden', 2, 'Rd'), timeout=poll_timeout, ) registry_path = get_contract_path('Registry.sol') registry_contracts = compile_file(registry_path) registry_proxy = jsonrpc_client.deploy_solidity_contract( address, 'Registry', registry_contracts, dict(), tuple(), timeout=poll_timeout, ) log_list = jsonrpc_client.call( 'eth_getLogs', { 'fromBlock': '0x0', 'toBlock': 'latest', 'topics': [], }, ) assert len(log_list) == 0 # pylint: disable=no-member assert token_proxy.balanceOf(address) == total_asset transaction_hash = registry_proxy.addAsset.transact( token_proxy.address, gasprice=denoms.wei, ) jsonrpc_client.poll(transaction_hash.decode('hex'), timeout=poll_timeout) assert len(registry_proxy.assetAddresses.call()) == 1 log_list = jsonrpc_client.call( 'eth_getLogs', { 'fromBlock': '0x0', 'toBlock': 'latest', 'topics': [], }, ) assert len(log_list) == 1 channel_manager_address_encoded = registry_proxy.channelManagerByAsset.call(token_proxy.address) channel_manager_address = channel_manager_address_encoded.decode('hex') log = log_list[0] log_topics = [ decode_topic(topic) for topic in log['topics'] # pylint: disable=invalid-sequence-index ] log_data = log['data'] event = registry_proxy.translator.decode_event( log_topics, log_data[2:].decode('hex'), ) assert channel_manager_address == event['channelManagerAddress'].decode('hex') assert token_proxy.address == event['assetAddress'].decode('hex') channel_manager_proxy = jsonrpc_client.new_contract_proxy( registry_contracts['ChannelManagerContract']['abi'], channel_manager_address, ) transaction_hash = channel_manager_proxy.newChannel.transact( addresses[1], 10, gasprice=denoms.wei, ) jsonrpc_client.poll(transaction_hash.decode('hex'), timeout=poll_timeout) log_list = jsonrpc_client.call( 'eth_getLogs', { 'fromBlock': '0x0', 'toBlock': 'latest', 'topics': [], }, ) assert len(log_list) == 2
def new_abi_contract(self, _abi, address): sender = self.sender or privtoaddr(self.privkey) return ABIContract(sender, _abi, address, self.eth_call, self.send_transaction)
def deployed_network(request, private_keys, channels_per_node, deposit, number_of_assets, settle_timeout, poll_timeout, transport_class, geth_cluster): gevent.sleep(2) assert channels_per_node in (0, 1, 2, CHAIN), ( 'deployed_network uses create_sequential_network that can only work ' 'with 0, 1 or 2 channels' ) privatekey = private_keys[0] address = privtoaddr(privatekey) blockchain_service_class = BlockChainService jsonrpc_client = JSONRPCClient( host='0.0.0.0', privkey=privatekey, print_communication=False, ) patch_send_transaction(jsonrpc_client) humantoken_path = get_contract_path('HumanStandardToken.sol') registry_path = get_contract_path('Registry.sol') humantoken_contracts = compile_file(humantoken_path, libraries=dict()) registry_contracts = compile_file(registry_path, libraries=dict()) registry_proxy = jsonrpc_client.deploy_solidity_contract( address, 'Registry', registry_contracts, dict(), tuple(), timeout=poll_timeout, ) registry_address = registry_proxy.address # Using 3 * deposit because we assume that is the maximum number of # channels that will be created. # `total_per_node = channels_per_node * deposit` total_per_node = 3 * deposit total_asset = total_per_node * len(private_keys) asset_addresses = [] for _ in range(number_of_assets): token_proxy = jsonrpc_client.deploy_solidity_contract( address, 'HumanStandardToken', humantoken_contracts, dict(), (total_asset, 'raiden', 2, 'Rd'), timeout=poll_timeout, ) asset_address = token_proxy.address assert len(asset_address) asset_addresses.append(asset_address) transaction_hash = registry_proxy.addAsset(asset_address) # pylint: disable=no-member jsonrpc_client.poll(transaction_hash.decode('hex'), timeout=poll_timeout) # only the creator of the token starts with a balance, transfer from # the creator to the other nodes for transfer_to in private_keys: if transfer_to != jsonrpc_client.privkey: transaction_hash = token_proxy.transfer( # pylint: disable=no-member privtoaddr(transfer_to), total_per_node, startgas=GAS_LIMIT, ) jsonrpc_client.poll(transaction_hash.decode('hex')) for key in private_keys: assert token_proxy.balanceOf(privtoaddr(key)) == total_per_node # pylint: disable=no-member raiden_apps = create_sequential_network( private_keys, asset_addresses[0], registry_address, channels_per_node, deposit, settle_timeout, poll_timeout, transport_class, blockchain_service_class, ) _raiden_cleanup(request, raiden_apps) return raiden_apps
def create_network(private_keys, assets_addresses, registry_address, # pylint: disable=too-many-arguments channels_per_node, deposit, settle_timeout, poll_timeout, transport_class, blockchain_service_class): """ Initialize a local test network using the UDP protocol. Note: The generated network will use two subnets, 127.0.0.10 and 127.0.0.11, for this test to work both virtual interfaces must be created prior to the test execution:: ifconfig lo:0 127.0.0.10 ifconfig lo:1 127.0.0.11 """ # pylint: disable=too-many-locals random.seed(1337) num_nodes = len(private_keys) if channels_per_node is not CHAIN and channels_per_node > num_nodes: raise ValueError("Can't create more channels than nodes") # if num_nodes it is not even half_of_nodes = int(floor(len(private_keys) / 2)) # globals discovery = Discovery() # The mock needs to be atomic since all app's will use the same instance, # for the real application the syncronization is done by the JSON-RPC # server blockchain_service_class = blockchain_service_class or BlockChainServiceMock # Each app instance is a Node in the network apps = [] for idx, privatekey_bin in enumerate(private_keys): # TODO: check if the loopback interfaces exists # split the nodes into two different networks if idx > half_of_nodes: host = '127.0.0.11' else: host = '127.0.0.10' nodeid = privtoaddr(privatekey_bin) port = INITIAL_PORT + idx discovery.register(nodeid, host, port) jsonrpc_client = JSONRPCClient( privkey=privatekey_bin, print_communication=False, ) blockchain_service = blockchain_service_class( jsonrpc_client, registry_address, poll_timeout=poll_timeout, ) app = create_app( privatekey_bin, blockchain_service, discovery, transport_class, port=port, host=host, ) apps.append(app) for asset in assets_addresses: if channels_per_node == CHAIN: app_channels = list(zip(apps[:-1], apps[1:])) else: app_channels = list(network_with_minimum_channels(apps, channels_per_node)) setup_channels( asset, app_channels, deposit, settle_timeout, ) for app in apps: app.raiden.register_registry(app.raiden.chain.default_registry) return apps
def test_account_creation(account, password, privkey, uuid): assert not account.locked assert account.privkey == privkey assert account.address == privtoaddr(privkey) assert account.uuid == uuid
def hydrachain_network(private_keys, base_port, base_datadir): """ Initializes a hydrachain network used for testing. """ # pylint: disable=too-many-locals from hydrachain.app import services, start_app, HPCApp import pyethapp.config as konfig gevent.get_hub().SYSTEM_ERROR = BaseException PBKDF2_CONSTANTS['c'] = 100 quantity = len(private_keys) def privkey_to_uri(private_key): host = b'0.0.0.0' pubkey = privtopub(private_key) return host_port_pubkey_to_uri(host, base_port, pubkey) addresses = [ privtoaddr(priv) for priv in private_keys ] bootstrap_nodes = [ privkey_to_uri(private_keys[0]), ] validator_keys = [ mk_privkey('raidenvalidator:{}'.format(position)) for position in range(quantity) ] validator_addresses = [ privtoaddr(validator_keys[position]) for position in range(quantity) ] alloc = { addr.encode('hex'): { 'balance': '1606938044258990275541962092341162602522202993782792835301376', } for addr in addresses } genesis = { 'nonce': '0x00006d6f7264656e', 'difficulty': '0x20000', 'mixhash': '0x00000000000000000000000000000000000000647572616c65787365646c6578', 'coinbase': '0x0000000000000000000000000000000000000000', 'timestamp': '0x00', 'parentHash': '0x0000000000000000000000000000000000000000000000000000000000000000', 'extraData': '0x', 'gasLimit': '0x5FEFD8', 'alloc': alloc, } all_apps = [] for number in range(quantity): port = base_port + number config = konfig.get_default_config(services + [HPCApp]) # del config['eth']['genesis_hash'] config = update_config_from_genesis_json(config, genesis) datadir = os.path.join(base_datadir, str(number)) konfig.setup_data_dir(datadir) account = Account.new( password='', key=validator_keys[number], ) config['data_dir'] = datadir config['node']['privkey_hex'] = private_keys[number].encode('hex') config['hdc']['validators'] = validator_addresses config['jsonrpc']['listen_port'] += number config['client_version_string'] = 'NODE{}'.format(number) # setting to 0 so that the CALLCODE opcode works at the start of the # network config['eth']['block']['HOMESTEAD_FORK_BLKNUM'] = 0 config['discovery']['bootstrap_nodes'] = bootstrap_nodes config['discovery']['listen_port'] = port config['p2p']['listen_port'] = port config['p2p']['min_peers'] = min(10, quantity - 1) config['p2p']['max_peers'] = quantity * 2 # only one of the nodes should have the Console service running if number != 0: config['deactivated_services'].append(Console.name) hydrachain_app = start_app(config, accounts=[account]) all_apps.append(hydrachain_app) return all_apps