Skip to content

Commit

Permalink
contracts: merge verifier and mixer, and use const-sized array for in…
Browse files Browse the repository at this point in the history
…puts
  • Loading branch information
dtebbs committed Dec 20, 2019
1 parent 7dcf575 commit c2cba55
Show file tree
Hide file tree
Showing 9 changed files with 504 additions and 638 deletions.
2 changes: 0 additions & 2 deletions pyClient/zeth/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@

# GROTH16 constants
GROTH16_ZKSNARK: str = "GROTH16"
GROTH16_VERIFIER_CONTRACT: str = "Groth16Verifier"
GROTH16_MIXER_CONTRACT: str = "Groth16Mixer"

# PGHR13 constants
PGHR13_ZKSNARK: str = "PGHR13"
PGHR13_VERIFIER_CONTRACT: str = "Pghr13Verifier"
PGHR13_MIXER_CONTRACT: str = "Pghr13Mixer"

# Set of valid snarks
Expand Down
86 changes: 14 additions & 72 deletions pyClient/zeth/contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,58 +74,36 @@ def get_block_number(web3: Any) -> int:
return web3.eth.blockNumber


def compile_contracts(
zksnark: IZKSnarkProvider) -> Tuple[Interface, Interface]:
def compile_mixer(zksnark: IZKSnarkProvider) -> Interface:
contracts_dir = get_contracts_dir()
(proof_verifier_name, mixer_name) = zksnark.get_contract_names()

path_to_proof_verifier = os.path.join(
contracts_dir, proof_verifier_name + ".sol")
mixer_name = zksnark.get_contract_name()
path_to_mixer = os.path.join(contracts_dir, mixer_name + ".sol")

compiled_sol = compile_files(
[path_to_proof_verifier, path_to_mixer],
optimize=True)

proof_verifier_interface = \
compiled_sol[path_to_proof_verifier + ':' + proof_verifier_name]
mixer_interface = compiled_sol[path_to_mixer + ':' + mixer_name]

return (proof_verifier_interface, mixer_interface)


def compile_util_contracts() -> Tuple[Interface]:
contracts_dir = get_contracts_dir()
path_to_pairing = os.path.join(contracts_dir, "Pairing.sol")
path_to_bytes = os.path.join(contracts_dir, "Bytes.sol")
path_to_tree = os.path.join(contracts_dir, "MerkleTreeMiMC7.sol")
compiled_sol = compile_files(
[path_to_pairing, path_to_bytes, path_to_tree],
optimize=True)
tree_interface = compiled_sol[path_to_tree + ':' + "MerkleTreeMiMC7"]
return tree_interface
compiled_sol = compile_files([path_to_mixer], optimize=True)
return compiled_sol[path_to_mixer + ':' + mixer_name]


def deploy_mixer(
web3: Any,
proof_verifier_address: str,
mixer_interface: Interface,
mk_tree_depth: int,
mixer_interface: Interface,
vk: GenericVerificationKey,
deployer_address: str,
deployment_gas: int,
token_address: str) -> Tuple[Any, str]:
token_address: str,
zksnark: IZKSnarkProvider) -> Tuple[Any, str]:
"""
Common function to deploy a mixer contract. Returns the mixer and the
initial merkle root of the commitment tree
"""
# Deploy the Mixer contract once the Verifier is successfully deployed
# Deploy the Mixer
mixer = web3.eth.contract(
abi=mixer_interface['abi'], bytecode=mixer_interface['bin'])

verification_key_params = zksnark.verification_key_parameters(vk)
tx_hash = mixer.constructor(
snark_ver=proof_verifier_address,
mk_depth=mk_tree_depth,
token=token_address
token=token_address,
**verification_key_params
).transact({'from': deployer_address, 'gas': deployment_gas})
# Get tx receipt to get Mixer contract address
tx_receipt = web3.eth.waitForTransactionReceipt(tx_hash, 10000)
Expand All @@ -143,43 +121,6 @@ def deploy_mixer(
return(mixer, initial_root)


def deploy_contracts(
web3: Any,
mk_tree_depth: int,
proof_verifier_interface: Interface,
mixer_interface: Interface,
vk: GenericVerificationKey,
deployer_address: str,
deployment_gas: int,
token_address: str,
zksnark: IZKSnarkProvider) -> Tuple[Any, str]:
"""
Deploy the mixer contract with the given merkle tree depth and returns an
instance of the mixer along with the initial merkle tree root to use for
the first zero knowledge payments
"""
# Deploy the proof verifier contract with the good verification key
proof_verifier = web3.eth.contract(
abi=proof_verifier_interface['abi'],
bytecode=proof_verifier_interface['bin']
)

verifier_constr_params = zksnark.verifier_constructor_parameters(vk)
tx_hash = proof_verifier.constructor(**verifier_constr_params) \
.transact({'from': deployer_address, 'gas': deployment_gas})
tx_receipt = web3.eth.waitForTransactionReceipt(tx_hash, 10000)
proof_verifier_address = tx_receipt['contractAddress']

return deploy_mixer(
web3,
proof_verifier_address,
mixer_interface,
mk_tree_depth,
deployer_address,
deployment_gas,
token_address)


def deploy_tree_contract(
web3: Any,
interface: Interface,
Expand Down Expand Up @@ -221,11 +162,12 @@ def mix(
"""
pk_sender_encoded = encode_encryption_public_key(pk_sender)
proof_params = zksnark.mixer_proof_parameters(parsed_proof)
inputs = hex_to_int(parsed_proof["inputs"])
tx_hash = mixer_instance.functions.mix(
*proof_params,
[int(vk.ppk[0]), int(vk.ppk[1]), int(vk.spk[0]), int(vk.spk[1])],
sigma,
hex_to_int(parsed_proof["inputs"]),
inputs,
pk_sender_encoded,
ciphertext1,
ciphertext2,
Expand Down
7 changes: 2 additions & 5 deletions pyClient/zeth/joinsplit.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,13 +447,10 @@ def deploy(
write_verification_key(vk_json)

print("[INFO] 3. VK written, deploying smart contracts...")
(proof_verifier_interface, mixer_interface) = \
contracts.compile_contracts(zksnark)
contracts.compile_util_contracts()
(mixer_instance, initial_merkle_root) = contracts.deploy_contracts(
mixer_interface = contracts.compile_mixer(zksnark)
(mixer_instance, initial_merkle_root) = contracts.deploy_mixer(
web3,
mk_tree_depth,
proof_verifier_interface,
mixer_interface,
vk_json,
deployer_eth_address,
Expand Down
18 changes: 8 additions & 10 deletions pyClient/zeth/zksnark.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ class IZKSnarkProvider(ABC):

@staticmethod
@abstractmethod
def get_contract_names() -> Tuple[str, str]:
def get_contract_name() -> str:
"""
Get the verifier and mixer contracts for this SNARK.
"""
pass

@staticmethod
@abstractmethod
def verifier_constructor_parameters(
def verification_key_parameters(
vk: GenericVerificationKey) -> Dict[str, List[int]]:
pass

Expand Down Expand Up @@ -70,12 +70,11 @@ def mixer_proof_parameters(parsed_proof: GenericProof) -> List[List[int]]:
class Groth16SnarkProvider(IZKSnarkProvider):

@staticmethod
def get_contract_names() -> Tuple[str, str]:
return (
constants.GROTH16_VERIFIER_CONTRACT, constants.GROTH16_MIXER_CONTRACT)
def get_contract_name() -> str:
return constants.GROTH16_MIXER_CONTRACT

@staticmethod
def verifier_constructor_parameters(
def verification_key_parameters(
vk: GenericVerificationKey) -> Dict[str, List[int]]:
return {
"Alpha": hex_to_int(vk["alpha_g1"]),
Expand Down Expand Up @@ -118,12 +117,11 @@ def mixer_proof_parameters(parsed_proof: GenericProof) -> List[List[Any]]:
class PGHR13SnarkProvider(IZKSnarkProvider):

@staticmethod
def get_contract_names() -> Tuple[str, str]:
return (
constants.PGHR13_VERIFIER_CONTRACT, constants.PGHR13_MIXER_CONTRACT)
def get_contract_name() -> str:
return constants.PGHR13_MIXER_CONTRACT

@staticmethod
def verifier_constructor_parameters(
def verification_key_parameters(
vk: GenericVerificationKey) -> Dict[str, List[int]]:
return {
"A1": hex_to_int(vk["a"][0]),
Expand Down
9 changes: 6 additions & 3 deletions zeth-contracts/contracts/BaseMixer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ contract BaseMixer is MerkleTreeMiMC7, ERC223ReceivingContract {
// (ie: Appends the commitments to the tree, appends the nullifiers to the list and so on)
function check_mkroot_nullifiers_hsig_append_nullifiers_state(
uint[4] memory vk,
uint[] memory primary_inputs) internal {
uint[nbInputs] memory primary_inputs) internal {
// 1. We re-assemble the full root digest and check it is in the tree
require(
roots[bytes32(primary_inputs[0])],
Expand Down Expand Up @@ -169,7 +169,8 @@ contract BaseMixer is MerkleTreeMiMC7, ERC223ReceivingContract {
}

function assemble_commitments_and_append_to_state(
uint[] memory primary_inputs) internal {
uint[nbInputs] memory primary_inputs
) internal {
// We re-assemble the commitments (JSOutputs)
for(uint i = 1 + 2 * jsIn ; i < 1 + 2*(jsIn + jsOut); i += 2) {
// See the way the inputs are ordered in the extended proof
Expand All @@ -180,7 +181,9 @@ contract BaseMixer is MerkleTreeMiMC7, ERC223ReceivingContract {
}
}

function process_public_values(uint[] memory primary_inputs) internal {
function process_public_values(
uint[nbInputs] memory primary_inputs
) internal {
// 1. We get the vpub_in in wei
uint vpub_in_zeth_units = Bytes.get_value_from_inputs(
Bytes.int256ToBytes8(primary_inputs[1 + 2*(jsIn + jsOut)]));
Expand Down
Loading

0 comments on commit c2cba55

Please sign in to comment.