コード例 #1
0
def contracts(general_config, actor_options, bare, gas, ignore_deployed):
    """
    Compile and deploy contracts.
    """
    # Init

    emitter = general_config.emitter
    ADMINISTRATOR, _, deployer_interface, local_registry = actor_options.create_actor(
        emitter)

    #
    # Deploy Single Contract (Amend Registry)
    #
    contract_name = actor_options.contract_name
    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()

        # Deploy
        emitter.echo(f"Deploying {contract_name}")
        if contract_deployer._upgradeable and not bare:
            # NOTE: Bare deployments do not engage the proxy contract
            secret = ADMINISTRATOR.collect_deployment_secret(
                deployer=contract_deployer)
            receipts, agent = ADMINISTRATOR.deploy_contract(
                contract_name=contract_name,
                plaintext_secret=secret,
                gas_limit=gas,
                bare=bare,
                ignore_deployed=ignore_deployed)
        else:
            # Non-Upgradeable or Bare
            receipts, agent = ADMINISTRATOR.deploy_contract(
                contract_name=contract_name,
                gas_limit=gas,
                bare=bare,
                ignore_deployed=ignore_deployed)

        # Report
        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=actor_options.etherscan)
        return  # Exit

    #
    # Deploy Automated Series (Create Registry)
    #

    # Confirm filesystem registry writes.
    if os.path.isfile(local_registry.filepath):
        emitter.echo(
            f"\nThere is an existing contract registry at {local_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(local_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 actor_options.force,
        etherscan=actor_options.etherscan,
        ignore_deployed=ignore_deployed)

    # Paint outfile paths
    registry_outfile = local_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)
コード例 #2
0
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}'")
コード例 #3
0
ファイル: actors.py プロジェクト: existentializm/nucypher
    def deploy_beneficiary_contracts(
        self,
        allocations: List[Dict[str, Union[str, int]]],
        allocation_outfile: str = None,
        allocation_registry: AllocationRegistry = None,
        crash_on_failure: bool = True,
        interactive: bool = True,
        emitter: StdoutEmitter = None,
    ) -> Dict[str, dict]:
        """
        The allocation file is a JSON file containing a list of allocations. Each allocation has a:
          * 'beneficiary_address': Checksum address of the beneficiary
          * 'name': User-friendly name of the beneficiary (Optional)
          * 'amount': Amount of tokens locked, in NuNits
          * 'duration_seconds': Lock duration expressed in seconds

        Example allocation file:

        [ {'beneficiary_address': '0xdeadbeef', 'name': 'H. E. Pennypacker', 'amount': 100, 'duration_seconds': 31536000},
          {'beneficiary_address': '0xabced120', 'amount': 133432, 'duration_seconds': 31536000},
          {'beneficiary_address': '0xf7aefec2', 'amount': 999, 'duration_seconds': 31536000}]

        """

        if interactive and not emitter:
            raise ValueError(
                "'emitter' is a required keyword argument when interactive is True."
            )

        if allocation_registry and allocation_outfile:
            raise self.ActorError(
                "Pass either allocation registry or allocation_outfile, not both."
            )
        if allocation_registry is None:
            allocation_registry = AllocationRegistry(
                filepath=allocation_outfile)

        if emitter:
            paint_input_allocation_file(emitter, allocations)

        if interactive:
            click.confirm("Continue with the allocation process?", abort=True)

        total_to_allocate = NU.from_nunits(
            sum(allocation['amount'] for allocation in allocations))
        balance = ContractAgency.get_agent(NucypherTokenAgent,
                                           self.registry).get_balance(
                                               self.deployer_address)
        if balance < total_to_allocate:
            raise ValueError(
                f"Not enough tokens to allocate. We need at least {total_to_allocate}."
            )

        allocation_receipts, failed, allocated = dict(), list(), list()
        total_deployment_transactions = len(allocations) * 4

        # Create an allocation template file, containing the allocation contract ABI and placeholder values
        # for the beneficiary and contract addresses. This file will be shared with all allocation users.
        empty_allocation_escrow_deployer = PreallocationEscrowDeployer(
            registry=self.registry)
        allocation_contract_abi = empty_allocation_escrow_deployer.get_contract_abi(
        )
        allocation_template = {
            "BENEFICIARY_ADDRESS":
            ["ALLOCATION_CONTRACT_ADDRESS", allocation_contract_abi]
        }

        parent_path = Path(allocation_registry.filepath
                           ).parent  # Use same folder as allocation registry
        template_filename = IndividualAllocationRegistry.REGISTRY_NAME
        template_filepath = os.path.join(parent_path, template_filename)
        AllocationRegistry(filepath=template_filepath).write(
            registry_data=allocation_template)
        if emitter:
            emitter.echo(
                f"Saved allocation template file to {template_filepath}",
                color='blue',
                bold=True)

        # Deploy each allocation contract
        with click.progressbar(length=total_deployment_transactions,
                               label="Allocation progress",
                               show_eta=False) as bar:
            bar.short_limit = 0
            for allocation in allocations:

                # TODO: Check if allocation already exists in allocation registry

                beneficiary = allocation['beneficiary_address']
                name = allocation.get('name', 'No name provided')

                if interactive:
                    click.pause(
                        info=f"\nPress any key to continue with allocation for "
                        f"beneficiary {beneficiary} ({name})")

                if emitter:
                    emitter.echo(
                        f"\nDeploying PreallocationEscrow contract for beneficiary {beneficiary} ({name})..."
                    )
                    bar._last_line = None
                    bar.render_progress()

                deployer = self.deploy_preallocation_escrow(
                    allocation_registry=allocation_registry, progress=bar)

                amount = allocation['amount']
                duration = allocation['duration_seconds']
                try:
                    receipts = deployer.deliver(
                        value=amount,
                        duration=duration,
                        beneficiary_address=beneficiary,
                        progress=bar)
                except TransactionFailed as e:
                    if crash_on_failure:
                        raise
                    self.log.debug(
                        f"Failed allocation transaction for {NU.from_nunits(amount)} to {beneficiary}: {e}"
                    )
                    failed.append(allocation)
                    continue

                else:
                    allocation_receipts[beneficiary] = receipts
                    allocation_contract_address = deployer.contract_address
                    self.log.info(
                        f"Created {deployer.contract_name} contract at {allocation_contract_address} "
                        f"for beneficiary {beneficiary}.")
                    allocated.append((allocation, allocation_contract_address))

                    # Create individual allocation file
                    individual_allocation_filename = f'allocation-{beneficiary}.json'
                    individual_allocation_filepath = os.path.join(
                        parent_path, individual_allocation_filename)
                    individual_allocation_file_data = {
                        'beneficiary_address': beneficiary,
                        'contract_address': allocation_contract_address
                    }
                    with open(individual_allocation_filepath, 'w') as outfile:
                        json.dump(individual_allocation_file_data, outfile)

                    if emitter:
                        blockchain = BlockchainInterfaceFactory.get_interface()
                        paint_contract_deployment(
                            contract_name=deployer.contract_name,
                            receipts=receipts,
                            contract_address=deployer.contract_address,
                            emitter=emitter,
                            chain_name=blockchain.client.chain_name,
                            open_in_browser=False)
                        emitter.echo(
                            f"Saved individual allocation file to {individual_allocation_filepath}",
                            color='blue',
                            bold=True)

            if emitter:
                paint_deployed_allocations(emitter, allocated, failed)

            csv_filename = f'allocations-{self.deployer_address[:6]}-{maya.now().epoch}.csv'
            csv_filepath = os.path.join(parent_path, csv_filename)
            write_deployed_allocations_to_csv(csv_filepath, allocated, failed)
            if emitter:
                emitter.echo(f"Saved allocation summary CSV to {csv_filepath}",
                             color='blue',
                             bold=True)

            if failed:
                # TODO: More with these failures: send to isolated logfile, and reattempt
                self.log.critical(
                    f"FAILED TOKEN ALLOCATION - {len(failed)} allocations failed."
                )

        return allocation_receipts
コード例 #4
0
ファイル: actors.py プロジェクト: existentializm/nucypher
    def deploy_network_contracts(self,
                                 secrets: dict,
                                 interactive: bool = True,
                                 emitter: StdoutEmitter = None,
                                 etherscan: bool = False) -> dict:
        """

        :param secrets: Contract upgrade secrets dictionary
        :param interactive: If True, wait for keypress after each contract deployment
        :param emitter: A console output emitter instance. If emitter is None, no output will be echoed to the console.
        :param etherscan: Open deployed contracts in Etherscan
        :return: Returns a dictionary of deployment receipts keyed by contract name
        """

        if interactive and not emitter:
            raise ValueError(
                "'emitter' is a required keyword argument when interactive is True."
            )

        deployment_receipts = dict()
        gas_limit = None  # TODO: Gas management

        # deploy contracts
        total_deployment_transactions = 0
        for deployer_class in self.deployer_classes:
            total_deployment_transactions += len(
                deployer_class.deployment_steps)

        first_iteration = True
        with click.progressbar(length=total_deployment_transactions,
                               label="Deployment progress",
                               show_eta=False) as bar:
            bar.short_limit = 0
            for deployer_class in self.deployer_classes:
                if interactive and not first_iteration:
                    click.pause(
                        info=
                        f"\nPress any key to continue with deployment of {deployer_class.contract_name}"
                    )

                if emitter:
                    emitter.echo(
                        f"\nDeploying {deployer_class.contract_name} ...")
                    bar._last_line = None
                    bar.render_progress()

                if deployer_class in self.standard_deployer_classes:
                    receipts, deployer = self.deploy_contract(
                        contract_name=deployer_class.contract_name,
                        gas_limit=gas_limit,
                        progress=bar)
                else:
                    receipts, deployer = self.deploy_contract(
                        contract_name=deployer_class.contract_name,
                        plaintext_secret=secrets[deployer_class.contract_name],
                        gas_limit=gas_limit,
                        progress=bar)

                if emitter:
                    blockchain = BlockchainInterfaceFactory.get_interface()
                    paint_contract_deployment(
                        contract_name=deployer_class.contract_name,
                        receipts=receipts,
                        contract_address=deployer.contract_address,
                        emitter=emitter,
                        chain_name=blockchain.client.chain_name,
                        open_in_browser=etherscan)

                deployment_receipts[deployer_class.contract_name] = receipts
                first_iteration = False

        return deployment_receipts
コード例 #5
0
ファイル: deploy.py プロジェクト: y3v63n/nucypher
def contracts(general_config, actor_options, mode, activate, gas, ignore_deployed, confirmations, parameters):
    """
    Compile and deploy contracts.
    """
    # Init

    emitter = general_config.emitter
    ADMINISTRATOR, _, deployer_interface, local_registry = actor_options.create_actor(emitter)
    chain_name = deployer_interface.client.chain_name

    deployment_parameters = {}
    if parameters:
        with open(parameters) as json_file:
            deployment_parameters = json.load(json_file)

    #
    # Deploy Single Contract (Amend Registry)
    #
    contract_name = actor_options.contract_name
    deployment_mode = constants.__getattr__(mode.upper())  # TODO: constant sorrow
    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()

        if activate:
            # For the moment, only StakingEscrow can be activated
            staking_escrow_deployer = contract_deployer_class(registry=ADMINISTRATOR.registry,
                                                              deployer_address=ADMINISTRATOR.deployer_address)
            if contract_name != STAKING_ESCROW_CONTRACT_NAME or not staking_escrow_deployer.ready_to_activate:
                raise click.BadOptionUsage(option_name="--activate",
                                           message=f"You can only activate an idle instance of {STAKING_ESCROW_CONTRACT_NAME}")

            click.confirm(f"Activate {STAKING_ESCROW_CONTRACT_NAME} at "
                          f"{staking_escrow_deployer._get_deployed_contract().address}?", abort=True)

            receipts = staking_escrow_deployer.activate()
            for tx_name, receipt in receipts.items():
                paint_receipt_summary(emitter=emitter,
                                      receipt=receipt,
                                      chain_name=chain_name,
                                      transaction_type=tx_name)
            return  # Exit

        # Deploy
        emitter.echo(f"Deploying {contract_name}")
        receipts, agent = ADMINISTRATOR.deploy_contract(contract_name=contract_name,
                                                        gas_limit=gas,
                                                        deployment_mode=deployment_mode,
                                                        ignore_deployed=ignore_deployed,
                                                        confirmations=confirmations,
                                                        deployment_parameters=deployment_parameters)

        # Report
        paint_contract_deployment(contract_name=contract_name,
                                  contract_address=agent.contract_address,
                                  receipts=receipts,
                                  emitter=emitter,
                                  chain_name=chain_name,
                                  open_in_browser=actor_options.etherscan)
        return  # Exit

    #
    # Deploy Automated Series (Create Registry)
    #
    if deployment_mode is not FULL:
        raise click.BadOptionUsage(option_name='--mode',
                                   message="Only 'full' mode is supported when deploying all network contracts")

    # Confirm filesystem registry writes.
    if os.path.isfile(local_registry.filepath):
        emitter.echo(f"\nThere is an existing contract registry at {local_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(local_registry.filepath)

    # Stage Deployment
    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(emitter=emitter,
                                                                 interactive=not actor_options.force,
                                                                 etherscan=actor_options.etherscan,
                                                                 ignore_deployed=ignore_deployed)

    # Paint outfile paths
    registry_outfile = local_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)
コード例 #6
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}'")
コード例 #7
0
ファイル: deploy.py プロジェクト: itsencrypted/nucypher
def contracts(  # Admin Actor Options
        provider_uri,
        contract_name,
        config_root,
        poa,
        force,
        etherscan,
        hw_wallet,
        deployer_address,
        registry_infile,
        registry_outfile,
        dev,

        # Other
        bare,
        gas):
    """
    Compile and deploy contracts.
    """
    # Init
    emitter = StdoutEmitter()
    _ensure_config_root(config_root)
    deployer_interface = _initialize_blockchain(poa, provider_uri)

    # Warnings
    _pre_launch_warnings(emitter, etherscan, hw_wallet)

    #
    # Make Authenticated Deployment Actor
    #
    ADMINISTRATOR, deployer_address, local_registry = _make_authenticated_deployment_actor(
        emitter, provider_uri, deployer_address, deployer_interface,
        contract_name, registry_infile, registry_outfile, hw_wallet, dev,
        force)

    #
    # 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()

        # Deploy
        emitter.echo(f"Deploying {contract_name}")
        if contract_deployer._upgradeable and not bare:
            # NOTE: Bare deployments do not engage the proxy contract
            secret = ADMINISTRATOR.collect_deployment_secret(
                deployer=contract_deployer)
            receipts, agent = ADMINISTRATOR.deploy_contract(
                contract_name=contract_name,
                plaintext_secret=secret,
                gas_limit=gas,
                bare=bare)
        else:
            # Non-Upgradeable or Bare
            receipts, agent = ADMINISTRATOR.deploy_contract(
                contract_name=contract_name, gas_limit=gas, bare=bare)

        # Report
        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(local_registry.filepath):
        emitter.echo(
            f"\nThere is an existing contract registry at {local_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(local_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 = local_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)