Exemple #1
0
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]
Exemple #2
0
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
Exemple #3
0
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
Exemple #4
0
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
Exemple #5
0
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_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]
Exemple #8
0
def deploy(action, poa, etherscan, provider_uri, gas, deployer_address,
           contract_name, allocation_infile, allocation_outfile,
           registry_infile, registry_outfile, amount, recipient_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.
    status                 Echo owner information and bare contract metadata.
    transfer-tokens        Transfer tokens to another 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)

    #
    # 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 Registry
    #

    # Establish a contract registry from disk if specified
    registry_filepath = registry_outfile or registry_infile
    if dev:
        # TODO: Need a way to detect a geth--dev registry filepath here. (then deprecate the --dev flag)
        registry_filepath = os.path.join(DEFAULT_CONFIG_ROOT,
                                         'dev_contract_registry.json')
    registry = EthereumContractRegistry(registry_filepath=registry_filepath)
    emitter.echo(f"Using contract registry filepath {registry.filepath}")

    #
    # Connect to Blockchain
    #

    blockchain = BlockchainDeployerInterface(provider_uri=provider_uri,
                                             poa=poa,
                                             registry=registry)
    try:
        blockchain.connect(fetch_registry=False, sync_now=False)
    except BlockchainDeployerInterface.ConnectionFailed as e:
        emitter.echo(str(e), color='red', bold=True)
        raise click.Abort()

    #
    # Make Authenticated Deployment Actor
    #

    # Verify Address & collect password
    if not deployer_address:
        prompt = "Select deployer account"
        deployer_address = select_client_account(emitter=emitter,
                                                 blockchain=blockchain,
                                                 prompt=prompt)

    if not force:
        click.confirm("Selected {} - Continue?".format(deployer_address),
                      abort=True)

    password = None
    if not hw_wallet and not blockchain.client.is_local:
        password = get_client_password(checksum_address=deployer_address)

    # Produce Actor
    DEPLOYER = DeployerActor(blockchain=blockchain,
                             client_password=password,
                             deployer_address=deployer_address)

    # Verify ETH Balance
    emitter.echo(f"\n\nDeployer ETH balance: {DEPLOYER.eth_balance}")
    if DEPLOYER.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)
        DEPLOYER.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)
        DEPLOYER.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 = DEPLOYER.deployers[contract_name]
            except KeyError:
                message = f"No such contract {contract_name}. Available contracts are {DEPLOYER.deployers.keys()}"
                emitter.echo(message, color='red', bold=True)
                raise click.Abort()
            else:
                emitter.echo(f"Deploying {contract_name}")
                if contract_deployer._upgradeable:
                    secret = DEPLOYER.collect_deployment_secret(
                        deployer=contract_deployer)
                    receipts, agent = DEPLOYER.deploy_contract(
                        contract_name=contract_name, plaintext_secret=secret)
                else:
                    receipts, agent = DEPLOYER.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=blockchain.client.chain_name,
                    open_in_browser=etherscan)
            return  # Exit

        #
        # Deploy Automated Series (Create Registry)
        #

        # Confirm filesystem registry writes.
        registry_filepath = DEPLOYER.blockchain.registry.filepath
        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 = DEPLOYER.collect_deployment_secrets()
        paint_staged_deployment(deployer=DEPLOYER, emitter=emitter)

        # Confirm Trigger Deployment
        if not actions.confirm_deployment(emitter=emitter, deployer=DEPLOYER):
            raise click.Abort()

        # Delay - Last chance to abort via KeyboardInterrupt
        paint_deployment_delay(emitter=emitter)

        # Execute Deployment
        deployment_receipts = DEPLOYER.deploy_network_contracts(
            secrets=secrets,
            emitter=emitter,
            interactive=not force,
            etherscan=etherscan)

        # Paint outfile paths
        registry_outfile = DEPLOYER.blockchain.registry.filepath
        emitter.echo('Generated registry {}'.format(registry_outfile),
                     bold=True,
                     color='blue')

        # Save transaction metadata
        receipts_filepath = DEPLOYER.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)
        DEPLOYER.deploy_beneficiaries_from_file(
            allocation_data_filepath=allocation_infile,
            allocation_outfile=allocation_outfile)
        return  # Exit

    elif action == "transfer":
        token_agent = NucypherTokenAgent(blockchain=blockchain)
        missing_options = list()
        if recipient_address is None:
            missing_options.append("--recipient-address")
        if amount is None:
            missing_options.append("--amount")
        if missing_options:
            raise click.BadOptionUsage(
                f"Need {' and '.join(missing_options)} to transfer tokens.")

        click.confirm(
            f"Transfer {amount} from {deployer_address} to {recipient_address}?",
            abort=True)
        receipt = token_agent.transfer(amount=amount,
                                       sender_address=deployer_address,
                                       target_address=recipient_address)
        emitter.echo(f"OK | Receipt: {receipt['transactionHash'].hex()}")
        return  # Exit

    else:
        raise click.BadArgumentUsage(message=f"Unknown action '{action}'")
Exemple #9
0
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,
           device,
           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())

    blockchain.connect(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)

    password = None
    if not device and not blockchain.client.is_local:
        password = get_password(confirm=False)

    deployer = Deployer(blockchain=blockchain,
                        client_password=password,
                        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()

    # 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}")

    else:
        raise click.BadArgumentUsage(message=f"Unknown action '{action}'")

    if ETH_NODE:
        ETH_NODE.stop()
Exemple #10
0
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
        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,
                                               economics=economics)
        token_deployer.deploy()

        staking_escrow_deployer = StakingEscrowDeployer(
            registry=registry, deployer_address=origin, economics=economics)
        deploy_earliest_contract(blockchain_interface, staking_escrow_deployer)

        policy_manager_deployer = None
        if test_staking_escrow or test_policy_manager:
            policy_manager_deployer = PolicyManagerDeployer(
                registry=registry,
                deployer_address=origin,
                economics=economics)
            deploy_earliest_contract(blockchain_interface,
                                     policy_manager_deployer)

        adjudicator_deployer = None
        if test_staking_escrow or test_adjudicator:
            adjudicator_deployer = AdjudicatorDeployer(registry=registry,
                                                       deployer_address=origin,
                                                       economics=economics)
            deploy_earliest_contract(blockchain_interface,
                                     adjudicator_deployer)

        if test_staking_escrow:
            worklock_deployer = WorklockDeployer(registry=registry,
                                                 deployer_address=origin,
                                                 economics=economics)
            worklock_deployer.deploy()
            # TODO prepare at least one staker before calling upgrade
            staking_escrow_deployer.upgrade(contract_version="latest",
                                            confirmations=0)

        if test_policy_manager:
            policy_manager_deployer.upgrade(contract_version="latest",
                                            confirmations=0)

        if test_adjudicator:
            adjudicator_deployer.upgrade(contract_version="latest",
                                         confirmations=0)

    finally:
        # Unregister interface  # TODO: Move to method?
        with contextlib.suppress(KeyError):
            del BlockchainInterfaceFactory._interfaces[provider_uri]
Exemple #11
0
def test_deployer_interface_multiversion_contract():

    # Prepare compiler
    base_dir = TEST_MULTIVERSION_CONTRACTS
    v1_dir, v2_dir = base_dir / 'v1', base_dir / 'v2'

    # TODO: Check type of sources
    # I am a contract administrator and I an compiling a new updated version of an existing contract...
    # Represents "Manually hardcoding" a new source directory on BlockchainDeployerInterface.SOURCES.
    BlockchainDeployerInterface.SOURCES = (SourceBundle(base_path=v1_dir),
                                           SourceBundle(base_path=v2_dir))

    # Prepare chain
    BlockchainInterfaceFactory._interfaces.clear()
    blockchain_interface = BlockchainDeployerInterface(
        provider_uri='tester://pyevm', gas_strategy='free')
    blockchain_interface.connect()
    BlockchainInterfaceFactory.register_interface(
        interface=blockchain_interface)  # Lets this test run in isolation

    origin = blockchain_interface.client.accounts[0]
    transacting_power = TransactingPower(
        password=INSECURE_DEVELOPMENT_PASSWORD,
        signer=Web3Signer(blockchain_interface.client),
        account=origin)

    # 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(
        transacting_power=transacting_power,
        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(
        transacting_power=transacting_power,
        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(
        transacting_power=transacting_power,
        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(
        transacting_power=transacting_power,
        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(
        transacting_power=transacting_power,
        registry=registry,
        contract_name=contract_name)
    assert contract.version == "v1.2.3"
    assert contract.functions.VERSION().call() == 2
Exemple #12
0
def test_upgradeability(temp_dir_path, token_economics):
    # 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
    blockchain_interface = BlockchainDeployerInterface(
        provider_uri='tester://pyevm/2', compiler=solidity_compiler)
    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,
                             secret=STAKING_ESCROW_DEPLOYMENT_SECRET)
    if test_staking_escrow:
        upgrade_to_latest_contract(staking_escrow_deployer,
                                   secret=STAKING_ESCROW_DEPLOYMENT_SECRET)

    if test_policy_manager:
        policy_manager_deployer = PolicyManagerDeployer(
            registry=registry, deployer_address=origin)
        deploy_earliest_contract(blockchain_interface,
                                 policy_manager_deployer,
                                 secret=POLICY_MANAGER_DEPLOYMENT_SECRET)
        upgrade_to_latest_contract(policy_manager_deployer,
                                   secret=POLICY_MANAGER_DEPLOYMENT_SECRET)

    if test_adjudicator:
        adjudicator_deployer = AdjudicatorDeployer(registry=registry,
                                                   deployer_address=origin)
        deploy_earliest_contract(blockchain_interface,
                                 adjudicator_deployer,
                                 secret=ADJUDICATOR_DEPLOYMENT_SECRET)
        upgrade_to_latest_contract(adjudicator_deployer,
                                   secret=ADJUDICATOR_DEPLOYMENT_SECRET)