def __init__( self, nested_snark_name: str, wrapper_snark_name: str, nested_pairing_parameters: PairingParameters, wrapper_pairing_parameters: PairingParameters): self.nested_snark_name = nested_snark_name self.wrapper_snark_name = wrapper_snark_name self.nested_snark = get_zksnark_provider(nested_snark_name) self.wrapper_snark = get_zksnark_provider(wrapper_snark_name) self.nested_pairing_parameters = nested_pairing_parameters self.wrapper_pairing_parameters = wrapper_pairing_parameters
def create_mix_parameters_from_proof( self, mix_call_desc: MixCallDescription, prover_inputs: ProofInputs, signing_keypair: signing.SigningKeyPair, ext_proof: ExtendedProof, sender_eth_address: str) -> MixParameters: # Encrypt the notes outputs_and_notes = zip(mix_call_desc.outputs, prover_inputs.js_outputs) \ # pylint: disable=no-member output_notes_with_k_pk: List[Tuple[ZethNote, EncryptionPublicKey]] = \ [(note, zeth_addr.k_pk) for ((zeth_addr, _), note) in outputs_and_notes] ciphertexts = encrypt_notes(output_notes_with_k_pk) # Sign zksnark = get_zksnark_provider(self.prover_config.zksnark_name) signature = joinsplit_sign(zksnark, self.prover_config.pairing_parameters, signing_keypair, sender_eth_address, ciphertexts, ext_proof) mix_params = MixParameters(ext_proof, signing_keypair.vk, signature, ciphertexts) return mix_params
def create_mix_parameters_and_signing_key( self, prover_client: ProverClient, mk_tree: MerkleTree, sender_ownership_keypair: OwnershipKeyPair, sender_eth_address: str, inputs: List[Tuple[int, ZethNote]], outputs: List[Tuple[ZethAddressPub, EtherValue]], v_in: EtherValue, v_out: EtherValue, compute_h_sig_cb: Optional[ComputeHSigCB] = None ) -> Tuple[MixParameters, JoinsplitSigKeyPair]: """ Convenience function around creation of MixCallDescription, ProofInputs, Proof and MixParameters. """ # Generate prover inputs and signing key mix_call_desc = MixCallDescription(mk_tree, sender_ownership_keypair, inputs, outputs, v_in, v_out, compute_h_sig_cb) prover_inputs, signing_keypair = MixerClient.create_prover_inputs( mix_call_desc) zksnark = get_zksnark_provider(self.prover_config.zksnark_name) # Query the prover_server for the related proof ext_proof_proto = prover_client.get_proof(prover_inputs) ext_proof = zksnark.extended_proof_from_proto(ext_proof_proto) # Create the final MixParameters object mix_params = self.create_mix_parameters_from_proof( mix_call_desc, prover_inputs, signing_keypair, ext_proof, sender_eth_address) return mix_params, signing_keypair
def open(web3: Any, prover_server_endpoint: str, mixer_instance: Any) -> MixerClient: """ Create a client for an existing Zeth deployment. """ return MixerClient(web3, ProverClient(prover_server_endpoint), mixer_instance, get_zksnark_provider(constants.ZKSNARK_DEFAULT))
def _create_mix_call(self, mix_parameters: MixParameters) -> Any: """ Given a MixParameters object and other transaction properties, create a web3 call object, which can be used to create a transaction or a query. """ zksnark = get_zksnark_provider(self.prover_config.zksnark_name) pp = self.prover_config.pairing_parameters mix_params_eth = mix_parameters_to_contract_arguments( zksnark, pp, mix_parameters) return self.mixer_instance.functions.mix(*mix_params_eth)
def deploy( web3: Any, prover_client: ProverClient, deployer_eth_address: str, deployer_eth_private_key: Optional[bytes], token_address: Optional[str] = None, permitted_dispatcher: Optional[str] = None, vk_hash: Optional[str] = None, deploy_gas: Optional[int] = None ) -> Tuple[MixerClient, contracts.InstanceDescription]: """ Deploy Zeth contracts. """ prover_config = prover_client.get_configuration() vk = prover_client.get_verification_key() contracts_dir = get_contracts_dir() zksnark = get_zksnark_provider(prover_config.zksnark_name) pp = prover_config.pairing_parameters mixer_name = zksnark.get_contract_name(pp) mixer_src = os.path.join(contracts_dir, mixer_name + ".sol") vk_hash_evm = list(hex_to_uint256_list(vk_hash)) if vk_hash else [0, 0] assert len(vk_hash_evm) == 2 # Constructor parameters have the form: # uint256 mk_depth # address token # ... snark-specific key data ... constructor_parameters: List[Any] = [ constants.ZETH_MERKLE_TREE_DEPTH, # mk_depth token_address or ZERO_ADDRESS, # token zksnark.verification_key_to_contract_parameters(vk, pp), # vk permitted_dispatcher or ZERO_ADDRESS, # permitted_dispatcher vk_hash_evm # vk_hash ] mixer_description = contracts.InstanceDescription.deploy( web3, mixer_src, mixer_name, deployer_eth_address, deployer_eth_private_key, deploy_gas, compiler_flags={}, args=constructor_parameters) mixer_instance = mixer_description.instantiate(web3) client = MixerClient(web3, prover_config, mixer_instance) return client, mixer_description
def zklay_deposit(self, deposit_params: DepositParameters, sender_eth_address: str, sender_eth_private_key: Optional[bytes], tx_value: EtherValue, call_gas: int = constants.DEFAULT_MIX_GAS_WEI) -> str: zksnark = get_zksnark_provider(self.prover_config.zksnark_name) pp = self.prover_config.pairing_parameters mix_params_eth = deposit_parameters_to_contract_arguments( zksnark, pp, deposit_params) deposit_call = self.mixer_instance.functions.deposit( *deposit_params_eth) tx_hash = contracts.send_contract_call(self.web3, deposit_call, sender_eth_address, sender_eth_private_key, tx_value, constants.DEFAULT_MIX_GAS_WEI) return tx_hash.hex()
def deploy( web3: Any, prover_client: ProverClient, deployer_eth_address: str, deployer_eth_private_key: Optional[bytes], token_address: Optional[str] = None, deploy_gas: Optional[int] = None ) -> Tuple[MixerClient, contracts.InstanceDescription]: """ Deploy Zeth contracts. """ prover_config = prover_client.get_configuration() zksnark = get_zksnark_provider(prover_config.zksnark_name) vk_proto = prover_client.get_verification_key() pp = prover_config.pairing_parameters vk = zksnark.verification_key_from_proto(vk_proto) deploy_gas = deploy_gas or constants.DEPLOYMENT_GAS_WEI contracts_dir = get_contracts_dir() mixer_name = zksnark.get_contract_name(pp) mixer_src = os.path.join(contracts_dir, mixer_name + ".sol") # Constructor parameters have the form: # uint256 mk_depth # address token # ... snark-specific key data ... constructor_parameters: List[Any] = [ constants.ZETH_MERKLE_TREE_DEPTH, # mk_depth token_address or ZERO_ADDRESS, # token zksnark.verification_key_to_contract_parameters(vk, pp), # vk ] mixer_description = contracts.InstanceDescription.deploy( web3, mixer_src, mixer_name, deployer_eth_address, deployer_eth_private_key, deploy_gas, compiler_flags={}, args=constructor_parameters) mixer_instance = mixer_description.instantiate(web3) client = MixerClient(web3, prover_config, mixer_instance) return client, mixer_description
def deploy( web3: Any, prover_server_endpoint: str, deployer_eth_address: str, deployer_eth_private_key: Optional[bytes], token_address: Optional[str] = None, deploy_gas: Optional[int] = None, zksnark: Optional[IZKSnarkProvider] = None) \ -> Tuple[MixerClient, contracts.InstanceDescription]: """ Deploy Zeth contracts. """ print("[INFO] 1. Fetching verification key from the proving server") zksnark = zksnark or get_zksnark_provider(constants.ZKSNARK_DEFAULT) prover_client = ProverClient(prover_server_endpoint) vk_proto = prover_client.get_verification_key() vk = zksnark.verification_key_from_proto(vk_proto) deploy_gas = deploy_gas or constants.DEPLOYMENT_GAS_WEI print("[INFO] 2. Received VK, writing verification key...") write_verification_key(vk, "vk.json") print("[INFO] 3. VK written, deploying smart contracts...") contracts_dir = get_contracts_dir() mixer_name = zksnark.get_contract_name() mixer_src = os.path.join(contracts_dir, mixer_name + ".sol") verification_key_params = zksnark.verification_key_parameters(vk) mixer_description = contracts.InstanceDescription.deploy( web3, mixer_src, mixer_name, deployer_eth_address, deployer_eth_private_key, deploy_gas, {}, mk_depth=constants.ZETH_MERKLE_TREE_DEPTH, token=token_address or "0x0000000000000000000000000000000000000000", **verification_key_params) mixer_instance = mixer_description.instantiate(web3) client = MixerClient(web3, prover_client, mixer_instance, zksnark) return client, mixer_description
def create_nested_tx(zeth_tx_file: str, prover_config_file: str, output_file: str) -> None: """ Create a Zecale nested transaction from a zeth MixParameters object """ # Load prover config (which is assumed to already exist) with open(prover_config_file, "r") as prover_config_f: prover_config = \ ProverConfiguration.from_json_dict(json.load(prover_config_f)) zksnark = zksnark = get_zksnark_provider(prover_config.zksnark_name) # Read the MixParameters with open(zeth_tx_file, "r") as zeth_tx_f: zeth_mix_params = \ MixParameters.from_json_dict(zksnark, json.load(zeth_tx_f)) # Convert to a nested transaction, and write to output file nested_tx = _create_zeth_nested_tx(zeth_mix_params, 0) with open(output_file, "w") as output_f: json.dump(nested_tx.to_json_dict(), output_f)
def create_mix_parameters_from_proof( self, mix_call_desc: MixCallDescription, prover_inputs: api.ProofInputs, signing_keypair: signing.SigningKeyPair, ext_proof: ExtendedProof, public_data: List[int], sender_eth_address: str, for_dispatch_call: bool = False) -> MixParameters: """ Create the MixParameters from MixCallDescription, signing keypair, sender address and derived data (prover inputs and proof). This includes creating and encrypting the plaintext messages, and generating the one-time signature. If for_dispatch_call is set, the parameters are to be passed to the Mixer's `dispatch` call in a later operation (in which proof data is not available), hence proof is ommitted from the signature. """ # Encrypt the notes outputs_and_notes = zip(mix_call_desc.outputs, prover_inputs.js_outputs) \ # pylint: disable=no-member output_notes_with_k_pk: List[Tuple[api.ZethNote, EncryptionPublicKey]] = \ [(note, zeth_addr.k_pk) for ((zeth_addr, _), note) in outputs_and_notes] ciphertexts = encrypt_notes(output_notes_with_k_pk) # Sign zksnark = get_zksnark_provider(self.prover_config.zksnark_name) signature = joinsplit_sign(zksnark, self.prover_config.pairing_parameters, signing_keypair, sender_eth_address, ciphertexts, ext_proof, public_data, for_dispatch_call) mix_params = MixParameters(ext_proof, public_data, signing_keypair.vk, signature, ciphertexts) return mix_params
def get_zksnark_provider(self) -> IZKSnarkProvider: """ Get the appropriate zksnark provider, based on the server configuration. """ config = self.get_configuration() return get_zksnark_provider(config.zksnark_name)