def testerchain(solidity_compiler): """ https: // github.com / ethereum / eth - tester # available-backends """ memory_registry = InMemoryEthereumContractRegistry() # Use the the custom provider and registrar to init an interface deployer_interface = BlockchainDeployerInterface( compiler=solidity_compiler, # freshly recompile if not None registry=memory_registry, provider_uri=TEST_PROVIDER_URI) # Create the blockchain testerchain = TesterBlockchain(interface=deployer_interface, eth_airdrop=True, free_transactions=True, poa=True) # Set the deployer address from a freshly created test account deployer_interface.deployer_address = testerchain.etherbase_account yield testerchain deployer_interface.disconnect() testerchain.sever_connection()
def testerchain(solidity_compiler): """ https: // github.com / ethereum / eth - tester # available-backends """ memory_registry = InMemoryEthereumContractRegistry() # Use the the custom provider and registrar to init an interface deployer_interface = BlockchainDeployerInterface( compiler=solidity_compiler, # freshly recompile if not None registry=memory_registry, provider_uri='tester://pyevm') # Create the blockchain testerchain = TesterBlockchain( interface=deployer_interface, test_accounts=NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK, airdrop=False) origin, *everyone = testerchain.interface.w3.eth.accounts deployer_interface.deployer_address = origin # Set the deployer address from a freshly created test account testerchain.ether_airdrop(amount=1000000000) # TODO: Use test constant yield testerchain testerchain.sever_connection()
def test_rollback(click_runner, mock_primary_registry_filepath): """Roll 'em all back!""" # Simulate "Reconnection" real_attach_provider = BlockchainDeployerInterface._attach_provider cached_blockchain = BlockchainDeployerInterface.reconnect() registry = cached_blockchain.registry assert registry.filepath == mock_primary_registry_filepath def attach_cached_provider(interface, *args, **kwargs): cached_provider = cached_blockchain.provider real_attach_provider(interface, provider=cached_provider) BlockchainDeployerInterface._attach_provider = attach_cached_provider # Input Components yes = 'Y\n' # Stage Rollbacks old_secret = INSECURE_SECRETS[PLANNED_UPGRADES] rollback_secret = generate_insecure_secret() user_input = '0\n' + yes + old_secret + rollback_secret + rollback_secret contracts_to_rollback = ('StakingEscrow', # v4 -> v3 'PolicyManager', # v4 -> v3 'Adjudicator', # v4 -> v3 ) # Execute Rollbacks for contract_name in contracts_to_rollback: command = ('rollback', '--contract-name', contract_name, '--registry-infile', MOCK_REGISTRY_FILEPATH, '--provider-uri', TEST_PROVIDER_URI, '--poa') result = click_runner.invoke(deploy, command, input=user_input, catch_exceptions=False) assert result.exit_code == 0 blockchain = BlockchainDeployerInterface.reconnect() records = blockchain.registry.search(contract_name=contract_name) assert len(records) == 4 *old_records, v3, v4 = records current_target, rollback_target = v4, v3 _name, current_target_address, *abi = current_target _name, rollback_target_address, *abi = rollback_target assert current_target_address != rollback_target_address # Ensure the proxy targets the rollback target (previous version) with pytest.raises(BlockchainInterface.UnknownContract): blockchain.get_proxy(target_address=current_target_address, proxy_name='Dispatcher') proxy = blockchain.get_proxy(target_address=rollback_target_address, proxy_name='Dispatcher') # Deeper - Ensure the proxy targets the old deployment on-chain targeted_address = proxy.functions.target().call() assert targeted_address != current_target assert targeted_address == rollback_target_address
def 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", confirmations=0) 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", confirmations=0) if test_adjudicator: adjudicator_deployer = AdjudicatorDeployer(registry=registry, deployer_address=origin) deploy_earliest_contract(blockchain_interface, adjudicator_deployer) adjudicator_deployer.upgrade(contract_version="latest", confirmations=0) finally: # Unregister interface with contextlib.suppress(KeyError): del BlockchainInterfaceFactory._interfaces[provider_uri]
def _initialize_blockchain(poa, provider_uri, emitter): 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, emitter=emitter) else: deployer_interface = BlockchainInterfaceFactory.get_interface(provider_uri=provider_uri) deployer_interface.connect() return deployer_interface
def another_testerchain(solidity_compiler): memory_registry = InMemoryEthereumContractRegistry() deployer_interface = BlockchainDeployerInterface( compiler=solidity_compiler, registry=memory_registry, provider_uri=TEST_PROVIDER_URI) testerchain = TesterBlockchain(interface=deployer_interface, test_accounts=2 * NUMBER_OF_ETH_TEST_ACCOUNTS, eth_airdrop=True) deployer_interface.deployer_address = testerchain.etherbase_account yield testerchain testerchain.sever_connection()
def test_geth_deployment_integration(instant_geth_dev_node): # TODO: Move to decorator if 'CIRCLECI' in os.environ: pytest.skip("Do not run Geth nodes in CI") memory_registry = InMemoryEthereumContractRegistry() blockchain = BlockchainDeployerInterface( provider_process=instant_geth_dev_node, registry=memory_registry) # Make Deployer etherbase = to_checksum_address(instant_geth_dev_node.accounts[0].decode( )) # TODO: Make property on nucypher geth node instances? deployer = DeployerActor( blockchain=blockchain, deployer_address=etherbase, client_password=None) # dev accounts have no password. assert int(deployer.blockchain.client.chain_id) == 1337 # Deploy secrets = dict() for deployer_class in deployer.upgradeable_deployer_classes: secrets[deployer_class.contract_name] = INSECURE_DEVELOPMENT_PASSWORD deployer.deploy_network_contracts(secrets=secrets, interactive=False)
def connect(cls, *args, **kwargs) -> 'TesterBlockchain': interface = BlockchainDeployerInterface(provider_uri=cls._PROVIDER_URI, compiler=SolidityCompiler(test_contract_dir=CONTRACT_ROOT), registry=InMemoryEthereumContractRegistry()) testerchain = TesterBlockchain(interface=interface, *args, **kwargs) return testerchain
def _initialize_blockchain(poa, provider_uri, emitter, ignore_solidity_check, gas_strategy=None): if not BlockchainInterfaceFactory.is_interface_initialized(provider_uri=provider_uri): # Note: For test compatibility. deployer_interface = BlockchainDeployerInterface(provider_uri=provider_uri, poa=poa, ignore_solidity_check=ignore_solidity_check, gas_strategy=gas_strategy) BlockchainInterfaceFactory.register_interface(interface=deployer_interface, sync=False, emitter=emitter) else: deployer_interface = BlockchainInterfaceFactory.get_interface(provider_uri=provider_uri) deployer_interface.connect() return deployer_interface
def test_rapid_deployment(): compiler = SolidityCompiler() registry = InMemoryEthereumContractRegistry() allocation_registry = InMemoryAllocationRegistry() interface = BlockchainDeployerInterface(compiler=compiler, registry=registry, provider_uri='tester://pyevm') blockchain = TesterBlockchain(interface=interface, airdrop=False, test_accounts=4) blockchain.ether_airdrop(amount=1000000000) origin, *everyone = blockchain.interface.w3.eth.accounts deployer = Deployer(blockchain=blockchain, deployer_address=origin) deployer_address, *all_yall = deployer.blockchain.interface.w3.eth.accounts # The Big Three (+ Dispatchers) deployer.deploy_network_contracts(miner_secret=os.urandom(32), policy_secret=os.urandom(32)) # User Escrow Proxy deployer.deploy_escrow_proxy(secret=os.urandom(32)) # Deploy User Escrow total_allocations = 100 # Start with some hard-coded cases... allocation_data = [{ 'address': all_yall[1], 'amount': MAX_ALLOWED_LOCKED, 'duration': ONE_YEAR_IN_SECONDS }, { 'address': all_yall[2], 'amount': MIN_ALLOWED_LOCKED, 'duration': ONE_YEAR_IN_SECONDS * 2 }, { 'address': all_yall[3], 'amount': MIN_ALLOWED_LOCKED * 100, 'duration': ONE_YEAR_IN_SECONDS * 3 }] # Pile on the rest for _ in range(total_allocations - len(allocation_data)): random_password = ''.join( random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(16)) acct = w3.eth.account.create(random_password) beneficiary_address = acct.address amount = random.randint(MIN_ALLOWED_LOCKED, MAX_ALLOWED_LOCKED) duration = random.randint(MIN_LOCKED_PERIODS, MAX_MINTING_PERIODS * 3) random_allocation = { 'address': beneficiary_address, 'amount': amount, 'duration': duration } allocation_data.append(random_allocation) deployer.deploy_beneficiary_contracts( allocations=allocation_data, allocation_registry=allocation_registry)
def deploy_base_contract(blockchain_interface: BlockchainDeployerInterface, deployer: BaseContractDeployer, transacting_power: TransactingPower, skipt_test: bool): contract_name = deployer.contract_name latest_version, _data = blockchain_interface.find_raw_contract_data( contract_name, "latest") raw_contracts = blockchain_interface._raw_contract_cache overrides = dict() if len(raw_contracts[contract_name]) != 1: try: overrides_func = CONSTRUCTOR_OVERRIDES[contract_name][ latest_version] overrides = overrides_func(blockchain_interface, transacting_power, deployer) except KeyError: pass version = "latest" if skipt_test else "earliest" try: deployer.deploy(transacting_power=transacting_power, contract_version=version, deployment_mode=constants.FULL, **overrides) except ValidationError: pass # Skip errors related to initialization
def initialize_deployer_interface(emitter: StdoutEmitter, poa: bool, provider_uri, ignore_solidity_check: bool, gas_strategy: str = None, max_gas_price: int = None ) -> BlockchainDeployerInterface: if not BlockchainInterfaceFactory.is_interface_initialized(provider_uri=provider_uri): deployer_interface = BlockchainDeployerInterface(provider_uri=provider_uri, poa=poa, gas_strategy=gas_strategy, max_gas_price=max_gas_price) BlockchainInterfaceFactory.register_interface(interface=deployer_interface, emitter=emitter) else: deployer_interface = BlockchainInterfaceFactory.get_interface(provider_uri=provider_uri) deployer_interface.connect(ignore_solidity_check=ignore_solidity_check) return deployer_interface
def skip_test(blockchain_interface: BlockchainDeployerInterface, contract_name: str): latest_version, _data = blockchain_interface.find_raw_contract_data(contract_name, "latest") raw_contracts = blockchain_interface._raw_contract_cache try: force_skip = latest_version in FORCE_SKIP[contract_name] except KeyError: force_skip = False return force_skip or len(raw_contracts[contract_name]) == 1
def make_testerchain(provider_uri, solidity_compiler): # Destroy existing blockchain BlockchainInterface.disconnect() TesterBlockchain.sever_connection() registry = EthereumContractRegistry(registry_filepath=MOCK_REGISTRY_FILEPATH) deployer_interface = BlockchainDeployerInterface(compiler=solidity_compiler, registry=registry, provider_uri=provider_uri) # Create new blockchain testerchain = TesterBlockchain(interface=deployer_interface, eth_airdrop=True, free_transactions=False, poa=True) # Set the deployer address from a freshly created test account deployer_interface.deployer_address = testerchain.etherbase_account return testerchain
def test_nucypher_deploy_allocation_contracts(click_runner, testerchain, deploy_user_input, mock_primary_registry_filepath, mock_allocation_infile, token_economics): # Simulate "Reconnection" real_attach_provider = BlockchainDeployerInterface._attach_provider cached_blockchain = BlockchainDeployerInterface.reconnect() registry = cached_blockchain.registry assert registry.filepath == mock_primary_registry_filepath def attach_cached_provider(interface, *args, **kwargs): cached_provider = cached_blockchain.provider real_attach_provider(interface, provider=cached_provider) BlockchainDeployerInterface._attach_provider = attach_cached_provider # # Main # deploy_command = ('allocations', '--registry-infile', MOCK_REGISTRY_FILEPATH, '--allocation-infile', mock_allocation_infile.filepath, '--allocation-outfile', MOCK_ALLOCATION_REGISTRY_FILEPATH, '--provider-uri', TEST_PROVIDER_URI, '--poa') account_index = '0\n' yes = 'Y\n' node_password = f'{INSECURE_DEVELOPMENT_PASSWORD}\n' user_input = account_index + yes + node_password + yes result = click_runner.invoke(deploy, deploy_command, input=user_input, catch_exceptions=False) assert result.exit_code == 0 # ensure that a pre-allocation recipient has the allocated token quantity. beneficiary = testerchain.client.accounts[-1] allocation_registry = AllocationRegistry( registry_filepath=MOCK_ALLOCATION_REGISTRY_FILEPATH) user_escrow_agent = UserEscrowAgent( blockchain=cached_blockchain, beneficiary=beneficiary, allocation_registry=allocation_registry) assert user_escrow_agent.unvested_tokens == token_economics.minimum_allowed_locked # # Tear Down # # Destroy existing blockchain testerchain.disconnect()
def deploy_earliest_contract(blockchain_interface: BlockchainDeployerInterface, deployer: BaseContractDeployer): contract_name = deployer.contract_name latest_version, _data = blockchain_interface.find_raw_contract_data(contract_name, "latest") try: overrides = CONSTRUCTOR_OVERRIDES[contract_name][latest_version] except KeyError: overrides = dict() try: deployer.deploy(contract_version="earliest", **overrides) except ValidationError: pass # Skip errors related to initialization
def test_rapid_deployment(token_economics): compiler = SolidityCompiler() registry = InMemoryEthereumContractRegistry() allocation_registry = InMemoryAllocationRegistry() interface = BlockchainDeployerInterface(compiler=compiler, registry=registry, provider_uri='tester://pyevm') blockchain = TesterBlockchain(interface=interface, airdrop=False, test_accounts=4) deployer_address = blockchain.etherbase_account deployer = Deployer(blockchain=blockchain, deployer_address=deployer_address) # The Big Three (+ Dispatchers) deployer.deploy_network_contracts(miner_secret=MINERS_ESCROW_DEPLOYMENT_SECRET, policy_secret=POLICY_MANAGER_DEPLOYMENT_SECRET, adjudicator_secret=MINING_ADJUDICATOR_DEPLOYMENT_SECRET) # Deploy User Escrow, too (+ Linker) deployer.deploy_escrow_proxy(secret=USER_ESCROW_PROXY_DEPLOYMENT_SECRET) total_allocations = NUMBER_OF_ALLOCATIONS_IN_TESTS all_yall = blockchain.unassigned_accounts # Start with some hard-coded cases... allocation_data = [{'address': all_yall[1], 'amount': token_economics.maximum_allowed_locked, 'duration': ONE_YEAR_IN_SECONDS}, {'address': all_yall[2], 'amount': token_economics.minimum_allowed_locked, 'duration': ONE_YEAR_IN_SECONDS*2}, {'address': all_yall[3], 'amount': token_economics.minimum_allowed_locked*100, 'duration': ONE_YEAR_IN_SECONDS*3} ] # Pile on the rest for _ in range(total_allocations - len(allocation_data)): random_password = ''.join(random.SystemRandom().choice(string.ascii_uppercase+string.digits) for _ in range(16)) acct = w3.eth.account.create(random_password) beneficiary_address = acct.address amount = random.randint(token_economics.minimum_allowed_locked, token_economics.maximum_allowed_locked) duration = random.randint(token_economics.minimum_locked_periods*ONE_YEAR_IN_SECONDS, (token_economics.maximum_locked_periods*ONE_YEAR_IN_SECONDS)*3) random_allocation = {'address': beneficiary_address, 'amount': amount, 'duration': duration} allocation_data.append(random_allocation) deployer.deploy_beneficiary_contracts(allocations=allocation_data, allocation_registry=allocation_registry)
def testerchain(solidity_compiler): """ https: // github.com / ethereum / eth - tester # available-backends """ temp_registrar = TemporaryEthereumContractRegistry() # Use the the custom provider and registrar to init an interface deployer_interface = BlockchainDeployerInterface( compiler=solidity_compiler, # freshly recompile if not None registry=temp_registrar, provider_uri='pyevm://tester') # Create the blockchain testerchain = TesterBlockchain(interface=deployer_interface, test_accounts=10) origin, *everyone = testerchain.interface.w3.eth.accounts deployer_interface.deployer_address = origin # Set the deployer address from a freshly created test account yield testerchain testerchain.sever_connection()
def deploy_base_contract(blockchain_interface: BlockchainDeployerInterface, deployer: BaseContractDeployer, skipt_test: bool): contract_name = deployer.contract_name latest_version, _data = blockchain_interface.find_raw_contract_data(contract_name, "latest") try: overrides = CONSTRUCTOR_OVERRIDES[contract_name][latest_version] except KeyError: overrides = dict() version = "latest" if skipt_test else "earliest" try: deployer.deploy(contract_version=version, deployment_mode=constants.FULL, **overrides) except ValidationError: pass # Skip errors related to initialization
def deployed_blockchain(): # # Interface # compiler = SolidityCompiler() registry = InMemoryEthereumContractRegistry() allocation_registry = InMemoryAllocationRegistry() interface = BlockchainDeployerInterface(compiler=compiler, registry=registry, provider_uri=TEST_PROVIDER_URI) # # Blockchain # blockchain = TesterBlockchain(interface=interface, airdrop=False, test_accounts=5, poa=True) blockchain.ether_airdrop(amount=TESTING_ETH_AIRDROP_AMOUNT) origin, *everyone = blockchain.interface.w3.eth.accounts # # Delpoyer # deployer = Deployer(blockchain=blockchain, deployer_address=origin) deployer_address, *all_yall = deployer.blockchain.interface.w3.eth.accounts # The Big Three (+ Dispatchers) deployer.deploy_network_contracts(miner_secret=os.urandom(32), policy_secret=os.urandom(32)) # User Escrow Proxy deployer.deploy_escrow_proxy(secret=os.urandom(32)) # Start with some hard-coded cases... allocation_data = [{ 'address': all_yall[1], 'amount': MAX_ALLOWED_LOCKED, 'duration': ONE_YEAR_IN_SECONDS }] deployer.deploy_beneficiary_contracts( allocations=allocation_data, allocation_registry=allocation_registry) yield blockchain, deployer_address, registry
def test_geth_deployment_integration(instant_geth_dev_node, test_registry): blockchain = BlockchainDeployerInterface( provider_process=instant_geth_dev_node, poa=True) # always poa here. BlockchainInterfaceFactory.register_interface(interface=blockchain) # Make Deployer etherbase = to_checksum_address(instant_geth_dev_node.accounts[0].decode( )) # TODO: Make property on nucypher geth node instances? administrator = ContractAdministrator( registry=test_registry, deployer_address=etherbase, client_password=None) # dev accounts have no password. assert int(blockchain.client.chain_id) == 1337 # Deploy administrator.deploy_network_contracts(interactive=False) # just do it
def deployed_blockchain(token_economics): # Interface compiler = SolidityCompiler() registry = InMemoryEthereumContractRegistry() allocation_registry = InMemoryAllocationRegistry() interface = BlockchainDeployerInterface(compiler=compiler, registry=registry, provider_uri=TEST_PROVIDER_URI) # Blockchain blockchain = TesterBlockchain(interface=interface, airdrop=True, test_accounts=5, poa=True) deployer_address = blockchain.etherbase_account # Deployer deployer = Deployer(blockchain=blockchain, deployer_address=deployer_address) # The Big Three (+ Dispatchers) deployer.deploy_network_contracts(miner_secret=os.urandom(32), policy_secret=os.urandom(32), adjudicator_secret=os.urandom(32)) # User Escrow Proxy deployer.deploy_escrow_proxy(secret=os.urandom(32)) # Start with some hard-coded cases... all_yall = blockchain.unassigned_accounts allocation_data = [{ 'address': all_yall[1], 'amount': token_economics.maximum_allowed_locked, 'duration': ONE_YEAR_IN_SECONDS }] deployer.deploy_beneficiary_contracts( allocations=allocation_data, allocation_registry=allocation_registry) yield blockchain, deployer_address, registry
def test_transfer_tokens(click_runner, mock_primary_registry_filepath): # # Setup # # Simulate "Reconnection" real_attach_provider = BlockchainDeployerInterface._attach_provider cached_blockchain = BlockchainDeployerInterface.reconnect() registry = cached_blockchain.registry assert registry.filepath == mock_primary_registry_filepath def attach_cached_provider(interface, *args, **kwargs): cached_provider = cached_blockchain.provider real_attach_provider(interface, provider=cached_provider) BlockchainDeployerInterface._attach_provider = attach_cached_provider # Let's transfer some NU to a random stranger recipient_address = to_checksum_address(os.urandom(20)) token_agent = NucypherTokenAgent() assert token_agent.get_balance(address=recipient_address) == 0 command = [ 'transfer', '--recipient-address', recipient_address, '--amount', 42, '--registry-infile', mock_primary_registry_filepath, '--provider', TEST_PROVIDER_URI, '--poa' ] user_input = '0\n' + 'Y\n' + 'Y\n' result = click_runner.invoke(deploy, command, input=user_input, catch_exceptions=False) assert result.exit_code == 0 # Check that the NU has arrived to the recipient assert token_agent.get_balance(address=recipient_address) == 42
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 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) 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 = 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, 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) policy_manager_deployer = PolicyManagerDeployer(registry=registry, economics=economics) deploy_base_contract(blockchain_interface, policy_manager_deployer, transacting_power=transacting_power, skipt_test=skip_policy_manager_test) adjudicator_deployer = AdjudicatorDeployer(registry=registry, economics=economics) deploy_base_contract(blockchain_interface, adjudicator_deployer, transacting_power=transacting_power, skipt_test=skip_adjudicator_test) if skip_staking_escrow_test: 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: # TODO prepare at least one staker before calling upgrade staking_escrow_deployer.upgrade( transacting_power=transacting_power, contract_version="latest", confirmations=0) if not skip_policy_manager_test: policy_manager_deployer.upgrade( transacting_power=transacting_power, contract_version="latest", confirmations=0) if not skip_adjudicator_test: adjudicator_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[provider_uri]
def estimate_gas(): solidity_compiler = SolidityCompiler(test_contract_dir=CONTRACTS_DIR) # create a temporary registrar for the tester blockchain temporary_registry = TemporaryEthereumContractRegistry() # Configure a custom provider overrides = {'gas_limit': 4626271} pyevm_backend = OverridablePyEVMBackend(genesis_overrides=overrides) eth_tester = EthereumTester(backend=pyevm_backend, auto_mine_transactions=True) pyevm_provider = EthereumTesterProvider(ethereum_tester=eth_tester) # Use the the custom provider and registrar to init an interface circumflex = BlockchainDeployerInterface( compiler=solidity_compiler, # freshly recompile registry=temporary_registry, # use temporary registrar providers=(pyevm_provider, )) # use custom test provider # Create the blockchain testerchain = TesterBlockchain(interface=circumflex, test_accounts=10) origin, ursula1, ursula2, ursula3, alice1, *everyone_else = testerchain.interface.w3.eth.accounts circumflex.deployer_address = origin # Set the deployer address from a freshly created test account token_deployer = NucypherTokenDeployer(blockchain=testerchain, deployer_address=origin) token_deployer.arm() token_deployer.deploy() token_agent = token_deployer.make_agent() miners_escrow_secret = os.urandom(constants.DISPATCHER_SECRET_LENGTH) miner_escrow_deployer = MinerEscrowDeployer( token_agent=token_agent, deployer_address=origin, secret_hash=testerchain.interface.w3.sha3(miners_escrow_secret)) miner_escrow_deployer.arm() miner_escrow_deployer.deploy() miner_agent = miner_escrow_deployer.make_agent() policy_manager_secret = os.urandom(constants.DISPATCHER_SECRET_LENGTH) policy_manager_deployer = PolicyManagerDeployer( miner_agent=miner_agent, deployer_address=origin, secret_hash=testerchain.interface.w3.sha3(policy_manager_secret)) policy_manager_deployer.arm() policy_manager_deployer.deploy() policy_agent = policy_manager_deployer.make_agent() web3 = testerchain.interface.w3 print("Estimate gas:") # Pre deposit tokens tx = token_agent.contract.functions.approve(miner_agent.contract_address, constants.MIN_ALLOWED_LOCKED * 5)\ .transact({'from': origin}) testerchain.wait_for_receipt(tx) print("Pre-deposit tokens for 5 owners = " + str( miner_agent.contract.functions.preDeposit( everyone_else[0:5], [int(constants.MIN_ALLOWED_LOCKED)] * 5, [int(constants.MIN_LOCKED_PERIODS)] * 5).estimateGas({'from': origin}))) # Give Ursula and Alice some coins print("Transfer tokens = " + str( token_agent.contract.functions.transfer( ursula1, constants.MIN_ALLOWED_LOCKED * 10).estimateGas({'from': origin}))) tx = token_agent.contract.functions.transfer( ursula1, constants.MIN_ALLOWED_LOCKED * 10).transact({'from': origin}) testerchain.wait_for_receipt(tx) tx = token_agent.contract.functions.transfer( ursula2, constants.MIN_ALLOWED_LOCKED * 10).transact({'from': origin}) testerchain.wait_for_receipt(tx) tx = token_agent.contract.functions.transfer( ursula3, constants.MIN_ALLOWED_LOCKED * 10).transact({'from': origin}) testerchain.wait_for_receipt(tx) # Ursula and Alice give Escrow rights to transfer print("Approving transfer = " + str( token_agent.contract.functions.approve( miner_agent.contract_address, constants.MIN_ALLOWED_LOCKED * 6).estimateGas({'from': ursula1}))) tx = token_agent.contract.functions.approve(miner_agent.contract_address, constants.MIN_ALLOWED_LOCKED * 6)\ .transact({'from': ursula1}) testerchain.wait_for_receipt(tx) tx = token_agent.contract.functions.approve(miner_agent.contract_address, constants.MIN_ALLOWED_LOCKED * 6)\ .transact({'from': ursula2}) testerchain.wait_for_receipt(tx) tx = token_agent.contract.functions.approve(miner_agent.contract_address, constants.MIN_ALLOWED_LOCKED * 6)\ .transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # Ursula and Alice transfer some tokens to the escrow and lock them print("First initial deposit tokens = " + str( miner_agent.contract.functions.deposit( constants.MIN_ALLOWED_LOCKED * 3, int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula1}))) tx = miner_agent.contract.functions.deposit(constants.MIN_ALLOWED_LOCKED * 3, int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second initial deposit tokens = " + str( miner_agent.contract.functions.deposit( constants.MIN_ALLOWED_LOCKED * 3, int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula2}))) tx = miner_agent.contract.functions.deposit(constants.MIN_ALLOWED_LOCKED * 3, int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third initial deposit tokens = " + str( miner_agent.contract.functions.deposit( constants.MIN_ALLOWED_LOCKED * 3, int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula3}))) tx = miner_agent.contract.functions.deposit(constants.MIN_ALLOWED_LOCKED * 3, int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # Wait 1 period and confirm activity testerchain.time_travel(periods=1) print("First confirm activity = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula1}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second confirm activity = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula2}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third confirm activity = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula3}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula3}) testerchain.wait_for_receipt(tx) # Wait 1 period and mint tokens testerchain.time_travel(periods=1) print("First mining (1 stake) = " + str( miner_agent.contract.functions.mint().estimateGas({'from': ursula1}))) tx = miner_agent.contract.functions.mint().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second mining (1 stake) = " + str( miner_agent.contract.functions.mint().estimateGas({'from': ursula2}))) tx = miner_agent.contract.functions.mint().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third/last mining (1 stake) = " + str( miner_agent.contract.functions.mint().estimateGas({'from': ursula3}))) tx = miner_agent.contract.functions.mint().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) print("First confirm activity again = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula1}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second confirm activity again = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula2}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third confirm activity again = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula3}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula3}) testerchain.wait_for_receipt(tx) # Confirm again testerchain.time_travel(periods=1) print("First confirm activity + mint = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula1}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second confirm activity + mint = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula2}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third confirm activity + mint = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula3}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula3}) testerchain.wait_for_receipt(tx) # Get locked tokens print("Getting locked tokens = " + str( miner_agent.contract.functions.getLockedTokens(ursula1).estimateGas())) # Wait 1 period and withdraw tokens testerchain.time_travel(periods=1) print("First withdraw = " + str( miner_agent.contract.functions.withdraw(1).estimateGas( {'from': ursula1}))) tx = miner_agent.contract.functions.withdraw(1).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second withdraw = " + str( miner_agent.contract.functions.withdraw(1).estimateGas( {'from': ursula2}))) tx = miner_agent.contract.functions.withdraw(1).transact({'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third withdraw = " + str( miner_agent.contract.functions.withdraw(1).estimateGas( {'from': ursula3}))) tx = miner_agent.contract.functions.withdraw(1).transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # Wait 1 period and confirm activity testerchain.time_travel(periods=1) print("First confirm activity after downtime = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula1}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second confirm activity after downtime = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula2}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third confirm activity after downtime = " + str(miner_agent.contract.functions.confirmActivity().estimateGas( {'from': ursula3}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula3}) testerchain.wait_for_receipt(tx) # Ursula and Alice deposit some tokens to the escrow again print("First deposit tokens again = " + str( miner_agent.contract.functions.deposit( constants.MIN_ALLOWED_LOCKED * 2, int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula1}))) tx = miner_agent.contract.functions.deposit(constants.MIN_ALLOWED_LOCKED * 2, int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second deposit tokens again = " + str( miner_agent.contract.functions.deposit( constants.MIN_ALLOWED_LOCKED * 2, int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula2}))) tx = miner_agent.contract.functions.deposit(constants.MIN_ALLOWED_LOCKED * 2, int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third deposit tokens again = " + str( miner_agent.contract.functions.deposit( constants.MIN_ALLOWED_LOCKED * 2, int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula3}))) tx = miner_agent.contract.functions.deposit(constants.MIN_ALLOWED_LOCKED * 2, int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # Wait 1 period and mint tokens testerchain.time_travel(periods=1) print("First mining again = " + str( miner_agent.contract.functions.mint().estimateGas({'from': ursula1}))) tx = miner_agent.contract.functions.mint().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second mining again = " + str( miner_agent.contract.functions.mint().estimateGas({'from': ursula2}))) tx = miner_agent.contract.functions.mint().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third/last mining again = " + str( miner_agent.contract.functions.mint().estimateGas({'from': ursula3}))) tx = miner_agent.contract.functions.mint().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # Create policy policy_id_1 = os.urandom(int(constants.POLICY_ID_LENGTH)) policy_id_2 = os.urandom(int(constants.POLICY_ID_LENGTH)) number_of_periods = 10 print("First creating policy (1 node, 10 periods) = " + str( policy_agent.contract.functions.createPolicy( policy_id_1, number_of_periods, 0, [ursula1]).estimateGas( { 'from': alice1, 'value': 10000 }))) tx = policy_agent.contract.functions.createPolicy(policy_id_1, number_of_periods, 0, [ursula1])\ .transact({'from': alice1, 'value': 10000}) testerchain.wait_for_receipt(tx) print("Second creating policy (1 node, 10 periods) = " + str( policy_agent.contract.functions.createPolicy( policy_id_2, number_of_periods, 0, [ursula1]).estimateGas( { 'from': alice1, 'value': 10000 }))) tx = policy_agent.contract.functions.createPolicy(policy_id_2, number_of_periods, 0, [ursula1])\ .transact({'from': alice1, 'value': 10000}) testerchain.wait_for_receipt(tx) # Revoke policy print("Revoking policy = " + str( policy_agent.contract.functions.revokePolicy(policy_id_1).estimateGas( {'from': alice1}))) tx = policy_agent.contract.functions.revokePolicy(policy_id_1).transact( {'from': alice1}) testerchain.wait_for_receipt(tx) tx = policy_agent.contract.functions.revokePolicy(policy_id_2).transact( {'from': alice1}) testerchain.wait_for_receipt(tx) # Create policy with more periods policy_id_1 = os.urandom(int(constants.POLICY_ID_LENGTH)) policy_id_2 = os.urandom(int(constants.POLICY_ID_LENGTH)) policy_id_3 = os.urandom(int(constants.POLICY_ID_LENGTH)) number_of_periods = 100 print("First creating policy (1 node, " + str(number_of_periods) + " periods, first reward) = " + str( policy_agent.contract.functions.createPolicy( policy_id_1, number_of_periods, 50, [ursula2]).estimateGas( { 'from': alice1, 'value': 10050 }))) tx = policy_agent.contract.functions.createPolicy(policy_id_1, number_of_periods, 50, [ursula2])\ .transact({'from': alice1, 'value': 10050}) testerchain.wait_for_receipt(tx) testerchain.time_travel(periods=1) print("Second creating policy (1 node, " + str(number_of_periods) + " periods, first reward) = " + str( policy_agent.contract.functions.createPolicy( policy_id_2, number_of_periods, 50, [ursula2]).estimateGas( { 'from': alice1, 'value': 10050 }))) tx = policy_agent.contract.functions.createPolicy(policy_id_2, number_of_periods, 50, [ursula2])\ .transact({'from': alice1, 'value': 10050}) testerchain.wait_for_receipt(tx) print("Third creating policy (1 node, " + str(number_of_periods) + " periods, first reward) = " + str( policy_agent.contract.functions.createPolicy( policy_id_3, number_of_periods, 50, [ursula1]).estimateGas( { 'from': alice1, 'value': 10050 }))) tx = policy_agent.contract.functions.createPolicy(policy_id_3, number_of_periods, 50, [ursula1])\ .transact({'from': alice1, 'value': 10050}) testerchain.wait_for_receipt(tx) # Mine and revoke policy testerchain.time_travel(periods=10) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula2}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) testerchain.time_travel(periods=1) print("First mining after downtime = " + str( miner_agent.contract.functions.mint().estimateGas({'from': ursula1}))) tx = miner_agent.contract.functions.mint().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second mining after downtime = " + str( miner_agent.contract.functions.mint().estimateGas({'from': ursula2}))) tx = miner_agent.contract.functions.mint().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) testerchain.time_travel(periods=10) print("First revoking policy after downtime = " + str( policy_agent.contract.functions.revokePolicy(policy_id_1).estimateGas( {'from': alice1}))) tx = policy_agent.contract.functions.revokePolicy(policy_id_1).transact( {'from': alice1}) testerchain.wait_for_receipt(tx) print("Second revoking policy after downtime = " + str( policy_agent.contract.functions.revokePolicy(policy_id_2).estimateGas( {'from': alice1}))) tx = policy_agent.contract.functions.revokePolicy(policy_id_2).transact( {'from': alice1}) testerchain.wait_for_receipt(tx) print("Second revoking policy after downtime = " + str( policy_agent.contract.functions.revokePolicy(policy_id_3).estimateGas( {'from': alice1}))) tx = policy_agent.contract.functions.revokePolicy(policy_id_3).transact( {'from': alice1}) testerchain.wait_for_receipt(tx) # Create policy with multiple nodes policy_id_1 = os.urandom(int(constants.POLICY_ID_LENGTH)) policy_id_2 = os.urandom(int(constants.POLICY_ID_LENGTH)) policy_id_3 = os.urandom(int(constants.POLICY_ID_LENGTH)) number_of_periods = 100 print("First creating policy (3 nodes, 100 periods, first reward) = " + str( policy_agent.contract.functions.createPolicy( policy_id_1, number_of_periods, 50, [ursula1, ursula2, ursula3]).estimateGas({ 'from': alice1, 'value': 30150 }))) tx = policy_agent.contract.functions.createPolicy(policy_id_1, number_of_periods, 50, [ursula1, ursula2, ursula3])\ .transact({'from': alice1, 'value': 30150}) testerchain.wait_for_receipt(tx) print("Second creating policy (3 nodes, 100 periods, first reward) = " + str( policy_agent.contract.functions.createPolicy( policy_id_2, number_of_periods, 50, [ursula1, ursula2, ursula3]).estimateGas({ 'from': alice1, 'value': 30150 }))) tx = policy_agent.contract.functions.createPolicy(policy_id_2, number_of_periods, 50, [ursula1, ursula2, ursula3])\ .transact({'from': alice1, 'value': 30150}) testerchain.wait_for_receipt(tx) print("Third creating policy (2 nodes, 100 periods, first reward) = " + str( policy_agent.contract.functions.createPolicy( policy_id_3, number_of_periods, 50, [ursula1, ursula2]).estimateGas({ 'from': alice1, 'value': 20100 }))) tx = policy_agent.contract.functions.createPolicy(policy_id_3, number_of_periods, 50, [ursula1, ursula2])\ .transact({'from': alice1, 'value': 20100}) testerchain.wait_for_receipt(tx) for index in range(5): tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula2}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula3}) testerchain.wait_for_receipt(tx) testerchain.time_travel(periods=1) tx = miner_agent.contract.functions.mint().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.mint().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.mint().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # Check regular deposit print("First deposit tokens = " + str( miner_agent.contract.functions.deposit( int(constants.MIN_ALLOWED_LOCKED), int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula1}))) tx = miner_agent.contract.functions.deposit(int(constants.MIN_ALLOWED_LOCKED), int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second deposit tokens = " + str( miner_agent.contract.functions.deposit( int(constants.MIN_ALLOWED_LOCKED), int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula2}))) tx = miner_agent.contract.functions.deposit(int(constants.MIN_ALLOWED_LOCKED), int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third deposit tokens = " + str( miner_agent.contract.functions.deposit( int(constants.MIN_ALLOWED_LOCKED), int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula3}))) tx = miner_agent.contract.functions.deposit(int(constants.MIN_ALLOWED_LOCKED), int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # ApproveAndCall testerchain.time_travel(periods=1) tx = miner_agent.contract.functions.mint().transact({'from': ursula1}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.mint().transact({'from': ursula2}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.mint().transact({'from': ursula3}) testerchain.wait_for_receipt(tx) print("First approveAndCall = " + str( token_agent.contract.functions.approveAndCall( miner_agent.contract_address, int(constants.MIN_ALLOWED_LOCKED) * 2, web3.toBytes(int(constants.MIN_LOCKED_PERIODS))).estimateGas( {'from': ursula1}))) tx = token_agent.contract.functions.approveAndCall(miner_agent.contract_address, int(constants.MIN_ALLOWED_LOCKED) * 2, web3.toBytes(int(constants.MIN_LOCKED_PERIODS)))\ .transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second approveAndCall = " + str( token_agent.contract.functions.approveAndCall( miner_agent.contract_address, int(constants.MIN_ALLOWED_LOCKED) * 2, web3.toBytes(int(constants.MIN_LOCKED_PERIODS))).estimateGas( {'from': ursula2}))) tx = token_agent.contract.functions.approveAndCall(miner_agent.contract_address, int(constants.MIN_ALLOWED_LOCKED) * 2, web3.toBytes(int(constants.MIN_LOCKED_PERIODS)))\ .transact({'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third approveAndCall = " + str( token_agent.contract.functions.approveAndCall( miner_agent.contract_address, int(constants.MIN_ALLOWED_LOCKED) * 2, web3.toBytes(int(constants.MIN_LOCKED_PERIODS))).estimateGas( {'from': ursula3}))) tx = token_agent.contract.functions.approveAndCall(miner_agent.contract_address, int(constants.MIN_ALLOWED_LOCKED) * 2, web3.toBytes(int(constants.MIN_LOCKED_PERIODS)))\ .transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # Locking tokens testerchain.time_travel(periods=1) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula2}) testerchain.wait_for_receipt(tx) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula3}) testerchain.wait_for_receipt(tx) print("First locking tokens = " + str( miner_agent.contract.functions.lock(int( constants.MIN_ALLOWED_LOCKED), int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula1}))) tx = miner_agent.contract.functions.lock(int(constants.MIN_ALLOWED_LOCKED), int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second locking tokens = " + str( miner_agent.contract.functions.lock(int( constants.MIN_ALLOWED_LOCKED), int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula2}))) tx = miner_agent.contract.functions.lock(int(constants.MIN_ALLOWED_LOCKED), int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula2}) testerchain.wait_for_receipt(tx) print("Third locking tokens = " + str( miner_agent.contract.functions.lock(int( constants.MIN_ALLOWED_LOCKED), int( constants.MIN_LOCKED_PERIODS)).estimateGas({'from': ursula3}))) tx = miner_agent.contract.functions.lock(int(constants.MIN_ALLOWED_LOCKED), int(constants.MIN_LOCKED_PERIODS))\ .transact({'from': ursula3}) testerchain.wait_for_receipt(tx) # Divide stake print("First divide stake = " + str( miner_agent.contract.functions.divideStake( 1, int(constants.MIN_ALLOWED_LOCKED), 2).estimateGas( {'from': ursula1}))) tx = miner_agent.contract.functions.divideStake( 1, int(constants.MIN_ALLOWED_LOCKED), 2).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) print("Second divide stake = " + str( miner_agent.contract.functions.divideStake( 3, int(constants.MIN_ALLOWED_LOCKED), 2).estimateGas( {'from': ursula1}))) tx = miner_agent.contract.functions.divideStake( 3, int(constants.MIN_ALLOWED_LOCKED), 2).transact({'from': ursula1}) testerchain.wait_for_receipt(tx) # Divide almost finished stake testerchain.time_travel(periods=1) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) testerchain.time_travel(periods=1) print("Divide stake (next period is not confirmed) = " + str( miner_agent.contract.functions.divideStake( 0, int(constants.MIN_ALLOWED_LOCKED), 2).estimateGas( {'from': ursula1}))) tx = miner_agent.contract.functions.confirmActivity().transact( {'from': ursula1}) testerchain.wait_for_receipt(tx) print("Divide stake (next period is confirmed) = " + str( miner_agent.contract.functions.divideStake( 0, int(constants.MIN_ALLOWED_LOCKED), 2).estimateGas( {'from': ursula1}))) print("All done!")
def test_run_felix(click_runner, testerchain, agency, deploy_user_input, mock_primary_registry_filepath): clock = Clock() Felix._CLOCK = clock Felix.DISTRIBUTION_INTERVAL = 5 # seconds Felix.DISBURSEMENT_INTERVAL = 0.01 # hours Felix.STAGING_DELAY = 2 # seconds # Main thread (Flask) os.environ['NUCYPHER_FELIX_DB_SECRET'] = INSECURE_DEVELOPMENT_PASSWORD # Simulate "Reconnection" real_attach_provider = BlockchainDeployerInterface._attach_provider cached_blockchain = BlockchainDeployerInterface.reconnect() cached_blockchain.registry.commit(filepath=mock_primary_registry_filepath) def attach_cached_provider(interface, *args, **kwargs): cached_provider = cached_blockchain.provider real_attach_provider(interface, provider=cached_provider) BlockchainDeployerInterface._attach_provider = attach_cached_provider # Mock live contract registry reads EthereumContractRegistry.read = lambda *a, **kw: cached_blockchain.registry.read( ) # Test subproc (Click) envvars = { 'NUCYPHER_KEYRING_PASSWORD': INSECURE_DEVELOPMENT_PASSWORD, 'NUCYPHER_FELIX_DB_SECRET': INSECURE_DEVELOPMENT_PASSWORD, 'FLASK_DEBUG': '1' } # Felix creates a system configuration init_args = ('--debug', 'felix', 'init', '--registry-filepath', mock_primary_registry_filepath, '--checksum-address', testerchain.client.accounts[0], '--config-root', MOCK_CUSTOM_INSTALLATION_PATH_2, '--network', TEMPORARY_DOMAIN, '--no-registry', '--provider-uri', TEST_PROVIDER_URI) result = click_runner.invoke(nucypher_cli, init_args, catch_exceptions=False, env=envvars) assert result.exit_code == 0 configuration_file_location = os.path.join( MOCK_CUSTOM_INSTALLATION_PATH_2, FelixConfiguration.generate_filename()) # Felix Creates a Database db_args = ('--debug', 'felix', 'createdb', '--registry-filepath', mock_primary_registry_filepath, '--config-file', configuration_file_location, '--provider-uri', TEST_PROVIDER_URI) result = click_runner.invoke(nucypher_cli, db_args, catch_exceptions=False, env=envvars) assert result.exit_code == 0 # Felix Runs Web Services def run_felix(): args = ('--debug', 'felix', 'run', '--registry-filepath', mock_primary_registry_filepath, '--config-file', configuration_file_location, '--provider-uri', TEST_PROVIDER_URI, '--dry-run', '--no-registry') run_result = click_runner.invoke(nucypher_cli, args, catch_exceptions=False, env=envvars) assert run_result.exit_code == 0 return run_result # A (mocked) client requests Felix's services def request_felix_landing_page(_result): # Init an equal Felix to the already running one. felix_config = FelixConfiguration.from_configuration_file( filepath=configuration_file_location) felix_config.attach_keyring() felix_config.keyring.unlock(password=INSECURE_DEVELOPMENT_PASSWORD) felix = felix_config.produce() # Make a flask app web_app = felix.make_web_app() test_client = web_app.test_client() # Load the landing page response = test_client.get('/') assert response.status_code == 200 # Register a new recipient response = test_client.post( '/register', data={'address': felix.blockchain.client.accounts[-1]}) assert response.status_code == 200 return def time_travel(_result): clock.advance(amount=60) # Record starting ether balance recipient = testerchain.client.accounts[-1] staker = Staker(checksum_address=recipient, blockchain=testerchain, is_me=True) original_eth_balance = staker.eth_balance # Run the callbacks d = threads.deferToThread(run_felix) d.addCallback(request_felix_landing_page) d.addCallback(time_travel) yield d def confirm_airdrop(_results): recipient = testerchain.client.accounts[-1] staker = Staker(checksum_address=recipient, blockchain=testerchain, is_me=True) assert staker.token_balance == NU(15000, 'NU') # TODO: Airdrop Testnet Ethers? # new_eth_balance = original_eth_balance + testerchain.w3.fromWei(Felix.ETHER_AIRDROP_AMOUNT, 'ether') assert staker.eth_balance == original_eth_balance staged_airdrops = Felix._AIRDROP_QUEUE next_airdrop = staged_airdrops[0] next_airdrop.addCallback(confirm_airdrop) yield next_airdrop
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 deploy(click_config, action, poa, provider_uri, geth, enode, deployer_address, contract_name, allocation_infile, allocation_outfile, registry_infile, registry_outfile, no_compile, amount, recipient_address, config_root, sync, force): """Manage contract and registry deployment""" ETH_NODE = None # # Validate # # Ensure config root exists, because we need a default place to put output files. config_root = config_root or DEFAULT_CONFIG_ROOT if not os.path.exists(config_root): os.makedirs(config_root) # # Connect to Blockchain # if geth: # Spawn geth child process ETH_NODE = NuCypherGethDevnetProcess(config_root=config_root) ETH_NODE.ensure_account_exists(password=click_config.get_password( confirm=True)) ETH_NODE.start() # TODO: Graceful shutdown provider_uri = ETH_NODE.provider_uri # Establish a contract registry from disk if specified registry, registry_filepath = None, (registry_outfile or registry_infile) if registry_filepath is not None: registry = EthereumContractRegistry( registry_filepath=registry_filepath) # Deployment-tuned blockchain connection blockchain = BlockchainDeployerInterface(provider_uri=provider_uri, poa=poa, registry=registry, compiler=SolidityCompiler(), fetch_registry=False, sync_now=sync) # # Deployment Actor # if not deployer_address: for index, address in enumerate(blockchain.client.accounts): click.secho(f"{index} --- {address}") choices = click.IntRange(0, len(blockchain.client.accounts)) deployer_address_index = click.prompt("Select deployer address", default=0, type=choices) deployer_address = blockchain.client.accounts[deployer_address_index] # Verify Address if not force: click.confirm("Selected {} - Continue?".format(deployer_address), abort=True) # TODO: Integrate with Deployer Actor (Character) blockchain.transacting_power = BlockchainPower(blockchain=blockchain, account=deployer_address) deployer = Deployer(blockchain=blockchain, deployer_address=deployer_address) # Verify ETH Balance click.secho(f"\n\nDeployer ETH balance: {deployer.eth_balance}") if deployer.eth_balance == 0: click.secho("Deployer address has no ETH.", fg='red', bold=True) raise click.Abort() if not blockchain.client.is_local: # (~ dev mode; Assume accounts are already unlocked) password = click.prompt("Enter ETH node password", hide_input=True) blockchain.client.unlockAccount(deployer_address, password) # Add ETH Bootnode or Peer if enode: if geth: blockchain.w3.geth.admin.addPeer(enode) click.secho(f"Added ethereum peer {enode}") else: raise NotImplemented # TODO: other backends # # Action switch # if action == 'upgrade': if not contract_name: raise click.BadArgumentUsage( message="--contract-name is required when using --upgrade") existing_secret = click.prompt( 'Enter existing contract upgrade secret', hide_input=True) new_secret = click.prompt('Enter new contract upgrade secret', hide_input=True, confirmation_prompt=True) deployer.upgrade_contract(contract_name=contract_name, existing_plaintext_secret=existing_secret, new_plaintext_secret=new_secret) elif action == 'rollback': existing_secret = click.prompt( 'Enter existing contract upgrade secret', hide_input=True) new_secret = click.prompt('Enter new contract upgrade secret', hide_input=True, confirmation_prompt=True) deployer.rollback_contract(contract_name=contract_name, existing_plaintext_secret=existing_secret, new_plaintext_secret=new_secret) elif action == "contracts": registry_filepath = deployer.blockchain.registry.filepath if os.path.isfile(registry_filepath): click.secho( f"\nThere is an existing contract registry at {registry_filepath}.\n" f"Did you mean 'nucypher-deploy upgrade'?\n", fg='yellow') click.confirm( "Optionally, destroy existing local registry and continue?", abort=True) click.confirm( f"Confirm deletion of contract registry '{registry_filepath}'?", abort=True) os.remove(registry_filepath) # # Deploy Single Contract # if contract_name: # TODO: Handle secret collection for single contract deployment try: deployer_func = deployer.deployers[contract_name] except KeyError: message = f"No such contract {contract_name}. Available contracts are {deployer.deployers.keys()}" click.secho(message, fg='red', bold=True) raise click.Abort() else: # Deploy single contract _txs, _agent = deployer_func() # TODO: Painting for single contract deployment if ETH_NODE: ETH_NODE.stop() return # # Stage Deployment # # Track tx hashes, and new agents __deployment_transactions = dict() __deployment_agents = dict() secrets = click_config.collect_deployment_secrets() click.clear() click.secho(NU_BANNER) w3 = deployer.blockchain.w3 click.secho(f"Current Time ........ {maya.now().iso8601()}") click.secho( f"Web3 Provider ....... {deployer.blockchain.provider_uri}") click.secho( f"Block ............... {deployer.blockchain.client.block_number}") click.secho( f"Gas Price ........... {deployer.blockchain.client.gas_price}") click.secho(f"Deployer Address .... {deployer.checksum_address}") click.secho(f"ETH ................. {deployer.eth_balance}") click.secho( f"Chain ID ............ {deployer.blockchain.client.chain_id}") click.secho( f"Chain Name .......... {deployer.blockchain.client.chain_name}") # Ask - Last chance to gracefully abort if not force: click.secho( "\nDeployment successfully staged. Take a deep breath. \n", fg='green') if click.prompt("Type 'DEPLOY' to continue") != 'DEPLOY': raise click.Abort() # Delay - Last chance to crash and abort click.secho(f"Starting deployment in 3 seconds...", fg='red') time.sleep(1) click.secho(f"2...", fg='yellow') time.sleep(1) click.secho(f"1...", fg='green') time.sleep(1) click.secho(f"Deploying...", bold=True) # # DEPLOY < ------- # txhashes, deployers = deployer.deploy_network_contracts( staker_secret=secrets.staker_secret, policy_secret=secrets.policy_secret, adjudicator_secret=secrets.adjudicator_secret, user_escrow_proxy_secret=secrets.escrow_proxy_secret) # Success __deployment_transactions.update(txhashes) # # Paint # total_gas_used = 0 # TODO: may be faulty for contract_name, transactions in __deployment_transactions.items(): # Paint heading heading = '\n{} ({})'.format( contract_name, deployers[contract_name].contract_address) click.secho(heading, bold=True) click.echo('*' * (42 + 3 + len(contract_name))) for tx_name, txhash in transactions.items(): # Wait for inclusion in the blockchain receipt = deployer.blockchain.w3.eth.waitForTransactionReceipt( txhash) click.secho("OK", fg='green', nl=False, bold=True) # Accumulate gas total_gas_used += int(receipt['gasUsed']) # Paint click.secho(" | {}".format(tx_name), fg='yellow', nl=False) click.secho(" | {}".format(txhash.hex()), fg='yellow', nl=False) click.secho(" ({} gas)".format(receipt['cumulativeGasUsed'])) click.secho("Block #{} | {}\n".format( receipt['blockNumber'], receipt['blockHash'].hex())) # Paint outfile paths click.secho( "Cumulative Gas Consumption: {} gas".format(total_gas_used), bold=True, fg='blue') registry_outfile = deployer.blockchain.registry.filepath click.secho('Generated registry {}'.format(registry_outfile), bold=True, fg='blue') # Save transaction metadata receipts_filepath = deployer.save_deployment_receipts( transactions=__deployment_transactions) click.secho(f"Saved deployment receipts to {receipts_filepath}", fg='blue', bold=True) elif action == "allocations": if not allocation_infile: allocation_infile = click.prompt("Enter allocation data filepath") click.confirm("Continue deploying and allocating?", abort=True) deployer.deploy_beneficiaries_from_file( allocation_data_filepath=allocation_infile, allocation_outfile=allocation_outfile) elif action == "transfer": token_agent = NucypherTokenAgent(blockchain=blockchain) click.confirm( f"Transfer {amount} from {token_agent.contract_address} to {recipient_address}?", abort=True) txhash = token_agent.transfer( amount=amount, sender_address=token_agent.contract_address, target_address=recipient_address) click.secho(f"OK | {txhash}") elif action == "destroy-registry": registry_filepath = deployer.blockchain.registry.filepath click.confirm( f"Are you absolutely sure you want to destroy the contract registry at {registry_filepath}?", abort=True) os.remove(registry_filepath) click.secho(f"Successfully destroyed {registry_filepath}", fg='red') else: raise click.BadArgumentUsage(message=f"Unknown action '{action}'") if ETH_NODE: ETH_NODE.stop()
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}'")