├── .clang-format ├── .clang-tidy ├── .cppcheck.suppressions ├── .dockerignore ├── .editorconfig ├── .git-hooks ├── README.md └── pre-commit ├── .gitattributes ├── .github ├── CODEOWNERS └── workflows │ ├── dev-docker-apps.yml │ ├── dev-docs.yml │ ├── onpullrequest-build-ubuntu.yml │ ├── onpush-build-macos.yml │ ├── onpush-build-ubuntu.yml │ ├── onpush-checks.yml │ ├── release-docker-apps.yml │ └── release-docker-base.yml ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── CODE_OF_CONDUCT.md ├── CODING_STANDARDS.md ├── CONTRIBUTING.md ├── Dockerfile-base ├── Dockerfile-client ├── Dockerfile-dev ├── Dockerfile-mpc ├── Dockerfile-prover ├── Doxyfile.in ├── LICENSE ├── README.md ├── README_doxygen.md ├── client ├── .flake8 ├── .pylintrc ├── Makefile ├── README.md ├── multiple_test.sh ├── mypy.ini ├── py.typed ├── requirements.txt ├── setup.py ├── test_commands │ ├── __init__.py │ ├── deploy_test_token.py │ ├── mock.py │ ├── scenario.py │ ├── test_erc_token_mixing.py │ └── test_ether_mixing.py ├── test_contracts │ ├── __init__.py │ ├── test_bls12_377_contract.py │ ├── test_bw6_761_contract.py │ ├── test_groth16_bls12_377_contract.py │ └── test_mimc_contract.py ├── tests │ ├── __init__.py │ ├── test_encryption.py │ ├── test_ethervalue.py │ ├── test_input_hasher.py │ ├── test_joinsplit.py │ ├── test_merkle_tree.py │ ├── test_mimc.py │ ├── test_mixer_client.py │ ├── test_pairing.py │ ├── test_signing.py │ └── test_zksnark.py └── zeth │ ├── __init__.py │ ├── api │ ├── __init__.py │ └── py.typed │ ├── cli │ ├── __init__.py │ ├── constants.py │ ├── py.typed │ ├── utils.py │ ├── zeth.py │ ├── zeth_deploy.py │ ├── zeth_gen_address.py │ ├── zeth_get_verification_key.py │ ├── zeth_ls_commits.py │ ├── zeth_ls_notes.py │ ├── zeth_mix.py │ ├── zeth_sync.py │ └── zeth_wait.py │ ├── core │ ├── __init__.py │ ├── constants.py │ ├── contracts.py │ ├── encryption.py │ ├── errors.py │ ├── input_hasher.py │ ├── merkle_tree.py │ ├── mimc.py │ ├── mixer_client.py │ ├── ownership.py │ ├── pairing.py │ ├── proto_utils.py │ ├── prover_client.py │ ├── py.typed │ ├── signing.py │ ├── timer.py │ ├── utils.py │ ├── wallet.py │ ├── zeth_address.py │ └── zksnark.py │ └── helper │ ├── __init__.py │ ├── eth_fund.py │ ├── eth_gen_address.py │ ├── eth_gen_network_config.py │ ├── eth_get_balance.py │ ├── eth_get_contract_address.py │ ├── eth_send.py │ ├── token_approve.py │ └── zeth_helper.py ├── cmake ├── FindProtobuf.cmake ├── FindgRPC.cmake ├── clang_dev_tools.cmake ├── code_coverage.cmake ├── documentation.cmake ├── gcc_dev_tools.cmake └── sanitizers.cmake ├── debug ├── README.md └── analyzer │ ├── README.md │ ├── __init__.py │ └── parse_r1cs.py ├── depends ├── .clang-format ├── .clang-tidy └── CMakeLists.txt ├── libtool ├── CMakeLists.txt ├── command.hpp ├── run.hpp ├── run.tcc ├── subcommand.hpp ├── subcommand.tcc ├── tool_util.cpp └── tool_util.hpp ├── libzeth ├── CMakeLists.txt ├── circuits │ ├── binary_operation.hpp │ ├── binary_operation.tcc │ ├── blake2s │ │ ├── blake2s.hpp │ │ ├── blake2s.tcc │ │ ├── blake2s_comp.hpp │ │ ├── blake2s_comp.tcc │ │ ├── blake2s_comp_setup.tcc │ │ ├── g_primitive.hpp │ │ └── g_primitive.tcc │ ├── circuit_types.hpp │ ├── circuit_utils.hpp │ ├── circuit_utils.tcc │ ├── circuit_wrapper.hpp │ ├── circuit_wrapper.tcc │ ├── commitments │ │ ├── commitment.hpp │ │ └── commitment.tcc │ ├── joinsplit.tcc │ ├── merkle_tree │ │ ├── merkle_path_authenticator.hpp │ │ ├── merkle_path_authenticator.tcc │ │ ├── merkle_path_compute.hpp │ │ ├── merkle_path_compute.tcc │ │ ├── merkle_path_selector.hpp │ │ └── merkle_path_selector.tcc │ ├── mimc │ │ ├── mimc_input_hasher.hpp │ │ ├── mimc_input_hasher.tcc │ │ ├── mimc_mp.hpp │ │ ├── mimc_mp.tcc │ │ ├── mimc_permutation.hpp │ │ ├── mimc_permutation.tcc │ │ ├── mimc_round.hpp │ │ ├── mimc_round.tcc │ │ └── mimc_selector.hpp │ ├── notes │ │ ├── note.hpp │ │ └── note.tcc │ ├── prfs │ │ ├── prf.hpp │ │ └── prf.tcc │ ├── safe_arithmetic.cpp │ ├── safe_arithmetic.hpp │ └── sha256 │ │ ├── sha256_ethereum.hpp │ │ └── sha256_ethereum.tcc ├── core │ ├── bits.cpp │ ├── bits.hpp │ ├── bits.tcc │ ├── chacha_rng.cpp │ ├── chacha_rng.hpp │ ├── evaluator_from_lagrange.hpp │ ├── evaluator_from_lagrange.tcc │ ├── extended_proof.hpp │ ├── extended_proof.tcc │ ├── field_element_utils.hpp │ ├── field_element_utils.tcc │ ├── group_element_utils.hpp │ ├── group_element_utils.tcc │ ├── hash_stream.hpp │ ├── hash_stream.tcc │ ├── include_libff.hpp │ ├── include_libsnark.hpp │ ├── joinsplit_input.hpp │ ├── merkle_tree_field.hpp │ ├── merkle_tree_field.tcc │ ├── multi_exp.hpp │ ├── multi_exp.tcc │ ├── note.hpp │ ├── utils.cpp │ ├── utils.hpp │ └── utils.tcc ├── mpc │ └── groth16 │ │ ├── mpc_hash.cpp │ │ ├── mpc_hash.hpp │ │ ├── mpc_utils.hpp │ │ ├── mpc_utils.tcc │ │ ├── phase2.hpp │ │ ├── phase2.tcc │ │ ├── powersoftau_utils.cpp │ │ ├── powersoftau_utils.hpp │ │ └── powersoftau_utils.tcc ├── serialization │ ├── filesystem_util.cpp │ ├── filesystem_util.hpp │ ├── proto_utils.cpp │ ├── proto_utils.hpp │ ├── proto_utils.tcc │ ├── r1cs_serialization.hpp │ ├── r1cs_serialization.tcc │ ├── r1cs_variable_assignment_serialization.hpp │ ├── r1cs_variable_assignment_serialization.tcc │ ├── stream_utils.hpp │ └── stream_utils.tcc ├── snarks │ ├── groth16 │ │ ├── groth16_api_handler.hpp │ │ ├── groth16_api_handler.tcc │ │ ├── groth16_snark.hpp │ │ └── groth16_snark.tcc │ └── pghr13 │ │ ├── pghr13_api_handler.hpp │ │ ├── pghr13_api_handler.tcc │ │ ├── pghr13_snark.hpp │ │ └── pghr13_snark.tcc ├── tests │ ├── CMakeLists.txt │ ├── README.md │ ├── circuits │ │ ├── binary_operation_test.cpp │ │ ├── blake2s_test.cpp │ │ ├── commitments_test.cpp │ │ ├── merkle_tree_test.cpp │ │ ├── mimc_input_hasher_test.cpp │ │ ├── mimc_mp_test.cpp │ │ ├── note_test.cpp │ │ ├── packed_addition_test.cpp │ │ ├── prfs_test.cpp │ │ ├── sha256_test.cpp │ │ ├── simple_test.cpp │ │ ├── simple_test.hpp │ │ └── simple_test.tcc │ ├── core │ │ ├── bits_test.cpp │ │ ├── chacha_test.cpp │ │ ├── ec_operation_data_test.cpp │ │ ├── evaluator_from_lagrange_test.cpp │ │ ├── field_element_utils_test.cpp │ │ ├── group_element_utils_test.cpp │ │ └── utils_test.cpp │ ├── mpc │ │ └── groth16 │ │ │ ├── mpc_hash_test.cpp │ │ │ ├── mpc_test.cpp │ │ │ └── powersoftau_test.cpp │ ├── prover │ │ └── prover_test.cpp │ ├── serialization │ │ ├── proto_utils_test.cpp │ │ ├── r1cs_serialization_test.cpp │ │ └── r1cs_variable_assignment_serialization_test.cpp │ └── snarks │ │ ├── common_api_tests.tcc │ │ ├── common_snark_tests.tcc │ │ ├── groth16 │ │ ├── groth16_api_handler_test.cpp │ │ └── groth16_snark_test.cpp │ │ └── pghr13 │ │ ├── pghr13_api_handler_test.cpp │ │ └── pghr13_snark_test.cpp └── zeth_constants.hpp ├── mpc ├── .flake8 ├── .pylintrc ├── Makefile ├── README.md ├── commands │ ├── __init__.py │ ├── constants.py │ ├── contributors_from_csv │ ├── create_keypair │ ├── generate_key │ ├── get_challenge │ ├── phase1_contribute │ ├── phase1_server │ ├── phase2_contribute │ ├── phase2_prepare │ ├── phase2_server │ ├── public_key │ ├── public_key_operations.py │ ├── sign_contribution │ └── upload_contribution ├── coordinator │ ├── __init__.py │ ├── client.py │ ├── contribute.py │ ├── contributor_list.py │ ├── crypto.py │ ├── icontributionhandler.py │ ├── interval.py │ ├── mpc_command.py │ ├── null_contribution_handler.py │ ├── phase1_contribution_handler.py │ ├── phase2_contribution_handler.py │ ├── powersoftau_command.py │ ├── powersoftau_process_command.py │ ├── server.py │ ├── server_configuration.py │ ├── server_state.py │ └── upload_utils.py ├── mypy.ini ├── requirements.txt ├── setup.py └── test │ ├── __init__.py │ ├── test_crypto.py │ └── test_server_state.py ├── mpc_tools ├── CMakeLists.txt ├── README.md ├── mpc_phase2 │ ├── CMakeLists.txt │ ├── cli │ │ ├── README.md │ │ ├── mpc_common.cpp │ │ ├── mpc_common.hpp │ │ ├── mpc_create_keypair.cpp │ │ ├── mpc_dummy_phase2.cpp │ │ ├── mpc_linear_combination.cpp │ │ ├── mpc_phase2_begin.cpp │ │ ├── mpc_phase2_contribute.cpp │ │ ├── mpc_phase2_verify_contribution.cpp │ │ ├── mpc_phase2_verify_transcript.cpp │ │ └── mpc_subcommand.hpp │ ├── mpc_client.cpp │ ├── mpc_coord.cpp │ └── test │ │ └── mpc_test_cli.cpp └── pot_process │ ├── README.md │ └── pot_process.cpp ├── proto └── zeth │ └── api │ ├── ec_group_messages.proto │ ├── groth16_messages.proto │ ├── pghr13_messages.proto │ ├── prover.proto │ ├── snark_messages.proto │ └── zeth_messages.proto ├── prover_server ├── CMakeLists.txt ├── README.md └── prover_server.cpp ├── scripts ├── build_utils.sh ├── check-copyright ├── ci ├── ci_utils.sh ├── docker │ └── entrypoint-mpc ├── ec2-setup ├── format ├── ganache-start ├── install-grpc ├── mimc_constraints.sage ├── mpc-setup ├── prover-profile ├── recover-keypair ├── set-jsinout ├── test-mpc-contributors-from-csv ├── test-mpc-server-phase1 ├── test-mpc-server-phase2 ├── test-phase2 ├── test-pot-process ├── test-zeth-cli ├── test-zeth-cli-token ├── test_mpc_common.sh ├── test_zeth_cli_common.sh ├── test_zeth_cli_get_accounts.js ├── test_zeth_cli_new_account.js ├── test_zeth_cli_show_balances.js └── test_zeth_cli_show_balances_named.js ├── setup_env.sh ├── testdata ├── mpc_contributors.json ├── mpc_key1.bin ├── mpc_key1.evidence ├── mpc_key1.pub ├── mpc_key2.bin ├── mpc_key2.evidence ├── mpc_key2.pub ├── mpc_key3.bin ├── mpc_key3.evidence ├── mpc_key3.pub ├── mpc_key4.bin ├── mpc_key4.evidence ├── mpc_key4.pub ├── mpc_phase1_server_config.json ├── mpc_phase2_server_config.json ├── powersoftau_challenge.4.bin ├── test_mpc_registration.csv └── test_mpc_registration_invalid.csv ├── zeth_config.h.in ├── zeth_contracts ├── .solhint.json ├── .solhintignore ├── contracts │ ├── AbstractMerkleTree.sol │ ├── AbstractMixer.sol │ ├── AbstractMixerAltBN128.sol │ ├── AbstractMixerBLS12_377.sol │ ├── ERC20Mintable.sol │ ├── LibGroth16AltBN128.sol │ ├── LibGroth16BLS12_377.sol │ ├── LibMiMC.sol │ ├── LibOTSchnorrVerifier.sol │ ├── LibPairing.sol │ ├── Migrations.sol │ ├── MixerGroth16AltBN128.sol │ ├── MixerGroth16BLS12_377.sol │ ├── MixerPghr13AltBN128.sol │ ├── README.md │ ├── TestBLS12_377.sol │ ├── TestBW6_761.sol │ ├── TestBaseMixerAltBN128.sol │ ├── TestGroth16BLS12_377.sol │ ├── TestMerkleTreeMiMCAltBN128.sol │ ├── TestMiMC.sol │ └── Tokens.sol ├── migrations │ └── 1_initial_migration.js ├── package.json └── truffle.js └── zeth_tool ├── CMakeLists.txt ├── README.md ├── dump_proof_cmd.cpp ├── dump_proof_cmd.hpp ├── joinsplit_circuit_cmd.cpp ├── joinsplit_circuit_cmd.hpp ├── main.cpp ├── prove_cmd.cpp ├── prove_cmd.hpp ├── split_keypair_cmd.cpp ├── split_keypair_cmd.hpp ├── tool_common.hpp ├── verify_cmd.cpp └── verify_cmd.hpp /.cppcheck.suppressions: -------------------------------------------------------------------------------- 1 | // Errors and Warnings to Suppress 2 | useStlAlgorithm:* 3 | 4 | // This raises some false positives, and inline suppressions seem not to work 5 | unusedFunction:* 6 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | build/ 2 | Dockerfile* 3 | client/env 4 | mpc/env 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = lf 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | charset = utf-8 10 | 11 | [*.yml] 12 | indent_size = 2 13 | 14 | -------------------------------------------------------------------------------- /.git-hooks/README.md: -------------------------------------------------------------------------------- 1 | # Zeth git hooks 2 | 3 | In order to use these hooks you can either: 4 | 1. Move the hooks of interest in your local `/.git/hooks` folder, or 5 | 2. Run (if `git --version` is `>2.9`): 6 | ```bash 7 | git config core.hooksPath hooks 8 | ``` 9 | -------------------------------------------------------------------------------- /.git-hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Git pre-commit hook for Zeth 4 | 5 | red="\033[0;31m" 6 | yellow="\033[1;33m" 7 | green="\033[1;32m" 8 | reset="\033[0m" 9 | 10 | # Run the format script before commits are made 11 | echo -e "${yellow}\n Formatting files \n${reset}" 12 | $ZETH/scripts/format 13 | res=$? 14 | if [ $res -ne 0 ] 15 | then 16 | echo -e "${red}\n Formatting FAILED\n\n commit ABORTED${reset}" 17 | exit 1 18 | else 19 | echo -e "${green}\nFormatting OK\n${reset}" 20 | fi 21 | 22 | exit 0 23 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # See: https://github.com/github/linguist/blob/master/lib/linguist/languages.yml 2 | 3 | *.tcc linguist-language=C++ 4 | *.sol linguist-language=Solidity 5 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Lines starting with '#' are comments. 2 | # Each line is a file pattern followed by one or more owners. 3 | 4 | * @AntoineRondelet @dtebbs 5 | -------------------------------------------------------------------------------- /.github/workflows/dev-docker-apps.yml: -------------------------------------------------------------------------------- 1 | name: dev-docker-build-zeth-apps 2 | 3 | on: 4 | push: 5 | branches: 6 | - develop 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | env: 12 | REPO_OWNER: "clearmatics" 13 | 14 | jobs: 15 | 16 | docker-build: 17 | name: Docker build 18 | runs-on: ubuntu-20.04 19 | timeout-minutes: 180 20 | 21 | strategy: 22 | fail-fast: true 23 | matrix: 24 | # Disable mpc for now 25 | # app: ['mpc', 'client', 'prover'] 26 | app: ['client', 'prover'] 27 | max-parallel: 3 28 | 29 | steps: 30 | - name: Checkout 31 | uses: actions/checkout@v2 32 | 33 | - name: Get vars from git 34 | id: git_vars 35 | run: echo ::set-output name=COMMIT_HASH::$(git rev-parse --short HEAD) 36 | 37 | - name: Configure Docker 38 | run: echo ${{ secrets.CR_PAT }} | docker login ghcr.io -u $GITHUB_ACTOR --password-stdin 39 | 40 | - name: Set up Buildx 41 | id: buildx 42 | uses: docker/setup-buildx-action@v1 43 | with: 44 | version: latest 45 | 46 | - name: Build and push image git-SHA 47 | run: | 48 | docker buildx build \ 49 | --tag ghcr.io/$GITHUB_REPOSITORY:git-${{ steps.git_vars.outputs.COMMIT_HASH }}-${{ matrix.app }} \ 50 | --cache-from=type=registry,ref=ghcr.io/$GITHUB_REPOSITORY:cache-${{ matrix.app }} \ 51 | --cache-to=type=registry,ref=ghcr.io/$GITHUB_REPOSITORY:cache-${{ matrix.app }} \ 52 | --platform linux/amd64 \ 53 | --output "type=image,push=true" \ 54 | --file ./Dockerfile-${{ matrix.app }} ./ 55 | -------------------------------------------------------------------------------- /.github/workflows/dev-docs.yml: -------------------------------------------------------------------------------- 1 | name: zeth-ci-dev-docs 2 | 3 | on: 4 | push: 5 | branches: [ develop ] 6 | 7 | jobs: 8 | build-grpc: 9 | runs-on: ubuntu-20.04 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Cache grpc 13 | uses: actions/cache@v2 14 | with: 15 | key: grpc-1.44.x-${{ runner.os }} 16 | path: depends/grpc 17 | - name: Build grpc 18 | run: if ! [ -d depends/grpc ] ; then scripts/install-grpc /usr v1.44.x ; fi 19 | 20 | build-documentation: 21 | runs-on: ubuntu-20.04 22 | needs: build-grpc 23 | steps: 24 | - name: Checkout repository and install submodules 25 | uses: actions/checkout@v2 26 | with: 27 | submodules: recursive 28 | - name: Cache grpc 29 | uses: actions/cache@v2 30 | with: 31 | key: grpc-1.44.x-${{ runner.os }} 32 | path: depends/grpc 33 | - name: Install dependencies 34 | run: | 35 | sudo apt update -y 36 | source scripts/build_utils.sh 37 | init_platform 38 | cpp_build_setup 39 | INSTALL_ONLY=1 scripts/install-grpc /usr v1.44.x 40 | sudo apt install -y doxygen graphviz 41 | - name: Generate documentation 42 | run: | 43 | mkdir -p build 44 | pushd build 45 | cmake -DGEN_DOC=ON .. 46 | make build_docs 47 | popd 48 | - name: GH Pages Deployment 49 | uses: peaceiris/actions-gh-pages@v3 50 | with: 51 | github_token: ${{ secrets.GITHUB_TOKEN }} 52 | publish_dir: ./build/docs/html/ 53 | enable_jekyll: false 54 | allow_empty_commit: false 55 | force_orphan: true 56 | publish_branch: doxy-gh-pages 57 | -------------------------------------------------------------------------------- /.github/workflows/onpush-build-macos.yml: -------------------------------------------------------------------------------- 1 | # Build actions for every push on macOS 2 | name: zeth-ci-push-build-macos 3 | 4 | on: 5 | push: 6 | 7 | env: 8 | MACOS_BREW_PACKAGES: "autoconf automake boost cmake gmp grpc openssl pkg-config protobuf libomp libtool" 9 | HOMEBREW_NO_AUTO_UPDATE: 1 10 | 11 | jobs: 12 | 13 | # Extract the commits of submodules for use by cache steps 14 | submodules: 15 | runs-on: ubuntu-20.04 16 | outputs: 17 | commits: ${{ steps.get-commits.outputs.commits }} 18 | steps: 19 | - uses: actions/checkout@v2 20 | - name: Get Submodule Commits 21 | id: get-commits 22 | run: | 23 | git submodule sync 24 | echo "::set-output name=commits::"`git submodule status depends/libsodium | grep -oe '[0-9a-fA-F]\+' | head -c 8`-`git submodule status depends/libsnark | grep -oe '[0-9a-fA-F]\+' | head -c 8` 25 | 26 | # Main build 27 | build-macos: 28 | runs-on: macos-11 29 | needs: submodules 30 | strategy: 31 | matrix: 32 | config: [ Debug, Release ] 33 | steps: 34 | - uses: actions/checkout@v2 35 | with: 36 | submodules: recursive 37 | - name: Set up Python 3.8 38 | uses: actions/setup-python@v2 39 | with: 40 | python-version: '3.8' 41 | - name: Cache ccache 42 | uses: actions/cache@v2 43 | with: 44 | key: submodules-${{ needs.submodules.outputs.commits }}-${{ runner.os }}-${{ matrix.config }} 45 | path: ~/Library/Caches/ccache 46 | - name: Cache pip (for mpc tests) 47 | uses: actions/cache@v2 48 | with: 49 | path: ~/Library/Caches/pip 50 | key: build-macos-pip-${{ hashFiles('**/setup.py') }}-${{ runner.os }} 51 | - name: Install Dependencies 52 | run: | 53 | brew install ${MACOS_BREW_PACKAGES} 54 | brew link llvm@14 55 | which clang 56 | which clang++ 57 | clang --version 58 | clang++ --version 59 | python3 -V 60 | - name: Execute 61 | env: 62 | CXX: clang 63 | run: | 64 | CI_MPC_TESTS=1 CI_CONFIG=${{ matrix.config }} scripts/ci build 65 | -------------------------------------------------------------------------------- /.github/workflows/onpush-checks.yml: -------------------------------------------------------------------------------- 1 | # Check actions (linters, analysis tools etc.) 2 | name: zeth-ci-onpush-checks 3 | 4 | on: 5 | push: 6 | 7 | jobs: 8 | 9 | check-contracts: 10 | runs-on: ubuntu-20.04 11 | steps: 12 | - uses: actions/checkout@v2 13 | with: 14 | submodules: recursive 15 | - name: Set up Python 3.8 16 | uses: actions/setup-python@v2 17 | with: 18 | python-version: '3.8' 19 | - name: Cache pip 20 | uses: actions/cache@v2 21 | with: 22 | path: | 23 | ~/.cache/pip 24 | ~/.solcx 25 | key: check-contracts-pip-solcx-${{ hashFiles('**/setup.py') }}-${{ runner.os }} 26 | - name: Check Contracts 27 | run: scripts/ci check_contracts 28 | 29 | check-client: 30 | runs-on: ubuntu-20.04 31 | steps: 32 | - uses: actions/checkout@v2 33 | with: 34 | submodules: recursive 35 | - name: Set up Python 3.8 36 | uses: actions/setup-python@v2 37 | with: 38 | python-version: '3.8' 39 | - name: Cache pip 40 | uses: actions/cache@v2 41 | with: 42 | path: ~/.cache/pip 43 | key: check-client-pip-${{ hashFiles('**/setup.py') }}-${{ runner.os }} 44 | - name: Check Client 45 | run: scripts/ci check_client 46 | 47 | check-cpp-linux: 48 | runs-on: ubuntu-20.04 49 | steps: 50 | - uses: actions/checkout@v2 51 | with: 52 | submodules: recursive 53 | - name: Execute 54 | run: CI_CHECK_FORMAT=1 CI_USE_DOCKER=1 scripts/ci check_cpp 55 | -------------------------------------------------------------------------------- /.github/workflows/release-docker-base.yml: -------------------------------------------------------------------------------- 1 | name: release-docker-build-zeth-base 2 | 3 | on: 4 | push: 5 | tags: 6 | - docker-base-v[0-9]+.[0-9]+.[0-9]+ # Triggered by git tags like: docker-base-v0.2.12 7 | 8 | jobs: 9 | 10 | docker-build: 11 | name: Docker build 12 | runs-on: ubuntu-20.04 13 | timeout-minutes: 360 14 | 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v2 18 | 19 | - name: Create swap from file 20 | run: | 21 | sudo fallocate -l 19G /swapfile2 22 | sudo chmod 600 /swapfile2 23 | sudo mkswap /swapfile2 24 | sudo swapon /swapfile2 25 | 26 | - name: Show build host parameters 27 | run: | 28 | free -h 29 | df -h 30 | nproc 31 | 32 | - name: Get vars from git 33 | id: git_vars 34 | run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\/docker-base-v/} 35 | 36 | - name: Configure Docker 37 | run: echo ${{ secrets.CR_PAT }} | docker login ghcr.io -u $GITHUB_ACTOR --password-stdin 38 | 39 | - name: Docker build 40 | run: docker build -f ./Dockerfile-base -t ghcr.io/$GITHUB_REPOSITORY:${{ steps.git_vars.outputs.VERSION }}-base . 41 | 42 | - name: Docker push 43 | run: | 44 | docker push ghcr.io/$GITHUB_REPOSITORY:${{ steps.git_vars.outputs.VERSION }}-base 45 | docker tag ghcr.io/$GITHUB_REPOSITORY:${{ steps.git_vars.outputs.VERSION }}-base ghcr.io/$GITHUB_REPOSITORY:latest-base 46 | docker push ghcr.io/$GITHUB_REPOSITORY:latest-base 47 | 48 | - name: Docker Info 49 | run: | 50 | docker inspect ghcr.io/$GITHUB_REPOSITORY:${{ steps.git_vars.outputs.VERSION }}-base 51 | docker history ghcr.io/$GITHUB_REPOSITORY:${{ steps.git_vars.outputs.VERSION }}-base --no-trunc 52 | docker version 53 | docker info 54 | uname -a 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore the build repo 2 | /build/ 3 | 4 | # Ignore the notes we created 5 | /notestore/ 6 | 7 | # Ignore the output of the trusted setup (ie: Proving and Verifying key) 8 | /zeth_setup/ 9 | 10 | # Ignore the content of the debug folder 11 | debug/*json 12 | 13 | # Ignore node_modules 14 | /zeth_contracts/node_modules/* 15 | 16 | # Ignore client env and build directories 17 | /client/zeth/api/*_pb2.py 18 | /client/zeth/api/*_pb2_grpc.py 19 | /client/zeth/api/*_pb2.pyi 20 | 21 | # Ignore test files 22 | /_test_contrib_*/ 23 | /_test_phase1_contrib_*/ 24 | /_test_contributors_from_csv/ 25 | /_test_server_phase*/ 26 | /_test_phase2_data/ 27 | /_test_zeth_cli/ 28 | /_test_zeth_cli_token/ 29 | 30 | # Ignore python cache dirs 31 | 32 | # Python temp files 33 | __pycache__ 34 | .mypy_cache 35 | env/ 36 | *.egg-info 37 | 38 | # Ignore some unix temp files 39 | *~ 40 | \#*\# 41 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "depends/libsnark"] 2 | path = depends/libsnark 3 | url = https://github.com/clearmatics/libsnark.git 4 | [submodule "depends/libsodium"] 5 | path = depends/libsodium 6 | url = https://github.com/jedisct1/libsodium.git 7 | [submodule "depends/ganache-cli"] 8 | path = depends/ganache-cli 9 | url = http://github.com/clearmatics/ganache-cli 10 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the changes you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note that we have a code of conduct. Please follow it in all your interactions with the project. 7 | 8 | ## Coding Standards 9 | 10 | Coding standards are described in full [here](CODING_STANDARDS.md). 11 | 12 | ## Pull Request Process 13 | 14 | 1. Ensure any install or build dependencies are removed from your branch before opening a Pull Request. 15 | Furthermore, please do make sure to extend the [.gitignore](./.gitignore) file to keep unnecessary files 16 | outside of the version control. 17 | 2. Update the README.md files and the relevant code comments with details of changes to the interface. 18 | This includes: new environment variables, exposed ports, useful file locations and container parameters for instance. 19 | 3. If the Pull Request requires a version change (e.g. a "fix" or new release), increase the version numbers in all relevant files. 20 | The versioning scheme we use is [SemVer][semver]. 21 | 4. All Pull Requests must be reviewed by a code owner. While under review, a code owner may ask the Pull Request author to *rebase* 22 | her branch on top of the targeted "base" branch. If so, please be sure to *rebase* on top of the base branch (and *not merge* 23 | the base branch in your branch), as we strive to avoid duplicated merge commits in the git history (merging is a unidirectional 24 | process e.g. `master < develop < feature` or `master < hotfix`). 25 | 5. Once approved, the Pull Request is merged by one of the code owners. 26 | 27 | ## Code of Conduct 28 | 29 | This project and everyone participating in it is governed by the [Code of Conduct][codeofconduct]. 30 | By participating, you are expected to uphold this code. Please report unacceptable behavior to [opensource@clearmatics.com][email]. 31 | 32 | [codeofconduct]: CODE_OF_CONDUCT.md 33 | [semver]: http://semver.org/ 34 | [email]: mailto:opensource@clearmatics.com 35 | -------------------------------------------------------------------------------- /Dockerfile-dev: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/clearmatics/zeth:0.0.2-base 2 | 3 | LABEL org.opencontainers.image.source https://github.com/clearmatics/zeth 4 | 5 | COPY . /home/zeth 6 | 7 | RUN cd /home/zeth && git submodule update --init --recursive 8 | 9 | WORKDIR /home/zeth 10 | 11 | CMD ["/bin/bash"] 12 | -------------------------------------------------------------------------------- /Dockerfile-mpc: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/clearmatics/zeth:0.0.2-base AS stage1 2 | 3 | LABEL org.opencontainers.image.source https://github.com/clearmatics/zeth 4 | 5 | # 1. Build phase 1: powers of tau rust binaries 6 | ENV POT_PATH=/home/powersoftau 7 | RUN apk --update --no-cache add \ 8 | musl-dev \ 9 | rust \ 10 | cargo 11 | 12 | RUN git clone https://github.com/clearmatics/powersoftau ${POT_PATH} 13 | RUN cd ${POT_PATH} \ 14 | && git submodule update --init --recursive \ 15 | && cargo install --path . \ 16 | && mv /root/.cargo/bin/* /usr/local/bin 17 | 18 | # 2. Build phase 2: phase 2 c++ binaries 19 | ENV ZETH_PATH=/home/zeth 20 | COPY . ${ZETH_PATH} 21 | 22 | RUN cd ${ZETH_PATH} \ 23 | && git submodule update --init --recursive 24 | 25 | RUN cd ${ZETH_PATH} && mkdir build && cd build \ 26 | && cmake -DSTATIC_BUILD=ON .. \ 27 | && make -j"$(($(nproc)+1))" mpc-client-phase2 \ 28 | && mv ${ZETH_PATH}/build/mpc_tools/mpc_phase2/mpc-client-phase2 /usr/local/bin 29 | 30 | ## 31 | 32 | FROM alpine:3.12 33 | 34 | LABEL org.opencontainers.image.source https://github.com/clearmatics/zeth 35 | 36 | # Move rust and c++ binaries from previous image and put it in the PATH 37 | COPY --from=stage1 /usr/local/bin/ /usr/local/bin 38 | # Move the mpc python code 39 | COPY --from=stage1 /home/zeth/mpc/ /home/zeth-mpc 40 | COPY --from=stage1 /home/zeth/scripts/docker/entrypoint-mpc /home/zeth-mpc/entrypoint 41 | RUN apk --update --no-cache add \ 42 | bash \ 43 | # Install necessary shared libs to run the rust binaries 44 | gcc \ 45 | # Necessary packages to use the MPC python code 46 | build-base \ 47 | linux-headers \ 48 | python3-dev \ 49 | make 50 | 51 | RUN cd /home/zeth-mpc \ 52 | && python3 -m venv env \ 53 | && source env/bin/activate \ 54 | && make setup 55 | 56 | RUN apk del \ 57 | linux-headers \ 58 | build-base \ 59 | make 60 | 61 | WORKDIR /home/zeth-mpc 62 | 63 | ENTRYPOINT ["./entrypoint"] 64 | CMD ["/bin/bash"] 65 | -------------------------------------------------------------------------------- /Dockerfile-prover: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/clearmatics/zeth:0.0.2-base AS stage1 2 | 3 | LABEL org.opencontainers.image.source https://github.com/clearmatics/zeth 4 | 5 | ENV ZETH_PATH=/home/zeth 6 | # Copy necessary files in the docker container 7 | COPY . ${ZETH_PATH} 8 | 9 | # Install the submodules 10 | RUN cd ${ZETH_PATH} \ 11 | && git submodule update --init --recursive 12 | 13 | # Build `prover-server` 14 | RUN cd ${ZETH_PATH} \ 15 | && mkdir build \ 16 | && cd build \ 17 | && cmake -DMPC=OFF -DSTATIC_BUILD=ON .. \ 18 | && make -j"$($(nprocs)+1)" prover-server 19 | 20 | ## 21 | 22 | FROM alpine:3.12 23 | 24 | LABEL org.opencontainers.image.source https://github.com/clearmatics/zeth 25 | 26 | RUN apk add --no-cache bash 27 | ## Move `prover-server` from previous image and put it in the PATH 28 | COPY --from=stage1 /home/zeth/build/prover_server/prover-server /usr/local/bin 29 | CMD ["/bin/bash"] 30 | -------------------------------------------------------------------------------- /README_doxygen.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | This is the developer documentation of the reference implementation of Zeth (Zerocash on ETHereum), an experimental digital-cash system for EVM-based chains. 4 | 5 | The software is an open source project and all community contributions are welcomed. The project is released under the LGPL-3.0 license. 6 | 7 | See https://github.com/clearmatics/zeth for further information about the project. 8 | -------------------------------------------------------------------------------- /client/.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length=82 3 | -------------------------------------------------------------------------------- /client/.pylintrc: -------------------------------------------------------------------------------- 1 | [MESSAGES CONTROL] 2 | disable= 3 | bad-continuation, 4 | too-many-arguments, 5 | missing-class-docstring, 6 | missing-function-docstring, 7 | too-many-locals, 8 | too-many-statements, 9 | too-few-public-methods, 10 | wrong-import-order, 11 | missing-module-docstring, 12 | broad-except, 13 | too-many-function-args, 14 | duplicate-code, 15 | fixme, 16 | unsubscriptable-object, 17 | 18 | # TODO: `unsubscriptable-object` generates false positives for python 3.9 and pylint==2.6. 19 | # https://github.com/PyCQA/pylint/issues/3882 20 | # Re-enable it when the issue is fixed. 21 | 22 | good-names=a,b,c,e,g,h,i,k,m,q,r,x,y,z,cm,ic,rc,ek,ex,ct,vk,sk,pk,pp,X,Y,r,el,nf,g1,g2,tx 23 | 24 | max-attributes=10 25 | 26 | [REPORTS] 27 | output-format=text 28 | -------------------------------------------------------------------------------- /client/Makefile: -------------------------------------------------------------------------------- 1 | 2 | .PHONY: setup setup-dev dev check test syntax grpc test_contracts 3 | 4 | setup: 5 | pip install --upgrade pip --progress-bar off 6 | pip install -e . --progress-bar off 7 | $(MAKE) grpc 8 | python -c "from zeth.core.contracts import install_sol; \ 9 | install_sol()" 10 | 11 | check: syntax test 12 | 13 | PROTOBUF_OUTPUT := \ 14 | zeth/api/prover_pb2.py zeth/api/prover_pb2_grpc.py \ 15 | zeth/api/pghr13_messages_pb2.py zeth/api/pghr13_messages_pb2_grpc.py \ 16 | zeth/api/groth16_messages_pb2.py zeth/api/groth16_messages_pb2_grpc.py \ 17 | zeth/api/ec_group_messages_pb2.py zeth/api/ec_group_messages_pb2_grpc.py \ 18 | zeth/api/snark_messages_pb2.py zeth/api/snark_messages_pb2_grpc.py \ 19 | zeth/api/zeth_messages_pb2.py zeth/api/zeth_messages_pb2_grpc.py 20 | 21 | zeth/api/%_pb2.py zeth/api/%_pb2_grpc.py: ../proto/zeth/api/%.proto 22 | python -m grpc_tools.protoc \ 23 | -I../proto --proto_path ../proto --python_out=. --grpc_python_out=. --mypy_out=. \ 24 | zeth/api/$*.proto 25 | 26 | grpc: $(PROTOBUF_OUTPUT) 27 | @# suppress "Nothing to do for ..." warning 28 | @echo -n 29 | 30 | syntax: ${PROTOBUF_OUTPUT} 31 | flake8 `git ls-files '**.py'` 32 | mypy -p zeth 33 | mypy -p tests 34 | mypy -p test_commands 35 | mypy -p test_contracts 36 | pylint zeth.core zeth.cli zeth.helper tests test_commands 37 | 38 | test: ${PROTOBUF_OUTPUT} 39 | python -m unittest discover tests 40 | 41 | test_contracts: ${PROTOBUF_OUTPUT} 42 | python -m unittest discover test_contracts 43 | -------------------------------------------------------------------------------- /client/multiple_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Script to run 50 integration tests 3 | 4 | NOW=`date '+%F_%H:%M:%S'`; 5 | filename="test_result_$NOW" 6 | 7 | echo "Test started\n" >> $filename 8 | 9 | for i in `seq 1 50`; 10 | do 11 | python testEtherMixing.py PGHR13 12 | ret=$? 13 | 14 | if [ $ret -ne 0 ]; then 15 | echo "ETH test $i failed\n" >> $filename 16 | fi 17 | 18 | python testERCTokenMixing.py PGHR13 19 | ret=$? 20 | 21 | if [ $ret -ne 0 ]; then 22 | echo "Token test $i failed\n" >> $filename 23 | fi 24 | 25 | echo "Test finished.\n" >> $filename 26 | done 27 | -------------------------------------------------------------------------------- /client/mypy.ini: -------------------------------------------------------------------------------- 1 | [mypy] 2 | strict_optional=True 3 | disallow_untyped_calls=True 4 | disallow_untyped_defs=True 5 | disallow_incomplete_defs=True 6 | check_untyped_defs=True 7 | scripts_are_modules = True 8 | 9 | [mypy-grpc.*] 10 | ignore_missing_imports = True 11 | 12 | [mypy-solcx] 13 | ignore_missing_imports = True 14 | 15 | [mypy-zeth.api.*] 16 | disallow_untyped_defs=False 17 | ignore_errors=True 18 | 19 | [mypy-cryptography.*] 20 | ignore_missing_imports = True 21 | -------------------------------------------------------------------------------- /client/py.typed: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | # Empty file, required for mypy. -------------------------------------------------------------------------------- /client/requirements.txt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /client/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import sys 8 | from setuptools import find_packages 9 | from distutils.core import setup 10 | 11 | if not hasattr(sys, 'base_prefix') or sys.base_prefix == sys.prefix: 12 | print("ERROR: This is not production software, install inside a venv") 13 | sys.exit(1) 14 | 15 | if sys.version_info < (3, 7): 16 | print("ERROR: requires python >=3.7") 17 | sys.exit(1) 18 | 19 | setup( 20 | name='zeth', 21 | version='0.8', 22 | description='Interface to zeth operations', 23 | packages=find_packages(), 24 | install_requires=[ 25 | "mypy==0.790", 26 | "mypy-protobuf==1.23", 27 | "flake8==3.8.3", 28 | "pylint==2.9", 29 | "click==7.0", 30 | "click-default-group==1.2", 31 | "grpcio==1.44", 32 | "grpcio-tools==1.44", 33 | "protobuf==3.18.3", 34 | "py_ecc==1.7.1", 35 | "py-solc-x==1.1.0", 36 | "cryptography==3.3.2", 37 | "web3>=5<6", 38 | ], 39 | entry_points={ 40 | 'console_scripts': [ 41 | 'zeth-helper=zeth.helper.zeth_helper:zeth_helper', 42 | 'zeth=zeth.cli.zeth:zeth', 43 | ], 44 | } 45 | ) 46 | -------------------------------------------------------------------------------- /client/test_commands/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | -------------------------------------------------------------------------------- /client/test_contracts/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | -------------------------------------------------------------------------------- /client/tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | -------------------------------------------------------------------------------- /client/tests/test_ethervalue.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from zeth.core.utils import EtherValue 8 | from unittest import TestCase 9 | 10 | 11 | class TestEthereValue(TestCase): 12 | 13 | def test_conversion(self) -> None: 14 | aval = EtherValue(75641320, 'wei') 15 | aval_eth = aval.ether() 16 | bval = EtherValue(aval_eth, 'ether') 17 | self.assertEqual(aval.wei, bval.wei) 18 | self.assertEqual(aval.ether(), bval.ether()) 19 | 20 | def test_equality(self) -> None: 21 | aval = EtherValue(1.2) 22 | aval_same = EtherValue(1.2) 23 | bval = EtherValue(0.8) 24 | 25 | self.assertEqual(aval, aval) 26 | self.assertEqual(aval, aval_same) 27 | self.assertNotEqual(aval, bval) 28 | 29 | def test_arithmetic(self) -> None: 30 | aval = EtherValue(1.2) 31 | bval = EtherValue(0.8) 32 | cval = EtherValue(0.4) 33 | 34 | self.assertEqual(aval, bval + cval) 35 | self.assertEqual(bval, aval - cval) 36 | 37 | def test_comparison(self) -> None: 38 | big = EtherValue(1.2) 39 | small = EtherValue(0.8) 40 | small_same = EtherValue(0.8) 41 | 42 | self.assertTrue(small < big) 43 | self.assertTrue(small <= big) 44 | self.assertTrue(big > small) 45 | self.assertTrue(big >= small) 46 | self.assertTrue(small_same >= small) 47 | self.assertTrue(small_same <= small) 48 | 49 | self.assertFalse(small > big) 50 | self.assertFalse(small >= big) 51 | self.assertFalse(big < small) 52 | self.assertFalse(big <= small) 53 | self.assertFalse(small_same > small) 54 | self.assertFalse(small_same < small) 55 | 56 | def test_bool(self) -> None: 57 | zero = EtherValue(0) 58 | self.assertFalse(zero) 59 | self.assertTrue(not zero) 60 | 61 | non_zero = EtherValue(0.1) 62 | self.assertTrue(non_zero) 63 | self.assertFalse(not non_zero) 64 | -------------------------------------------------------------------------------- /client/tests/test_input_hasher.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | from zeth.core.mimc import MiMCAltBN128, MiMCBLS12_377 6 | from zeth.core.input_hasher import InputHasher 7 | from unittest import TestCase 8 | 9 | DUMMY_INPUT_VALUES = [-1, 0, 1] 10 | 11 | 12 | class TestInputHasher(TestCase): 13 | 14 | def test_input_hasher_simple(self) -> None: 15 | # Some very simple cases 16 | mimc = MiMCAltBN128() 17 | input_hasher = InputHasher(mimc, 7) 18 | self.assertEqual(mimc.hash_int(7, 0), input_hasher.hash([])) 19 | self.assertEqual( 20 | mimc.hash_int(mimc.hash_int(7, 1), 1), input_hasher.hash([1])) 21 | self.assertEqual( 22 | mimc.hash_int( 23 | mimc.hash_int( 24 | mimc.hash_int(7, 1), 2), 25 | 2), 26 | input_hasher.hash([1, 2])) 27 | 28 | def test_input_hasher_mimc_alt_bn128(self) -> None: 29 | mimc = MiMCAltBN128() 30 | input_hasher = InputHasher(mimc) 31 | values = [x % mimc.prime for x in DUMMY_INPUT_VALUES] 32 | # pylint:disable=line-too-long 33 | expect = 1147542777914688064255377945014225852776952826405497760158376896026758431650 # noqa 34 | # pylint:enable=line-too-long 35 | self.assertEqual(expect, input_hasher.hash(values)) 36 | 37 | def test_input_hasher_mimc_bls12_377(self) -> None: 38 | mimc = MiMCBLS12_377() 39 | input_hasher = InputHasher(mimc) 40 | values = [x % mimc.prime for x in DUMMY_INPUT_VALUES] 41 | # pylint: disable=line-too-long 42 | expect = 3481757288350338818975783012202519902801563645563026508811358096682731778741 # noqa 43 | # pylint: enable=line-too-long 44 | self.assertEqual(expect, input_hasher.hash(values)) 45 | -------------------------------------------------------------------------------- /client/tests/test_joinsplit.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | from zeth.core.mixer_client import compute_commitment 6 | from zeth.api.zeth_messages_pb2 import ZethNote 7 | from tests.test_pairing import ALT_BN128_PAIRING 8 | from unittest import TestCase 9 | 10 | 11 | class TestJoinsplit(TestCase): 12 | 13 | def test_compute_commitment(self) -> None: 14 | """ 15 | Test the commitment value for a note, as computed by the circuit. 16 | """ 17 | scalar_field_mod = ALT_BN128_PAIRING.scalar_field_mod() 18 | apk = "44810c8d62784f5e9ce862925ebb889d1076a453677a5d73567387cd5717a402" 19 | value = "0000000005f5e100" 20 | rho = "0b0bb358233326ce4d346d86f9a0c3778ed8ce15efbf7640aad6e9359145659f" 21 | r = "1e3063320fd43f2d6c456d7f1ee11b7ab486308133e2a5afe916daa4ff5357f6" 22 | cm_expect = int( 23 | "fdf5279335a2fa36fb0d664509808db8d02b6f05f9e5639960952a7038363cfc", 24 | 16) 25 | cm_expect_field = cm_expect % scalar_field_mod 26 | 27 | note = ZethNote(apk=apk, value=value, rho=rho, trap_r=r) 28 | cm = int.from_bytes( 29 | compute_commitment(note, ALT_BN128_PAIRING), 30 | byteorder="big") 31 | 32 | self.assertEqual(cm_expect_field, cm) 33 | -------------------------------------------------------------------------------- /client/zeth/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | -------------------------------------------------------------------------------- /client/zeth/api/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | -------------------------------------------------------------------------------- /client/zeth/api/py.typed: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | # Empty file, required for mypy. -------------------------------------------------------------------------------- /client/zeth/cli/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | -------------------------------------------------------------------------------- /client/zeth/cli/constants.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | 6 | """ 7 | Constants and defaults specific to the CLI interface. 8 | """ 9 | 10 | ETH_RPC_ENDPOINT_DEFAULTS = { 11 | "ganache": "http://localhost:8545", 12 | "autonity-helloworld": "http://localhost:8541", 13 | "bakerloo": "https://rpc3.bakerloo.autonity.network:8545", 14 | } 15 | 16 | ETH_NETWORK_FILE_DEFAULT = "eth-network" 17 | ETH_NETWORK_DEFAULT = "ganache" 18 | PROVER_SERVER_ENDPOINT_DEFAULT = "localhost:50051" 19 | 20 | # Note that these must satisfy: 21 | # ZETH_PUBLIC_ADDRESS_FILE_DEFAULT == \ 22 | # commands.utils.find_pub_address_file(ZETH_SECRET_ADDRESS_FILE_DEFAULT) 23 | ZETH_SECRET_ADDRESS_FILE_DEFAULT = "zeth-address.priv" 24 | ZETH_PUBLIC_ADDRESS_FILE_DEFAULT = "zeth-address.pub" 25 | 26 | INSTANCE_FILE_DEFAULT = "zeth-instance" 27 | ETH_ADDRESS_DEFAULT = "eth-address" 28 | ETH_PRIVATE_KEY_FILE_DEFAULT = "eth-private-key" 29 | 30 | PROVER_CONFIGURATION_FILE_DEFAULT = "prover-config.cache" 31 | 32 | WALLET_DIR_DEFAULT = "./wallet" 33 | WALLET_USERNAME = "zeth" 34 | -------------------------------------------------------------------------------- /client/zeth/cli/py.typed: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | # Empty file, required for mypy. -------------------------------------------------------------------------------- /client/zeth/cli/zeth_gen_address.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | from zeth.core.zeth_address import generate_zeth_address 6 | from zeth.cli.utils import get_zeth_address_file, pub_address_file, \ 7 | write_zeth_address_secret, write_zeth_address_public 8 | from click import command, pass_context, ClickException, Context 9 | from os.path import exists 10 | 11 | 12 | @command() 13 | @pass_context 14 | def gen_address(ctx: Context) -> None: 15 | """ 16 | Generate a new Zeth secret key and public address 17 | """ 18 | client_ctx = ctx.obj 19 | addr_file = get_zeth_address_file(client_ctx) 20 | if exists(addr_file): 21 | raise ClickException(f"ZethAddress file {addr_file} exists") 22 | 23 | pub_addr_file = pub_address_file(addr_file) 24 | if exists(pub_addr_file): 25 | raise ClickException(f"ZethAddress pub file {pub_addr_file} exists") 26 | 27 | zeth_address = generate_zeth_address() 28 | write_zeth_address_secret(zeth_address.addr_sk, addr_file) 29 | print(f"ZethAddress Secret key written to {addr_file}") 30 | write_zeth_address_public(zeth_address.addr_pk, pub_addr_file) 31 | print(f"Public ZethAddress written to {pub_addr_file}") 32 | -------------------------------------------------------------------------------- /client/zeth/cli/zeth_get_verification_key.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | from click import command, option, Context, pass_context 6 | 7 | from zeth.cli.utils import create_prover_client 8 | import json 9 | from typing import Optional 10 | 11 | 12 | @command() 13 | @option("--vk-out", "-o", help="Output file") 14 | @pass_context 15 | def get_verification_key(ctx: Context, vk_out: Optional[str]) -> None: 16 | """ 17 | Command help text. 18 | """ 19 | 20 | # Get the VK (proto object) 21 | client_ctx = ctx.obj 22 | prover_client = create_prover_client(client_ctx) 23 | vk = prover_client.get_verification_key() 24 | vk_json = vk.to_json_dict() 25 | 26 | # Write the json to stdout or a file 27 | if vk_out: 28 | with open(vk_out, "w") as vk_f: 29 | json.dump(vk_json, vk_f) 30 | else: 31 | print(json.dumps(vk_json)) 32 | -------------------------------------------------------------------------------- /client/zeth/cli/zeth_ls_commits.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | from zeth.cli.utils import \ 6 | create_mixer_client_and_mixer_desc, load_zeth_address, open_wallet 7 | from zeth.core.utils import short_commitment 8 | from click import Context, command, pass_context 9 | 10 | 11 | @command() 12 | @pass_context 13 | def ls_commits(ctx: Context) -> None: 14 | """ 15 | List all commitments in the Zeth mixer contract 16 | """ 17 | client_ctx = ctx.obj 18 | zeth_client, _mixer_desc = create_mixer_client_and_mixer_desc(client_ctx) 19 | zeth_address = load_zeth_address(client_ctx) 20 | wallet = open_wallet( 21 | zeth_client.mixer_instance, zeth_address.addr_sk, client_ctx) 22 | print("COMMITMENTS:") 23 | for commit in wallet.merkle_tree.get_leaves(): 24 | print(f" {short_commitment(commit)}") 25 | -------------------------------------------------------------------------------- /client/zeth/cli/zeth_ls_notes.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | from zeth.cli.utils import open_web3_from_ctx, load_zeth_address_secret, \ 6 | open_wallet, load_mixer_description_from_ctx 7 | from zeth.core.utils import EtherValue 8 | from click import Context, command, option, pass_context 9 | 10 | 11 | @command() 12 | @option("--balance", is_flag=True, help="Show total balance") 13 | @option("--spent", is_flag=True, help="Show spent notes") 14 | @pass_context 15 | def ls_notes(ctx: Context, balance: bool, spent: bool) -> None: 16 | """ 17 | List the set of notes owned by this wallet 18 | """ 19 | client_ctx = ctx.obj 20 | web3 = open_web3_from_ctx(client_ctx) 21 | mixer_desc = load_mixer_description_from_ctx(client_ctx) 22 | mixer_instance = mixer_desc.mixer.instantiate(web3) 23 | js_secret = load_zeth_address_secret(client_ctx) 24 | wallet = open_wallet(mixer_instance, js_secret, client_ctx) 25 | 26 | total = EtherValue(0) 27 | for addr, short_commit, value in wallet.note_summaries(): 28 | print(f"{short_commit}: value={value.ether()}, addr={addr}") 29 | total = total + value 30 | 31 | if balance: 32 | print(f"TOTAL BALANCE: {total.ether()}") 33 | 34 | if not spent: 35 | return 36 | 37 | print("SPENT NOTES:") 38 | for addr, short_commit, value in wallet.spent_note_summaries(): 39 | print(f"{short_commit}: value={value.ether()}, addr={addr}") 40 | -------------------------------------------------------------------------------- /client/zeth/cli/zeth_sync.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | from zeth.cli.utils import open_web3_from_ctx, create_prover_client, \ 6 | load_zeth_address_secret, open_wallet, do_sync, \ 7 | load_mixer_description_from_ctx, zeth_note_short_print 8 | from click import command, option, pass_context, Context 9 | from typing import Optional 10 | 11 | 12 | @command() 13 | @option("--wait-tx", help="Wait for tx hash") 14 | @option("--batch-size", type=int, help="Override blocks per query") 15 | @pass_context 16 | def sync(ctx: Context, wait_tx: Optional[str], batch_size: Optional[int]) -> None: 17 | """ 18 | Attempt to retrieve new notes for the key in 19 | """ 20 | client_ctx = ctx.obj 21 | web3 = open_web3_from_ctx(client_ctx) 22 | mixer_desc = load_mixer_description_from_ctx(client_ctx) 23 | mixer_instance = mixer_desc.mixer.instantiate(web3) 24 | js_secret = load_zeth_address_secret(client_ctx) 25 | wallet = open_wallet(mixer_instance, js_secret, client_ctx) 26 | prover_client = create_prover_client(client_ctx) 27 | pp = prover_client.get_configuration().pairing_parameters 28 | chain_block_number = do_sync( 29 | web3, wallet, pp, wait_tx, zeth_note_short_print, batch_size) 30 | print(f"SYNCED to {chain_block_number}") 31 | -------------------------------------------------------------------------------- /client/zeth/cli/zeth_wait.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | from zeth.cli.utils import load_mixer_description_from_ctx, open_web3_from_ctx 6 | from zeth.core.contracts import get_event_logs_from_tx_receipt 7 | from click import command, pass_context, Context, argument 8 | 9 | 10 | @command() 11 | @argument("transaction-id") 12 | @pass_context 13 | def wait(ctx: Context, transaction_id: str) -> None: 14 | """ 15 | Wait for a mix transaction and dump all log data. Does not update the 16 | wallet. Use sync to scan the chain for new notes. 17 | """ 18 | client_ctx = ctx.obj 19 | mixer_desc = load_mixer_description_from_ctx(client_ctx) 20 | instance_desc = mixer_desc.mixer 21 | 22 | # Retrieve the tx receipt and dump logs 23 | web3 = open_web3_from_ctx(client_ctx) # type: ignore 24 | instance = instance_desc.instantiate(web3) 25 | tx_receipt = web3.eth.waitForTransactionReceipt(transaction_id, 10000) \ 26 | # pylint: disable=no-member 27 | 28 | print("LogDebug events:") 29 | logs = get_event_logs_from_tx_receipt(instance, "LogDebug", tx_receipt) 30 | for log in logs: 31 | print( 32 | f" {log.args['message']}: {log.args['value']} " 33 | f"({hex(log.args['value'])})") 34 | 35 | print("LogMix events:") 36 | logs = get_event_logs_from_tx_receipt(instance, "LogMix", tx_receipt) 37 | for log in logs: 38 | print(f" {log}") 39 | -------------------------------------------------------------------------------- /client/zeth/core/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | -------------------------------------------------------------------------------- /client/zeth/core/errors.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | # Zeth standard error messages 8 | SNARK_NOT_SUPPORTED: str = \ 9 | "Invalid zkSNARK, should be one of ('PGHR13', 'GROTH16')" 10 | -------------------------------------------------------------------------------- /client/zeth/core/input_hasher.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | from zeth.core.mimc import MiMCBase 6 | from typing import List 7 | 8 | 9 | # Default seed, generated as: 10 | # zeth.core.mimc._keccak_256( 11 | # zeth.core.mimc._str_to_bytes("clearmatics_hash_seed")) 12 | DEFAULT_IV_UINT256 = \ 13 | 13196537064117388418196223856311987714388543839552400408340921397545324034315 14 | 15 | 16 | class InputHasher: 17 | """ 18 | Note that this is currently experimental code. Hash a series of field 19 | elements via the Merkle-Damgard construction on a MiMC compression 20 | function. Note that since this function only accepts whole numbers of 21 | scalar field elements, there is no ambiguity w.r.t to padding and we could 22 | technically omit the finalization step. It has been kept for now, to allow 23 | time for further consideration, and in case the form of the hasher changes 24 | (e.g. in case we want to be able to hash arbitrary bit strings in the 25 | future). 26 | """ 27 | def __init__(self, compression_fn: MiMCBase, iv: int = DEFAULT_IV_UINT256): 28 | assert compression_fn.prime < (2 << 256) 29 | self._compression_fn = compression_fn 30 | self._iv = iv % compression_fn.prime 31 | 32 | def hash(self, values: List[int]) -> int: 33 | current = self._iv 34 | for m in values: 35 | current = self._compression_fn.hash_int(current, m) 36 | return self._compression_fn.hash_int(current, len(values)) 37 | -------------------------------------------------------------------------------- /client/zeth/core/py.typed: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | # Empty file, required for mypy. -------------------------------------------------------------------------------- /client/zeth/core/timer.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | from __future__ import annotations 6 | import time 7 | from typing import Optional 8 | 9 | 10 | class Timer: 11 | """ 12 | Very simple class to help measure time. 13 | """ 14 | 15 | def __init__(self) -> None: 16 | self._start_time: Optional[float] = None 17 | 18 | def start(self) -> None: 19 | assert self._start_time is None 20 | self._start_time = time.time() 21 | 22 | @staticmethod 23 | def started() -> Timer: 24 | timer = Timer() 25 | timer.start() 26 | return timer 27 | 28 | def elapsed_seconds(self) -> float: 29 | assert self._start_time is not None 30 | return time.time() - self._start_time 31 | -------------------------------------------------------------------------------- /client/zeth/helper/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | -------------------------------------------------------------------------------- /client/zeth/helper/eth_gen_address.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from zeth.cli.constants import ETH_ADDRESS_DEFAULT, ETH_PRIVATE_KEY_FILE_DEFAULT 8 | from zeth.cli.utils import write_eth_private_key, write_eth_address 9 | from zeth.core.utils import eth_address_from_private_key 10 | from click import command, option, ClickException 11 | from web3 import Web3 # type: ignore 12 | import os 13 | import sys 14 | from typing import Optional 15 | 16 | 17 | @command() 18 | @option("--eth-addr-file", help="Address output filename") 19 | @option("--eth-private-key-file", help="Private key output filename") 20 | @option("--use-private-key", help="Use existing private key") 21 | def eth_gen_address( 22 | eth_addr_file: Optional[str], 23 | eth_private_key_file: Optional[str], 24 | use_private_key: Optional[str]) -> None: 25 | """ 26 | Locally generate a new Ethereum private key and address file, and write 27 | them to the current directory. 28 | """ 29 | sys.stderr.write( 30 | "*** WARNING: this address should not be used in production ***\n") 31 | 32 | eth_addr_file = eth_addr_file or ETH_ADDRESS_DEFAULT 33 | eth_private_key_file = eth_private_key_file or ETH_PRIVATE_KEY_FILE_DEFAULT 34 | 35 | if use_private_key: 36 | eth_private_key = bytes.fromhex(use_private_key) 37 | else: 38 | eth_private_key = gen_eth_private_key() 39 | 40 | if len(eth_private_key) != 32: 41 | raise ClickException("invalid private key length") 42 | 43 | write_eth_private_key(eth_private_key, eth_private_key_file) 44 | eth_address = eth_address_from_private_key(eth_private_key) 45 | write_eth_address(eth_address, eth_addr_file) 46 | print( 47 | f"{eth_address}: written to {eth_addr_file}, " 48 | f"private key to {eth_private_key_file}") 49 | 50 | 51 | def gen_eth_private_key() -> bytes: 52 | """ 53 | Simple private key generation function. Not for production use. 54 | """ 55 | return Web3.sha3(os.urandom(4096)) 56 | -------------------------------------------------------------------------------- /client/zeth/helper/eth_get_balance.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | from zeth.cli.constants import ETH_ADDRESS_DEFAULT 6 | from zeth.cli.utils import \ 7 | load_eth_address, get_eth_network, open_web3_from_network 8 | from zeth.core.utils import EtherValue 9 | from click import command, option, pass_context 10 | from typing import Optional, Any 11 | 12 | 13 | @command() 14 | @option( 15 | "--eth-addr", 16 | help=f"Address or address filename (default: {ETH_ADDRESS_DEFAULT})") 17 | @option( 18 | "--wei", 19 | is_flag=True, 20 | default=False, 21 | help="Display in Wei instead of Ether") 22 | @pass_context 23 | def eth_get_balance(ctx: Any, eth_addr: Optional[str], wei: bool) -> None: 24 | """ 25 | Command to get the balance of specific addresses. Support multiple queries 26 | per invocation (outputs one per line), for efficiency. 27 | """ 28 | eth_addr = load_eth_address(eth_addr) 29 | web3 = open_web3_from_network(get_eth_network(ctx.obj["eth_network"])) 30 | balance_wei = web3.eth.getBalance(eth_addr) # pylint: disable=no-member 31 | if wei: 32 | print(balance_wei) 33 | else: 34 | print(EtherValue(balance_wei, "wei").ether()) 35 | -------------------------------------------------------------------------------- /client/zeth/helper/eth_get_contract_address.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | from zeth.cli.utils import load_contract_address 6 | from click import command, argument 7 | 8 | 9 | @command() 10 | @argument("instance-file") 11 | def eth_get_contract_address(instance_file: str) -> None: 12 | """ 13 | Extract the address from a contract instance description file. 14 | """ 15 | print(load_contract_address(instance_file)) 16 | -------------------------------------------------------------------------------- /client/zeth/helper/token_approve.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | from zeth.cli.constants import INSTANCE_FILE_DEFAULT 6 | from zeth.cli.utils import load_eth_address, load_eth_private_key, \ 7 | get_eth_network, open_web3_from_network, load_mixer_description, EtherValue 8 | from zeth.core.contracts import send_contract_call 9 | from click import command, argument, option, pass_context, ClickException, Context 10 | 11 | 12 | @command() 13 | @argument("value") 14 | @option("--eth-addr", help="Sender eth address or address filename") 15 | @option("--eth-private-key", help="Sender eth private key") 16 | @option("--wait", is_flag=True, help="Wait for transaction to complete") 17 | @option( 18 | "--instance-file", 19 | default=INSTANCE_FILE_DEFAULT, 20 | help=f"Instance file (default={INSTANCE_FILE_DEFAULT})") 21 | @pass_context 22 | def token_approve( 23 | ctx: Context, 24 | value: str, 25 | eth_addr: str, 26 | eth_private_key: str, 27 | wait: bool, 28 | instance_file: str) -> None: 29 | """ 30 | Approve the mixer to spend some amount of ERC20/223 tokens 31 | """ 32 | approve_value = EtherValue(value) 33 | eth_addr = load_eth_address(eth_addr) 34 | eth_private_key_data = load_eth_private_key(eth_private_key) 35 | web3 = open_web3_from_network(get_eth_network(ctx.obj["eth_network"])) 36 | mixer_desc = load_mixer_description(instance_file) 37 | if not mixer_desc.token: 38 | raise ClickException("no token for mixer {mixer_desc.mixer.address}") 39 | 40 | token_instance = mixer_desc.token.instantiate(web3) 41 | approve_call = token_instance.functions.approve( 42 | mixer_desc.mixer.address, 43 | approve_value.wei) 44 | tx_hash = send_contract_call( 45 | web3, approve_call, eth_addr, eth_private_key_data) 46 | 47 | if wait: 48 | web3.eth.waitForTransactionReceipt(tx_hash) # pylint: disable=no-member 49 | else: 50 | print(tx_hash.hex()) 51 | -------------------------------------------------------------------------------- /cmake/code_coverage.cmake: -------------------------------------------------------------------------------- 1 | # Runs code coverage tools 2 | 3 | if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") 4 | message(WARNING "Code coverage should not be used in non-debug mode" 5 | " (CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE})") 6 | endif() 7 | 8 | find_program(GCOV gcov) 9 | if(NOT GCOV) 10 | message(FATAL_ERROR "gcov not found. Aborting...") 11 | endif() 12 | 13 | set( 14 | COVERAGE_COMPILER_FLAGS 15 | "-g -fprofile-arcs -ftest-coverage" 16 | CACHE 17 | INTERNAL 18 | "Compiler flags for test coverage" 19 | ) 20 | 21 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}") 22 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}") 23 | 24 | find_program(LCOV lcov) 25 | if(NOT LCOV) 26 | message(FATAL_ERROR "lcov not found. Aborting...") 27 | endif() 28 | 29 | # See: https://wiki.documentfoundation.org/Development/Lcov#patch_.27geninfo.27 30 | add_custom_target( 31 | raw_coverage 32 | COMMAND ${LCOV} --initial --directory ${PROJECT_SOURCE_DIR} --capture --output-file base_coverage.info 33 | COMMAND ${LCOV} --directory ${PROJECT_SOURCE_DIR} --capture --output-file test_coverage.info 34 | COMMAND ${LCOV} --add-tracefile base_coverage.info --add-tracefile test_coverage.info --output-file coverage.info 35 | COMMAND ${LCOV} --remove coverage.info /usr/\\*include/\\* ${PROJECT_SOURCE_DIR}/depends/\\* --output-file coverage.info 36 | ) 37 | 38 | find_program(GENHTML genhtml) 39 | if(NOT GENHTML) 40 | message(FATAL_ERROR "genhtml not found. Cannot export the tests" 41 | " coverages to HMTL. Please run 'raw_coverage' command instead.") 42 | endif() 43 | 44 | find_program(XDG_OPEN xdg-open) 45 | if(NOT XDG_OPEN) 46 | set(XDG_OPEN cmake -E echo Test coverage report generated. Open ) 47 | endif() 48 | 49 | add_custom_target( 50 | coverage 51 | COMMAND ${GENHTML} coverage.info --legend --title "Zeth code coverage report" --output-directory coverage_report 52 | COMMAND ${XDG_OPEN} coverage_report/index.html 53 | DEPENDS raw_coverage 54 | ) 55 | -------------------------------------------------------------------------------- /cmake/documentation.cmake: -------------------------------------------------------------------------------- 1 | # Generate the Doxygen code documentation for the project. 2 | # 3 | # TODO: Consider using: https://codedocs.xyz/ at some point 4 | # 5 | # The following is adapted from: 6 | # https://vicrucann.github.io/tutorials/quick-cmake-doxygen/ 7 | 8 | # Check if Doxygen is installed 9 | find_package(Doxygen) 10 | if(NOT DOXYGEN_FOUND) 11 | message(FATAL_ERROR "You need to install Doxygen to generate" 12 | " the documentation. Aborting...") 13 | endif() 14 | 15 | # Set input and output files 16 | set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in) 17 | set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) 18 | 19 | # Request to configure the file 20 | configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY) 21 | message("Doxygen build started") 22 | 23 | # The option ALL allows to build the docs together with the application 24 | add_custom_target( 25 | build_docs 26 | ALL 27 | COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} 28 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 29 | COMMENT "Generating API documentation with Doxygen" 30 | VERBATIM 31 | ) 32 | 33 | find_program(XDG_OPEN xdg-open) 34 | if(NOT XDG_OPEN) 35 | set(XDG_OPEN cmake -E echo Documentation generated. Open ) 36 | endif() 37 | 38 | add_custom_target( 39 | docs 40 | COMMAND ${XDG_OPEN} ${CMAKE_CURRENT_BINARY_DIR}/docs/html/index.html 41 | DEPENDS build_docs 42 | ) 43 | -------------------------------------------------------------------------------- /cmake/gcc_dev_tools.cmake: -------------------------------------------------------------------------------- 1 | # Run a set of GCC tools on the code base to maintain high code standards 2 | # and catch potential security vulnerabilities 3 | # 4 | # Tools ran: 5 | # - cppcheck 6 | 7 | option( 8 | USE_CPP_CHECK 9 | "Use cppcheck if the program is found." 10 | OFF 11 | ) 12 | 13 | # Adding clang-format target if executable is found 14 | if(USE_CPP_CHECK) 15 | find_program(CPP_CHECK "cppcheck") 16 | if(CPP_CHECK) 17 | message("cppcheck found!") 18 | message("Using cppcheck. Creating target... To run, use: make cppcheck") 19 | # TODO: gtest includes are not found by cppcheck, because they are marked 20 | # as "SYSTEM" (to prevent compile warnings). We exclude all tests for now, 21 | # to avoid many "syntaxError" reports, but the analysis should be run on 22 | # tests. 23 | add_custom_target( 24 | cppcheck 25 | COMMAND cppcheck 26 | --project=${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json 27 | --enable=all 28 | --suppressions-list=${PROJECT_SOURCE_DIR}/.cppcheck.suppressions 29 | --inline-suppr 30 | --quiet 31 | -i${DEPENDS_DIR} 32 | --suppress='*:${DEPENDS_DIR}/*' 33 | -i${PROJECT_BINARY_DIR}/api 34 | --suppress='*:${PROJECT_BINARY_DIR}/api/*' 35 | --suppress='unmatchedSuppression:*' 36 | --error-exitcode=1 37 | --suppress='*:${PROJECT_SOURCE_DIR}/libzeth/tests/*' 38 | ) 39 | else() 40 | message(FATAL_ERROR "cppcheck not found. Aborting...") 41 | endif() 42 | endif() 43 | -------------------------------------------------------------------------------- /debug/README.md: -------------------------------------------------------------------------------- 1 | # Debug folder 2 | 3 | This folder is the default location (pointed by the environment variable `ZETH_DEBUG_DIR`) to write debug data: 4 | - Proofs 5 | - R1CS - Constraints 6 | and so on. 7 | -------------------------------------------------------------------------------- /debug/analyzer/README.md: -------------------------------------------------------------------------------- 1 | # Circuit/R1CS analyzer 2 | 3 | Basic set of functionalities to parse and run basic queries on the r1cs exported in a json file. 4 | 5 | ## JSON format expected for the R1CS 6 | 7 | ```json 8 | { 9 | "scalar_field_characteristic": "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001", 10 | "num_variables": 549746, # Number of wires 11 | "num_constraints": 433391, # Number of gates 12 | "num_inputs": 17, # Number of primary inputs 13 | "variables_annotations": [ # The wires annotations 14 | {"index":0,"annotation":"ONE"}, 15 | {"index":1,"annotation":"joinsplit_gadget merkle_root"}, 16 | {"index":2,"annotation":"joinsplit_gadget in_nullifier[0]_0"}, 17 | {"index":3,"annotation":"joinsplit_gadget in_nullifier[0]_1"}, 18 | {"index":4,"annotation":"joinsplit_gadget in_nullifier[1]_0"}, 19 | ... 20 | ], 21 | "constraints": [ # The gates 22 | { 23 | "constraint_id": 0, 24 | "constraint_annotation": "joinsplit_gadget packer_nullifiers[0] packers_0 packing_constraint", 25 | "linear_combination": [ 26 | { 27 | "A": [ 28 | { 29 | "index": 0, # index of the wire 30 | "scalar": "0x1" # scalar used on the wire in the lin. comb 31 | } 32 | ], 33 | "B": [ 34 | { 35 | "index": 530, 36 | "scalar": "0x1" 37 | }, 38 | { 39 | "index": 531, 40 | "scalar": "0x2" 41 | } 42 | ], 43 | "C": [ 44 | { 45 | "index": 2, 46 | "scalar": "0x1" 47 | } 48 | ] 49 | } 50 | ] 51 | }, 52 | ... 53 | ] 54 | } 55 | ``` 56 | -------------------------------------------------------------------------------- /debug/analyzer/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | # 3 | # SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | -------------------------------------------------------------------------------- /depends/.clang-format: -------------------------------------------------------------------------------- 1 | { 2 | # Prevent formatting of dependencies 3 | DisableFormat: "true", 4 | } -------------------------------------------------------------------------------- /depends/.clang-tidy: -------------------------------------------------------------------------------- 1 | # Disable all checks. 2 | # (Dummy check here prevents error from clang-tidy) 3 | Checks: '-*,misc-definitions-in-headers' 4 | CheckOptions: 5 | - { key: HeaderFileExtensions, value: "x" } 6 | -------------------------------------------------------------------------------- /depends/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # libsnark 2 | OPTION(IS_LIBSNARK_PARENT OFF) 3 | add_subdirectory(libsnark) 4 | 5 | set_target_properties(snark PROPERTIES COMPILE_FLAGS 6 | "-Wno-error -Wno-unused-variable -Wno-unused-parameter -Wno-delete-non-virtual-dtor -Wno-sign-compare" 7 | ) 8 | 9 | set_target_properties(ff PROPERTIES COMPILE_FLAGS 10 | "-Wno-error -Wno-unused-variable -Wno-unused-parameter" 11 | ) 12 | 13 | set_target_properties(gtest PROPERTIES COMPILE_FLAGS 14 | "-Wno-error" 15 | ) 16 | 17 | # get NUM_CPUS 18 | include(ProcessorCount) 19 | ProcessorCount(NUM_CPUS) 20 | if(NOT NUM_CPUS EQUAL 0) 21 | set(MAKE_BUILD_FLAGS -j${NUM_CPUS}) 22 | endif() 23 | 24 | # libsodium 25 | set(LIBSODIUM_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libsodium) 26 | set(LIBSODIUM_CONFIGURE_CMD "CC=\"${CMAKE_C_COMPILER_LAUNCHER} ${CMAKE_C_COMPILER}\" CXX=\"${CMAKE_C_COMPILER_LAUNCHER} ${CMAKE_CXX_COMPILER}\" ./configure --prefix= --enable-minimal --disable-shared --enable-static") 27 | 28 | include(ExternalProject) 29 | ExternalProject_Add( 30 | libsodium 31 | SOURCE_DIR ${LIBSODIUM_SOURCE_DIR} 32 | CONFIGURE_COMMAND cd ${LIBSODIUM_SOURCE_DIR} && DO_NOT_UPDATE_CONFIG_SCRIPTS=1 ./autogen.sh && eval ${LIBSODIUM_CONFIGURE_CMD} 33 | BUILD_COMMAND cd ${LIBSODIUM_SOURCE_DIR} && make ${MAKE_BUILD_FLAGS} 34 | INSTALL_COMMAND cd ${LIBSODIUM_SOURCE_DIR} && make install) 35 | -------------------------------------------------------------------------------- /libtool/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(.) 2 | 3 | find_package(Boost REQUIRED COMPONENTS program_options) 4 | include_directories(${Boost_INCLUDE_DIR}) 5 | 6 | file(GLOB_RECURSE LIBTOOL_SOURCE **.?pp **.tcc) 7 | 8 | add_library(tool ${LIBTOOL_SOURCE}) 9 | target_include_directories(tool PUBLIC ..) 10 | target_link_libraries(tool ${Boost_PROGRAM_OPTIONS_LIBRARY}) 11 | -------------------------------------------------------------------------------- /libtool/command.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_LIBTOOL_COMMAND_HPP__ 6 | #define __ZETH_LIBTOOL_COMMAND_HPP__ 7 | 8 | #include "libtool/subcommand.hpp" 9 | 10 | namespace libtool 11 | { 12 | 13 | /// Represents a top-level command, implementing parsing of global options. 14 | template class command 15 | { 16 | public: 17 | /// Set up global options which are valid for all subcommands. 18 | virtual void initialize_global_options( 19 | boost::program_options::options_description &global, 20 | boost::program_options::options_description &all_options) = 0; 21 | 22 | /// Parse the variables map to update the GlobalOptionsT object. 23 | virtual void parse_global_options( 24 | GlobalOptionsT &out_options, 25 | const boost::program_options::variables_map &vm) = 0; 26 | }; 27 | 28 | } // namespace libtool 29 | 30 | #endif // __ZETH_LIBTOOL_COMMAND_HPP__ 31 | -------------------------------------------------------------------------------- /libtool/run.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_LIBTOOL_RUN_HPP__ 6 | #define __ZETH_LIBTOOL_RUN_HPP__ 7 | 8 | #include "libtool/command.hpp" 9 | 10 | namespace libtool 11 | { 12 | 13 | /// Execute a command object, with some global options object (initialized to 14 | /// default values), supporting the given set of subcommands. 15 | template 16 | int run_command( 17 | command &command, 18 | GlobalOptionsT &options, 19 | const std::map *> &subcommands, 20 | int argc, 21 | char **argv); 22 | 23 | } // namespace libtool 24 | 25 | #include "libtool/run.tcc" 26 | 27 | #endif // __ZETH_LIBTOOL_RUN_HPP__ 28 | -------------------------------------------------------------------------------- /libtool/subcommand.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_LIBTOOL_SUBCOMMAND_HPP__ 6 | #define __ZETH_LIBTOOL_SUBCOMMAND_HPP__ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace po = boost::program_options; 13 | 14 | namespace libtool 15 | { 16 | 17 | /// Class representing a tool subcommand. 18 | template class subcommand 19 | { 20 | public: 21 | subcommand( 22 | const std::string &subcommand_name, const std::string &description); 23 | virtual ~subcommand(); 24 | const std::string &description() const; 25 | 26 | /// Common code to parse options and invoke the virtual execute entrypoint. 27 | int execute( 28 | const char *argv0, 29 | const std::vector command_args, 30 | const GlobalOptionsT &global); 31 | 32 | protected: 33 | void usage( 34 | const char *argv0, 35 | const boost::program_options::options_description &options); 36 | 37 | /// Instantiation can now set up the boost program_options structures. 38 | virtual void initialize_suboptions( 39 | boost::program_options::options_description &options, 40 | boost::program_options::options_description &all_options, 41 | boost::program_options::positional_options_description &pos) = 0; 42 | 43 | /// Instantiation can record any command-specific information from the 44 | /// parsed variables_map. 45 | virtual void parse_suboptions( 46 | const boost::program_options::variables_map &vm) = 0; 47 | 48 | /// Any command-specific output for usage. 49 | virtual void subcommand_usage(const char *argv0) = 0; 50 | 51 | /// Execute the command using global options defined by the caller. 52 | virtual int execute_subcommand(const GlobalOptionsT &global) = 0; 53 | 54 | std::string subcommand_name; 55 | std::string subcommand_description; 56 | }; 57 | 58 | } // namespace libtool 59 | 60 | #include "libtool/subcommand.tcc" 61 | 62 | #endif // __ZETH_LIBTOOL_SUBCOMMAND_HPP__ 63 | -------------------------------------------------------------------------------- /libtool/tool_util.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #include "libtool/tool_util.hpp" 6 | 7 | namespace libtool 8 | { 9 | 10 | std::ifstream open_binary_input_file(const std::string &filename) 11 | { 12 | std::ifstream in_s( 13 | filename.c_str(), std::ios_base::in | std::ios_base::binary); 14 | in_s.exceptions( 15 | std::ios_base::eofbit | std::ios_base::badbit | std::ios_base::failbit); 16 | return in_s; 17 | } 18 | 19 | std::ofstream open_binary_output_file(const std::string &filename) 20 | { 21 | std::ofstream out_s( 22 | filename.c_str(), std::ios_base::out | std::ios_base::binary); 23 | return out_s; 24 | } 25 | 26 | } // namespace libtool 27 | -------------------------------------------------------------------------------- /libtool/tool_util.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_LIBTOOL_TOOL_UTIL_HPP__ 6 | #define __ZETH_LIBTOOL_TOOL_UTIL_HPP__ 7 | 8 | #include "libtool/subcommand.hpp" 9 | 10 | #include 11 | 12 | /// Utilities that are likely to be useful for command line tools. 13 | 14 | namespace libtool 15 | { 16 | 17 | /// Utility function to open a file for reading, with appropriate flags and 18 | /// exception handling enabled. 19 | std::ifstream open_binary_input_file(const std::string &filename); 20 | 21 | /// Utility function to open a binary file for writing, with appropriate flags. 22 | std::ofstream open_binary_output_file(const std::string &filename); 23 | 24 | } // namespace libtool 25 | 26 | #endif // __ZETH_LIBTOOL_TOOL_UTIL_HPP__ 27 | -------------------------------------------------------------------------------- /libzeth/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(.) 2 | 3 | find_package(Protobuf REQUIRED) 4 | find_package(gRPC REQUIRED) 5 | 6 | # NOTE: dependency include directories use SYSTEM, to prevent the compiler from 7 | # issuing warnings from their headers. See: 8 | # https://foonathan.net/2018/10/cmake-warnings/ 9 | 10 | # Add the directory containing the Protobuf generated files. 11 | # `PROTO_SRC_DIR` is defined in the parent CMakeLists.txt 12 | include_directories(SYSTEM ${PROTO_SRC_DIR}) 13 | 14 | # Function defined in the cmake scripts in the cmake folder. 15 | # Generate the protobuf files and set the result of the generation 16 | # in the given env var (PROTO_SRCS, PROTO_HDRS). 17 | protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${PROTO_SRC_DIR} ${PROTO_FILES}) 18 | set_property(SOURCE ${PROTO_SRCS} PROPERTY 19 | COMPILE_FLAGS "-Wno-unused-variable -Wno-unused-parameter -Wno-error" 20 | ) 21 | 22 | # Enable Boost for filesystem 23 | find_package(Boost REQUIRED COMPONENTS system filesystem) 24 | include_directories(${Boost_INCLUDE_DIR}) 25 | 26 | # libsodium 27 | ExternalProject_Get_Property(libsodium INSTALL_DIR) 28 | set(libsodium_INCLUDE_DIR "${INSTALL_DIR}/include") 29 | set(libsodium_LIBRARY "${INSTALL_DIR}/lib/libsodium.a") 30 | 31 | # zeth library 32 | file( 33 | GLOB_RECURSE 34 | ZETH_SOURCE 35 | 36 | *.hpp 37 | core/**.?pp core/**.tcc 38 | snarks/**.?pp snarks/**.tcc 39 | serialization/**.?pp serialization/**.tcc 40 | circuits/**.?pp circuits/**.tcc 41 | mpc/**.?pp mpc/**.tcc 42 | ) 43 | 44 | add_library( 45 | zeth 46 | 47 | ${ZETH_SOURCE} 48 | ${PROTO_SRCS} 49 | ) 50 | target_include_directories( 51 | zeth 52 | 53 | SYSTEM 54 | PUBLIC 55 | ${DEPENDS_DIR}/libsnark 56 | ${DEPENDS_DIR}/libsnark/depends/libff 57 | ${DEPENDS_DIR}/libsnark/depends/libfqfft 58 | ${libsodium_INCLUDE_DIR} 59 | ) 60 | target_link_libraries( 61 | zeth 62 | 63 | snark 64 | ${libsodium_LIBRARY} 65 | ) 66 | add_dependencies(zeth libsodium) 67 | 68 | # Tests 69 | if ("${IS_ZETH_PARENT}") 70 | add_subdirectory(tests) 71 | endif() 72 | -------------------------------------------------------------------------------- /libzeth/circuits/circuit_types.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_CIRCUITS_CIRCUIT_TYPES_HPP__ 6 | #define __ZETH_CIRCUITS_CIRCUIT_TYPES_HPP__ 7 | 8 | #include "libzeth/circuits/blake2s/blake2s.hpp" 9 | #include "libzeth/circuits/circuit_wrapper.hpp" 10 | #include "libzeth/circuits/mimc/mimc_selector.hpp" 11 | #include "libzeth/core/include_libsnark.hpp" 12 | 13 | #include 14 | #include 15 | 16 | // Types that must be common across all executable, defined once here. Outside 17 | // of tests, these should not be set anywhere else in the code. Do not include 18 | // this file in code that is intended to be parameterized by hash type. 19 | 20 | namespace libzeth 21 | { 22 | 23 | // Hash used for the commitments and PRFs 24 | template using HashT = BLAKE2s_256; 25 | 26 | // Hash function to be used in the Merkle Tree 27 | template 28 | using HashTreeT = mimc_compression_function_gadget; 29 | 30 | template 31 | using JoinsplitCircuitT = circuit_wrapper< 32 | HashT>, 33 | HashTreeT>, 34 | ppT, 35 | snarkT, 36 | libzeth::ZETH_NUM_JS_INPUTS, 37 | libzeth::ZETH_NUM_JS_OUTPUTS, 38 | libzeth::ZETH_MERKLE_TREE_DEPTH>; 39 | 40 | } // namespace libzeth 41 | 42 | #endif // __ZETH_CIRCUITS_CIRCUIT_TYPES_HPP__ 43 | -------------------------------------------------------------------------------- /libzeth/circuits/circuit_utils.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_CIRCUITS_CIRCUIT_UTILS_HPP__ 6 | #define __ZETH_CIRCUITS_CIRCUIT_UTILS_HPP__ 7 | 8 | #include "libzeth/core/bits.hpp" 9 | 10 | #include 11 | 12 | namespace libzeth 13 | { 14 | 15 | template 16 | libsnark::linear_combination packed_addition( 17 | const libsnark::pb_variable_array &input); 18 | 19 | template 20 | libsnark::pb_variable_array pb_variable_array_from_bit_vector( 21 | libsnark::protoboard &pb, 22 | const std::vector &bits, 23 | const std::string &annotation_prefix); 24 | 25 | } // namespace libzeth 26 | 27 | #include "libzeth/circuits/circuit_utils.tcc" 28 | 29 | #endif // __ZETH_CIRCUITS_CIRCUIT_UTILS_HPP__ 30 | -------------------------------------------------------------------------------- /libzeth/circuits/merkle_tree/merkle_path_compute.hpp: -------------------------------------------------------------------------------- 1 | // DISCLAIMER: 2 | // Content taken and adapted from: 3 | // https://github.com/HarryR/ethsnarks/blob/master/src/gadgets/merkle_tree.hpp 4 | // https://github.com/HarryR/ethsnarks/blob/master/src/gadgets/merkle_tree.cpp 5 | 6 | #ifndef __ZETH_CIRCUITS_MERKLE_PATH_COMPUTE_HPP__ 7 | #define __ZETH_CIRCUITS_MERKLE_PATH_COMPUTE_HPP__ 8 | 9 | #include "libzeth/circuits/merkle_tree/merkle_path_selector.hpp" 10 | 11 | namespace libzeth 12 | { 13 | 14 | template 15 | class merkle_path_compute : public libsnark::gadget 16 | { 17 | public: 18 | const size_t depth; 19 | // Address of the leaf to authenticate 20 | const libsnark::pb_variable_array address_bits; 21 | // Leaf to authenticate 22 | const libsnark::pb_variable leaf; 23 | // Merkle Authentication path 24 | const libsnark::pb_variable_array path; 25 | 26 | // Digests 27 | libsnark::pb_variable_array digests; 28 | // Gadget informing the position in the three of the computed 29 | // hash and authentication node 30 | std::vector> selectors; 31 | // Vector of hash gadgets to compute the intermediary digests 32 | std::vector hashers; 33 | 34 | merkle_path_compute( 35 | libsnark::protoboard &pb, 36 | // Depth of the tree 37 | const size_t depth, 38 | // Address of the leaf to authenticate 39 | const libsnark::pb_variable_array &address_bits, 40 | // Leaf to authenticate 41 | const libsnark::pb_variable leaf, 42 | // Merkle Authentication path 43 | const libsnark::pb_variable_array &path, 44 | const std::string &annotation_prefix); 45 | 46 | void generate_r1cs_constraints(); 47 | void generate_r1cs_witness(); 48 | 49 | // Returns the computed root 50 | const libsnark::pb_variable result(); 51 | }; 52 | 53 | } // namespace libzeth 54 | 55 | #include "libzeth/circuits/merkle_tree/merkle_path_compute.tcc" 56 | 57 | #endif // __ZETH_CIRCUITS_MERKLE_PATH_COMPUTE_HPP__ 58 | -------------------------------------------------------------------------------- /libzeth/circuits/mimc/mimc_input_hasher.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_CIRCUITS_MIMC_MIMC_INPUT_HASHER_HPP__ 6 | #define __ZETH_CIRCUITS_MIMC_MIMC_INPUT_HASHER_HPP__ 7 | 8 | #include 9 | #include 10 | 11 | namespace libzeth 12 | { 13 | 14 | /// Given a list of variables, hash the variables to a value which can be used 15 | /// as a public input bound to the original variables. 16 | template 17 | class mimc_input_hasher : public libsnark::gadget 18 | { 19 | private: 20 | // Output variable 21 | libsnark::pb_variable _result; 22 | 23 | // Compression function constraints 24 | std::vector> _compression_functions; 25 | 26 | // Intermediate values 27 | libsnark::pb_variable_array _intermediate_values; 28 | 29 | public: 30 | mimc_input_hasher( 31 | libsnark::protoboard &pb, 32 | const libsnark::pb_linear_combination_array &inputs, 33 | const libsnark::pb_variable hash_output, 34 | const std::string &annotation_prefix); 35 | 36 | void generate_r1cs_constraints(); 37 | void generate_r1cs_witness() const; 38 | 39 | static FieldT get_iv(); 40 | static FieldT compute_hash(const std::vector &values); 41 | }; 42 | 43 | } // namespace libzeth 44 | 45 | #include "mimc_input_hasher.tcc" 46 | 47 | #endif // __ZETH_CIRCUITS_MIMC_MIMC_INPUT_HASHER_HPP__ 48 | -------------------------------------------------------------------------------- /libzeth/circuits/safe_arithmetic.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #include "libzeth/circuits/safe_arithmetic.hpp" 6 | 7 | namespace libzeth 8 | { 9 | 10 | std::size_t subtract_with_clamp(std::size_t a, std::size_t b) 11 | { 12 | if (b > a) { 13 | return 0; 14 | } 15 | return a - b; 16 | }; 17 | 18 | } // namespace libzeth 19 | -------------------------------------------------------------------------------- /libzeth/circuits/safe_arithmetic.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_CIRCUITS_SAFE_ARITHMETIC_HPP__ 6 | #define __ZETH_CIRCUITS_SAFE_ARITHMETIC_HPP__ 7 | 8 | #include 9 | 10 | namespace libzeth 11 | { 12 | 13 | /// Subtract `b` from `a`, clamping the result to [0, a] (i.e. returns `0` if 14 | /// `b > a` instead of wrapping around to the top of the range of values). 15 | size_t subtract_with_clamp(size_t a, size_t b); 16 | 17 | } // namespace libzeth 18 | 19 | #endif // __ZETH_CIRCUITS_SAFE_ARITHMETIC_HPP__ 20 | -------------------------------------------------------------------------------- /libzeth/core/bits.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #include "libzeth/core/bits.hpp" 6 | 7 | #include "libzeth/core/include_libff.hpp" 8 | #include "libzeth/core/utils.hpp" 9 | 10 | namespace libzeth 11 | { 12 | 13 | std::vector bit_vector_from_hex(const std::string &hex_str) 14 | { 15 | std::vector result; 16 | result.reserve(4 * hex_str.size()); 17 | for (char c : hex_str) { 18 | const uint8_t nibble = char_to_nibble(c); 19 | result.push_back(nibble & 8); 20 | result.push_back(nibble & 4); 21 | result.push_back(nibble & 2); 22 | result.push_back(nibble & 1); 23 | } 24 | 25 | return result; 26 | } 27 | 28 | std::vector bit_vector_from_size_t_le(size_t x) 29 | { 30 | std::vector ret; 31 | while (x) { 32 | ret.push_back((x & 1) != 0); 33 | x >>= 1; 34 | } 35 | 36 | return ret; 37 | } 38 | 39 | std::vector bit_vector_from_size_t_be(size_t x) 40 | { 41 | std::vector res; 42 | size_t num_bits = 8 * sizeof(size_t); 43 | const size_t mask = 1ULL << (num_bits - 1); 44 | 45 | // Remove 0-bits at the front 46 | while (num_bits > 0) { 47 | if ((x & mask) != 0) { 48 | break; 49 | } 50 | x = x << 1; 51 | --num_bits; 52 | } 53 | 54 | // Pre-allocate and fill the vector with remaining bits 55 | res.reserve(num_bits); 56 | while (num_bits > 0) { 57 | res.push_back((x & mask) != 0); 58 | x = x << 1; 59 | --num_bits; 60 | } 61 | 62 | return res; 63 | } 64 | 65 | void bit_vector_write_string(const std::vector &bits, std::ostream &out_s) 66 | { 67 | out_s << "{"; 68 | for (size_t i = 0; i < bits.size() - 1; ++i) { 69 | out_s << bits[i] << ", "; 70 | } 71 | out_s << bits[bits.size() - 1] << "}\n"; 72 | } 73 | 74 | } // namespace libzeth 75 | -------------------------------------------------------------------------------- /libzeth/core/chacha_rng.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_CORE_CHACHA_RNG_HPP__ 6 | #define __ZETH_CORE_CHACHA_RNG_HPP__ 7 | 8 | #include 9 | #include 10 | 11 | namespace libzeth 12 | { 13 | 14 | /// Random number generator matching the implementation used by zcash 15 | /// powersoftau and phase2. 16 | /// Usage: 17 | /// https://github.com/clearmatics/powersoftau 18 | /// (See hash_to_g2 function) 19 | /// Implementation is based on: 20 | /// https://docs.rs/rand/0.4.6/src/rand/prng/chacha.rs.html 21 | /// (See description comment, in particular word layout) 22 | class chacha_rng 23 | { 24 | public: 25 | chacha_rng(const void *seed, size_t seed_size); 26 | void random(void *output, size_t output_size); 27 | 28 | private: 29 | void update(); 30 | 31 | // The key generated from the seed data 32 | uint32_t key[8]; 33 | 34 | // 128-bit counter 35 | uint32_t counter[4]; 36 | 37 | // Current block of output from chacha 38 | uint8_t block[64]; 39 | 40 | // Number of bytes of data already used from block 41 | size_t data_used; 42 | }; 43 | 44 | } // namespace libzeth 45 | 46 | #endif // __ZETH_CORE_CHACHA_RNG_HPP__ 47 | -------------------------------------------------------------------------------- /libzeth/core/evaluator_from_lagrange.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_CORE_EVALUATOR_FROM_LAGRANGE_HPP__ 6 | #define __ZETH_CORE_EVALUATOR_FROM_LAGRANGE_HPP__ 7 | 8 | #include "libzeth/core/include_libsnark.hpp" 9 | 10 | #include 11 | 12 | namespace libzeth 13 | { 14 | 15 | /// Given a sequence of powers of x (with some factor) encoded in 16 | /// GroupT, compute the values of various linear combination of 17 | /// Lagrange polynomials at x. Note that this is not optimal, and 18 | /// primarily intended for testing and validation. 19 | template class evaluator_from_lagrange 20 | { 21 | private: 22 | const std::vector &powers; 23 | libfqfft::evaluation_domain> &domain; 24 | 25 | public: 26 | evaluator_from_lagrange( 27 | const std::vector &powers, 28 | libfqfft::evaluation_domain> &domain); 29 | 30 | GroupT evaluate_from_lagrange_factors( 31 | const std::map> &lagrange_factors); 32 | }; 33 | 34 | } // namespace libzeth 35 | 36 | #include "libzeth/core/evaluator_from_lagrange.tcc" 37 | 38 | #endif // __ZETH_CORE_EVALUATOR_FROM_LAGRANGE_HPP__ 39 | -------------------------------------------------------------------------------- /libzeth/core/evaluator_from_lagrange.tcc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_CORE_EVALUATOR_FROM_LAGRANGE_TCC__ 6 | #define __ZETH_CORE_EVALUATOR_FROM_LAGRANGE_TCC__ 7 | 8 | #include "libzeth/core/evaluator_from_lagrange.hpp" 9 | #include "libzeth/core/multi_exp.hpp" 10 | 11 | namespace libzeth 12 | { 13 | 14 | template 15 | evaluator_from_lagrange::evaluator_from_lagrange( 16 | const std::vector &powers, 17 | libfqfft::evaluation_domain> &domain) 18 | : powers(powers), domain(domain) 19 | { 20 | // Lagrange polynomials have order <= m-1, requiring at least m 21 | // entries in powers (0, ..., m-1) in order to evaluate. 22 | assert(powers.size() >= domain.m); 23 | } 24 | 25 | template 26 | GroupT evaluator_from_lagrange::evaluate_from_lagrange_factors( 27 | const std::map> &lagrange_factors) 28 | { 29 | // libfqfft::evaluation_domain modifies an incoming vector of factors. 30 | // Write the factors into the vector (it must be large enough to hold 31 | // domain.m entries), and then run iFFT to transform to coefficients. 32 | std::vector> coefficients(domain.m, libff::Fr::zero()); 33 | for (auto it : lagrange_factors) { 34 | const size_t lagrange_idx = it.first; 35 | const libff::Fr &lagrange_factor = it.second; 36 | 37 | assert(lagrange_idx < domain.m); 38 | if (!lagrange_factor.is_zero()) { 39 | coefficients[lagrange_idx] = lagrange_factor; 40 | } 41 | } 42 | 43 | domain.iFFT(coefficients); 44 | return multi_exp(powers, coefficients); 45 | } 46 | 47 | } // namespace libzeth 48 | 49 | #endif // __ZETH_CORE_EVALUATOR_FROM_LAGRANGE_TCC__ 50 | -------------------------------------------------------------------------------- /libzeth/core/extended_proof.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_CORE_EXTENDED_PROOF_HPP__ 6 | #define __ZETH_CORE_EXTENDED_PROOF_HPP__ 7 | 8 | #include "libzeth/core/include_libsnark.hpp" 9 | #include "libzeth/serialization/filesystem_util.hpp" 10 | 11 | namespace libzeth 12 | { 13 | 14 | /// An extended_proof is a data structure containing a proof and the 15 | /// corresponding primary inputs It corresponds to the data needed for the 16 | /// verifier to be able to run the verifying algorithm. 17 | template class extended_proof 18 | { 19 | private: 20 | typename snarkT::proof proof; 21 | libsnark::r1cs_primary_input> primary_inputs; 22 | 23 | public: 24 | extended_proof( 25 | typename snarkT::proof &&in_proof, 26 | libsnark::r1cs_primary_input> &&in_primary_inputs); 27 | 28 | const typename snarkT::proof &get_proof() const; 29 | 30 | const libsnark::r1cs_primary_input> &get_primary_inputs() 31 | const; 32 | 33 | std::ostream &write_json(std::ostream &) const; 34 | }; 35 | 36 | } // namespace libzeth 37 | 38 | #include "libzeth/core/extended_proof.tcc" 39 | 40 | #endif // __ZETH_CORE_EXTENDED_PROOF_HPP__ 41 | -------------------------------------------------------------------------------- /libzeth/core/extended_proof.tcc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_TYPES_EXTENDED_PROOF_TCC__ 6 | #define __ZETH_TYPES_EXTENDED_PROOF_TCC__ 7 | 8 | #include "libzeth/core/extended_proof.hpp" 9 | #include "libzeth/core/field_element_utils.hpp" 10 | #include "libzeth/serialization/r1cs_serialization.hpp" 11 | 12 | namespace libzeth 13 | { 14 | 15 | template 16 | extended_proof::extended_proof( 17 | typename snarkT::proof &&in_proof, 18 | libsnark::r1cs_primary_input> &&in_primary_inputs) 19 | : proof(in_proof), primary_inputs(in_primary_inputs) 20 | { 21 | } 22 | 23 | template 24 | const typename snarkT::proof &extended_proof::get_proof() const 25 | { 26 | return proof; 27 | } 28 | 29 | template 30 | const libsnark::r1cs_primary_input> 31 | &extended_proof::get_primary_inputs() const 32 | { 33 | return primary_inputs; 34 | } 35 | 36 | template 37 | std::ostream &extended_proof::write_json(std::ostream &out_s) const 38 | { 39 | out_s << "{\n" 40 | " \"proof\": "; 41 | snarkT::proof_write_json(proof, out_s); 42 | out_s << ",\n" 43 | " \"inputs\": "; 44 | primary_inputs_write_json(primary_inputs, out_s); 45 | out_s << "\n" 46 | "}\n"; 47 | return out_s; 48 | } 49 | 50 | } // namespace libzeth 51 | 52 | #endif // __ZETH_TYPES_EXTENDED_PROOF_TCC__ 53 | -------------------------------------------------------------------------------- /libzeth/core/field_element_utils.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_CORE_FIELD_ELEMENT_UTILS_HPP__ 6 | #define __ZETH_CORE_FIELD_ELEMENT_UTILS_HPP__ 7 | 8 | #include "include_libff.hpp" 9 | 10 | namespace libzeth 11 | { 12 | /// Convert a base field element (single component) to a hexadecimal 13 | /// string (without any JSON decoration such as '"'). 14 | template 15 | std::string base_field_element_to_hex(const FieldT &field_el); 16 | 17 | /// Convert a plain hex string (without any JSON decoration such as '"') to a 18 | /// base field element (single component). 19 | template 20 | FieldT base_field_element_from_hex(const std::string &field_str); 21 | 22 | template 23 | void field_element_write_json(const FieldT &el, std::ostream &out_s); 24 | 25 | template 26 | void field_element_read_json(FieldT &el, std::istream &in_s); 27 | 28 | template std::string field_element_to_json(const FieldT &el); 29 | 30 | template 31 | FieldT field_element_from_json(const std::string &json); 32 | 33 | /// Write a field element as bytes. Base field elements are written in plain 34 | /// (non-Montgomery) form as fixed-size big-endian integers. Extension field 35 | /// elements are written as a series of components. 36 | template 37 | void field_element_write_bytes(const FieldT &el, std::ostream &out_s); 38 | 39 | /// Read a field element as bytes, in the format described for 40 | /// field_element_write_bytes. 41 | template 42 | void field_element_read_bytes(FieldT &el, std::istream &in_s); 43 | 44 | } // namespace libzeth 45 | 46 | #include "libzeth/core/field_element_utils.tcc" 47 | 48 | #endif // __ZETH_CORE_FIELD_ELEMENT_UTILS_HPP__ 49 | -------------------------------------------------------------------------------- /libzeth/core/group_element_utils.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_CORE_GROUP_ELEMENT_UTILS_HPP__ 6 | #define __ZETH_CORE_GROUP_ELEMENT_UTILS_HPP__ 7 | 8 | #include "include_libff.hpp" 9 | 10 | namespace libzeth 11 | { 12 | 13 | /// Write a group element as a json string to a stream 14 | template 15 | void group_element_write_json(const GroupT &point, std::ostream &out_s); 16 | 17 | /// Read a JSON string from a stream and convert it into a group element 18 | template 19 | void group_element_read_json(GroupT &point, std::istream &in_s); 20 | 21 | /// Convert a group element to a json string (array of hexadecimal strings). 22 | template 23 | std::string group_element_to_json(const GroupT &point); 24 | 25 | /// Convert a JSON string into a group element 26 | template 27 | GroupT group_element_from_json(const std::string &json); 28 | 29 | /// Write a group element as bytes to a stream. The elements are written as X 30 | /// and Y coordinates of the affine form, where each coordinate is written 31 | /// using field_element_write_bytes. 32 | template 33 | void group_element_write_bytes(const GroupT &point, std::ostream &out_s); 34 | 35 | /// Read a group elements as bytes from a stream, in the format described for 36 | /// group_element_write_bytes. 37 | template 38 | void group_element_read_bytes(GroupT &point, std::istream &in_s); 39 | 40 | /// Write a collection of group elements as bytes to a stream, using 41 | /// group_element_write_bytes. 42 | template 43 | void group_elements_write_bytes( 44 | const GroupCollectionT &points, std::ostream &out_s); 45 | 46 | /// Read a collection of group elements as bytes, using 47 | /// group_elements_read_bytes. 48 | template 49 | void group_elements_read_bytes(GroupCollectionT &points, std::istream &in_s); 50 | 51 | } // namespace libzeth 52 | 53 | #include "libzeth/core/group_element_utils.tcc" 54 | 55 | #endif // __ZETH_CORE_GROUP_ELEMENT_UTILS_HPP__ 56 | -------------------------------------------------------------------------------- /libzeth/core/include_libff.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_CORE_INCLUDE_LIBFF__ 6 | #define __ZETH_CORE_INCLUDE_LIBFF__ 7 | 8 | // Include minimal set of libff types for curve-independent operations. 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #endif // __ZETH_CORE_INCLUDE_LIBFF__ 15 | -------------------------------------------------------------------------------- /libzeth/core/include_libsnark.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_CORE_INCLUDE_LIBSNARK_HPP__ 6 | #define __ZETH_CORE_INCLUDE_LIBSNARK_HPP__ 7 | 8 | // Include minimal libsnark headers for snark-independent processing of 9 | // circuits. 10 | 11 | #include "libzeth/core/include_libff.hpp" 12 | 13 | #include 14 | #include 15 | 16 | #endif // __ZETH_CORE_INCLUDE_LIBSNARK_HPP__ 17 | -------------------------------------------------------------------------------- /libzeth/core/joinsplit_input.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_CORE_JOINSPLIT_INPUT_HPP__ 6 | #define __ZETH_CORE_JOINSPLIT_INPUT_HPP__ 7 | 8 | #include "libzeth/core/bits.hpp" 9 | #include "libzeth/core/note.hpp" 10 | 11 | #include 12 | #include 13 | 14 | namespace libzeth 15 | { 16 | 17 | /// We simplify the interface of the joinsplit_input object compared to what 18 | /// Zcash did. In fact, all our fields are going to be computed from another 19 | /// component written in Python or JS, that will use the Ethereum primitives 20 | /// to hash. 21 | template class joinsplit_input 22 | { 23 | public: 24 | // merkle tree witness (path, and address) 25 | std::vector witness_merkle_path; 26 | // boolean vector, of length the depth of the merkle tree, containing the 27 | // binary encoding of the address 28 | bits_addr address_bits; 29 | zeth_note note; 30 | bits256 spending_key_a_sk; 31 | bits256 nullifier; 32 | 33 | joinsplit_input(){}; 34 | joinsplit_input( 35 | std::vector &&witness_merkle_path, 36 | const bits_addr &address_bits, 37 | const zeth_note ¬e, 38 | const bits256 &key, 39 | const bits256 &nullifier) 40 | : witness_merkle_path(std::move(witness_merkle_path)) 41 | , address_bits(address_bits) 42 | , note(note) 43 | , spending_key_a_sk(key) 44 | , nullifier(nullifier) 45 | { 46 | } 47 | }; 48 | 49 | } // namespace libzeth 50 | 51 | #endif // __ZETH_CORE_JOINSPLIT_INPUT_HPP__ 52 | -------------------------------------------------------------------------------- /libzeth/core/merkle_tree_field.hpp: -------------------------------------------------------------------------------- 1 | // DISCLAIMER: 2 | // Content taken and adapted from: 3 | // https://github.com/scipr-lab/libsnark/blob/master/libsnark/common/data_structures/merkle_tree.hpp 4 | 5 | #ifndef __ZETH_CORE_MERKLE_TREE_FIELD_HPP__ 6 | #define __ZETH_CORE_MERKLE_TREE_FIELD_HPP__ 7 | 8 | #include "libzeth/core/include_libff.hpp" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace libzeth 15 | { 16 | 17 | /// Merkle Tree whose nodes are field elements 18 | /// 19 | /// A Merkle tree is maintained as two maps: 20 | /// - `values` = Map from addresses to values, and 21 | /// - `hashes` = Map from addresses to hashes. 22 | /// 23 | /// The second map maintains the intermediate hashes of a Merkle tree 24 | /// built atop the values currently stored in the tree (the 25 | /// implementation admits a very efficient support for sparse 26 | /// trees). Besides offering methods to load and store values, the 27 | /// class offers methods to retrieve the root of the Merkle tree and to 28 | /// obtain the authentication paths for (the value at) a given address. 29 | template class merkle_tree_field 30 | { 31 | 32 | public: 33 | std::vector hash_defaults; 34 | std::map values; 35 | std::map hashes; 36 | size_t depth; 37 | 38 | merkle_tree_field(const size_t depth); 39 | merkle_tree_field( 40 | const size_t depth, const std::vector &contents_as_vector); 41 | merkle_tree_field( 42 | const size_t depth, const std::map &contents); 43 | 44 | FieldT get_value(const size_t address) const; 45 | void set_value(const size_t address, const FieldT &value); 46 | 47 | FieldT get_root() const; 48 | std::vector get_path(const size_t address) const; 49 | 50 | void dump() const; 51 | }; 52 | 53 | } // namespace libzeth 54 | 55 | #include "libzeth/core/merkle_tree_field.tcc" 56 | 57 | #endif // __ZETH_CORE_MERKLE_TREE_FIELD_HPP__ 58 | -------------------------------------------------------------------------------- /libzeth/core/multi_exp.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_CORE_MULTI_EXP_HPP__ 6 | #define __ZETH_CORE_MULTI_EXP_HPP__ 7 | 8 | #include "libzeth/core/include_libff.hpp" 9 | 10 | namespace libzeth 11 | { 12 | 13 | template 14 | GroupT multi_exp( 15 | typename std::vector::const_iterator gs_start, 16 | typename std::vector::const_iterator gs_end, 17 | typename std::vector::const_iterator fs_start, 18 | typename std::vector::const_iterator fs_end); 19 | 20 | template 21 | GroupT multi_exp( 22 | const std::vector &gs, const libff::Fr_vector &fs); 23 | 24 | } // namespace libzeth 25 | 26 | #include "libzeth/core/multi_exp.tcc" 27 | 28 | #endif // __ZETH_CORE_MULTI_EXP_HPP__ 29 | -------------------------------------------------------------------------------- /libzeth/core/multi_exp.tcc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_CORE_MULTI_EXP_TCC__ 6 | #define __ZETH_CORE_MULTI_EXP_TCC__ 7 | 8 | #include "libzeth/core/multi_exp.hpp" 9 | 10 | namespace libzeth 11 | { 12 | 13 | template 14 | GroupT multi_exp( 15 | typename std::vector::const_iterator gs_start, 16 | typename std::vector::const_iterator gs_end, 17 | typename std::vector::const_iterator fs_start, 18 | typename std::vector::const_iterator fs_end) 19 | { 20 | const libff::multi_exp_method Method = libff::multi_exp_method_BDLO12; 21 | return libff::multi_exp_filter_one_zero( 22 | gs_start, gs_end, fs_start, fs_end, 1); 23 | } 24 | 25 | template 26 | GroupT multi_exp(const std::vector &gs, const libff::Fr_vector &fs) 27 | { 28 | assert(gs.size() >= fs.size()); 29 | assert(gs.size() > 0); 30 | 31 | using Fr = libff::Fr; 32 | const libff::multi_exp_method Method = libff::multi_exp_method_BDLO12; 33 | return libff::multi_exp_filter_one_zero( 34 | gs.begin(), gs.begin() + fs.size(), fs.begin(), fs.end(), 1); 35 | } 36 | 37 | } // namespace libzeth 38 | 39 | #endif // __ZETH_CORE_MULTI_EXP_TCC__ 40 | -------------------------------------------------------------------------------- /libzeth/core/note.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_CORE_NOTE_HPP__ 6 | #define __ZETH_CORE_NOTE_HPP__ 7 | 8 | #include "libzeth/core/bits.hpp" 9 | 10 | #include 11 | 12 | namespace libzeth 13 | { 14 | 15 | class zeth_note 16 | { 17 | public: 18 | bits256 a_pk; 19 | bits64 value; 20 | bits256 rho; 21 | bits256 r; 22 | 23 | // Note, r-value refs are not used because the bits* objects are all 24 | // trivially-copyable. 25 | zeth_note( 26 | const bits256 &a_pk, 27 | const bits64 &value, 28 | const bits256 &rho, 29 | const bits256 &r) 30 | : a_pk(a_pk), value(value), rho(rho), r(r) 31 | { 32 | } 33 | 34 | zeth_note() {} 35 | 36 | inline bool is_zero_valued() const { return value.is_zero(); } 37 | }; 38 | 39 | } // namespace libzeth 40 | 41 | #endif // __ZETH_CORE_NOTE_HPP__ 42 | -------------------------------------------------------------------------------- /libzeth/core/utils.tcc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_CORE_UTILS_TCC__ 6 | #define __ZETH_CORE_UTILS_TCC__ 7 | 8 | #include "libzeth/core/utils.hpp" 9 | 10 | #include 11 | #include // required for std::length_error on linux 12 | 13 | namespace libzeth 14 | { 15 | 16 | template<> constexpr size_t bit_utils<0>::bit_size() { return 0; } 17 | 18 | template<> constexpr size_t bit_utils<0>::hamming_weight() { return 0; } 19 | 20 | template constexpr size_t bit_utils::bit_size() 21 | { 22 | return 1 + bit_utils<(X >> 1)>::bit_size(); 23 | } 24 | 25 | template constexpr size_t bit_utils::hamming_weight() 26 | { 27 | return (X & 1) + bit_utils<(X >> 1)>::hamming_weight(); 28 | } 29 | 30 | template T swap_byte_endianness(T v) 31 | { 32 | size_t len = v.size(); 33 | if (len == 0) { 34 | throw std::length_error( 35 | "Invalid bit length for the given boolean vector (should be > 0)"); 36 | } 37 | if (len % 8 != 0) { 38 | throw std::length_error("Invalid bit length for the given boolean " 39 | "vector (should be multiple of 8)"); 40 | } 41 | 42 | size_t byte_mid_length = std::ceil((len / 8) / 2); 43 | for (size_t i = 0; i < byte_mid_length; i++) { 44 | for (size_t j = 0; j < 8; j++) { 45 | std::swap(v[8 * i + j], v[len - 8 * (i + 1) + j]); 46 | } 47 | } 48 | return v; 49 | } 50 | 51 | template 52 | bool container_is_well_formed(const StructuredTs &values) 53 | { 54 | for (const auto &v : values) { 55 | if (!v.is_well_formed()) { 56 | return false; 57 | } 58 | } 59 | 60 | return true; 61 | } 62 | 63 | template 64 | void check_well_formed(const StructuredT &v, const char *name) 65 | { 66 | if (!v.is_well_formed()) { 67 | throw std::invalid_argument(std::string(name) + " not well-formed"); 68 | } 69 | } 70 | 71 | } // namespace libzeth 72 | 73 | #endif // __ZETH_CORE_UTILS_TCC__ 74 | -------------------------------------------------------------------------------- /libzeth/mpc/groth16/mpc_hash.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_MPC_GROTH16_MPC_HASH_HPP__ 6 | #define __ZETH_MPC_GROTH16_MPC_HASH_HPP__ 7 | 8 | #include "libzeth/core/hash_stream.hpp" 9 | 10 | #include 11 | #include 12 | 13 | namespace libzeth 14 | { 15 | 16 | // Hashing for MPC. Streaming and whole-buffer interfaces. 17 | static const size_t MPC_HASH_SIZE_BYTES = 64; 18 | static const size_t MPC_HASH_ARRAY_LENGTH = 19 | MPC_HASH_SIZE_BYTES / sizeof(size_t); 20 | 21 | using mpc_hash_t = size_t[MPC_HASH_ARRAY_LENGTH]; 22 | using mpc_hash_state_t = crypto_generichash_blake2b_state; 23 | 24 | void mpc_hash_init(mpc_hash_state_t &); 25 | void mpc_hash_update(mpc_hash_state_t &, const void *, size_t); 26 | void mpc_hash_final(mpc_hash_state_t &, mpc_hash_t); 27 | void mpc_compute_hash(mpc_hash_t out_hash, const void *data, size_t data_size); 28 | void mpc_compute_hash(mpc_hash_t out_hash, const std::string &data); 29 | 30 | /// Convert a hash to a human-readable string (4 x 4 x 4-byte hex words), 31 | /// following the format used in the "powersoftau" and "Sapling MPC" code. 32 | void mpc_hash_write(const mpc_hash_t hash, std::ostream &out); 33 | 34 | /// Parse a human-readable string (4 x 4 x 4-byte hex words) representing an 35 | /// mpc_hash_t. 36 | bool mpc_hash_read(mpc_hash_t out_hash, std::istream &in); 37 | 38 | /// Simple class wrapper around the above hash, following the HashT interface 39 | /// in hash_stream.hpp. 40 | class mpc_hash 41 | { 42 | private: 43 | mpc_hash_state_t state; 44 | 45 | public: 46 | using OutBuffer = mpc_hash_t; 47 | 48 | mpc_hash(); 49 | void update(const void *, size_t); 50 | void final(OutBuffer out_buffer); 51 | }; 52 | 53 | using mpc_hash_ostream = hash_ostream; 54 | using mpc_hash_ostream_wrapper = hash_ostream_wrapper; 55 | using mpc_hash_istream_wrapper = hash_istream_wrapper; 56 | 57 | } // namespace libzeth 58 | 59 | #endif // __ZETH_MPC_GROTH16_MPC_HASH_HPP__ 60 | -------------------------------------------------------------------------------- /libzeth/mpc/groth16/powersoftau_utils.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #include "libzeth/mpc/groth16/powersoftau_utils.hpp" 6 | 7 | #include 8 | 9 | namespace libzeth 10 | { 11 | 12 | template<> 13 | void read_powersoftau_g2( 14 | std::istream &in, libff::alt_bn128_G2 &out) 15 | { 16 | uint8_t marker; 17 | in.read((char *)&marker, 1); 18 | 19 | switch (marker) { 20 | case 0x00: 21 | // zero 22 | out = libff::alt_bn128_G2::zero(); 23 | break; 24 | 25 | case 0x04: 26 | // Uncompressed 27 | read_powersoftau_fp2(in, out.X); 28 | read_powersoftau_fp2(in, out.Y); 29 | out.Z = libff::alt_bn128_Fq2::one(); 30 | break; 31 | 32 | default: 33 | assert(false); 34 | break; 35 | } 36 | } 37 | 38 | template<> 39 | void write_powersoftau_g2( 40 | std::ostream &out, const libff::alt_bn128_G2 &g2) 41 | { 42 | if (g2.is_zero()) { 43 | const uint8_t zero = 0; 44 | out.write((const char *)&zero, 1); 45 | return; 46 | } 47 | 48 | libff::alt_bn128_G2 copy(g2); 49 | copy.to_affine_coordinates(); 50 | 51 | const uint8_t marker = 0x04; 52 | out.write((const char *)&marker, 1); 53 | write_powersoftau_fp2(out, copy.X); 54 | write_powersoftau_fp2(out, copy.Y); 55 | } 56 | 57 | } // namespace libzeth 58 | -------------------------------------------------------------------------------- /libzeth/serialization/filesystem_util.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #include "libzeth/serialization/filesystem_util.hpp" 6 | 7 | namespace libzeth 8 | { 9 | 10 | boost::filesystem::path get_path_to_setup_directory() 11 | { 12 | // If the ZETH_SETUP_DIR env var is not set, check HOME, and 13 | // fallback to current directory. 14 | 15 | const char *path = std::getenv("ZETH_SETUP_DIR"); 16 | if (path != nullptr) { 17 | return path; 18 | } 19 | 20 | path = std::getenv("HOME"); 21 | if (path != nullptr) { 22 | return boost::filesystem::path(path) / "zeth_setup"; 23 | } 24 | 25 | return ""; 26 | } 27 | 28 | boost::filesystem::path get_path_to_debug_directory() 29 | { 30 | const char *path = std::getenv("ZETH_DEBUG_DIR"); 31 | if (path != nullptr) { 32 | return boost::filesystem::path(path); 33 | } 34 | 35 | // Fallback destination if the ZETH_DEBUG_DIR env var is not set 36 | // We assume below that `std::getenv("HOME")` does not return `nullptr` 37 | boost::filesystem::path home_path = 38 | boost::filesystem::path(std::getenv("HOME")); 39 | boost::filesystem::path zeth_debug("zeth_debug"); 40 | boost::filesystem::path default_path = home_path / zeth_debug; 41 | return default_path; 42 | } 43 | 44 | } // namespace libzeth 45 | -------------------------------------------------------------------------------- /libzeth/serialization/filesystem_util.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_SERIALIZATION_FILESYSTEM_UTIL_HPP__ 6 | #define __ZETH_SERIALIZATION_FILESYSTEM_UTIL_HPP__ 7 | 8 | #include 9 | 10 | namespace libzeth 11 | { 12 | 13 | /// This function returns the path to the setup directory in which the SRS will 14 | /// be written and/or read from. It uses the ZETH_SETUP_DIR environment 15 | /// variable, if available, falling back to ${HOME}/zeth_setup (using the POSIX 16 | /// HOME environment variable, see: 17 | /// https://pubs.opengroup.org/onlinepubs/9699919799/), and finally the current 18 | /// directory. 19 | boost::filesystem::path get_path_to_setup_directory(); 20 | 21 | /// This function returns the path to the debug directory used in Zeth. It 22 | /// assumes that the host OS is compliant with the POSIX specification since it 23 | /// assumes that the HOME environment variable is set. See: 24 | /// https://pubs.opengroup.org/onlinepubs/9699919799/ 25 | boost::filesystem::path get_path_to_debug_directory(); 26 | 27 | } // namespace libzeth 28 | 29 | #endif // __ZETH_SERIALIZATION_FILESYSTEM_UTIL_HPP__ 30 | -------------------------------------------------------------------------------- /libzeth/serialization/proto_utils.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #include "libzeth/serialization/proto_utils.hpp" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace libzeth 12 | { 13 | 14 | // Note, any attempt to call an implementation not given will result in a 15 | // linker error. 16 | 17 | template<> std::string pp_name() 18 | { 19 | return std::string("alt-bn128"); 20 | } 21 | 22 | template<> std::string pp_name() 23 | { 24 | return std::string("bls12-377"); 25 | } 26 | 27 | template<> std::string pp_name() 28 | { 29 | return std::string("bw6-761"); 30 | } 31 | 32 | zeth_note zeth_note_from_proto(const zeth_proto::ZethNote ¬e) 33 | { 34 | return zeth_note( 35 | bits256::from_hex(note.apk()), 36 | bits64::from_hex(note.value()), 37 | bits256::from_hex(note.rho()), 38 | bits256::from_hex(note.trap_r())); 39 | } 40 | 41 | } // namespace libzeth 42 | -------------------------------------------------------------------------------- /libzeth/serialization/proto_utils.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_SERIALIZATION_PROTO_UTILS_HPP__ 6 | #define __ZETH_SERIALIZATION_PROTO_UTILS_HPP__ 7 | 8 | #include "libzeth/core/bits.hpp" 9 | #include "libzeth/core/extended_proof.hpp" 10 | #include "libzeth/core/group_element_utils.hpp" 11 | #include "libzeth/core/include_libff.hpp" 12 | #include "libzeth/core/include_libsnark.hpp" 13 | #include "libzeth/core/joinsplit_input.hpp" 14 | #include "libzeth/core/note.hpp" 15 | #include "libzeth/core/utils.hpp" 16 | 17 | #include 18 | #include 19 | 20 | // Functions to convert between in-memory and protobuf types. Consistent with 21 | // encoding functions for other types, we use the `_to_proto` and 22 | // `_from_proto` naming everywhere.a 23 | 24 | namespace libzeth 25 | { 26 | 27 | zeth_note zeth_note_from_proto(const zeth_proto::ZethNote ¬e); 28 | 29 | template 30 | zeth_proto::Group1Point point_g1_affine_to_proto(const libff::G1 &point); 31 | 32 | template 33 | libff::G1 point_g1_affine_from_proto(const zeth_proto::Group1Point &point); 34 | 35 | template 36 | zeth_proto::Group2Point point_g2_affine_to_proto(const libff::G2 &point); 37 | 38 | template 39 | libff::G2 point_g2_affine_from_proto(const zeth_proto::Group2Point &point); 40 | 41 | template 42 | joinsplit_input joinsplit_input_from_proto( 43 | const zeth_proto::JoinsplitInput &input); 44 | 45 | template std::string pp_name(); 46 | 47 | /// Populate a protobuf description of some pairing parameters 48 | template 49 | void pp_to_proto(zeth_proto::PairingParameters &pp_proto); 50 | 51 | } // namespace libzeth 52 | 53 | #include "libzeth/serialization/proto_utils.tcc" 54 | 55 | #endif // __ZETH_SERIALIZATION_PROTO_UTILS_HPP__ 56 | -------------------------------------------------------------------------------- /libzeth/serialization/r1cs_serialization.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_SERIALIZATION_R1CS_SERIALIZATION_HPP__ 6 | #define __ZETH_SERIALIZATION_R1CS_SERIALIZATION_HPP__ 7 | 8 | #include "libzeth/core/include_libff.hpp" 9 | #include "libzeth/core/include_libsnark.hpp" 10 | 11 | #include 12 | 13 | namespace libzeth 14 | { 15 | 16 | template 17 | std::ostream &primary_inputs_write_json( 18 | const std::vector &public_inputs, std::ostream &out_s); 19 | 20 | template 21 | std::istream &primary_inputs_read_json( 22 | std::vector &public_inputs, std::istream &in_s); 23 | 24 | template 25 | std::string accumulation_vector_to_json( 26 | const libsnark::accumulation_vector> &acc_vector); 27 | 28 | /// A valid string is on the form: 29 | /// "[[\"0x...\", ..., \"0x...\"], ..., [\"0x...\", ... \"0x...\"]]" 30 | /// As such, we verify the prefix and suffix of the input string to verify 31 | /// that it starts with "[[" and finishes with "]]". 32 | /// 33 | /// TODO: Have proper and more robust implementation. 34 | template 35 | libsnark::accumulation_vector> accumulation_vector_from_json( 36 | const std::string &acc_vector_str); 37 | 38 | template 39 | std::ostream &r1cs_write_json( 40 | const libsnark::r1cs_constraint_system &r1cs, std::ostream &out_s); 41 | 42 | template 43 | void r1cs_read_bytes( 44 | libsnark::r1cs_constraint_system &r1cs, std::istream &in_s); 45 | 46 | template 47 | void r1cs_write_bytes( 48 | const libsnark::r1cs_constraint_system &r1cs, std::ostream &out_s); 49 | 50 | } // namespace libzeth 51 | 52 | #include "libzeth/serialization/r1cs_serialization.tcc" 53 | 54 | #endif // __ZETH_SERIALIZATION_R1CS_SERIALIZATION_HPP__ 55 | -------------------------------------------------------------------------------- /libzeth/serialization/r1cs_variable_assignment_serialization.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_SERIALIZATION_R1CS_VARIABLE_ASSIGNMENT_SERIALIZATION_HPP__ 6 | #define __ZETH_SERIALIZATION_R1CS_VARIABLE_ASSIGNMENT_SERIALIZATION_HPP__ 7 | 8 | #include 9 | 10 | namespace libzeth 11 | { 12 | 13 | template 14 | void r1cs_variable_assignment_read_bytes( 15 | libsnark::r1cs_variable_assignment &assignment, std::istream &in_s); 16 | 17 | template 18 | void r1cs_variable_assignment_read_bytes( 19 | libsnark::r1cs_primary_input &primary, 20 | libsnark::r1cs_auxiliary_input &auxiliary, 21 | const size_t primary_input_size, 22 | std::istream &in_s); 23 | 24 | template 25 | void r1cs_variable_assignment_write_bytes( 26 | const libsnark::r1cs_variable_assignment &assignment, 27 | std::ostream &out_s); 28 | 29 | template 30 | void r1cs_variable_assignment_write_bytes( 31 | const libsnark::r1cs_primary_input &primary, 32 | const libsnark::r1cs_auxiliary_input &auxiliary, 33 | std::ostream &out_s); 34 | 35 | } // namespace libzeth 36 | 37 | #include "libzeth/serialization/r1cs_variable_assignment_serialization.tcc" 38 | 39 | #endif // __ZETH_SERIALIZATION_R1CS_VARIABLE_ASSIGNMENT_SERIALIZATION_HPP__ 40 | -------------------------------------------------------------------------------- /libzeth/snarks/groth16/groth16_api_handler.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_SNARKS_GROTH16_GROTH16_API_HANDLER_HPP__ 6 | #define __ZETH_SNARKS_GROTH16_GROTH16_API_HANDLER_HPP__ 7 | 8 | #include "libzeth/core/extended_proof.hpp" 9 | #include "libzeth/snarks/groth16/groth16_snark.hpp" 10 | 11 | #include 12 | 13 | namespace libzeth 14 | { 15 | 16 | /// Implementation of API-related functions for the Groth16 snark. 17 | template class groth16_api_handler 18 | { 19 | public: 20 | using snark = groth16_snark; 21 | 22 | static void verification_key_to_proto( 23 | const typename snark::verification_key &vk, 24 | zeth_proto::VerificationKey *message); 25 | 26 | static typename snark::verification_key verification_key_from_proto( 27 | const zeth_proto::VerificationKey &verification_key); 28 | 29 | static void extended_proof_to_proto( 30 | const extended_proof &ext_proof, 31 | zeth_proto::ExtendedProof *message); 32 | 33 | static libzeth::extended_proof extended_proof_from_proto( 34 | const zeth_proto::ExtendedProof &ext_proof); 35 | }; 36 | 37 | } // namespace libzeth 38 | 39 | #include "libzeth/snarks/groth16/groth16_api_handler.tcc" 40 | 41 | #endif // __ZETH_SNARKS_GROTH16_GROTH16_API_HANDLER_HPP__ 42 | -------------------------------------------------------------------------------- /libzeth/snarks/pghr13/pghr13_api_handler.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_SNARKS_PGHR13_PGHR13_API_HANDLER_HPP__ 6 | #define __ZETH_SNARKS_PGHR13_PGHR13_API_HANDLER_HPP__ 7 | 8 | #include "libzeth/core/extended_proof.hpp" 9 | #include "libzeth/snarks/pghr13/pghr13_snark.hpp" 10 | 11 | #include 12 | 13 | namespace libzeth 14 | { 15 | 16 | /// Implementation of API-related functions for the PGHR13 snark. 17 | template class pghr13_api_handler 18 | { 19 | public: 20 | using snark = pghr13_snark; 21 | 22 | static void verification_key_to_proto( 23 | const typename snark::verification_key &vk, 24 | zeth_proto::VerificationKey *message); 25 | 26 | static typename snark::verification_key verification_key_from_proto( 27 | const zeth_proto::VerificationKey &verification_key); 28 | 29 | static void extended_proof_to_proto( 30 | const extended_proof &ext_proof, 31 | zeth_proto::ExtendedProof *message); 32 | 33 | static libzeth::extended_proof extended_proof_from_proto( 34 | const zeth_proto::ExtendedProof &ext_proof); 35 | }; 36 | 37 | } // namespace libzeth 38 | 39 | #include "libzeth/snarks/pghr13/pghr13_api_handler.tcc" 40 | 41 | #endif // __ZETH_SNARKS_PGHR13_PGHR13_API_HANDLER_HPP__ 42 | -------------------------------------------------------------------------------- /libzeth/tests/README.md: -------------------------------------------------------------------------------- 1 | # Zeth tests 2 | 3 | ## Adding Tests 4 | 5 | The directory structure here should match that in libzeth, where files are named `_test.cpp`. 6 | 7 | Tests are built as individual executables, so must contain a minimal `main` function which invokes the tests. (See existing tests for details.) 8 | 9 | ## Run the tests 10 | 11 | Execute these commands from the `build` directory: 12 | 13 | ```console 14 | # Build and run all tests. 15 | $ cmake .. 16 | $ make check 17 | ``` 18 | 19 | Other operations can be performed as follows: 20 | 21 | ```console 22 | # Build (but do not run) all tests 23 | $ make build_tests 24 | # Build a single test 25 | $ make utils_test 26 | # Execute a single test 27 | $ libzeth/tests/utils_test 28 | # Invoke tests, with verbose output on failure 29 | $ CTEST_OUTPUT_ON_FAILURE=1 make check 30 | ``` 31 | -------------------------------------------------------------------------------- /libzeth/tests/circuits/simple_test.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_TEST_SIMPLE_TEST_HPP__ 6 | #define __ZETH_TEST_SIMPLE_TEST_HPP__ 7 | 8 | #include "libzeth/core/include_libsnark.hpp" 9 | 10 | namespace libzeth 11 | { 12 | namespace tests 13 | { 14 | 15 | /// Generate a simple test circuit with 1 public input 'y' and auxiliary 16 | /// inputs 'x', 'g1, and 'g2' for the expression: 17 | /// x^3 + 4x^2 + 2x + 5 = y 18 | /// where: 19 | /// g1 = x * x 20 | /// g2 = g1 * x 21 | template void simple_circuit(libsnark::protoboard &pb); 22 | 23 | /// Append a set of valid simple circuit inputs [ 'y', 'x', 'g1', 'g2' ] to 24 | /// out_inputs. Note that out_primary can be the same as out_auxiliary (primary 25 | /// input is appended first). 26 | template 27 | void simple_circuit_assignment( 28 | const FieldT &x, 29 | std::vector &out_primary, 30 | std::vector &out_auxiliary); 31 | 32 | } // namespace tests 33 | } // namespace libzeth 34 | 35 | #include "simple_test.tcc" 36 | 37 | #endif // __ZETH_TEST_SIMPLE_TEST_HPP__ 38 | -------------------------------------------------------------------------------- /libzeth/tests/circuits/simple_test.tcc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_TEST_SIMPLE_TEST_TCC__ 6 | #define __ZETH_TEST_SIMPLE_TEST_TCC__ 7 | 8 | #include "simple_test.hpp" 9 | 10 | namespace libzeth 11 | { 12 | namespace tests 13 | { 14 | 15 | template void simple_circuit(libsnark::protoboard &pb) 16 | { 17 | using namespace libsnark; 18 | 19 | // Prover wants to show that, for a public 'y', he knows a secret 20 | // 'x' s.t. 21 | // 22 | // x^3 + 4x^2 + 2x + 5 = y 23 | pb_variable x; 24 | pb_variable y; 25 | pb_variable g1; 26 | pb_variable g2; 27 | 28 | // Statement 29 | y.allocate(pb, "y"); 30 | 31 | // Witness 32 | x.allocate(pb, "x"); 33 | g1.allocate(pb, "g1"); 34 | g2.allocate(pb, "g2"); 35 | 36 | pb.set_input_sizes(1); 37 | 38 | // g1 == x * x 39 | pb.add_r1cs_constraint(r1cs_constraint(x, x, g1), "g1"); 40 | 41 | // g2 == g1 * x 42 | pb.add_r1cs_constraint(r1cs_constraint(g1, x, g2), "g2"); 43 | 44 | // y == (g2 + 4.g1 + 2x + 5) * 1 45 | pb.add_r1cs_constraint( 46 | r1cs_constraint(g2 + (4 * g1) + (2 * x) + 5, 1, y), "y"); 47 | } 48 | 49 | template 50 | void simple_circuit_assignment( 51 | const FieldT &x, 52 | std::vector &out_primary, 53 | std::vector &out_auxiliary) 54 | { 55 | const FieldT g1 = x * x; 56 | const FieldT g2 = g1 * x; 57 | const FieldT y = g2 + (g1 * 4) + (x * 2) + 5; 58 | out_primary.push_back(y); 59 | out_auxiliary.push_back(x); 60 | out_auxiliary.push_back(g1); 61 | out_auxiliary.push_back(g2); 62 | } 63 | 64 | } // namespace tests 65 | } // namespace libzeth 66 | 67 | #endif // __ZETH_TEST_SIMPLE_TEST_TCC__ 68 | -------------------------------------------------------------------------------- /libzeth/tests/core/chacha_test.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #include "libzeth/core/chacha_rng.hpp" 6 | #include "libzeth/core/utils.hpp" 7 | 8 | #include 9 | 10 | using namespace libzeth; 11 | 12 | namespace 13 | { 14 | 15 | TEST(ChaChaTest, ChaChaRng) 16 | { 17 | // expect_output is generated by the ChaChaRng implementation used in the 18 | // zcash powersoftau and phase2 Rust code. 19 | 20 | const std::string seed = hex_to_bytes( 21 | "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"); 22 | const std::string expect_output_0 = hex_to_bytes( 23 | "1fbc70a0206f844bb7b62ace04d25ee4de8a512b608ea1fdf2269c36f4eafb"); 24 | const std::string expect_output_1 = hex_to_bytes( 25 | "7f5941a5cd2fbe3da5c1579ec2d6fdcfd2f474bb4c93b5be09294045cb69dfe2"); 26 | const std::string expect_output_2 = hex_to_bytes( 27 | "6a10e6ac34b7180858b9964b082e617446477164a623066dc0d6b8da37b67351" 28 | "c00b43600b984a6d637503e25aae1719b1f0df6a315d0dc9cf0210b1d8d77e13"); 29 | 30 | chacha_rng rng(seed.data(), seed.size()); 31 | uint8_t output[64]; 32 | 33 | auto check_output = [&](const std::string &expect_out, 34 | const std::string &label) { 35 | rng.random(&output[0], expect_out.size()); 36 | ASSERT_EQ(0, memcmp(expect_out.data(), output, expect_out.size())) 37 | << label; 38 | }; 39 | 40 | check_output(expect_output_0, "expect_output_0"); 41 | check_output(expect_output_1, "expect_output_1"); 42 | check_output(expect_output_2, "expect_output_2"); 43 | } 44 | 45 | } // namespace 46 | 47 | int main(int argc, char **argv) 48 | { 49 | ::testing::InitGoogleTest(&argc, argv); 50 | return RUN_ALL_TESTS(); 51 | } 52 | -------------------------------------------------------------------------------- /libzeth/tests/snarks/common_api_tests.tcc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #include 6 | 7 | template void verification_key_encode_decode_json_test() 8 | { 9 | using snark = typename apiHandlerT::snark; 10 | 11 | const typename snark::verification_key initial_vk = 12 | snark::verification_key::dummy_verification_key(42); 13 | 14 | zeth_proto::VerificationKey proto_vk; 15 | apiHandlerT::verification_key_to_proto(initial_vk, &proto_vk); 16 | 17 | const typename snark::verification_key recovered_vk = 18 | apiHandlerT::verification_key_from_proto(proto_vk); 19 | ASSERT_EQ(initial_vk, recovered_vk); 20 | } 21 | 22 | template 23 | void extended_proof_encode_decode_json_test( 24 | const libzeth::extended_proof &proof) 25 | { 26 | using snark = typename apiHandlerT::snark; 27 | 28 | zeth_proto::ExtendedProof proto_proof; 29 | apiHandlerT::extended_proof_to_proto(proof, &proto_proof); 30 | 31 | const libzeth::extended_proof recovered_proof = 32 | apiHandlerT::extended_proof_from_proto(proto_proof); 33 | 34 | ASSERT_EQ(proof.get_proof(), recovered_proof.get_proof()); 35 | ASSERT_EQ(proof.get_primary_inputs(), recovered_proof.get_primary_inputs()); 36 | } 37 | -------------------------------------------------------------------------------- /libzeth/tests/snarks/groth16/groth16_api_handler_test.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #include "libzeth/serialization/proto_utils.hpp" 6 | #include "libzeth/snarks/groth16/groth16_api_handler.hpp" 7 | #include "libzeth/tests/snarks/common_api_tests.tcc" 8 | #include "zeth_config.h" 9 | 10 | #include 11 | 12 | using pp = libzeth::defaults::pp; 13 | using Fr = libff::Fr; 14 | using G1 = libff::G1; 15 | using G2 = libff::G2; 16 | using snark = libzeth::groth16_snark; 17 | 18 | namespace 19 | { 20 | 21 | TEST(Groth16ApiHandlerTest, VerificationKeyEncodeDecode) 22 | { 23 | verification_key_encode_decode_json_test< 24 | libzeth::groth16_api_handler>(); 25 | } 26 | 27 | TEST(Groth16ApiHandlerTest, ProofEncodeDecode) 28 | { 29 | snark::proof dummy_proof{ 30 | G1::random_element(), G2::random_element(), G1::random_element()}; 31 | libsnark::r1cs_primary_input dummy_inputs{ 32 | Fr::random_element(), Fr::random_element(), Fr::random_element()}; 33 | extended_proof_encode_decode_json_test< 34 | pp, 35 | libzeth::groth16_api_handler>( 36 | {std::move(dummy_proof), std::move(dummy_inputs)}); 37 | } 38 | 39 | } // namespace 40 | 41 | int main(int argc, char **argv) 42 | { 43 | pp::init_public_params(); 44 | ::testing::InitGoogleTest(&argc, argv); 45 | return RUN_ALL_TESTS(); 46 | } 47 | -------------------------------------------------------------------------------- /libzeth/tests/snarks/pghr13/pghr13_api_handler_test.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #include "libzeth/serialization/proto_utils.hpp" 6 | #include "libzeth/snarks/pghr13/pghr13_api_handler.hpp" 7 | #include "libzeth/tests/snarks/common_api_tests.tcc" 8 | #include "zeth_config.h" 9 | 10 | #include 11 | 12 | using pp = libzeth::defaults::pp; 13 | using Fr = libff::Fr; 14 | using G1 = libff::G1; 15 | using G2 = libff::G2; 16 | using snark = libzeth::pghr13_snark; 17 | 18 | namespace 19 | { 20 | 21 | TEST(PGHR13ApiHandlerTest, VerificationKeyEncodeDecode) 22 | { 23 | verification_key_encode_decode_json_test>(); 24 | } 25 | 26 | TEST(PGHR13ApiHandlerTest, ProofEncodeDecode) 27 | { 28 | snark::proof dummy_proof( 29 | {G1::random_element(), G1::random_element()}, 30 | {G2::random_element(), G1::random_element()}, 31 | {G1::random_element(), G1::random_element()}, 32 | G1::random_element(), 33 | G1::random_element()); 34 | libsnark::r1cs_primary_input dummy_inputs{ 35 | Fr::random_element(), Fr::random_element(), Fr::random_element()}; 36 | extended_proof_encode_decode_json_test>( 37 | {std::move(dummy_proof), std::move(dummy_inputs)}); 38 | } 39 | 40 | } // namespace 41 | 42 | int main(int argc, char **argv) 43 | { 44 | pp::init_public_params(); 45 | ::testing::InitGoogleTest(&argc, argv); 46 | return RUN_ALL_TESTS(); 47 | } 48 | -------------------------------------------------------------------------------- /libzeth/zeth_constants.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_ZETH_CONSTANTS_HPP__ 6 | #define __ZETH_ZETH_CONSTANTS_HPP__ 7 | 8 | #include 9 | 10 | namespace libzeth 11 | { 12 | 13 | static const size_t ZETH_NUM_JS_INPUTS = 2; 14 | static const size_t ZETH_NUM_JS_OUTPUTS = 2; 15 | 16 | static const size_t ZETH_MERKLE_TREE_DEPTH = 32; 17 | 18 | static const size_t ZETH_V_SIZE = 64; // 64 bits for the value 19 | static const size_t ZETH_RHO_SIZE = 256; // 256 bits for rho 20 | static const size_t ZETH_PHI_SIZE = 256; // 256 bits for phi 21 | static const size_t ZETH_HSIG_SIZE = 256; // 256 bits for h_sig 22 | static const size_t ZETH_A_SK_SIZE = 256; // 256 bits for a_sk 23 | static const size_t ZETH_A_PK_SIZE = 256; // 256 bits for a_pk 24 | static const size_t ZETH_R_SIZE = 256; // 256 bits for r 25 | 26 | } // namespace libzeth 27 | 28 | #endif // __ZETH_ZETH_CONSTANTS_HPP__ 29 | -------------------------------------------------------------------------------- /mpc/.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length=82 3 | -------------------------------------------------------------------------------- /mpc/.pylintrc: -------------------------------------------------------------------------------- 1 | [MESSAGES CONTROL] 2 | disable= 3 | bad-continuation, 4 | too-many-arguments, 5 | too-many-instance-attributes, 6 | missing-class-docstring, 7 | missing-function-docstring, 8 | too-many-locals, 9 | too-many-statements, 10 | too-few-public-methods, 11 | wrong-import-order, 12 | missing-module-docstring, 13 | broad-except, 14 | too-many-function-args, 15 | duplicate-code, 16 | protected-access, 17 | fixme, 18 | import-outside-toplevel, 19 | unsubscriptable-object, 20 | 21 | # TODO: `unsubscriptable-object` generates false positives for python 3.9 and pylint==2.6. 22 | # https://github.com/PyCQA/pylint/issues/3882 23 | # Re-enable it when the issue is fixed. 24 | 25 | good-names=c,e,h,i,k,m,r,y,x,cm,ct,el,ek,ex,rc,sk,vk,X,Y,nf 26 | 27 | [REPORTS] 28 | output-format=text 29 | -------------------------------------------------------------------------------- /mpc/Makefile: -------------------------------------------------------------------------------- 1 | 2 | .PHONY: setup check test syntax 3 | 4 | setup: 5 | pip install -e . --progress-bar off 6 | 7 | check: syntax test 8 | 9 | syntax: 10 | flake8 `git ls-files 'coordinator/**.py' commands 'test/**.py'` 11 | mypy `git ls-files 'coordinator/**.py' commands 'test/**.py'` 12 | pylint coordinator commands test 13 | 14 | test: 15 | python -m unittest 16 | -------------------------------------------------------------------------------- /mpc/commands/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | -------------------------------------------------------------------------------- /mpc/commands/constants.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | DEFAULT_CONFIG_FILE = "server_config.json" 8 | 9 | # Intermediate files 10 | LAGRANGE_FILE = "lagrange.bin" 11 | LINEAR_COMBINATION_FILE = "linear_combination.bin" 12 | -------------------------------------------------------------------------------- /mpc/commands/create_keypair: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from commands.constants import DEFAULT_CONFIG_FILE, LINEAR_COMBINATION_FILE 8 | from coordinator.phase1_contribution_handler import \ 9 | Phase1ServerConfig, FINAL_OUTPUT 10 | from coordinator.mpc_command import MPCCommand 11 | 12 | from click import command, option, argument 13 | from typing import Optional 14 | from os.path import join, exists 15 | 16 | 17 | @command() 18 | @argument("phase1-dir") 19 | @argument("keypair-out-file") 20 | @option("--mpc-tool", default=None, help="Path to mpc tool") 21 | def create_keypair( 22 | phase1_dir: str, 23 | keypair_out_file: str, 24 | mpc_tool: Optional[str]) -> None: 25 | """ 26 | Create a keypair from the results of the Phase1 and Phase2 MPC. This 27 | command should be executed in the Phase2 working directory, with the 28 | location of Phase1 data specified as the first argument. 29 | """ 30 | 31 | if exists(keypair_out_file): 32 | raise Exception(f"keypair file already exists: {keypair_out_file}") 33 | 34 | # Read phase1 properties from phase1/server_config.json 35 | phase1_config_file = join(phase1_dir, DEFAULT_CONFIG_FILE) 36 | with open(phase1_config_file, "r") as phase1_config_f: 37 | phase1_config = Phase1ServerConfig.from_json( 38 | phase1_config_f.read(), phase1_config_file) 39 | 40 | pot_file = join(phase1_dir, FINAL_OUTPUT) 41 | 42 | mpc = MPCCommand(mpc_tool) 43 | if not mpc.create_keypair( 44 | pot_file, 45 | LINEAR_COMBINATION_FILE, 46 | FINAL_OUTPUT, 47 | keypair_out_file, 48 | phase1_config.num_powers): 49 | raise Exception("create_keypair command failed") 50 | 51 | 52 | if __name__ == "__main__": 53 | create_keypair() 54 | -------------------------------------------------------------------------------- /mpc/commands/generate_key: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from commands.public_key_operations import public_key_information 8 | from coordinator.crypto import generate_signing_key, export_signing_key 9 | from click import command, argument, option, ClickException 10 | from os.path import exists 11 | from typing import Optional 12 | 13 | 14 | @command() 15 | @argument("key-file") 16 | @option("--public-key", "public_key_file", default=None, help="Public key file") 17 | @option("--evidence", "evidence_file", default=None, help="Evidence file") 18 | def generate_key( 19 | key_file: str, 20 | public_key_file: Optional[str], 21 | evidence_file: Optional[str]) -> None: 22 | """ 23 | Generate new private key to key-file. Public key is written to stdout. 24 | """ 25 | 26 | if exists(key_file): 27 | raise ClickException(f"key file {key_file} already exists") 28 | 29 | signing_key = generate_signing_key() 30 | public_key_information(signing_key, public_key_file, evidence_file) 31 | with open(key_file, "wb") as out_f: 32 | out_f.write(export_signing_key(signing_key)) 33 | 34 | 35 | if __name__ == "__main__": 36 | generate_key() 37 | -------------------------------------------------------------------------------- /mpc/commands/get_challenge: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from coordinator.powersoftau_command import CHALLENGE_FILE 8 | from coordinator.client import Client 9 | from click import command, argument, option 10 | from typing import Optional 11 | 12 | # The default name of the challenge file is defined by phase1 (powersoftau) 13 | # which has the strongest restrictions. 14 | 15 | 16 | @command() 17 | @argument("base-url") 18 | @option( 19 | "--challenge-file", 20 | default=CHALLENGE_FILE, 21 | help="File in which write the downloaded challenge") 22 | def get_challenge( 23 | base_url: str, 24 | challenge_file: str, 25 | server_certificate: Optional[str], 26 | insecure: bool) -> None: 27 | """ 28 | Manually download the current challenge (usually performed as part of a 29 | contribute command). 30 | """ 31 | client = Client(base_url, server_certificate, insecure) 32 | client.get_challenge(challenge_file) 33 | 34 | 35 | if __name__ == "__main__": 36 | get_challenge() 37 | -------------------------------------------------------------------------------- /mpc/commands/phase1_server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from commands.constants import DEFAULT_CONFIG_FILE 8 | from click import command, option 9 | from typing import Optional 10 | 11 | 12 | @command() 13 | @option("--path", default=".", help="Server working path") 14 | @option("--config", "-c", default=DEFAULT_CONFIG_FILE, help="Configuration file") 15 | @option( 16 | "--pot-path", 17 | default=None, 18 | help="Path to powersoftau binaries directory") 19 | @option("--num-powers", "-n", default=None, type=int, help="Number of powers") 20 | def phase1_server( 21 | path: str, 22 | config: str, 23 | pot_path: Optional[str], 24 | num_powers: Optional[int]) -> None: 25 | """ 26 | Phase1 MPC coordinator process. Reads the given configuration file and 27 | listens for contributor connections. Command line parameters override 28 | any values set in the config file. 29 | """ 30 | 31 | from coordinator.phase1_contribution_handler import \ 32 | Phase1ServerConfig, Phase1ContributionHandler 33 | from coordinator.server import Server 34 | import time 35 | 36 | # Load config file, overriding with any command line params. 37 | with open(config, "r") as config_f: 38 | phase1_config = Phase1ServerConfig.from_json(config_f.read()) 39 | if pot_path: 40 | phase1_config.powersoftau_path = pot_path 41 | if num_powers: 42 | phase1_config.num_powers = num_powers 43 | 44 | try: 45 | handler = Phase1ContributionHandler(phase1_config) 46 | server = Server(handler, phase1_config.server_configuration, path) 47 | while True: 48 | time.sleep(1) 49 | except KeyboardInterrupt: 50 | server.stop() 51 | 52 | 53 | if __name__ == "__main__": 54 | phase1_server() 55 | -------------------------------------------------------------------------------- /mpc/commands/phase2_server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | """ 8 | Script to launch a phase2 coordinator server. 9 | """ 10 | 11 | from commands.constants import DEFAULT_CONFIG_FILE 12 | from click import command, option 13 | from typing import Optional 14 | 15 | 16 | @command() 17 | @option("--path", default=".", help="Server working path") 18 | @option("--config", default=DEFAULT_CONFIG_FILE, help="Configuration file") 19 | @option("--mpc-tool", default=None, help="Path to mpc executable") 20 | def phase2_server( 21 | path: str, 22 | config: str, 23 | mpc_tool: Optional[str]) -> None: 24 | """ 25 | Phase2 MPC coordinator process. Reads the given configuration file and 26 | listens for contributor connections. Command line parameters override 27 | any values set in the config file. 28 | """ 29 | from coordinator.phase2_contribution_handler import \ 30 | Phase2ServerConfig, Phase2ContributionHandler 31 | from coordinator.server import Server 32 | import time 33 | 34 | with open(config, "r") as config_f: 35 | phase2_config = Phase2ServerConfig.from_json(config_f.read()) 36 | if mpc_tool: 37 | phase2_config.mpc_tool = mpc_tool 38 | 39 | try: 40 | handler = Phase2ContributionHandler(phase2_config) 41 | server = Server(handler, phase2_config.server_configuration, path) 42 | while True: 43 | time.sleep(1) 44 | except KeyboardInterrupt: 45 | server.stop() 46 | 47 | 48 | if __name__ == "__main__": 49 | phase2_server() 50 | -------------------------------------------------------------------------------- /mpc/commands/public_key: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from commands.public_key_operations import public_key_information 8 | from coordinator.crypto import import_signing_key 9 | from click import command, argument, option 10 | from typing import Optional 11 | 12 | 13 | @command() 14 | @argument("key-file") 15 | @option("--public-key", "public_key_file", default=None, help="Public key file") 16 | @option("--evidence", "evidence_file", default=None, help="Evidence file") 17 | def public_key_cmd( 18 | key_file: str, 19 | public_key_file: Optional[str], 20 | evidence_file: Optional[str]) -> None: 21 | """ 22 | Load signing key and print public information to stdout. 23 | """ 24 | 25 | with open(key_file, "rb") as key_f: 26 | key = import_signing_key(key_f.read()) 27 | public_key_information(key, public_key_file, evidence_file) 28 | 29 | 30 | if __name__ == "__main__": 31 | public_key_cmd() 32 | -------------------------------------------------------------------------------- /mpc/commands/public_key_operations.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | """ 8 | Functions for processing public keys, common to multiple commands. 9 | """ 10 | 11 | from coordinator.crypto import \ 12 | SigningKey, get_verification_key, \ 13 | export_verification_key, \ 14 | create_key_evidence, export_signature 15 | from typing import Optional 16 | from os.path import exists 17 | 18 | 19 | def public_key_information( 20 | key: SigningKey, 21 | public_key_file: Optional[str], 22 | evidence_file: Optional[str]) -> None: 23 | """ 24 | Print (and optionally save) public information about a private key. 25 | """ 26 | 27 | if public_key_file and exists(public_key_file): 28 | raise Exception("public key file already exists") 29 | if evidence_file and exists(evidence_file): 30 | raise Exception("evidence file already exists") 31 | 32 | pub_key = get_verification_key(key) 33 | key_evidence = create_key_evidence(key) 34 | pub_key_str = export_verification_key(pub_key) 35 | evidence_str = export_signature(key_evidence) 36 | 37 | if public_key_file: 38 | with open(public_key_file, "w") as pk_f: 39 | pk_f.write(pub_key_str) 40 | if evidence_file: 41 | with open(evidence_file, "w") as ev_f: 42 | ev_f.write(evidence_str) 43 | 44 | print("Public Verification Key:") 45 | print(pub_key_str) 46 | print("\nKey Evidence:") 47 | print(evidence_str) 48 | -------------------------------------------------------------------------------- /mpc/commands/sign_contribution: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from coordinator.crypto import \ 8 | import_digest, import_signing_key, sign, export_signature 9 | from click import command, argument 10 | 11 | 12 | @command() 13 | @argument("key-file") 14 | @argument("digest-hex") 15 | def sign_contribution(key_file: str, digest_hex: str) -> None: 16 | """ 17 | Given a key file and a digest of a contribution (as hex), generate a 18 | contribution signature. 19 | """ 20 | digest = import_digest(digest_hex) 21 | with open(key_file, "rb") as prv_f: 22 | signing_key = import_signing_key(prv_f.read()) 23 | 24 | sig = sign(signing_key, digest) 25 | print(export_signature(sig)) 26 | 27 | 28 | if __name__ == "__main__": 29 | sign_contribution() 30 | -------------------------------------------------------------------------------- /mpc/commands/upload_contribution: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from coordinator.client import Client 8 | import coordinator.contribute as contribute 9 | from click import command, argument, option 10 | from typing import Optional 11 | 12 | 13 | @command() 14 | @argument("base-url") 15 | @argument("key-file") 16 | @argument("response-file") 17 | @option("--server-certificate", default=None, help="Server certificate") 18 | @option("--insecure", is_flag=True, help="Allow missing certificate chain") 19 | def upload_contribution( 20 | base_url: str, 21 | key_file: str, 22 | response_file: str, 23 | server_certificate: Optional[str], 24 | insecure: bool) -> None: 25 | """ 26 | Manually upload a response to the MPC challenge (usually performed as part 27 | of a contribute command). 28 | """ 29 | client = Client(base_url, server_certificate, insecure) 30 | contribute.upload_response(client, response_file, key_file) 31 | 32 | 33 | if __name__ == "__main__": 34 | upload_contribution() 35 | -------------------------------------------------------------------------------- /mpc/coordinator/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | -------------------------------------------------------------------------------- /mpc/coordinator/icontributionhandler.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | """ 8 | IContributionHandler interface 9 | """ 10 | 11 | # pylint: disable=unnecessary-pass 12 | 13 | from abc import (ABC, abstractmethod) 14 | 15 | 16 | class IContributionHandler(ABC): 17 | """ 18 | Interface that must be implemented by handlers processing contributions 19 | """ 20 | 21 | @abstractmethod 22 | def get_current_challenge_file(self, contributor_idx: int) -> str: 23 | """ 24 | Return the location of the current challenge to serve. 25 | """ 26 | pass 27 | 28 | @abstractmethod 29 | def process_contribution( 30 | self, contribution_idx: int, file_name: str) -> bool: 31 | """ 32 | Process the given uploaded file as a contribution. If any errors are 33 | found, throw an exception with an appropriate message, or return false. 34 | """ 35 | pass 36 | 37 | @abstractmethod 38 | def on_completed(self) -> None: 39 | """ 40 | All contributions have been received and the MPC is complete. 41 | """ 42 | pass 43 | -------------------------------------------------------------------------------- /mpc/coordinator/interval.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import time 8 | from threading import Condition, Thread 9 | from typing import Callable 10 | 11 | 12 | class Interval: 13 | """ 14 | Simple thread that periodically executes a callback (in a thread). 15 | """ 16 | def __init__(self, period: float, callback: Callable[[], None]): 17 | self.period = period 18 | self.callback = callback 19 | self.next_deadline = time.time() 20 | self.running = True 21 | self.condition = Condition() 22 | self.thread = Thread(target=self._thread) 23 | self.thread.start() 24 | 25 | def stop(self) -> None: 26 | self.running = False 27 | self.condition.acquire() 28 | self.condition.notify() 29 | self.condition.release() 30 | self.thread.join() 31 | 32 | def _thread(self) -> None: 33 | while self.running: 34 | self.callback() 35 | self.next_deadline = self.next_deadline + self.period 36 | 37 | self.condition.acquire() 38 | while self.running: 39 | now = time.time() 40 | if now >= self.next_deadline: 41 | break 42 | self.condition.wait(self.next_deadline - now) 43 | -------------------------------------------------------------------------------- /mpc/coordinator/null_contribution_handler.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from coordinator.icontributionhandler import IContributionHandler 8 | 9 | import os 10 | import os.path 11 | 12 | CONTRIBUTION_FILE_NAME = "contrib" 13 | FINAL_FILE_NAME = "final-upload" 14 | 15 | 16 | class NullContributionHandler(IContributionHandler): 17 | """ 18 | A null handler that accepts contributions and simply stores them as 19 | subsequent challenges. When the MPC has completed, the latest contribution 20 | is moved to 'final-upload'. Can be used for testing coordinator 21 | configuration (certificate setup, etc). 22 | """ 23 | 24 | def get_current_challenge_file(self, _next_contributor_idx: int) -> str: 25 | return CONTRIBUTION_FILE_NAME 26 | 27 | def process_contribution( 28 | self, _contributionn_idx: int, file_name: str) -> bool: 29 | os.rename(file_name, CONTRIBUTION_FILE_NAME) 30 | return True 31 | 32 | def on_completed(self) -> None: 33 | assert not os.path.exists(FINAL_FILE_NAME) 34 | if os.path.exists(CONTRIBUTION_FILE_NAME): 35 | os.rename(CONTRIBUTION_FILE_NAME, FINAL_FILE_NAME) 36 | else: 37 | print("WARNING: no contributions found") 38 | -------------------------------------------------------------------------------- /mpc/coordinator/powersoftau_process_command.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from typing import Optional, List 8 | from os.path import exists 9 | 10 | CONFIG = "release" 11 | 12 | 13 | class PowersOfTauProcessCommand: 14 | """ 15 | Wrapper around the pot-process command. 16 | """ 17 | 18 | def __init__( 19 | self, pot_process_tool: Optional[str] = None, dry_run: bool = False): 20 | self.pot_process_tool = pot_process_tool or _default_tool() 21 | self.dry_run = dry_run 22 | assert exists(self.pot_process_tool), \ 23 | f"pot-process tool does not exist {self.pot_process_tool}" 24 | 25 | def compute_lagrange( 26 | self, 27 | pot_file: str, 28 | pot_degree: int, 29 | lagrange_output_file: str, 30 | lagrange_degree: Optional[int]) -> bool: 31 | lagrange_degree = lagrange_degree or pot_degree 32 | return self._exec( 33 | ["--out", lagrange_output_file, 34 | "--lagrange-degree", str(lagrange_degree), 35 | pot_file, 36 | str(pot_degree)]) 37 | 38 | def _exec(self, args: List[str]) -> bool: 39 | import subprocess 40 | args = [self.pot_process_tool] + args 41 | print(f"CMD: {' '.join(args)}") 42 | return self.dry_run or \ 43 | subprocess.run(args=args, check=False).returncode == 0 44 | 45 | 46 | def _default_tool() -> str: 47 | from os.path import join, dirname 48 | return join( 49 | dirname(__file__), "..", "..", "build", "mpc_tools", "pot-process") 50 | -------------------------------------------------------------------------------- /mpc/mypy.ini: -------------------------------------------------------------------------------- 1 | [mypy] 2 | strict_optional=True 3 | disallow_untyped_calls=True 4 | disallow_untyped_defs=True 5 | disallow_incomplete_defs=True 6 | check_untyped_defs=True 7 | scripts_are_modules=True 8 | -------------------------------------------------------------------------------- /mpc/requirements.txt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /mpc/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import sys 8 | from setuptools import find_packages 9 | from distutils.core import setup 10 | 11 | 12 | if not hasattr(sys, 'base_prefix') or sys.base_prefix == sys.prefix: 13 | print("ERROR: This is not production software, install inside a venv") 14 | exit(1) 15 | 16 | if sys.version_info < (3, 7): 17 | print("ERROR: requires python >=3.7") 18 | exit(1) 19 | 20 | 21 | setup( 22 | name='coordinator', 23 | version='0.8', 24 | description='MPC Coordinator for Zeth SRS', 25 | packages=find_packages(), 26 | install_requires=[ 27 | "mypy==0.790", 28 | "flake8==3.7.8", 29 | "pylint==2.9", 30 | "flask==1.1.1", 31 | "cheroot==7.0.0", 32 | "pycryptodome==3.9.0", 33 | "ecdsa==0.13.3", 34 | "click==7.0", 35 | "requests==2.22.0", 36 | # flask constraints on dependencies are too loose. Constrain the 37 | # versions here to avoid CI failures. 38 | "Jinja2==3.0.3", 39 | "itsdangerous==2.0.1", 40 | "Werkzeug==2.0.2", 41 | ], 42 | scripts=[ 43 | "commands/phase1_server", 44 | "commands/phase1_contribute", 45 | "commands/phase2_prepare", 46 | "commands/phase2_server", 47 | "commands/phase2_contribute", 48 | "commands/get_challenge", 49 | "commands/upload_contribution", 50 | "commands/sign_contribution", 51 | "commands/generate_key", 52 | "commands/public_key", 53 | "commands/contributors_from_csv", 54 | "commands/create_keypair", 55 | ] 56 | ) 57 | -------------------------------------------------------------------------------- /mpc/test/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | -------------------------------------------------------------------------------- /mpc/test/test_crypto.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2015-2022 Clearmatics Technologies Ltd 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from unittest import TestCase 8 | from coordinator.crypto import import_verification_key, export_verification_key 9 | 10 | 11 | TEST_VK = \ 12 | "30" + \ 13 | "819b301006072a8648ce3d020106052b810400230381860004010b0bcea9b4fa" + \ 14 | "331695817099759bcc2d21105603a308c0957212975e1b355c43f3d204b66652" + \ 15 | "a0786e53cf3448771809a05fe1fe97e4086de26f84b33a70e31ebc00aa568907" + \ 16 | "3aa89da9ecb036c1031aa27c7839de62f097cf1d46704b594c021cde001ebd0e" + \ 17 | "3f0033b98817ffa466905ce81b7916432666b490e3cbf4ca8808ebf401" 18 | 19 | 20 | class TestCrypto(TestCase): 21 | 22 | def test_vk_import_export(self) -> None: 23 | vk = import_verification_key(TEST_VK) 24 | self.assertEqual( 25 | TEST_VK, 26 | export_verification_key(vk)) 27 | -------------------------------------------------------------------------------- /mpc_tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Build for mpc utilities 2 | 3 | find_package(Boost REQUIRED COMPONENTS system program_options) 4 | include_directories(SYSTEM ${Boost_INCLUDE_DIR}) 5 | 6 | # Add the binary tree to the search path for include files 7 | # so that we will find zethConfig.h 8 | include_directories(${PROJECT_BINARY_DIR}) 9 | 10 | # Compile the pot-process utility (GROTH16 ALT-BN128 only) 11 | if(${ZETH_SNARK} STREQUAL "GROTH16" AND ${ZETH_CURVE} STREQUAL "ALT_BN128") 12 | add_executable( 13 | pot-process 14 | pot_process/pot_process.cpp 15 | ) 16 | target_link_libraries( 17 | pot-process 18 | 19 | zeth 20 | ${Boost_SYSTEM_LIBRARY} 21 | ${Boost_PROGRAM_OPTIONS_LIBRARY} 22 | ) 23 | add_subdirectory(mpc_phase2) 24 | else() 25 | message("Disabling MPC tools (only available in GROTH16 ALT-BN128 config)") 26 | endif() 27 | -------------------------------------------------------------------------------- /mpc_tools/README.md: -------------------------------------------------------------------------------- 1 | # Multi-Party Computation (MPC) tools 2 | 3 | - `pot_process`: Processes the output of ["Powers of Tau"](https://github.com/clearmatics/powersoftau), i.e. "Phase 1" 4 | - `mpc_phase2`: Implements the "Phase 2" of the MPC 5 | -------------------------------------------------------------------------------- /mpc_tools/mpc_phase2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Build for mpc phase2 utilities 2 | 3 | # library of mpc subcommands 4 | file( 5 | GLOB 6 | MPC_CLI_SOURCE 7 | cli/*.?pp 8 | ) 9 | 10 | add_library( 11 | mpc-cli 12 | 13 | ${MPC_CLI_SOURCE} 14 | ) 15 | target_include_directories(mpc-cli PUBLIC cli) 16 | target_link_libraries( 17 | mpc-cli 18 | zeth 19 | tool 20 | ${Boost_SYSTEM_LIBRARY} 21 | ${Boost_PROGRAM_OPTIONS_LIBRARY} 22 | ) 23 | 24 | # mpc coordinator executable 25 | add_executable(mpc-coord-phase2 mpc_coord.cpp) 26 | target_link_libraries(mpc-coord-phase2 mpc-cli) 27 | 28 | # mpc client executable 29 | add_executable(mpc-client-phase2 mpc_client.cpp) 30 | target_link_libraries(mpc-client-phase2 mpc-cli) 31 | 32 | # mpc test utility 33 | add_executable(mpc-test-phase2 test/mpc_test_cli.cpp) 34 | target_link_libraries(mpc-test-phase2 mpc-cli) 35 | -------------------------------------------------------------------------------- /mpc_tools/mpc_phase2/cli/README.md: -------------------------------------------------------------------------------- 1 | # mpc commands 2 | 3 | (Sub)commands to perform administrative operations related to the MPC for SRS 4 | generation. Some operations relying on the circuit-agnostic `powersoftau` data 5 | and pre-computed Lagrange polynomials evaluations, as computed by the 6 | `powersoftau` command. 7 | 8 | cli executables can be implemented as `main` functions which call into the code 9 | in this library, passing in the set of commands to make available, and a 10 | function to generate the circuit for the MPC. 11 | 12 | Commands are provided to: 13 | - generate initial "challenge" of the Phase 2 MPC 14 | - compute participants' responses to a given challenge 15 | - verify a response and create a subsequent challeng 16 | - verify the auditable transcript of contributions 17 | - create a final keypair from the MPC output 18 | -------------------------------------------------------------------------------- /mpc_tools/mpc_phase2/cli/mpc_common.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #include "mpc_common.hpp" 6 | 7 | #include "libtool/run.hpp" 8 | 9 | #include 10 | 11 | namespace 12 | { 13 | 14 | /// Instantiation of libtool::command which parses the global options for all 15 | /// mpc subcommands. 16 | class mpc_command : public libtool::command 17 | { 18 | public: 19 | void initialize_global_options( 20 | boost::program_options::options_description &global, 21 | boost::program_options::options_description &all_options) override 22 | { 23 | global.add_options()("verbose,v", "Verbose output"); 24 | all_options.add(global); 25 | } 26 | 27 | void parse_global_options( 28 | global_options &out_options, 29 | const boost::program_options::variables_map &vm) override 30 | { 31 | const bool verbose = (bool)vm.count("verbose"); 32 | if (!verbose) { 33 | libff::inhibit_profiling_info = true; 34 | libff::inhibit_profiling_counters = true; 35 | } 36 | 37 | out_options.verbose = verbose; 38 | } 39 | }; 40 | 41 | } // namespace 42 | 43 | int mpc_main( 44 | const std::map &subcommands, 45 | const ProtoboardInitFn &pb_init, 46 | int argc, 47 | char **argv) 48 | { 49 | libzeth::defaults::pp::init_public_params(); 50 | 51 | global_options options{pb_init, false}; 52 | mpc_command cmd; 53 | return libtool::run_command(cmd, options, subcommands, argc, argv); 54 | } 55 | -------------------------------------------------------------------------------- /mpc_tools/mpc_phase2/cli/mpc_subcommand.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_MPC_TOOLS_MPC_PHASE2_MPC_SUBCOMMAND_HPP__ 6 | #define __ZETH_MPC_TOOLS_MPC_PHASE2_MPC_SUBCOMMAND_HPP__ 7 | 8 | #include "libtool/subcommand.hpp" 9 | #include "zeth_config.h" 10 | 11 | using Field = libzeth::defaults::Field; 12 | 13 | using ProtoboardInitFn = std::function &)>; 14 | 15 | class global_options 16 | { 17 | public: 18 | ProtoboardInitFn protoboard_init; 19 | bool verbose; 20 | }; 21 | 22 | using mpc_subcommand = libtool::subcommand; 23 | 24 | #endif // __ZETH_MPC_TOOLS_MPC_PHASE2_MPC_SUBCOMMAND_HPP__ 25 | -------------------------------------------------------------------------------- /mpc_tools/mpc_phase2/mpc_client.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | // Utility for executing operations that are only required by "clients" (that 6 | // is, participants in the MPC that only contribute and potentially validate 7 | // the final transcript. 8 | 9 | #include "libzeth/circuits/circuit_types.hpp" 10 | #include "libzeth/circuits/circuit_wrapper.hpp" 11 | #include "mpc_common.hpp" 12 | #include "zeth_config.h" 13 | 14 | using Field = libzeth::defaults::Field; 15 | 16 | void zeth_protoboard(libsnark::protoboard &pb) 17 | { 18 | libzeth::joinsplit_gadget< 19 | Field, 20 | libzeth::HashT, 21 | libzeth::HashTreeT, 22 | libzeth::ZETH_NUM_JS_INPUTS, 23 | libzeth::ZETH_NUM_JS_OUTPUTS, 24 | libzeth::ZETH_MERKLE_TREE_DEPTH> 25 | js(pb); 26 | js.generate_r1cs_constraints(); 27 | } 28 | 29 | int main(int argc, char **argv) 30 | { 31 | const std::map commands{ 32 | {"phase2-contribute", mpc_phase2_contribute_cmd}, 33 | {"phase2-verify-transcript", mpc_phase2_verify_transcript_cmd}, 34 | {"create-keypair", mpc_create_keypair_cmd}, 35 | }; 36 | return mpc_main(commands, zeth_protoboard, argc, argv); 37 | } 38 | -------------------------------------------------------------------------------- /mpc_tools/mpc_phase2/mpc_coord.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #include "libzeth/circuits/circuit_types.hpp" 6 | #include "libzeth/circuits/circuit_wrapper.hpp" 7 | #include "mpc_common.hpp" 8 | #include "zeth_config.h" 9 | 10 | using Field = libzeth::defaults::Field; 11 | 12 | void zeth_protoboard(libsnark::protoboard &pb) 13 | { 14 | libzeth::joinsplit_gadget< 15 | Field, 16 | libzeth::HashT, 17 | libzeth::HashTreeT, 18 | libzeth::ZETH_NUM_JS_INPUTS, 19 | libzeth::ZETH_NUM_JS_OUTPUTS, 20 | libzeth::ZETH_MERKLE_TREE_DEPTH> 21 | js(pb); 22 | js.generate_r1cs_constraints(); 23 | } 24 | 25 | int main(int argc, char **argv) 26 | { 27 | const std::map commands{ 28 | {"linear-combination", mpc_linear_combination_cmd}, 29 | {"dummy-phase2", mpc_dummy_phase2_cmd}, 30 | {"phase2-begin", mpc_phase2_begin_cmd}, 31 | {"phase2-contribute", mpc_phase2_contribute_cmd}, 32 | {"phase2-verify-contribution", mpc_phase2_verify_contribution_cmd}, 33 | {"phase2-verify-transcript", mpc_phase2_verify_transcript_cmd}, 34 | {"create-keypair", mpc_create_keypair_cmd}, 35 | }; 36 | return mpc_main(commands, zeth_protoboard, argc, argv); 37 | } 38 | -------------------------------------------------------------------------------- /mpc_tools/mpc_phase2/test/mpc_test_cli.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #include "libzeth/tests/circuits/simple_test.hpp" 6 | #include "mpc_common.hpp" 7 | 8 | void simple_protoboard(libsnark::protoboard &pb) 9 | { 10 | libzeth::tests::simple_circuit(pb); 11 | } 12 | 13 | int main(int argc, char **argv) 14 | { 15 | const std::map commands{ 16 | {"linear-combination", mpc_linear_combination_cmd}, 17 | {"dummy-phase2", mpc_dummy_phase2_cmd}, 18 | {"phase2-begin", mpc_phase2_begin_cmd}, 19 | {"phase2-contribute", mpc_phase2_contribute_cmd}, 20 | {"phase2-verify-contribution", mpc_phase2_verify_contribution_cmd}, 21 | {"phase2-verify-transcript", mpc_phase2_verify_transcript_cmd}, 22 | {"create-keypair", mpc_create_keypair_cmd}, 23 | }; 24 | return mpc_main(commands, simple_protoboard, argc, argv); 25 | } 26 | -------------------------------------------------------------------------------- /mpc_tools/pot_process/README.md: -------------------------------------------------------------------------------- 1 | # pot-process command 2 | 3 | Command for processing powersoftau data (output from commands in 4 | https://github.com/clearmatics/powersoftau), independent of any 5 | specific circuit. Main use-case is to pre-compute the evaluations of 6 | the Lagrange polynomials for domains of specific sizes, so that this 7 | data can be used during the remaining steps of the SRS computation, 8 | across multiple circuits. 9 | 10 | `pot-process` command can also be used to verify powersoftau data, and 11 | to generate "dummy" powersoftau data (that is, based purely on local 12 | randomness with no MPC) for testing. 13 | 14 | For usage details, see output of `pot-process --help` 15 | -------------------------------------------------------------------------------- /proto/zeth/api/ec_group_messages.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package zeth_proto; 4 | 5 | 6 | // The points in G1 are represented in affine form. The coordinates are encoded 7 | // as JSON objects. In this case (where coordinates are base field elements), 8 | // these are plain JSON strings. 9 | // 10 | // e.g. Let A be a `Group1Point` message. Then `A` is of the form: 11 | // ``` 12 | // A = { 13 | // x_coord = "\"0xa34...ef\"", 14 | // y_coord = "\"0xae7...dc\"" 15 | // } 16 | message Group1Point { 17 | // First coordinate of the point 18 | string x_coord = 1; 19 | // Second coordinate of the point 20 | string y_coord = 2; 21 | } 22 | 23 | // The points in G2 are represented in affine form. Coordinates are encoded as 24 | // JSON objects containing hexadecimal strings. Depending on the pairing, 25 | // coordinates may be in the base field (simple strings, as for G1) or in 26 | // extension fields (JSON arrays of strings). 27 | // 28 | // e.g. Let A be a `Group2Point` message. Then `A` is of the form: 29 | // ``` 30 | // A = { 31 | // x_coord = "[\"0xa34...ef\", ... \"0xaef...ab\"]", 32 | // y_coord = "[\"0xae7...dc\", ... \"0xbfe...54\"]" 33 | // } 34 | message Group2Point { 35 | // First coordinate of the point 36 | string x_coord = 1; 37 | // Second coordinate of the point 38 | string y_coord = 2; 39 | } 40 | 41 | // A set of useful attributes of a pairing. Expand this as clients are required 42 | // to perform more operations. 43 | message PairingParameters { 44 | // Name of the pairing 45 | string name = 1; 46 | 47 | // Order of the G1 and G2 subgroups as a hex string. 48 | string r = 2; 49 | 50 | // Modulus of the base field as a hex string. 51 | string q = 3; 52 | 53 | // Generator of G1 54 | Group1Point generator_g1 = 4; 55 | 56 | // Generator of G2 57 | Group2Point generator_g2 = 5; 58 | } 59 | -------------------------------------------------------------------------------- /proto/zeth/api/groth16_messages.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package zeth_proto; 4 | 5 | import "zeth/api/ec_group_messages.proto"; 6 | 7 | message VerificationKeyGROTH16 { 8 | Group1Point alpha_g1 = 1; 9 | Group2Point beta_g2 = 2; 10 | Group2Point delta_g2 = 4; 11 | string abc_g1 = 5; 12 | } 13 | 14 | message ExtendedProofGROTH16 { 15 | Group1Point a = 1; 16 | Group2Point b = 2; 17 | Group1Point c = 3; 18 | string inputs = 4; 19 | } 20 | -------------------------------------------------------------------------------- /proto/zeth/api/pghr13_messages.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package zeth_proto; 4 | 5 | import "zeth/api/ec_group_messages.proto"; 6 | 7 | message VerificationKeyPGHR13 { 8 | Group2Point a = 1; 9 | Group1Point b = 2; 10 | Group2Point c = 3; 11 | Group2Point gamma = 4; 12 | Group1Point gamma_beta_g1 = 5; 13 | Group2Point gamma_beta_g2 = 6; 14 | Group2Point z = 7; 15 | string ic = 8; 16 | } 17 | 18 | // Contains the proof along with the public inputs 19 | message ExtendedProofPGHR13 { 20 | Group1Point a = 1; 21 | Group1Point a_p = 2; 22 | Group2Point b = 3; 23 | Group1Point b_p = 4; 24 | Group1Point c = 5; 25 | Group1Point c_p = 6; 26 | Group1Point h = 7; 27 | Group1Point k = 8; 28 | string inputs = 9; 29 | } 30 | -------------------------------------------------------------------------------- /proto/zeth/api/prover.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package zeth_proto; 4 | 5 | import "google/protobuf/empty.proto"; 6 | 7 | import "zeth/api/zeth_messages.proto"; 8 | import "zeth/api/snark_messages.proto"; 9 | import "zeth/api/ec_group_messages.proto"; 10 | 11 | 12 | // Information describing configuration options of the server that may be of 13 | // interest to clients. 14 | message ProverConfiguration { 15 | // The zk-snark scheme used by this server ("GROTH16" or "PGHR13"). 16 | string zksnark = 1; 17 | 18 | // PairingParameters used by the server 19 | PairingParameters pairing_parameters = 2; 20 | } 21 | 22 | service Prover { 23 | // Get some configuration information 24 | rpc GetConfiguration(google.protobuf.Empty) returns (ProverConfiguration) {} 25 | 26 | // Fetch the verification key from the prover server 27 | rpc GetVerificationKey(google.protobuf.Empty) returns (VerificationKey) {} 28 | 29 | // Request a proof generation on the given inputs 30 | rpc Prove(ProofInputs) returns (ExtendedProofAndPublicData) {} 31 | } 32 | -------------------------------------------------------------------------------- /proto/zeth/api/snark_messages.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package zeth_proto; 4 | 5 | import "zeth/api/pghr13_messages.proto"; 6 | import "zeth/api/groth16_messages.proto"; 7 | 8 | message VerificationKey { 9 | oneof VK { 10 | VerificationKeyPGHR13 pghr13_verification_key = 1; 11 | VerificationKeyGROTH16 groth16_verification_key = 2; 12 | } 13 | } 14 | 15 | message ExtendedProof { 16 | oneof EP { 17 | ExtendedProofPGHR13 pghr13_extended_proof = 1; 18 | ExtendedProofGROTH16 groth16_extended_proof = 2; 19 | } 20 | } -------------------------------------------------------------------------------- /proto/zeth/api/zeth_messages.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package zeth_proto; 4 | 5 | import "zeth/api/snark_messages.proto"; 6 | 7 | message ZethNote { 8 | string apk = 1; 9 | // Hex string representing a int64 value 10 | string value = 2; 11 | string rho = 3; 12 | string trap_r = 4; 13 | } 14 | 15 | message JoinsplitInput { 16 | // Merkle authentication path to the commitment 17 | // of the note in the Merkle tree. Each node of 18 | // the merkle tree is treated as a string 19 | repeated string merkle_path = 1; 20 | int64 address = 2; 21 | ZethNote note = 3; 22 | string spending_ask = 4; 23 | string nullifier = 5; 24 | } 25 | 26 | message ProofInputs { 27 | string mk_root = 1; 28 | // List of inputs to the Joinsplit 29 | repeated JoinsplitInput js_inputs = 2; 30 | // List of output to the Joinsplit 31 | repeated ZethNote js_outputs = 3; 32 | // Hexadecimal string representing a uint64 value 33 | string pub_in_value = 4; 34 | // Hexadecimal string representing a uint64 value 35 | string pub_out_value = 5; 36 | string h_sig = 6; 37 | string phi = 7; 38 | } 39 | 40 | // The extended proof and related public data for the Zeth statement using ProofInputs data 41 | message ExtendedProofAndPublicData { 42 | // The extended proof (with single public input - the hash of public_data). 43 | ExtendedProof extended_proof = 1; 44 | 45 | // The public data (public inputs to the Zeth statement). Each element in 46 | // the array is a hex-encoded member of the scalar field for the pairing 47 | // being used. 48 | repeated string public_data = 2; 49 | } 50 | -------------------------------------------------------------------------------- /prover_server/README.md: -------------------------------------------------------------------------------- 1 | # Zeth Prover Server 2 | 3 | This component listens for incoming "proof generation" requests, generates the proof and returns it to the caller. 4 | 5 | Note that this program is seen as a daemon running on the machine of the Zeth user. It can be deployed on a different machine but care will need to be taken to make sure that the witness is protected while communicating with the server. This is out of scope of this work. 6 | -------------------------------------------------------------------------------- /scripts/build_utils.sh: -------------------------------------------------------------------------------- 1 | # Utility functions for general build tasks. 2 | # 3 | # All functions expect to be executed the root directory of the repository, and 4 | # will exit with this as the current directory. 5 | 6 | 7 | # Init some global variables related to the platform. Some other functions may 8 | # expect this to be called before they are invoked. 9 | function init_platform() { 10 | platform=`uname` 11 | echo platform=${platform} 12 | } 13 | 14 | # Assert that init_platform has been called 15 | function assert_init_platform() { 16 | if [ "${platform}" == "" ] ; then 17 | echo init_platform has not been called 18 | exit 1 19 | fi 20 | } 21 | 22 | # Install dependencies for cpp builds 23 | function cpp_build_setup() { 24 | assert_init_platform 25 | 26 | # Extra deps for native builds 27 | 28 | if [ "${platform}" == "Linux" ] ; then 29 | if (which apk) ; then 30 | # Packages already available in Docker build 31 | echo -n # null op required for syntax 32 | elif (which yum) ; then 33 | sudo yum groupinstall -y "Development Tools" 34 | sudo yum install -y \ 35 | openssl openssl-devel \ 36 | gmp-devel procps-devel cmake3 \ 37 | python3 python3-devel \ 38 | boost-devel 39 | else 40 | sudo apt install \ 41 | libboost-dev \ 42 | libboost-system-dev \ 43 | libboost-filesystem-dev \ 44 | libboost-program-options-dev \ 45 | libgmp-dev \ 46 | libprocps-dev \ 47 | libxslt1-dev \ 48 | pkg-config 49 | fi 50 | fi 51 | } 52 | -------------------------------------------------------------------------------- /scripts/check-copyright: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Simple script to check source files in the repository and ensure that they is 4 | # a Copyright or DISCLAIMER in the first few lines. 5 | 6 | export RESULT=0 7 | function check_copyright_files() { 8 | count=0 9 | while read -r file ; do 10 | if ! (head -n 4 ${file} | grep -q "Copyright\|DISCLAIMER") ; then 11 | echo "check-copyright: ${file}" 12 | count=$((${count} + 1)) 13 | fi 14 | done 15 | return ${count} 16 | } 17 | 18 | if ! (git ls-files '*.py' | check_copyright_files && \ 19 | git ls-files 'client/commands' | check_copyright_files && \ 20 | git ls-files 'mpc/commands' | check_copyright_files && \ 21 | git ls-files '*.hpp' '*.cpp' '*.tcc' | check_copyright_files) 22 | then 23 | echo "check-copyright: ERROR: the above files have missing copyright notices" 24 | exit 1 25 | fi 26 | -------------------------------------------------------------------------------- /scripts/docker/entrypoint-mpc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | COORDINATOR_HOST_ENTRY="${COORDINATOR_IP} mpc-coordinator" 6 | echo ${COORDINATOR_HOST_ENTRY} >> /etc/hosts 7 | 8 | echo "Phase1 binaries >> $(which compute)" 9 | echo "Phase2 binaries >> $(which mpc-client-phase2)" 10 | 11 | exec "$@" 12 | -------------------------------------------------------------------------------- /scripts/ec2-setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Installs dependencies and runs a build of all components required to execute 4 | # the zeth pipeline. Specialized for ec2 instances using the 'yum' package 5 | # manager. 6 | 7 | if ! (which yum) ; then 8 | echo ERROR: yum package manager not found. 9 | exit 1 10 | fi 11 | 12 | set -e 13 | set -x 14 | 15 | # 16 | # Dependencies 17 | # 18 | 19 | # Packages 20 | sudo yum groupinstall -y "Development Tools" 21 | sudo yum install -y \ 22 | openssl openssl-devel \ 23 | gmp-devel procps-devel cmake3 \ 24 | python3 python3-devel \ 25 | boost-devel \ 26 | emacs-nox 27 | sudo ln -sf /usr/bin/cmake3 /usr/local/bin/cmake 28 | 29 | # Library directories 30 | sudo sh -c 'echo /usr/local/lib > /etc/ld.so.conf.d/local-x86_64.conf' 31 | sudo ldconfig 32 | 33 | # Install grpc 34 | scripts/install-grpc /usr/local v1.44.x 35 | 36 | # Install and activate nodejs 37 | curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash 38 | . ~/.nvm/nvm.sh 39 | nvm install 10 40 | 41 | # Setup ganache 42 | pushd zeth_contracts 43 | npm config set python python2.7 44 | npm config set engine-strict true 45 | npm config set unsafe-perm true 46 | npm install --unsafe-perm 47 | popd 48 | 49 | # 50 | # Zeth-specific setup 51 | # 52 | 53 | # Setup client 54 | pushd client 55 | python3 -m venv env 56 | . env/bin/activate 57 | make setup 58 | sudo ln -sf ~/.solcx/solc-* /usr/local/bin/solc 59 | popd 60 | 61 | # Prover server 62 | mkdir -p build 63 | pushd build 64 | CMAKE_PREFIX_PATH=/usr/local cmake -DCMAKE_BUILD_TYPE=Release .. 65 | make -j"$(($(nproc)+1))" prover-server zeth-tool 66 | popd 67 | -------------------------------------------------------------------------------- /scripts/format: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CLANG_FORMAT=clang-format 4 | 5 | ${CLANG_FORMAT} --version 6 | if [ "" == "$1" ] ; then 7 | files=`git ls-files '*.cpp' '*.cc' '*.hpp' '*.hh' '*.tcc'` 8 | for f in $files ; do 9 | echo "FORMATTING $f" 10 | ${CLANG_FORMAT} -style=file -i $f 11 | done 12 | else 13 | for f in $@ ; do 14 | echo "FORMATTING $f" 15 | ${CLANG_FORMAT} -style=file -i $f 16 | done 17 | fi 18 | -------------------------------------------------------------------------------- /scripts/ganache-start: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo Starting ganache docker container. Press CTRL-C to exit. 4 | 5 | # Run ganache from the Docker container, passing in the flags required by the 6 | # zeth tests. 7 | docker run \ 8 | --rm \ 9 | -p 8545:8545 \ 10 | ghcr.io/clearmatics/ganache-cli:latest \ 11 | --hardfork istanbul \ 12 | --gasLimit 0x3FFFFFFFFFFFF \ 13 | --gasPrice 1 \ 14 | --defaultBalanceEther 9000000000 15 | -------------------------------------------------------------------------------- /scripts/mpc-setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | platform=`uname` 4 | echo platform=${platform} 5 | 6 | set -x 7 | 8 | python3 --version 9 | which python3 || echo No python3 10 | 11 | set -e 12 | set -x 13 | 14 | cd mpc 15 | python3 -m venv env 16 | . env/bin/activate 17 | pip install --upgrade pip --progress-bar off 18 | make setup 19 | -------------------------------------------------------------------------------- /scripts/prover-profile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Simple script to run the generic prover with some keys and witness data, 4 | # recording the output (including timing information) to separate files. 5 | # 6 | # DATA_DIR and CIRCUIT variables must be set such that the directory 7 | # ${DATA_DIR} contains the following files: 8 | # 9 | # ${CIRCUIT}_pk.bin 10 | # ${CIRCUIT}_vk.bin 11 | # ${CIRCUIT}_assignment.bin 12 | # ${CIRCUIT}_primary.bin 13 | # 14 | # The zeth-tool binary is expected to be in the path, or at ${ZETH_TOOL}. 15 | 16 | if [ "${DATA_DIR}" == "" ] ; then 17 | echo "DATA_DIR var must be set (see comments in script)" 18 | exit 1 19 | fi 20 | 21 | if [ "${CIRCUIT}" == "" ] ; then 22 | echo "CIRCUIT var must be set (see comments in script)" 23 | exit 1 24 | fi 25 | 26 | # If not given, use any zeth-tool in the path or a default location. 27 | if [ "${ZETH_TOOL}" == "" ] ; then 28 | if (which zeth-tool) ; then 29 | ZETH_TOOL=`which zeth-tool` 30 | else 31 | ZETH_TOOL=./zeth_tool/zeth-tool 32 | fi 33 | fi 34 | 35 | PK=${DATA_DIR}/${CIRCUIT}_pk.bin 36 | VK=${DATA_DIR}/${CIRCUIT}_vk.bin 37 | ASSIGNMENT=${DATA_DIR}/${CIRCUIT}_assignment.bin 38 | PRIMARY_INPUT=${DATA_DIR}/${CIRCUIT}_primary.bin 39 | 40 | if [ "$1" == "" ] ; then 41 | echo Usage: $0 '' 42 | exit 1 43 | fi 44 | TAG=$1 45 | 46 | set -e 47 | set -x 48 | 49 | ${ZETH_TOOL} prove --profile ${PK} ${ASSIGNMENT} proof.bin > ${CIRCUIT}_${TAG}_proof_1.txt 50 | ${ZETH_TOOL} verify ${VK} ${PRIMARY_INPUT} proof.bin 51 | ${ZETH_TOOL} prove --profile ${PK} ${ASSIGNMENT} proof.bin > ${CIRCUIT}_${TAG}_proof_2.txt 52 | ${ZETH_TOOL} verify ${VK} ${PRIMARY_INPUT} proof.bin 53 | ${ZETH_TOOL} prove --profile ${PK} ${ASSIGNMENT} proof.bin > ${CIRCUIT}_${TAG}_proof_3.txt 54 | ${ZETH_TOOL} verify ${VK} ${PRIMARY_INPUT} proof.bin 55 | -------------------------------------------------------------------------------- /scripts/recover-keypair: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This scripts is used during the distribution of the SRS. 4 | # Since hosting platforms may have size limits for files, it is possible to 5 | # compress the keypair and split the archive file into pieces, by using: 6 | # ``` 7 | # tar cvf - ./zeth_setup | gzip -9 - > zeth_setup.tar.gz \ 8 | # && split -b zeth_setup.tar.gz zeth_setup.tar.gz. \ 9 | # ``` 10 | # All those pieces can be used for distribution. Upon reception of all 11 | # pieces, the script below recovers the keypair and outputs the file digest 12 | # allowing to check that the SRS has properly been distributed. 13 | 14 | TAR_KEYPAIR_FILE="zeth_setup.tar.gz" 15 | FILES=$(ls ${TAR_KEYPAIR_FILE}.??) 16 | 17 | if [ -z "$FILES" ] 18 | then 19 | echo "No files to process." 20 | echo "Please make sure to download the archive files and place" \ 21 | "them in the Zeth directory" 22 | exit 1 23 | fi 24 | 25 | echo "Assembling files..." 26 | cat ${FILES} > ${TAR_KEYPAIR_FILE} 27 | 28 | echo "Decompressing recovered archive ${TAR_KEYPAIR_FILE}..." 29 | tar xvzf ${TAR_KEYPAIR_FILE} 30 | 31 | echo "Computing keypair hash digest..." 32 | echo $(shasum zeth_setup/keypair.bin) 33 | 34 | echo "Removing archive pieces..." 35 | rm ${FILES} 36 | -------------------------------------------------------------------------------- /scripts/set-jsinout: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # client/zeth/core/constants.py:JS_INPUTS: int = 2 4 | # client/zeth/core/constants.py:JS_OUTPUTS: int = 2 5 | sed -i -e 's/JS_INPUTS: int = 2/JS_INPUTS: int = '$1'/g' client/zeth/core/constants.py 6 | sed -i -e 's/JS_OUTPUTS: int = 2/JS_OUTPUTS: int = '$1'/g' client/zeth/core/constants.py 7 | 8 | # libzeth/zeth_constants.hpp:static const size_t ZETH_NUM_JS_INPUTS = 2; 9 | # libzeth/zeth_constants.hpp:static const size_t ZETH_NUM_JS_OUTPUTS = 2; 10 | sed -i -e 's/static const size_t ZETH_NUM_JS_INPUTS = 2/static const size_t ZETH_NUM_JS_INPUTS = '$1'/g' libzeth/zeth_constants.hpp 11 | sed -i -e 's/static const size_t ZETH_NUM_JS_OUTPUTS = 2/static const size_t ZETH_NUM_JS_OUTPUTS = '$1'/g' libzeth/zeth_constants.hpp 12 | -------------------------------------------------------------------------------- /scripts/test-mpc-contributors-from-csv: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . scripts/test_mpc_common.sh 4 | . mpc/env/bin/activate 5 | 6 | set -e 7 | set -x 8 | 9 | VALID_CONTRIBUTORS_CSV=${TEST_DATA_DIR}/test_mpc_registration.csv 10 | INVALID_CONTRIBUTORS_CSV=${TEST_DATA_DIR}/test_mpc_registration_invalid.csv 11 | 12 | mkdir -p _test_contributors_from_csv 13 | 14 | pushd _test_contributors_from_csv 15 | # Valid contributors CSV 16 | contributors_from_csv ${VALID_CONTRIBUTORS_CSV} server_config.json 17 | 18 | # Invalid contributors CSV should fail 19 | if (contributors_from_csv ${INVALID_CONTRIBUTORS_CSV} server_config_invalid.json) 20 | then 21 | echo "ERROR: invalid contributors file should generate an error" 22 | exit 1 23 | fi 24 | popd 25 | 26 | set +x 27 | passed 28 | -------------------------------------------------------------------------------- /scripts/test-pot-process: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | POT_PROCESS=$1 4 | [ "" == "${POT_PROCESS}" ] && POT_PROCESS="build/mpc_tools/pot-process" 5 | 6 | POT_DATA="testdata/powersoftau_challenge.4.bin" 7 | POT_DATA_DEGREE=16 8 | 9 | set -e 10 | set -x 11 | 12 | # Check real data 13 | ${POT_PROCESS} --check ${POT_DATA} ${POT_DATA_DEGREE} 14 | 15 | # Write dummy data 16 | ${POT_PROCESS} --dummy /tmp/test_pot-6.bin 64 17 | 18 | # Check consistency of dummy data 19 | ${POT_PROCESS} --check /tmp/test_pot-6.bin 64 20 | 21 | # Generate encoded Lagrange evaluation from real data 22 | ${POT_PROCESS} --out /tmp/lagrange-4.bin ${POT_DATA} ${POT_DATA_DEGREE} 23 | 24 | # Generate encoded evaluation of Lagrange polynomials of smaller 25 | # degree, from real data 26 | ${POT_PROCESS} \ 27 | --out /tmp/lagrange-3.bin \ 28 | --lagrange-degree $((${POT_DATA_DEGREE} / 2)) \ 29 | ${POT_DATA} ${POT_DATA_DEGREE} 30 | 31 | set +x 32 | echo "==================================================================" 33 | echo "== PASSED ==" 34 | echo "==================================================================" 35 | -------------------------------------------------------------------------------- /scripts/test_zeth_cli_common.sh: -------------------------------------------------------------------------------- 1 | 2 | TRUFFLE_DIR=`pwd`/zeth_contracts 3 | 4 | function run_truffle() { 5 | pushd ${TRUFFLE_DIR} 6 | eval truffle $@ 7 | popd 8 | } 9 | 10 | function run_as() { 11 | pushd $1 12 | shift 13 | eval $@ 14 | popd 15 | } 16 | 17 | function show_balances() { 18 | run_truffle exec ../scripts/test_zeth_cli_show_balances.js 19 | } 20 | 21 | # Show the balance for the users in the test, based on their locally managed 22 | # accounts. 23 | function show_balances() { 24 | for name in deployer alice bob charlie ; do 25 | pushd ${name} 26 | echo -n "${name}: " 27 | zeth-helper eth-get-balance 28 | popd 29 | done 30 | } 31 | 32 | # 1 - name 33 | function setup_user_hosted_key() { 34 | mkdir -p $1 35 | pushd $1 36 | ! [ -e eth-network ] && \ 37 | (zeth-helper eth-gen-network-config) 38 | ! [ -e eth-address ] && \ 39 | (grep $1 ../accounts | grep -oe '0x.*' > eth-address) 40 | ! [ -e zeth-address.priv ] && \ 41 | (zeth gen-address) 42 | popd 43 | } 44 | 45 | # 1 - name 46 | # 2 - (optional) network-name 47 | function setup_user_local_key() { 48 | mkdir -p $1 49 | pushd $1 50 | ! [ -e eth-network ] && \ 51 | (zeth-helper eth-gen-network-config $2) 52 | ! [ -e eth-address ] && \ 53 | (zeth-helper eth-gen-address && zeth-helper eth-fund) 54 | ! [ -e zeth-address.priv ] && \ 55 | (zeth gen-address) 56 | 57 | # Ensure that we have been able to perform all of these operations without 58 | # querying the prover-server for the configuration. 59 | if [ -e prover-config.cache ] ; then 60 | echo Expected no prover config file 61 | exit 1 62 | fi 63 | 64 | popd 65 | } 66 | 67 | # 1 - deployer_name 68 | # 2 - user_name 69 | function copy_deployment_info() { 70 | cp $1/zeth-instance $2 71 | } 72 | -------------------------------------------------------------------------------- /scripts/test_zeth_cli_get_accounts.js: -------------------------------------------------------------------------------- 1 | module.exports = function(cb) { 2 | var accountsA = web3.eth.getAccounts(); 3 | accountsA.then(function(accounts) { 4 | console.log("deployer: " + accounts[0]); 5 | console.log("alice: " + accounts[1]); 6 | console.log("bob: " + accounts[2]); 7 | console.log("charlie: " + accounts[3]); 8 | cb(); 9 | }); 10 | // var accounts = await accountsA; 11 | // console.log(accounts); 12 | } 13 | -------------------------------------------------------------------------------- /scripts/test_zeth_cli_new_account.js: -------------------------------------------------------------------------------- 1 | module.exports = function(cb) { 2 | newAccountA = web3.eth.personal.newAccount(); 3 | newAccountA.then(function (account) { 4 | console.log(account); 5 | cb(); 6 | }); 7 | }; 8 | -------------------------------------------------------------------------------- /scripts/test_zeth_cli_show_balances.js: -------------------------------------------------------------------------------- 1 | module.exports = function(cb) { 2 | var accountsA = web3.eth.getAccounts(); 3 | accountsA.then(function(accounts) { 4 | var num_accounts = accounts.length; 5 | accounts.forEach(function (account) { 6 | var on_balance = function(balance) { 7 | console.log(account + ": " + balance); 8 | if (--num_accounts == 0) { 9 | cb(); 10 | } 11 | }; 12 | web3.eth.getBalance(account).then(on_balance); 13 | }); 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /scripts/test_zeth_cli_show_balances_named.js: -------------------------------------------------------------------------------- 1 | module.exports = function(cb) { 2 | var accountsA = web3.eth.getAccounts(); 3 | accountsA.then(function(accounts) { 4 | var shown = 0; 5 | var on_balance = function(name) { 6 | return function(bal) { 7 | console.log(name + ": " + bal); 8 | if (++shown == 4) { cb(); } 9 | }; 10 | }; 11 | 12 | web3.eth.getBalance(accounts[0]).then(on_balance("deployer ")); 13 | web3.eth.getBalance(accounts[1]).then(on_balance("alice ")); 14 | web3.eth.getBalance(accounts[2]).then(on_balance("bob ")); 15 | web3.eth.getBalance(accounts[3]).then(on_balance("charlie ")); 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /setup_env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export ZETH=`pwd` 4 | export ZETH_CONTRACTS_DIR=$ZETH/zeth_contracts/contracts 5 | export ZETH_DEBUG_DIR=$ZETH/debug 6 | 7 | export ZETH_SETUP_DIR=$ZETH/zeth_setup 8 | mkdir -p $ZETH_SETUP_DIR 9 | 10 | # Add the zeth executables in the PATH 11 | export PATH=$ZETH/build/prover_server:$ZETH/build/mpc_tools:$ZETH/build/mpc_tools/mpc_phase2:$ZETH/build/zeth_tool:$PATH 12 | -------------------------------------------------------------------------------- /testdata/mpc_key1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/zeth/4e0c07528db93fbcf0baecfac4905a3108a0496a/testdata/mpc_key1.bin -------------------------------------------------------------------------------- /testdata/mpc_key1.evidence: -------------------------------------------------------------------------------- 1 | 015bbb49bf4ca076c6cf6668d710bc415483dd2f78f3600e1a9052ed6712e8ca0b4468ce65d59e8eb9c0d24bcc28ea58fe7fa899f9703cbd2db89f3cf70822684cc300fc8cc01eea1c8652fafe158fb378ed9820515ef856503a347db6579f945cf4e00f6c2850d5c544db3803561faa2a85d300a7b78d5c95f1f0f9c333aaf4fb8671d8 -------------------------------------------------------------------------------- /testdata/mpc_key1.pub: -------------------------------------------------------------------------------- 1 | 30819b301006072a8648ce3d020106052b81040023038186000401ca3dde04a97e63757a9d67ee6e4d957f1da3b19b8e3b85029664471e969439ee26f375a523aef3d3a27b78060ff1ac781c306b73979613a9cb18d9ac549cda1ee601b243420de194977e655827f053c531b9d2639cf714b0741ae63647fdffc40a386a579b24145c32a76c842e4ff3107cdeda73608c0a15d587a4bd5f1a5bc3b2eed4 2 | -------------------------------------------------------------------------------- /testdata/mpc_key2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/zeth/4e0c07528db93fbcf0baecfac4905a3108a0496a/testdata/mpc_key2.bin -------------------------------------------------------------------------------- /testdata/mpc_key2.evidence: -------------------------------------------------------------------------------- 1 | 00150bee7f0b1170f81f5174e7b2c9f72d10da6ea78de03ae02d9019865db375d53de484a1d440bfdb2054d485888bd5a9e411991e984907f87cd19206ac561b682c011164524c9895791a8883a2e50a895211a7591504b6ca91b7686610f313cc03924896b798d519e0469a5dc432a366a4e62ba7d31d6c8b794773eedcaf91cf6b25d6 -------------------------------------------------------------------------------- /testdata/mpc_key2.pub: -------------------------------------------------------------------------------- 1 | 30819b301006072a8648ce3d020106052b81040023038186000401ee724e89353bfb3295b20807895b9482127bc32b6312bf81732b7978ba5810087e88c78c5f973f47446c7bb953e1c884cddb721d02b22edb2a8337b77c7811b68f0091caf56b1597641d064321b6fd974a702e719b4dce9ed7d9b64b5bc6378bca2754622a2b14b8519d57b00780b156186a4442e2b073a5532b1dc42eb0e864490650 2 | -------------------------------------------------------------------------------- /testdata/mpc_key3.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/zeth/4e0c07528db93fbcf0baecfac4905a3108a0496a/testdata/mpc_key3.bin -------------------------------------------------------------------------------- /testdata/mpc_key3.evidence: -------------------------------------------------------------------------------- 1 | 00f1e8edf366b47dca3edcdae3f08cdcfbeec107960eec3ae1c8cc996cdc47d8a214562f9b8ff7a377ccd6cc9b2240af61f8fc0ba14f967859eff28e1cf74a4201ac00d342be7d8e0cf512a840bbf1d6cdbb29965b23e7d31304ea20db9441cd6173d8a5199939e7e5406a1af47078d871c5958a522c6b46c2d8a442d17e93d7c6d1e0bd -------------------------------------------------------------------------------- /testdata/mpc_key3.pub: -------------------------------------------------------------------------------- 1 | 30819b301006072a8648ce3d020106052b81040023038186000401737f916582dd8b636eb4d91c26833dfffef49f139fa5fc352c9296100211509e00cf50c5e781d15331db6e1c9d8f5a59e4649c715a555f3c8174f182a13fecb1ff008958b112d318f389ae2c8e434d2c49578eb705ab505b1806d7929c14acf0f5d13dd60b277521ab637e4ed8540761dd275342d9d1fb4222679286f7769afc28f876 2 | -------------------------------------------------------------------------------- /testdata/mpc_key4.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/zeth/4e0c07528db93fbcf0baecfac4905a3108a0496a/testdata/mpc_key4.bin -------------------------------------------------------------------------------- /testdata/mpc_key4.evidence: -------------------------------------------------------------------------------- 1 | 0156297506fcc4535682943562e19e702e3ae94382057847dc469cb337a4cc6f4b5c4dbe0da066b29eb716a2c14690db9b38f44a06623cb465cf0461ddab201cd22c002bd6205d415bf66b7cf8e16e06736fca2e029edd6b0eb1ec741ae299df02cd27030986b6bbfcb0677003226b1fabb83af29d37765fa514118b0a9422ecaf156c85 -------------------------------------------------------------------------------- /testdata/mpc_key4.pub: -------------------------------------------------------------------------------- 1 | 30819b301006072a8648ce3d020106052b810400230381860004019396c56f94897f5b9e1f2c11ec436c3450ce5a2f9d3eea526ae41d17478ea7f2a839069225fa8c39d9b8844b9245df47863e289b6cffd24bf35371c1b756bc28cd00258cd5d1775f8e9b54ef530a6c8badffba6765aba84c7a47f1a19fce91daea6aa2adce3369e9068fd73b25a4cdebfb77a2db3fbb3ae0a266cba861b82ba91a0118 2 | -------------------------------------------------------------------------------- /testdata/mpc_phase1_server_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "server": { 3 | "_contributors_file_description": "Relative path of contributors file", 4 | "contributors_file": "../testdata/mpc_contributors.json", 5 | 6 | "_start_time_utc_description": "Time (in UTC) that first contribution is allowed", 7 | "_start_time_utc_example": "2019-11-05 13:33:13", 8 | "start_time_utc": "TIME", 9 | 10 | "_contribution_interval_description": "Interval time in seconds", 11 | "contribution_interval": "60.0", 12 | 13 | "_email_description": "Optional email server and credentials", 14 | "_email_server_example": "smtp.myorg.com:465", 15 | "_email_address_example": "mpc.coordinator@myorg.com", 16 | "_email_password_file_example": "email_pwd", 17 | 18 | "_tls_description": "Key and certificate for the server.", 19 | "tls_key": "key.pem", 20 | "tls_certificate": "cert.pem", 21 | 22 | "_port_description": "Port to listen on", 23 | "port": PORT 24 | }, 25 | 26 | "_pot_path_description": "Path (relative) to the powersoftau binaries", 27 | "pot_path": "../../powersoftau/target/release", 28 | 29 | "_num_powers_description": "Determines max degree of QAP (Power of 2)", 30 | "num_powers": QAP_DEGREE 31 | } 32 | -------------------------------------------------------------------------------- /testdata/mpc_phase2_server_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "server": { 3 | "help1": "This section is common over phase1 and phase2. See ", 4 | "help2": "mpc_phase1_server.config.json for details.", 5 | 6 | "contributors_file": "../testdata/mpc_contributors.json", 7 | "start_time_utc": "TIME", 8 | "contribution_interval": "60.0", 9 | "_email_server_example": "smtp.myorg.com:465", 10 | "_email_address_example": "mpc.coordinator@myorg.com", 11 | "_email_password_file_example": "email_pwd", 12 | "tls_key": "key.pem", 13 | "tls_certificate": "cert.pem", 14 | "port": PORT 15 | }, 16 | 17 | "_mpc_tool_description": "Path (relative) to the phase2 mpc tool", 18 | "mpc_tool": "../build/mpc_tools/mpc_phase2/mpc-test-phase2" 19 | } 20 | -------------------------------------------------------------------------------- /testdata/powersoftau_challenge.4.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/zeth/4e0c07528db93fbcf0baecfac4905a3108a0496a/testdata/powersoftau_challenge.4.bin -------------------------------------------------------------------------------- /testdata/test_mpc_registration.csv: -------------------------------------------------------------------------------- 1 | "Timestamp","Email","Contributor Verification Key","Key Evidence" 2 | "2019-10-25 09:51:39","c1@mpc.clearmatics.com","30819b301006072a8648ce3d020106052b81040023038186000401ca3dde04a97e63757a9d67ee6e4d957f1da3b19b8e3b85029664471e969439ee26f375a523aef3d3a27b78060ff1ac781c306b73979613a9cb18d9ac549cda1ee601b243420de194977e655827f053c531b9d2639cf714b0741ae63647fdffc40a386a579b24145c32a76c842e4ff3107cdeda73608c0a15d587a4bd5f1a5bc3b2eed4","015bbb49bf4ca076c6cf6668d710bc415483dd2f78f3600e1a9052ed6712e8ca0b4468ce65d59e8eb9c0d24bcc28ea58fe7fa899f9703cbd2db89f3cf70822684cc300fc8cc01eea1c8652fafe158fb378ed9820515ef856503a347db6579f945cf4e00f6c2850d5c544db3803561faa2a85d300a7b78d5c95f1f0f9c333aaf4fb8671d8" 3 | "2019-10-25 09:52:29","c2@mpc.clearmatics.com","30819b301006072a8648ce3d020106052b81040023038186000401ee724e89353bfb3295b20807895b9482127bc32b6312bf81732b7978ba5810087e88c78c5f973f47446c7bb953e1c884cddb721d02b22edb2a8337b77c7811b68f0091caf56b1597641d064321b6fd974a702e719b4dce9ed7d9b64b5bc6378bca2754622a2b14b8519d57b00780b156186a4442e2b073a5532b1dc42eb0e864490650","00150bee7f0b1170f81f5174e7b2c9f72d10da6ea78de03ae02d9019865db375d53de484a1d440bfdb2054d485888bd5a9e411991e984907f87cd19206ac561b682c011164524c9895791a8883a2e50a895211a7591504b6ca91b7686610f313cc03924896b798d519e0469a5dc432a366a4e62ba7d31d6c8b794773eedcaf91cf6b25d6" 4 | "2019-10-25 09:53:12","c3@mpc.clearmatics.com","30819b301006072a8648ce3d020106052b81040023038186000401737f916582dd8b636eb4d91c26833dfffef49f139fa5fc352c9296100211509e00cf50c5e781d15331db6e1c9d8f5a59e4649c715a555f3c8174f182a13fecb1ff008958b112d318f389ae2c8e434d2c49578eb705ab505b1806d7929c14acf0f5d13dd60b277521ab637e4ed8540761dd275342d9d1fb4222679286f7769afc28f876","00f1e8edf366b47dca3edcdae3f08cdcfbeec107960eec3ae1c8cc996cdc47d8a214562f9b8ff7a377ccd6cc9b2240af61f8fc0ba14f967859eff28e1cf74a4201ac00d342be7d8e0cf512a840bbf1d6cdbb29965b23e7d31304ea20db9441cd6173d8a5199939e7e5406a1af47078d871c5958a522c6b46c2d8a442d17e93d7c6d1e0bd" -------------------------------------------------------------------------------- /testdata/test_mpc_registration_invalid.csv: -------------------------------------------------------------------------------- 1 | "Timestamp","Email","Contributor Verification Key","Key Evidence" 2 | "2019-10-25 09:51:39","c1@mpc.clearmatics.com","30819b301006072a8648ce3d020106052b81040023038186000401ca3dde04a97e63757a9d67ee6e4d957f1da3b19b8e3b85029664471e969439ee26f375a523aef3d3a27b78060ff1ac781c306b73979613a9cb18d9ac549cda1ee601b243420de194977e655827f053c531b9d2639cf714b0741ae63647fdffc40a386a579b24145c32a76c842e4ff3107cdeda73608c0a15d587a4bd5f1a5bc3b2eed4","015bbb49bf4ca076c6cf6668d710bc415483dd2f78f3600e1a9052ed6712e8ca0b4468ce65d59e8eb9c0d24bcc28ea58fe7fa899f9703cbd2db89f3cf70822684cc300fc8cc01eea1c8652fafe158fb378ed9820515ef856503a347db6579f945cf4e00f6c2850d5c544db3803561faa2a85d300a7b78d5c95f1f0f9c333aaf4fb8671d8" 3 | "2019-10-25 09:52:29","c2@mpc.clearmatics.com","30819b301006072a8648ce3d020106052b81040023038186000401ee724e89353bfb3295b20807895b9482127bc32b6312bf81732b7978ba5810087e88c78c5f973f47446c7bb953e1c884cddb721d02b22edb2a8337b77c7811b68f0091caf56b1597641d064321b6fd974a702e719b4dce9ed7d9b64b5bc6378bca2754622a2b14b8519d57b00780b156186a4442e2b073a5532b1dc42eb0e864490650","015bbb49bf4ca076c6cf6668d710bc415483dd2f78f3600e1a9052ed6712e8ca0b4468ce65d59e8eb9c0d24bcc28ea58fe7fa899f9703cbd2db89f3cf70822684cc300fc8cc01eea1c8652fafe158fb378ed9820515ef856503a347db6579f945cf4e00f6c2850d5c544db3803561faa2a85d300a7b78d5c95f1f0f9c333aaf4fb8671d8" 4 | "2019-10-25 09:53:12","c3@mpc.clearmatics.com","30819b301006072a8648ce3d020106052b81040023038186000401737f916582dd8b636eb4d91c26833dfffef49f139fa5fc352c9296100211509e00cf50c5e781d15331db6e1c9d8f5a59e4649c715a555f3c8174f182a13fecb1ff008958b112d318f389ae2c8e434d2c49578eb705ab505b1806d7929c14acf0f5d13dd60b277521ab637e4ed8540761dd275342d9d1fb4222679286f7769afc28f876","00f1e8edf366b47dca3edcdae3f08cdcfbeec107960eec3ae1c8cc996cdc47d8a214562f9b8ff7a377ccd6cc9b2240af61f8fc0ba14f967859eff28e1cf74a4201ac00d342be7d8e0cf512a840bbf1d6cdbb29965b23e7d31304ea20db9441cd6173d8a5199939e7e5406a1af47078d871c5958a522c6b46c2d8a442d17e93d7c6d1e0bd" -------------------------------------------------------------------------------- /zeth_contracts/.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solhint:recommended", 3 | "plugins": [], 4 | "rules": { 5 | "var-name-mixedcase": "off", 6 | "func-name-mixedcase": "off", 7 | "contract-name-camelcase": "off", 8 | "no-empty-blocks": "off", 9 | "compiler-version": "off", 10 | "reason-string": "off", 11 | "avoid-suicide": "error", 12 | "no-inline-assembly": "off", 13 | "avoid-sha3": "warn", 14 | "func-visibility": ["error", {"ignoreConstructors": true}], 15 | "max-line-length": ["error", 79] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /zeth_contracts/.solhintignore: -------------------------------------------------------------------------------- 1 | ERC20Mintable.sol 2 | node_modules/ 3 | contracts/Migrations.sol 4 | -------------------------------------------------------------------------------- /zeth_contracts/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | contract Migrations { 8 | address public owner; 9 | uint public last_completed_migration; 10 | 11 | constructor() { 12 | owner = msg.sender; 13 | } 14 | 15 | modifier restricted() { 16 | if (msg.sender == owner) _; 17 | } 18 | 19 | function setCompleted(uint completed) public restricted { 20 | last_completed_migration = completed; 21 | } 22 | 23 | function upgrade(address new_address) public restricted { 24 | Migrations upgraded = Migrations(new_address); 25 | upgraded.setCompleted(last_completed_migration); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /zeth_contracts/contracts/MixerGroth16AltBN128.sol: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./AbstractMixerAltBN128.sol"; 8 | import "./LibGroth16AltBN128.sol"; 9 | 10 | /// Instance of AbstractMixerAltBN128 implementing the Groth16 verifier for the 11 | /// alt-bn128 pairing. 12 | contract MixerGroth16AltBN128 is AbstractMixerAltBN128 13 | { 14 | constructor( 15 | uint256 mkDepth, 16 | address token, 17 | uint256[] memory vk, 18 | address permittedDispatcher, 19 | uint256[2] memory vkHash 20 | ) 21 | AbstractMixerAltBN128(mkDepth, token, vk, permittedDispatcher, vkHash) 22 | { 23 | } 24 | 25 | function _verifyZkProof( 26 | uint256[] memory proof, 27 | uint256 publicInputsHash 28 | ) 29 | internal 30 | override 31 | returns (bool) 32 | { 33 | // Convert the single primary input to a dynamic array 34 | // expected by the verifier. 35 | uint256[] memory inputValues = new uint256[](1); 36 | inputValues[0] = publicInputsHash; 37 | return LibGroth16AltBN128._verify(_vk, proof, inputValues); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /zeth_contracts/contracts/MixerGroth16BLS12_377.sol: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./LibGroth16BLS12_377.sol"; 8 | import "./AbstractMixerBLS12_377.sol"; 9 | 10 | // Instance of AbstractMixerBLS12_377 implementing the Groth16 verifier for the 11 | // bls12-377 pairing. 12 | contract MixerGroth16BLS12_377 is AbstractMixerBLS12_377 13 | { 14 | constructor( 15 | uint256 mkDepth, 16 | address token, 17 | uint256[] memory vk, 18 | address permittedDispatcher, 19 | uint256[2] memory vkHash 20 | ) 21 | AbstractMixerBLS12_377(mkDepth, token, vk, permittedDispatcher, vkHash) 22 | { 23 | } 24 | 25 | function _verifyZkProof( 26 | uint256[] memory proof, 27 | uint256 publicInputsHash 28 | ) 29 | internal 30 | override 31 | returns (bool) 32 | { 33 | // Convert the single primary input to a dynamic array 34 | // expected by the verifier. 35 | uint256[] memory input_values = new uint256[](1); 36 | input_values[0] = publicInputsHash; 37 | return LibGroth16BLS12_377._verify(_vk, proof, input_values); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /zeth_contracts/contracts/README.md: -------------------------------------------------------------------------------- 1 | # Zeth smart contracts 2 | 3 | The Byzantium hard fork of Ethereum has introduced [precompiled contracts for elliptic curves operations (on bn256)](https://github.com/ethereum/go-ethereum/blob/v1.7.1/core/vm/contracts.go#L57-L59). When configured with `ALT_BN128`, Zeth will use these precompiled contracts (in the client) as part of the transition to new blockchain states. 4 | 5 | However, when using other curves such as `BLS12_377` or `BW6_761` for instance (which, at the time of writing, are not supported by the [go-ethereum client](https://github.com/ethereum/go-ethereum/tree/v1.9.25)), one needs to make sure that the underlying client will support precompiled for arithmetic over these curves. 6 | Such extension to the execution environment is supported in [our fork of ganache-cli](https://github.com/clearmatics/ganache-cli/tree/v6.10.1-clearmatics) for testing purposes (check [here](https://github.com/clearmatics/ethereumjs-vm/blob/v4.1.3-clearmatics/lib/evm/precompiles/index.ts#L30-L36) for the addresses of these instructions). Some of the Zeth contracts use these additional precompiled contracts to specify state transitions. 7 | -------------------------------------------------------------------------------- /zeth_contracts/contracts/TestBaseMixerAltBN128.sol: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./AbstractMixerAltBN128.sol"; 8 | 9 | 10 | // Implementation of AbstractMixerAltBN128 contract, to allow testing 11 | // specific methods. 12 | contract TestAbstractMixerAltBN128 is AbstractMixerAltBN128 13 | { 14 | constructor( 15 | uint256 mkDepth, 16 | address permittedDispatcher, 17 | uint256[2] memory vkHash 18 | ) 19 | AbstractMixerAltBN128( 20 | mkDepth, 21 | address(0), 22 | new uint256[](0), 23 | permittedDispatcher, 24 | vkHash) 25 | { 26 | } 27 | 28 | function testHashPublicProofData( 29 | uint256[_NUM_INPUTS] memory publicData 30 | ) 31 | external 32 | returns (uint256) 33 | { 34 | return _hashPublicProofData(publicData); 35 | } 36 | 37 | function testAssemblePublicValues(uint256 residualBits) 38 | external 39 | pure 40 | returns (uint256 vpub_in, uint256 vpub_out) 41 | { 42 | return _assemblePublicValues(residualBits); 43 | } 44 | 45 | function testAssembleHsig( 46 | uint256[_NUM_INPUTS] memory primaryInputs 47 | ) 48 | external 49 | pure 50 | returns(bytes32 hsig) 51 | { 52 | return _assembleHsig(primaryInputs); 53 | } 54 | 55 | function testAssembleNullifier( 56 | uint256 index, 57 | uint256[_NUM_INPUTS] memory primaryInputs 58 | ) 59 | external 60 | pure 61 | returns(bytes32 nf) 62 | { 63 | return _assembleNullifier(index, primaryInputs); 64 | } 65 | 66 | // Dummy implementation of abstract function 67 | function _verifyZkProof( 68 | uint256[] memory /* proof */, 69 | uint256 /* publicInputsHash */ 70 | ) 71 | internal 72 | pure 73 | override 74 | returns (bool) 75 | { 76 | return false; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /zeth_contracts/contracts/TestGroth16BLS12_377.sol: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./LibGroth16BLS12_377.sol"; 8 | 9 | contract TestGroth16BLS12_377 10 | { 11 | uint256[] private _vk; 12 | 13 | function testVerify( 14 | uint256[] memory vk, 15 | uint256[] memory proof, 16 | uint256[] memory inputs 17 | ) 18 | external 19 | returns(bool) 20 | { 21 | _vk = vk; 22 | return LibGroth16BLS12_377._verify(_vk, proof, inputs); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /zeth_contracts/contracts/TestMerkleTreeMiMCAltBN128.sol: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./AbstractMerkleTree.sol"; 8 | import "./LibMiMC.sol"; 9 | 10 | /// Implementation of AbstractMerkleTree for testing. 11 | contract TestMerkleTreeMiMCAltBN128 is AbstractMerkleTree 12 | { 13 | constructor(uint treeDepth) AbstractMerkleTree(treeDepth) 14 | { 15 | } 16 | 17 | /// Add some leaves, computing the root, then adding more leaves and 18 | /// recomputing the root. Returns the full set of nodes at the end. This 19 | /// allows testing of the update code paths for any starting / finishing 20 | /// state combination. 21 | function testAddLeaves( 22 | bytes32[] memory first, 23 | bytes32[] memory second 24 | ) 25 | external 26 | returns (bytes32) 27 | { 28 | for (uint i = 0 ; i < first.length ; ++i) { 29 | insert(first[i]); 30 | } 31 | bytes32 root = _recomputeRoot(first.length); 32 | 33 | for (uint i = 0 ; i < second.length ; ++i) { 34 | insert(second[i]); 35 | } 36 | root = _recomputeRoot(second.length); 37 | return root; 38 | } 39 | 40 | function _hash(bytes32 left, bytes32 right) 41 | internal 42 | pure 43 | override 44 | returns(bytes32) 45 | { 46 | return LibMiMC._hashAltBN128(left, right); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /zeth_contracts/contracts/TestMiMC.sol: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | import "./LibMiMC.sol"; 8 | 9 | /// Contract to test the MiMC libraries 10 | contract TestMiMC 11 | { 12 | /// Test function for LibMiMC._hashAltBN128 13 | function testMimcAltBN128(bytes32 x, bytes32 y) 14 | external 15 | pure 16 | returns (bytes32) { 17 | return LibMiMC._hashAltBN128(x, y); 18 | } 19 | 20 | /// Test function for LibMiMC._hashBLS12_377 21 | function testMimcBLS12_377(bytes32 x, bytes32 y) 22 | external 23 | pure 24 | returns (bytes32) { 25 | return LibMiMC._hashBLS12_377(x, y); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /zeth_contracts/contracts/Tokens.sol: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | pragma solidity ^0.8.0; 6 | 7 | /// Declare the IERC20 interface in order to handle ERC20 tokens transfers to 8 | /// and from the Mixer. Note that we only declare the functions we are 9 | /// interested in, namely, transferFrom() (used to do a Deposit), and 10 | /// transfer() (used to do a withdrawal) 11 | interface IERC20 12 | { 13 | function transferFrom(address from, address to, uint256 value) 14 | external 15 | returns (bool); 16 | 17 | function transfer(address to, uint256 value) 18 | external 19 | returns (bool); 20 | 21 | event Transfer(address indexed from, address indexed to, uint256 value); 22 | event Approval( 23 | address indexed owner, 24 | address indexed spender, 25 | uint256 value); 26 | } 27 | 28 | /// ERC223 token compatible contract 29 | contract ERC223ReceivingContract 30 | { 31 | // See: 32 | // solhint-disable-next-line max-line-length 33 | // https://github.com/Dexaran/ERC223-token-standard/blob/Recommended/Receiver_Interface.sol 34 | struct Token { 35 | address sender; 36 | uint256 value; 37 | bytes data; 38 | bytes4 sig; 39 | } 40 | 41 | function tokenFallback( 42 | address from, 43 | uint256 value, 44 | bytes memory data 45 | ) 46 | public 47 | pure 48 | { 49 | Token memory tkn; 50 | tkn.sender = from; 51 | tkn.value = value; 52 | tkn.data = data; 53 | 54 | // See: 55 | // solhint-disable-next-line max-line-length 56 | // https://solidity.readthedocs.io/en/v0.5.5/types.html#conversions-between-elementary-types 57 | uint32 u = 58 | uint32(bytes4(data[0])) + 59 | uint32(bytes4(data[1]) >> 8) + 60 | uint32(bytes4(data[2]) >> 16) + 61 | uint32(bytes4(data[3]) >> 24); 62 | tkn.sig = bytes4(u); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /zeth_contracts/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /zeth_contracts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zeth-contracts", 3 | "version": "1.0.0", 4 | "description": "zerocash on Ethereum", 5 | "main": "truffle.js", 6 | "scripts": { 7 | "compile": "truffle compile", 8 | "deploy": "truffle deploy", 9 | "test": "truffle test", 10 | "debug": "truffle debug", 11 | "check": "node_modules/solhint/solhint.js --max-warnings 0 'contracts/**/*.sol'" 12 | }, 13 | "author": "Clearmatics Technologies LTD: Cryptography R&D Department", 14 | "license": "LGPL-3.0+", 15 | "dependencies": { 16 | "solhint": "^3.3.2" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /zeth_contracts/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8545, 6 | gas: 0x3FFFFFFFFFFFF, 7 | gasprice: 0x1, 8 | network_id: "*" 9 | }, 10 | coverage: { 11 | host: "localhost", 12 | port: 8555, 13 | gas: 0xFFFFFFF, 14 | gasprice: 0x1, 15 | network_id: "*" // Match any network id 16 | }, 17 | autonityhelloworld: { 18 | host: "localhost", 19 | port: 8541, 20 | network_id: "*", 21 | }, 22 | }, 23 | mocha: { 24 | useColors: true, 25 | enableTimeouts: false 26 | }, 27 | compilers: { 28 | solc: { 29 | version: "^0.8.0", 30 | settings: { 31 | optimizer: { 32 | enabled: true, 33 | runs: 200 34 | } 35 | } 36 | } 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /zeth_tool/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | find_package(Boost REQUIRED COMPONENTS system filesystem program_options) 3 | 4 | file(GLOB_RECURSE ZETH_TOOL_SOURCE **.?pp **.tcc) 5 | add_executable(zeth-tool ${ZETH_TOOL_SOURCE}) 6 | target_include_directories(zeth-tool PRIVATE SYSTEM ${Boost_INCLUDE_DIR}) 7 | target_link_libraries( 8 | zeth-tool 9 | 10 | tool 11 | zeth 12 | ${Boost_SYSTEM_LIBRARY} 13 | ${Boost_FILESYSTEM_LIBRARY} 14 | ${Boost_PROGRAM_OPTIONS_LIBRARY} 15 | ) 16 | -------------------------------------------------------------------------------- /zeth_tool/README.md: -------------------------------------------------------------------------------- 1 | # zeth-tool command 2 | 3 | Primarily designed for performing fine-grained operations, either outside of the scope of the zeth client, or as part of larger high-level operations. 4 | 5 | Examples include, generation of arbitrary proofs (given a proving key and full assignment), verification of arbitrary proofs (given a proof, verification key and primary input), re-serialization of objects (e.g. conversion to/from binary, JSON etc). 6 | 7 | Since the tool is more development / administration focused, not all functionality is necessarily complete, and may be extended as required in the future (possibly including operations that are specific to the zeth circuit). 8 | 9 | To build, run `make zeth-tool` in the `build` directory (see the [main README](../README.md)) to build to executable at `build/zeth_tool/zeth-tool`. Run `zeth-tool help` (with the appropriate path to the executable) to see the up-to-date list of supported commands. 10 | -------------------------------------------------------------------------------- /zeth_tool/dump_proof_cmd.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_TOOL_DUMP_PROOF_CMD_HPP__ 6 | #define __ZETH_TOOL_DUMP_PROOF_CMD_HPP__ 7 | 8 | #include "zeth_tool/tool_common.hpp" 9 | 10 | namespace zethtool 11 | { 12 | 13 | extern zeth_subcommand *dump_proof_cmd; 14 | 15 | } // namespace zethtool 16 | 17 | #endif // __ZETH_TOOL_DUMP_PROOF_CMD_HPP__ 18 | -------------------------------------------------------------------------------- /zeth_tool/joinsplit_circuit_cmd.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_TOOL_JOINSPLIT_CIRCUIT_CMD_HPP__ 6 | #define __ZETH_TOOL_JOINSPLIT_CIRCUIT_CMD_HPP__ 7 | 8 | #include "zeth_tool/tool_common.hpp" 9 | 10 | namespace zethtool 11 | { 12 | 13 | extern zeth_subcommand *joinsplit_circuit_cmd; 14 | 15 | } // namespace zethtool 16 | 17 | #endif // __ZETH_TOOL_JOINSPLIT_CIRCUIT_CMD_HPP__ 18 | -------------------------------------------------------------------------------- /zeth_tool/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #include "libtool/run.hpp" 6 | #include "zeth_tool/dump_proof_cmd.hpp" 7 | #include "zeth_tool/joinsplit_circuit_cmd.hpp" 8 | #include "zeth_tool/prove_cmd.hpp" 9 | #include "zeth_tool/split_keypair_cmd.hpp" 10 | #include "zeth_tool/tool_common.hpp" 11 | #include "zeth_tool/verify_cmd.hpp" 12 | 13 | using namespace zethtool; 14 | 15 | class zeth_command : public libtool::command 16 | { 17 | public: 18 | void initialize_global_options( 19 | boost::program_options::options_description &global, 20 | boost::program_options::options_description &all_options) override 21 | { 22 | global.add_options()("verbose,v", "Verbose output"); 23 | all_options.add(global); 24 | } 25 | 26 | /// Parse the variables map to update the GlobalOptionsT object. 27 | void parse_global_options( 28 | global_options &out_options, 29 | const boost::program_options::variables_map &vm) override 30 | { 31 | out_options = (bool)vm.count("verbose"); 32 | } 33 | }; 34 | 35 | int main(int argc, char **argv) 36 | { 37 | // Create command structures 38 | std::map commands{ 39 | {"verify", verify_cmd}, 40 | {"prove", prove_cmd}, 41 | {"dump-proof", dump_proof_cmd}, 42 | {"joinsplit-circuit", joinsplit_circuit_cmd}, 43 | {"split-keypair", split_keypair_cmd}, 44 | }; 45 | 46 | zeth_command cmd; 47 | bool verbose = false; 48 | 49 | // Execute tool_main 50 | return libtool::run_command(cmd, verbose, commands, argc, argv); 51 | } 52 | -------------------------------------------------------------------------------- /zeth_tool/prove_cmd.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_TOOL_PROVE_CMD_HPP__ 6 | #define __ZETH_TOOL_PROVE_CMD_HPP__ 7 | 8 | #include "zeth_tool/tool_common.hpp" 9 | 10 | namespace zethtool 11 | { 12 | 13 | extern zeth_subcommand *prove_cmd; 14 | 15 | } // namespace zethtool 16 | 17 | #endif // __ZETH_TOOL_PROVE_CMD_HPP__ 18 | -------------------------------------------------------------------------------- /zeth_tool/split_keypair_cmd.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_TOOL_SPLIT_KEYPAIR_CMD_HPP__ 6 | #define __ZETH_TOOL_SPLIT_KEYPAIR_CMD_HPP__ 7 | 8 | #include "zeth_tool/tool_common.hpp" 9 | 10 | namespace zethtool 11 | { 12 | 13 | extern zeth_subcommand *split_keypair_cmd; 14 | 15 | } // namespace zethtool 16 | 17 | #endif // __ZETH_TOOL_SPLIT_KEYPAIR_CMD_HPP__ 18 | -------------------------------------------------------------------------------- /zeth_tool/verify_cmd.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2022 Clearmatics Technologies Ltd 2 | // 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | #ifndef __ZETH_TOOL_VERIFY_CMD_HPP__ 6 | #define __ZETH_TOOL_VERIFY_CMD_HPP__ 7 | 8 | #include "zeth_tool/tool_common.hpp" 9 | 10 | namespace zethtool 11 | { 12 | 13 | extern zeth_subcommand *verify_cmd; 14 | 15 | } // namespace zethtool 16 | 17 | #endif // __ZETH_TOOL_VERIFY_CMD_HPP__ 18 | --------------------------------------------------------------------------------