Example #1
0
def mix(ctx: Context, vin: str, vout: str, input_notes: List[str],
        output_specs: List[str], eth_addr: Optional[str],
        eth_private_key: Optional[str], wait: bool,
        show_parameters: bool) -> None:
    """
    Generic mix function
    """
    # Some sanity checks
    if len(input_notes) > JS_INPUTS:
        raise ClickException(f"too many inputs (max {JS_INPUTS})")
    if len(output_specs) > JS_OUTPUTS:
        raise ClickException(f"too many outputs (max {JS_OUTPUTS})")

    print(f"vin = {vin}")
    print(f"vout = {vout}")

    vin_pub = EtherValue(vin)
    vout_pub = EtherValue(vout)
    client_ctx = ctx.obj
    zeth_client, mixer_desc = create_zeth_client_and_mixer_desc(client_ctx)
    zeth_address = load_zeth_address(client_ctx)
    wallet = open_wallet(zeth_client.mixer_instance, zeth_address.addr_sk,
                         client_ctx)

    inputs: List[Tuple[int, ZethNote]] = [
        wallet.find_note(note_id).as_input() for note_id in input_notes
    ]
    outputs: List[Tuple[ZethAddressPub, EtherValue]] = [
        parse_output(out_spec) for out_spec in output_specs
    ]

    # Compute input and output value total and check that they match
    input_note_sum = from_zeth_units(
        sum([int(note.value, 16) for _, note in inputs]))
    output_note_sum = sum([value for _, value in outputs], EtherValue(0))
    if vin_pub + input_note_sum != vout_pub + output_note_sum:
        raise ClickException("input and output value mismatch")

    eth_address = load_eth_address(eth_addr)
    eth_private_key_data = load_eth_private_key(eth_private_key)

    # If instance uses an ERC20 token, tx_value can be 0. Otherwise it should
    # match vin_pub.
    tx_value = EtherValue(0) if mixer_desc.token else vin_pub

    mix_params = zeth_client.create_mix_parameters(
        wallet.merkle_tree, zeth_address.ownership_keypair(), eth_address,
        inputs, outputs, vin_pub, vout_pub)

    if show_parameters:
        print(f"mix_params={mix_params.to_json()}")

    tx_hash = zeth_client.mix(mix_params=mix_params,
                              sender_eth_address=eth_address,
                              sender_eth_private_key=eth_private_key_data,
                              tx_value=tx_value)

    print(tx_hash)
    if wait:
        do_sync(zeth_client.web3, wallet, tx_hash, zeth_note_short_print)
Example #2
0
def sync(ctx: Context, wait_tx: Optional[str],
         batch_size: Optional[int]) -> None:
    """
    Attempt to retrieve new notes for the key in <key-file>
    """
    client_ctx = ctx.obj
    web3 = open_web3_from_ctx(client_ctx)
    mixer_desc = load_mixer_description_from_ctx(client_ctx)
    mixer_instance = mixer_desc.mixer.instantiate(web3)
    js_secret = load_zeth_address_secret(client_ctx)
    wallet = open_wallet(mixer_instance, js_secret, client_ctx)
    chain_block_number = do_sync(web3, wallet, wait_tx, zeth_note_short_print,
                                 batch_size)
    print(f"SYNCED to {chain_block_number}")
Example #3
0
def mix(
        ctx: Context,
        vin: str,
        vout: str,
        input_notes: List[str],
        output_specs: List[str],
        eth_addr: Optional[str],
        eth_private_key: Optional[str],
        wait: bool,
        for_dispatch_call: bool,
        dump_parameters: Optional[str],
        dump_signing_keypair: Optional[str],
        dry_run: bool) -> None:
    """
    Generic mix function
    """
    # Some sanity checks
    if len(input_notes) > JS_INPUTS:
        raise ClickException(f"too many inputs (max {JS_INPUTS})")
    if len(output_specs) > JS_OUTPUTS:
        raise ClickException(f"too many outputs (max {JS_OUTPUTS})")

    vin_pub = EtherValue(vin)
    vout_pub = EtherValue(vout)
    client_ctx = ctx.obj
    prover_client = create_prover_client(client_ctx)
    zeth_client, mixer_desc = create_mixer_client_and_mixer_desc(
        client_ctx, prover_client)
    zeth_address = load_zeth_address(client_ctx)
    wallet = open_wallet(
        zeth_client.mixer_instance, zeth_address.addr_sk, client_ctx)

    inputs: List[Tuple[int, ZethNote]] = [
        wallet.find_note(note_id).as_input() for note_id in input_notes]
    outputs: List[Tuple[ZethAddressPub, EtherValue]] = [
        parse_output(out_spec) for out_spec in output_specs]

    # Compute input and output value total and check that they match
    input_note_sum = from_zeth_units(
        sum([int(note.value, 16) for _, note in inputs]))
    output_note_sum = sum([value for _, value in outputs], EtherValue(0))
    if vin_pub + input_note_sum != vout_pub + output_note_sum:
        raise ClickException("input and output value mismatch")

    eth_address = load_eth_address(eth_addr)

    # If instance uses an ERC20 token, tx_value can be 0. Otherwise it should
    # match vin_pub.
    tx_value = EtherValue(0) if mixer_desc.token else vin_pub

    # Create the MixParameters object manually so they can be displayed.
    # TODO: support saving the generated MixParameters to be sent later.
    mix_params, signing_keypair = \
        zeth_client.create_mix_parameters_and_signing_key(
            prover_client,
            wallet.merkle_tree,
            zeth_address.ownership_keypair(),
            eth_address,
            inputs,
            outputs,
            vin_pub,
            vout_pub,
            for_dispatch_call=for_dispatch_call)

    # Dump parameters if requested
    if dump_parameters:
        if dump_parameters == '-':
            print(f"mix_params={mix_params.to_json()}")
        else:
            with open(dump_parameters, "w") as mix_params_f:
                json.dump(mix_params.to_json_dict(), mix_params_f)

    # Dump one-time signature keypair if requested
    if dump_signing_keypair:
        if dump_signing_keypair == '-':
            print(f"signing_key={signing_keypair.to_json_dict()}")
        else:
            with open(dump_signing_keypair, "w") as signing_keypair_f:
                json.dump(signing_keypair.to_json_dict(), signing_keypair_f)

    # Early-out if dry_run flag is set
    if for_dispatch_call or dry_run:
        return

    eth_private_key_data = load_eth_private_key(eth_private_key)
    tx_hash = zeth_client.mix(
        mix_params=mix_params,
        sender_eth_address=eth_address,
        sender_eth_private_key=eth_private_key_data,
        tx_value=tx_value)

    print(tx_hash)
    if wait:
        pp = prover_client.get_configuration().pairing_parameters
        do_sync(zeth_client.web3, wallet, pp, tx_hash, zeth_note_short_print)