Zeth - Zerocash on Ethereum  0.8
Reference implementation of the Zeth protocol by Clearmatics
zeth_mix.py
Go to the documentation of this file.
1 # Copyright (c) 2015-2022 Clearmatics Technologies Ltd
2 #
3 # SPDX-License-Identifier: LGPL-3.0+
4 
5 from zeth.cli.utils import create_mixer_client_and_mixer_desc, \
6  load_zeth_address, open_wallet, parse_output, do_sync, load_eth_address, \
7  load_eth_private_key, zeth_note_short_print, create_prover_client
8 from zeth.core.constants import JS_INPUTS, JS_OUTPUTS
9 from zeth.core.mixer_client import ZethAddressPub
10 from zeth.core.utils import EtherValue, from_zeth_units
11 from zeth.api.zeth_messages_pb2 import ZethNote
12 from click import command, option, pass_context, ClickException, Context
13 from typing import List, Tuple, Optional
14 import json
15 
16 
17 @command()
18 @option("--vin", default="0", help="Public input value")
19 @option("--vout", default="0", help="Public output value")
20 @option("--in", "input_notes", multiple=True, help="Input note identifier")
21 @option(
22  "--out",
23  "output_specs",
24  multiple=True,
25  help="<receiver_pub_addr>,<value> where <receiver_pub_addr> can be a "
26  "filename or hex address")
27 @option("--eth-addr", help="Sender's eth address or address filename")
28 @option("--eth-private-key", help="Sender's eth private key file")
29 @option("--wait", is_flag=True, help="Wait for transaction to be mined")
30 @option(
31  "--for-dispatch-call",
32  is_flag=True,
33  help="Generate signature for later call to dispatch (implies --dry-run)")
34 @option("--dump-parameters", help="Write mix parameters to file ('-' for stdout)")
35 @option(
36  "--dump-signing-keypair",
37  help="Write signing keypair to file ('-' for stdout). "
38  "USE ONLY FOR DEBUGGING.")
39 @option("--dry-run", "-n", is_flag=True, help="Do not send the mix transaction")
40 @pass_context
41 def mix(
42  ctx: Context,
43  vin: str,
44  vout: str,
45  input_notes: List[str],
46  output_specs: List[str],
47  eth_addr: Optional[str],
48  eth_private_key: Optional[str],
49  wait: bool,
50  for_dispatch_call: bool,
51  dump_parameters: Optional[str],
52  dump_signing_keypair: Optional[str],
53  dry_run: bool) -> None:
54  """
55  Generic mix function
56  """
57  # Some sanity checks
58  if len(input_notes) > JS_INPUTS:
59  raise ClickException(f"too many inputs (max {JS_INPUTS})")
60  if len(output_specs) > JS_OUTPUTS:
61  raise ClickException(f"too many outputs (max {JS_OUTPUTS})")
62 
63  vin_pub = EtherValue(vin)
64  vout_pub = EtherValue(vout)
65  client_ctx = ctx.obj
66  prover_client = create_prover_client(client_ctx)
67  zeth_client, mixer_desc = create_mixer_client_and_mixer_desc(
68  client_ctx, prover_client)
69  zeth_address = load_zeth_address(client_ctx)
70  wallet = open_wallet(
71  zeth_client.mixer_instance, zeth_address.addr_sk, client_ctx)
72 
73  inputs: List[Tuple[int, ZethNote]] = [
74  wallet.find_note(note_id).as_input() for note_id in input_notes]
75  outputs: List[Tuple[ZethAddressPub, EtherValue]] = [
76  parse_output(out_spec) for out_spec in output_specs]
77 
78  # Compute input and output value total and check that they match
79  input_note_sum = from_zeth_units(
80  sum([int(note.value, 16) for _, note in inputs]))
81  output_note_sum = sum([value for _, value in outputs], EtherValue(0))
82  if vin_pub + input_note_sum != vout_pub + output_note_sum:
83  raise ClickException("input and output value mismatch")
84 
85  eth_address = load_eth_address(eth_addr)
86 
87  # If instance uses an ERC20 token, tx_value can be 0. Otherwise it should
88  # match vin_pub.
89  tx_value = EtherValue(0) if mixer_desc.token else vin_pub
90 
91  # Create the MixParameters object manually so they can be displayed.
92  # TODO: support saving the generated MixParameters to be sent later.
93  mix_params, signing_keypair = \
94  zeth_client.create_mix_parameters_and_signing_key(
95  prover_client,
96  wallet.merkle_tree,
97  zeth_address.ownership_keypair(),
98  eth_address,
99  inputs,
100  outputs,
101  vin_pub,
102  vout_pub,
103  for_dispatch_call=for_dispatch_call)
104 
105  # Dump parameters if requested
106  if dump_parameters:
107  if dump_parameters == '-':
108  print(f"mix_params={mix_params.to_json()}")
109  else:
110  with open(dump_parameters, "w") as mix_params_f:
111  json.dump(mix_params.to_json_dict(), mix_params_f)
112 
113  # Dump one-time signature keypair if requested
114  if dump_signing_keypair:
115  if dump_signing_keypair == '-':
116  print(f"signing_key={signing_keypair.to_json_dict()}")
117  else:
118  with open(dump_signing_keypair, "w") as signing_keypair_f:
119  json.dump(signing_keypair.to_json_dict(), signing_keypair_f)
120 
121  # Early-out if dry_run flag is set
122  if for_dispatch_call or dry_run:
123  return
124 
125  eth_private_key_data = load_eth_private_key(eth_private_key)
126  tx_hash = zeth_client.mix(
127  mix_params=mix_params,
128  sender_eth_address=eth_address,
129  sender_eth_private_key=eth_private_key_data,
130  tx_value=tx_value)
131 
132  print(tx_hash)
133  if wait:
134  pp = prover_client.get_configuration().pairing_parameters
135  do_sync(zeth_client.web3, wallet, pp, tx_hash, zeth_note_short_print)
zeth.cli.utils.create_prover_client
ProverClient create_prover_client(ClientConfig ctx)
Definition: utils.py:373
zeth.cli.utils.open_wallet
Wallet open_wallet(Any mixer_instance, ZethAddressPriv js_secret, ClientConfig ctx)
Definition: utils.py:275
zeth.cli.zeth_deploy.int
int
Definition: zeth_deploy.py:27
zeth.cli.utils.load_eth_address
str load_eth_address(Optional[str] eth_addr)
Definition: utils.py:444
zeth.cli.utils.create_mixer_client_and_mixer_desc
Tuple[MixerClient, MixerDescription] create_mixer_client_and_mixer_desc(ClientConfig ctx, Optional[ProverClient] prover_client=None)
Definition: utils.py:391
zeth.core.constants
Definition: constants.py:1
zeth.cli.utils.parse_output
Tuple[ZethAddressPub, EtherValue] parse_output(str output_str)
Definition: utils.py:421
zeth.cli.utils
Definition: utils.py:1
zeth.cli.utils.load_zeth_address
ZethAddress load_zeth_address(ClientConfig ctx)
Definition: utils.py:265
zeth.core.mixer_client
Definition: mixer_client.py:1
zeth.core.utils
Definition: utils.py:1
zeth.cli.utils.load_eth_private_key
Optional[bytes] load_eth_private_key(Optional[str] private_key_file)
Definition: utils.py:465
zeth.core.utils.from_zeth_units
EtherValue from_zeth_units(int zeth_units)
Definition: utils.py:227
zeth.core.utils.EtherValue
Definition: utils.py:46
zeth.cli.utils.do_sync
int do_sync(Any web3, Wallet wallet, PairingParameters pp, Optional[str] wait_tx, Optional[Callable[[ZethNoteDescription], None]] callback=None, Optional[int] batch_size=None)
Definition: utils.py:289
zeth.cli.zeth_mix.mix
None mix(Context ctx, str vin, str vout, List[str] input_notes, List[str] output_specs, Optional[str] eth_addr, Optional[str] eth_private_key, bool wait, bool for_dispatch_call, Optional[str] dump_parameters, Optional[str] dump_signing_keypair, bool dry_run)
Definition: zeth_mix.py:41