def main(keystore_file, password, rpc_url, eth_amount, targets_file): web3 = Web3(HTTPProvider(rpc_url)) with open(keystore_file, 'r') as keystore: account = Account(json.load(keystore), password, keystore_file) print("Using account:", to_checksum_address(account.address)) client = JSONRPCClient( web3, account.privkey, block_num_confirmations=DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS, ) targets = [t.strip() for t in targets_file] balance = client.balance(client.address) balance_needed = len(targets) * eth_amount if balance_needed * WEI_TO_ETH > balance: print("Not enough balance to fund {} accounts with {} eth each. Need {}, have {}".format( len(targets), eth_amount, balance_needed, balance / WEI_TO_ETH, )) print("Sending {} eth to:".format(eth_amount)) for target in targets: print(" - {}".format(target)) client.send_transaction( to=target, startgas=21000, value=eth_amount * WEI_TO_ETH, )
def deploy_contract_web3( contract_name: str, deploy_client: JSONRPCClient, num_confirmations: int = None, constructor_arguments: typing.Tuple[typing.Any, ...] = (), ) -> typing.Address: contract_interface = CONTRACT_MANAGER.get_contract(contract_name) contract = deploy_client.web3.eth.contract( abi=contract_interface['abi'], bytecode=contract_interface['bin'], ) transaction = contract.constructor(*constructor_arguments).buildTransaction() transaction['nonce'] = deploy_client.nonce() signed_txn = deploy_client.web3.eth.account.signTransaction( transaction, deploy_client.privkey, ) tx_hash = deploy_client.web3.eth.sendRawTransaction(signed_txn.rawTransaction) deploy_client.poll(transaction_hash=tx_hash, confirmations=num_confirmations) receipt = deploy_client.get_transaction_receipt(tx_hash) if receipt.get('status', 0) == 0: raise RuntimeError('contract was not sucessfully deployed') return typing.Address( unhexlify(remove_0x_prefix(receipt['contractAddress'])), )
def test_duplicated_transaction_same_gas_price_raises(deploy_client): """ If the same transaction is sent twice a JSON RPC error is raised. """ gas_price = 2000000000 gas_price_strategy = make_fixed_gas_price_strategy(gas_price) deploy_client.web3.eth.setGasPriceStrategy(gas_price_strategy) contract_proxy = deploy_rpc_test_contract(deploy_client) address = contract_proxy.contract_address assert len(deploy_client.web3.eth.getCode(to_checksum_address(address))) > 0 second_client = JSONRPCClient( web3=deploy_client.web3, privkey=deploy_client.privkey, ) second_proxy = second_client.new_contract_proxy( contract_proxy.contract.abi, contract_proxy.contract_address, ) startgas = safe_gas_limit(contract_proxy.estimate_gas('pending', 'ret')) with pytest.raises(TransactionAlreadyPending): second_proxy.transact('ret', startgas) contract_proxy.transact('ret', startgas)
def test_register_secret_batch_with_pruned_block( proxy_manager: ProxyManager, secret_registry_proxy: SecretRegistry, web3: Web3, private_keys: List[PrivateKey], ) -> None: """Test secret registration with a pruned given block.""" rpc_client = JSONRPCClient(web3, private_keys[1]) # Now wait until this block becomes pruned pruned_number = rpc_client.block_number() rpc_client.wait_until_block( target_block_number=BlockNumber(pruned_number + STATE_PRUNING_AFTER_BLOCKS) ) secret_registry_batch_happy_path(proxy_manager, secret_registry_proxy)
def test_transact_opcode(deploy_client: JSONRPCClient) -> None: """ The receipt status field of a transaction that did not throw is 0x1 """ contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") address = contract_proxy.contract_address assert len(deploy_client.web3.eth.getCode( to_checksum_address(address))) > 0 check_block = deploy_client.get_checking_block() startgas = contract_proxy.estimate_gas(check_block, "ret") * 2 transaction = contract_proxy.transact("ret", startgas) receipt = deploy_client.poll(transaction) assert check_transaction_threw(receipt=receipt) is None, "must be empty"
def test_query_pruned_state( token_network_proxy, private_keys, web3, contract_manager, ): """A test for https://github.com/raiden-network/raiden/issues/3566 If pruning limit blocks pass make sure that can_query_state_for_block returns False. """ token_network_address = to_canonical_address( token_network_proxy.proxy.contract.address) c1_client = JSONRPCClient(web3, private_keys[1]) c1_chain = BlockChainService( jsonrpc_client=c1_client, contract_manager=contract_manager, ) c2_client = JSONRPCClient(web3, private_keys[2]) c1_token_network_proxy = TokenNetwork( jsonrpc_client=c1_client, token_network_address=token_network_address, contract_manager=contract_manager, ) # create a channel and query the state at the current block hash channel_identifier = c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=10, given_block_identifier='latest', ) block = c1_client.web3.eth.getBlock('latest') block_number = int(block['number']) block_hash = bytes(block['hash']) channel_id = c1_token_network_proxy._inspect_channel_identifier( participant1=c1_client.address, participant2=c2_client.address, called_by_fn='test', block_identifier=block_hash, ) assert channel_id == channel_identifier assert c1_client.can_query_state_for_block(block_hash) # wait until state pruning kicks in target_block = block_number + STATE_PRUNING_AFTER_BLOCKS + 1 c1_chain.wait_until_block(target_block_number=target_block) # and now query again for the old block identifier and see we can't query assert not c1_client.can_query_state_for_block(block_hash)
def test_transact_throws_opcode(deploy_client: JSONRPCClient) -> None: """ The receipt status field of a transaction that hit an assert or require is 0x0 """ contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") address = contract_proxy.address assert len(deploy_client.web3.eth.getCode(address)) > 0 # the method always fails, so the gas estimation returns 0 here, using a # hardcoded a value to circumvent gas estimation. estimated_gas = safe_gas_limit(22000) gas_price = gas_price_for_fast_transaction(deploy_client.web3) block = deploy_client.get_block(BLOCK_ID_LATEST) estimated_transaction_fail_assert = TransactionEstimated( from_address=address, data=SmartContractCall(contract_proxy, "fail_assert", (), {}, value=0), eth_node=deploy_client.eth_node, extra_log_details={}, estimated_gas=estimated_gas, gas_price=gas_price, approximate_block=(block["hash"], block["number"]), ) transaction_fail_assert_sent = deploy_client.transact( estimated_transaction_fail_assert) transaction_fail_assert_mined = deploy_client.poll_transaction( transaction_fail_assert_sent) msg = "Transaction must have failed" assert not was_transaction_successfully_mined( transaction_fail_assert_mined), msg estimated_transaction_fail_require = TransactionEstimated( from_address=address, data=SmartContractCall(contract_proxy, "fail_require", (), {}, value=0), eth_node=deploy_client.eth_node, extra_log_details={}, estimated_gas=estimated_gas, gas_price=gas_price, approximate_block=(block["hash"], block["number"]), ) transaction_fail_require_sent = deploy_client.transact( estimated_transaction_fail_require) transaction_fail_require_mined = deploy_client.poll_transaction( transaction_fail_require_sent) msg = "Transaction must have failed" assert not was_transaction_successfully_mined( transaction_fail_require_mined), msg
def register_token_and_return_the_network_proxy( contract_manager: ContractManager, deploy_client: JSONRPCClient, token_proxy: Token, token_network_registry_address: TokenNetworkRegistryAddress, ) -> TokenNetwork: blockchain_service = ProxyManager( rpc_client=deploy_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) token_network_registry_proxy = blockchain_service.token_network_registry( token_network_registry_address) token_network_address = token_network_registry_proxy.add_token( token_address=token_proxy.address, channel_participant_deposit_limit= RED_EYES_PER_CHANNEL_PARTICIPANT_LIMIT, token_network_deposit_limit=RED_EYES_PER_TOKEN_NETWORK_LIMIT, block_identifier=deploy_client.get_confirmed_blockhash(), ) blockchain_service = ProxyManager( rpc_client=deploy_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) return blockchain_service.token_network(token_network_address)
def __init__( self, jsonrpc_client: JSONRPCClient, user_deposit_address: UserDepositAddress, contract_manager: ContractManager, proxy_manager: "ProxyManager", ) -> None: if not is_binary_address(user_deposit_address): raise ValueError("Expected binary address format for token nework") check_address_has_code( client=jsonrpc_client, address=Address(user_deposit_address), contract_name=CONTRACT_USER_DEPOSIT, expected_code=decode_hex( contract_manager.get_runtime_hexcode(CONTRACT_USER_DEPOSIT)), ) self.client = jsonrpc_client self.address = user_deposit_address self.node_address = self.client.address self.contract_manager = contract_manager self.gas_measurements = gas_measurements( self.contract_manager.contracts_version) self.proxy_manager = proxy_manager self.proxy = jsonrpc_client.new_contract_proxy( abi=self.contract_manager.get_contract_abi(CONTRACT_USER_DEPOSIT), contract_address=Address(user_deposit_address), ) self.deposit_lock = RLock()
def deploy_token( deploy_client: JSONRPCClient, contract_manager: ContractManager, initial_amount: typing.TokenAmount, decimals: int, token_name: str, token_symbol: str, )-> ContractProxy: token_address = deploy_contract_web3( contract_name=CONTRACT_HUMAN_STANDARD_TOKEN, deploy_client=deploy_client, contract_manager=contract_manager, constructor_arguments=( initial_amount, decimals, token_name, token_symbol, ), ) contract_abi = contract_manager.get_contract_abi(CONTRACT_HUMAN_STANDARD_TOKEN) return deploy_client.new_contract_proxy( contract_interface=contract_abi, contract_address=token_address, )
def deploy_service_registry( token_deploy_result: Callable[[], Contract], deploy_client: JSONRPCClient, contract_manager: ContractManager, proxy_manager: ProxyManager, ) -> ServiceRegistry: token_contract = token_deploy_result() contract, receipt = deploy_client.deploy_single_contract( contract_name=CONTRACT_SERVICE_REGISTRY, contract=contract_manager.get_contract(CONTRACT_SERVICE_REGISTRY), constructor_parameters=( token_contract.address, EMPTY_ADDRESS, int(500e18), 6, 5, 180 * SECONDS_PER_DAY, 1000, 200 * SECONDS_PER_DAY, ), ) return proxy_manager.service_registry( ServiceRegistryAddress(to_canonical_address(contract.address)), BlockNumber(receipt["blockNumber"]), )
def call_minting_method(client: JSONRPCClient, proxy: ContractProxy, contract_method: MintingMethod, args: List[Any]) -> TransactionHash: """ Try to mint tokens by calling `contract_method` on `proxy`. Raises: MintFailed if anything goes wrong. """ method = contract_method.value gas_limit = proxy.estimate_gas("latest", method, *args) if gas_limit is None: raise MintFailed(f"Gas estimation failed. Make sure the token has a " f"method named {method} with the expected signature.") try: tx_hash = proxy.transact(method, gas_limit, *args) except (RaidenError, ValueError) as e: # Re-raise TransactionAlreadyPending etc. as MintFailed. # Since the token minting api is not standardized, we also catch ValueErrors # that might fall through ContractProxy.transact()'s exception handling. raise MintFailed(str(e)) receipt = client.poll(tx_hash) if check_transaction_threw(receipt=receipt): raise MintFailed( f"Call to contract method {method}: Transaction failed.") return tx_hash
def jsonrpc_services( deploy_service, private_keys, secret_registry_address, token_network_registry_address, web3, contract_manager, ): secret_registry = deploy_service.secret_registry(secret_registry_address) deploy_registry = deploy_service.token_network_registry( token_network_registry_address) blockchain_services = list() for privkey in private_keys: rpc_client = JSONRPCClient(web3, privkey) blockchain = BlockChainService( privatekey_bin=privkey, jsonrpc_client=rpc_client, contract_manager=contract_manager, ) blockchain_services.append(blockchain) return BlockchainServices( deploy_registry, secret_registry, deploy_service, blockchain_services, )
def __init__( self, jsonrpc_client: JSONRPCClient, token_address: TokenAddress, contract_manager: ContractManager, ) -> None: contract = jsonrpc_client.new_contract( contract_manager.get_contract_abi(CONTRACT_CUSTOM_TOKEN), Address(token_address)) proxy = ContractProxy(jsonrpc_client, contract) if not is_binary_address(token_address): raise ValueError("token_address must be a valid address") check_address_has_code(jsonrpc_client, Address(token_address), "Token", expected_code=None) self.address = token_address self.client = jsonrpc_client self.node_address = jsonrpc_client.address self.proxy = proxy self.token_lock: RLock = RLock()
def eth_maybe_transfer( orchestration_client: JSONRPCClient, target: Address, minimum_balance: int, maximum_balance: int, ) -> None: balance = orchestration_client.balance(target) if balance < minimum_balance: eth_transfer = EthTransfer( to_address=target, value=maximum_balance - balance, gas_price=orchestration_client.web3.eth.gasPrice, ) tx_hash = orchestration_client.transact(eth_transfer) orchestration_client.poll_transaction(tx_hash)
def deploy_token( deploy_client: JSONRPCClient, contract_manager: ContractManager, initial_amount: typing.TokenAmount, decimals: int, token_name: str, token_symbol: str, ) -> ContractProxy: token_address = deploy_contract_web3( contract_name=CONTRACT_HUMAN_STANDARD_TOKEN, deploy_client=deploy_client, contract_manager=contract_manager, constructor_arguments=( initial_amount, decimals, token_name, token_symbol, ), ) contract_abi = contract_manager.get_contract_abi( CONTRACT_HUMAN_STANDARD_TOKEN) return deploy_client.new_contract_proxy( contract_interface=contract_abi, contract_address=token_address, )
def deploy_monitoring_service( token_deploy_result: Callable[[], Contract], user_deposit_deploy_result: Callable[[], UserDeposit], service_registry_deploy_result: Callable[[], ServiceRegistry], token_network_registry_deploy_result: Callable[[], TokenNetworkRegistry], deploy_client: JSONRPCClient, contract_manager: ContractManager, proxy_manager: ProxyManager, ) -> MonitoringService: token_contract = token_deploy_result() token_network_registry_proxy = token_network_registry_deploy_result() user_deposit_proxy = user_deposit_deploy_result() service_registry_proxy = service_registry_deploy_result() contract, receipt = deploy_client.deploy_single_contract( contract_name=CONTRACT_MONITORING_SERVICE, contract=contract_manager.get_contract(CONTRACT_MONITORING_SERVICE), constructor_parameters=[ token_contract.address, service_registry_proxy.address, user_deposit_proxy.address, token_network_registry_proxy.address, ], ) return proxy_manager.monitoring_service( MonitoringServiceAddress(to_canonical_address(contract.address)), BlockNumber(receipt["blockNumber"]), )
def __init__( self, jsonrpc_client: JSONRPCClient, service_registry_address: Address, contract_manager: ContractManager, ): if not is_binary_address(service_registry_address): raise InvalidAddress( "Expected binary address for service registry") self.contract_manager = contract_manager check_address_has_code(jsonrpc_client, service_registry_address, CONTRACT_SERVICE_REGISTRY) proxy = jsonrpc_client.new_contract_proxy( self.contract_manager.get_contract_abi(CONTRACT_SERVICE_REGISTRY), to_normalized_address(service_registry_address), ) compare_contract_versions( proxy=proxy, expected_version=contract_manager.contracts_version, contract_name=CONTRACT_SERVICE_REGISTRY, address=service_registry_address, ) self.address = service_registry_address self.proxy = proxy self.client = jsonrpc_client self.node_address = self.client.address
def test_transact_fails_if_the_account_does_not_have_enough_eth_to_pay_for_the_gas( deploy_client: JSONRPCClient, ) -> None: """ The gas estimation does not fail if the transaction execution requires more gas then the account's eth balance. However sending the transaction will. """ contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") estimated_transaction = deploy_client.estimate_gas(contract_proxy, "loop", {}, 1000) assert estimated_transaction, "The gas estimation should not have failed." burn_eth(deploy_client, amount_to_leave=estimated_transaction.estimated_gas // 2) with pytest.raises(InsufficientEth): deploy_client.transact(estimated_transaction)
def burn_eth(rpc_client: JSONRPCClient, amount_to_leave: int = 0) -> None: """Burns all the ETH on the account of the given raiden service""" address = rpc_client.address web3 = rpc_client.web3 gas_price = web3.eth.gasPrice # Leave enough ETH to pay for the burn transaction. amount_to_leave = TRANSACTION_INTRINSIC_GAS + amount_to_leave amount_to_burn = web3.eth.getBalance(address) - gas_price * amount_to_leave burn_transfer = EthTransfer(to_address=Address(HOP1), value=amount_to_burn, gas_price=gas_price) transaction_hash = rpc_client.transact(burn_transfer) rpc_client.poll_transaction(transaction_hash)
def test_token( deploy_client, token_proxy, private_keys, web3, contract_manager, ): privkey = private_keys[1] address = privatekey_to_address(privkey) address = to_canonical_address(address) other_client = JSONRPCClient(web3, privkey) other_token_proxy = Token( jsonrpc_client=other_client, token_address=to_canonical_address(token_proxy.proxy.contract.address), contract_manager=contract_manager, ) # send some funds from deployer to generated address transfer_funds = 100 token_proxy.transfer(address, transfer_funds, 'latest') assert transfer_funds == token_proxy.balance_of(address) allow_funds = 100 token_proxy.approve(address, allow_funds, 'latest') assert allow_funds == token_proxy.proxy.contract.functions.allowance( to_checksum_address(deploy_client.address), to_checksum_address(address), ).call(block_identifier='latest') other_token_proxy.transfer(deploy_client.address, transfer_funds, 'latest') assert token_proxy.balance_of(address) == 0
def __init__( self, privkey_seed: str, contract_manager, web3: Web3, block_confirmations: int, service_registry_address: Address, poll_interval: int = 30, error_poll_interval: int = 600, ) -> None: """Creates a new presence service getting the online status of nodes from a PFS""" super().__init__() self.running = False self.poll_interval = poll_interval self.error_poll_interval = error_poll_interval jsonrpc_client = JSONRPCClient( web3=web3, privkey=hashlib.sha256(privkey_seed.encode()).digest(), block_num_confirmations=block_confirmations, ) self.service_registry = ServiceRegistry( jsonrpc_client=jsonrpc_client, service_registry_address=service_registry_address, contract_manager=contract_manager, block_identifier=BLOCK_ID_LATEST, ) self.nodes_presence_status: Dict[bytes, bool] = {}
def test_transact_opcode(deploy_client: JSONRPCClient) -> None: """ The receipt status field of a transaction that did not throw is 0x1 """ contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") address = contract_proxy.address assert len(deploy_client.web3.eth.getCode(address)) > 0 estimated_transaction = deploy_client.estimate_gas(contract_proxy, "ret", {}) assert estimated_transaction estimated_transaction.estimated_gas *= 2 transaction_sent = deploy_client.transact(estimated_transaction) transaction_mined = deploy_client.poll_transaction(transaction_sent) assert was_transaction_successfully_mined( transaction_mined), "Transaction must be succesfull"
def __init__( self, jsonrpc_client: JSONRPCClient, user_deposit_address: Address, contract_manager: ContractManager, ): if not is_binary_address(user_deposit_address): raise InvalidAddress( "Expected binary address format for token nework") check_address_has_code(jsonrpc_client, Address(user_deposit_address), CONTRACT_USER_DEPOSIT) self.client = jsonrpc_client self.address = user_deposit_address self.node_address = self.client.address self.contract_manager = contract_manager self.proxy = jsonrpc_client.new_contract_proxy( self.contract_manager.get_contract_abi(CONTRACT_USER_DEPOSIT), to_normalized_address(user_deposit_address), ) self.deposit_lock = RLock()
def __init__( self, jsonrpc_client: JSONRPCClient, one_to_n_address: OneToNAddress, contract_manager: ContractManager, block_identifier: BlockIdentifier, ): if not is_binary_address(one_to_n_address): raise ValueError("Expected binary address for monitoring service") self.contract_manager = contract_manager check_address_has_code_handle_pruned_block( client=jsonrpc_client, address=Address(one_to_n_address), contract_name=CONTRACT_ONE_TO_N, expected_code=decode_hex( contract_manager.get_runtime_hexcode(CONTRACT_ONE_TO_N)), given_block_identifier=block_identifier, ) proxy = jsonrpc_client.new_contract_proxy( abi=self.contract_manager.get_contract_abi(CONTRACT_ONE_TO_N), contract_address=Address(one_to_n_address), ) self.address = one_to_n_address self.proxy = proxy self.client = jsonrpc_client self.node_address = self.client.address
def __init__( self, jsonrpc_client: JSONRPCClient, token_address: TokenAddress, contract_manager: ContractManager, block_identifier: BlockIdentifier, ) -> None: proxy = jsonrpc_client.new_contract_proxy(self.abi(contract_manager), Address(token_address)) if not is_binary_address(token_address): raise ValueError("token_address must be a valid address") check_address_has_code_handle_pruned_block( jsonrpc_client, Address(token_address), "Token", expected_code=None, given_block_identifier=block_identifier, ) self.address = token_address self.client = jsonrpc_client self.node_address = jsonrpc_client.address self.proxy = proxy self.token_lock: RLock = RLock()
def __init__( self, rpc_client: JSONRPCClient, metadata: SmartContractMetadata, proxy_manager: "ProxyManager", block_identifier: BlockIdentifier, ) -> None: check_address_has_code_handle_pruned_block( client=rpc_client, address=Address(metadata.address), contract_name=CONTRACT_TOKEN_NETWORK_REGISTRY, expected_code=metadata.runtime_bytecode, given_block_identifier=block_identifier, ) proxy = rpc_client.new_contract_proxy(abi=metadata.abi, contract_address=Address( metadata.address)) self.address = TokenNetworkRegistryAddress(metadata.address) self.proxy_manager = proxy_manager self.rpc_client = rpc_client self.gas_measurements = metadata.gas_measurements self.metadata = metadata self.node_address = self.rpc_client.address self.proxy = proxy
def test_token(deploy_client, token_proxy, private_keys, web3, contract_manager): privkey = private_keys[1] address = privatekey_to_address(privkey) address = to_canonical_address(address) other_client = JSONRPCClient(web3, privkey) other_token_proxy = Token( jsonrpc_client=other_client, token_address=to_canonical_address(token_proxy.proxy.address), contract_manager=contract_manager, block_identifier=BLOCK_ID_LATEST, ) # send some funds from deployer to generated address transfer_funds = 100 transaction_hash = token_proxy.transfer(address, transfer_funds) assert is_tx_hash_bytes(transaction_hash) assert transfer_funds == token_proxy.balance_of(address) allow_funds = 100 transaction_hash = token_proxy.approve(address, allow_funds) assert is_tx_hash_bytes(transaction_hash) assert allow_funds == token_proxy.proxy.functions.allowance( deploy_client.address, address).call(block_identifier=BLOCK_ID_LATEST) other_token_proxy.transfer(deploy_client.address, transfer_funds) assert token_proxy.balance_of(address) == 0
def __init__( self, jsonrpc_client: JSONRPCClient, monitoring_service_address: MonitoringServiceAddress, contract_manager: ContractManager, block_identifier: BlockIdentifier, ): if not is_binary_address(monitoring_service_address): raise ValueError("Expected binary address for monitoring service") check_address_has_code_handle_pruned_block( client=jsonrpc_client, address=Address(monitoring_service_address), contract_name=CONTRACT_MONITORING_SERVICE, expected_code=decode_hex( contract_manager.get_runtime_hexcode(CONTRACT_MONITORING_SERVICE) ), given_block_identifier=block_identifier, ) proxy = jsonrpc_client.new_contract_proxy( abi=contract_manager.get_contract_abi(CONTRACT_MONITORING_SERVICE), contract_address=Address(monitoring_service_address), ) self.address = monitoring_service_address self.client = jsonrpc_client self.contract_manager = contract_manager self.node_address = self.client.address self.proxy = proxy
def deploy_token_network_registry( secret_registry_deploy_result: Callable[[], SecretRegistry], deploy_client: JSONRPCClient, contract_manager: ContractManager, proxy_manager: ProxyManager, chain_id: ChainID, settle_timeout_min: int, settle_timeout_max: int, max_token_networks: int, ) -> TokenNetworkRegistry: secret_registry_proxy = secret_registry_deploy_result() contract, receipt = deploy_client.deploy_single_contract( contract_name=CONTRACT_TOKEN_NETWORK_REGISTRY, contract=contract_manager.get_contract( CONTRACT_TOKEN_NETWORK_REGISTRY), constructor_parameters=[ secret_registry_proxy.address, chain_id, settle_timeout_min, settle_timeout_max, max_token_networks, ], ) return proxy_manager.token_network_registry( TokenNetworkRegistryAddress(to_canonical_address(contract.address)), BlockNumber(receipt["blockNumber"]), )
def jsonrpc_services( proxy_manager: ProxyManager, private_keys: List[PrivateKey], secret_registry_address: SecretRegistryAddress, service_registry_address: ServiceRegistryAddress, token_network_registry_address: TokenNetworkRegistryAddress, web3: Web3, contract_manager: ContractManager, ) -> BlockchainServices: secret_registry = proxy_manager.secret_registry(secret_registry_address) service_registry = None if service_registry_address: service_registry = proxy_manager.service_registry(service_registry_address) deploy_registry = proxy_manager.token_network_registry(token_network_registry_address) blockchain_services = list() for privkey in private_keys: rpc_client = JSONRPCClient(web3, privkey) proxy_manager = ProxyManager( rpc_client=rpc_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) blockchain_services.append(proxy_manager) return BlockchainServices( deploy_registry=deploy_registry, secret_registry=secret_registry, service_registry=service_registry, proxy_manager=proxy_manager, blockchain_services=blockchain_services, )
def test_token( deploy_client, token_proxy, private_keys, blockchain_rpc_ports, web3, ): privkey = private_keys[1] address = privatekey_to_address(privkey) address = to_canonical_address(address) other_client = JSONRPCClient( '0.0.0.0', blockchain_rpc_ports[0], privkey, web3=web3, ) other_token_proxy = Token( other_client, to_canonical_address(token_proxy.proxy.contract.address), ) # send some funds from deployer to generated address transfer_funds = 100 token_proxy.transfer(address, transfer_funds) assert transfer_funds == token_proxy.balance_of(address) allow_funds = 100 token_proxy.approve(address, allow_funds) assert allow_funds == token_proxy.proxy.contract.functions.allowance( to_checksum_address(deploy_client.sender), to_checksum_address(address), ).call() other_token_proxy.transfer(deploy_client.sender, transfer_funds) assert token_proxy.balance_of(address) == 0
def jsonrpc_services( deploy_service, private_keys, secret_registry_address, token_network_registry_address, web3=None, ): secret_registry = deploy_service.secret_registry(secret_registry_address) deploy_registry = deploy_service.token_network_registry( token_network_registry_address) host = '0.0.0.0' blockchain_services = list() for privkey in private_keys: rpc_client = JSONRPCClient( host, deploy_service.client.port, privkey, web3=web3, ) blockchain = BlockChainService(privkey, rpc_client) blockchain_services.append(blockchain) return BlockchainServices( deploy_registry, secret_registry, deploy_service, blockchain_services, )
def new_filter( jsonrpc_client: JSONRPCClient, contract_address: address, topics: Optional[List[int]], from_block: Union[str, int] = 0, to_block: Union[str, int] = 'latest'): """ Custom new filter implementation to handle bad encoding from geth rpc. """ if isinstance(from_block, int): from_block = hex(from_block) if isinstance(to_block, int): to_block = hex(to_block) json_data = { 'fromBlock': from_block, 'toBlock': to_block, 'address': address_encoder(normalize_address(contract_address)), } if topics is not None: json_data['topics'] = [ topic_encoder(topic) for topic in topics ] return jsonrpc_client.call('eth_newFilter', json_data)
def __init__( self, jsonrpc_client: JSONRPCClient, service_registry_address: Address, contract_manager: ContractManager, ): if not is_binary_address(service_registry_address): raise ValueError("Expected binary address for service registry") self.contract_manager = contract_manager check_address_has_code( client=jsonrpc_client, address=service_registry_address, contract_name=CONTRACT_SERVICE_REGISTRY, expected_code=decode_hex( contract_manager.get_runtime_hexcode( CONTRACT_SERVICE_REGISTRY)), ) proxy = jsonrpc_client.new_contract_proxy( abi=self.contract_manager.get_contract_abi( CONTRACT_SERVICE_REGISTRY), contract_address=service_registry_address, ) self.address = service_registry_address self.proxy = proxy self.client = jsonrpc_client self.node_address = self.client.address
def get_filter_events( jsonrpc_client: JSONRPCClient, contract_address: address, topics: Optional[List[int]], from_block: Union[str, int] = 0, to_block: Union[str, int] = 'latest') -> List[Dict]: """ Get filter. This handles bad encoding from geth rpc. """ if isinstance(from_block, int): from_block = hex(from_block) if isinstance(to_block, int): to_block = hex(to_block) json_data = { 'fromBlock': from_block, 'toBlock': to_block, 'address': address_encoder(normalize_address(contract_address)), } if topics is not None: json_data['topics'] = [ topic_encoder(topic) for topic in topics ] filter_changes = jsonrpc_client.call('eth_getLogs', json_data) # geth could return None if filter_changes is None: return [] result = [] for log_event in filter_changes: address = address_decoder(log_event['address']) data = data_decoder(log_event['data']) topics = [ topic_decoder(topic) for topic in log_event['topics'] ] block_number = log_event.get('blockNumber') if not block_number: block_number = 0 else: block_number = int(block_number, 0) result.append({ 'topics': topics, 'data': data, 'address': address, 'block_number': block_number, }) return result
def main(private_key, eth_amount, targets_file, port, host): client = JSONRPCClient( host, port, private_key, ) targets = [t.strip() for t in targets_file] balance = client.balance(client.sender) balance_needed = len(targets) * eth_amount if balance_needed * WEI_TO_ETH > balance: print("Not enough balance to fund {} accounts with {} eth each. Need {}, have {}".format( len(targets), eth_amount, balance_needed, balance / WEI_TO_ETH )) print("Sending {} eth to:".format(eth_amount)) for target in targets: print(" - {}".format(target)) client.send_transaction(sender=client.sender, to=target, value=eth_amount * WEI_TO_ETH)
def deploy_contract_web3( contract_name: str, deploy_client: JSONRPCClient, contract_manager: ContractManager, constructor_arguments: typing.Tuple[typing.Any, ...] = (), ) -> typing.Address: compiled = { contract_name: contract_manager.get_contract(contract_name), } contract_proxy = deploy_client.deploy_solidity_contract( contract_name, compiled, constructor_parameters=constructor_arguments, ) return typing.Address(to_canonical_address(contract_proxy.contract.address))
def test_duplicated_transaction_raises(deploy_client): """ If the same transaction is sent twice a JSON RPC error is raised. """ contract_proxy = deploy_rpc_test_contract(deploy_client) address = contract_proxy.contract_address assert len(deploy_client.web3.eth.getCode(to_checksum_address(address))) > 0 second_client = JSONRPCClient( '0.0.0.0', deploy_client.port, deploy_client.privkey, web3=deploy_client.web3, ) second_proxy = second_client.new_contract_proxy( contract_proxy.contract.abi, contract_proxy.contract_address, ) gas = contract_proxy.estimate_gas('ret') * 2 with pytest.raises((ReplacementTransactionUnderpriced, ValidationError)): second_proxy.transact('ret', startgas=gas) contract_proxy.transact('ret', startgas=gas)
def test_duplicated_transaction_raises(deploy_client, blockchain_backend): """ If the same transaction is sent twice a JSON RPC error is raised. """ contract_proxy = deploy_rpc_test_contract(deploy_client) address = contract_proxy.contract_address assert len(deploy_client.eth_getCode(address)) > 0 host = '0.0.0.0' # hardcoded in the deploy_client fixture second_client = JSONRPCClient( host, deploy_client.port, deploy_client.privkey, ) second_proxy = second_client.new_contract_proxy( contract_proxy.abi, contract_proxy.contract_address, ) gas = contract_proxy.estimate_gas('ret') * 2 with pytest.raises(EthNodeCommunicationError): second_proxy.transact('ret', startgas=gas) contract_proxy.transact('ret', startgas=gas)
def all_contract_events_raw( rpc: JSONRPCClient, contract_address: str, start_block: Union[str, int] = 0, end_block: Union[str, int] = 'latest') -> List[Dict]: """Find all events for a deployed contract given its `contract_address`. Args: rpc: client instance. contract_address: hex encoded contract address. start_block: read event-logs starting from this block number (default: 0). end_block: read event-logs up to this block number (default: 'latest'). Returns: events """ return rpc.call('eth_getLogs', { 'fromBlock': str(start_block), 'toBlock': str(end_block), 'address': address_encoder(normalize_address(contract_address)), 'topics': [], })
def test_payment_channel_proxy_basics( token_network_proxy, private_keys, token_proxy, chain_id, web3, contract_manager, ): token_network_address = to_canonical_address(token_network_proxy.proxy.contract.address) c1_client = JSONRPCClient(web3, private_keys[1]) c1_chain = BlockChainService(private_keys[1], c1_client) c2_client = JSONRPCClient(web3, private_keys[2]) c1_token_network_proxy = TokenNetwork( jsonrpc_client=c1_client, token_network_address=token_network_address, contract_manager=contract_manager, ) c2_token_network_proxy = TokenNetwork( jsonrpc_client=c2_client, token_network_address=token_network_address, contract_manager=contract_manager, ) start_block = web3.eth.blockNumber # create a channel channel_identifier = c1_token_network_proxy.new_netting_channel( c2_client.address, TEST_SETTLE_TIMEOUT_MIN, ) assert channel_identifier is not None # create channel proxies channel_proxy_1 = PaymentChannel( token_network=c1_token_network_proxy, channel_identifier=channel_identifier, contract_manager=contract_manager, ) channel_proxy_2 = PaymentChannel( token_network=c2_token_network_proxy, channel_identifier=channel_identifier, contract_manager=contract_manager, ) channel_filter = channel_proxy_1.all_events_filter( from_block=start_block, to_block='latest', ) assert channel_proxy_1.channel_identifier == channel_identifier assert channel_proxy_2.channel_identifier == channel_identifier assert channel_proxy_1.opened() is True assert channel_proxy_2.opened() is True # check the settlement timeouts assert channel_proxy_1.settle_timeout() == channel_proxy_2.settle_timeout() assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN events = channel_filter.get_all_entries() assert len(events) == 1 # ChannelOpened # test deposits initial_token_balance = 100 token_proxy.transfer(c1_client.address, initial_token_balance) initial_balance_c1 = token_proxy.balance_of(c1_client.address) assert initial_balance_c1 == initial_token_balance initial_balance_c2 = token_proxy.balance_of(c2_client.address) assert initial_balance_c2 == 0 # actual deposit channel_proxy_1.set_total_deposit(10) events = channel_filter.get_all_entries() assert len(events) == 2 # ChannelOpened, ChannelNewDeposit # balance proof by c2 transferred_amount = 3 balance_proof = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=1, chain_id=chain_id, transferred_amount=transferred_amount, ) balance_proof.signature = encode_hex(eth_sign( privkey=encode_hex(private_keys[1]), data=balance_proof.serialize_bin(), )) # correct close c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), signature=decode_hex(balance_proof.signature), ) assert channel_proxy_1.closed() is True assert channel_proxy_2.closed() is True events = channel_filter.get_all_entries() assert len(events) == 3 # ChannelOpened, ChannelNewDeposit, ChannelClosed # check the settlement timeouts again assert channel_proxy_1.settle_timeout() == channel_proxy_2.settle_timeout() assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN # update transfer wait_until_block(c1_chain, c1_client.block_number() + TEST_SETTLE_TIMEOUT_MIN) c2_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=0, locked_amount=0, locksroot=EMPTY_HASH, partner=c1_client.address, partner_transferred_amount=transferred_amount, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, ) assert channel_proxy_1.settled() is True assert channel_proxy_2.settled() is True events = channel_filter.get_all_entries() assert len(events) == 4 # ChannelOpened, ChannelNewDeposit, ChannelClosed, ChannelSettled
def test_payment_channel_outdated_channel_close( token_network_proxy, private_keys, chain_id, web3, contract_manager, ): token_network_address = to_canonical_address(token_network_proxy.proxy.contract.address) partner = privatekey_to_address(private_keys[0]) client = JSONRPCClient(web3, private_keys[1]) chain = BlockChainService(private_keys[1], client) token_network_proxy = TokenNetwork( jsonrpc_client=client, token_network_address=token_network_address, contract_manager=contract_manager, ) start_block = web3.eth.blockNumber # create a channel channel_identifier = token_network_proxy.new_netting_channel( partner, TEST_SETTLE_TIMEOUT_MIN, ) assert channel_identifier is not None # create channel proxies channel_proxy_1 = PaymentChannel( token_network=token_network_proxy, channel_identifier=channel_identifier, contract_manager=contract_manager, ) channel_filter = channel_proxy_1.all_events_filter( from_block=start_block, to_block='latest', ) assert channel_proxy_1.channel_identifier == channel_identifier assert channel_proxy_1.opened() is True # balance proof by c1 balance_proof = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=0, chain_id=chain_id, transferred_amount=0, ) balance_proof.signature = encode_hex(eth_sign( privkey=encode_hex(private_keys[0]), data=balance_proof.serialize_bin(), )) # correct close token_network_proxy.close( channel_identifier=channel_identifier, partner=partner, balance_hash=bytes(32), nonce=balance_proof.nonce, additional_hash=bytes(32), signature=decode_hex(balance_proof.signature), ) assert channel_proxy_1.closed() is True events = channel_filter.get_all_entries() assert len(events) == 2 # ChannelOpened, ChannelClosed # check the settlement timeouts again assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN # update transfer wait_until_block(chain, client.block_number() + TEST_SETTLE_TIMEOUT_MIN) token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=0, locked_amount=0, locksroot=EMPTY_HASH, partner=partner, partner_transferred_amount=0, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, ) assert channel_proxy_1.settled() is True events = channel_filter.get_all_entries() assert len(events) == 3 # ChannelOpened, ChannelClosed, ChannelSettled # Create a new channel with a different identifier # create a channel new_channel_identifier = token_network_proxy.new_netting_channel( partner, TEST_SETTLE_TIMEOUT_MIN, ) assert new_channel_identifier is not None # create channel proxies channel_proxy_2 = PaymentChannel( token_network=token_network_proxy, channel_identifier=new_channel_identifier, contract_manager=contract_manager, ) assert channel_proxy_2.channel_identifier == new_channel_identifier assert channel_proxy_2.opened() is True with pytest.raises(ChannelOutdatedError): token_network_proxy.close( channel_identifier=channel_identifier, partner=partner, balance_hash=bytes(32), nonce=balance_proof.nonce, additional_hash=bytes(32), signature=decode_hex(balance_proof.signature), )
def test_blockchain( blockchain_backend, # required to start the geth backend pylint: disable=unused-argument blockchain_rpc_ports, private_keys, poll_timeout): # pylint: disable=too-many-locals addresses = [ privatekey_to_address(priv) for priv in private_keys ] privatekey = private_keys[0] address = privatekey_to_address(privatekey) total_token = 100 host = '127.0.0.1' jsonrpc_client = JSONRPCClient( host, blockchain_rpc_ports[0], privatekey, ) 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, list(), (total_token, 'raiden', 2, 'Rd'), contract_path=humantoken_path, gasprice=GAS_PRICE, 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, list(), tuple(), contract_path=registry_path, gasprice=GAS_PRICE, timeout=poll_timeout, ) log_list = jsonrpc_client.call( 'eth_getLogs', { 'fromBlock': '0x0', 'toBlock': 'latest', 'topics': [], }, ) assert not log_list assert token_proxy.call('balanceOf', address) == total_token transaction_hash = registry_proxy.transact( 'addToken', token_proxy.contract_address, gasprice=denoms.wei, ) jsonrpc_client.poll(unhexlify(transaction_hash), timeout=poll_timeout) assert len(registry_proxy.call('tokenAddresses')) == 1 log_list = jsonrpc_client.call( 'eth_getLogs', { 'fromBlock': '0x0', 'toBlock': 'latest', 'topics': [], }, ) assert len(log_list) == 1 channel_manager_address_encoded = registry_proxy.call( 'channelManagerByToken', token_proxy.contract_address, ) channel_manager_address = normalize_address(channel_manager_address_encoded) log = log_list[0] log_topics = [ topic_decoder(topic) for topic in log['topics'] # pylint: disable=invalid-sequence-index ] log_data = log['data'] # pylint: disable=invalid-sequence-index event = registry_proxy.translator.decode_event( log_topics, unhexlify(log_data[2:]), ) assert channel_manager_address == normalize_address(event['channel_manager_address']) assert token_proxy.contract_address == normalize_address(event['token_address']) channel_manager_proxy = jsonrpc_client.new_contract_proxy( CONTRACT_MANAGER.get_abi(CONTRACT_CHANNEL_MANAGER), channel_manager_address, ) transaction_hash = channel_manager_proxy.transact( 'newChannel', addresses[1], 10, gasprice=denoms.wei, ) jsonrpc_client.poll(unhexlify(transaction_hash), timeout=poll_timeout) log_list = jsonrpc_client.call( 'eth_getLogs', { 'fromBlock': '0x0', 'toBlock': 'latest', 'topics': [], }, ) assert len(log_list) == 2
def reclaim_eth(account: Account, chain_rpc_urls: dict, data_path: str, min_age_hours: int): web3s: Dict[str, Web3] = { name: Web3(HTTPProvider(urls[0])) for name, urls in chain_rpc_urls.items() } data_path = Path(data_path) log.info('Starting eth reclaim', data_path=data_path) addresses = dict() for node_dir in data_path.glob('**/node_???'): scenario_name: Path = node_dir.parent.name last_run = next( iter( sorted( list(node_dir.glob('run-*.log')), key=lambda p: p.stat().st_mtime, reverse=True, ), ), None, ) # If there is no last run assume we can reclaim if last_run: age_hours = (time.time() - last_run.stat().st_mtime) / 3600 if age_hours < min_age_hours: log.debug( 'Skipping too recent node', scenario_name=scenario_name, node=node_dir.name, age_hours=age_hours, ) continue for keyfile in node_dir.glob('keys/*'): keyfile_content = json.loads(keyfile.read_text()) address = keyfile_content.get('address') if address: addresses[to_checksum_address(address)] = decode_keyfile_json(keyfile_content, b'') log.info('Reclaiming candidates', addresses=list(addresses.keys())) txs = defaultdict(list) reclaim_amount = defaultdict(int) for chain_name, web3 in web3s.items(): log.info('Checking chain', chain=chain_name) for address, privkey in addresses.items(): balance = web3.eth.getBalance(address) if balance > RECLAIM_MIN_BALANCE: drain_amount = balance - (web3.eth.gasPrice * VALUE_TX_GAS_COST) log.info( 'Reclaiming', from_address=address, amount=drain_amount.__format__(',d'), chain=chain_name, ) reclaim_amount[chain_name] += drain_amount client = JSONRPCClient(web3, privkey) txs[chain_name].append( client.send_transaction( to=account.address, value=drain_amount, startgas=VALUE_TX_GAS_COST, ), ) for chain_name, chain_txs in txs.items(): wait_for_txs(web3s[chain_name], chain_txs, 1000) for chain_name, amount in reclaim_amount.items(): log.info('Reclaimed', chain=chain_name, amount=amount.__format__(',d'))