def nucypher_test_config(blockchain_config): config = NucypherConfig(keyring="this is the most secure password in the world.", blockchain_config=blockchain_config) yield config NucypherConfig.reset() Blockchain.sever() del config
def __init__(self, checksum_address: str = None, blockchain: Blockchain = None ) -> None: """ :param checksum_address: If not passed, we assume this is an unknown actor :param token_agent: The token agent with the blockchain attached; If not passed, A default token agent and blockchain connection will be created from default values. """ try: parent_address = self.checksum_public_address # type: str if checksum_address is not None: if parent_address != checksum_address: raise ValueError("Can't have two different addresses.") except AttributeError: self.checksum_public_address = checksum_address # type: str if blockchain is None: blockchain = Blockchain.connect() self.blockchain = blockchain self.token_agent = NucypherTokenAgent() self._transaction_cache = list() # type: list # track transactions transmitted
def connect_to_blockchain(self, enode: str = None, recompile_contracts: bool = False, full_sync: bool = False) -> None: """ :param enode: ETH seednode or bootnode enode address to start learning from, i.e. 'enode://[email protected]:30303' :param recompile_contracts: Recompile all contracts on connection. :return: None """ if self.federated_only: raise NodeConfiguration.ConfigurationError("Cannot connect to blockchain in federated mode") self.blockchain = Blockchain.connect(provider_uri=self.provider_uri, compile=recompile_contracts, poa=self.poa, fetch_registry=True, provider_process=self.provider_process, sync=full_sync) # Read Ethereum Node Keyring self.accounts = self.blockchain.interface.w3.eth.accounts # Add Ethereum Peer if enode: if self.blockchain.interface.client_version == 'geth': self.blockchain.interface.w3.geth.admin.addPeer(enode) else: raise NotImplementedError
def __init__(self, blockchain: Blockchain = None, contract: Contract = None, transaction_gas: int = None ) -> None: self.log = Logger(self.__class__.__name__) if blockchain is None: blockchain = Blockchain.connect() self.blockchain = blockchain if contract is None: # Fetch the contract contract = self.blockchain.interface.get_contract_by_name(name=self.registry_contract_name, proxy_name=self._proxy_name, use_proxy_address=self._forward_address) self.__contract = contract if not transaction_gas: transaction_gas = EthereumContractAgent.DEFAULT_TRANSACTION_GAS self.transaction_gas = transaction_gas super().__init__() self.log.info("Initialized new {} for {} with {} and {}".format(self.__class__.__name__, self.contract_address, self.blockchain.interface.provider_uri, self.blockchain.interface.registry.filepath))
def connect_to_blockchain(self): """Initialize all blockchain entities from parsed config values""" self.blockchain = Blockchain.from_config(filepath=self.config_filepath) self.accounts = self.blockchain.interface.w3.eth.accounts #TODO: Exception handling here for key error when using incompadible operating mode if self.payload['tester'] and self.payload['deploy']: self.blockchain.interface.deployer_address = self.accounts[0]
def from_blockchain(cls, provider_uri: str, registry=None, *args, **kwargs): blockchain = Blockchain.connect(provider_uri=provider_uri, registry=registry) instance = cls(blockchain=blockchain, *args, **kwargs) return instance
def connect_to_blockchain(self, recompile_contracts: bool = False): if self.federated_only: raise NodeConfiguration.ConfigurationError("Cannot connect to blockchain in federated mode") self.blockchain = Blockchain.connect(provider_uri=self.provider_uri, compile=recompile_contracts, poa=self.poa) self.accounts = self.blockchain.interface.w3.eth.accounts self.log.debug("Established connection to provider {}".format(self.blockchain.interface.provider_uri))
def connect_to_blockchain(self): """Initialize all blockchain entities from parsed config values""" if self.node_config is constants.NO_NODE_CONFIGURATION: raise RuntimeError("No node configuration is available") self.blockchain = Blockchain.from_config(config=self.node_config) self.accounts = self.blockchain.interface.w3.eth.accounts if self.node_config.deploy: self.blockchain.interface.deployer_address = self.accounts[0]
def __init__(self, blockchain: Blockchain = None, *args, **kwargs): if blockchain is None: blockchain = Blockchain.connect() self.blockchain = blockchain # Fetch the contract by reading address and abi from the registry and blockchain contract = self.blockchain.interface.get_contract_by_name( name=self.principal_contract_name, upgradeable=self._upgradeable) self.__contract = contract super().__init__()
def test_rollback(click_runner): """Roll 'em all back!""" mock_temporary_registry = EthereumContractRegistry(registry_filepath=MOCK_REGISTRY_FILEPATH) blockchain = Blockchain.connect(registry=mock_temporary_registry) # Input Components yes = 'Y\n' # Stage Rollbacks old_secret = INSECURE_SECRETS[PLANNED_UPGRADES] rollback_secret = generate_insecure_secret() user_input = '0\n' + yes + old_secret + rollback_secret + rollback_secret contracts_to_rollback = ('MinersEscrow', # v4 -> v3 'PolicyManager', # v4 -> v3 'MiningAdjudicator', # v4 -> v3 ) # Execute Rollbacks for contract_name in contracts_to_rollback: command = ('rollback', '--contract-name', contract_name, '--registry-infile', MOCK_REGISTRY_FILEPATH, '--provider-uri', TEST_PROVIDER_URI, '--poa') result = click_runner.invoke(deploy, command, input=user_input, catch_exceptions=False) assert result.exit_code == 0 records = blockchain.interface.registry.search(contract_name=contract_name) assert len(records) == 4 *old_records, v3, v4 = records current_target, rollback_target = v4, v3 _name, current_target_address, *abi = current_target _name, rollback_target_address, *abi = rollback_target assert current_target_address != rollback_target_address # Ensure the proxy targets the rollback target (previous version) with pytest.raises(BlockchainInterface.UnknownContract): blockchain.interface.get_proxy(target_address=current_target_address, proxy_name='Dispatcher') proxy = blockchain.interface.get_proxy(target_address=rollback_target_address, proxy_name='Dispatcher') # Deeper - Ensure the proxy targets the old deployment on-chain targeted_address = proxy.functions.target().call() assert targeted_address != current_target assert targeted_address == rollback_target_address
def derive_crypto_power( self, power_class: ClassVar ) -> Union[KeyPairBasedPower, DerivedKeyBasedPower]: """ Takes either a SigningPower or an DecryptingPower and returns either a SigningPower or DecryptingPower with the coinciding private key. TODO: Derive a key from the root_key. """ # Keypair-Based if issubclass(power_class, KeyPairBasedPower): codex = { SigningPower: self.__signing_keypath, DecryptingPower: self.__root_keypath, TLSHostingPower: self.__tls_keypath } # Create Power try: umbral_privkey = self.__decrypt_keyfile(codex[power_class]) keypair = power_class._keypair_class(umbral_privkey) new_cryptopower = power_class(keypair=keypair) except KeyError: failure_message = "{} is an invalid type for deriving a CryptoPower".format( power_class.__name__) raise TypeError(failure_message) # Derived elif issubclass(power_class, DerivedKeyBasedPower): key_data = _read_keyfile(self.__delegating_keypath, deserializer=self._private_key_serializer) wrap_key = _derive_wrapping_key_from_key_material( salt=key_data['wrap_salt'], key_material=self.__derived_key_material) keying_material = SecretBox(wrap_key).decrypt(key_data['key']) new_cryptopower = power_class(keying_material=keying_material) elif power_class is BlockchainPower: new_cryptopower = power_class(blockchain=Blockchain.connect(), account=self.checksum_address) else: failure_message = "{} is an invalid type for deriving a CryptoPower.".format( power_class.__name__) raise ValueError(failure_message) return new_cryptopower
def test_geth_EIP_191_client_signature_integration(geth_dev_node): if 'CIRCLECI' in os.environ: pytest.skip("Do not run Geth nodes in CI") # Start a geth process blockchain = Blockchain.connect(provider_process=geth_dev_node, sync=False) # Sign a message (RPC) and verify it. etherbase = blockchain.interface.accounts[0] stamp = b'STAMP-' + os.urandom(64) signature = blockchain.interface.client.sign_message(account=etherbase, message=stamp) is_valid = verify_eip_191(address=etherbase, signature=signature, message=stamp) assert is_valid
def connect_to_blockchain(self): if self.federated_only: raise NodeConfiguration.ConfigurationError( "Cannot connect to blockchain in federated mode") if self.deployer: self.registry_filepath = NodeConfiguration.REGISTRY_SOURCE if self.compile: click.confirm("Compile solidity source?", abort=True) self.blockchain = Blockchain.connect(provider_uri=self.provider_uri, deployer=self.deployer, compile=self.compile) if self.poa: w3 = self.blockchain.interface.w3 w3.middleware_stack.inject(geth_poa_middleware, layer=0) self.accounts = self.blockchain.interface.w3.eth.accounts self.log.debug("CLI established connection to provider {}".format( self.blockchain.interface.provider_uri))
def __init__(self, beneficiary: str, blockchain: Blockchain = None, allocation_registry: AllocationRegistry = None, *args, **kwargs) -> None: self.blockchain = blockchain or Blockchain.connect() self.__allocation_registry = allocation_registry or self.__allocation_registry() self.__beneficiary = beneficiary self.__principal_contract = NO_CONTRACT_AVAILABLE self.__proxy_contract = NO_CONTRACT_AVAILABLE # Sets the above self.__read_principal() self.__read_proxy() super().__init__(blockchain=self.blockchain, contract=self.principal_contract, *args, **kwargs)
def __init__(self, blockchain: Blockchain = None, contract: Contract = None, *args, **kwargs): if blockchain is None: blockchain = Blockchain.connect() self.blockchain = blockchain if contract is None: address = blockchain.interface.get_contract_address( contract_name=self._principal_contract_name)[ -1] # TODO: Handle multiple contract = blockchain.interface.get_contract(address) self.__contract = contract super().__init__(*args, **kwargs)
def __init__(self, checksum_address: str = None, blockchain: Blockchain = None): """ :param checksum_address: If not passed, we assume this is an unknown actor """ try: parent_address = self.checksum_address # type: str if checksum_address is not None: if parent_address != checksum_address: raise ValueError("Can't have two different addresses.") except AttributeError: self.checksum_address = checksum_address # type: str if blockchain is None: blockchain = Blockchain.connect() # Attempt to connect self.blockchain = blockchain self.token_agent = NucypherTokenAgent(blockchain=self.blockchain) self._transaction_cache = list( ) # type: list # track transactions transmitted
def __init__(self, blockchain: Blockchain = None, contract: Contract = None) -> None: self.log = getLogger('agency') if blockchain is None: blockchain = Blockchain.connect() self.blockchain = blockchain if contract is None: # Fetch the contract by reading address and abi from the registry and blockchain contract = self.blockchain.interface.get_contract_by_name( name=self.principal_contract_name, upgradeable=self._upgradeable) self.__contract = contract super().__init__() self.log.info("Initialized new {} for {} with {} and {}".format( self.__class__.__name__, self.contract_address, self.blockchain.interface.provider_uri, self.blockchain.interface.registry.filepath))
def __init__(self, blockchain: Blockchain = None, registry_filepath: str = None, *args, **kwargs) -> None: if blockchain is None: blockchain = Blockchain.connect() self.blockchain = blockchain if registry_filepath is not None: # TODO: Warn on override? self.blockchain.interface._registry._swap_registry( filepath=registry_filepath) # Fetch the contract by reading address and abi from the registry and blockchain contract = self.blockchain.interface.get_contract_by_name( name=self.principal_contract_name, upgradeable=self._upgradeable) self.__contract = contract super().__init__()
def produce(self, passphrase: str = None, **overrides): """Produce a new Ursula from configuration""" if not self.temp: self.read_keyring() self.keyring.unlock(passphrase=passphrase) merged_parameters = { **self.static_payload, **self.dynamic_payload, **overrides } if self.federated_only is False: if self.poa: # TODO: move this..? w3 = self.miner_agent.blockchain.interface.w3 w3.middleware_stack.inject(geth_poa_middleware, layer=0) if not self.miner_agent: # TODO: move this..? self.blockchain = Blockchain.connect( provider_uri=self.blockchain_uri, registry_filepath=self.registry_filepath) self.token_agent = NucypherTokenAgent( blockchain=self.blockchain) self.miner_agent = MinerAgent(token_agent=self.token_agent) merged_parameters.update(miner_agent=self.miner_agent) ursula = self._Character(**merged_parameters) if self.temp: # TODO: Move this..? class MockDatastoreThreadPool(object): def callInThread(self, f, *args, **kwargs): return f(*args, **kwargs) ursula.datastore_threadpool = MockDatastoreThreadPool() return ursula
def __connect(deployer_address=None): # Ensure config root exists if not os.path.exists(DEFAULT_CONFIG_ROOT): os.makedirs(DEFAULT_CONFIG_ROOT) # Connect to Blockchain blockchain = Blockchain.connect(provider_uri=provider_uri, deployer=True, compile=not no_compile, poa=poa) if not deployer_address: etherbase = blockchain.interface.w3.eth.accounts[0] deployer_address = etherbase click.confirm( "Deployer Address is {} - Continue?".format(deployer_address), abort=True) deployer = Deployer(blockchain=blockchain, deployer_address=deployer_address) return deployer
def __init__(self, domains: Set = (GLOBAL_DOMAIN, ), is_me: bool = True, federated_only: bool = False, blockchain: Blockchain = None, checksum_public_address: bytes = NO_BLOCKCHAIN_CONNECTION. bool_value(False), network_middleware: RestMiddleware = None, keyring_dir: str = None, crypto_power: CryptoPower = None, crypto_power_ups: List[CryptoPowerUp] = None, *args, **kwargs) -> None: """ Base class for Nucypher protocol actors. PowerUps ======== :param crypto_power: A CryptoPower object; if provided, this will be the character's CryptoPower. :param crypto_power_ups: If crypto_power is not provided, a new one will be made to consume all CryptoPowerUps. If neither crypto_power nor crypto_power_ups are provided, we give this Character all CryptoPowerUps listed in their _default_crypto_powerups attribute. :param is_me: Set this to True when you want this Character to represent the owner of the configuration under which the program is being run. A Character who is_me can do things that other Characters can't, like run servers, sign messages, and decrypt messages which are encrypted for them. Typically this will be True for exactly one Character, but there are scenarios in which its imaginable to be represented by zero Characters or by more than one Character. """ self.federated_only = federated_only # type: bool # # Powers # if crypto_power and crypto_power_ups: raise ValueError( "Pass crypto_power or crypto_power_ups (or neither), but not both." ) crypto_power_ups = crypto_power_ups or list() # type: list if crypto_power: self._crypto_power = crypto_power # type: CryptoPower elif crypto_power_ups: self._crypto_power = CryptoPower(power_ups=crypto_power_ups) else: self._crypto_power = CryptoPower( power_ups=self._default_crypto_powerups) self._checksum_address = checksum_public_address # # Self-Character # if is_me is True: if not self.federated_only: self.blockchain = blockchain or Blockchain.connect() self.keyring_dir = keyring_dir # type: str self.treasure_maps = {} # type: dict self.network_middleware = network_middleware or RestMiddleware() # # Signing Power # try: signing_power = self._crypto_power.power_ups( SigningPower) # type: SigningPower self._stamp = signing_power.get_signature_stamp( ) # type: SignatureStamp except NoSigningPower: self._stamp = NO_SIGNING_POWER # # Learner # Learner.__init__(self, domains=domains, network_middleware=network_middleware, *args, **kwargs) # # Stranger-Character # else: # Feel like a stranger if network_middleware is not None: raise TypeError( "Network middleware cannot be attached to a Stanger-Character." ) self._stamp = StrangerStamp(self.public_keys(SigningPower)) self.keyring_dir = STRANGER self.network_middleware = STRANGER # # Decentralized # if not federated_only: if not checksum_public_address: raise ValueError( "No checksum_public_address provided while running in a non-federated mode." ) else: self._checksum_address = checksum_public_address # TODO: Check that this matches BlockchainPower # # Federated # elif federated_only: try: self._set_checksum_address() # type: str except NoSigningPower: self._checksum_address = NO_BLOCKCHAIN_CONNECTION if checksum_public_address: # We'll take a checksum address, as long as it matches their singing key if not checksum_public_address == self.checksum_public_address: error = "Federated-only Characters derive their address from their Signing key; got {} instead." raise self.SuspiciousActivity( error.format(checksum_public_address)) # # Nicknames # try: self.nickname, self.nickname_metadata = nickname_from_seed( self.checksum_public_address) except SigningPower.not_found_error: if self.federated_only: self.nickname = self.nickname_metadata = NO_NICKNAME else: raise # # Fleet state # if is_me is True: self.known_nodes.record_fleet_state() # # Character Control # self.controller = NO_CONTROL_PROTOCOL
def deploy(click_config, action, poa, provider_uri, deployer_address, contract_name, allocation_infile, allocation_outfile, registry_infile, registry_outfile, no_compile, amount, recipient_address, config_root, force): """Manage contract and registry deployment""" # Ensure config root exists, because we need a default place to put outfiles. config_root = config_root or DEFAULT_CONFIG_ROOT if not os.path.exists(config_root): os.makedirs(config_root) # Establish a contract Registry registry, registry_filepath = None, (registry_outfile or registry_infile) if registry_filepath is not None: registry = EthereumContractRegistry( registry_filepath=registry_filepath) # Connect to Blockchain blockchain = Blockchain.connect(provider_uri=provider_uri, registry=registry, deployer=True, compile=not no_compile, poa=poa) # OK - Let's init a Deployment actor if not deployer_address: etherbase = blockchain.interface.w3.eth.accounts[0] deployer_address = etherbase # TODO: Make this required instead, perhaps interactive click.confirm( "Deployer Address is {} - Continue?".format(deployer_address), abort=True) deployer = Deployer(blockchain=blockchain, deployer_address=deployer_address) # The Big Three if action == "contracts": secrets = click_config.collect_deployment_secrets() # Track tx hashes, and new agents __deployment_transactions = dict() __deployment_agents = dict() if force: deployer.blockchain.interface.registry._destroy() try: txhashes, agents = deployer.deploy_network_contracts( miner_secret=bytes(secrets.miner_secret, encoding='utf-8'), policy_secret=bytes(secrets.policy_secret, encoding='utf-8'), adjudicator_secret=bytes(secrets.mining_adjudicator_secret, encoding='utf-8')) except BlockchainInterface.InterfaceError: raise # TODO: Handle registry management here (contract may already exist) else: __deployment_transactions.update(txhashes) # User Escrow Proxy deployer.deploy_escrow_proxy( secret=bytes(secrets.escrow_proxy_secret, encoding='utf-8')) click.secho("Deployed!", fg='green', bold=True) # # Deploy Single Contract # if contract_name: try: deployer_func = deployer.deployers[contract_name] except KeyError: message = "No such contract {}. Available contracts are {}".format( contract_name, deployer.deployers.keys()) click.secho(message, fg='red', bold=True) raise click.Abort() else: _txs, _agent = deployer_func() registry_outfile = deployer.blockchain.interface.registry.filepath click.secho( '\nDeployment Transaction Hashes for {}'.format(registry_outfile), bold=True, fg='blue') for contract_name, transactions in __deployment_transactions.items(): heading = '\n{} ({})'.format( contract_name, agents[contract_name].contract_address) click.secho(heading, bold=True) click.echo('*' * (42 + 3 + len(contract_name))) total_gas_used = 0 for tx_name, txhash in transactions.items(): receipt = deployer.blockchain.wait_for_receipt(txhash=txhash) total_gas_used += int(receipt['gasUsed']) if receipt['status'] == 1: click.secho("OK", fg='green', nl=False, bold=True) else: click.secho("Failed", fg='red', nl=False, bold=True) click.secho(" | {}".format(tx_name), fg='yellow', nl=False) click.secho(" | {}".format(txhash.hex()), fg='yellow', nl=False) click.secho(" ({} gas)".format(receipt['cumulativeGasUsed'])) click.secho("Block #{} | {}\n".format( receipt['blockNumber'], receipt['blockHash'].hex())) click.secho( "Cumulative Gas Consumption: {} gas\n".format(total_gas_used), bold=True, fg='blue') elif action == "allocations": if not allocation_infile: allocation_infile = click.prompt("Enter allocation data filepath") click.confirm("Continue deploying and allocating?", abort=True) deployer.deploy_beneficiaries_from_file( allocation_data_filepath=allocation_infile, allocation_outfile=allocation_outfile) elif action == "transfer": token_agent = NucypherTokenAgent(blockchain=blockchain) click.confirm( f"Transfer {amount} from {token_agent.contract_address} to {recipient_address}?", abort=True) txhash = token_agent.transfer( amount=amount, sender_address=token_agent.contract_address, target_address=recipient_address) click.secho(f"OK | {txhash}") return elif action == "destroy-registry": registry_filepath = deployer.blockchain.interface.registry.filepath click.confirm( f"Are you absolutely sure you want to destroy the contract registry at {registry_filepath}?", abort=True) os.remove(registry_filepath) click.secho(f"Successfully destroyed {registry_filepath}", fg='red') else: raise click.BadArgumentUsage(message=f"Unknown action '{action}'")
def test_upgrade_contracts(click_runner): # # Setup # # Connect to the blockchain with a blank temporary file-based registry mock_temporary_registry = EthereumContractRegistry(registry_filepath=MOCK_REGISTRY_FILEPATH) blockchain = Blockchain.connect(registry=mock_temporary_registry) # Check the existing state of the registry before the meat and potatoes expected_registrations = 9 with open(MOCK_REGISTRY_FILEPATH, 'r') as file: raw_registry_data = file.read() registry_data = json.loads(raw_registry_data) assert len(registry_data) == expected_registrations # # Input Components # cli_action = 'upgrade' base_command = ('--registry-infile', MOCK_REGISTRY_FILEPATH, '--provider-uri', TEST_PROVIDER_URI, '--poa') # Generate user inputs yes = 'Y\n' # :-) upgrade_inputs = dict() for version, insecure_secret in INSECURE_SECRETS.items(): next_version = version + 1 old_secret = INSECURE_SECRETS[version] try: new_secret = INSECURE_SECRETS[next_version] except KeyError: continue # addr-----secret----new deploy secret (2x for confirmation) user_input = '0\n' + yes + old_secret + (new_secret * 2) upgrade_inputs[next_version] = user_input # # Stage Upgrades # contracts_to_upgrade = ('MinersEscrow', # v1 -> v2 'PolicyManager', # v1 -> v2 'MiningAdjudicator', # v1 -> v2 'UserEscrowProxy', # v1 -> v2 'MinersEscrow', # v2 -> v3 'MinersEscrow', # v3 -> v4 'MiningAdjudicator', # v2 -> v3 'PolicyManager', # v2 -> v3 'UserEscrowProxy', # v2 -> v3 'UserEscrowProxy', # v3 -> v4 'PolicyManager', # v3 -> v4 'MiningAdjudicator', # v3 -> v4 ) # NOTE: Keep all versions the same in this test (all version 4, for example) # Each contract starts at version 1 version_tracker = {name: 1 for name in contracts_to_upgrade} # # Upgrade Contracts # for contract_name in contracts_to_upgrade: # Assemble CLI command command = (cli_action, '--contract-name', contract_name, *base_command) # Select upgrade interactive input scenario current_version = version_tracker[contract_name] new_version = current_version + 1 user_input = upgrade_inputs[new_version] # Execute upgrade (Meat) result = click_runner.invoke(deploy, command, input=user_input, catch_exceptions=False) assert result.exit_code == 0 # TODO: Console painting # Mutate the version tracking version_tracker[contract_name] += 1 expected_registrations += 1 # Verify the registry is updated (Potatoes) with open(MOCK_REGISTRY_FILEPATH, 'r') as file: # Read the registry file directly, bypassing its interfaces raw_registry_data = file.read() registry_data = json.loads(raw_registry_data) assert len(registry_data) == expected_registrations # Check that there is more than one entry, since we've deployed a "version 2" expected_enrollments = current_version + 1 registered_names = [r[0] for r in registry_data] enrollments = registered_names.count(contract_name) assert enrollments > 1, f"New contract is not enrolled in {MOCK_REGISTRY_FILEPATH}" assert enrollments == expected_enrollments, f"Incorrect number of records enrolled for {contract_name}. " \ f"Expected {expected_enrollments} got {enrollments}." # Ensure deployments are different addresses records = blockchain.interface.registry.search(contract_name=contract_name) assert len(records) == expected_enrollments old, new = records[-2:] # Get the last two entries old_name, old_address, *abi = old # Previous version new_name, new_address, *abi = new # New version assert old_name == new_name # TODO: Inspect ABI? assert old_address != new_address # Select proxy (Dispatcher vs Linker) if contract_name == "UserEscrowProxy": proxy_name = "UserEscrowLibraryLinker" else: proxy_name = 'Dispatcher' # Ensure the proxy targets the new deployment proxy = blockchain.interface.get_proxy(target_address=new_address, proxy_name=proxy_name) targeted_address = proxy.functions.target().call() assert targeted_address != old_address assert targeted_address == new_address
======= from nucypher.config.constants import DEFAULT_SIMULATION_REGISTRY_FILEPATH from nucypher.config.metadata import collect_stored_nodes from nucypher.data_sources import DataSource # This is already running in another process. from nucypher.network.middleware import RestMiddleware >>>>>>> 26103ab... Project-wide automated import optimization, followed-up with some hand-tweaking:examples/finnegans-wake-demo.py # This is already running in another process. ############################################## # This is already running in another process. ############################################## BLOCKCHAIN = Blockchain.connect() URSULA = Ursula.from_config() ######### # Alice # ######### ALICE = Alice.from_config() # Here are our Policy details. policy_end_datetime = maya.now() + datetime.timedelta(days=201) m = 2 n = 3 label = b"secret/files/and/stuff"
def deploy(click_config, action, poa, provider_uri, geth, enode, deployer_address, contract_name, allocation_infile, allocation_outfile, registry_infile, registry_outfile, no_compile, amount, recipient_address, config_root, sync, force): """Manage contract and registry deployment""" ETH_NODE = None # # Validate # # Ensure config root exists, because we need a default place to put output files. config_root = config_root or DEFAULT_CONFIG_ROOT if not os.path.exists(config_root): os.makedirs(config_root) # # Connect to Blockchain # # Establish a contract registry from disk if specified registry, registry_filepath = None, (registry_outfile or registry_infile) if registry_filepath is not None: registry = EthereumContractRegistry( registry_filepath=registry_filepath) if geth: # Spawn geth child process ETH_NODE = NuCypherGethDevnetProcess(config_root=config_root) ETH_NODE.ensure_account_exists(password=click_config.get_password( confirm=True)) if not ETH_NODE.initialized: ETH_NODE.initialize_blockchain() ETH_NODE.start() # TODO: Graceful shutdown provider_uri = ETH_NODE.provider_uri # Deployment-tuned blockchain connection blockchain = Blockchain.connect(provider_uri=provider_uri, poa=poa, registry=registry, compile=not no_compile, deployer=True, fetch_registry=False, sync=sync) # # Deployment Actor # if not deployer_address: for index, address in enumerate(blockchain.interface.w3.eth.accounts): click.secho(f"{index} --- {address}") choices = click.IntRange(0, len(blockchain.interface.w3.eth.accounts)) deployer_address_index = click.prompt("Select deployer address", default=0, type=choices) deployer_address = blockchain.interface.w3.eth.accounts[ deployer_address_index] # Verify Address if not force: click.confirm("Selected {} - Continue?".format(deployer_address), abort=True) deployer = Deployer(blockchain=blockchain, deployer_address=deployer_address) # Verify ETH Balance click.secho(f"\n\nDeployer ETH balance: {deployer.eth_balance}") if deployer.eth_balance == 0: click.secho("Deployer address has no ETH.", fg='red', bold=True) raise click.Abort() if not blockchain.interface.is_local: # (~ dev mode; Assume accounts are already unlocked) password = click.prompt("Enter ETH node password", hide_input=True) blockchain.interface.w3.geth.personal.unlockAccount( deployer_address, password) # Add ETH Bootnode or Peer if enode: if geth: blockchain.interface.w3.geth.admin.addPeer(enode) click.secho(f"Added ethereum peer {enode}") else: raise NotImplemented # TODO: other backends # # Action switch # if action == 'upgrade': if not contract_name: raise click.BadArgumentUsage( message="--contract-name is required when using --upgrade") existing_secret = click.prompt( 'Enter existing contract upgrade secret', hide_input=True) new_secret = click.prompt('Enter new contract upgrade secret', hide_input=True, confirmation_prompt=True) deployer.upgrade_contract(contract_name=contract_name, existing_plaintext_secret=existing_secret, new_plaintext_secret=new_secret) elif action == 'rollback': existing_secret = click.prompt( 'Enter existing contract upgrade secret', hide_input=True) new_secret = click.prompt('Enter new contract upgrade secret', hide_input=True, confirmation_prompt=True) deployer.rollback_contract(contract_name=contract_name, existing_plaintext_secret=existing_secret, new_plaintext_secret=new_secret) elif action == "contracts": registry_filepath = deployer.blockchain.interface.registry.filepath if os.path.isfile(registry_filepath): click.secho( f"\nThere is an existing contract registry at {registry_filepath}.\n" f"Did you mean 'nucypher-deploy upgrade'?\n", fg='yellow') click.confirm( "Optionally, destroy existing local registry and continue?", abort=True) click.confirm( f"Confirm deletion of contract registry '{registry_filepath}'?", abort=True) os.remove(registry_filepath) # # Deploy Single Contract # if contract_name: # TODO: Handle secret collection for single contract deployment try: deployer_func = deployer.deployers[contract_name] except KeyError: message = f"No such contract {contract_name}. Available contracts are {deployer.deployers.keys()}" click.secho(message, fg='red', bold=True) raise click.Abort() else: # Deploy single contract _txs, _agent = deployer_func() # TODO: Painting for single contract deployment if ETH_NODE: ETH_NODE.stop() return # # Stage Deployment # # Track tx hashes, and new agents __deployment_transactions = dict() __deployment_agents = dict() secrets = click_config.collect_deployment_secrets() click.clear() click.secho(NU_BANNER) w3 = deployer.blockchain.interface.w3 click.secho(f"Current Time ........ {maya.now().iso8601()}") click.secho( f"Web3 Provider ....... {deployer.blockchain.interface.provider_uri}" ) click.secho(f"Block ............... {w3.eth.blockNumber}") click.secho(f"Gas Price ........... {w3.eth.gasPrice}") click.secho(f"Deployer Address .... {deployer.checksum_address}") click.secho(f"ETH ................. {deployer.eth_balance}") click.secho( f"CHAIN ID............. {deployer.blockchain.interface.chain_id}") click.secho( f"CHAIN................ {deployer.blockchain.interface.chain_name}" ) # Ask - Last chance to gracefully abort if not force: click.secho( "\nDeployment successfully staged. Take a deep breath. \n", fg='green') if click.prompt("Type 'DEPLOY' to continue") != 'DEPLOY': raise click.Abort() # Delay - Last chance to crash and abort click.secho(f"Starting deployment in 3 seconds...", fg='red') time.sleep(1) click.secho(f"2...", fg='yellow') time.sleep(1) click.secho(f"1...", fg='green') time.sleep(1) click.secho(f"Deploying...", bold=True) # # DEPLOY < ------- # txhashes, deployers = deployer.deploy_network_contracts( miner_secret=secrets.miner_secret, policy_secret=secrets.policy_secret, adjudicator_secret=secrets.mining_adjudicator_secret, user_escrow_proxy_secret=secrets.escrow_proxy_secret) # Success __deployment_transactions.update(txhashes) # # Paint # total_gas_used = 0 # TODO: may be faulty for contract_name, transactions in __deployment_transactions.items(): # Paint heading heading = '\n{} ({})'.format( contract_name, deployers[contract_name].contract_address) click.secho(heading, bold=True) click.echo('*' * (42 + 3 + len(contract_name))) for tx_name, txhash in transactions.items(): # Wait for inclusion in the blockchain try: receipt = deployer.blockchain.wait_for_receipt( txhash=txhash) except TimeExhausted: raise # TODO: Option to wait longer or retry # Examine Receipt # TODO: This currently cannot receive failed transactions if receipt['status'] == 1: click.secho("OK", fg='green', nl=False, bold=True) else: click.secho("Failed", fg='red', nl=False, bold=True) # Accumulate gas total_gas_used += int(receipt['gasUsed']) # Paint click.secho(" | {}".format(tx_name), fg='yellow', nl=False) click.secho(" | {}".format(txhash.hex()), fg='yellow', nl=False) click.secho(" ({} gas)".format(receipt['cumulativeGasUsed'])) click.secho("Block #{} | {}\n".format( receipt['blockNumber'], receipt['blockHash'].hex())) # Paint outfile paths click.secho( "Cumulative Gas Consumption: {} gas".format(total_gas_used), bold=True, fg='blue') registry_outfile = deployer.blockchain.interface.registry.filepath click.secho('Generated registry {}'.format(registry_outfile), bold=True, fg='blue') # Save transaction metadata receipts_filepath = deployer.save_deployment_receipts( transactions=__deployment_transactions) click.secho(f"Saved deployment receipts to {receipts_filepath}", fg='blue', bold=True) # # Publish Contract Registry # if not deployer.blockchain.interface.is_local: if click.confirm("Publish new contract registry?"): try: response = registry.publish( ) # TODO: Handle non-200 response and dehydrate except EthereumContractRegistry.RegistryError as e: click.secho("Registry publication failed.", fg='red', bold=True) click.secho(str(e)) raise click.Abort() click.secho(f"Published new contract registry.", fg='green') elif action == "allocations": if not allocation_infile: allocation_infile = click.prompt("Enter allocation data filepath") click.confirm("Continue deploying and allocating?", abort=True) deployer.deploy_beneficiaries_from_file( allocation_data_filepath=allocation_infile, allocation_outfile=allocation_outfile) elif action == "transfer": token_agent = NucypherTokenAgent(blockchain=blockchain) click.confirm( f"Transfer {amount} from {token_agent.contract_address} to {recipient_address}?", abort=True) txhash = token_agent.transfer( amount=amount, sender_address=token_agent.contract_address, target_address=recipient_address) click.secho(f"OK | {txhash}") elif action == "publish-registry": registry = deployer.blockchain.interface.registry click.confirm( f"Publish {registry.filepath} to GitHub (Authentication Required)?", abort=True) try: response = registry.publish( ) # TODO: Handle non-200 response and dehydrate except EthereumContractRegistry.RegistryError as e: click.secho(str(e)) raise click.Abort() click.secho(f"Published new contract registry.", fg='green') elif action == "destroy-registry": registry_filepath = deployer.blockchain.interface.registry.filepath click.confirm( f"Are you absolutely sure you want to destroy the contract registry at {registry_filepath}?", abort=True) os.remove(registry_filepath) click.secho(f"Successfully destroyed {registry_filepath}", fg='red') else: raise click.BadArgumentUsage(message=f"Unknown action '{action}'") if ETH_NODE: ETH_NODE.stop()