def establish_deployer_registry(emitter, registry_infile: str = None, registry_outfile: str = None, use_existing_registry: bool = False, download_registry: bool = False, dev: bool = False) -> BaseContractRegistry: if download_registry: registry = InMemoryContractRegistry.from_latest_publication() emitter.message( f"Using latest published registry from {registry.source}") return registry # Establish a contract registry from disk if specified filepath = registry_infile default_registry_filepath = os.path.join( DEFAULT_CONFIG_ROOT, BaseContractRegistry.REGISTRY_NAME) if registry_outfile: registry_infile = registry_infile or default_registry_filepath if use_existing_registry: try: _result = shutil.copyfile(registry_infile, registry_outfile) except shutil.SameFileError: raise click.BadArgumentUsage( f"--registry-infile and --registry-outfile must not be the same path '{registry_infile}'." ) filepath = registry_outfile if dev: # TODO: Need a way to detect a geth --dev registry filepath here. (then deprecate the --dev flag) filepath = os.path.join(DEFAULT_CONFIG_ROOT, BaseContractRegistry.DEVELOPMENT_REGISTRY_NAME) registry_filepath = filepath or default_registry_filepath # All Done. registry = LocalContractRegistry(filepath=registry_filepath) emitter.message(f"Configured to registry filepath {registry_filepath}") return registry
def bootstrap_network( cls, economics: BaseEconomics = None ) -> Tuple['TesterBlockchain', 'InMemoryContractRegistry']: """For use with metric testing scripts""" registry = InMemoryContractRegistry() testerchain = cls(compiler=SolidityCompiler()) BlockchainInterfaceFactory.register_interface(testerchain) power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD, account=testerchain.etherbase_account) power.activate() testerchain.transacting_power = power origin = testerchain.client.etherbase deployer = ContractAdministrator(deployer_address=origin, registry=registry, economics=economics or cls._default_token_economics, staking_escrow_test_mode=True) _receipts = deployer.deploy_network_contracts(interactive=False) return testerchain, registry
def bootstrap_network( cls, registry: Optional[BaseContractRegistry] = None, economics: BaseEconomics = None ) -> Tuple['TesterBlockchain', 'InMemoryContractRegistry']: """For use with metric testing scripts""" if registry is None: registry = InMemoryContractRegistry() testerchain = cls() if not BlockchainInterfaceFactory.is_interface_initialized( provider_uri=testerchain.provider_uri): BlockchainInterfaceFactory.register_interface( interface=testerchain) origin = testerchain.client.etherbase admin = ContractAdministrator(deployer_address=origin, registry=registry, signer=Web3Signer(testerchain.client), economics=economics or cls.DEFAULT_ECONOMICS) gas_limit = None # TODO: Gas management - #842 for deployer_class in admin.primary_deployer_classes: if deployer_class is StakingEscrowDeployer: admin.deploy_contract( contract_name=deployer_class.contract_name, gas_limit=gas_limit, deployment_mode=INIT) else: admin.deploy_contract( contract_name=deployer_class.contract_name, gas_limit=gas_limit) admin.deploy_contract( contract_name=StakingEscrowDeployer.contract_name, gas_limit=gas_limit) return testerchain, registry
def bootstrap_network( cls, registry: Optional[BaseContractRegistry] = None, economics: BaseEconomics = None ) -> Tuple['TesterBlockchain', 'InMemoryContractRegistry']: """For use with metric testing scripts""" if registry is None: registry = InMemoryContractRegistry() testerchain = cls() if not BlockchainInterfaceFactory.is_interface_initialized( provider_uri=testerchain.provider_uri): BlockchainInterfaceFactory.register_interface( interface=testerchain) power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD, account=testerchain.etherbase_account) power.activate() testerchain.transacting_power = power origin = testerchain.client.etherbase admin = ContractAdministrator(deployer_address=origin, registry=registry, economics=economics or cls.DEFAULT_ECONOMICS, staking_escrow_test_mode=True) gas_limit = None # TODO: Gas management - #842 for deployer_class in admin.primary_deployer_classes: if deployer_class in ContractAdministrator.standard_deployer_classes: admin.deploy_contract( contract_name=deployer_class.contract_name, gas_limit=gas_limit) else: admin.deploy_contract( contract_name=deployer_class.contract_name, gas_limit=gas_limit) return testerchain, registry
def establish_deployer_registry(emitter, network: str = None, registry_infile: Optional[Path] = None, registry_outfile: Optional[Path] = None, use_existing_registry: bool = False, download_registry: bool = False, dev: bool = False ) -> BaseContractRegistry: if download_registry: registry = InMemoryContractRegistry.from_latest_publication(network=network) emitter.message(PRODUCTION_REGISTRY_ADVISORY.format(source=registry.source)) return registry # Establish a contract registry from disk if specified filepath = registry_infile default_registry_filepath = DEFAULT_CONFIG_ROOT / BaseContractRegistry.REGISTRY_NAME if registry_outfile: # mutative usage of existing registry registry_infile = registry_infile or default_registry_filepath if use_existing_registry: try: _result = shutil.copyfile(registry_infile, registry_outfile) except shutil.SameFileError: raise click.BadArgumentUsage(f"--registry-infile and --registry-outfile must not be the same path '{registry_infile}'.") filepath = registry_outfile if dev: # TODO: Need a way to detect a geth --dev registry filepath here. (then deprecate the --dev flag) filepath = DEFAULT_CONFIG_ROOT / BaseContractRegistry.DEVELOPMENT_REGISTRY_NAME registry_filepath = filepath or default_registry_filepath # All Done. registry = LocalContractRegistry(filepath=registry_filepath) emitter.message(LOCAL_REGISTRY_ADVISORY.format(registry_filepath=registry_filepath)) return registry
def download_registry(general_config, config_root, registry_outfile, network, force): """Download the latest registry.""" # Setup emitter = general_config.emitter ensure_config_root(config_root) github_source = GithubRegistrySource(network=network, registry_name=BaseContractRegistry.REGISTRY_NAME) source_manager = RegistrySourceManager(sources=[github_source]) if not force: prompt = CONFIRM_MANUAL_REGISTRY_DOWNLOAD.format(source=github_source) click.confirm(prompt, abort=True) try: registry = InMemoryContractRegistry.from_latest_publication(source_manager=source_manager, network=network) except RegistrySourceManager.NoSourcesAvailable: emitter.message(REGISTRY_NOT_AVAILABLE, color="red") raise click.Abort try: output_filepath = registry.commit(filepath=registry_outfile, overwrite=force) except InMemoryContractRegistry.CantOverwriteRegistry: emitter.message(CANNOT_OVERWRITE_REGISTRY, color="red") raise click.Abort emitter.message(SUCCESSFUL_REGISTRY_DOWNLOAD.format(output_filepath=output_filepath))
def create_crawler(node_db_filepath: str = IN_MEMORY_FILEPATH, dont_set_teacher: bool = False): registry = InMemoryContractRegistry() middleware = RestMiddleware() teacher_nodes = None if not dont_set_teacher: teacher_nodes = actions.load_seednodes( None, teacher_uris=['https://discover.nucypher.network:9151'], min_stake=0, federated_only=False, network_domains={'goerli'}, network_middleware=middleware) crawler = Crawler(domains={'goerli'}, network_middleware=middleware, known_nodes=teacher_nodes, registry=registry, start_learning_now=True, learn_on_same_thread=False, blockchain_db_host='localhost', blockchain_db_port=8086, node_storage_filepath=node_db_filepath) return crawler
def create_crawler(node_db_filepath: str = IN_MEMORY_FILEPATH, dont_set_teacher: bool = False): registry = InMemoryContractRegistry() middleware = RestMiddleware() teacher_nodes = None if not dont_set_teacher: teacher_nodes = actions.load_seednodes( None, # TODO: Needs emitter min_stake=0, federated_only=False, network_domains={'gemini'}, # TODO: Needs Cleanup network_middleware=middleware) crawler = Crawler( domains={'goerli'}, # TODO: Needs Cleanup network_middleware=middleware, known_nodes=teacher_nodes, registry=registry, start_learning_now=True, learn_on_same_thread=False, influx_host='localhost', # TODO: Needs Cleanup influx_port=8086, # TODO: Needs Cleanup node_storage_filepath=node_db_filepath) return crawler
def test_upgradeability(temp_dir_path): # Prepare remote source for compilation download_github_dir(GITHUB_SOURCE_LINK, temp_dir_path) # Prepare the blockchain BlockchainDeployerInterface.SOURCES = [ SourceBundle(base_path=SOLIDITY_SOURCE_ROOT), SourceBundle(base_path=Path(temp_dir_path)) ] provider_uri = 'tester://pyevm/2' # TODO: Testerchain caching Issues try: blockchain_interface = BlockchainDeployerInterface( provider_uri=provider_uri, gas_strategy='free') blockchain_interface.connect() origin = blockchain_interface.client.accounts[0] BlockchainInterfaceFactory.register_interface( interface=blockchain_interface) blockchain_interface.transacting_power = TransactingPower( password=INSECURE_DEVELOPMENT_PASSWORD, account=origin) blockchain_interface.transacting_power.activate() economics = make_token_economics(blockchain_interface) # Check contracts with multiple versions contract_name = AdjudicatorDeployer.contract_name skip_adjudicator_test = skip_test(blockchain_interface, contract_name) contract_name = StakingEscrowDeployer.contract_name skip_staking_escrow_test = skip_test(blockchain_interface, contract_name) contract_name = PolicyManagerDeployer.contract_name skip_policy_manager_test = skip_test(blockchain_interface, contract_name) if not skip_adjudicator_test and not skip_staking_escrow_test and not skip_policy_manager_test: return # Prepare master version of contracts and upgrade to the latest registry = InMemoryContractRegistry() token_deployer = NucypherTokenDeployer(registry=registry, deployer_address=origin, economics=economics) token_deployer.deploy() staking_escrow_deployer = StakingEscrowDeployer( registry=registry, deployer_address=origin, economics=economics) staking_escrow_deployer.deploy(deployment_mode=constants.INIT) policy_manager_deployer = PolicyManagerDeployer( registry=registry, deployer_address=origin, economics=economics) deploy_base_contract(blockchain_interface, policy_manager_deployer, skipt_test=skip_policy_manager_test) adjudicator_deployer = AdjudicatorDeployer(registry=registry, deployer_address=origin, economics=economics) deploy_base_contract(blockchain_interface, adjudicator_deployer, skipt_test=skip_adjudicator_test) if skip_staking_escrow_test: worklock_deployer = WorklockDeployer(registry=registry, deployer_address=origin, economics=economics) worklock_deployer.deploy() staking_escrow_deployer = StakingEscrowDeployer( registry=registry, deployer_address=origin, economics=economics) deploy_base_contract(blockchain_interface, staking_escrow_deployer, skipt_test=skip_staking_escrow_test) if not skip_staking_escrow_test: # TODO prepare at least one staker before calling upgrade staking_escrow_deployer.upgrade(contract_version="latest", confirmations=0) if not skip_policy_manager_test: policy_manager_deployer.upgrade(contract_version="latest", confirmations=0) if not skip_adjudicator_test: adjudicator_deployer.upgrade(contract_version="latest", confirmations=0) finally: # Unregister interface # TODO: Move to method? with contextlib.suppress(KeyError): del BlockchainInterfaceFactory._interfaces[provider_uri]
def estimate_gas(analyzer: AnalyzeGas = None) -> None: """ Execute a linear sequence of NyCypher transactions mimicking post-deployment usage on a local PyEVM blockchain; Record the resulting estimated transaction gas expenditure. Note: The function calls below are *order dependant* """ # # Setup # if analyzer is None: analyzer = AnalyzeGas() log = Logger(AnalyzeGas.LOG_NAME) os.environ[ 'GAS_ESTIMATOR_BACKEND_FUNC'] = 'eth.estimators.gas.binary_gas_search_exact' # Blockchain economics = StandardTokenEconomics(base_penalty=MIN_ALLOWED_LOCKED - 1, penalty_history_coefficient=0, percentage_penalty_coefficient=2, reward_coefficient=2) testerchain, registry = TesterBlockchain.bootstrap_network( economics=economics) web3 = testerchain.w3 print("\n********* SIZE OF MAIN CONTRACTS *********") MAX_SIZE = 24576 rows = list() for contract_name in NUCYPHER_CONTRACT_NAMES: compiled_contract = testerchain._raw_contract_cache[contract_name] version = list(compiled_contract).pop() # FIXME this value includes constructor code size but should not bin_runtime = compiled_contract[version]['evm']['bytecode']['object'] bin_length_in_bytes = len(bin_runtime) // 2 percentage = int(100 * bin_length_in_bytes / MAX_SIZE) bar = ('*' * (percentage // 2)).ljust(50) rows.append( (contract_name, bin_length_in_bytes, f'{bar} {percentage}%')) headers = ('Contract', 'Size (B)', f'% of max allowed contract size ({MAX_SIZE} B)') print(tabulate.tabulate(rows, headers=headers, tablefmt="simple"), end="\n\n") # Accounts origin, staker1, staker2, staker3, staker4, alice1, alice2, *everyone_else = testerchain.client.accounts ursula_with_stamp = mock_ursula(testerchain, staker1) # Contracts token_agent = NucypherTokenAgent(registry=registry) staking_agent = StakingEscrowAgent(registry=registry) policy_agent = PolicyManagerAgent(registry=registry) adjudicator_agent = AdjudicatorAgent(registry=registry) # Contract Callers token_functions = token_agent.contract.functions staker_functions = staking_agent.contract.functions policy_functions = policy_agent.contract.functions adjudicator_functions = adjudicator_agent.contract.functions analyzer.start_collection() print("********* Estimating Gas *********") def transact_and_log(label, function, transaction): estimates = function.estimateGas(transaction) transaction.update(gas=estimates) tx = function.transact(transaction) receipt = testerchain.wait_for_receipt(tx) log.info(f"{label} = {estimates} | {receipt['gasUsed']}") def transact(function, transaction): transaction.update(gas=1000000) tx = function.transact(transaction) testerchain.wait_for_receipt(tx) # First deposit ever is the most expensive, make it to remove unusual gas spending transact( token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 10), {'from': origin}) transact( staker_functions.deposit(everyone_else[0], MIN_ALLOWED_LOCKED, LOCKED_PERIODS), {'from': origin}) testerchain.time_travel(periods=1) # # Give Ursula and Alice some coins # transact_and_log( "Transfer tokens", token_functions.transfer(staker1, MIN_ALLOWED_LOCKED * 10), {'from': origin}) transact(token_functions.transfer(staker2, MIN_ALLOWED_LOCKED * 10), {'from': origin}) transact(token_functions.transfer(staker3, MIN_ALLOWED_LOCKED * 10), {'from': origin}) # # Ursula and Alice give Escrow rights to transfer # transact_and_log( "Approving transfer", token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 7), {'from': staker1}) transact( token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 6), {'from': staker2}) transact( token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 6), {'from': staker3}) # # Ursula and Alice transfer some tokens to the escrow and lock them # transact_and_log( "Initial deposit tokens, first", staker_functions.deposit(staker1, MIN_ALLOWED_LOCKED * 3, LOCKED_PERIODS), {'from': staker1}) transact_and_log( "Initial deposit tokens, other", staker_functions.deposit(staker2, MIN_ALLOWED_LOCKED * 3, LOCKED_PERIODS), {'from': staker2}) transact( staker_functions.deposit(staker3, MIN_ALLOWED_LOCKED * 3, LOCKED_PERIODS), {'from': staker3}) transact(staker_functions.bondWorker(staker1), {'from': staker1}) transact(staker_functions.bondWorker(staker2), {'from': staker2}) transact(staker_functions.bondWorker(staker3), {'from': staker3}) transact(staker_functions.setReStake(False), {'from': staker1}) transact(staker_functions.setReStake(False), {'from': staker2}) transact(staker_functions.setWindDown(True), {'from': staker1}) transact(staker_functions.setWindDown(True), {'from': staker2}) transact(staker_functions.commitToNextPeriod(), {'from': staker1}) transact(staker_functions.commitToNextPeriod(), {'from': staker2}) # # Wait 1 period and make a commitment # testerchain.time_travel(periods=1) transact_and_log("Make a commitment, first", staker_functions.commitToNextPeriod(), {'from': staker1}) transact_and_log("Make a commitment, other", staker_functions.commitToNextPeriod(), {'from': staker2}) # # Wait 1 period and mint tokens # testerchain.time_travel(periods=1) transact_and_log("Minting (1 stake), first", staker_functions.mint(), {'from': staker1}) transact_and_log("Minting (1 stake), other", staker_functions.mint(), {'from': staker2}) transact_and_log("Make a commitment again, first", staker_functions.commitToNextPeriod(), {'from': staker1}) transact_and_log("Make a commitment again, other", staker_functions.commitToNextPeriod(), {'from': staker2}) transact(staker_functions.commitToNextPeriod(), {'from': staker3}) # # Commit again # testerchain.time_travel(periods=1) transact_and_log("Make a commitment + mint, first", staker_functions.commitToNextPeriod(), {'from': staker1}) transact_and_log("Make a commitment + mint, other", staker_functions.commitToNextPeriod(), {'from': staker2}) # # Create policy # policy_id_1 = os.urandom(int(Policy.POLICY_ID_LENGTH)) policy_id_2 = os.urandom(int(Policy.POLICY_ID_LENGTH)) number_of_periods = 10 rate = 100 one_period = economics.hours_per_period * 60 * 60 value = number_of_periods * rate current_timestamp = testerchain.w3.eth.getBlock('latest').timestamp end_timestamp = current_timestamp + (number_of_periods - 1) * one_period transact_and_log( "Creating policy (1 node, 10 periods, pre-committed), first", policy_functions.createPolicy(policy_id_1, alice1, end_timestamp, [staker1]), { 'from': alice1, 'value': value }) transact_and_log( "Creating policy (1 node, 10 periods, pre-committed), other", policy_functions.createPolicy(policy_id_2, alice1, end_timestamp, [staker1]), { 'from': alice1, 'value': value }) # # Get locked tokens # transact_and_log("Getting locked tokens", staker_functions.getLockedTokens(staker1, 0), {}) # # Wait 1 period and withdraw tokens # testerchain.time_travel(periods=1) transact_and_log("Withdraw", staker_functions.withdraw(1), {'from': staker1}) # # Make a commitment with re-stake # transact(staker_functions.setReStake(True), {'from': staker1}) transact(staker_functions.setReStake(True), {'from': staker2}) # Used to remove spending for first call in a period for mint and commitToNextPeriod transact(staker_functions.commitToNextPeriod(), {'from': staker3}) transact_and_log("Make a commitment + mint + re-stake", staker_functions.commitToNextPeriod(), {'from': staker2}) transact_and_log( "Make a commitment + mint + re-stake + first fee + first fee rate", staker_functions.commitToNextPeriod(), {'from': staker1}) transact(staker_functions.setReStake(False), {'from': staker1}) transact(staker_functions.setReStake(False), {'from': staker2}) # # Wait 2 periods and make a commitment after downtime # testerchain.time_travel(periods=2) transact(staker_functions.commitToNextPeriod(), {'from': staker3}) transact_and_log("Make a commitment after downtime", staker_functions.commitToNextPeriod(), {'from': staker2}) transact_and_log("Make a commitment after downtime + updating fee", staker_functions.commitToNextPeriod(), {'from': staker1}) # # Ursula and Alice deposit some tokens to the escrow again # transact_and_log( "Deposit tokens after making a commitment", staker_functions.deposit(staker1, MIN_ALLOWED_LOCKED * 2, LOCKED_PERIODS), {'from': staker1}) transact( staker_functions.deposit(staker2, MIN_ALLOWED_LOCKED * 2, LOCKED_PERIODS), {'from': staker2}) # # Revoke policy # transact_and_log("Revoking policy", policy_functions.revokePolicy(policy_id_1), {'from': alice1}) # # Wait 1 period # testerchain.time_travel(periods=1) # # Create policy with multiple pre-committed nodes # policy_id_1 = os.urandom(int(Policy.POLICY_ID_LENGTH)) policy_id_2 = os.urandom(int(Policy.POLICY_ID_LENGTH)) policy_id_3 = os.urandom(int(Policy.POLICY_ID_LENGTH)) number_of_periods = 100 value = 3 * number_of_periods * rate current_timestamp = testerchain.w3.eth.getBlock('latest').timestamp end_timestamp = current_timestamp + (number_of_periods - 1) * one_period transact_and_log( "Creating policy (3 nodes, 100 periods, pre-committed), first", policy_functions.createPolicy(policy_id_1, alice1, end_timestamp, [staker1, staker2, staker3]), { 'from': alice1, 'value': value }) transact_and_log( "Creating policy (3 nodes, 100 periods, pre-committed), other", policy_functions.createPolicy(policy_id_2, alice1, end_timestamp, [staker1, staker2, staker3]), { 'from': alice1, 'value': value }) value = 2 * number_of_periods * rate transact_and_log( "Creating policy (2 nodes, 100 periods, pre-committed), other", policy_functions.createPolicy(policy_id_3, alice1, end_timestamp, [staker1, staker2]), { 'from': alice1, 'value': value }) # # Wait 1 period and mint tokens # testerchain.time_travel(periods=1) transact(staker_functions.mint(), {'from': staker3}) transact_and_log("Last minting + updating fee + updating fee rate", staker_functions.mint(), {'from': staker1}) transact_and_log("Last minting + first fee + first fee rate", staker_functions.mint(), {'from': staker2}) # # Create policy again without pre-committed nodes # policy_id_1 = os.urandom(int(Policy.POLICY_ID_LENGTH)) policy_id_2 = os.urandom(int(Policy.POLICY_ID_LENGTH)) policy_id_3 = os.urandom(int(Policy.POLICY_ID_LENGTH)) number_of_periods = 100 value = number_of_periods * rate current_timestamp = testerchain.w3.eth.getBlock('latest').timestamp end_timestamp = current_timestamp + (number_of_periods - 1) * one_period transact_and_log( "Creating policy (1 node, 100 periods)", policy_functions.createPolicy(policy_id_1, alice2, end_timestamp, [staker2]), { 'from': alice1, 'value': value }) testerchain.time_travel(periods=1) current_timestamp = testerchain.w3.eth.getBlock('latest').timestamp end_timestamp = current_timestamp + (number_of_periods - 1) * one_period transact_and_log( "Creating policy (1 node, 100 periods), next period", policy_functions.createPolicy(policy_id_2, alice2, end_timestamp, [staker2]), { 'from': alice1, 'value': value }) transact_and_log( "Creating policy (1 node, 100 periods), another node", policy_functions.createPolicy(policy_id_3, alice2, end_timestamp, [staker1]), { 'from': alice1, 'value': value }) # # Mint and revoke policy # testerchain.time_travel(periods=10) transact(staker_functions.commitToNextPeriod(), {'from': staker1}) transact(staker_functions.commitToNextPeriod(), {'from': staker3}) testerchain.time_travel(periods=2) transact(staker_functions.mint(), {'from': staker3}) transact_and_log("Last minting after downtime + updating fee", staker_functions.mint(), {'from': staker1}) testerchain.time_travel(periods=10) transact_and_log("Revoking policy after downtime, 1st policy", policy_functions.revokePolicy(policy_id_1), {'from': alice2}) transact_and_log("Revoking policy after downtime, 2nd policy", policy_functions.revokePolicy(policy_id_2), {'from': alice2}) transact_and_log("Revoking policy after downtime, 3rd policy", policy_functions.revokePolicy(policy_id_3), {'from': alice2}) transact(staker_functions.commitToNextPeriod(), {'from': staker1}) transact(staker_functions.commitToNextPeriod(), {'from': staker2}) transact(staker_functions.commitToNextPeriod(), {'from': staker3}) testerchain.time_travel(periods=1) # # Batch granting # policy_id_1 = os.urandom(int(Policy.POLICY_ID_LENGTH)) policy_id_2 = os.urandom(int(Policy.POLICY_ID_LENGTH)) current_timestamp = testerchain.w3.eth.getBlock('latest').timestamp end_timestamp = current_timestamp + (number_of_periods - 1) * one_period value = 3 * number_of_periods * rate transact_and_log( "Creating 2 policies (3 nodes, 100 periods, pre-committed)", policy_functions.createPolicies([policy_id_1, policy_id_2], alice1, end_timestamp, [staker1, staker2, staker3]), { 'from': alice1, 'value': 2 * value }) for index in range(4): transact(staker_functions.commitToNextPeriod(), {'from': staker1}) testerchain.time_travel(periods=1) transact(staker_functions.mint(), {'from': staker1}) # # Check regular deposit # transact_and_log( "Deposit tokens to new sub-stake", staker_functions.deposit(staker1, MIN_ALLOWED_LOCKED, LOCKED_PERIODS), {'from': staker1}) transact_and_log( "Deposit tokens using existing sub-stake", staker_functions.depositAndIncrease(0, MIN_ALLOWED_LOCKED), {'from': staker1}) # # ApproveAndCall # testerchain.time_travel(periods=1) transact(staker_functions.mint(), {'from': staker1}) transact_and_log( "ApproveAndCall", token_functions.approveAndCall(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 2, web3.toBytes(LOCKED_PERIODS)), {'from': staker1}) # # Locking tokens # testerchain.time_travel(periods=1) transact(staker_functions.commitToNextPeriod(), {'from': staker1}) transact_and_log( "Locking tokens and creating new sub-stake", staker_functions.lockAndCreate(MIN_ALLOWED_LOCKED, LOCKED_PERIODS), {'from': staker1}) transact_and_log("Locking tokens using existing sub-stake", staker_functions.lockAndIncrease(0, MIN_ALLOWED_LOCKED), {'from': staker1}) # # Divide stake # transact_and_log("Divide stake", staker_functions.divideStake(1, MIN_ALLOWED_LOCKED, 2), {'from': staker1}) transact(staker_functions.divideStake(3, MIN_ALLOWED_LOCKED, 2), {'from': staker1}) # # Divide almost finished stake # testerchain.time_travel(periods=1) transact(staker_functions.commitToNextPeriod(), {'from': staker1}) testerchain.time_travel(periods=1) transact(staker_functions.commitToNextPeriod(), {'from': staker1}) testerchain.time_travel(periods=1) for index in range(18): transact(staker_functions.commitToNextPeriod(), {'from': staker1}) testerchain.time_travel(periods=1) transact( staker_functions.lockAndCreate(MIN_ALLOWED_LOCKED, LOCKED_PERIODS), {'from': staker1}) deposit = staker_functions.stakerInfo(staker1).call()[0] unlocked = deposit - staker_functions.getLockedTokens(staker1, 1).call() transact(staker_functions.withdraw(unlocked), {'from': staker1}) transact_and_log("Prolong stake", staker_functions.prolongStake(0, 20), {'from': staker1}) transact_and_log("Merge sub-stakes", staker_functions.mergeStake(2, 3), {'from': staker1}) # Large number of sub-stakes number_of_sub_stakes = 24 transact(token_functions.approve(staking_agent.contract_address, 0), {'from': origin}) transact( token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * number_of_sub_stakes), {'from': origin}) for i in range(number_of_sub_stakes): transact( staker_functions.deposit(staker4, MIN_ALLOWED_LOCKED, LOCKED_PERIODS), {'from': origin}) transact(staker_functions.bondWorker(staker4), {'from': staker4}) transact(staker_functions.setWindDown(True), {'from': staker4}) # Used to remove spending for first call in a period for mint and commitToNextPeriod transact(staker_functions.commitToNextPeriod(), {'from': staker1}) transact_and_log(f"Make a commitment ({number_of_sub_stakes} sub-stakes)", staker_functions.commitToNextPeriod(), {'from': staker4}) testerchain.time_travel(periods=1) transact(staker_functions.commitToNextPeriod(), {'from': staker4}) testerchain.time_travel(periods=1) # Used to remove spending for first call in a period for mint and commitToNextPeriod transact(staker_functions.commitToNextPeriod(), {'from': staker1}) transact_and_log( f"Make a commitment + mint + re-stake ({number_of_sub_stakes} sub-stakes)", staker_functions.commitToNextPeriod(), {'from': staker4}) print("********* Estimates of migration *********") registry = InMemoryContractRegistry() deployer_power = TransactingPower(signer=Web3Signer(testerchain.client), account=testerchain.etherbase_account) def deploy_contract(contract_name, *args, **kwargs): return testerchain.deploy_contract(deployer_power, registry, contract_name, *args, **kwargs) token_economics = StandardTokenEconomics( genesis_hours_per_period=StandardTokenEconomics. _default_hours_per_period, hours_per_period=2 * StandardTokenEconomics._default_hours_per_period) token, _ = deploy_contract( 'NuCypherToken', _totalSupplyOfTokens=token_economics.erc20_total_supply) # Deploy Adjudicator mock adjudicator, _ = deploy_contract('AdjudicatorForStakingEscrowMock', token_economics.reward_coefficient) # Deploy old StakingEscrow contract deploy_args = token_economics.staking_deployment_parameters deploy_args = (deploy_args[0], *deploy_args[2:]) escrow_old_library, _ = deploy_contract( 'StakingEscrowOld', token.address, *deploy_args, False # testContract ) escrow_dispatcher, _ = deploy_contract('Dispatcher', escrow_old_library.address) escrow = testerchain.client.get_contract(abi=escrow_old_library.abi, address=escrow_dispatcher.address, ContractFactoryClass=Contract) # Deploy old PolicyManager contract policy_manager_old_library, _ = deploy_contract( contract_name='PolicyManagerOld', _escrow=escrow.address) policy_manager_dispatcher, _ = deploy_contract( 'Dispatcher', policy_manager_old_library.address) policy_manager = testerchain.client.get_contract( abi=policy_manager_old_library.abi, address=policy_manager_dispatcher.address, ContractFactoryClass=Contract) tx = adjudicator.functions.setStakingEscrow(escrow.address).transact() testerchain.wait_for_receipt(tx) tx = escrow.functions.setPolicyManager(policy_manager.address).transact() testerchain.wait_for_receipt(tx) tx = escrow.functions.setAdjudicator(adjudicator.address).transact() testerchain.wait_for_receipt(tx) # Initialize Escrow contract tx = token.functions.approve( escrow.address, token_economics.erc20_reward_supply).transact() testerchain.wait_for_receipt(tx) tx = escrow.functions.initialize(token_economics.erc20_reward_supply, testerchain.etherbase_account).transact() testerchain.wait_for_receipt(tx) # Prepare stakers stakers = (staker1, staker2, staker3, staker4) for staker in stakers: max_stake_size = token_economics.maximum_allowed_locked tx = token.functions.transfer(staker, max_stake_size).transact() testerchain.wait_for_receipt(tx) tx = token.functions.approve(escrow.address, max_stake_size).transact({'from': staker}) testerchain.wait_for_receipt(tx) sub_stakes_1 = 2 duration = token_economics.minimum_locked_periods stake_size = token_economics.minimum_allowed_locked for staker in (staker1, staker3): for i in range(1, sub_stakes_1 + 1): tx = escrow.functions.deposit(staker, stake_size, duration * i).transact({'from': staker}) testerchain.wait_for_receipt(tx) sub_stakes_2 = 24 for staker in (staker2, staker4): for i in range(1, sub_stakes_2 + 1): tx = escrow.functions.deposit(staker, stake_size, duration * i).transact({'from': staker}) testerchain.wait_for_receipt(tx) for staker in stakers: tx = escrow.functions.bondWorker(staker).transact({'from': staker}) testerchain.wait_for_receipt(tx) for i in range(duration): tx = escrow.functions.commitToNextPeriod().transact({'from': staker1}) testerchain.wait_for_receipt(tx) tx = escrow.functions.commitToNextPeriod().transact({'from': staker3}) testerchain.wait_for_receipt(tx) if i % 2 == 0: tx = escrow.functions.commitToNextPeriod().transact( {'from': staker2}) testerchain.wait_for_receipt(tx) tx = escrow.functions.commitToNextPeriod().transact( {'from': staker4}) testerchain.wait_for_receipt(tx) testerchain.time_travel( periods=1, periods_base=token_economics.genesis_seconds_per_period) ########## # Deploy new version of contracts ########## deploy_args = token_economics.staking_deployment_parameters escrow_library, _ = deploy_contract('StakingEscrow', token.address, policy_manager.address, adjudicator.address, NULL_ADDRESS, *deploy_args) escrow = testerchain.client.get_contract(abi=escrow_library.abi, address=escrow_dispatcher.address, ContractFactoryClass=Contract) policy_manager_library, _ = deploy_contract( contract_name='PolicyManager', _escrowDispatcher=escrow.address, _escrowImplementation=escrow_library.address) tx = escrow_dispatcher.functions.upgrade(escrow_library.address).transact() testerchain.wait_for_receipt(tx) tx = policy_manager_dispatcher.functions.upgrade( policy_manager_library.address).transact() testerchain.wait_for_receipt(tx) for staker in (staker1, staker2): downtime_length = escrow.functions.getPastDowntimeLength(staker).call() sub_stakes_length = escrow.functions.getSubStakesLength(staker).call() transact_and_log( f"Migrate with {sub_stakes_length} sub-stakes and {downtime_length} downtimes", escrow.functions.migrate(staker), {'from': staker}) downtime_length = escrow.functions.getPastDowntimeLength(staker).call() sub_stakes_length = escrow.functions.getSubStakesLength(staker).call() transact_and_log( f"Commit after migration with {sub_stakes_length} sub-stakes and {downtime_length} downtimes", escrow.functions.commitToNextPeriod(), {'from': staker}) for staker in (staker3, staker4): downtime_length = escrow.functions.getPastDowntimeLength(staker).call() sub_stakes_length = escrow.functions.getSubStakesLength(staker).call() transact_and_log( f"Commit together with migration with {sub_stakes_length} sub-stakes and {downtime_length} downtimes", escrow.functions.commitToNextPeriod(), {'from': staker}) transact_and_log(f"Dummy migrate call", escrow.functions.migrate(staker1), {'from': staker1}) print("********* All Done! *********")
def __init__(self, domains: Set = None, is_me: bool = True, federated_only: bool = False, checksum_address: str = NO_BLOCKCHAIN_CONNECTION.bool_value(False), network_middleware: RestMiddleware = None, keyring: NucypherKeyring = None, keyring_root: str = None, crypto_power: CryptoPower = None, crypto_power_ups: List[CryptoPowerUp] = None, provider_uri: str = None, registry: BaseContractRegistry = 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. """ # # Operating Mode # if federated_only: if registry or provider_uri: raise ValueError(f"Cannot init federated-only character with {registry or provider_uri}.") self.federated_only = federated_only # type: bool # # Powers # # Derive powers from keyring if keyring_root and keyring: if keyring_root != keyring.keyring_root: raise ValueError("Inconsistent keyring root directory path") if keyring: keyring_root, checksum_address = keyring.keyring_root, keyring.checksum_address crypto_power_ups = list() for power_up in self._default_crypto_powerups: power = keyring.derive_crypto_power(power_class=power_up) crypto_power_ups.append(power) self.keyring_root = keyring_root self.keyring = keyring 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_address # Fleet and Blockchain Connection (Everyone) if not domains: domains = (CharacterConfiguration.DEFAULT_DOMAIN,) # # Self-Character # if is_me: if not bool(federated_only) ^ bool(registry): raise ValueError(f"Pass either federated only or registry for is_me Characters. \ Got '{federated_only}' and '{registry}'.") 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 # # Blockchain # self.provider_uri = provider_uri if not self.federated_only: self.registry = registry or InMemoryContractRegistry.from_latest_publication() else: self.registry = NO_BLOCKCHAIN_CONNECTION.bool_value(False) # # Learner # Learner.__init__(self, domains=domains, network_middleware=self.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 Stranger-Character.") if registry is not None: raise TypeError("Registry cannot be attached to stranger-Characters.") self._stamp = StrangerStamp(self.public_keys(SigningPower)) self.network_middleware = STRANGER # # Decentralized # if not federated_only: self._checksum_address = checksum_address # TODO: Check that this matches TransactingPower # # Federated # elif federated_only: try: self._set_checksum_address() # type: str except NoSigningPower: self._checksum_address = NO_BLOCKCHAIN_CONNECTION if checksum_address: # We'll take a checksum address, as long as it matches their singing key if not checksum_address == self.checksum_address: error = "Federated-only Characters derive their address from their Signing key; got {} instead." raise self.SuspiciousActivity(error.format(checksum_address)) # # Nicknames # try: self.nickname, self.nickname_metadata = nickname_from_seed(self.checksum_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
network = sys.argv[1] except IndexError: network = "ibex" BlockchainInterfaceFactory.initialize_interface(provider_uri=provider_uri, light=False, sync=False, emitter=emitter) blockchain = BlockchainInterfaceFactory.get_interface( provider_uri=provider_uri) emitter.echo(message="Reading Latest Chaindata...") blockchain.connect() registry = InMemoryContractRegistry.from_latest_publication(network=network) emitter.echo(f"NOTICE: Connecting to {network} network", color='yellow') staking_agent = ContractAgency.get_agent( agent_class=StakingEscrowAgent, registry=registry) # type: StakingEscrowAgent policy_agent = ContractAgency.get_agent( agent_class=PolicyManagerAgent, registry=registry) # type: PolicyManagerAgent token_agent = ContractAgency.get_agent( agent_class=NucypherTokenAgent, registry=registry) # type: NucypherTokenAgent emitter.echo(message=f"Current period: {staking_agent.get_current_period()}", color='yellow')
def select_client_account(emitter, provider_uri: str = None, signer: Signer = None, signer_uri: str = None, wallet: Wallet = None, prompt: str = None, default: int = 0, registry=None, show_eth_balance: bool = False, show_nu_balance: bool = False, show_staking: bool = False, network: str = None, poa: bool = None) -> str: """ Interactively select an ethereum wallet account from a table of nucypher account metadata. Note: Showing ETH and/or NU balances, causes an eager blockchain connection. """ if wallet and (provider_uri or signer_uri or signer): raise ValueError( "If a wallet is provided, don't provide a signer, provider URI, or signer URI." ) # We use Wallet internally as an account management abstraction if not wallet: if signer and signer_uri: raise ValueError('Pass either signer or signer_uri but not both.') if not provider_uri and not signer_uri: raise ValueError( "At least a provider URI or signer URI is necessary to select an account" ) if provider_uri: # Lazy connect the blockchain interface if not BlockchainInterfaceFactory.is_interface_initialized( provider_uri=provider_uri): BlockchainInterfaceFactory.initialize_interface( provider_uri=provider_uri, poa=poa, emitter=emitter) if signer_uri: testnet = network != NetworksInventory.MAINNET signer = Signer.from_signer_uri(signer_uri, testnet=testnet) wallet = Wallet(provider_uri=provider_uri, signer=signer) # Display accounts info if show_nu_balance or show_staking: # Lazy registry fetching if not registry: if not network: raise ValueError("Pass network name or registry; Got neither.") registry = InMemoryContractRegistry.from_latest_publication( network=network) wallet_accounts = wallet.accounts enumerated_accounts = dict(enumerate(wallet_accounts)) if len(enumerated_accounts) < 1: emitter.echo(NO_ETH_ACCOUNTS, color='red', bold=True) raise click.Abort() # Display account info headers = ['Account'] if show_staking: headers.append('Staking') if show_eth_balance: headers.append('ETH') if show_nu_balance: headers.append('NU') rows = list() for index, account in enumerated_accounts.items(): row = [account] if show_staking: staker = Staker(is_me=True, checksum_address=account, registry=registry) staker.refresh_stakes() is_staking = 'Yes' if bool(staker.stakes) else 'No' row.append(is_staking) if show_eth_balance: ether_balance = Web3.fromWei(wallet.eth_balance(account), 'ether') row.append(f'{ether_balance} ETH') if show_nu_balance: token_balance = NU.from_nunits( wallet.token_balance(account, registry)) row.append(token_balance) rows.append(row) emitter.echo(tabulate(rows, headers=headers, showindex='always')) # Prompt the user for selection, and return prompt = prompt or GENERIC_SELECT_ACCOUNT account_range = click.IntRange(min=0, max=len(enumerated_accounts) - 1) choice = click.prompt(prompt, type=account_range, default=default) chosen_account = enumerated_accounts[choice] emitter.echo(SELECTED_ACCOUNT.format(choice=choice, chosen_account=chosen_account), color='blue') return chosen_account
def test_multiversion_contract(): # Prepare compiler base_dir = TEST_MULTIVERSION_CONTRACTS v1_dir, v2_dir = base_dir / 'v1', base_dir / 'v2' bundles = [ SourceBundle(base_path=SOLIDITY_SOURCE_ROOT, other_paths=(v1_dir, )), SourceBundle(base_path=SOLIDITY_SOURCE_ROOT, other_paths=(v2_dir, )) ] compiled_contracts = multiversion_compile(source_bundles=bundles) # Prepare chain BlockchainDeployerInterface.GAS_STRATEGIES = { **BlockchainDeployerInterface.GAS_STRATEGIES, 'free': free_gas_price_strategy } blockchain_interface = BlockchainDeployerInterface( provider_uri='tester://pyevm/2', gas_strategy='free') blockchain_interface.connect(compile_now=False) blockchain_interface._raw_contract_cache = compiled_contracts origin = blockchain_interface.client.accounts[0] blockchain_interface.transacting_power = TransactingPower( password=INSECURE_DEVELOPMENT_PASSWORD, signer=Web3Signer(blockchain_interface.client), account=origin) blockchain_interface.transacting_power.activate() # Searching both contract through raw data contract_name = "VersionTest" requested_version = "v1.2.3" version, _data = blockchain_interface.find_raw_contract_data( contract_name=contract_name, requested_version=requested_version) assert version == requested_version version, _data = blockchain_interface.find_raw_contract_data( contract_name=contract_name, requested_version="latest") assert version == requested_version requested_version = "v1.1.4" version, _data = blockchain_interface.find_raw_contract_data( contract_name=contract_name, requested_version=requested_version) assert version == requested_version version, _data = blockchain_interface.find_raw_contract_data( contract_name=contract_name, requested_version="earliest") assert version == requested_version # Deploy different contracts and check their versions registry = InMemoryContractRegistry() contract, receipt = blockchain_interface.deploy_contract( deployer_address=origin, registry=registry, contract_name=contract_name, contract_version="v1.1.4") assert contract.version == "v1.1.4" assert contract.functions.VERSION().call() == 1 contract, receipt = blockchain_interface.deploy_contract( deployer_address=origin, registry=registry, contract_name=contract_name, contract_version="earliest") assert contract.version == "v1.1.4" assert contract.functions.VERSION().call() == 1 contract, receipt = blockchain_interface.deploy_contract( deployer_address=origin, registry=registry, contract_name=contract_name, contract_version="v1.2.3") assert contract.version == "v1.2.3" assert contract.functions.VERSION().call() == 2 contract, receipt = blockchain_interface.deploy_contract( deployer_address=origin, registry=registry, contract_name=contract_name, contract_version="latest") assert contract.version == "v1.2.3" assert contract.functions.VERSION().call() == 2 contract, receipt = blockchain_interface.deploy_contract( deployer_address=origin, registry=registry, contract_name=contract_name) assert contract.version == "v1.2.3" assert contract.functions.VERSION().call() == 2
def select_client_account(emitter, eth_provider_uri: str = None, signer: Signer = None, signer_uri: str = None, prompt: str = None, default: int = 0, registry: BaseContractRegistry = None, show_eth_balance: bool = False, show_nu_balance: bool = False, show_staking: bool = False, network: str = None, poa: bool = None) -> str: """ Interactively select an ethereum wallet account from a table of nucypher account metadata. Note: Showing ETH and/or NU balances, causes an eager blockchain connection. """ if signer and signer_uri: raise ValueError('Pass either signer or signer_uri but not both.') if not any((eth_provider_uri, signer_uri, signer)): raise ValueError( "At least a provider URI, signer URI or signer must be provided to select an account" ) if eth_provider_uri: # Connect to the blockchain in order to select an account if not BlockchainInterfaceFactory.is_interface_initialized( eth_provider_uri=eth_provider_uri): BlockchainInterfaceFactory.initialize_interface( eth_provider_uri=eth_provider_uri, poa=poa, emitter=emitter) if not signer_uri: signer_uri = eth_provider_uri blockchain = BlockchainInterfaceFactory.get_interface( eth_provider_uri=eth_provider_uri) if signer_uri and not signer: testnet = network != NetworksInventory.MAINNET signer = Signer.from_signer_uri(signer_uri, testnet=testnet) # Display accounts info if show_nu_balance or show_staking: # Lazy registry fetching if not registry: if not network: raise ValueError("Pass network name or registry; Got neither.") registry = InMemoryContractRegistry.from_latest_publication( network=network) enumerated_accounts = dict(enumerate(signer.accounts)) if len(enumerated_accounts) < 1: emitter.echo(NO_ETH_ACCOUNTS, color='red', bold=True) raise click.Abort() elif len(enumerated_accounts) == 1: # There are no choices if there is only one available address. return enumerated_accounts[0] # Display account info headers = ['Account'] if show_staking: headers.append('Staking') if show_eth_balance: headers.append('ETH') if show_nu_balance: headers.append('NU') rows = list() for index, account in enumerated_accounts.items(): row = [account] if show_staking: staker = Staker(domain=network, checksum_address=account, registry=registry) staker.refresh_stakes() is_staking = 'Yes' if bool(staker.stakes) else 'No' row.append(is_staking) if show_eth_balance: ether_balance = Web3.fromWei( blockchain.client.get_balance(account), 'ether') row.append(f'{ether_balance} ETH') if show_nu_balance: token_agent = ContractAgency.get_agent(NucypherTokenAgent, registry=registry) token_balance = NU.from_units( token_agent.get_balance(account, registry)) row.append(token_balance) rows.append(row) emitter.echo(tabulate(rows, headers=headers, showindex='always')) # Prompt the user for selection, and return prompt = prompt or GENERIC_SELECT_ACCOUNT account_range = click.IntRange(min=0, max=len(enumerated_accounts) - 1) choice = click.prompt(prompt, type=account_range, default=default) chosen_account = enumerated_accounts[choice] emitter.echo(SELECTED_ACCOUNT.format(choice=choice, chosen_account=chosen_account), color='blue') return chosen_account
def select_client_account(emitter, provider_uri: str, prompt: str = None, default: int = 0, registry=None, show_balances: bool = True, show_staking: bool = False, network: str = None, poa: bool = False ) -> str: """ Note: Setting show_balances to True, causes an eager contract and blockchain connection. """ # TODO: Break show_balances into show_eth_balance and show_token_balance if not provider_uri: raise ValueError("Provider URI must be provided to select a wallet account.") # Lazy connect the blockchain interface if not BlockchainInterfaceFactory.is_interface_initialized(provider_uri=provider_uri): BlockchainInterfaceFactory.initialize_interface(provider_uri=provider_uri, poa=poa, emitter=emitter) blockchain = BlockchainInterfaceFactory.get_interface(provider_uri=provider_uri) # Lazy connect to contracts token_agent = None if show_balances or show_staking: if not registry: registry = InMemoryContractRegistry.from_latest_publication(network=network) token_agent = NucypherTokenAgent(registry=registry) # Real wallet accounts enumerated_accounts = dict(enumerate(blockchain.client.accounts)) if len(enumerated_accounts) < 1: emitter.echo("No ETH accounts were found.", color='red', bold=True) raise click.Abort() # Display account info headers = ['Account'] if show_staking: headers.append('Staking') if show_balances: headers.extend(('', '')) rows = list() for index, account in enumerated_accounts.items(): row = [account] if show_staking: staker = Staker(is_me=True, checksum_address=account, registry=registry) staker.stakes.refresh() is_staking = 'Yes' if bool(staker.stakes) else 'No' row.append(is_staking) if show_balances: token_balance = NU.from_nunits(token_agent.get_balance(address=account)) ether_balance = Web3.fromWei(blockchain.client.get_balance(account=account), 'ether') row.extend((token_balance, f'{ether_balance} ETH')) rows.append(row) emitter.echo(tabulate(rows, headers=headers, showindex='always')) # Prompt the user for selection, and return prompt = prompt or "Select index of account" account_range = click.IntRange(min=0, max=len(enumerated_accounts)-1) choice = click.prompt(prompt, type=account_range, default=default) chosen_account = enumerated_accounts[choice] emitter.echo(f"Selected {choice}: {chosen_account}", color='blue') return chosen_account
def __init__(self, domain: str = None, known_node_class: object = None, is_me: bool = True, federated_only: bool = False, checksum_address: str = NO_BLOCKCHAIN_CONNECTION.bool_value(False), network_middleware: RestMiddleware = None, keyring: NucypherKeyring = None, keyring_root: str = None, crypto_power: CryptoPower = None, crypto_power_ups: List[CryptoPowerUp] = None, provider_uri: str = None, signer: Signer = None, registry: BaseContractRegistry = None, *args, **kwargs ) -> None: """ A participant in the cryptological drama (a screenplay, if you like) of NuCypher. Characters can represent users, nodes, wallets, offline devices, or other objects of varying levels of abstraction. The Named Characters use this class as a Base, and achieve their individuality from additional methods and PowerUps. 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. """ if provider_uri: if not BlockchainInterfaceFactory.is_interface_initialized(provider_uri=provider_uri): BlockchainInterfaceFactory.initialize_interface(provider_uri=provider_uri) # # Operating Mode # if hasattr(self, '_interface_class'): # TODO: have argument about meaning of 'lawful' # and whether maybe only Lawful characters have an interface self.interface = self._interface_class(character=self) if is_me: self._set_known_node_class(known_node_class, federated_only) else: # What an awful hack. The last convulsions of #466. # TODO: Anything else. with suppress(AttributeError): federated_only = known_node_class._federated_only_instances if federated_only: if registry or provider_uri: raise ValueError(f"Cannot init federated-only character with {registry or provider_uri}.") self.federated_only: bool = federated_only # # Powers # # Derive powers from keyring if keyring_root and keyring: if keyring_root != keyring.keyring_root: raise ValueError("Inconsistent keyring root directory path") if keyring: keyring_root, checksum_address = keyring.keyring_root, keyring.checksum_address crypto_power_ups = list() for power_up in self._default_crypto_powerups: power = keyring.derive_crypto_power(power_class=power_up) crypto_power_ups.append(power) self.keyring_root = keyring_root self.keyring = keyring 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-Character # if is_me: # # Signing Power # self.signer = signer 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 # # Blockchain # self.provider_uri = provider_uri if not self.federated_only: self.registry = registry or InMemoryContractRegistry.from_latest_publication(network=domain) # See #1580 else: self.registry = NO_BLOCKCHAIN_CONNECTION.bool_value(False) # REST self.network_middleware = network_middleware or RestMiddleware(registry=self.registry) # # Learner # Learner.__init__(self, domain=domain, network_middleware=self.network_middleware, node_class=known_node_class, *args, **kwargs) # # Stranger-Character # else: # Feel like a stranger if network_middleware is not None: raise TypeError("Network middleware cannot be attached to a Stranger-Character.") if registry is not None: raise TypeError("Registry cannot be attached to stranger-Characters.") verifying_key = self.public_keys(SigningPower) self._stamp = StrangerStamp(verifying_key) self.keyring_root = STRANGER self.network_middleware = STRANGER # TODO: Figure out when to do this. try: _transacting_power = self._crypto_power.power_ups(TransactingPower) except NoTransactingPower: self._checksum_address = checksum_address else: self._set_checksum_address(checksum_address) # # Nicknames # if self._checksum_address is NO_BLOCKCHAIN_CONNECTION and not self.federated_only and not is_me: # Sometimes we don't care about the nickname. For example, if Alice is granting to Bob, she usually # doesn't know or care about his wallet. Maybe this needs to change? # Currently, if this is a stranger and there's no blockchain connection, we assign NO_NICKNAME: self.nickname = NO_NICKNAME else: try: # TODO: It's possible that this is NO_BLOCKCHAIN_CONNECTION. if self.checksum_address is NO_BLOCKCHAIN_CONNECTION: self.nickname = NO_NICKNAME else: # This can call _set_checksum_address. self.nickname = Nickname.from_seed(self.checksum_address) except SigningPower.not_found_error: # TODO: Handle NO_BLOCKCHAIN_CONNECTION more coherently - #1547 if self.federated_only: self.nickname = 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 select_client_account(emitter, provider_uri: str = None, signer_uri: str = None, wallet: Wallet = None, prompt: str = None, default: int = 0, registry=None, show_eth_balance: bool = False, show_nu_balance: bool = False, show_staking: bool = False, network: str = None, poa: bool = None) -> str: """ Note: Showing ETH and/or NU balances, causes an eager blockchain connection. """ # We use Wallet internally as an account management abstraction if not wallet: if not provider_uri and not signer_uri: raise ValueError( "At least a provider URI or signer URI is necessary to select an account" ) # Lazy connect the blockchain interface if not BlockchainInterfaceFactory.is_interface_initialized( provider_uri=provider_uri): BlockchainInterfaceFactory.initialize_interface( provider_uri=provider_uri, poa=poa, emitter=emitter) signer = Signer.from_signer_uri(signer_uri) if signer_uri else None wallet = Wallet(provider_uri=provider_uri, signer=signer) elif provider_uri or signer_uri: raise ValueError( "If you input a wallet, don't pass a provider URI or signer URI too" ) # Display accounts info if show_nu_balance or show_staking: # Lazy registry fetching if not registry: registry = InMemoryContractRegistry.from_latest_publication( network=network) wallet_accounts = wallet.accounts enumerated_accounts = dict(enumerate(wallet_accounts)) if len(enumerated_accounts) < 1: emitter.echo("No ETH accounts were found.", color='red', bold=True) raise click.Abort() # Display account info headers = ['Account'] if show_staking: headers.append('Staking') if show_eth_balance: headers.append('ETH') if show_nu_balance: headers.append('NU') rows = list() for index, account in enumerated_accounts.items(): row = [account] if show_staking: staker = Staker(is_me=True, checksum_address=account, registry=registry) staker.stakes.refresh() is_staking = 'Yes' if bool(staker.stakes) else 'No' row.append(is_staking) if show_eth_balance: ether_balance = Web3.fromWei(wallet.eth_balance(account), 'ether') row.append(f'{ether_balance} ETH') if show_nu_balance: token_balance = NU.from_nunits( wallet.token_balance(account, registry)) row.append(token_balance) rows.append(row) emitter.echo(tabulate(rows, headers=headers, showindex='always')) # Prompt the user for selection, and return prompt = prompt or "Select index of account" account_range = click.IntRange(min=0, max=len(enumerated_accounts) - 1) choice = click.prompt(prompt, type=account_range, default=default) chosen_account = enumerated_accounts[choice] emitter.echo(f"Selected {choice}: {chosen_account}", color='blue') return chosen_account
def status(click_config, action, provider_uri, sync, geth, poa, periods, staking_address, registry_filepath): """ Echo a snapshot of live NuCypher Network metadata. \b Actions ------------------------------------------------- network Overall information of the NuCypher Network stakers Show relevant information about stakers locked-tokens Display a graph of evolution of locked tokens """ emitter = click_config.emitter click.clear() emitter.banner(NU_BANNER) # # Connect to Blockchain # try: ETH_NODE = None if geth: ETH_NODE = get_provider_process() # Note: For test compatibility. if not BlockchainInterfaceFactory.is_interface_initialized(provider_uri=provider_uri): BlockchainInterfaceFactory.initialize_interface(provider_uri=provider_uri, provider_process=ETH_NODE, poa=poa, sync=False, show_sync_progress=False) blockchain = BlockchainInterfaceFactory.get_interface(provider_uri=provider_uri) emitter.echo(message="Reading Latest Chaindata...") blockchain.connect() except Exception as e: if click_config.debug: raise click.secho(str(e), bold=True, fg='red') raise click.Abort if registry_filepath: registry = LocalContractRegistry(filepath=registry_filepath) else: registry = InMemoryContractRegistry.from_latest_publication() staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=registry) if action == 'network': paint_contract_status(registry, emitter=emitter) return # Exit elif action == 'stakers': stakers = [staking_address] if staking_address else staking_agent.get_stakers() paint_stakers(emitter=emitter, stakers=stakers, agent=staking_agent) return # Exit elif action == 'locked-tokens': paint_locked_tokens_status(emitter=emitter, agent=staking_agent, periods=periods) return # Exit else: ctx = click.get_current_context() raise click.UsageError(message=f"Unknown action '{action}'.", ctx=ctx)
def __init__(self, domain: str = None, known_node_class: object = None, is_me: bool = True, federated_only: bool = False, checksum_address: str = None, network_middleware: RestMiddleware = None, keyring: NucypherKeyring = None, crypto_power: CryptoPower = None, crypto_power_ups: List[CryptoPowerUp] = None, provider_uri: str = None, signer: Signer = None, registry: BaseContractRegistry = None, include_self_in_the_state: bool = False, *args, **kwargs) -> None: """ A participant in the cryptological drama (a screenplay, if you like) of NuCypher. Characters can represent users, nodes, wallets, offline devices, or other objects of varying levels of abstraction. The Named Characters use this class as a Base, and achieve their individuality from additional methods and PowerUps. 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. """ # # Prologue of the federation # # FIXME: excuse me... can I speak to the manager? if is_me: # If this is a federated-is_me-character, assume everyone else is too. self._set_known_node_class(known_node_class, federated_only) else: # What an awful hack. The last convulsions of #466. # TODO: Anything else. with suppress(AttributeError): federated_only = known_node_class._federated_only_instances if federated_only: if registry or provider_uri: raise ValueError( f"Cannot init federated-only character with {registry or provider_uri}." ) self.federated_only: bool = federated_only ########################################## # # Keys & Powers # if keyring: keyring_root, keyring_checksum_address = keyring.keyring_root, keyring.checksum_address if checksum_address and (keyring_checksum_address != checksum_address): raise ValueError( f"Provided checksum address {checksum_address} " f"does not match character's keyring checksum address {keyring_checksum_address}" ) checksum_address = keyring_checksum_address crypto_power_ups = list() for power_up in self._default_crypto_powerups: power = keyring.derive_crypto_power(power_class=power_up) crypto_power_ups.append(power) self.keyring = keyring 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 # if is_me: # Signing Power self.signer = signer 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 # Blockchainy if not self.federated_only: self.provider_uri = provider_uri # TODO: Implicit / lazy blockchain connection here? # if not BlockchainInterfaceFactory.is_interface_initialized(provider_uri=provider_uri): # BlockchainInterfaceFactory.initialize_interface(provider_uri=provider_uri) self.registry = registry or InMemoryContractRegistry.from_latest_publication( network=domain) # See #1580 else: self.registry = NO_BLOCKCHAIN_CONNECTION.bool_value(False) # REST self.network_middleware = network_middleware or RestMiddleware( registry=self.registry) # Learner Learner.__init__( self, domain=domain, network_middleware=self.network_middleware, node_class=known_node_class, include_self_in_the_state=include_self_in_the_state, *args, **kwargs) if self.federated_only: try: derived_federated_address = self.derive_federated_address() except NoSigningPower: derived_federated_address = NO_SIGNING_POWER.bool_value( False) if checksum_address and (checksum_address != derived_federated_address): raise ValueError( f"Provided checksum address {checksum_address} " f"does not match federated character's verifying key {derived_federated_address}" ) checksum_address = derived_federated_address self.checksum_address = checksum_address # # Stranger # else: if network_middleware is not None: raise TypeError( "Network middleware cannot be attached to a Stranger-Character." ) if registry is not None: raise TypeError( "Registry cannot be attached to stranger-Characters.") verifying_key = self.public_keys(SigningPower) self._stamp = StrangerStamp(verifying_key) self.keyring_root = STRANGER self.network_middleware = STRANGER self.checksum_address = checksum_address self.__setup_nickname(is_me=is_me) # Character Control # TODO: have argument about meaning of 'lawful' and whether maybe only Lawful characters have an interface if hasattr(self, '_interface_class'): # Controller Interface self.interface = self._interface_class(character=self) self.controller = NO_CONTROL_PROTOCOL
def __init__(self, # Base config_root: str = None, filepath: str = None, # Mode dev_mode: bool = False, federated_only: bool = False, # Identity checksum_address: str = None, crypto_power: CryptoPower = None, # Keyring keyring: NucypherKeyring = None, keyring_root: str = None, # Learner learn_on_same_thread: bool = False, abort_on_learning_error: bool = False, start_learning_now: bool = True, # Network controller_port: int = None, domains: Set[str] = None, # TODO: Mapping between learning domains and "registry" domains - #1580 interface_signature: Signature = None, network_middleware: RestMiddleware = None, # Node Storage known_nodes: set = None, node_storage: NodeStorage = None, reload_metadata: bool = True, save_metadata: bool = True, # Blockchain poa: bool = False, light: bool = False, sync: bool = False, provider_uri: str = None, provider_process=None, gas_strategy: Union[Callable, str] = DEFAULT_GAS_STRATEGY, # Registry registry: BaseContractRegistry = None, registry_filepath: str = None, emitter=None, ): self.log = Logger(self.__class__.__name__) UNINITIALIZED_CONFIGURATION.bool_value(False) # Identity # NOTE: NodeConfigurations can only be used with Self-Characters self.is_me = True self.checksum_address = checksum_address # Network self.controller_port = controller_port or self.DEFAULT_CONTROLLER_PORT self.network_middleware = network_middleware or self.DEFAULT_NETWORK_MIDDLEWARE() self.interface_signature = interface_signature # Keyring self.crypto_power = crypto_power self.keyring = keyring or NO_KEYRING_ATTACHED self.keyring_root = keyring_root or UNINITIALIZED_CONFIGURATION # Contract Registry if registry and registry_filepath: if registry.filepath != registry_filepath: error = f"Inconsistent registry filepaths for '{registry.filepath}' and '{registry_filepath}'." raise ValueError(error) else: self.log.warn(f"Registry and registry filepath were both passed.") self.registry = registry or NO_BLOCKCHAIN_CONNECTION.bool_value(False) self.registry_filepath = registry_filepath or UNINITIALIZED_CONFIGURATION # Blockchain self.poa = poa self.is_light = light self.provider_uri = provider_uri or NO_BLOCKCHAIN_CONNECTION self.provider_process = provider_process or NO_BLOCKCHAIN_CONNECTION # Learner self.federated_only = federated_only self.domains = domains or {self.DEFAULT_DOMAIN} self.learn_on_same_thread = learn_on_same_thread self.abort_on_learning_error = abort_on_learning_error self.start_learning_now = start_learning_now self.save_metadata = save_metadata self.reload_metadata = reload_metadata self.known_nodes = known_nodes or set() # handpicked # Configuration self.__dev_mode = dev_mode self.config_file_location = filepath or UNINITIALIZED_CONFIGURATION self.config_root = UNINITIALIZED_CONFIGURATION # # Federated vs. Blockchain arguments consistency # # # Federated # if self.federated_only: # Check for incompatible values blockchain_args = {'filepath': registry_filepath, 'poa': poa, 'provider_process': provider_process, 'provider_uri': provider_uri, 'gas_strategy': gas_strategy} if any(blockchain_args.values()): bad_args = (f"{arg}={val}" for arg, val in blockchain_args.items() if val) self.log.warn(f"Arguments {bad_args} are incompatible with federated_only. " f"Overridden with a sane default.") # Clear decentralized attributes to ensure consistency with a # federated configuration. self.poa = False self.is_light = False self.provider_uri = None self.provider_process = None self.registry_filepath = None self.gas_strategy = None # # Decentralized # else: self.gas_strategy = gas_strategy is_initialized = BlockchainInterfaceFactory.is_interface_initialized(provider_uri=self.provider_uri) if not is_initialized and provider_uri: BlockchainInterfaceFactory.initialize_interface(provider_uri=self.provider_uri, poa=self.poa, light=self.is_light, provider_process=self.provider_process, sync=sync, emitter=emitter, gas_strategy=gas_strategy) else: self.log.warn(f"Using existing blockchain interface connection ({self.provider_uri}).") if not self.registry: # TODO: These two code blocks are untested. if not self.registry_filepath: # TODO: Registry URI (goerli://speedynet.json) :-) self.log.info(f"Fetching latest registry from source.") self.registry = InMemoryContractRegistry.from_latest_publication(network=list(self.domains)[0]) # TODO: #1580 else: self.registry = LocalContractRegistry(filepath=self.registry_filepath) self.log.info(f"Using local registry ({self.registry}).") if dev_mode: self.__temp_dir = UNINITIALIZED_CONFIGURATION self.__setup_node_storage() self.initialize(password=DEVELOPMENT_CONFIGURATION) else: self.__temp_dir = LIVE_CONFIGURATION self.config_root = config_root or self.DEFAULT_CONFIG_ROOT self._cache_runtime_filepaths() self.__setup_node_storage(node_storage=node_storage) super().__init__(filepath=self.config_file_location, config_root=self.config_root)
def get_registry(network: str, registry_filepath: Optional[Path] = None) -> BaseContractRegistry: if registry_filepath: registry = LocalContractRegistry(filepath=registry_filepath) else: registry = InMemoryContractRegistry.from_latest_publication(network=network) return registry
def __init__(self, domains: Set = None, known_node_class: object = None, is_me: bool = True, federated_only: bool = False, checksum_address: str = NO_BLOCKCHAIN_CONNECTION.bool_value( False), network_middleware: RestMiddleware = None, keyring: NucypherKeyring = None, keyring_root: str = None, crypto_power: CryptoPower = None, crypto_power_ups: List[CryptoPowerUp] = None, provider_uri: str = None, signer: Signer = None, registry: BaseContractRegistry = 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. """ # # Operating Mode if hasattr(self, '_interface_class' ): # TODO: have argument about meaning of 'lawful' # and whether maybe only Lawful characters have an interface self.interface = self._interface_class(character=self) if is_me: if not known_node_class: # Once in a while, in tests or demos, we init a plain Character who doesn't already know about its node class. from nucypher.characters.lawful import Ursula known_node_class = Ursula # If we're federated only, we assume that all other nodes in our domain are as well. known_node_class.set_federated_mode(federated_only) else: # What an awful hack. The last convulsions of #466. # TODO: Anything else. with suppress(AttributeError): federated_only = known_node_class._federated_only_instances if federated_only: if registry or provider_uri: raise ValueError( f"Cannot init federated-only character with {registry or provider_uri}." ) self.federated_only = bool(federated_only) # type: bool # # Powers # # Derive powers from keyring if keyring_root and keyring: if keyring_root != keyring.keyring_root: raise ValueError("Inconsistent keyring root directory path") if keyring: keyring_root, checksum_address = keyring.keyring_root, keyring.checksum_address crypto_power_ups = list() for power_up in self._default_crypto_powerups: power = keyring.derive_crypto_power(power_class=power_up) crypto_power_ups.append(power) self.keyring_root = keyring_root self.keyring = keyring 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_address # Fleet and Blockchain Connection (Everyone) if not domains: domains = {CharacterConfiguration.DEFAULT_DOMAIN} # # Self-Character # if is_me: self.treasure_maps = {} # type: dict # # Signing Power # self.signer = signer 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 # # Blockchain # self.provider_uri = provider_uri if not self.federated_only: self.registry = registry or InMemoryContractRegistry.from_latest_publication( network=list(domains)[0]) #TODO: #1580 else: self.registry = NO_BLOCKCHAIN_CONNECTION.bool_value(False) # REST self.network_middleware = network_middleware or RestMiddleware( registry=self.registry) # # Learner # Learner.__init__(self, domains=domains, network_middleware=self.network_middleware, node_class=known_node_class, *args, **kwargs) # # Stranger-Character # else: # Feel like a stranger if network_middleware is not None: raise TypeError( "Network middleware cannot be attached to a Stranger-Character." ) if registry is not None: raise TypeError( "Registry cannot be attached to stranger-Characters.") verifying_key = self.public_keys(SigningPower) self._stamp = StrangerStamp(verifying_key) self.keyring_root = STRANGER self.network_middleware = STRANGER # # Decentralized # if not federated_only: self._checksum_address = checksum_address # TODO: Check that this matches TransactingPower # # Federated # elif federated_only: try: self._set_checksum_address() # type: str except NoSigningPower: self._checksum_address = NO_BLOCKCHAIN_CONNECTION if checksum_address: # We'll take a checksum address, as long as it matches their singing key if not checksum_address == self.checksum_address: error = "Federated-only Characters derive their address from their Signing key; got {} instead." raise self.SuspiciousActivity( error.format(checksum_address)) # # Nicknames # if self._checksum_address is NO_BLOCKCHAIN_CONNECTION and not self.federated_only and not is_me: # Sometimes we don't care about the nickname. For example, if Alice is granting to Bob, she usually # doesn't know or care about his wallet. Maybe this needs to change? # Currently, if this is a stranger and there's no blockchain connection, we assign NO_NICKNAME: self.nickname = self.nickname_metadata = NO_NICKNAME else: try: self.nickname, self.nickname_metadata = nickname_from_seed( self.checksum_address) except SigningPower.not_found_error: # TODO: Handle NO_BLOCKCHAIN_CONNECTION more coherently - #1547 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 __init__( self, # Base emitter=None, config_root: Optional[Path] = None, filepath: Optional[Path] = None, # Mode dev_mode: bool = False, federated_only: bool = False, # Identity checksum_address: str = None, crypto_power: CryptoPower = None, # Keystore keystore: Keystore = None, keystore_path: Optional[Path] = None, # Learner learn_on_same_thread: bool = False, abort_on_learning_error: bool = False, start_learning_now: bool = True, # Network controller_port: int = None, domain: str = DEFAULT_DOMAIN, network_middleware: RestMiddleware = None, lonely: bool = False, # Node Storage known_nodes: set = None, node_storage: NodeStorage = None, reload_metadata: bool = True, save_metadata: bool = True, # Blockchain poa: bool = None, light: bool = False, provider_uri: str = None, gas_strategy: Union[Callable, str] = DEFAULT_GAS_STRATEGY, max_gas_price: Optional[int] = None, signer_uri: str = None, # Registry registry: BaseContractRegistry = None, registry_filepath: Optional[Path] = None, # Deployed Workers worker_data: dict = None): self.log = Logger(self.__class__.__name__) # This constant is used to signal that a path can be generated if one is not provided. UNINITIALIZED_CONFIGURATION.bool_value(False) # Identity # NOTE: NodeConfigurations can only be used with Self-Characters self.is_me = True self.checksum_address = checksum_address # Keystore self.crypto_power = crypto_power if keystore_path and not keystore: keystore = Keystore(keystore_path=keystore_path) self.__keystore = self.__keystore = keystore or NO_KEYSTORE_ATTACHED.bool_value( False) self.keystore_dir = Path( keystore.keystore_path ).parent if keystore else UNINITIALIZED_CONFIGURATION # Contract Registry if registry and registry_filepath: if registry.filepath != registry_filepath: error = f"Inconsistent registry filepaths for '{registry.filepath.absolute()}'" \ f" and '{registry_filepath.absolute()}'." raise ValueError(error) else: self.log.warn( f"Registry and registry filepath were both passed.") self.registry = registry or NO_BLOCKCHAIN_CONNECTION.bool_value(False) self.registry_filepath = registry_filepath or UNINITIALIZED_CONFIGURATION # Blockchain self.poa = poa self.is_light = light self.provider_uri = provider_uri or NO_BLOCKCHAIN_CONNECTION self.signer_uri = signer_uri or None # Learner self.federated_only = federated_only self.domain = domain self.learn_on_same_thread = learn_on_same_thread self.abort_on_learning_error = abort_on_learning_error self.start_learning_now = start_learning_now self.save_metadata = save_metadata self.reload_metadata = reload_metadata self.known_nodes = known_nodes or set() # handpicked self.lonely = lonely # Configuration self.__dev_mode = dev_mode self.config_file_location = filepath or UNINITIALIZED_CONFIGURATION self.config_root = UNINITIALIZED_CONFIGURATION # Deployed Workers self.worker_data = worker_data # # Federated vs. Blockchain arguments consistency # # # Federated # if self.federated_only: # Check for incompatible values blockchain_args = { 'filepath': registry_filepath, 'poa': poa, 'provider_uri': provider_uri, 'gas_strategy': gas_strategy, 'max_gas_price': max_gas_price } if any(blockchain_args.values()): bad_args = ", ".join(f"{arg}={val}" for arg, val in blockchain_args.items() if val) self.log.warn( f"Arguments {bad_args} are incompatible with federated_only. " f"Overridden with a sane default.") # Clear decentralized attributes to ensure consistency with a # federated configuration. self.poa = False self.is_light = False self.provider_uri = None self.registry_filepath = None self.gas_strategy = None self.max_gas_price = None # # Decentralized # else: self.gas_strategy = gas_strategy self.max_gas_price = max_gas_price # gwei is_initialized = BlockchainInterfaceFactory.is_interface_initialized( provider_uri=self.provider_uri) if not is_initialized and provider_uri: BlockchainInterfaceFactory.initialize_interface( provider_uri=self.provider_uri, poa=self.poa, light=self.is_light, emitter=emitter, gas_strategy=self.gas_strategy, max_gas_price=self.max_gas_price) else: self.log.warn( f"Using existing blockchain interface connection ({self.provider_uri})." ) if not self.registry: # TODO: These two code blocks are untested. if not self.registry_filepath: # TODO: Registry URI (goerli://speedynet.json) :-) self.log.info(f"Fetching latest registry from source.") self.registry = InMemoryContractRegistry.from_latest_publication( network=self.domain) else: self.registry = LocalContractRegistry( filepath=self.registry_filepath) self.log.info(f"Using local registry ({self.registry}).") self.testnet = self.domain != NetworksInventory.MAINNET self.signer = Signer.from_signer_uri(self.signer_uri, testnet=self.testnet) if dev_mode: self.__temp_dir = UNINITIALIZED_CONFIGURATION self._setup_node_storage() self.initialize(password=DEVELOPMENT_CONFIGURATION) else: self.__temp_dir = LIVE_CONFIGURATION self.config_root = config_root or self.DEFAULT_CONFIG_ROOT self._cache_runtime_filepaths() self._setup_node_storage(node_storage=node_storage) # Network self.controller_port = controller_port or self.DEFAULT_CONTROLLER_PORT self.network_middleware = network_middleware or self.DEFAULT_NETWORK_MIDDLEWARE( registry=self.registry) super().__init__(filepath=self.config_file_location, config_root=self.config_root)
def test_multiversion_contract(): # Prepare compiler base_dir = os.path.join(dirname(abspath(__file__)), "contracts", "multiversion") v1_dir = os.path.join(base_dir, "v1") v2_dir = os.path.join(base_dir, "v2") root_dir = SolidityCompiler.default_contract_dir() solidity_compiler = SolidityCompiler(source_dirs=[ SourceDirs(root_dir, {v2_dir}), SourceDirs(root_dir, {v1_dir}) ]) # Prepare chain blockchain_interface = BlockchainDeployerInterface( provider_uri='tester://pyevm/2', compiler=solidity_compiler) blockchain_interface.connect() origin = blockchain_interface.client.accounts[0] blockchain_interface.transacting_power = TransactingPower( password=INSECURE_DEVELOPMENT_PASSWORD, account=origin) blockchain_interface.transacting_power.activate() # Searching both contract through raw data contract_name = "VersionTest" requested_version = "v1.2.3" version, _data = blockchain_interface.find_raw_contract_data( contract_name=contract_name, requested_version=requested_version) assert version == requested_version version, _data = blockchain_interface.find_raw_contract_data( contract_name=contract_name, requested_version="latest") assert version == requested_version requested_version = "v1.1.4" version, _data = blockchain_interface.find_raw_contract_data( contract_name=contract_name, requested_version=requested_version) assert version == requested_version version, _data = blockchain_interface.find_raw_contract_data( contract_name=contract_name, requested_version="earliest") assert version == requested_version # Deploy different contracts and check their versions registry = InMemoryContractRegistry() contract, receipt = blockchain_interface.deploy_contract( deployer_address=origin, registry=registry, contract_name=contract_name, contract_version="v1.1.4") assert contract.version == "v1.1.4" assert contract.functions.VERSION().call() == 1 contract, receipt = blockchain_interface.deploy_contract( deployer_address=origin, registry=registry, contract_name=contract_name, contract_version="earliest") assert contract.version == "v1.1.4" assert contract.functions.VERSION().call() == 1 contract, receipt = blockchain_interface.deploy_contract( deployer_address=origin, registry=registry, contract_name=contract_name, contract_version="v1.2.3") assert contract.version == "v1.2.3" assert contract.functions.VERSION().call() == 2 contract, receipt = blockchain_interface.deploy_contract( deployer_address=origin, registry=registry, contract_name=contract_name, contract_version="latest") assert contract.version == "v1.2.3" assert contract.functions.VERSION().call() == 2 contract, receipt = blockchain_interface.deploy_contract( deployer_address=origin, registry=registry, contract_name=contract_name) assert contract.version == "v1.2.3" assert contract.functions.VERSION().call() == 2
def test_upgradeability(temp_dir_path): # Prepare remote source for compilation download_github_dir(GITHUB_SOURCE_LINK, temp_dir_path) solidity_compiler = SolidityCompiler(source_dirs=[ SourceDirs(SolidityCompiler.default_contract_dir()), SourceDirs(temp_dir_path) ]) # Prepare the blockchain provider_uri = 'tester://pyevm/2' try: blockchain_interface = BlockchainDeployerInterface( provider_uri=provider_uri, compiler=solidity_compiler, gas_strategy=free_gas_price_strategy) blockchain_interface.connect() origin = blockchain_interface.client.accounts[0] BlockchainInterfaceFactory.register_interface( interface=blockchain_interface) blockchain_interface.transacting_power = TransactingPower( password=INSECURE_DEVELOPMENT_PASSWORD, account=origin) blockchain_interface.transacting_power.activate() # Check contracts with multiple versions raw_contracts = blockchain_interface._raw_contract_cache contract_name = AdjudicatorDeployer.contract_name test_adjudicator = len(raw_contracts[contract_name]) > 1 contract_name = StakingEscrowDeployer.contract_name test_staking_escrow = len(raw_contracts[contract_name]) > 1 contract_name = PolicyManagerDeployer.contract_name test_policy_manager = len(raw_contracts[contract_name]) > 1 if not test_adjudicator and not test_staking_escrow and not test_policy_manager: return # Prepare master version of contracts and upgrade to the latest registry = InMemoryContractRegistry() token_deployer = NucypherTokenDeployer(registry=registry, deployer_address=origin) token_deployer.deploy() staking_escrow_deployer = StakingEscrowDeployer( registry=registry, deployer_address=origin) deploy_earliest_contract(blockchain_interface, staking_escrow_deployer) if test_staking_escrow: staking_escrow_deployer.upgrade(contract_version="latest") if test_policy_manager: policy_manager_deployer = PolicyManagerDeployer( registry=registry, deployer_address=origin) deploy_earliest_contract(blockchain_interface, policy_manager_deployer) policy_manager_deployer.upgrade(contract_version="latest") if test_adjudicator: adjudicator_deployer = AdjudicatorDeployer(registry=registry, deployer_address=origin) deploy_earliest_contract(blockchain_interface, adjudicator_deployer) adjudicator_deployer.upgrade(contract_version="latest") finally: # Unregister interface with contextlib.suppress(KeyError): del BlockchainInterfaceFactory._interfaces[provider_uri]
def test_manual_deployment_of_idle_network(click_runner): if os.path.exists(ALTERNATE_REGISTRY_FILEPATH_2): os.remove(ALTERNATE_REGISTRY_FILEPATH_2) assert not os.path.exists(ALTERNATE_REGISTRY_FILEPATH_2) registry = LocalContractRegistry(filepath=ALTERNATE_REGISTRY_FILEPATH_2) registry.write(InMemoryContractRegistry().read()) # TODO: Manual deployments from scratch require an existing but empty registry (i.e., a json file just with "[]") user_input = '0\n' + YES_ENTER + 'DEPLOY' # 1. Deploy NuCypherToken command = ('contracts', '--contract-name', NUCYPHER_TOKEN_CONTRACT_NAME, '--provider', TEST_PROVIDER_URI, '--network', TEMPORARY_DOMAIN, '--registry-infile', ALTERNATE_REGISTRY_FILEPATH_2) result = click_runner.invoke(deploy, command, input=user_input, catch_exceptions=False) assert result.exit_code == 0, result.output assert os.path.exists(ALTERNATE_REGISTRY_FILEPATH_2) new_registry = LocalContractRegistry(filepath=ALTERNATE_REGISTRY_FILEPATH_2) deployed_contracts = [NUCYPHER_TOKEN_CONTRACT_NAME] assert list(new_registry.enrolled_names) == deployed_contracts # 2. Deploy StakingEscrow in INIT mode command = ('contracts', '--contract-name', STAKING_ESCROW_CONTRACT_NAME, '--mode', 'init', '--provider', TEST_PROVIDER_URI, '--network', TEMPORARY_DOMAIN, '--registry-infile', ALTERNATE_REGISTRY_FILEPATH_2) result = click_runner.invoke(deploy, command, input=user_input, catch_exceptions=False) assert result.exit_code == 0 deployed_contracts.extend([STAKING_ESCROW_STUB_CONTRACT_NAME, DISPATCHER_CONTRACT_NAME]) assert list(new_registry.enrolled_names) == deployed_contracts # 3. Deploy PolicyManager command = ('contracts', '--contract-name', POLICY_MANAGER_CONTRACT_NAME, '--provider', TEST_PROVIDER_URI, '--network', TEMPORARY_DOMAIN, '--registry-infile', ALTERNATE_REGISTRY_FILEPATH_2) result = click_runner.invoke(deploy, command, input=user_input, catch_exceptions=False) assert result.exit_code == 0 deployed_contracts.extend([POLICY_MANAGER_CONTRACT_NAME, DISPATCHER_CONTRACT_NAME]) assert list(new_registry.enrolled_names) == deployed_contracts # 4. Deploy Adjudicator command = ('contracts', '--contract-name', ADJUDICATOR_CONTRACT_NAME, '--provider', TEST_PROVIDER_URI, '--network', TEMPORARY_DOMAIN, '--registry-infile', ALTERNATE_REGISTRY_FILEPATH_2) result = click_runner.invoke(deploy, command, input=user_input, catch_exceptions=False) assert result.exit_code == 0 deployed_contracts.extend([ADJUDICATOR_CONTRACT_NAME, DISPATCHER_CONTRACT_NAME]) assert list(new_registry.enrolled_names) == deployed_contracts # 5. Deploy StakingEscrow in IDLE mode command = ('contracts', '--contract-name', STAKING_ESCROW_CONTRACT_NAME, '--mode', 'idle', '--provider', TEST_PROVIDER_URI, '--network', TEMPORARY_DOMAIN, '--registry-infile', ALTERNATE_REGISTRY_FILEPATH_2) result = click_runner.invoke(deploy, command, input=user_input, catch_exceptions=False) assert result.exit_code == 0 deployed_contracts.extend([STAKING_ESCROW_CONTRACT_NAME]) assert list(new_registry.enrolled_names) == deployed_contracts # 6. Activate StakingEscrow command = ('contracts', '--contract-name', STAKING_ESCROW_CONTRACT_NAME, '--activate', '--provider', TEST_PROVIDER_URI, '--network', TEMPORARY_DOMAIN, '--registry-infile', ALTERNATE_REGISTRY_FILEPATH_2) user_input = '0\n' + YES_ENTER + YES_ENTER + INSECURE_DEVELOPMENT_PASSWORD result = click_runner.invoke(deploy, command, input=user_input, catch_exceptions=False) assert result.exit_code == 0 assert list(new_registry.enrolled_names) == deployed_contracts
def deploy(action, poa, etherscan, provider_uri, gas, deployer_address, contract_name, allocation_infile, allocation_outfile, registry_infile, registry_outfile, value, target_address, config_root, hw_wallet, force, dev): """ Manage contract and registry deployment. \b Actions ----------------------------------------------------------------------------- contracts Compile and deploy contracts. allocations Deploy pre-allocation contracts. upgrade Upgrade NuCypher existing proxy contract deployments. rollback Rollback a proxy contract's target. inspect Echo owner information and bare contract metadata. transfer-tokens Transfer tokens from a contract to another address using the owner's address. transfer-ownership Transfer ownership of contracts to another address. """ emitter = StdoutEmitter() # # 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) if not provider_uri: raise click.BadOptionUsage( message=f"--provider is required to deploy.", option_name="--provider") # # Pre-Launch Warnings # if not hw_wallet: emitter.echo("WARNING: --no-hw-wallet is enabled.", color='yellow') if etherscan: emitter.echo( "WARNING: --etherscan is enabled. " "A browser tab will be opened with deployed contracts and TXs as provided by Etherscan.", color='yellow') else: emitter.echo( "WARNING: --etherscan is disabled. " "If you want to see deployed contracts and TXs in your browser, activate --etherscan.", color='yellow') # # Connect to Blockchain # if not BlockchainInterfaceFactory.is_interface_initialized( provider_uri=provider_uri): # Note: For test compatibility. deployer_interface = BlockchainDeployerInterface( provider_uri=provider_uri, poa=poa) BlockchainInterfaceFactory.register_interface( interface=deployer_interface, sync=False, show_sync_progress=False) else: deployer_interface = BlockchainInterfaceFactory.get_interface( provider_uri=provider_uri) if action == "inspect": if registry_infile: registry = LocalContractRegistry(filepath=registry_infile) else: registry = InMemoryContractRegistry.from_latest_publication() administrator = ContractAdministrator( registry=registry, deployer_address=deployer_address) paint_deployer_contract_inspection(emitter=emitter, administrator=administrator) return # Exit # # Establish Registry # # Establish a contract registry from disk if specified default_registry_filepath = os.path.join( DEFAULT_CONFIG_ROOT, BaseContractRegistry.REGISTRY_NAME) registry_filepath = (registry_outfile or registry_infile) or default_registry_filepath if dev: # TODO: Need a way to detect a geth --dev registry filepath here. (then deprecate the --dev flag) registry_filepath = os.path.join(config_root, 'dev_contract_registry.json') registry = LocalContractRegistry(filepath=registry_filepath) emitter.message(f"Configured to registry filepath {registry_filepath}") # # Make Authenticated Deployment Actor # # Verify Address & collect password if not deployer_address: prompt = "Select deployer account" deployer_address = select_client_account(emitter=emitter, prompt=prompt, provider_uri=provider_uri, show_balances=False) if not force: click.confirm("Selected {} - Continue?".format(deployer_address), abort=True) password = None if not hw_wallet and not deployer_interface.client.is_local: password = get_client_password(checksum_address=deployer_address) # Produce Actor ADMINISTRATOR = ContractAdministrator(registry=registry, client_password=password, deployer_address=deployer_address) # Verify ETH Balance emitter.echo(f"\n\nDeployer ETH balance: {ADMINISTRATOR.eth_balance}") if ADMINISTRATOR.eth_balance == 0: emitter.echo("Deployer address has no ETH.", color='red', bold=True) raise click.Abort() # # 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) ADMINISTRATOR.upgrade_contract( contract_name=contract_name, existing_plaintext_secret=existing_secret, new_plaintext_secret=new_secret) return # Exit elif action == 'rollback': if not contract_name: raise click.BadArgumentUsage( message="--contract-name is required when using --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) ADMINISTRATOR.rollback_contract( contract_name=contract_name, existing_plaintext_secret=existing_secret, new_plaintext_secret=new_secret) return # Exit elif action == "contracts": # # Deploy Single Contract (Amend Registry) # if contract_name: try: contract_deployer = ADMINISTRATOR.deployers[contract_name] except KeyError: message = f"No such contract {contract_name}. Available contracts are {ADMINISTRATOR.deployers.keys()}" emitter.echo(message, color='red', bold=True) raise click.Abort() else: emitter.echo(f"Deploying {contract_name}") if contract_deployer._upgradeable: secret = ADMINISTRATOR.collect_deployment_secret( deployer=contract_deployer) receipts, agent = ADMINISTRATOR.deploy_contract( contract_name=contract_name, plaintext_secret=secret) else: receipts, agent = ADMINISTRATOR.deploy_contract( contract_name=contract_name, gas_limit=gas) paint_contract_deployment( contract_name=contract_name, contract_address=agent.contract_address, receipts=receipts, emitter=emitter, chain_name=deployer_interface.client.chain_name, open_in_browser=etherscan) return # Exit # # Deploy Automated Series (Create Registry) # # Confirm filesystem registry writes. if os.path.isfile(registry_filepath): emitter.echo( f"\nThere is an existing contract registry at {registry_filepath}.\n" f"Did you mean 'nucypher-deploy upgrade'?\n", color='yellow') click.confirm("*DESTROY* existing local registry and continue?", abort=True) os.remove(registry_filepath) # Stage Deployment secrets = ADMINISTRATOR.collect_deployment_secrets() paint_staged_deployment(deployer_interface=deployer_interface, administrator=ADMINISTRATOR, emitter=emitter) # Confirm Trigger Deployment if not confirm_deployment(emitter=emitter, deployer_interface=deployer_interface): raise click.Abort() # Delay - Last chance to abort via KeyboardInterrupt paint_deployment_delay(emitter=emitter) # Execute Deployment deployment_receipts = ADMINISTRATOR.deploy_network_contracts( secrets=secrets, emitter=emitter, interactive=not force, etherscan=etherscan) # Paint outfile paths registry_outfile = registry_filepath emitter.echo('Generated registry {}'.format(registry_outfile), bold=True, color='blue') # Save transaction metadata receipts_filepath = ADMINISTRATOR.save_deployment_receipts( receipts=deployment_receipts) emitter.echo(f"Saved deployment receipts to {receipts_filepath}", color='blue', bold=True) return # Exit elif action == "allocations": if not allocation_infile: allocation_infile = click.prompt("Enter allocation data filepath") click.confirm("Continue deploying and allocating?", abort=True) ADMINISTRATOR.deploy_beneficiaries_from_file( allocation_data_filepath=allocation_infile, allocation_outfile=allocation_outfile) return # Exit elif action == "transfer-tokens": token_agent = ContractAgency.get_agent(NucypherTokenAgent, registry=registry) if not target_address: target_address = click.prompt("Enter recipient's checksum address", type=EIP55_CHECKSUM_ADDRESS) if not value: stake_value_range = click.FloatRange(min=0, clamp=False) value = NU.from_tokens( click.prompt(f"Enter value in NU", type=stake_value_range)) click.confirm( f"Transfer {value} from {deployer_address} to {target_address}?", abort=True) receipt = token_agent.transfer(amount=value, sender_address=deployer_address, target_address=target_address) emitter.echo(f"OK | Receipt: {receipt['transactionHash'].hex()}") return # Exit elif action == "transfer-ownership": if not target_address: target_address = click.prompt("Enter new owner's checksum address", type=EIP55_CHECKSUM_ADDRESS) if contract_name: try: contract_deployer_class = ADMINISTRATOR.deployers[ contract_name] except KeyError: message = f"No such contract {contract_name}. Available contracts are {ADMINISTRATOR.deployers.keys()}" emitter.echo(message, color='red', bold=True) raise click.Abort() else: contract_deployer = contract_deployer_class( registry=ADMINISTRATOR.registry, deployer_address=ADMINISTRATOR.deployer_address) receipt = contract_deployer.transfer_ownership( new_owner=target_address, transaction_gas_limit=gas) emitter.ipc(receipt, request_id=0, duration=0) # TODO: #1216 return # Exit else: receipts = ADMINISTRATOR.relinquish_ownership( new_owner=target_address, transaction_gas_limit=gas) emitter.ipc(receipts, request_id=0, duration=0) # TODO: #1216 return # Exit else: raise click.BadArgumentUsage(message=f"Unknown action '{action}'")
def test_registry(): registry = InMemoryContractRegistry() return registry
def test_upgradeability(temp_dir_path): # Prepare remote source for compilation download_github_dir(GITHUB_SOURCE_LINK, temp_dir_path) # Prepare the blockchain TesterBlockchain.SOURCES = [ SourceBundle(base_path=SOLIDITY_SOURCE_ROOT, other_paths=(TEST_SOLIDITY_SOURCE_ROOT, )), SourceBundle(base_path=Path(temp_dir_path)) ] eth_provider_uri = 'tester://pyevm/2' # TODO: Testerchain caching Issues try: blockchain_interface = TesterBlockchain(gas_strategy='free') blockchain_interface.eth_provider_uri = eth_provider_uri blockchain_interface.connect() origin = blockchain_interface.client.accounts[0] BlockchainInterfaceFactory.register_interface( interface=blockchain_interface) transacting_power = TransactingPower( password=INSECURE_DEVELOPMENT_PASSWORD, signer=Web3Signer(blockchain_interface.client), account=origin) economics = make_token_economics(blockchain_interface) # Check contracts with multiple versions contract_name = StakingEscrowDeployer.contract_name skip_staking_escrow_test = skip_test(blockchain_interface, contract_name) if skip_staking_escrow_test: return # Prepare master version of contracts and upgrade to the latest registry = InMemoryContractRegistry() token_deployer = NucypherTokenDeployer(registry=registry, economics=economics) token_deployer.deploy(transacting_power=transacting_power) staking_escrow_deployer = StakingEscrowDeployer(registry=registry, economics=economics) staking_escrow_deployer.deploy(deployment_mode=constants.INIT, transacting_power=transacting_power) if not skip_staking_escrow_test: economics.worklock_supply = economics.maximum_allowed_locked worklock_deployer = WorklockDeployer(registry=registry, economics=economics) worklock_deployer.deploy(transacting_power=transacting_power) staking_escrow_deployer = StakingEscrowDeployer(registry=registry, economics=economics) deploy_base_contract(blockchain_interface, staking_escrow_deployer, transacting_power=transacting_power, skipt_test=skip_staking_escrow_test) if not skip_staking_escrow_test: prepare_staker(blockchain_interface=blockchain_interface, deployer=staking_escrow_deployer, transacting_power=transacting_power) staking_escrow_deployer.upgrade( transacting_power=transacting_power, contract_version="latest", confirmations=0) finally: # Unregister interface # TODO: Move to method? with contextlib.suppress(KeyError): del BlockchainInterfaceFactory._interfaces[eth_provider_uri]