コード例 #1
0
def sign(general_config, blockchain_options, multisig_options, proposal):
    """
    Sign a proposed transaction before being sent to the MultiSig contract for execution
    """
    # Init
    emitter = general_config.emitter
    #_ensure_config_root(actor_options.config_root)
    blockchain = blockchain_options.connect_blockchain(emitter, general_config.debug)
    registry = get_registry(network=blockchain_options.network)

    proposal = Proposal.from_file(proposal)

    if not multisig_options.checksum_address:
        multisig_options.checksum_address = select_client_account(emitter=emitter,
                                                                  provider_uri=blockchain_options.provider_uri,
                                                                  poa=blockchain_options.poa,
                                                                  network=blockchain_options.network,
                                                                  registry=registry,
                                                                  show_balances=True)

    name, version, address, abi = registry.search(contract_address=proposal.target_address)
    # TODO: This assumes that we're always signing proxy retargetting. For the moment is true.
    proxy_contract = blockchain.client.w3.eth.contract(abi=abi,
                                                       address=address,
                                                       version=version,
                                                       ContractFactoryClass=blockchain._CONTRACT_FACTORY)
    paint_multisig_proposed_transaction(emitter, proposal, proxy_contract)

    click.confirm(PROMPT_CONFIRM_MULTISIG_SIGNATURE, abort=True)

    executive = multisig_options.create_transactingless_executive(registry)  # FIXME: Since we use a signer, don't ask for PW
    authorization = executive.authorize_proposal(proposal)
    emitter.echo(MULTISIG_SIGNATURE_RECEIVED.format(recovered_address=authorization.recover_executive_address(proposal)))
    emitter.echo(f"{authorization.serialize().hex()}\n", bold=True, color='green')
コード例 #2
0
 def setup(self, general_config) -> tuple:
     emitter = setup_emitter(general_config)
     registry = get_registry(network=self.network,
                             registry_filepath=self.registry_filepath)
     blockchain = connect_to_blockchain(emitter=emitter,
                                        provider_uri=self.provider_uri)
     return emitter, registry, blockchain
コード例 #3
0
def inspect(general_config, blockchain_options):
    """Show information of the MultiSig contract"""
    emitter = general_config.emitter
    _blockchain = blockchain_options.connect_blockchain(emitter, general_config.debug)
    registry = get_registry(network=blockchain_options.network)
    multisig_agent = ContractAgency.get_agent(MultiSigAgent, registry=registry)
    token_agent = ContractAgency.get_agent(NucypherTokenAgent, registry=registry)
    paint_multisig_contract_info(emitter, multisig_agent, token_agent)
コード例 #4
0
 def setup(self, general_config) -> tuple:
     emitter = setup_emitter(general_config)
     registry = get_registry(network=self.network, registry_filepath=self.registry_filepath)
     blockchain = initialize_deployer_interface(emitter=emitter,
                                                provider_uri=self.provider_uri,
                                                poa=False,
                                                ignore_solidity_check=True)
     return emitter, registry, blockchain
コード例 #5
0
ファイル: bond.py プロジェクト: KPrasch/nucypher
def unbond(registry_filepath, eth_provider_uri, signer_uri, staking_provider,
           network, force):
    """Unbonds an operator from an authorized staking provider."""

    #
    # Setup
    #

    emitter = StdoutEmitter()
    if not signer_uri:
        emitter.message('--signer is required', color='red')
        raise click.Abort()
    if not network:
        network = select_network(emitter=emitter,
                                 network_type=NetworksInventory.ETH)

    connect_to_blockchain(eth_provider_uri=eth_provider_uri, emitter=emitter)
    registry = get_registry(network=network,
                            registry_filepath=registry_filepath)
    agent = ContractAgency.get_agent(PREApplicationAgent, registry=registry)
    signer = Signer.from_signer_uri(signer_uri)
    transacting_power = TransactingPower(account=staking_provider,
                                         signer=signer)

    #
    # Check
    #

    bonded, onchain_operator_address = is_bonded(
        agent=agent, staking_provider=staking_provider, return_address=True)
    if not bonded:
        emitter.message(NOT_BONDED.format(provider=staking_provider),
                        color='red')
        raise click.Abort()
    check_bonding_requirements(emitter=emitter,
                               agent=agent,
                               staking_provider=staking_provider)

    #
    # Unbond
    #

    if not force:
        click.confirm(CONFIRM_UNBONDING.format(
            provider=staking_provider, operator=onchain_operator_address),
                      abort=True)
    transacting_power.unlock(password=get_client_password(
        checksum_address=staking_provider,
        envvar=NUCYPHER_ENVVAR_STAKING_PROVIDER_ETH_PASSWORD))
    emitter.echo(UNBONDING.format(operator=onchain_operator_address))
    receipt = agent.bond_operator(operator=NULL_ADDRESS,
                                  transacting_power=transacting_power,
                                  staking_provider=staking_provider)
    paint_receipt_summary(receipt=receipt, emitter=emitter)
コード例 #6
0
def propose(general_config, blockchain_options, multisig_options):
    """Create a proposal of MultiSig transaction"""
    # TODO: Extend this command to cover this list of proposals
    #  - Add new MultiSig owner
    #  - Remove MultiSig owner
    #  - Change threshold of MultiSig
    #  - Upgrade contract (in particular, retarget to a deployed one)
    #  - Transfer ownership of contract
    #  - Send ETH from MultiSig
    #  - Send tokens from MultiSig
    #  - Change global fee range in PolicyManager
    #  - Send raw transaction

    # Init
    emitter = general_config.emitter
    #_ensure_config_root(actor_options.config_root)  # TODO: Review this commented out line
    blockchain = blockchain_options.connect_blockchain(emitter,
                                                       general_config.debug)
    registry = get_registry(network=blockchain_options.network)

    if not multisig_options.checksum_address:
        multisig_options.checksum_address = select_client_account(
            emitter=emitter,
            provider_uri=blockchain_options.provider_uri,
            poa=blockchain_options.poa,
            network=blockchain_options.network,
            registry=registry,
            show_balances=True)  # FIXME: Unexpected input

    trustee = multisig_options.create_transactingless_trustee(registry)

    # As a PoC, this command only allows to change the threshold
    # TODO: Think in the UX for choosing between different types of proposals

    new_threshold = click.prompt(PROMPT_NEW_MULTISIG_THRESHOLD, type=click.INT)
    proposal = trustee.propose_changing_threshold(new_threshold)

    paint_multisig_proposed_transaction(emitter=emitter,
                                        proposal=proposal,
                                        registry=registry)

    filepath = Path(
        f'proposal-changeThreshold-{trustee.multisig_agent.contract_address[:8]}-TX-{proposal.nonce}.json'
    )
    proposal.write(filepath=filepath)
    emitter.echo(
        SUCCESSFUL_SAVE_MULTISIG_TX_PROPOSAL.format(filepath=filepath),
        color='blue',
        bold=True)
コード例 #7
0
def execute(general_config, blockchain_options, multisig_options, proposal):
    """
    Collect authorizations from executives and execute transaction through MultiSig contract
    """
    # Init
    emitter = general_config.emitter
    #_ensure_config_root(actor_options.config_root)
    blockchain = blockchain_options.connect_blockchain(emitter,
                                                       general_config.debug)
    registry = get_registry(network=blockchain_options.network)

    proposal = Proposal.from_file(proposal)

    if not multisig_options.checksum_address:
        multisig_options.checksum_address = select_client_account(
            emitter=emitter,
            provider_uri=blockchain_options.provider_uri,
            poa=blockchain_options.poa,
            network=blockchain_options.network,
            registry=registry,
            show_balances=True)  # FIXME: Unexpected argument!!

    name, version, address, abi = registry.search(
        contract_address=proposal.target_address)
    # TODO: This assumes that we're always signing proxy retargetting. For the moment is true.
    proxy_contract = blockchain.client.w3.eth.contract(
        abi=abi,
        address=address,
        version=version,
        ContractFactoryClass=blockchain._CONTRACT_FACTORY)
    paint_multisig_proposed_transaction(emitter, proposal, proxy_contract)

    trustee = multisig_options.create_trustee(registry)
    threshold = trustee.multisig_agent.threshold

    while len(trustee.authorizations) < threshold:
        auth_hex = click.prompt(PROMPT_FOR_RAW_SIGNATURE, type=click.STRING)
        authorization = Authorization.from_hex(auth_hex)
        executive_address = trustee.add_authorization(authorization, proposal)
        emitter.echo(SUCCESSFUL_MULTISIG_AUTHORIZATION.format(
            executive_address=executive_address),
                     color='green')

    click.confirm(CONFIRM_EXECUTE_MULTISIG_TRANSACTION, abort=True)

    receipt = trustee.execute(proposal)
    paint_receipt_summary(emitter, receipt)
コード例 #8
0
def bond(registry_filepath, eth_provider_uri, signer_uri, operator_address,
         staking_provider, network, force):
    """
    Bond an operator to a staking provider.
    The staking provider must be authorized to use the PREApplication.
    """

    #
    # Setup
    #

    emitter = StdoutEmitter()
    connect_to_blockchain(eth_provider_uri=eth_provider_uri, emitter=emitter)
    if not signer_uri:
        emitter.message('--signer is required', color='red')
        raise click.Abort()
    if not network:
        network = select_network(emitter=emitter)

    signer = Signer.from_signer_uri(signer_uri)
    transacting_power = TransactingPower(account=staking_provider,
                                         signer=signer)
    registry = get_registry(network=network,
                            registry_filepath=registry_filepath)
    agent = ContractAgency.get_agent(PREApplicationAgent, registry=registry)

    #
    # Checks
    #

    # Check for authorization
    is_authorized(emitter=emitter,
                  agent=agent,
                  staking_provider=staking_provider)

    # Check bonding
    if is_bonded(agent=agent,
                 staking_provider=staking_provider,
                 return_address=False):
        # operator is already set - check timing
        check_bonding_requirements(emitter=emitter,
                                   agent=agent,
                                   staking_provider=staking_provider)

    # Check for pre-existing staking providers for this operator
    onchain_staking_provider = agent.get_staking_provider_from_operator(
        operator_address=operator_address)
    if onchain_staking_provider != NULL_ADDRESS:
        emitter.message(ALREADY_BONDED.format(
            provider=onchain_staking_provider, operator=operator_address),
                        color='red')
        raise click.Abort()  # dont steal bananas

    # Check that operator is not human
    if staking_provider != operator_address:
        # if the operator has a beneficiary it is the staking provider.
        beneficiary = agent.get_beneficiary(staking_provider=operator_address)
        if beneficiary != NULL_ADDRESS:
            emitter.message(UNEXPECTED_HUMAN_OPERATOR, color='red')
            raise click.Abort()

    #
    # Bond
    #

    if not force:
        click.confirm(CONFIRM_BONDING.format(provider=staking_provider,
                                             operator=operator_address),
                      abort=True)
    transacting_power.unlock(password=get_client_password(
        checksum_address=staking_provider,
        envvar=NUCYPHER_ENVVAR_STAKING_PROVIDER_ETH_PASSWORD))
    emitter.echo(BONDING.format(operator=operator_address))
    receipt = agent.bond_operator(operator=operator_address,
                                  transacting_power=transacting_power,
                                  staking_provider=staking_provider)
    paint_receipt_summary(receipt=receipt, emitter=emitter)
コード例 #9
0
def run(general_config, network, provider_uri, federated_only, teacher_uri,
        registry_filepath, min_stake, http_port, tls_certificate_filepath,
        tls_key_filepath, basic_auth_filepath, allow_origins, dry_run, eager):
    """Start Porter's Web controller."""
    emitter = setup_emitter(general_config, banner=Porter.BANNER)

    # HTTP/HTTPS
    if bool(tls_key_filepath) ^ bool(tls_certificate_filepath):
        raise click.BadOptionUsage(
            option_name='--tls-key-filepath, --tls-certificate-filepath',
            message=PORTER_BOTH_TLS_KEY_AND_CERTIFICATION_MUST_BE_PROVIDED)

    is_https = (tls_key_filepath and tls_certificate_filepath)

    # check authentication
    if basic_auth_filepath and not is_https:
        raise click.BadOptionUsage(option_name='--basic-auth-filepath',
                                   message=PORTER_BASIC_AUTH_REQUIRES_HTTPS)

    if federated_only:
        if not teacher_uri:
            raise click.BadOptionUsage(
                option_name='--teacher',
                message="--teacher is required for federated porter.")

        teacher = Ursula.from_teacher_uri(
            teacher_uri=teacher_uri, federated_only=True,
            min_stake=min_stake)  # min stake is irrelevant for federated
        PORTER = Porter(domain=TEMPORARY_DOMAIN,
                        start_learning_now=eager,
                        known_nodes={teacher},
                        verify_node_bonding=False,
                        federated_only=True)
    else:
        # decentralized/blockchain
        if not provider_uri:
            raise click.BadOptionUsage(
                option_name='--provider',
                message="--provider is required for decentralized porter.")
        if not network:
            # should never happen - network defaults to 'mainnet' if not specified
            raise click.BadOptionUsage(
                option_name='--network',
                message="--network is required for decentralized porter.")

        registry = get_registry(network=network,
                                registry_filepath=registry_filepath)
        teacher = None
        if teacher_uri:
            teacher = Ursula.from_teacher_uri(
                teacher_uri=teacher_uri,
                federated_only=False,  # always False
                min_stake=min_stake,
                registry=registry)

        PORTER = Porter(domain=network,
                        known_nodes={teacher} if teacher else None,
                        registry=registry,
                        start_learning_now=eager,
                        provider_uri=provider_uri)

    # RPC
    if general_config.json_ipc:
        rpc_controller = PORTER.make_rpc_controller()
        _transport = rpc_controller.make_control_transport()
        rpc_controller.start()
        return

    emitter.message(f"Network: {PORTER.domain.capitalize()}", color='green')
    if not federated_only:
        emitter.message(f"Provider: {provider_uri}", color='green')

    # firm up falsy status (i.e. change specified empty string to None)
    allow_origins = allow_origins if allow_origins else None
    # covert to list of strings/regexes
    allow_origins_list = None
    if allow_origins:
        allow_origins_list = allow_origins.split(
            ",")  # split into list of origins to allow
        emitter.message(PORTER_CORS_ALLOWED_ORIGINS.format(
            allow_origins=allow_origins_list),
                        color='green')

    if basic_auth_filepath:
        emitter.message(PORTER_BASIC_AUTH_ENABLED, color='green')

    controller = PORTER.make_web_controller(
        crash_on_error=False,
        htpasswd_filepath=basic_auth_filepath,
        cors_allow_origins_list=allow_origins_list)
    http_scheme = "https" if is_https else "http"
    message = PORTER_RUN_MESSAGE.format(http_scheme=http_scheme,
                                        http_port=http_port)
    emitter.message(message, color='green', bold=True)
    return controller.start(port=http_port,
                            tls_key_filepath=tls_key_filepath,
                            tls_certificate_filepath=tls_certificate_filepath,
                            dry_run=dry_run)