예제 #1
0
파일: deploy.py 프로젝트: y3v63n/nucypher
def upgrade(general_config, actor_options, retarget, target_address, ignore_deployed, multisig):
    """
    Upgrade NuCypher existing proxy contract deployments.
    """
    # Init
    emitter = general_config.emitter

    ADMINISTRATOR, _, _, registry = actor_options.create_actor(emitter, is_multisig=bool(multisig))  # FIXME: Workaround for building MultiSig TXs

    contract_name = actor_options.contract_name
    if not contract_name:
        raise click.BadArgumentUsage(message="--contract-name is required when using --upgrade")

    if multisig:
        if not target_address:
            raise click.BadArgumentUsage(message="--multisig requires using --target-address.")
        if not actor_options.force:
            click.confirm(f"Confirm building a re-target transaction for {contract_name}'s proxy to {target_address}?",
                          abort=True)
        transaction = ADMINISTRATOR.retarget_proxy(contract_name=contract_name,
                                                   target_address=target_address,
                                                   just_build_transaction=True)

        trustee_address = select_client_account(emitter=emitter,
                                                prompt="Select trustee address",
                                                provider_uri=actor_options.provider_uri,
                                                show_balances=False)

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

        trustee = Trustee(registry=registry, checksum_address=trustee_address)
        transaction_proposal = trustee.create_transaction_proposal(transaction)

        emitter.message(f"Transaction to retarget {contract_name} proxy to {target_address} was built:", color='green')
        paint_multisig_proposed_transaction(emitter, transaction_proposal)  # TODO: Show decoded function too

        filepath = f'proposal-{trustee.multisig_agent.contract_address[:8]}-TX-{transaction_proposal.nonce}.json'
        transaction_proposal.write(filepath=filepath)
        emitter.echo(f"Saved proposal to {filepath}", color='blue', bold=True)

    elif retarget:
        if not target_address:
            raise click.BadArgumentUsage(message="--target-address is required when using --retarget")
        if not actor_options.force:
            click.confirm(f"Confirm re-target {contract_name}'s proxy to {target_address}?", abort=True)
        receipt = ADMINISTRATOR.retarget_proxy(contract_name=contract_name,
                                               target_address=target_address)
        emitter.message(f"Successfully re-targeted {contract_name} proxy to {target_address}", color='green')
        paint_receipt_summary(emitter=emitter, receipt=receipt)
    else:
        if not actor_options.force:
            click.confirm(f"Confirm deploy new version of {contract_name} and retarget proxy?", abort=True)
        receipts = ADMINISTRATOR.upgrade_contract(contract_name=contract_name,
                                                  ignore_deployed=ignore_deployed)
        emitter.message(f"Successfully deployed and upgraded {contract_name}", color='green')
        for name, receipt in receipts.items():
            paint_receipt_summary(emitter=emitter, receipt=receipt)
예제 #2
0
 def __create_trustee(self, registry, transacting: bool = False) -> Trustee:
     client_password = None
     is_clef = ClefSigner.is_valid_clef_uri(self.signer_uri)
     if transacting and not self.hw_wallet and not is_clef:
         client_password = get_client_password(checksum_address=self.checksum_address)
     trustee = Trustee(checksum_address=self.checksum_address, registry=registry, client_password=client_password)
     return trustee
예제 #3
0
 def __create_trustee(self, registry, transacting: bool = False) -> Trustee:
     client_password = None
     if transacting and not self.hw_wallet:
         client_password = get_client_password(
             checksum_address=self.checksum_address)
     trustee = Trustee(checksum_address=self.checksum_address,
                       registry=registry,
                       client_password=client_password)
     return trustee
예제 #4
0
def upgrade(general_config, actor_options, retarget, target_address, ignore_deployed, multisig, confirmations):
    """Upgrade NuCypher existing proxy contract deployments."""

    #
    # Setup
    #

    emitter = general_config.emitter
    ADMINISTRATOR, deployer_address, blockchain, local_registry = actor_options.create_actor(emitter, is_multisig=bool(multisig))  # FIXME: Workaround for building MultiSig TXs | NRN

    #
    # Pre-flight
    #

    contract_name = actor_options.contract_name
    if not contract_name:
        raise click.BadArgumentUsage(message="--contract-name is required when using --upgrade")

    try:
        # Check contract name exists
        Deployer = ADMINISTRATOR.deployers[contract_name]
    except KeyError:
        message = UNKNOWN_CONTRACT_NAME.format(contract_name=contract_name, constants=ADMINISTRATOR.deployers.keys())
        emitter.echo(message, color='red', bold=True)
        raise click.Abort()
    deployer = Deployer(registry=local_registry)

    # Check deployer address is owner
    if Deployer._ownable and deployer_address != deployer.owner:  # blockchain read
        emitter.echo(DEPLOYER_IS_NOT_OWNER.format(deployer_address=deployer_address,
                                                  contract_name=contract_name,
                                                  agent=deployer.make_agent()))
        raise click.Abort()
    else:
        emitter.echo('✓ Verified deployer address as contract owner', color='green')

    #
    # Business
    #

    if multisig:
        if not target_address:
            raise click.BadArgumentUsage(message="--multisig requires using --target-address.")
        if not actor_options.force:
            click.confirm(CONFIRM_BUILD_RETARGET_TRANSACTION.format(contract_name=contract_name,
                                                                    target_address=target_address), abort=True)
        transaction = ADMINISTRATOR.retarget_proxy(contract_name=contract_name,
                                                   target_address=target_address,
                                                   just_build_transaction=True,
                                                   confirmations=confirmations)

        trustee_address = select_client_account(emitter=emitter,
                                                prompt="Select trustee address",
                                                provider_uri=actor_options.provider_uri,
                                                show_eth_balance=False,
                                                show_nu_balance=False,
                                                show_staking=False)

        if not actor_options.force:
            click.confirm(CONFIRM_SELECTED_ACCOUNT.format(address=trustee_address), abort=True)

        trustee = Trustee(registry=local_registry, checksum_address=trustee_address)
        transaction_proposal = trustee.create_transaction_proposal(transaction)

        message = SUCCESSFUL_RETARGET_TX_BUILT.format(contract_name=contract_name, target_address=target_address)
        emitter.message(message, color='green')
        paint_multisig_proposed_transaction(emitter, transaction_proposal)  # TODO: Show decoded function too

        filepath = f'proposal-{trustee.multisig_agent.contract_address[:8]}-TX-{transaction_proposal.nonce}.json'
        transaction_proposal.write(filepath=filepath)
        emitter.echo(SUCCESSFUL_SAVE_MULTISIG_TX_PROPOSAL.format(filepath=filepath), color='blue', bold=True)
        return  # Exit

    elif retarget:
        if not target_address:
            raise click.BadArgumentUsage(message="--target-address is required when using --retarget")
        if not actor_options.force:
            click.confirm(CONFIRM_RETARGET.format(contract_name=contract_name, target_address=target_address), abort=True)
        receipt = ADMINISTRATOR.retarget_proxy(contract_name=contract_name,target_address=target_address, confirmations=confirmations)
        message = SUCCESSFUL_RETARGET.format(contract_name=contract_name, target_address=target_address)
        emitter.message(message, color='green')
        paint_receipt_summary(emitter=emitter, receipt=receipt)
        return  # Exit

    else:
        github_registry = establish_deployer_registry(emitter=emitter,
                                                      download_registry=True,
                                                      network=actor_options.network)
        if not actor_options.force:

            # Check for human verification of versioned upgrade details
            click.confirm(CONFIRM_BEGIN_UPGRADE.format(contract_name=contract_name), abort=True)
            if deployer._ownable:  # Only ownable + upgradeable contracts apply
                verify_upgrade_details(blockchain=blockchain,
                                       registry=github_registry,
                                       deployer=deployer)

        # Success
        receipts = ADMINISTRATOR.upgrade_contract(contract_name=contract_name,
                                                  ignore_deployed=ignore_deployed,
                                                  confirmations=confirmations)
        emitter.message(SUCCESSFUL_UPGRADE.format(contract_name=contract_name), color='green')

        for name, receipt in receipts.items():
            paint_receipt_summary(emitter=emitter, receipt=receipt)
        emitter.echo(REGISTRY_PUBLICATION_HINT.format(contract_name=contract_name,
                                                      local_registry=local_registry,
                                                      network=actor_options.network), color='blue')
        emitter.echo(ETHERSCAN_VERIFY_HINT.format(solc_version=SOLIDITY_COMPILER_VERSION), color='blue')
        return  # Exit
예제 #5
0
def test_trustee_proposes_multisig_management_operations(
        testerchain, test_registry):
    origin = testerchain.etherbase_account
    multisig_deployer = MultiSigDeployer(deployer_address=origin,
                                         registry=test_registry)

    threshold = 2
    owners = testerchain.unassigned_accounts[0:3]
    receipts = multisig_deployer.deploy(threshold=threshold, owners=owners)
    for step in multisig_deployer.deployment_steps:
        assert receipts[step]['status'] == 1

    multisig_agent = multisig_deployer.make_agent()  # type: MultiSigAgent

    trustee_address = testerchain.unassigned_accounts[-1]
    trustee = Trustee(checksum_address=trustee_address, registry=test_registry)

    # Propose changing threshold

    # FIXME: I had to mock the gas_price property of EthereumTesterClient because I'm unable to set a free gas strategy
    with patch(
            'nucypher.blockchain.eth.clients.EthereumTesterClient.gas_price',
            new_callable=PropertyMock) as mock_ethtester:
        mock_ethtester.return_value = 0
        proposal = trustee.propose_changing_threshold(new_threshold=1)

    assert proposal.trustee_address == trustee_address
    assert proposal.target_address == multisig_agent.contract_address
    assert proposal.nonce == multisig_agent.nonce
    assert proposal.value == 0

    contract_function, params = proposal.decode_transaction_data(
        registry=test_registry)
    assert list(params.values()) == [
        1
    ]  # The new threshold is the only parameter in the call

    # Propose adding new owner

    new_owner = testerchain.unassigned_accounts[4]
    with patch(
            'nucypher.blockchain.eth.clients.EthereumTesterClient.gas_price',
            new_callable=PropertyMock) as mock_ethtester:
        mock_ethtester.return_value = 0
        proposal = trustee.propose_adding_owner(new_owner_address=new_owner,
                                                evidence=None)

    assert proposal.trustee_address == trustee_address
    assert proposal.target_address == multisig_agent.contract_address
    assert proposal.nonce == multisig_agent.nonce
    assert proposal.value == 0

    contract_function, params = proposal.decode_transaction_data(
        registry=test_registry)
    assert list(params.values()) == [
        new_owner
    ]  # The new owner is the only parameter in the call

    # Propose removing owner

    evicted_owner = testerchain.unassigned_accounts[1]
    with patch(
            'nucypher.blockchain.eth.clients.EthereumTesterClient.gas_price',
            new_callable=PropertyMock) as mock_ethtester:
        mock_ethtester.return_value = 0
        proposal = trustee.propose_removing_owner(evicted_owner)

    assert proposal.trustee_address == trustee_address
    assert proposal.target_address == multisig_agent.contract_address
    assert proposal.nonce == multisig_agent.nonce
    assert proposal.value == 0

    contract_function, params = proposal.decode_transaction_data(
        registry=test_registry)
    assert list(params.values()) == [
        evicted_owner
    ]  # The owner to remove is the only parameter in the call
예제 #6
0
def upgrade(general_config, actor_options, retarget, target_address,
            ignore_deployed, multisig):
    """
    Upgrade NuCypher existing proxy contract deployments.
    """
    # Init
    emitter = general_config.emitter

    ADMINISTRATOR, _, _, registry = actor_options.create_actor(
        emitter, is_multisig=bool(
            multisig))  # FIXME: Workaround for building MultiSig TXs

    contract_name = actor_options.contract_name
    if not contract_name:
        raise click.BadArgumentUsage(
            message="--contract-name is required when using --upgrade")

    if multisig:
        if not target_address:
            raise click.BadArgumentUsage(
                message="--multisig requires using --target-address.")
        if not actor_options.force:
            click.confirm(CONFIRM_BUILD_RETARGET_TRANSACTION.format(
                contract_name=contract_name, target_address=target_address),
                          abort=True)
        transaction = ADMINISTRATOR.retarget_proxy(
            contract_name=contract_name,
            target_address=target_address,
            just_build_transaction=True)

        trustee_address = select_client_account(
            emitter=emitter,
            prompt="Select trustee address",
            provider_uri=actor_options.provider_uri,
            show_eth_balance=False,
            show_nu_balance=False,
            show_staking=False)

        if not actor_options.force:
            click.confirm(
                CONFIRM_SELECTED_ACCOUNT.format(address=trustee_address),
                abort=True)

        trustee = Trustee(registry=registry, checksum_address=trustee_address)
        transaction_proposal = trustee.create_transaction_proposal(transaction)

        message = SUCCESSFUL_RETARGET_TX_BUILT.format(
            contract_name=contract_name, target_address=target_address)
        emitter.message(message, color='green')
        paint_multisig_proposed_transaction(
            emitter, transaction_proposal)  # TODO: Show decoded function too

        filepath = f'proposal-{trustee.multisig_agent.contract_address[:8]}-TX-{transaction_proposal.nonce}.json'
        transaction_proposal.write(filepath=filepath)
        emitter.echo(
            SUCCESSFUL_SAVE_MULTISIG_TX_PROPOSAL.format(filepath=filepath),
            color='blue',
            bold=True)

    elif retarget:
        if not target_address:
            raise click.BadArgumentUsage(
                message="--target-address is required when using --retarget")
        if not actor_options.force:
            click.confirm(CONFIRM_RETARGET.format(
                contract_name=contract_name, target_address=target_address),
                          abort=True)
        receipt = ADMINISTRATOR.retarget_proxy(contract_name=contract_name,
                                               target_address=target_address)
        message = SUCCESSFUL_RETARGET.format(contract_name=contract_name,
                                             target_address=target_address)
        emitter.message(message, color='green')
        paint_receipt_summary(emitter=emitter, receipt=receipt)
    else:
        if not actor_options.force:
            click.confirm(
                CONFIRM_BEGIN_UPGRADE.format(contract_name=contract_name),
                abort=True)
        receipts = ADMINISTRATOR.upgrade_contract(
            contract_name=contract_name, ignore_deployed=ignore_deployed)
        emitter.message(SUCCESSFUL_UPGRADE.format(contract_name=contract_name),
                        color='green')
        for name, receipt in receipts.items():
            paint_receipt_summary(emitter=emitter, receipt=receipt)
예제 #7
0
def upgrade(general_config, actor_options, retarget, target_address,
            ignore_deployed, multisig):
    """
    Upgrade NuCypher existing proxy contract deployments.
    """
    # Init
    emitter = general_config.emitter
    ADMINISTRATOR, _, _, registry = actor_options.create_actor(emitter)

    contract_name = actor_options.contract_name
    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)

    if multisig:
        if not target_address:
            raise click.BadArgumentUsage(
                message="--multisig requires using --target-address.")
        if not actor_options.force:
            click.confirm(
                f"Confirm building a re-target transaction for {contract_name}'s proxy to {target_address}?",
                abort=True)
        transaction = ADMINISTRATOR.retarget_proxy(
            contract_name=contract_name,
            target_address=target_address,
            existing_plaintext_secret=existing_secret,
            new_plaintext_secret=new_secret,
            just_build_transaction=True)

        trustee = Trustee(registry=registry,
                          checksum_address=ADMINISTRATOR.deployer_address)
        data_for_multisig_executives = trustee.produce_data_to_sign(
            transaction)

        emitter.message(
            f"Transaction to retarget {contract_name} proxy to {target_address} was built:",
            color='green')
        paint_multisig_proposed_transaction(emitter,
                                            data_for_multisig_executives)

        # TODO: Move this logic to a better place
        nonce = data_for_multisig_executives['parameters']['nonce']
        filepath = f'proposal-{nonce}.json'
        with open(filepath, 'w') as outfile:
            json.dump(data_for_multisig_executives, outfile)
        emitter.echo(f"Saved proposal to {filepath}", color='blue', bold=True)

    elif retarget:
        if not target_address:
            raise click.BadArgumentUsage(
                message="--target-address is required when using --retarget")
        if not actor_options.force:
            click.confirm(
                f"Confirm re-target {contract_name}'s proxy to {target_address}?",
                abort=True)
        receipt = ADMINISTRATOR.retarget_proxy(
            contract_name=contract_name,
            target_address=target_address,
            existing_plaintext_secret=existing_secret,
            new_plaintext_secret=new_secret)
        emitter.message(
            f"Successfully re-targeted {contract_name} proxy to {target_address}",
            color='green')
        paint_receipt_summary(emitter=emitter, receipt=receipt)
    else:
        if not actor_options.force:
            click.confirm(
                f"Confirm deploy new version of {contract_name} and retarget proxy?",
                abort=True)
        receipts = ADMINISTRATOR.upgrade_contract(
            contract_name=contract_name,
            existing_plaintext_secret=existing_secret,
            new_plaintext_secret=new_secret,
            ignore_deployed=ignore_deployed)
        emitter.message(f"Successfully deployed and upgraded {contract_name}",
                        color='green')
        for name, receipt in receipts.items():
            paint_receipt_summary(emitter=emitter, receipt=receipt)
예제 #8
0
def test_trustee_proposes_multisig_management_operations(
        testerchain, test_registry):
    origin = testerchain.etherbase_account
    tpower = TransactingPower(account=origin,
                              signer=Web3Signer(testerchain.client))
    multisig_deployer = MultiSigDeployer(registry=test_registry)

    threshold = 2
    owners = testerchain.unassigned_accounts[0:3]
    receipts = multisig_deployer.deploy(threshold=threshold,
                                        owners=owners,
                                        transacting_power=tpower)
    for step in multisig_deployer.deployment_steps:
        assert receipts[step]['status'] == 1

    multisig_agent = multisig_deployer.make_agent()

    trustee_address = testerchain.unassigned_accounts[-1]
    trustee = Trustee(checksum_address=trustee_address,
                      domain=TEMPORARY_DOMAIN,
                      signer=Web3Signer(testerchain.client),
                      registry=test_registry,
                      is_transacting=True)

    # Propose changing threshold
    free_payload = {
        'nonce': 0,
        'from': multisig_agent.contract_address,
        'gasPrice': 0
    }
    with patch.object(testerchain, 'build_payload', return_value=free_payload):
        proposal = trustee.propose_changing_threshold(new_threshold=1)

    assert proposal.trustee_address == trustee_address
    assert proposal.target_address == multisig_agent.contract_address
    assert proposal.nonce == multisig_agent.nonce
    assert proposal.value == 0

    contract_function, params = proposal.decode_transaction_data(
        registry=test_registry)
    assert list(params.values()) == [
        1
    ]  # The new threshold is the only parameter in the call

    # Propose adding new owner

    new_owner = testerchain.unassigned_accounts[4]
    with patch.object(testerchain, 'build_payload', return_value=free_payload):
        proposal = trustee.propose_adding_owner(new_owner_address=new_owner,
                                                evidence=None)

    assert proposal.trustee_address == trustee_address
    assert proposal.target_address == multisig_agent.contract_address
    assert proposal.nonce == multisig_agent.nonce
    assert proposal.value == 0

    contract_function, params = proposal.decode_transaction_data(
        registry=test_registry)
    assert list(params.values()) == [
        new_owner
    ]  # The new owner is the only parameter in the call

    # Propose removing owner

    evicted_owner = testerchain.unassigned_accounts[1]
    with patch.object(testerchain, 'build_payload', return_value=free_payload):
        proposal = trustee.propose_removing_owner(evicted_owner)

    assert proposal.trustee_address == trustee_address
    assert proposal.target_address == multisig_agent.contract_address
    assert proposal.nonce == multisig_agent.nonce
    assert proposal.value == 0

    contract_function, params = proposal.decode_transaction_data(
        registry=test_registry)
    assert list(params.values()) == [
        evicted_owner
    ]  # The owner to remove is the only parameter in the call