diff --git a/.github/workflows/dev-docs.yml b/.github/workflows/dev-docs.yml new file mode 100644 index 000000000..fc73818dd --- /dev/null +++ b/.github/workflows/dev-docs.yml @@ -0,0 +1,56 @@ +name: zeth-ci-dev-docs + +on: + push: + branches: [ develop ] + +jobs: + build-grpc: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - name: Cache grpc + uses: actions/cache@v2 + with: + key: grpc-1.31.x-${{ runner.os }} + path: depends/grpc + - name: Build grpc + run: if ! [ -d depends/grpc ] ; then scripts/install-grpc /usr v1.31.x ; fi + + build-documentation: + runs-on: ubuntu-20.04 + needs: build-grpc + steps: + - name: Checkout repository and install submodules + uses: actions/checkout@v2 + with: + submodules: recursive + - name: Cache grpc + uses: actions/cache@v2 + with: + key: grpc-1.31.x-${{ runner.os }} + path: depends/grpc + - name: Install dependencies + run: | + sudo apt update -y + source scripts/build_utils.sh + init_platform + cpp_build_setup + INSTALL_ONLY=1 scripts/install-grpc /usr v1.31.x + sudo apt install -y doxygen graphviz + - name: Generatate documentation + run: | + mkdir -p build + pushd build + cmake -DGEN_DOC=ON .. + make build_docs + popd + - name: GH Pages Deployment + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./build/docs/html/ + enable_jekyll: false + allow_empty_commit: false + force_orphan: true + publish_branch: doxy-gh-pages diff --git a/.github/workflows/onpullrequest-build-ubuntu.yml b/.github/workflows/onpullrequest-build-ubuntu.yml index 025532ce8..e1b569204 100644 --- a/.github/workflows/onpullrequest-build-ubuntu.yml +++ b/.github/workflows/onpullrequest-build-ubuntu.yml @@ -22,7 +22,7 @@ jobs: key: grpc-1.31.x-${{ runner.os }} path: depends/grpc - name: Build grpc - run: if ! [ -d depends/grpc ] ; then scripts/install_grpc /usr v1.31.x depends/grpc ; fi + run: if ! [ -d depends/grpc ] ; then scripts/install-grpc /usr v1.31.x ; fi # Extract the commits of submodules for use by cache steps onpr-submodules: @@ -45,7 +45,7 @@ jobs: matrix: curve: [ BLS12_377, ALT_BN128 ] steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 with: submodules: recursive - uses: actions/setup-node@v1 @@ -77,7 +77,7 @@ jobs: key: prover-tests-npm-${{ hashFiles('**/package-lock.json') }}-${{ runner.os }} - name: Install dependencies run: | - scripts/install_grpc /usr v1.31.x depends/grpc + INSTALL_ONLY=1 scripts/install-grpc /usr v1.31.x sudo apt install -y ccache - name: Execute run: CI_CONFIG=Release CI_CURVE=${{ matrix.curve }} CI_PROVER_TESTS=1 scripts/ci build @@ -90,7 +90,7 @@ jobs: matrix: curve: [ BLS12_377, ALT_BN128 ] steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 with: submodules: recursive - uses: actions/setup-node@v1 @@ -124,7 +124,7 @@ jobs: key: integration-tests-npm-${{ hashFiles('**/package-lock.json') }}-${{ runner.os }} - name: Install dependencies run: | - scripts/install_grpc /usr v1.31.x depends/grpc + INSTALL_ONLY=1 scripts/install-grpc /usr v1.31.x sudo apt install -y ccache - name: Execute run: CI_CONFIG=Release CI_CURVE=${{ matrix.curve }} CI_FULL_TESTS=1 CI_INTEGRATION_TESTS=1 scripts/ci build diff --git a/.github/workflows/onpush-build-ubuntu.yml b/.github/workflows/onpush-build-ubuntu.yml index 1c711ff8a..f6ad053cc 100644 --- a/.github/workflows/onpush-build-ubuntu.yml +++ b/.github/workflows/onpush-build-ubuntu.yml @@ -22,7 +22,7 @@ jobs: key: grpc-1.31.x-${{ runner.os }} path: depends/grpc - name: Build grpc - run: if ! [ -d depends/grpc ] ; then scripts/install_grpc /usr v1.31.x depends/grpc ; fi + run: if ! [ -d depends/grpc ] ; then scripts/install-grpc /usr v1.31.x ; fi build-linux: runs-on: ubuntu-20.04 @@ -46,7 +46,7 @@ jobs: key: build-linux-pip-${{ hashFiles('**/setup.py') }}-${{ runner.os }} - name: Install dependencies run: | - scripts/install_grpc /usr v1.31.x depends/grpc + INSTALL_ONLY=1 scripts/install-grpc /usr v1.31.x sudo apt install -y ccache - name: Execute run: CI_CHECK_FORMAT=1 CI_MPC_TESTS=1 CI_CONFIG=${{ matrix.config }} scripts/ci build @@ -65,7 +65,7 @@ jobs: path: depends/grpc - name: Install dependencies run: | - scripts/install_grpc /usr v1.31.x depends/grpc + INSTALL_ONLY=1 scripts/install-grpc /usr v1.31.x sudo apt install -y ccache - name: Execute run: CI_CONFIG=Release CI_ZKSNARK=PGHR13 scripts/ci build @@ -74,7 +74,7 @@ jobs: runs-on: ubuntu-20.04 needs: build-grpc steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 with: submodules: recursive - name: Cache grpc @@ -84,7 +84,7 @@ jobs: path: depends/grpc - name: Install dependencies run: | - scripts/install_grpc /usr v1.31.x depends/grpc + INSTALL_ONLY=1 scripts/install-grpc /usr v1.31.x sudo apt install -y ccache - name: Execute run: CI_CONFIG=Release CI_CURVE=BLS12_377 scripts/ci build diff --git a/.github/workflows/onpush-checks.yml b/.github/workflows/onpush-checks.yml index d0fb3b386..cd08a1246 100644 --- a/.github/workflows/onpush-checks.yml +++ b/.github/workflows/onpush-checks.yml @@ -35,7 +35,7 @@ jobs: check-client: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 with: submodules: recursive - name: Cache pip @@ -49,7 +49,7 @@ jobs: check-cpp-linux: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 with: submodules: recursive - name: Execute diff --git a/CMakeLists.txt b/CMakeLists.txt index 146c72ee7..7604824a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.13) # Change the compiler BEFORE the first `project()` command to avoid an infinite loop. # See: https://public.kitware.com/pipermail/cmake/2009-November/033133.html @@ -16,7 +16,7 @@ project(zeth CXX) # Versionning of the project set(ZETH_VERSION_MAJOR 0) -set(ZETH_VERSION_MINOR 7) +set(ZETH_VERSION_MINOR 8) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -311,11 +311,12 @@ endif() # Add all local subdirecetories add_subdirectory(libzeth) +add_subdirectory(libtool) # If zeth is being used as a dependency, skip the tools build if ("${IS_ZETH_PARENT}") add_subdirectory(prover_server) - add_subdirectory(verifier) + add_subdirectory(zeth_tool) # For now the MPC for Groth16 only is tailored to the alt_bn128 pairing group if((${ZETH_SNARK} STREQUAL "GROTH16") AND (${MPC})) add_subdirectory(mpc_tools) diff --git a/CODING_STANDARDS.md b/CODING_STANDARDS.md index 5f3255a7a..ea175bca4 100644 --- a/CODING_STANDARDS.md +++ b/CODING_STANDARDS.md @@ -8,6 +8,31 @@ New code should follow these rules, and old code should be changed over time to - Each file should have a well-defined purpose and be concerned with a single narrow concept. - Add unit tests for new code. As far as possible, one test per source file or logical group of files. - Names should be as clear and concise as possible, avoiding opaque abbreviations. +- In conditions, the tested variable must appear on the left of the operator. This is to stay consistent with English, which writes/reads from left to right. + ``` + // GOOD: + // The test below reads "If age is above 18" + // (the test is on the value of `age` here, so it appears first) + if (age >= 18) { + drive(); + } + ``` + instead of: + ``` + // BAD: + // The test below reads "If 18 is below age" + // (the test is on the value `age` yet it appears last, which doesn't read naturally) + if (18 <= age) { + drive(); + } + ``` +- Executables (bash scripts, CLIs etc.) and their flags are named using `kebab-case` (e.g. `foo-bar --baz`). + +## Bash + +Only executable bash scripts must be set to be executable (e.g. via `chmod +x `). +Executable bash scripts are named using `kebab-case` and do not have file extension (e.g. `my-bash-command` and **not** `my-bash-command.sh` or `my_bash_command`). Non-executable bash scripts are named in `snake_case` and have an `.sh` extension. +Use the `env` functionality by default in shebangs except if the context suggests otherwise (e.g. `#!/usr/bin/env bash` instead of `#!/bin/bash`). ## Python diff --git a/Dockerfile-mpc b/Dockerfile-mpc index 8d071a81d..19c4eacb0 100644 --- a/Dockerfile-mpc +++ b/Dockerfile-mpc @@ -37,7 +37,7 @@ LABEL org.opencontainers.image.source https://github.com/clearmatics/zeth COPY --from=stage1 /usr/local/bin/ /usr/local/bin # Move the mpc python code COPY --from=stage1 /home/zeth/mpc/ /home/zeth-mpc -COPY --from=stage1 /home/zeth/scripts/docker/entrypoint-mpc.sh /home/zeth-mpc/entrypoint.sh +COPY --from=stage1 /home/zeth/scripts/docker/entrypoint-mpc /home/zeth-mpc/entrypoint RUN apk --update --no-cache add \ bash \ # Install necessary shared libs to run the rust binaries @@ -60,5 +60,5 @@ RUN apk del \ WORKDIR /home/zeth-mpc -ENTRYPOINT ["./entrypoint.sh"] +ENTRYPOINT ["./entrypoint"] CMD ["/bin/bash"] diff --git a/Dockerfile-prover b/Dockerfile-prover index c2fa91d5c..99623ed91 100644 --- a/Dockerfile-prover +++ b/Dockerfile-prover @@ -10,12 +10,12 @@ COPY . ${ZETH_PATH} RUN cd ${ZETH_PATH} \ && git submodule update --init --recursive -# Build `prover_server` +# Build `prover-server` RUN cd ${ZETH_PATH} \ && mkdir build \ && cd build \ && cmake -DMPC=OFF -DSTATIC_BUILD=ON .. \ - && make -j"$($(nprocs)+1)" prover_server + && make -j"$($(nprocs)+1)" prover-server ## @@ -24,6 +24,6 @@ FROM alpine:3.12 LABEL org.opencontainers.image.source https://github.com/clearmatics/zeth RUN apk add --no-cache bash -## Move `prover_server` from previous image and put it in the PATH -COPY --from=stage1 /home/zeth/build/prover_server/prover_server /usr/local/bin +## Move `prover-server` from previous image and put it in the PATH +COPY --from=stage1 /home/zeth/build/prover_server/prover-server /usr/local/bin CMD ["/bin/bash"] diff --git a/Doxyfile.in b/Doxyfile.in index 74e7e5a71..a99f14e0a 100644 --- a/Doxyfile.in +++ b/Doxyfile.in @@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = "Zeth - Clearmatics Technologies LTD" +PROJECT_NAME = "Zeth - Zerocash on Ethereum" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version @@ -44,7 +44,7 @@ PROJECT_NUMBER = @ZETH_VERSION_MAJOR@.@ZETH_VERSION_MINOR@ # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. -PROJECT_BRIEF = "Zerocash on Ethereum" +PROJECT_BRIEF = "Reference implementation of the Zeth protocol by Clearmatics" # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 @@ -58,7 +58,7 @@ PROJECT_LOGO = # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/doc_doxygen/ +OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/docs/ # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and @@ -780,9 +780,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = @CMAKE_CURRENT_SOURCE_DIR@/libzeth/ \ - @CMAKE_CURRENT_SOURCE_DIR@/mpc_tools/ \ - @CMAKE_CURRENT_SOURCE_DIR@/prover_server +INPUT = @CMAKE_SOURCE_DIR@ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -843,7 +841,11 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = */env/* \ + */node_modules/* \ + */tests/* \ + */depends/* \ + */build/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the @@ -936,7 +938,9 @@ FILTER_SOURCE_PATTERNS = # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. -USE_MDFILE_AS_MAINPAGE = +INPUT += @CMAKE_SOURCE_DIR@/README_doxygen.md +FILE_PATTERNS += *.md +USE_MDFILE_AS_MAINPAGE = @CMAKE_SOURCE_DIR@/README_doxygen.md #--------------------------------------------------------------------------- # Configuration options related to source browsing @@ -1195,7 +1199,7 @@ HTML_COLORSTYLE_GAMMA = 80 # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_TIMESTAMP = NO +HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the @@ -2285,7 +2289,7 @@ INCLUDED_BY_GRAPH = YES # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. -CALL_GRAPH = NO +CALL_GRAPH = YES # If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller # dependency graph for every global function or class method. @@ -2297,7 +2301,7 @@ CALL_GRAPH = NO # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. -CALLER_GRAPH = NO +CALLER_GRAPH = YES # If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical # hierarchy of all classes instead of a textual one. diff --git a/README.md b/README.md index ff3fa1bc7..fca66ee2b 100644 --- a/README.md +++ b/README.md @@ -36,9 +36,9 @@ Additionally, several tools from the GCC and LLVM tools suite are used to improv To use the Zeth functionality, 3 components are required: - An Ethereum network (the commands below use a local testnet) to host the Zeth contracts and handle transactions. -- A running "prover_server" process, used by Zeth clients to generate proofs. +- A running `prover-server` process, used by Zeth clients to generate proofs. - Client tools, which generate all inputs required for a Zeth operations, - request proofs from the "prover_server", and transmit transactions to the + request proofs from the `prover-server`, and transmit transactions to the Ethereum network holding the Zeth contract. We use 3 terminals, one for each of the above components. @@ -47,16 +47,16 @@ Note: Mac users should increase docker runtime memory from 2GB to 4GB to allow T #### Terminal 1: -We propose 2 alternatives to run the `prover_server` below. +We propose 2 alternatives to run the `prover-server` below. -##### Fetch the prover_server image (recommended) +##### Fetch the `prover-server` image (recommended) ```bash docker pull ghcr.io/clearmatics/zeth:latest-prover -docker run -ti -p 50051:50051 --name prover ghcr.io/clearmatics/zeth:latest-prover prover_server +docker run -ti -p 50051:50051 --name prover ghcr.io/clearmatics/zeth:latest-prover prover-server ``` -##### Build and run the prover_server in the development container +##### Build and run the `prover-server` in the development container ```bash # Clone this repository: @@ -76,19 +76,19 @@ docker run -ti -p 50051:50051 --name zeth zeth-dev:latest mkdir build cd build cmake .. [] -# Compile all libraries and tools, including the prover_server +# Compile all libraries and tools, including the prover-server make # (optional) Run the unit tests make test # (optional) Run the all tests (unit tests, syntax checks, etc) make check -# Start the prover_server process -prover_server +# Start the prover-server process +prover-server ``` -Note: By default, `prover_server` generates a key at startup. Flags can be used -to force the server to load and/or save keys. Run `prover_server --help` +Note: By default, `prover-server` generates a key at startup. Flags can be used +to force the server to load and/or save keys. Run `prover-server --help` for more details. ##### Build Options diff --git a/README_doxygen.md b/README_doxygen.md new file mode 100644 index 000000000..71117d756 --- /dev/null +++ b/README_doxygen.md @@ -0,0 +1,7 @@ +# Introduction + +This is the developer documentation of the reference implementation of Zeth (Zerocash on ETHereum), an experimental digital-cash system for EVM-based chains. + +The software is an open source project and all community contributions are welcomed. The project is released under the LGPL-3.0 license. + +See https://github.com/clearmatics/zeth for further information about the project. diff --git a/client/.pylintrc b/client/.pylintrc index bc1cb5ae5..4b9fbf44b 100644 --- a/client/.pylintrc +++ b/client/.pylintrc @@ -19,7 +19,7 @@ disable= # https://github.com/PyCQA/pylint/issues/3882 # Re-enable it when the issue is fixed. -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 +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 max-attributes=10 diff --git a/client/Makefile b/client/Makefile index 9cc596444..d5e4e5bca 100644 --- a/client/Makefile +++ b/client/Makefile @@ -30,7 +30,6 @@ grpc: $(PROTOBUF_OUTPUT) syntax: ${PROTOBUF_OUTPUT} flake8 `git ls-files '**.py'` mypy -p zeth - mypy zeth/cli/zeth zeth/helper/zeth_helper mypy -p tests mypy -p test_commands mypy -p test_contracts diff --git a/client/README.md b/client/README.md index 66c68e099..5e617c59d 100644 --- a/client/README.md +++ b/client/README.md @@ -80,14 +80,14 @@ Note that `make setup` will automatically install the solidity compiler in `$HOM The `zeth` command exposes Zeth operations via a command line interface. A brief description is given in this section. More details are available via `zeth --help`, and example usage can be seen in the [pyclient test -script](../scripts/test_zeth_cli). +script](../scripts/test-zeth-cli). ## Environment Depending on the operation being performed, the `zeth` client must: - interact with an Ethereum RPC host, - interact with the deployed Zeth contracts, -- request proofs and proof verification keys from `prover_server`, and +- request proofs and proof verification keys from `prover-server`, and - access secret and public data for the current user Quite a lot of information must be given in order for the client to do this, diff --git a/client/setup.py b/client/setup.py index b6d331dd1..bda608969 100644 --- a/client/setup.py +++ b/client/setup.py @@ -18,52 +18,28 @@ setup( name='zeth', - version='0.7', + version='0.8', description='Interface to zeth operations', packages=find_packages(), install_requires=[ "mypy==0.790", "mypy-protobuf==1.23", "flake8==3.8.3", - "pylint==2.6", + "pylint==2.9", "click==7.0", "click-default-group==1.2", - "attrdict==2.0.1", - "certifi==2018.11.29", - "chardet==3.0.4", - "cytoolz==0.11.0", - "eth-abi==1.3.0", - "eth-account==0.3.0", - "eth-hash==0.2.0", - "eth-keyfile==0.5.1", - "eth-keys==0.2.1", - "eth-rlp==0.1.2", - "eth-typing==2.1.0", - "eth-utils==1.4.1", "grpcio==1.33.2", "grpcio-tools==1.33.2", - "hexbytes==0.1.0", - "idna==2.8", - "lru-dict==1.1.6", - "parsimonious==0.8.1", "protobuf==3.13.0", "py_ecc==1.7.1", "py-solc-x==1.1.0", - "pycryptodome==3.9.8", "cryptography==3.3.2", - "requests==2.21.0", - "rlp==1.1.0", - "semantic-version==2.8.4", - "six==1.15.0", - "toolz==0.9.0", - "urllib3==1.24.2", - "web3==4.8.2", - "websockets==6.0", + "web3>=5<6", ], - scripts=[ - "test_commands/test_ether_mixing.py", - "test_commands/test_erc_token_mixing.py", - "zeth/helper/zeth_helper", - "zeth/cli/zeth", - ] + entry_points={ + 'console_scripts': [ + 'zeth-helper=zeth.helper.zeth_helper:zeth_helper', + 'zeth=zeth.cli.zeth:zeth', + ], + } ) diff --git a/client/test_commands/scenario.py b/client/test_commands/scenario.py index dab9ee4df..f0bdc4ece 100644 --- a/client/test_commands/scenario.py +++ b/client/test_commands/scenario.py @@ -7,19 +7,20 @@ from zeth.core.zeth_address import ZethAddressPub from zeth.core.mixer_client import MixCallDescription, MixParameters, MixResult, \ MixerClient, OwnershipKeyPair, JoinsplitSigVerificationKey, ComputeHSigCB, \ - JoinsplitSigKeyPair, parse_mix_call, joinsplit_sign, encrypt_notes, \ - get_dummy_input_and_address, compute_h_sig + JoinsplitSigKeyPair, joinsplit_sign, encrypt_notes, \ + event_args_to_mix_result, get_dummy_input_and_address, compute_h_sig from zeth.core.prover_client import ProverClient from zeth.core.zksnark import IZKSnarkProvider, ExtendedProof -import zeth.core.signing as signing +from zeth.core import signing +from zeth.core.contracts import get_event_logs_from_tx_receipt from zeth.core.merkle_tree import MerkleTree from zeth.core.utils import EtherValue from zeth.api.zeth_messages_pb2 import ZethNote -import test_commands.mock as mock +from test_commands import mock from os import urandom from web3 import Web3 # type: ignore -from typing import List, Tuple, Optional +from typing import List, Tuple, Optional, Any ZERO_UNITS_HEX = "0000000000000000" BOB_DEPOSIT_ETH = 200 @@ -39,6 +40,18 @@ def dump_merkle_tree(mk_tree: List[bytes]) -> None: print("Node: " + Web3.toHex(node)[2:]) +def parse_mix_call( + mixer_instance: Any, + tx_receipt: Any) -> MixResult: + """ + Get the logs data associated with this mixing + """ + log_mix_events = \ + get_event_logs_from_tx_receipt(mixer_instance, "LogMix", tx_receipt) + mix_results = [event_args_to_mix_result(ev.args) for ev in log_mix_events] + return mix_results[0] + + def wait_for_tx_update_mk_tree( zeth_client: MixerClient, mk_tree: MerkleTree, @@ -224,10 +237,12 @@ def charlie_double_withdraw( attack_primary_input4: int = 0 def compute_h_sig_attack_nf( - nf0: bytes, - nf1: bytes, + nfs: List[bytes], sign_vk: JoinsplitSigVerificationKey) -> bytes: # We disassemble the nfs to get the formatting of the primary inputs + assert len(nfs) == 2 + nf0 = nfs[0] + nf1 = nfs[1] input_nullifier0 = nf0.hex() input_nullifier1 = nf1.hex() nf0_rev = "{0:0256b}".format(int(input_nullifier0, 16)) @@ -255,7 +270,7 @@ def compute_h_sig_attack_nf( primary_input4_res_bits attack_nf1 = "{0:064x}".format(int(attack_nf1_bits, 2)) return compute_h_sig( - bytes.fromhex(attack_nf0), bytes.fromhex(attack_nf1), sign_vk) + [bytes.fromhex(attack_nf0), bytes.fromhex(attack_nf1)], sign_vk) output_note1, output_note2, proof, public_data, signing_keypair = \ get_mix_parameters_components( diff --git a/client/test_commands/test_erc_token_mixing.py b/client/test_commands/test_erc_token_mixing.py index 912ac2cd1..7ac111d4b 100644 --- a/client/test_commands/test_erc_token_mixing.py +++ b/client/test_commands/test_erc_token_mixing.py @@ -6,15 +6,15 @@ import zeth.core.merkle_tree import zeth.core.utils -import zeth.core.constants as constants +from zeth.core import constants from zeth.core.mimc import get_tree_hash_for_pairing from zeth.core.prover_client import ProverClient from zeth.core.zeth_address import ZethAddressPriv from zeth.core.mixer_client import MixOutputEvents, MixerClient from zeth.core.wallet import Wallet, ZethNoteDescription from zeth.core.utils import EtherValue -import test_commands.mock as mock -import test_commands.scenario as scenario +from test_commands import mock +from test_commands import scenario from test_commands.deploy_test_token import deploy_token, mint_token from os.path import join, exists import shutil diff --git a/client/test_commands/test_ether_mixing.py b/client/test_commands/test_ether_mixing.py index 8d5db1803..4c5c7a86a 100644 --- a/client/test_commands/test_ether_mixing.py +++ b/client/test_commands/test_ether_mixing.py @@ -14,8 +14,8 @@ from zeth.core.zeth_address import ZethAddressPriv from zeth.core.mixer_client import MixOutputEvents, MixerClient from zeth.core.wallet import Wallet, ZethNoteDescription -import test_commands.mock as mock -import test_commands.scenario as scenario +from test_commands import mock +from test_commands import scenario from os.path import join, exists import shutil diff --git a/client/tests/test_encryption.py b/client/tests/test_encryption.py index 2ff86b710..6c50381d4 100644 --- a/client/tests/test_encryption.py +++ b/client/tests/test_encryption.py @@ -4,8 +4,8 @@ # # SPDX-License-Identifier: LGPL-3.0+ -import zeth.core.constants as constants -import zeth.core.encryption as encryption +from zeth.core import constants +from zeth.core import encryption from unittest import TestCase diff --git a/client/zeth/cli/constants.py b/client/zeth/cli/constants.py index 598dd677e..04397b8c5 100644 --- a/client/zeth/cli/constants.py +++ b/client/zeth/cli/constants.py @@ -10,6 +10,7 @@ ETH_RPC_ENDPOINT_DEFAULTS = { "ganache": "http://localhost:8545", "autonity-helloworld": "http://localhost:8541", + "bakerloo": "https://rpc3.bakerloo.autonity.network:8545", } ETH_NETWORK_FILE_DEFAULT = "eth-network" diff --git a/client/zeth/cli/utils.py b/client/zeth/cli/utils.py index 827db4162..8737f6069 100644 --- a/client/zeth/cli/utils.py +++ b/client/zeth/cli/utils.py @@ -338,9 +338,13 @@ def _do_sync() -> int: if wait_tx: _do_sync() tx_receipt = web3.eth.waitForTransactionReceipt(wait_tx, 10000) + tx = web3.eth.getTransaction(wait_tx) gas_used = tx_receipt.gasUsed status = tx_receipt.status - print(f"{wait_tx[0:8]}: gasUsed={gas_used}, status={status}") + size_bytes = len(tx.input) + print( + f"{wait_tx[0:8]}: gasUsed={gas_used}, status={status}, " + f"input_size={size_bytes}") return _do_sync() diff --git a/client/zeth/cli/zeth b/client/zeth/cli/zeth.py similarity index 98% rename from client/zeth/cli/zeth rename to client/zeth/cli/zeth.py index aaa1a8ddd..ba1cd9331 100644 --- a/client/zeth/cli/zeth +++ b/client/zeth/cli/zeth.py @@ -19,9 +19,10 @@ from zeth.cli.zeth_ls_commits import ls_commits from click import group, command, option, pass_context, ClickException, Context from click_default_group import DefaultGroup # type: ignore -from typing import Optional, Any +from typing import Optional +# pylint: disable=redefined-builtin @command() @pass_context def help(ctx: Context) -> None: diff --git a/client/zeth/cli/zeth_mix.py b/client/zeth/cli/zeth_mix.py index 7025f62dc..8b9776da9 100644 --- a/client/zeth/cli/zeth_mix.py +++ b/client/zeth/cli/zeth_mix.py @@ -60,9 +60,6 @@ def mix( if len(output_specs) > JS_OUTPUTS: raise ClickException(f"too many outputs (max {JS_OUTPUTS})") - print(f"vin = {vin}") - print(f"vout = {vout}") - vin_pub = EtherValue(vin) vout_pub = EtherValue(vout) client_ctx = ctx.obj diff --git a/client/zeth/cli/zeth_wait.py b/client/zeth/cli/zeth_wait.py index 066cd841d..262e8d200 100644 --- a/client/zeth/cli/zeth_wait.py +++ b/client/zeth/cli/zeth_wait.py @@ -21,17 +21,18 @@ def wait(ctx: Context, transaction_id: str) -> None: # Retrieve the tx receipt and dump logs web3 = open_web3_from_ctx(client_ctx) # type: ignore + instance = instance_desc.instantiate(web3) tx_receipt = web3.eth.waitForTransactionReceipt(transaction_id, 10000) \ # pylint: disable=no-member print("LogDebug events:") - logs = get_event_logs_from_tx_receipt(instance_desc, "LogDebug", tx_receipt) + logs = get_event_logs_from_tx_receipt(instance, "LogDebug", tx_receipt) for log in logs: print( f" {log.args['message']}: {log.args['value']} " f"({hex(log.args['value'])})") print("LogMix events:") - logs = get_event_logs_from_tx_receipt(instance_desc, "LogMix", tx_receipt) + logs = get_event_logs_from_tx_receipt(instance, "LogMix", tx_receipt) for log in logs: print(f" {log}") diff --git a/client/zeth/core/constants.py b/client/zeth/core/constants.py index 4e46d3032..1b7adc1c0 100644 --- a/client/zeth/core/constants.py +++ b/client/zeth/core/constants.py @@ -45,11 +45,6 @@ def bit_length_to_byte_length(bit_length: int) -> int: # Nb of output notes JS_OUTPUTS: int = 2 -# Gas cost estimates -DEPLOYMENT_GAS_WEI: int = ZETH_MERKLE_TREE_DEPTH * 250000 - -DEFAULT_MIX_GAS_WEI: int = DEPLOYMENT_GAS_WEI - # Hash digest length (for commitment and PRFs) DIGEST_LENGTH: int = 256 diff --git a/client/zeth/core/contracts.py b/client/zeth/core/contracts.py index 85201c57e..31f8db3ff 100644 --- a/client/zeth/core/contracts.py +++ b/client/zeth/core/contracts.py @@ -7,11 +7,10 @@ from __future__ import annotations from zeth.core.utils import EtherValue from zeth.core.constants import SOL_COMPILER_VERSION -from web3.utils.contracts import find_matching_event_abi # type: ignore -from web3.utils.events import get_event_data # type: ignore -from eth_utils import event_abi_to_log_topic # type: ignore +from web3._utils.contracts import find_matching_event_abi +from eth_utils import event_abi_to_log_topic import solcx -from typing import Dict, List, Iterator, Optional, Union, Iterable, Any +from typing import Dict, List, Iterator, Optional, Union, Iterable, Any, cast # Avoid trying to read too much data into memory SYNC_BLOCKS_PER_BATCH = 1000 @@ -44,7 +43,7 @@ def deploy( contract_name: str, deployer_eth_address: str, deployer_eth_private_key: Optional[bytes], - deployment_gas: int, + deployment_gas: Optional[int], compiler_flags: Dict[str, Any] = None, args: Iterable[Any] = None) -> InstanceDescription: """ @@ -72,7 +71,7 @@ def deploy_from_compiled( web3: Any, deployer_eth_address: str, deployer_eth_private_key: Optional[bytes], - deployment_gas: int, + deployment_gas: Optional[int], compiled: Any, *args: Any) -> InstanceDescription: contract = web3.eth.contract( @@ -153,6 +152,7 @@ def send_contract_call( transaction = call.buildTransaction(tx_desc) signed_tx = web3.eth.account.signTransaction( transaction, sender_eth_private_key) + print(f"send_contract_call: size={len(signed_tx.rawTransaction)}") return web3.eth.sendRawTransaction(signed_tx.rawTransaction) # Hosted path @@ -201,10 +201,12 @@ def get_event_logs( # skpping events with other topics, from the same contract. contract_address = instance.address + contract_event = instance.events[event_name]() + event_abi = find_matching_event_abi(instance.abi, event_name=event_name) - log_topic = event_abi_to_log_topic(event_abi) - batch_size = batch_size or SYNC_BLOCKS_PER_BATCH + log_topic = event_abi_to_log_topic(cast(Dict[str, Any], event_abi)) + batch_size = batch_size or SYNC_BLOCKS_PER_BATCH while start_block <= end_block: # Filters are *inclusive* wrt "toBlock", hence the -1 here, and +1 to # set start_block before iterating. @@ -217,12 +219,12 @@ def get_event_logs( logs = web3.eth.getLogs(filter_params) for log in logs: if log_topic == log['topics'][0]: - yield get_event_data(event_abi, log) + yield contract_event.processLog(log) start_block = to_block + 1 def get_event_logs_from_tx_receipt( - instance_desc: InstanceDescription, + instance: Any, event_name: str, tx_receipt: Any) -> Iterator[Any]: """ @@ -231,9 +233,11 @@ def get_event_logs_from_tx_receipt( objects to be decoded by the caller. This function intentionally avoids connecting to a node, or creating host-side filters. """ - contract_address = instance_desc.address - event_abi = find_matching_event_abi(instance_desc.abi, event_name=event_name) - log_topic = event_abi_to_log_topic(event_abi) + contract_address = instance.address + contract_event = instance.events[event_name]() + + event_abi = find_matching_event_abi(instance.abi, event_name=event_name) + log_topic = event_abi_to_log_topic(cast(Dict[str, Any], event_abi)) for log in tx_receipt.logs: if log.address == contract_address and log_topic == log['topics'][0]: - yield get_event_data(event_abi, log) + yield contract_event.processLog(log) diff --git a/client/zeth/core/mimc.py b/client/zeth/core/mimc.py index 8585cf519..6fa736fea 100644 --- a/client/zeth/core/mimc.py +++ b/client/zeth/core/mimc.py @@ -7,6 +7,7 @@ from Crypto.Hash import keccak \ # pylint: disable=import-error,no-name-in-module,line-too-long #type: ignore from abc import abstractmethod +from typing import List # Reference papers: # @@ -117,6 +118,23 @@ def __init__(self, seed_str: str = MIMC_MT_SEED): 62) +def generate_round_constants(seed_str: str, num_rounds: int) -> List[int]: + """ + Return the first `num_rounds` round constants. Not called directly here, + but used to precompute (in particular for the mimc_permutation gadget). + """ + seed = _keccak_256(_str_to_bytes(seed_str)) + rc = seed + + rcs = [0] + for _ in range(1, num_rounds): + rc = _update_round_constant(rc) + rcs.append(rc) + + assert len(rcs) == num_rounds + return rcs + + def get_tree_hash_for_pairing(pairing_name: str) -> ITreeHash: """ Select an appropriate hash for a given pairing. Note that these must match diff --git a/client/zeth/core/mixer_client.py b/client/zeth/core/mixer_client.py index f57ba21a1..257379f21 100644 --- a/client/zeth/core/mixer_client.py +++ b/client/zeth/core/mixer_client.py @@ -5,8 +5,8 @@ # SPDX-License-Identifier: LGPL-3.0+ from __future__ import annotations -import zeth.core.contracts as contracts -import zeth.core.constants as constants +from zeth.core import contracts +from zeth.core import constants from zeth.core.zeth_address import ZethAddressPub, ZethAddress from zeth.core.ownership import OwnershipPublicKey, OwnershipSecretKey, \ OwnershipKeyPair, ownership_key_as_hex @@ -15,18 +15,19 @@ generate_encryption_keypair, encrypt, decrypt from zeth.core.merkle_tree import MerkleTree, compute_merkle_path from zeth.core.pairing import PairingParameters -import zeth.core.signing as signing -import zeth.core.proto_utils as proto_utils +from zeth.core import signing +from zeth.core import proto_utils from zeth.core.zksnark import IZKSnarkProvider, get_zksnark_provider, \ ExtendedProof from zeth.core.utils import EtherValue, digest_to_binary_string, \ int64_to_hex, message_to_bytes, eth_address_to_bytes32, to_zeth_units, \ get_contracts_dir, hex_to_uint256_list from zeth.core.prover_client import ProverConfiguration, ProverClient -from zeth.api.zeth_messages_pb2 import ZethNote, JoinsplitInput, ProofInputs +import zeth.api.zeth_messages_pb2 as api import os import json +import math from Crypto import Random from hashlib import blake2s, sha256 import traceback @@ -42,7 +43,7 @@ JoinsplitSigSecretKey = signing.SigningSecretKey JoinsplitSigKeyPair = signing.SigningKeyPair -ComputeHSigCB = Callable[[bytes, bytes, JoinsplitSigVerificationKey], bytes] +ComputeHSigCB = Callable[[List[bytes], JoinsplitSigVerificationKey], bytes] class MixCallDescription: @@ -55,7 +56,7 @@ def __init__( self, mk_tree: MerkleTree, sender_ownership_keypair: OwnershipKeyPair, - inputs: List[Tuple[int, ZethNote]], + inputs: List[Tuple[int, api.ZethNote]], outputs: List[Tuple[ZethAddressPub, EtherValue]], v_in: EtherValue, v_out: EtherValue, @@ -223,13 +224,13 @@ def event_args_to_mix_result(event_args: Any) -> MixResult: output_events=out_events) -def create_joinsplit_input( +def create_api_joinsplit_input( merkle_path: List[str], address: int, - note: ZethNote, + note: api.ZethNote, a_sk: OwnershipSecretKey, - nullifier: bytes) -> JoinsplitInput: - return JoinsplitInput( + nullifier: bytes) -> api.JoinsplitInput: + return api.JoinsplitInput( merkle_path=merkle_path, address=address, note=note, @@ -238,12 +239,12 @@ def create_joinsplit_input( def get_dummy_input_and_address( - a_pk: OwnershipPublicKey) -> Tuple[int, ZethNote]: + a_pk: OwnershipPublicKey) -> Tuple[int, api.ZethNote]: """ Create a zeth note and address, for use as circuit inputs where there is no real input. """ - dummy_note = ZethNote( + dummy_note = api.ZethNote( apk=ownership_key_as_hex(a_pk), value=ZERO_UNITS_HEX, rho=_get_dummy_rho(), @@ -284,7 +285,6 @@ def deploy( """ prover_config = prover_client.get_configuration() vk = prover_client.get_verification_key() - deploy_gas = deploy_gas or constants.DEPLOYMENT_GAS_WEI contracts_dir = get_contracts_dir() zksnark = get_zksnark_provider(prover_config.zksnark_name) @@ -350,7 +350,7 @@ def joinsplit( sender_ownership_keypair: OwnershipKeyPair, sender_eth_address: str, sender_eth_private_key: Optional[bytes], - inputs: List[Tuple[int, ZethNote]], + inputs: List[Tuple[int, api.ZethNote]], outputs: List[Tuple[ZethAddressPub, EtherValue]], v_in: EtherValue, v_out: EtherValue, @@ -374,8 +374,7 @@ def joinsplit( mix_params, sender_eth_address, sender_eth_private_key, - tx_value or v_in, - constants.DEFAULT_MIX_GAS_WEI) + tx_value or v_in) def mix( self, @@ -383,7 +382,7 @@ def mix( sender_eth_address: str, sender_eth_private_key: Optional[bytes], tx_value: EtherValue, - call_gas: int = constants.DEFAULT_MIX_GAS_WEI) -> str: + call_gas: Optional[int] = None) -> str: """ Given a MixParameters object, create and broadcast a transaction performing the appropriate mix call. @@ -403,7 +402,7 @@ def mix_call( mix_params: MixParameters, sender_eth_address: str, tx_value: EtherValue, - call_gas: int = constants.DEFAULT_MIX_GAS_WEI) -> bool: + call_gas: Optional[int] = None) -> bool: """ Call the mix method (executes on the RPC host without creating a transaction). Returns True if the call succeeds. False, otherwise. @@ -439,7 +438,7 @@ def _create_mix_call( @staticmethod def create_prover_inputs( mix_call_desc: MixCallDescription - ) -> Tuple[ProofInputs, signing.SigningKeyPair]: + ) -> Tuple[api.ProofInputs, signing.SigningKeyPair]: """ Given the basic parameters for a mix call, compute the input to the prover server, and the signing key pair. @@ -447,16 +446,29 @@ def create_prover_inputs( # Compute Merkle paths mk_tree = mix_call_desc.mk_tree - mk_root = mk_tree.get_root() + sender_ask = mix_call_desc.sender_ownership_keypair.a_sk + + def _create_api_input( + input_address: int, + input_note: api.ZethNote) -> api.JoinsplitInput: + mk_path = compute_merkle_path(input_address, mk_tree) + input_nullifier = compute_nullifier(input_note, sender_ask) + return create_api_joinsplit_input( + mk_path, + input_address, + input_note, + sender_ask, + input_nullifier) + inputs = mix_call_desc.inputs - mk_paths = [compute_merkle_path(addr, mk_tree) for addr, _ in inputs] + api_inputs = [_create_api_input(addr, note) for addr, note in inputs] + + mk_root = mk_tree.get_root() # Extract (, ) tuples outputs_with_a_pk = \ [(zeth_addr.a_pk, to_zeth_units(value)) for (zeth_addr, value) in mix_call_desc.outputs] - output0 = outputs_with_a_pk[0] - output1 = outputs_with_a_pk[1] # Public input and output values as Zeth units public_in_value_zeth_units = to_zeth_units(mix_call_desc.v_in) @@ -464,50 +476,21 @@ def create_prover_inputs( # Generate the signing key signing_keypair = signing.gen_signing_keypair() - sender_ask = mix_call_desc.sender_ownership_keypair.a_sk - - # Compute the input note nullifiers - (input_address0, input_note0) = mix_call_desc.inputs[0] - (input_address1, input_note1) = mix_call_desc.inputs[1] - input_nullifier0 = compute_nullifier(input_note0, sender_ask) - input_nullifier1 = compute_nullifier(input_note1, sender_ask) - - # Convert to JoinsplitInput objects - js_inputs: List[JoinsplitInput] = [ - create_joinsplit_input( - mk_paths[0], - input_address0, - input_note0, - sender_ask, - input_nullifier0), - create_joinsplit_input( - mk_paths[1], - input_address1, - input_note1, - sender_ask, - input_nullifier1) - ] # Use the specified or default h_sig computation compute_h_sig_cb = mix_call_desc.compute_h_sig_cb or compute_h_sig h_sig = compute_h_sig_cb( - input_nullifier0, - input_nullifier1, + [bytes.fromhex(input.nullifier) for input in api_inputs], signing_keypair.vk) phi = _phi_randomness() - # Joinsplit Output Notes - output_note0, output_note1 = _create_zeth_notes( - phi, h_sig, output0, output1) - js_outputs = [ - output_note0, - output_note1 - ] + # Create the api.ZethNote objects + api_outputs = _create_api_zeth_notes(phi, h_sig, outputs_with_a_pk) - proof_inputs = ProofInputs( + proof_inputs = api.ProofInputs( mk_root=mk_root.hex(), - js_inputs=js_inputs, - js_outputs=js_outputs, + js_inputs=api_inputs, + js_outputs=api_outputs, pub_in_value=int64_to_hex(public_in_value_zeth_units), pub_out_value=int64_to_hex(public_out_value_zeth_units), h_sig=h_sig.hex(), @@ -517,7 +500,7 @@ def create_prover_inputs( def create_mix_parameters_from_proof( self, mix_call_desc: MixCallDescription, - prover_inputs: ProofInputs, + prover_inputs: api.ProofInputs, signing_keypair: signing.SigningKeyPair, ext_proof: ExtendedProof, public_data: List[int], @@ -538,7 +521,7 @@ def create_mix_parameters_from_proof( # Encrypt the notes outputs_and_notes = zip(mix_call_desc.outputs, prover_inputs.js_outputs) \ # pylint: disable=no-member - output_notes_with_k_pk: List[Tuple[ZethNote, EncryptionPublicKey]] = \ + output_notes_with_k_pk: List[Tuple[api.ZethNote, EncryptionPublicKey]] = \ [(note, zeth_addr.k_pk) for ((zeth_addr, _), note) in outputs_and_notes] ciphertexts = encrypt_notes(output_notes_with_k_pk) @@ -565,7 +548,7 @@ def create_mix_parameters_and_signing_key( mk_tree: MerkleTree, sender_ownership_keypair: OwnershipKeyPair, sender_eth_address: str, - inputs: List[Tuple[int, ZethNote]], + inputs: List[Tuple[int, api.ZethNote]], outputs: List[Tuple[ZethAddressPub, EtherValue]], v_in: EtherValue, v_out: EtherValue, @@ -588,10 +571,18 @@ def create_mix_parameters_and_signing_key( v_in, v_out, compute_h_sig_cb) + assert len(mix_call_desc.inputs) == constants.JS_INPUTS + assert len(mix_call_desc.outputs) == constants.JS_OUTPUTS + prover_inputs, signing_keypair = MixerClient.create_prover_inputs( mix_call_desc) - # Query the prover_server for the related proof + # pylint: disable=no-member + assert len(prover_inputs.js_inputs) == constants.JS_INPUTS + assert len(prover_inputs.js_outputs) == constants.JS_OUTPUTS + # pylint: enable=no-member + + # Query the prover-server for the related proof ext_proof, public_data = prover_client.get_proof(prover_inputs) # Create the final MixParameters object @@ -608,13 +599,14 @@ def create_mix_parameters_and_signing_key( def encrypt_notes( - notes: List[Tuple[ZethNote, EncryptionPublicKey]]) -> List[bytes]: + notes: List[Tuple[api.ZethNote, EncryptionPublicKey]]) -> List[bytes]: """ Encrypts a set of output notes to be decrypted by the respective receivers. Returns the ciphertexts corresponding to each note. """ - def _encrypt_note(out_note: ZethNote, pub_key: EncryptionPublicKey) -> bytes: + def _encrypt_note( + out_note: api.ZethNote, pub_key: EncryptionPublicKey) -> bytes: out_note_bytes = proto_utils.zeth_note_to_bytes(out_note) return encrypt(out_note_bytes, pub_key) @@ -626,7 +618,7 @@ def _encrypt_note(out_note: ZethNote, pub_key: EncryptionPublicKey) -> bytes: def receive_note( out_ev: MixOutputEvents, receiver_k_sk: EncryptionSecretKey -) -> Optional[Tuple[bytes, ZethNote]]: +) -> Optional[Tuple[bytes, api.ZethNote]]: """ Given the receivers secret key, and the event data from a transaction (encrypted notes), decrypt any that are intended for the receiver. Return @@ -645,18 +637,6 @@ def receive_note( return None -def parse_mix_call( - mixer_instance: Any, - _tx_receipt: str) -> MixResult: - """ - Get the logs data associated with this mixing - """ - log_mix_filter = mixer_instance.eventFilter("LogMix", {'fromBlock': 'latest'}) - log_mix_events = log_mix_filter.get_all_entries() - mix_results = [event_args_to_mix_result(ev.args) for ev in log_mix_events] - return mix_results[0] - - def get_mix_results( web3: Any, mixer_instance: Any, @@ -718,7 +698,7 @@ def joinsplit_sign( return signing.sign(signing_keypair.sk, message_digest) -def compute_commitment(zeth_note: ZethNote, pp: PairingParameters) -> bytes: +def compute_commitment(zeth_note: api.ZethNote, pp: PairingParameters) -> bytes: """ Used by the recipient of a payment to recompute the commitment and check the membership in the tree to confirm the validity of a payment @@ -736,7 +716,7 @@ def compute_commitment(zeth_note: ZethNote, pp: PairingParameters) -> bytes: def compute_nullifier( - zeth_note: ZethNote, + zeth_note: api.ZethNote, spending_authority_ask: OwnershipSecretKey) -> bytes: """ Returns nf = blake2s(1110 || [a_sk]_252 || rho) @@ -752,50 +732,40 @@ def compute_nullifier( def compute_h_sig( - nf0: bytes, - nf1: bytes, + nullifiers: List[bytes], sign_vk: JoinsplitSigVerificationKey) -> bytes: """ - Compute h_sig = sha256(nf0 || nf1 || sign_vk) - Flatten the verification key + Compute h_sig = sha256(nf_1 || ... || nf_{JS_INPUTS} || sign_vk) """ h = sha256() - h.update(nf0) - h.update(nf1) + for nf in nullifiers: + h.update(nf) h.update(sign_vk.to_bytes()) return h.digest() -def _create_zeth_notes( +def _create_api_zeth_notes( phi: bytes, hsig: bytes, - output0: Tuple[OwnershipPublicKey, int], - output1: Tuple[OwnershipPublicKey, int] -) -> Tuple[ZethNote, ZethNote]: - """ - Create two ordered ZethNotes. Used to generate new output - notes to be passed to the prover server. - """ - (recipient0, value0) = output0 - (recipient1, value1) = output1 - - rho0 = _compute_rho_i(phi, hsig, 0) - trap_r0 = _trap_r_randomness() - note0 = ZethNote( - apk=ownership_key_as_hex(recipient0), - value=int64_to_hex(value0), - rho=rho0.hex(), - trap_r=trap_r0) - - rho1 = _compute_rho_i(phi, hsig, 1) - trap_r1 = _trap_r_randomness() - note1 = ZethNote( - apk=ownership_key_as_hex(recipient1), - value=int64_to_hex(value1), - rho=rho1.hex(), - trap_r=trap_r1) + outputs: List[Tuple[OwnershipPublicKey, int]] +) -> List[api.ZethNote]: + """ + Create ordered list of api.ZethNote objects from the output descriptions. + """ + def _create_api_zeth_note( + out_index: int, recipient: OwnershipPublicKey, value: int + ) -> api.ZethNote: + rho = _compute_rho_i(phi, hsig, out_index) + trap_r = _trap_r_randomness() + return api.ZethNote( + apk=ownership_key_as_hex(recipient), + value=int64_to_hex(value), + rho=rho.hex(), + trap_r=trap_r) - return note0, note1 + return [ + _create_api_zeth_note(idx, recipient, value) + for idx, (recipient, value) in enumerate(outputs)] def _proof_and_inputs_to_bytes( @@ -826,21 +796,36 @@ def _trap_r_randomness() -> str: def _compute_rho_i(phi: bytes, hsig: bytes, i: int) -> bytes: """ - Returns rho_i = blake2s(0 || i || 10 || [phi]_252 || hsig) + Returns + rho_i = blake2s(0 || i || 10 || phi_truncated || hsig) + where i is encoded in the smallest number of bits (index_bits) required to + hold values 0, ..., JS_OUTPUTS-1, and phi_truncated is binary + representation of phi, truncated to 256 - index_bits - 3 bits. + See: Zcash protocol spec p. 57, Section 5.4.2 Pseudo Random Functions """ - # [SANITY CHECK] make sure i is in the interval [0, JS_INPUTS]. For now, - # this code also relies on JS_INPUTS being <= 2. - assert i < constants.JS_INPUTS - assert constants.JS_INPUTS <= 2, \ - "function needs updating to support JS_INPUTS > 2" + assert i < constants.JS_OUTPUTS - blake_hash = blake2s() + # Compute the number of bits required to represent the input index, and + # truncate phi so that: + # left_leg = 0 || i || 10 || phi_truncated + # occupies exactly 256 bits + + index_bits = math.ceil(math.log(constants.JS_OUTPUTS, 2)) + index_bin = f"{i:b}" + index_bin = "0" * (index_bits - len(index_bin)) + index_bin + assert len(index_bin) == index_bits, \ + f"index_bits: {index_bits}, index_bin: {index_bin}, i: {i}" - # Append PRF^{rho} tag to a_sk - binary_phi = digest_to_binary_string(phi) - first_252bits_phi = binary_phi[:252] - left_leg_bin = "0" + str(i) + "10" + first_252bits_phi + phi_truncated_bits = 256 - 1 - index_bits - 2 + phi_truncated_bin = digest_to_binary_string(phi)[:phi_truncated_bits] + assert len(phi_truncated_bin) == phi_truncated_bits + + left_leg_bin = "0" + index_bin + "10" + phi_truncated_bin + assert len(left_leg_bin) == 256 + + # Compute blake2s(left_leg || hsig) + blake_hash = blake2s() blake_hash.update(int(left_leg_bin, 2).to_bytes(32, byteorder='big')) blake_hash.update(hsig) return blake_hash.digest() diff --git a/client/zeth/core/proto_utils.py b/client/zeth/core/proto_utils.py index a8f9def23..a078ba86d 100644 --- a/client/zeth/core/proto_utils.py +++ b/client/zeth/core/proto_utils.py @@ -6,7 +6,7 @@ Utilities to handle protobuf types """ -import zeth.core.constants as constants +from zeth.core import constants from zeth.api.zeth_messages_pb2 import ZethNote from typing import Dict diff --git a/client/zeth/core/prover_client.py b/client/zeth/core/prover_client.py index f4cb149df..b88b65807 100644 --- a/client/zeth/core/prover_client.py +++ b/client/zeth/core/prover_client.py @@ -7,6 +7,7 @@ from __future__ import annotations from zeth.core.zksnark import IZKSnarkProvider, get_zksnark_provider, \ IVerificationKey, ExtendedProof +from zeth.core.constants import JS_INPUTS from zeth.core.pairing import PairingParameters, pairing_parameters_from_proto from zeth.api.zeth_messages_pb2 import ProofInputs from zeth.api import prover_pb2 # type: ignore @@ -117,9 +118,9 @@ def get_proof( """ Request a proof generation to the proving service """ + assert len(proof_inputs.js_inputs) == JS_INPUTS with grpc.insecure_channel(self.endpoint) as channel: stub = prover_pb2_grpc.ProverStub(channel) # type: ignore - print("-------------- Get the proof --------------") extproof_and_pub_data = stub.Prove(proof_inputs) zksnark = self.get_zksnark_provider() extproof = zksnark.extended_proof_from_proto( diff --git a/client/zeth/core/zksnark.py b/client/zeth/core/zksnark.py index d8ecca224..5926d2037 100644 --- a/client/zeth/core/zksnark.py +++ b/client/zeth/core/zksnark.py @@ -13,7 +13,7 @@ g1_point_to_contract_parameters, g1_point_from_proto, g1_point_to_proto, \ g2_point_to_contract_parameters, g2_point_from_proto, g2_point_to_proto, \ g2_point_negate -import zeth.core.constants as constants +from zeth.core import constants from zeth.api import snark_messages_pb2 import json diff --git a/client/zeth/helper/eth_fund.py b/client/zeth/helper/eth_fund.py index 3e02fac6f..d11b0038e 100644 --- a/client/zeth/helper/eth_fund.py +++ b/client/zeth/helper/eth_fund.py @@ -30,7 +30,8 @@ def eth_fund( amount: int) -> None: """ Fund an address. If no source address is given, the first hosted account on - the RPC host is used. + the RPC host is used. This command should only be used in test environments + such as ganache or autonity-helloworld. """ eth_addr = load_eth_address(eth_addr) eth_network = get_eth_network(ctx.obj["eth_network"]) @@ -45,9 +46,10 @@ def eth_fund( # with the password 'test'. Attempt to unlock it. # pylint: disable=import-outside-toplevel, no-member from web3.middleware import geth_poa_middleware # type: ignore - web3.middleware_stack.inject(geth_poa_middleware, layer=0) + web3.middleware_onion.inject(geth_poa_middleware, layer=0) web3.personal.unlockAccount(source_addr, "test") + source_addr = load_eth_address(source_addr) print(f"eth_addr = {eth_addr}") print(f"source_addr = {source_addr}") print(f"amount = {amount}") diff --git a/client/zeth/helper/eth_gen_network_config.py b/client/zeth/helper/eth_gen_network_config.py index b1b907a4b..b0bcfc271 100644 --- a/client/zeth/helper/eth_gen_network_config.py +++ b/client/zeth/helper/eth_gen_network_config.py @@ -38,23 +38,23 @@ def eth_gen_network_config( \b # Write default config for "ganache" to the default file - $ zeth_helper eth-gen-network-config ganache + $ zeth-helper eth-gen-network-config ganache \b # Write "geth" config with a custom endpoint to default file - $ zeth_helper eth-gen-network-config geth \\ + $ zeth-helper eth-gen-network-config geth \\ --eth-rpc-endpoint http://localhost:8080 \b # Write a custom https endpoint to file, specifying the certificate - $ zeth_helper eth-gen-network-config \\ + $ zeth-helper eth-gen-network-config \\ my-network \\ --eth-rpc-endpoint https://rpc.my-network.io:8545 \\ --eth-rpc-certificate rpc.my-network.io.crt \b # Write default network and endpoint to file "default-network" - $ zeth_helper eth-gen-network-config --output-file default-network + $ zeth-helper eth-gen-network-config --output-file default-network """ if eth_rpc_endpoint is not None: diff --git a/client/zeth/helper/zeth_helper b/client/zeth/helper/zeth_helper.py similarity index 98% rename from client/zeth/helper/zeth_helper rename to client/zeth/helper/zeth_helper.py index f0d1a3964..9d95841ec 100644 --- a/client/zeth/helper/zeth_helper +++ b/client/zeth/helper/zeth_helper.py @@ -16,6 +16,7 @@ from click_default_group import DefaultGroup # type: ignore +# pylint: disable=redefined-builtin @command() @pass_context def help(ctx: Context) -> None: diff --git a/cmake/documentation.cmake b/cmake/documentation.cmake index 55bafa67f..9a48f7b59 100644 --- a/cmake/documentation.cmake +++ b/cmake/documentation.cmake @@ -22,7 +22,7 @@ message("Doxygen build started") # The option ALL allows to build the docs together with the application add_custom_target( - doc_doxygen + build_docs ALL COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} @@ -37,6 +37,6 @@ endif() add_custom_target( docs - COMMAND ${XDG_OPEN} ${CMAKE_CURRENT_BINARY_DIR}/doc_doxygen/html/index.html - DEPENDS doc_doxygen + COMMAND ${XDG_OPEN} ${CMAKE_CURRENT_BINARY_DIR}/docs/html/index.html + DEPENDS build_docs ) diff --git a/depends/libsnark b/depends/libsnark index 104ed9021..3b1dc6b22 160000 --- a/depends/libsnark +++ b/depends/libsnark @@ -1 +1 @@ -Subproject commit 104ed902141d41dfb4efb2b9270386031d98e12e +Subproject commit 3b1dc6b22016f57d92a194094a6376ec1bd69e05 diff --git a/libtool/CMakeLists.txt b/libtool/CMakeLists.txt new file mode 100644 index 000000000..5fb38e6fe --- /dev/null +++ b/libtool/CMakeLists.txt @@ -0,0 +1,10 @@ +include_directories(.) + +find_package(Boost REQUIRED COMPONENTS program_options) +include_directories(${Boost_INCLUDE_DIR}) + +file(GLOB_RECURSE LIBTOOL_SOURCE **.?pp **.tcc) + +add_library(tool ${LIBTOOL_SOURCE}) +target_include_directories(tool PUBLIC ..) +target_link_libraries(tool ${Boost_PROGRAM_OPTIONS_LIBRARY}) diff --git a/libtool/command.hpp b/libtool/command.hpp new file mode 100644 index 000000000..25bc192bf --- /dev/null +++ b/libtool/command.hpp @@ -0,0 +1,30 @@ +// Copyright (c) 2015-2021 Clearmatics Technologies Ltd +// +// SPDX-License-Identifier: LGPL-3.0+ + +#ifndef __ZETH_LIBTOOL_COMMAND_HPP__ +#define __ZETH_LIBTOOL_COMMAND_HPP__ + +#include "libtool/subcommand.hpp" + +namespace libtool +{ + +/// Represents a top-level command, implementing parsing of global options. +template class command +{ +public: + /// Set up global options which are valid for all subcommands. + virtual void initialize_global_options( + boost::program_options::options_description &global, + boost::program_options::options_description &all_options) = 0; + + /// Parse the variables map to update the GlobalOptionsT object. + virtual void parse_global_options( + GlobalOptionsT &out_options, + const boost::program_options::variables_map &vm) = 0; +}; + +} // namespace libtool + +#endif // __ZETH_LIBTOOL_COMMAND_HPP__ diff --git a/libtool/run.hpp b/libtool/run.hpp new file mode 100644 index 000000000..55ab70ed0 --- /dev/null +++ b/libtool/run.hpp @@ -0,0 +1,27 @@ +// Copyright (c) 2015-2021 Clearmatics Technologies Ltd +// +// SPDX-License-Identifier: LGPL-3.0+ + +#ifndef __ZETH_LIBTOOL_RUN_HPP__ +#define __ZETH_LIBTOOL_RUN_HPP__ + +#include "libtool/command.hpp" + +namespace libtool +{ + +/// Execute a command object, with some global options object (initialized to +/// default values), supporting the given set of subcommands. +template +int run_command( + command &command, + GlobalOptionsT &options, + const std::map *> &subcommands, + int argc, + char **argv); + +} // namespace libtool + +#include "libtool/run.tcc" + +#endif // __ZETH_LIBTOOL_RUN_HPP__ diff --git a/libtool/run.tcc b/libtool/run.tcc new file mode 100644 index 000000000..f961073aa --- /dev/null +++ b/libtool/run.tcc @@ -0,0 +1,152 @@ +// Copyright (c) 2015-2021 Clearmatics Technologies Ltd +// +// SPDX-License-Identifier: LGPL-3.0+ + +#ifndef __ZETH_LIBTOOL_RUN_TCC__ +#define __ZETH_LIBTOOL_RUN_TCC__ + +#include "libtool/run.hpp" + +namespace libtool +{ + +namespace internal +{ + +template +void print_usage( + const char *const *argv, + const po::options_description &options, + const std::map *> &subcommands) +{ + std::cout << "Usage:\n" + << " " << argv[0] << " [OPTIONS] COMMAND [ARGS] ...\n\n" + << options; + + std::cout << "\nCommands:\n"; + + // list_commands(commands); + using entry_t = std::pair *>; + + // +4 here to ensure minimal space between command name and description + const size_t cmd_name_padded = + 4 + std::max_element( + subcommands.begin(), + subcommands.end(), + [](const entry_t &a, const entry_t &b) { + return a.first.size() < b.first.size(); + }) + ->first.size(); + + for (const auto &cmd : subcommands) { + const size_t padding = cmd_name_padded - cmd.first.size(); + std::cout << " " << cmd.first << std::string(padding, ' ') + << cmd.second->description() << "\n"; + } + + std::cout << std::endl; +} + +template +int run_subcommand( + const std::map *> &subcommands, + const std::string &command_name, + const char *argv0, + const std::vector &command_args, + const GlobalOptionsT &global_options) +{ + const typename std::map *>:: + const_iterator sub_it = subcommands.find(command_name); + if (sub_it == subcommands.end()) { + throw po::error("invalid command"); + } + + subcommand *sub = sub_it->second; + return sub->execute(argv0, command_args, global_options); +} + +} // namespace internal + +template +int run_command( + command &command, + GlobalOptionsT &options, + const std::map *> &subcommands, + int argc, + char **argv) +{ + po::options_description global("Global options"); + po::options_description all(""); + + // Default --help option + global.add_options()("help,h", "Show this help message and exit"); + + // Global options + command.initialize_global_options(global, all); + + // Add a single positional "command" option. + po::positional_options_description pos; + all.add_options()( + "command", po::value(), "Command to execute")( + "subargs", + po::value>(), + "Arguments to command"); + pos.add("command", 1).add("subargs", -1); + + auto usage = [&argv, &global, &subcommands]() { + internal::print_usage(argv, global, subcommands); + }; + + try { + po::variables_map vm; + po::parsed_options parsed = po::command_line_parser(argc, argv) + .options(all) + .positional(pos) + .allow_unregistered() + .run(); + po::store(parsed, vm); + + const bool help_flag = (bool)vm.count("help"); + + // If no command was given, print the top-level usage message. If a + // help flag was specified, exit normally, otherwise print an error + // message and exit with error. (If a command was given, the help flag + // is passed to the subcommand). + if (!vm.count("command")) { + if (help_flag) { + usage(); + return 0; + } + std::cerr << "error: no command specified\n"; + usage(); + return 1; + } + + // Parse the global options + command.parse_global_options(options, vm); + + // Execute the subcommand + const std::string subcommand(vm["command"].as()); + std::vector subargs = + po::collect_unrecognized(parsed.options, po::include_positional); + subargs[0] = std::string(argv[0]) + " " + subargs[0]; + + // Add the --help flag back, if given (it was absorbed by the global + // parser above). + if (help_flag) { + subargs.push_back("--help"); + } + + return internal::run_subcommand( + subcommands, subcommand, argv[0], subargs, options); + } catch (po::error &error) { + std::cerr << " ERROR: " << error.what() << std::endl; + usage(); + } + + return 1; +} + +} // namespace libtool + +#endif // __ZETH_LIBTOOL_RUN_TCC__ diff --git a/libtool/subcommand.hpp b/libtool/subcommand.hpp new file mode 100644 index 000000000..34bd28e54 --- /dev/null +++ b/libtool/subcommand.hpp @@ -0,0 +1,62 @@ +// Copyright (c) 2015-2021 Clearmatics Technologies Ltd +// +// SPDX-License-Identifier: LGPL-3.0+ + +#ifndef __ZETH_LIBTOOL_SUBCOMMAND_HPP__ +#define __ZETH_LIBTOOL_SUBCOMMAND_HPP__ + +#include +#include +#include + +namespace po = boost::program_options; + +namespace libtool +{ + +/// Class representing a tool subcommand. +template class subcommand +{ +public: + subcommand( + const std::string &subcommand_name, const std::string &description); + virtual ~subcommand(); + const std::string &description() const; + + /// Common code to parse options and invoke the virtual execute entrypoint. + int execute( + const char *argv0, + const std::vector command_args, + const GlobalOptionsT &global); + +protected: + void usage( + const char *argv0, + const boost::program_options::options_description &options); + + /// Instantiation can now set up the boost program_options structures. + virtual void initialize_suboptions( + boost::program_options::options_description &options, + boost::program_options::options_description &all_options, + boost::program_options::positional_options_description &pos) = 0; + + /// Instantiation can record any command-specific information from the + /// parsed variables_map. + virtual void parse_suboptions( + const boost::program_options::variables_map &vm) = 0; + + /// Any command-specific output for usage. + virtual void subcommand_usage(const char *argv0) = 0; + + /// Execute the command using global options defined by the caller. + virtual int execute_subcommand(const GlobalOptionsT &global) = 0; + + std::string subcommand_name; + std::string subcommand_description; +}; + +} // namespace libtool + +#include "libtool/subcommand.tcc" + +#endif // __ZETH_LIBTOOL_SUBCOMMAND_HPP__ diff --git a/libtool/subcommand.tcc b/libtool/subcommand.tcc new file mode 100644 index 000000000..ea3cd4028 --- /dev/null +++ b/libtool/subcommand.tcc @@ -0,0 +1,91 @@ +// Copyright (c) 2015-2021 Clearmatics Technologies Ltd +// +// SPDX-License-Identifier: LGPL-3.0+ + +#ifndef __ZETH_LIBTOOL_SUBCOMMAND_TCC__ +#define __ZETH_LIBTOOL_SUBCOMMAND_TCC__ + +#include "libtool/subcommand.hpp" + +#include + +namespace libtool +{ + +template +subcommand::subcommand( + const std::string &subcommand_name, const std::string &description) + : subcommand_name(subcommand_name), subcommand_description(description) +{ +} + +template subcommand::~subcommand() {} + +template +const std::string &subcommand::description() const +{ + return subcommand_description; +} + +template +int subcommand::execute( + const char *argv0, + const std::vector command_args, + const GlobalOptionsT &global) +{ + po::options_description options_desc("Options"); + po::options_description all_options_desc(""); + po::positional_options_description positional_options_desc; + + try { + // Common options + options_desc.add_options()("help,h", "This help"); + + // Subcommand options + initialize_suboptions( + options_desc, all_options_desc, positional_options_desc); + + // Send parsed structure to subcommand-specific so it can initialize + // itself. + po::variables_map vm; + po::parsed_options parsed = + po::command_line_parser( + std::vector( + command_args.begin() + 1, command_args.end())) + .options(all_options_desc) + .positional(positional_options_desc) + .run(); + po::store(parsed, vm); + + // If help was specified, print the usage and exit. + if (vm.count("help")) { + usage(argv0, options_desc); + return 0; + } + + // Otherwise, give the parsed options to the subcommand and execute. + parse_suboptions(vm); + return execute_subcommand(global); + } catch (po::error &error) { + std::cerr << "error: " << error.what() << "\n\n"; + usage(argv0, options_desc); + return 1; + } catch (std::invalid_argument &error) { + std::cerr << "error: " << error.what() << "\n"; + return 1; + } +} + +template +void subcommand::usage( + const char *argv0, + const boost::program_options::options_description &options) +{ + subcommand_usage(argv0); + std::cout << "\n" << description() << "\n\n"; + std::cout << options << std::endl; +} + +} // namespace libtool + +#endif // __ZETH_LIBTOOL_SUBCOMMAND_TCC__ diff --git a/libtool/tool_util.cpp b/libtool/tool_util.cpp new file mode 100644 index 000000000..efd278a8c --- /dev/null +++ b/libtool/tool_util.cpp @@ -0,0 +1,26 @@ +// Copyright (c) 2015-2021 Clearmatics Technologies Ltd +// +// SPDX-License-Identifier: LGPL-3.0+ + +#include "libtool/tool_util.hpp" + +namespace libtool +{ + +std::ifstream open_binary_input_file(const std::string &filename) +{ + std::ifstream in_s( + filename.c_str(), std::ios_base::in | std::ios_base::binary); + in_s.exceptions( + std::ios_base::eofbit | std::ios_base::badbit | std::ios_base::failbit); + return in_s; +} + +std::ofstream open_binary_output_file(const std::string &filename) +{ + std::ofstream out_s( + filename.c_str(), std::ios_base::out | std::ios_base::binary); + return out_s; +} + +} // namespace libtool diff --git a/libtool/tool_util.hpp b/libtool/tool_util.hpp new file mode 100644 index 000000000..50c475e77 --- /dev/null +++ b/libtool/tool_util.hpp @@ -0,0 +1,26 @@ +// Copyright (c) 2015-2021 Clearmatics Technologies Ltd +// +// SPDX-License-Identifier: LGPL-3.0+ + +#ifndef __ZETH_LIBTOOL_TOOL_UTIL_HPP__ +#define __ZETH_LIBTOOL_TOOL_UTIL_HPP__ + +#include "libtool/subcommand.hpp" + +#include + +/// Utilities that are likely to be useful for command line tools. + +namespace libtool +{ + +/// Utility function to open a file for reading, with appropriate flags and +/// exception handling enabled. +std::ifstream open_binary_input_file(const std::string &filename); + +/// Utility function to open a binary file for writing, with appropriate flags. +std::ofstream open_binary_output_file(const std::string &filename); + +} // namespace libtool + +#endif // __ZETH_LIBTOOL_TOOL_UTIL_HPP__ diff --git a/libzeth/CMakeLists.txt b/libzeth/CMakeLists.txt index 0b6579cf6..0429a6bbd 100644 --- a/libzeth/CMakeLists.txt +++ b/libzeth/CMakeLists.txt @@ -19,8 +19,8 @@ set_property(SOURCE ${PROTO_SRCS} PROPERTY COMPILE_FLAGS "-Wno-unused-variable -Wno-unused-parameter -Wno-error" ) -# Enable Boost for program_options -find_package(Boost REQUIRED COMPONENTS system filesystem program_options) +# Enable Boost for filesystem +find_package(Boost REQUIRED COMPONENTS system filesystem) include_directories(${Boost_INCLUDE_DIR}) # libsodium diff --git a/libzeth/circuits/binary_operation.hpp b/libzeth/circuits/binary_operation.hpp index 543eb6846..63a30d325 100644 --- a/libzeth/circuits/binary_operation.hpp +++ b/libzeth/circuits/binary_operation.hpp @@ -70,7 +70,6 @@ class xor_constant_gadget : public libsnark::gadget /// however given the inputs are boolean, the output is automatically boolean template class xor_rot_gadget : public libsnark::gadget { - private: const libsnark::pb_variable_array a; const libsnark::pb_variable_array b; @@ -98,7 +97,6 @@ template class xor_rot_gadget : public libsnark::gadget template class double_bit32_sum_eq_gadget : public libsnark::gadget { - private: libsnark::pb_variable_array a; libsnark::pb_variable_array b; diff --git a/libzeth/circuits/binary_operation.tcc b/libzeth/circuits/binary_operation.tcc index 1f812f9be..0d42fc00a 100644 --- a/libzeth/circuits/binary_operation.tcc +++ b/libzeth/circuits/binary_operation.tcc @@ -254,7 +254,7 @@ void double_bit32_sum_eq_gadget::generate_r1cs_witness() bits32 a_bits32 = bits32::from_vector(a.get_bits(this->pb)); bits32 b_bits32 = bits32::from_vector(b.get_bits(this->pb)); bits32 left_side_acc = bits_add<32>(a_bits32, b_bits32, false); - left_side_acc.fill_variable_array(this->pb, res); + left_side_acc.fill_pb_variable_array(this->pb, res); } } // namespace libzeth diff --git a/libzeth/circuits/blake2s/blake2s_comp_setup.tcc b/libzeth/circuits/blake2s/blake2s_comp_setup.tcc index 8612af1c7..c1cd4a050 100644 --- a/libzeth/circuits/blake2s/blake2s_comp_setup.tcc +++ b/libzeth/circuits/blake2s/blake2s_comp_setup.tcc @@ -159,16 +159,16 @@ void BLAKE2s_256_comp::setup_v(bool is_last_block) // [v_8, v_9, v_10, v_11] = [IV_0, IV_1, IV_2, IV_3] for (size_t i = 8; i < 12; i++) { - BLAKE2s_IV[i - 8].fill_variable_array(this->pb, v[0][i]); + BLAKE2s_IV[i - 8].fill_pb_variable_array(this->pb, v[0][i]); } // v_12 = t0 XOR IV_4 bits32 temp_xored = bits_xor(BLAKE2s_IV[4], t[0]); - temp_xored.fill_variable_array(this->pb, v[0][12]); + temp_xored.fill_pb_variable_array(this->pb, v[0][12]); // v_13 = t1 XOR IV_5 temp_xored = bits_xor(BLAKE2s_IV[5], t[1]); - temp_xored.fill_variable_array(this->pb, v[0][13]); + temp_xored.fill_pb_variable_array(this->pb, v[0][13]); // v_14 = f0 XOR IV_6 if (is_last_block) { @@ -176,11 +176,11 @@ void BLAKE2s_256_comp::setup_v(bool is_last_block) } else { temp_xored = BLAKE2s_IV[6]; } - temp_xored.fill_variable_array(this->pb, v[0][14]); + temp_xored.fill_pb_variable_array(this->pb, v[0][14]); // v_15 = f1 XOR IV_7 temp_xored = BLAKE2s_IV[7]; - temp_xored.fill_variable_array(this->pb, v[0][15]); + temp_xored.fill_pb_variable_array(this->pb, v[0][15]); } template void BLAKE2s_256_comp::setup_mixing_gadgets() diff --git a/libzeth/circuits/circuit_types.hpp b/libzeth/circuits/circuit_types.hpp index e8b02c923..61a3c41ae 100644 --- a/libzeth/circuits/circuit_types.hpp +++ b/libzeth/circuits/circuit_types.hpp @@ -50,6 +50,16 @@ template<> class tree_hash_selector template using HashTreeT = typename tree_hash_selector::tree_hash; +template +using JoinsplitCircuitT = circuit_wrapper< + HashT>, + HashTreeT>, + ppT, + snarkT, + libzeth::ZETH_NUM_JS_INPUTS, + libzeth::ZETH_NUM_JS_OUTPUTS, + libzeth::ZETH_MERKLE_TREE_DEPTH>; + } // namespace libzeth #endif // __ZETH_CIRCUITS_CIRCUIT_TYPES_HPP__ diff --git a/libzeth/circuits/circuit_utils.hpp b/libzeth/circuits/circuit_utils.hpp index 43f029c52..f715f9b96 100644 --- a/libzeth/circuits/circuit_utils.hpp +++ b/libzeth/circuits/circuit_utils.hpp @@ -15,9 +15,12 @@ namespace libzeth template libsnark::linear_combination packed_addition( const libsnark::pb_variable_array &input); + template -libsnark::pb_variable_array variable_array_from_bit_vector( - const std::vector &bits, const libsnark::pb_variable &ZERO); +libsnark::pb_variable_array pb_variable_array_from_bit_vector( + libsnark::protoboard &pb, + const std::vector &bits, + const std::string &annotation_prefix); } // namespace libzeth diff --git a/libzeth/circuits/circuit_utils.tcc b/libzeth/circuits/circuit_utils.tcc index 197ea9e6e..346693f59 100644 --- a/libzeth/circuits/circuit_utils.tcc +++ b/libzeth/circuits/circuit_utils.tcc @@ -46,22 +46,21 @@ libsnark::linear_combination packed_addition( // Thus here, we make sure our binary string is interpreted correctly. return libsnark::pb_packing_sum( libsnark::pb_variable_array(inputs.rbegin(), inputs.rend())); -}; +} -// Takes a vector of boolean values, and convert this vector of boolean values -// into a vector of FieldT::zero() and FieldT:one() +// Allocate an array of variables on a given protoboard, and set the values to +// zero or one based on a vector of bits. template -libsnark::pb_variable_array variable_array_from_bit_vector( - const std::vector &bits, const libsnark::pb_variable &ZERO) +libsnark::pb_variable_array pb_variable_array_from_bit_vector( + libsnark::protoboard &pb, + const std::vector &bits, + const std::string &annotation_prefix) { - libsnark::pb_variable_array acc; - acc.reserve(bits.size()); - for (bool bit : bits) { - acc.emplace_back(bit ? ONE : ZERO); - } - - return acc; -}; + libsnark::pb_variable_array vars; + vars.allocate(pb, bits.size(), annotation_prefix); + vars.fill_with_bits(pb, bits); + return vars; +} } // namespace libzeth diff --git a/libzeth/circuits/commitments/commitment.hpp b/libzeth/circuits/commitments/commitment.hpp index 5e1720051..52fad7621 100644 --- a/libzeth/circuits/commitments/commitment.hpp +++ b/libzeth/circuits/commitments/commitment.hpp @@ -14,7 +14,7 @@ namespace libzeth { template -class COMM_gadget : libsnark::gadget +class COMM_gadget : public libsnark::gadget { private: // input variable block = {x, y} diff --git a/libzeth/circuits/joinsplit.tcc b/libzeth/circuits/joinsplit.tcc index b6dcd183d..37e0c962e 100644 --- a/libzeth/circuits/joinsplit.tcc +++ b/libzeth/circuits/joinsplit.tcc @@ -23,7 +23,7 @@ template< size_t NumInputs, size_t NumOutputs, size_t TreeDepth> -class joinsplit_gadget : libsnark::gadget +class joinsplit_gadget : public libsnark::gadget { private: const size_t digest_len_minus_field_cap = @@ -467,10 +467,10 @@ public: // Witness public values // // Witness LHS public value - vpub_in.fill_variable_array(this->pb, zk_vpub_in); + vpub_in.fill_pb_variable_array(this->pb, zk_vpub_in); // Witness RHS public value - vpub_out.fill_variable_array(this->pb, zk_vpub_out); + vpub_out.fill_pb_variable_array(this->pb, zk_vpub_out); // Witness h_sig h_sig->generate_r1cs_witness(h_sig_in.to_vector()); @@ -495,7 +495,7 @@ public: left_side_acc, inputs[i].note.value, true); } - left_side_acc.fill_variable_array(this->pb, zk_total_uint64); + left_side_acc.fill_pb_variable_array(this->pb, zk_total_uint64); } // Witness the JoinSplit inputs and the h_is diff --git a/libzeth/circuits/mimc/mimc_permutation.hpp b/libzeth/circuits/mimc/mimc_permutation.hpp index 2cc82f9e1..73485b57b 100644 --- a/libzeth/circuits/mimc/mimc_permutation.hpp +++ b/libzeth/circuits/mimc/mimc_permutation.hpp @@ -20,8 +20,11 @@ template class MiMC_permutation_gadget : public libsnark::gadget { private: - // Round constants only available up to some maximum number of rounds - static const size_t MaxRounds = 65; + // Round constants only available up to some maximum number of rounds. Note + // that the instantiations used in this library do not use all 93 round + // constants, but other instantiations may (in particular, see + // instantations for other curves in https://github.com/clearmatics/zecale). + static const size_t MaxRounds = 93; static_assert( NumRounds <= MaxRounds, "NumRounds must be less than MaxRounds"); diff --git a/libzeth/circuits/mimc/mimc_permutation.tcc b/libzeth/circuits/mimc/mimc_permutation.tcc index 827b53cf2..21329c518 100644 --- a/libzeth/circuits/mimc/mimc_permutation.tcc +++ b/libzeth/circuits/mimc/mimc_permutation.tcc @@ -155,145 +155,112 @@ void MiMC_permutation_gadget:: return; } - // For simplicity, always generate constants for MaxRounds. - round_constants.reserve(MaxRounds); + // Constants are generated as follows (in client python env): + // (env) $ python + // >>> import zeth.core.mimc as mimc + // >>> import zeth.core.constants as constants + // >>> mimc.generate_round_constants(constants.MIMC_MT_SEED, 93) // The constant is set to "0" in the first round of MiMC permutation (see: // https://eprint.iacr.org/2016/492.pdf) - round_constants.push_back(FieldT("0")); + // For simplicity, always populate with enough constants for MaxRounds. // clang-format off - - // This is sha3_256(sha3_256("clearmatics_mt_seed")) - round_constants.push_back(FieldT( - "22159019873790129476324495190496603411493310235845550845393361088354059025587")); - - round_constants.push_back(FieldT( - "27761654615899466766976328798614662221520122127418767386594587425934055859027")); - round_constants.push_back(FieldT( - "94824950344308939111646914673652476426466554475739520071212351703914847519222")); - round_constants.push_back(FieldT( - "84875755167904490740680810908425347913240786521935721949482414218097022905238")); - round_constants.push_back(FieldT( - "103827469404022738626089808362855974444473512881791722903435218437949312500276")); - round_constants.push_back(FieldT( - "79151333313630310680682684119244096199179603958178503155035988149812024220238")); - round_constants.push_back(FieldT( - "69032546029442066350494866745598303896748709048209836077355812616627437932521")); - round_constants.push_back(FieldT( - "71828934229806034323678289655618358926823037947843672773514515549250200395747")); - round_constants.push_back(FieldT( - "20380360065304068228640594346624360147706079921816528167847416754157399404427")); - round_constants.push_back(FieldT( - "33389882590456326015242966586990383840423378222877476683761799984554709177407")); - round_constants.push_back(FieldT( - "50122810070778420844700285367936543284029126632619100118638682958218725318756")); - round_constants.push_back(FieldT( - "49246859699528342369154520789249265070136349803358469088610922925489948122588")); - round_constants.push_back(FieldT( - "42301293999667742503298132605205313473294493780037112351216393454277775233701")); - round_constants.push_back(FieldT( - "84114918321547685007627041787929288135785026882582963701427252073231899729239")); - round_constants.push_back(FieldT( - "62442564517333183431281494169332072638102772915973556148439397377116238052032")); - round_constants.push_back(FieldT( - "90371696767943970492795296318744142024828099537644566050263944542077360454000")); - round_constants.push_back(FieldT( - "115430938798103259020685569971731347341632428718094375123887258419895353452385")); - round_constants.push_back(FieldT( - "113486567655643015051612432235944767094037016028918659325405959747202187788641")); - round_constants.push_back(FieldT( - "42521224046978113548086179860571260859679910353297292895277062016640527060158")); - round_constants.push_back(FieldT( - "59337418021535832349738836949730504849571827921681387254433920345654363097721")); - round_constants.push_back(FieldT( - "11312792726948192147047500338922194498305047686482578113645836215734847502787")); - round_constants.push_back(FieldT( - "5531104903388534443968883334496754098135862809700301013033503341381689618972")); - round_constants.push_back(FieldT( - "67267967506593457603372921446668397713655666818276613345969561709158934132467")); - round_constants.push_back(FieldT( - "14150601882795046585170507190892504128795190437985555320824531798948976631295")); - round_constants.push_back(FieldT( - "85062650450907709431728516509140931676564801299509460081586249478375415684322")); - round_constants.push_back(FieldT( - "3190636703526705373452173482292964566521687248139217048214149162895182633187")); - round_constants.push_back(FieldT( - "94697707246459731032848302079578714910941380385884087153796554334872238022178")); - round_constants.push_back(FieldT( - "105237079024348272465679804525604310926083869213267017956044692586513087552889")); - round_constants.push_back(FieldT( - "107666297462370279081061498341391155289817553443536637437225808625028106164694")); - round_constants.push_back(FieldT( - "50658185643016152702409617752847261961811370146977869351531768522548888496960")); - round_constants.push_back(FieldT( - "40194505239242861003888376856216043830225436269588275639840138989648733836164")); - round_constants.push_back(FieldT( - "18446023938001439123322925291203176968088321100216399802351969471087090508798")); - round_constants.push_back(FieldT( - "56716868411561319312404565555682857409226456576794830238428782927207680423406")); - round_constants.push_back(FieldT( - "99446603622401702299467002115709680008186357666919726252089514718382895122907")); - round_constants.push_back(FieldT( - "14440268383603206763216449941954085575335212955165966039078057319953582173633")); - round_constants.push_back(FieldT( - "19800531992512132732080265836821627955799468140051158794892004229352040429024")); - round_constants.push_back(FieldT( - "105297016338495372394147178784104774655759157445835217996114870903812070518445")); - round_constants.push_back(FieldT( - "25603899274511343521079846952994517772529013612481201245155078199291999403355")); - round_constants.push_back(FieldT( - "42343992762533961606462320250264898254257373842674711124109812370529823212221")); - round_constants.push_back(FieldT( - "10746157796797737664081586165620034657529089112211072426663365617141344936203")); - round_constants.push_back(FieldT( - "83415911130754382252267592583976834889211427666721691843694426391396310581540")); - round_constants.push_back(FieldT( - "90866605176883156213219983011392724070678633758652939051248987072469444200627")); - round_constants.push_back(FieldT( - "37024565646714391930474489137778856553925761915366252060067939966442059957164")); - round_constants.push_back(FieldT( - "7989471243134634308962365261048299254340659799910534445820512869869542788064")); - round_constants.push_back(FieldT( - "15648939481289140348738679797715724220399212972574021006219862339465296839884")); - round_constants.push_back(FieldT( - "100133438935846292803417679717817950677446943844926655798697284495340753961844")); - round_constants.push_back(FieldT( - "84618212755822467879717121296483255659772850854170590780922087915497421596465")); - round_constants.push_back(FieldT( - "66815981435852782130184794409662156021404245655267602728283138458689925010111")); - round_constants.push_back(FieldT( - "100011403138602452635630699813302791324969902443516593676764382923531277739340")); - round_constants.push_back(FieldT( - "57430361797750645341842394309545159343198597441951985629580530284393758413106")); - round_constants.push_back(FieldT( - "70240009849732555205629614425470918637568887938810907663457802670777054165279")); - round_constants.push_back(FieldT( - "115341201140672997375646566164431266507025151688875346248495663683620086806942")); - round_constants.push_back(FieldT( - "11188962021222070760150833399355814187143871338754315850627637681691407594017")); - round_constants.push_back(FieldT( - "22685520879254273934490401340849316430229408194604166253482138215686716109430")); - round_constants.push_back(FieldT( - "51189210546148312327463530170430162293845070064001770900624850430825589457055")); - round_constants.push_back(FieldT( - "14807565813027010873011142172745696288480075052292277459306275231121767039664")); - round_constants.push_back(FieldT( - "95539138374056424883213912295679274059417180869462186511207318536449091576661")); - round_constants.push_back(FieldT( - "113489397464329757187555603731541774715600099685729291423921796997078292946609")); - round_constants.push_back(FieldT( - "104312240868162447193722372229442001535106018532365202206691174960555358414880")); - round_constants.push_back(FieldT( - "8267151326618998101166373872748168146937148303027773815001564349496401227343")); - round_constants.push_back(FieldT( - "76298755107890528830128895628139521831584444593650120338808262678169950673284")); - round_constants.push_back(FieldT( - "73002305935054160156217464153178860593131914821282451210510325210791458847694")); - round_constants.push_back(FieldT( - "74544443080560119509560262720937836494902079641131221139823065933367514898276")); - round_constants.push_back(FieldT( - "36856043990250139109110674451326757800006928098085552406998173198427373834846")); + round_constants = { + FieldT("0"), + FieldT("22159019873790129476324495190496603411493310235845550845393361088354059025587"), + FieldT("27761654615899466766976328798614662221520122127418767386594587425934055859027"), + FieldT("94824950344308939111646914673652476426466554475739520071212351703914847519222"), + FieldT("84875755167904490740680810908425347913240786521935721949482414218097022905238"), + FieldT("103827469404022738626089808362855974444473512881791722903435218437949312500276"), + FieldT("79151333313630310680682684119244096199179603958178503155035988149812024220238"), + FieldT("69032546029442066350494866745598303896748709048209836077355812616627437932521"), + FieldT("71828934229806034323678289655618358926823037947843672773514515549250200395747"), + FieldT("20380360065304068228640594346624360147706079921816528167847416754157399404427"), + FieldT("33389882590456326015242966586990383840423378222877476683761799984554709177407"), + FieldT("50122810070778420844700285367936543284029126632619100118638682958218725318756"), + FieldT("49246859699528342369154520789249265070136349803358469088610922925489948122588"), + FieldT("42301293999667742503298132605205313473294493780037112351216393454277775233701"), + FieldT("84114918321547685007627041787929288135785026882582963701427252073231899729239"), + FieldT("62442564517333183431281494169332072638102772915973556148439397377116238052032"), + FieldT("90371696767943970492795296318744142024828099537644566050263944542077360454000"), + FieldT("115430938798103259020685569971731347341632428718094375123887258419895353452385"), + FieldT("113486567655643015051612432235944767094037016028918659325405959747202187788641"), + FieldT("42521224046978113548086179860571260859679910353297292895277062016640527060158"), + FieldT("59337418021535832349738836949730504849571827921681387254433920345654363097721"), + FieldT("11312792726948192147047500338922194498305047686482578113645836215734847502787"), + FieldT("5531104903388534443968883334496754098135862809700301013033503341381689618972"), + FieldT("67267967506593457603372921446668397713655666818276613345969561709158934132467"), + FieldT("14150601882795046585170507190892504128795190437985555320824531798948976631295"), + FieldT("85062650450907709431728516509140931676564801299509460081586249478375415684322"), + FieldT("3190636703526705373452173482292964566521687248139217048214149162895182633187"), + FieldT("94697707246459731032848302079578714910941380385884087153796554334872238022178"), + FieldT("105237079024348272465679804525604310926083869213267017956044692586513087552889"), + FieldT("107666297462370279081061498341391155289817553443536637437225808625028106164694"), + FieldT("50658185643016152702409617752847261961811370146977869351531768522548888496960"), + FieldT("40194505239242861003888376856216043830225436269588275639840138989648733836164"), + FieldT("18446023938001439123322925291203176968088321100216399802351969471087090508798"), + FieldT("56716868411561319312404565555682857409226456576794830238428782927207680423406"), + FieldT("99446603622401702299467002115709680008186357666919726252089514718382895122907"), + FieldT("14440268383603206763216449941954085575335212955165966039078057319953582173633"), + FieldT("19800531992512132732080265836821627955799468140051158794892004229352040429024"), + FieldT("105297016338495372394147178784104774655759157445835217996114870903812070518445"), + FieldT("25603899274511343521079846952994517772529013612481201245155078199291999403355"), + FieldT("42343992762533961606462320250264898254257373842674711124109812370529823212221"), + FieldT("10746157796797737664081586165620034657529089112211072426663365617141344936203"), + FieldT("83415911130754382252267592583976834889211427666721691843694426391396310581540"), + FieldT("90866605176883156213219983011392724070678633758652939051248987072469444200627"), + FieldT("37024565646714391930474489137778856553925761915366252060067939966442059957164"), + FieldT("7989471243134634308962365261048299254340659799910534445820512869869542788064"), + FieldT("15648939481289140348738679797715724220399212972574021006219862339465296839884"), + FieldT("100133438935846292803417679717817950677446943844926655798697284495340753961844"), + FieldT("84618212755822467879717121296483255659772850854170590780922087915497421596465"), + FieldT("66815981435852782130184794409662156021404245655267602728283138458689925010111"), + FieldT("100011403138602452635630699813302791324969902443516593676764382923531277739340"), + FieldT("57430361797750645341842394309545159343198597441951985629580530284393758413106"), + FieldT("70240009849732555205629614425470918637568887938810907663457802670777054165279"), + FieldT("115341201140672997375646566164431266507025151688875346248495663683620086806942"), + FieldT("11188962021222070760150833399355814187143871338754315850627637681691407594017"), + FieldT("22685520879254273934490401340849316430229408194604166253482138215686716109430"), + FieldT("51189210546148312327463530170430162293845070064001770900624850430825589457055"), + FieldT("14807565813027010873011142172745696288480075052292277459306275231121767039664"), + FieldT("95539138374056424883213912295679274059417180869462186511207318536449091576661"), + FieldT("113489397464329757187555603731541774715600099685729291423921796997078292946609"), + FieldT("104312240868162447193722372229442001535106018532365202206691174960555358414880"), + FieldT("8267151326618998101166373872748168146937148303027773815001564349496401227343"), + FieldT("76298755107890528830128895628139521831584444593650120338808262678169950673284"), + FieldT("73002305935054160156217464153178860593131914821282451210510325210791458847694"), + FieldT("74544443080560119509560262720937836494902079641131221139823065933367514898276"), + FieldT("36856043990250139109110674451326757800006928098085552406998173198427373834846"), + FieldT("89876265522016337550524744707009312276376790319197860491657618155961055194949"), + FieldT("110827903006446644954303964609043521818500007209339765337677716791359271709709"), + FieldT("19507166101303357762640682204614541813131172968402646378144792525256753001746"), + FieldT("107253144238416209039771223682727408821599541893659793703045486397265233272366"), + FieldT("50595349797145823467207046063156205987118773849740473190540000392074846997926"), + FieldT("44703482889665897122601827877356260454752336134846793080442136212838463818460"), + FieldT("72587689163044446617379334085046687704026377073069181869522598220420039333904"), + FieldT("102651401786920090371975453907921346781687924794638352783098945209363379010084"), + FieldT("93452870373806728605513560063145330258676656934938716540885043830342716774537"), + FieldT("78296669596559313198894751403351590225284664485458045241864014863714864424243"), + FieldT("115089219682233450926699488628267277641700041858332325616476033644461392438459"), + FieldT("12503229023709380637667243769419362848195673442247523096260626221166887267863"), + FieldT("4710254915107472945023322521703570589554948344762175784852248799008742965033"), + FieldT("7718237385336937042064321465151951780913850666971695410931421653062451982185"), + FieldT("115218487714637830492048339157964615618803212766527542809597433013530253995292"), + FieldT("30146276054995781136885926012526705051587400199196161599789168368938819073525"), + FieldT("81645575619063610562025782726266715757461113967190574155696199274188206173145"), + FieldT("103065286526250765895346723898189993161715212663393551904337911885906019058491"), + FieldT("19401253163389218637767300383887292725233192135251696535631823232537040754970"), + FieldT("39843332085422732827481601668576197174769872102167705377474553046529879993254"), + FieldT("27288628349107331632228897768386713717171618488175838305048363657709955104492"), + FieldT("63512042813079522866974560192099016266996589861590638571563519363305976473166"), + FieldT("88099896769123586138541398153669061847681467623298355942484821247745931328016"), + FieldT("69497565113721491657291572438744729276644895517335084478398926389231201598482"), + FieldT("17118586436782638926114048491697362406660860405685472757612739816905521144705"), + FieldT("50507769484714413215987736701379019852081133212073163694059431350432441698257"), + FieldT("58260458108608505301755075857897657610125730489308125711681594839108744994599"), + FieldT("74417125471829501682706919197813397955210189244710764612359440617050537569714") + }; // clang-format on assert(round_constants.size() == MaxRounds); diff --git a/libzeth/circuits/notes/note.tcc b/libzeth/circuits/notes/note.tcc index fbf792ab9..927c716fd 100644 --- a/libzeth/circuits/notes/note.tcc +++ b/libzeth/circuits/notes/note.tcc @@ -41,8 +41,8 @@ template void note_gadget::generate_r1cs_constraints() template void note_gadget::generate_r1cs_witness(const zeth_note ¬e) { - note.r.fill_variable_array(this->pb, r); - note.value.fill_variable_array(this->pb, value); + note.r.fill_pb_variable_array(this->pb, r); + note.value.fill_pb_variable_array(this->pb, value); } // Gadget that makes sure that all conditions are met in order to spend a note: @@ -175,7 +175,7 @@ void input_note_gadget:: spend_authority->generate_r1cs_witness(); // Witness rho for the input note - note.rho.fill_variable_array(this->pb, rho); + note.rho.fill_pb_variable_array(this->pb, rho); // Witness the nullifier for the input note expose_nullifiers->generate_r1cs_witness(); @@ -258,7 +258,7 @@ void input_note_gadget:: << (this->pb.val(value_enforce)).as_ulong() << std::endl; // Witness merkle tree authentication path - address_bits.fill_variable_array(this->pb, address_bits_va); + address_bits.fill_pb_variable_array(this->pb, address_bits_va); // Set auth_path values auth_path->fill_with_field_elements(this->pb, merkle_path); @@ -301,7 +301,7 @@ void output_note_gadget::generate_r1cs_witness( note_gadget::generate_r1cs_witness(note); // Witness a_pk with note information - note.a_pk.fill_variable_array(this->pb, a_pk->bits); + note.a_pk.fill_pb_variable_array(this->pb, a_pk->bits); commit_to_outputs_cm->generate_r1cs_witness(); } diff --git a/libzeth/circuits/sha256/sha256_ethereum.hpp b/libzeth/circuits/sha256/sha256_ethereum.hpp index d2ed9ae6b..434062ab4 100644 --- a/libzeth/circuits/sha256/sha256_ethereum.hpp +++ b/libzeth/circuits/sha256/sha256_ethereum.hpp @@ -43,7 +43,6 @@ class sha256_ethereum : public libsnark::gadget sha256_ethereum( libsnark::protoboard &pb, - const libsnark::pb_variable &ZERO, const libsnark::block_variable &input_block, const libsnark::digest_variable &output, const std::string &annotation_prefix = "sha256_ethereum"); diff --git a/libzeth/circuits/sha256/sha256_ethereum.tcc b/libzeth/circuits/sha256/sha256_ethereum.tcc index 4464adbe9..91d1685c3 100644 --- a/libzeth/circuits/sha256/sha256_ethereum.tcc +++ b/libzeth/circuits/sha256/sha256_ethereum.tcc @@ -24,7 +24,6 @@ namespace libzeth template sha256_ethereum::sha256_ethereum( libsnark::protoboard &pb, - const libsnark::pb_variable &ZERO, const libsnark::block_variable &input_block, const libsnark::digest_variable &output, const std::string &annotation_prefix) @@ -41,7 +40,8 @@ sha256_ethereum::sha256_ethereum( // written in the checkSum function of the crypto/sha256 go package // Total size of this vector = 512bits libsnark::pb_variable_array length_padding = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, { 1, 0, 0, 0, 0, 0, 0, 0, // First part: 448bits <-> 56bytes 0, 0, 0, 0, 0, 0, 0, 0, // @@ -108,7 +108,7 @@ sha256_ethereum::sha256_ethereum( 0, 0, 0, 0, 0, 0, 1, 0, // 0, 0, 0, 0, 0, 0, 0, 0, // }, - ZERO); + FMT(annotation_prefix, " padding")); // https://github.com/scipr-lab/libsnark/blob/master/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_components.tcc#L35 // Note: The IV defined in libsnark is made of: @@ -164,7 +164,7 @@ sha256_ethereum::sha256_ethereum( // then used as IV for the second hashing round libsnark::pb_linear_combination_array IV2(intermediate_hash->bits); - // We hash the intermediate hash wiht the padding. + // We hash the intermediate hash with the padding. hasher2.reset(new libsnark::sha256_compression_function_gadget( pb, IV2, diff --git a/libzeth/core/bits.cpp b/libzeth/core/bits.cpp index 28dbe8f2e..7136a45a1 100644 --- a/libzeth/core/bits.cpp +++ b/libzeth/core/bits.cpp @@ -62,4 +62,13 @@ std::vector bit_vector_from_size_t_be(size_t x) return res; } +void bit_vector_write_string(const std::vector &bits, std::ostream &out_s) +{ + out_s << "{"; + for (size_t i = 0; i < bits.size() - 1; ++i) { + out_s << bits[i] << ", "; + } + out_s << bits[bits.size() - 1] << "}\n"; +} + } // namespace libzeth diff --git a/libzeth/core/bits.hpp b/libzeth/core/bits.hpp index e717796dc..0a96eaa3d 100644 --- a/libzeth/core/bits.hpp +++ b/libzeth/core/bits.hpp @@ -35,7 +35,7 @@ template class bits : public std::array /// Construct from initializer-list. // cppcheck-suppress noExplicitConstructor - template bits(const boolList &... bits); + template bits(const boolList &...bits); std::vector to_vector() const; @@ -53,7 +53,7 @@ template class bits : public std::array /// Fill a libsnark::pb_variable_array with bits from this container, /// representing each as 1 or 0 in FieldT. template - void fill_variable_array( + void fill_pb_variable_array( libsnark::protoboard &pb, libsnark::pb_variable_array &var_array) const; @@ -88,6 +88,9 @@ std::vector bit_vector_from_size_t_le(size_t x); /// Returns the big endian binary encoding of the integer x. std::vector bit_vector_from_size_t_be(size_t x); +void bit_vector_write_string( + const std::vector &bits, std::ostream &out_s); + } // namespace libzeth #include "libzeth/core/bits.tcc" diff --git a/libzeth/core/bits.tcc b/libzeth/core/bits.tcc index 8c0bb87a9..439b755b7 100644 --- a/libzeth/core/bits.tcc +++ b/libzeth/core/bits.tcc @@ -37,7 +37,7 @@ template bits::bits() template template -bits::bits(const boolList &... bits) +bits::bits(const boolList &...bits) : std::array{std::forward(bits)...} { } @@ -106,7 +106,7 @@ template bool bits::is_zero() const template template -void bits::fill_variable_array( +void bits::fill_pb_variable_array( libsnark::protoboard &pb, libsnark::pb_variable_array &var_array) const { diff --git a/libzeth/core/field_element_utils.hpp b/libzeth/core/field_element_utils.hpp index 84e6c68e7..e74d7e154 100644 --- a/libzeth/core/field_element_utils.hpp +++ b/libzeth/core/field_element_utils.hpp @@ -9,41 +9,13 @@ namespace libzeth { - -/// WARNING: The following function assumes that the platform is little-endian -/// and that NAILS are NOT used. See Section 8.2 (page 68): -/// https://gmplib.org/gmp-man-6.2.0.pdf -/// -/// In other words, we assume that: -/// - GMP_NUMB_BITS = GMP_LIMB_BITS and thus, -/// - GMP_NAIL_BITS = 0 -/// -/// Under these assumptions, bigints are layed out in memory with low-order -/// bytes first, occupying `FieldT::num_limbs * GMP_LIMB_BITS / 8` bytes. For -/// readability, this function returns the big-endian hex representation -/// (high-order byte first). If `prefix` is true, add the "0x" prefix. -template -std::string bigint_to_hex( - const libff::bigint &limbs, bool prefix = false); - -/// WARNING: The following function assumes that the platform is little-endian -/// and that NAILS are NOT used. See Section 8.2 (page 68): -/// https://gmplib.org/gmp-man-6.2.0.pdf -/// -/// In other words, we assume that: -/// - GMP_NUMB_BITS = GMP_LIMB_BITS and thus, -/// - GMP_NAIL_BITS = 0 -/// -/// Hex is read as most-significant-character-first (the natural ordering for -/// numbers), as generated by `bigint_to_hex`. -template -libff::bigint bigint_from_hex(const std::string &hex); - -/// Convert a base/ground field element to a hexadecimal string. +/// Convert a base field element (single component) to a hexadecimal +/// string (without any JSON decoration such as '"'). template std::string base_field_element_to_hex(const FieldT &field_el); -/// Convert an hexadecimal string to a base/ground field element +/// Convert a plain hex string (without any JSON decoration such as '"') to a +/// base field element (single component). template FieldT base_field_element_from_hex(const std::string &field_str); diff --git a/libzeth/core/field_element_utils.tcc b/libzeth/core/field_element_utils.tcc index 824f2cd61..87d7d5d9e 100644 --- a/libzeth/core/field_element_utils.tcc +++ b/libzeth/core/field_element_utils.tcc @@ -8,182 +8,42 @@ #include "libzeth/core/field_element_utils.hpp" #include "libzeth/core/utils.hpp" -#include +#include #include -/// This file uses types and preprocessor variables defined in the `gmp.h` -/// header: -/// - `mp_size_t` -/// - `GMP_LIMB_BITS` -/// - `GMP_NAIL_BITS` - namespace libzeth { -namespace internal -{ - -template class field_element_json -{ -public: - /// Convert a field element to JSON - static void write(const FieldT &field_el, std::ostream &out_s) - { - // Note that we write components of extension fields - // highest-order-first. - out_s << '['; - size_t i = FieldT::tower_extension_degree - 1; - do { - out_s << field_element_to_json(field_el.coeffs[i]); - if (i > 0) { - out_s << ','; - } - } while (i-- > 0); - out_s << ']'; - } - - /// Read a field element from JSON - static void read(FieldT &field_el, std::istream &in_s) - { - // Read opening '[' char, then each component (highest-order-first) - // separated by ',' char, then a closing ']' char. - - char sep; - in_s >> sep; - if (sep != '[') { - throw std::runtime_error("expected opening bracket"); - } - - size_t i = FieldT::tower_extension_degree - 1; - do { - field_element_read_json(field_el.coeffs[i], in_s); - if (i > 0) { - in_s >> sep; - if (sep != ',') { - throw std::runtime_error("expected comma separator"); - } - } - } while (i-- > 0); - - in_s >> sep; - if (sep != ']') { - throw std::runtime_error("expected closing bracket"); - } - } -}; - -/// Implementation of field_element_json for the base-case of Fp_model -/// types. -template &modulus> -class field_element_json> -{ -public: - using Field = libff::Fp_model; - static void write(const Field &field_el, std::ostream &out_s) - { - out_s << '"' << base_field_element_to_hex(field_el) << '"'; - }; - static void read(Field &field_el, std::istream &in_s) - { - char quote; - in_s >> quote; - if (quote != '"') { - throw std::runtime_error("expected json string"); - } - std::string bigint_hex; - try { - std::getline(in_s, bigint_hex, '"'); - } catch (...) { - throw std::runtime_error("json string not terminated"); - } - field_el = base_field_element_from_hex(bigint_hex); - } -}; - -// Generic reader and write for fields and field extensions. -template class field_element_bytes -{ -public: - static void write(const FieldT &field_el, std::ostream &out_s) - { - for (size_t i = 0; i < FieldT::tower_extension_degree; ++i) { - field_element_write_bytes(field_el.coeffs[i], out_s); - } - } - static void read(FieldT &field_el, std::istream &in_s) - { - for (size_t i = 0; i < FieldT::tower_extension_degree; ++i) { - field_element_read_bytes(field_el.coeffs[i], in_s); - } - } -}; - -/// Implementation of field_element_bytes for the base-case of Fp_model types. -/// Big-endian bigint values (i.e. not in montgomery form). -template &modulus> -class field_element_bytes> -{ -public: - using Field = libff::Fp_model; - static void write(const Field &field_el, std::ostream &out_s) - { - // Convert to bigint, reverse bytes in-place, and write to stream. - const libff::bigint bi = field_el.as_bigint(); - std::reverse((char *)(&bi), (char *)(&bi + 1)); - out_s.write((const char *)(&bi.data[0]), sizeof(bi)); - } - static void read(Field &field_el, std::istream &in_s) - { - // Read bigint from stream, reverse bytes in-place and convert to field - // element. - libff::bigint res; - in_s.read((char *)(&res.data[0]), sizeof(res)); - std::reverse((char *)(&res), (char *)(&res + 1)); - field_el = Field(res); - } -}; - -} // namespace internal - -template -std::string bigint_to_hex( - const libff::bigint &limbs, bool prefix) -{ - return bytes_to_hex_reversed(&limbs.data[0], sizeof(limbs.data), prefix); -} - -template -libff::bigint bigint_from_hex(const std::string &hex) -{ - libff::bigint res; - hex_to_bytes_reversed(hex, &res.data[0], sizeof(res.data)); - return res; -} - template std::string base_field_element_to_hex(const FieldT &field_el) { - // Serialize a "ground/base" field element - BOOST_ASSERT(FieldT::extension_degree() == 1); - return bigint_to_hex(field_el.as_bigint(), true); + static_assert( + FieldT::extension_degree() == 1, "only valid on base/ground fields"); + return libff::bigint_to_hex(field_el.as_bigint(), true); } template FieldT base_field_element_from_hex(const std::string &hex) { - return FieldT(bigint_from_hex(hex)); + static_assert( + FieldT::extension_degree() == 1, "only valid on base/ground fields"); + using BigIntT = + typename std::decaymont_repr)>::type; + BigIntT v; + libff::bigint_from_hex(v, hex); + return FieldT(v); } template void field_element_write_json(const FieldT &el, std::ostream &out_s) { - internal::field_element_json::write(el, out_s); + libff::field_write(el, out_s); } template void field_element_read_json(FieldT &el, std::istream &in_s) { - internal::field_element_json::read(el, in_s); + libff::field_read(el, in_s); } template std::string field_element_to_json(const FieldT &el) @@ -207,13 +67,13 @@ FieldT field_element_from_json(const std::string &json) template void field_element_write_bytes(const FieldT &el, std::ostream &out_s) { - internal::field_element_bytes::write(el, out_s); + libff::field_write(el, out_s); } template void field_element_read_bytes(FieldT &el, std::istream &in_s) { - internal::field_element_bytes::read(el, in_s); + libff::field_read(el, in_s); } } // namespace libzeth diff --git a/libzeth/core/hash_stream.hpp b/libzeth/core/hash_stream.hpp index 5210797a5..4b21209f9 100644 --- a/libzeth/core/hash_stream.hpp +++ b/libzeth/core/hash_stream.hpp @@ -32,7 +32,7 @@ template class hash_ostream_wrapper; template class hash_istream_wrapper; /// Internal streambuf for hash_ostream. Hash and discard all written data. -template class hash_streambuf : std::streambuf +template class hash_streambuf : public std::streambuf { protected: hash_streambuf(); @@ -44,7 +44,7 @@ template class hash_streambuf : std::streambuf }; /// Internal streambuf for wrapped streams. Hash data and forward. -template class hash_streambuf_wrapper : std::streambuf +template class hash_streambuf_wrapper : public std::streambuf { protected: explicit hash_streambuf_wrapper(std::ostream *inner); diff --git a/libzeth/core/multi_exp.tcc b/libzeth/core/multi_exp.tcc index daf71016d..47ad3bbd3 100644 --- a/libzeth/core/multi_exp.tcc +++ b/libzeth/core/multi_exp.tcc @@ -18,7 +18,7 @@ GroupT multi_exp( typename std::vector::const_iterator fs_end) { const libff::multi_exp_method Method = libff::multi_exp_method_BDLO12; - return libff::multi_exp_with_mixed_addition( + return libff::multi_exp_filter_one_zero( gs_start, gs_end, fs_start, fs_end, 1); } @@ -30,7 +30,7 @@ GroupT multi_exp(const std::vector &gs, const libff::Fr_vector &fs) using Fr = libff::Fr; const libff::multi_exp_method Method = libff::multi_exp_method_BDLO12; - return libff::multi_exp_with_mixed_addition( + return libff::multi_exp_filter_one_zero( gs.begin(), gs.begin() + fs.size(), fs.begin(), fs.end(), 1); } diff --git a/libzeth/mpc/groth16/mpc_utils.tcc b/libzeth/mpc/groth16/mpc_utils.tcc index a51004834..93885a8f8 100644 --- a/libzeth/mpc/groth16/mpc_utils.tcc +++ b/libzeth/mpc/groth16/mpc_utils.tcc @@ -6,7 +6,6 @@ #define __ZETH_MPC_GROTH16_MPC_UTILS_TCC__ #include "libzeth/core/evaluator_from_lagrange.hpp" -#include "libzeth/core/multi_exp.hpp" #include "libzeth/core/utils.hpp" #include "libzeth/mpc/groth16/mpc_utils.hpp" #include "libzeth/mpc/groth16/phase2.hpp" diff --git a/libzeth/mpc/groth16/phase2.hpp b/libzeth/mpc/groth16/phase2.hpp index c89021d1e..29f1ee093 100644 --- a/libzeth/mpc/groth16/phase2.hpp +++ b/libzeth/mpc/groth16/phase2.hpp @@ -286,8 +286,14 @@ srs_mpc_phase2_challenge srs_mpc_dummy_phase2( size_t num_inputs); /// Given the output from all phases of the MPC, create the proving and -/// verification keys for the given circuit. -template +/// verification keys for the given circuit. If BaseForm = +/// libff::multi_exp_base_form_special, all arrays are converted to special +/// form for more efficient proving (This will happen naturally as a side +/// effect of (de)serialization, and hence this batch conversion is disabled by +/// default). +template< + typename ppT, + libff::multi_exp_base_form BaseForm = libff::multi_exp_base_form_normal> libsnark::r1cs_gg_ppzksnark_keypair mpc_create_key_pair( srs_powersoftau &&pot, srs_mpc_layer_L1 &&layer1, diff --git a/libzeth/mpc/groth16/phase2.tcc b/libzeth/mpc/groth16/phase2.tcc index 2806e7241..f3d199cb2 100644 --- a/libzeth/mpc/groth16/phase2.tcc +++ b/libzeth/mpc/groth16/phase2.tcc @@ -689,7 +689,7 @@ srs_mpc_phase2_challenge srs_mpc_dummy_phase2( return srs_mpc_phase2_compute_challenge(std::move(response_1)); } -template +template libsnark::r1cs_gg_ppzksnark_keypair mpc_create_key_pair( srs_powersoftau &&pot, srs_mpc_layer_L1 &&layer1, @@ -762,6 +762,14 @@ libsnark::r1cs_gg_ppzksnark_keypair mpc_create_key_pair( layer2.delta_g2, libsnark::accumulation_vector(std::move(ABC_0), std::move(ABC_i))); + // Convert all arrays to special form, if requested. + if (BaseForm == libff::multi_exp_base_form_special) { + libff::batch_to_special(layer1.A_g1); + libff::batch_to_special(B_i); + libff::batch_to_special(layer2.H_g1); + libff::batch_to_special(layer2.L_g1); + } + libsnark::r1cs_gg_ppzksnark_proving_key pk( G1(pot.alpha_tau_powers_g1[0]), G1(pot.beta_tau_powers_g1[0]), diff --git a/libzeth/serialization/proto_utils.tcc b/libzeth/serialization/proto_utils.tcc index 00b7859c9..f9f57fb9d 100644 --- a/libzeth/serialization/proto_utils.tcc +++ b/libzeth/serialization/proto_utils.tcc @@ -84,8 +84,8 @@ template void pairing_parameters_to_proto(zeth_proto::PairingParameters &pp_proto) { pp_proto.set_name(pp_name()); - pp_proto.set_r(bigint_to_hex>(libff::Fr::mod)); - pp_proto.set_q(bigint_to_hex>(libff::Fq::mod)); + pp_proto.set_r(libff::bigint_to_hex(libff::Fr::mod)); + pp_proto.set_q(libff::bigint_to_hex(libff::Fq::mod)); *pp_proto.mutable_generator_g1() = point_g1_affine_to_proto(libff::G1::one()); *pp_proto.mutable_generator_g2() = diff --git a/libzeth/serialization/r1cs_serialization.tcc b/libzeth/serialization/r1cs_serialization.tcc index 54947f57d..913dadf56 100644 --- a/libzeth/serialization/r1cs_serialization.tcc +++ b/libzeth/serialization/r1cs_serialization.tcc @@ -31,8 +31,7 @@ void constraints_write_json( out_s << "{"; out_s << "\"index\":" << lt.index << ","; out_s << "\"value\":" - << "\"" + bigint_to_hex(lt.coeff.as_bigint(), true) - << "\""; + << "\"" + base_field_element_to_hex(lt.coeff) << "\""; out_s << "}"; count++; } @@ -152,8 +151,7 @@ std::ostream &r1cs_write_json( out_s << "{\n"; out_s << "\"scalar_field_characteristic\":" - << "\"" + bigint_to_hex(FieldT::field_char(), true) - << "\",\n"; + << "\"" + libff::bigint_to_hex(FieldT::field_char(), true) << "\",\n"; out_s << "\"num_variables\":" << r1cs.num_variables() << ",\n"; out_s << "\"num_constraints\":" << r1cs.num_constraints() << ",\n"; out_s << "\"num_inputs\": " << r1cs.num_inputs() << ",\n"; diff --git a/libzeth/serialization/r1cs_variable_assignment_serialization.hpp b/libzeth/serialization/r1cs_variable_assignment_serialization.hpp index f5de76000..2bc2e8281 100644 --- a/libzeth/serialization/r1cs_variable_assignment_serialization.hpp +++ b/libzeth/serialization/r1cs_variable_assignment_serialization.hpp @@ -14,6 +14,13 @@ template void r1cs_variable_assignment_read_bytes( libsnark::r1cs_variable_assignment &assignment, std::istream &in_s); +template +void r1cs_variable_assignment_read_bytes( + libsnark::r1cs_primary_input &primary, + libsnark::r1cs_auxiliary_input &auxiliary, + const size_t primary_input_size, + std::istream &in_s); + template void r1cs_variable_assignment_write_bytes( const libsnark::r1cs_variable_assignment &assignment, diff --git a/libzeth/serialization/r1cs_variable_assignment_serialization.tcc b/libzeth/serialization/r1cs_variable_assignment_serialization.tcc index de5a85726..a2168d7d8 100644 --- a/libzeth/serialization/r1cs_variable_assignment_serialization.tcc +++ b/libzeth/serialization/r1cs_variable_assignment_serialization.tcc @@ -21,6 +21,33 @@ void r1cs_variable_assignment_read_bytes( field_element_read_bytes>(assignment, in_s); } +template +void r1cs_variable_assignment_read_bytes( + libsnark::r1cs_primary_input &primary, + libsnark::r1cs_auxiliary_input &auxiliary, + const size_t primary_input_size, + std::istream &in_s) +{ + // Manually read the collection size, compute the primary and auxiliary + // sizes and read into the separate arrays. + const size_t n = read_bytes(in_s); + if (n < primary_input_size) { + throw std::length_error( + "assignment length smaller than primary input size"); + } + + primary.clear(); + collection_n_read_bytes< + libsnark::r1cs_primary_input, + field_element_read_bytes>(primary, primary_input_size, in_s); + + auxiliary.clear(); + collection_n_read_bytes< + libsnark::r1cs_auxiliary_input, + field_element_read_bytes>( + auxiliary, n - primary_input_size, in_s); +} + template void r1cs_variable_assignment_write_bytes( const libsnark::r1cs_variable_assignment &assignment, diff --git a/libzeth/tests/CMakeLists.txt b/libzeth/tests/CMakeLists.txt index f7801f3de..cac2df908 100644 --- a/libzeth/tests/CMakeLists.txt +++ b/libzeth/tests/CMakeLists.txt @@ -5,6 +5,8 @@ include(CTest) # A target which builds all tests, even if they will not be run. add_custom_target(build_tests) +find_package(Boost REQUIRED COMPONENTS system filesystem) + # Function to create test targets, based on the FAST flag: # # zeth_test( diff --git a/libzeth/tests/circuits/binary_operation_test.cpp b/libzeth/tests/circuits/binary_operation_test.cpp index 5a6911b27..acae1058b 100644 --- a/libzeth/tests/circuits/binary_operation_test.cpp +++ b/libzeth/tests/circuits/binary_operation_test.cpp @@ -21,27 +21,26 @@ namespace TEST(TestXOR, TestTrue) { libsnark::protoboard pb; - libsnark::pb_variable ZERO; - ZERO.allocate(pb, "zero"); - pb.val(ZERO) = Field::zero(); - libsnark::pb_variable_array a = variable_array_from_bit_vector( + libsnark::pb_variable_array a = pb_variable_array_from_bit_vector( + pb, { 0, 0, 0, 0, 1, 1, 1, 1, // 0F 0, 1, 0, 1, 0, 1, 0, 1, // 55 1, 0, 1, 0, 1, 0, 1, 0, // AA 1, 1, 1, 1, 0, 0, 0, 0 // F0 }, - ZERO); + "a"); - libsnark::pb_variable_array b = variable_array_from_bit_vector( + libsnark::pb_variable_array b = pb_variable_array_from_bit_vector( + pb, { 1, 1, 1, 1, 0, 0, 0, 0, // F0 1, 0, 1, 0, 1, 0, 1, 0, // AA 1, 0, 1, 0, 1, 0, 1, 0, // AA 1, 1, 1, 1, 0, 0, 0, 0 // F0 }, - ZERO); + "b"); libsnark::pb_variable_array xored; xored.allocate(pb, 32, "xored"); @@ -51,14 +50,15 @@ TEST(TestXOR, TestTrue) xor_gadget.generate_r1cs_witness(); libsnark::pb_variable_array expected = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, { 1, 1, 1, 1, 1, 1, 1, 1, // FF 1, 1, 1, 1, 1, 1, 1, 1, // FF 0, 0, 0, 0, 0, 0, 0, 0, // 00 0, 0, 0, 0, 0, 0, 0, 0 // 00 }, - ZERO); + "expected"); ASSERT_EQ(expected.get_bits(pb), xored.get_bits(pb)); } @@ -66,27 +66,26 @@ TEST(TestXOR, TestTrue) TEST(TestXORConstant, TestTrue) { libsnark::protoboard pb; - libsnark::pb_variable ZERO; - ZERO.allocate(pb, "zero"); - pb.val(ZERO) = Field::zero(); - libsnark::pb_variable_array a = variable_array_from_bit_vector( + libsnark::pb_variable_array a = pb_variable_array_from_bit_vector( + pb, { 0, 0, 0, 0, 1, 1, 1, 1, // 0F 0, 1, 0, 1, 0, 1, 0, 1, // 55 1, 0, 1, 0, 1, 0, 1, 0, // AA 1, 1, 1, 1, 0, 0, 0, 0 // F0 }, - ZERO); + "a"); - libsnark::pb_variable_array b = variable_array_from_bit_vector( + libsnark::pb_variable_array b = pb_variable_array_from_bit_vector( + pb, { 1, 1, 1, 1, 0, 0, 0, 0, // F0 1, 0, 1, 0, 1, 0, 1, 0, // AA 1, 0, 1, 0, 1, 0, 1, 0, // AA 1, 1, 1, 1, 0, 0, 0, 0 // F0 }, - ZERO); + "b"); std::vector c = { 0, 0, 0, 0, 1, 1, 1, 1, // 0F @@ -103,14 +102,15 @@ TEST(TestXORConstant, TestTrue) xor_c_gadget.generate_r1cs_witness(); libsnark::pb_variable_array expected = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, { 1, 1, 1, 1, 0, 0, 0, 0, // F0 0, 0, 0, 0, 1, 1, 1, 1, // 0F 0, 0, 0, 0, 0, 0, 0, 0, // 00 1, 0, 1, 0, 1, 0, 1, 0 // AA }, - ZERO); + "expected"); ASSERT_EQ(expected.get_bits(pb), xored.get_bits(pb)); } @@ -118,27 +118,26 @@ TEST(TestXORConstant, TestTrue) TEST(Testxor_rot, TestTrue) { libsnark::protoboard pb; - libsnark::pb_variable ZERO; - ZERO.allocate(pb, "zero"); - pb.val(ZERO) = Field::zero(); - libsnark::pb_variable_array a = variable_array_from_bit_vector( + libsnark::pb_variable_array a = pb_variable_array_from_bit_vector( + pb, { 0, 0, 0, 0, 1, 1, 1, 1, // 0F 0, 1, 0, 1, 0, 1, 0, 1, // 55 1, 0, 1, 0, 1, 0, 1, 0, // AA 1, 1, 1, 1, 0, 0, 0, 0 // F0 }, - ZERO); + "a"); - libsnark::pb_variable_array b = variable_array_from_bit_vector( + libsnark::pb_variable_array b = pb_variable_array_from_bit_vector( + pb, { 1, 1, 1, 1, 0, 0, 0, 0, // F0 1, 0, 1, 0, 1, 0, 1, 0, // AA 1, 0, 1, 0, 1, 0, 1, 0, // AA 1, 1, 1, 1, 0, 0, 0, 0 // F0 }, - ZERO); + "b"); libsnark::pb_variable_array rot0; rot0.allocate(pb, 32, "rot0"); @@ -176,44 +175,48 @@ TEST(Testxor_rot, TestTrue) xor_rot32_gadget.generate_r1cs_witness(); libsnark::pb_variable_array expected0 = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, { 1, 1, 1, 1, 1, 1, 1, 1, // FF 1, 1, 1, 1, 1, 1, 1, 1, // FF 0, 0, 0, 0, 0, 0, 0, 0, // 00 0, 0, 0, 0, 0, 0, 0, 0 // 00 }, - ZERO); + "expected0"); libsnark::pb_variable_array expected8 = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, { 0, 0, 0, 0, 0, 0, 0, 0, // 00 1, 1, 1, 1, 1, 1, 1, 1, // FF 1, 1, 1, 1, 1, 1, 1, 1, // FF 0, 0, 0, 0, 0, 0, 0, 0 // 00 }, - ZERO); + "expected8"); libsnark::pb_variable_array expected16 = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, { 0, 0, 0, 0, 0, 0, 0, 0, // 00 0, 0, 0, 0, 0, 0, 0, 0, // 00 1, 1, 1, 1, 1, 1, 1, 1, // FF 1, 1, 1, 1, 1, 1, 1, 1 // FF }, - ZERO); + "expected16"); libsnark::pb_variable_array expected24 = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, { 1, 1, 1, 1, 1, 1, 1, 1, // FF 0, 0, 0, 0, 0, 0, 0, 0, // 00 0, 0, 0, 0, 0, 0, 0, 0, // 00 1, 1, 1, 1, 1, 1, 1, 1 // FF }, - ZERO); + "expected24"); ASSERT_EQ(expected0.get_bits(pb), rot0.get_bits(pb)); ASSERT_EQ(expected8.get_bits(pb), rot8.get_bits(pb)); @@ -225,27 +228,26 @@ TEST(Testxor_rot, TestTrue) TEST(Testdouble_packed, TestTrue) { libsnark::protoboard pb; - libsnark::pb_variable ZERO; - ZERO.allocate(pb, "zero"); - pb.val(ZERO) = Field::zero(); - libsnark::pb_variable_array a = variable_array_from_bit_vector( + libsnark::pb_variable_array a = pb_variable_array_from_bit_vector( + pb, { 1, 0, 0, 0, 1, 1, 1, 1, // 8F 0, 1, 0, 1, 0, 1, 0, 1, // 55 1, 0, 1, 0, 1, 0, 1, 0, // AA 1, 1, 1, 1, 0, 0, 0, 0 // F0 }, - ZERO); + "a"); - libsnark::pb_variable_array b = variable_array_from_bit_vector( + libsnark::pb_variable_array b = pb_variable_array_from_bit_vector( + pb, { 1, 1, 1, 1, 0, 0, 0, 0, // F0 1, 0, 1, 0, 1, 0, 1, 0, // AA 1, 0, 1, 0, 1, 0, 1, 0, // AA 1, 1, 1, 1, 0, 0, 0, 0 // F0 }, - ZERO); + "b"); libsnark::pb_variable_array add; add.allocate(pb, 32, "add"); @@ -255,14 +257,15 @@ TEST(Testdouble_packed, TestTrue) add_mod32_gadget.generate_r1cs_witness(); libsnark::pb_variable_array expected = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, { 1, 0, 0, 0, 0, 0, 0, 0, // 80 0, 0, 0, 0, 0, 0, 0, 0, // 00 0, 1, 0, 1, 0, 1, 0, 1, // 55 1, 1, 1, 0, 0, 0, 0, 0 // E0 }, - ZERO); + "expected"); ASSERT_EQ(expected.get_bits(pb), add.get_bits(pb)); } diff --git a/libzeth/tests/circuits/blake2s_test.cpp b/libzeth/tests/circuits/blake2s_test.cpp index f96b561de..bf027e2d6 100644 --- a/libzeth/tests/circuits/blake2s_test.cpp +++ b/libzeth/tests/circuits/blake2s_test.cpp @@ -30,65 +30,67 @@ TEST(TestG, TestTrue) { libsnark::protoboard pb; - libsnark::pb_variable ZERO; - ZERO.allocate(pb, "zero"); - pb.val(ZERO) = Field::zero(); - - libsnark::pb_variable_array a = variable_array_from_bit_vector( + libsnark::pb_variable_array a = pb_variable_array_from_bit_vector( + pb, { 0, 1, 1, 0, 1, 0, 1, 1, // 6B 0, 0, 0, 0, 1, 0, 0, 0, // 08 1, 1, 1, 0, 0, 1, 1, 0, // E6 0, 1, 0, 0, 0, 1, 1, 1 // 47 }, - ZERO); + "a"); - libsnark::pb_variable_array b = variable_array_from_bit_vector( + libsnark::pb_variable_array b = pb_variable_array_from_bit_vector( + pb, { 0, 1, 0, 1, 0, 0, 0, 1, // 51 0, 0, 0, 0, 1, 1, 1, 0, // 0E 0, 1, 0, 1, 0, 0, 1, 0, // 52 0, 1, 1, 1, 1, 1, 1, 1 // 7F }, - ZERO); + "b"); - libsnark::pb_variable_array c = variable_array_from_bit_vector( + libsnark::pb_variable_array c = pb_variable_array_from_bit_vector( + pb, { 0, 1, 1, 0, 1, 0, 1, 0, // 6A 0, 0, 0, 0, 1, 0, 0, 1, // 09 1, 1, 1, 0, 0, 1, 1, 0, // E6 0, 1, 1, 0, 0, 1, 1, 1 // 67 }, - ZERO); + "c"); - libsnark::pb_variable_array d = variable_array_from_bit_vector( + libsnark::pb_variable_array d = pb_variable_array_from_bit_vector( + pb, { 0, 1, 0, 1, 0, 0, 0, 1, // 51 0, 0, 0, 0, 1, 1, 1, 0, // 0E 0, 1, 0, 1, 0, 0, 1, 0, // 52 0, 1, 1, 1, 0, 1, 0, 0 // 74 }, - ZERO); + "d"); // First word in little endian "lleh" - libsnark::pb_variable_array x = variable_array_from_bit_vector( + libsnark::pb_variable_array x = pb_variable_array_from_bit_vector( + pb, { 0, 1, 1, 0, 1, 1, 0, 0, // 6C 0, 1, 1, 0, 1, 1, 0, 0, // 6C 0, 1, 1, 0, 0, 1, 0, 1, // 65 0, 1, 1, 0, 1, 0, 0, 0 // 68 }, - ZERO); + "x"); // Second word in little endian "ow o" - libsnark::pb_variable_array y = variable_array_from_bit_vector( + libsnark::pb_variable_array y = pb_variable_array_from_bit_vector( + pb, { 0, 1, 1, 0, 1, 1, 1, 1, // 6F 0, 1, 1, 1, 0, 1, 1, 1, // 77 0, 0, 1, 0, 0, 0, 0, 0, // 20 0, 1, 1, 0, 1, 1, 1, 1 // 6F }, - ZERO); + "y"); libsnark::pb_variable_array a2; a2.allocate(pb, BLAKE2s_word_size, "a2"); @@ -107,44 +109,48 @@ TEST(TestG, TestTrue) g_gadget.generate_r1cs_witness(); libsnark::pb_variable_array a2_expected = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, { 0, 1, 1, 1, 0, 0, 0, 0, // 70 1, 0, 1, 1, 0, 0, 0, 1, // B1 0, 0, 1, 1, 0, 1, 0, 1, // 35 0, 0, 1, 1, 1, 1, 0, 1 // 3D }, - ZERO); + "a2_expected"); libsnark::pb_variable_array b2_expected = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, { 1, 1, 0, 0, 0, 0, 0, 0, // C0 0, 1, 1, 1, 1, 1, 1, 1, // 7F 0, 0, 1, 0, 1, 1, 1, 0, // 2E 0, 1, 1, 1, 1, 0, 1, 1 // 7B }, - ZERO); + "b2_expected"); libsnark::pb_variable_array c2_expected = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, { 1, 1, 1, 0, 0, 1, 1, 1, // E7 0, 0, 1, 0, 0, 0, 0, 1, // 21 0, 1, 0, 0, 1, 0, 1, 1, // 4B 0, 1, 0, 0, 0, 0, 0, 0 // 40 }, - ZERO); + "c2_expected"); libsnark::pb_variable_array d2_expected = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, { 1, 0, 1, 1, 0, 0, 0, 0, // B0 1, 0, 1, 1, 1, 1, 0, 0, // BC 1, 1, 1, 0, 1, 0, 1, 1, // EB 0, 1, 0, 0, 1, 1, 0, 0 // 4C }, - ZERO); + "d2_expected"); ASSERT_EQ(a2_expected.get_bits(pb), a2.get_bits(pb)); ASSERT_EQ(b2_expected.get_bits(pb), b2.get_bits(pb)); @@ -164,7 +170,8 @@ TEST(TestBlake2sComp, TestTrue) // b"hello world" in big endian libsnark::pb_variable_array pb_var_input = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, { 0, 1, 1, 0, 1, 0, 0, 0, // 68 0, 1, 1, 0, 0, 1, 0, 1, // 65 @@ -187,14 +194,15 @@ TEST(TestBlake2sComp, TestTrue) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - ZERO); + "pb_var_input"); libsnark::block_variable input( pb, {pb_var_input}, "blake2s_block_input"); // default chaining value libsnark::pb_variable_array pb_var_h = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, {0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, @@ -207,7 +215,7 @@ TEST(TestBlake2sComp, TestTrue) 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1}, - ZERO); + "pb_var_h"); libsnark::digest_variable h( pb, BLAKE2s_digest_size, pb_var_h, ZERO, "blake2s_h"); @@ -219,7 +227,8 @@ TEST(TestBlake2sComp, TestTrue) // blake2s(b"hello world") libsnark::pb_variable_array expected = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, { 1, 0, 0, 1, 1, 0, 1, 0, // 9A 1, 1, 1, 0, 1, 1, 0, 0, // EC @@ -254,7 +263,7 @@ TEST(TestBlake2sComp, TestTrue) 0, 0, 1, 1, 1, 0, 1, 1, // 3B 0, 0, 0, 0, 1, 0, 1, 1 // 0B }, - ZERO); + "expected"); ASSERT_EQ(expected.get_bits(pb), output.bits.get_bits(pb)); } @@ -271,7 +280,8 @@ TEST(TestBlake2s, TestTrue) // b"hello world" in big endian libsnark::pb_variable_array pb_var_input = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, { 0, 1, 1, 0, 1, 0, 0, 0, // 68 0, 1, 1, 0, 0, 1, 0, 1, // 65 @@ -285,7 +295,7 @@ TEST(TestBlake2s, TestTrue) 0, 1, 1, 0, 1, 1, 0, 0, // 6C 0, 1, 1, 0, 0, 1, 0, 0 // 64 }, - ZERO); + "pb_var_input"); libsnark::block_variable input( pb, {pb_var_input}, "blake2s_block_input"); @@ -298,7 +308,8 @@ TEST(TestBlake2s, TestTrue) // blake2s(b"hello world") libsnark::pb_variable_array expected = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, { 1, 0, 0, 1, 1, 0, 1, 0, // 9A 1, 1, 1, 0, 1, 1, 0, 0, // EC @@ -333,7 +344,7 @@ TEST(TestBlake2s, TestTrue) 0, 0, 1, 1, 1, 0, 1, 1, // 3B 0, 0, 0, 0, 1, 0, 1, 1 // 0B }, - ZERO); + "expected"); ASSERT_EQ(expected.get_bits(pb), output.bits.get_bits(pb)); } @@ -349,142 +360,141 @@ TEST(TestBlake2s, TestTrue2) pb.val(ZERO) = Field::zero(); // b"zeth" in big endian - libsnark::pb_variable_array pb_var_input = - variable_array_from_bit_vector( - { - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0, // 68 - 0, 1, 1, 1, 1, 0, 1, 0, // 7A - 0, 1, 1, 0, 0, 1, 0, 1, // 65 - 0, 1, 1, 1, 0, 1, 0, 0, // 74 - 0, 1, 1, 0, 1, 0, 0, 0 // 68 - }, - ZERO); + const std::vector input_bits = { + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0, // 68 + 0, 1, 1, 1, 1, 0, 1, 0, // 7A + 0, 1, 1, 0, 0, 1, 0, 1, // 65 + 0, 1, 1, 1, 0, 1, 0, 0, // 74 + 0, 1, 1, 0, 1, 0, 0, 0 // 68 + }; + libsnark::pb_variable_array input_vars = + pb_variable_array_from_bit_vector(pb, input_bits, "input_vars"); libsnark::block_variable input( - pb, {pb_var_input}, "blake2s_block_input"); + pb, {input_vars}, "blake2s_block_input"); libsnark::digest_variable output(pb, BLAKE2s_digest_size, "output"); @@ -497,6 +507,7 @@ TEST(TestBlake2s, TestTrue2) "b5f199b422df36c99363725d886e64c07ffd8852063adbbfbb86f43716ffab0e"); ASSERT_EQ(expected.to_vector(), output.bits.get_bits(pb)); + ASSERT_EQ(expected.to_vector(), BLAKE2s_256::get_hash(input_bits)); } } // namespace diff --git a/libzeth/tests/circuits/prfs_test.cpp b/libzeth/tests/circuits/prfs_test.cpp index 670b5527a..0e9f61cec 100644 --- a/libzeth/tests/circuits/prfs_test.cpp +++ b/libzeth/tests/circuits/prfs_test.cpp @@ -31,7 +31,8 @@ TEST(TestPRFs, TestGenZeroes) pb.val(ZERO) = Field::zero(); libsnark::pb_variable_array zeroes256 = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, { 0, 0, 0, 0, 0, 0, 0, 0, // 0, 0, 0, 0, 0, 0, 0, 0, // @@ -66,12 +67,12 @@ TEST(TestPRFs, TestGenZeroes) 0, 0, 0, 0, 0, 0, 0, 0, // 0, 0, 0, 0, 0, 0, 0, 0, // }, - ZERO); + "zeroes256"); libsnark::pb_variable_array result = gen_256_zeroes(ZERO); ASSERT_EQ(result.get_bits(pb), zeroes256.get_bits(pb)); -}; +} TEST(TestPRFs, TestPRFAddrApkGadget) { @@ -82,7 +83,8 @@ TEST(TestPRFs, TestPRFAddrApkGadget) // a_sk corresponds to the number: // 0x0F000000000000FF00000000000000FF00000000000000FF00000000000000FF - libsnark::pb_variable_array a_sk = variable_array_from_bit_vector( + libsnark::pb_variable_array a_sk = pb_variable_array_from_bit_vector( + pb, { 0, 0, 0, 0, 1, 1, 1, 1, // 0F 0, 0, 0, 0, 0, 0, 0, 0, // 00 @@ -117,7 +119,7 @@ TEST(TestPRFs, TestPRFAddrApkGadget) 0, 0, 0, 0, 0, 0, 0, 0, // 00 1, 1, 1, 1, 1, 1, 1, 1 // FF }, - ZERO); + "a_sk"); // a_pk should equal: // 0x208f95ee37621c3c2d9c74be39bf687c47e84c679b88df270858067c08a16daf Since @@ -131,10 +133,11 @@ TEST(TestPRFs, TestPRFAddrApkGadget) // function Note: (we want to make sure that we generate the same digests // both on-chain and off-chain) libsnark::pb_variable_array a_pk_expected = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, bit_vector_from_hex("2390c9e5370be7355f220b29caf3912ef970d828b73976" "ae9bfeb1402ce4c1f9"), - ZERO); + "a_pk_expected"); std::shared_ptr> result( new digest_variable(pb, Hash::get_digest_len(), "result")); @@ -146,7 +149,7 @@ TEST(TestPRFs, TestPRFAddrApkGadget) bool is_valid_witness = pb.is_satisfied(); ASSERT_TRUE(is_valid_witness); ASSERT_EQ(result->get_digest(), a_pk_expected.get_bits(pb)); -}; +} TEST(TestPRFs, TestPRFNFGadget) { @@ -157,7 +160,8 @@ TEST(TestPRFs, TestPRFNFGadget) // a_sk corresponds to the number: // 0x0F000000000000FF00000000000000FF00000000000000FF00000000000000FF - libsnark::pb_variable_array a_sk = variable_array_from_bit_vector( + libsnark::pb_variable_array a_sk = pb_variable_array_from_bit_vector( + pb, { 0, 0, 0, 0, 1, 1, 1, 1, // 0F 0, 0, 0, 0, 0, 0, 0, 0, // 00 @@ -192,10 +196,11 @@ TEST(TestPRFs, TestPRFNFGadget) 0, 0, 0, 0, 0, 0, 0, 0, // 00 1, 1, 1, 1, 1, 1, 1, 1 // FF }, - ZERO); + "a_sk"); // hex: 0x0F000000000000FF00000000000000FF00000000000000FF00000000000000FF - libsnark::pb_variable_array rho = variable_array_from_bit_vector( + libsnark::pb_variable_array rho = pb_variable_array_from_bit_vector( + pb, { 0, 0, 0, 0, 1, 1, 1, 1, // 0F 0, 0, 0, 0, 0, 0, 0, 0, // @@ -230,7 +235,7 @@ TEST(TestPRFs, TestPRFNFGadget) 0, 0, 0, 0, 0, 0, 0, 0, // 1, 1, 1, 1, 1, 1, 1, 1 // FF }, - ZERO); + "rho"); // nf should equal: // 4a5f4f585dda39cc597366f9172bae924d22e832487e12e76742dbab9393b620 @@ -243,10 +248,11 @@ TEST(TestPRFs, TestPRFNFGadget) // blake2s function (we want to make sure that we generate the same digests // both on-chain and off-chain) libsnark::pb_variable_array nf_expected = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, bit_vector_from_hex("ea43866d185e1bdb84713b699a2966d929d1392488c010" "c603e46a4cb92986f8"), - ZERO); + "nf_expected"); std::shared_ptr> result( new digest_variable(pb, Hash::get_digest_len(), "result")); @@ -259,7 +265,7 @@ TEST(TestPRFs, TestPRFNFGadget) bool is_valid_witness = pb.is_satisfied(); ASSERT_TRUE(is_valid_witness); ASSERT_EQ(result->get_digest(), nf_expected.get_bits(pb)); -}; +} TEST(TestPRFs, TestPRFPKGadget) { @@ -270,7 +276,8 @@ TEST(TestPRFs, TestPRFPKGadget) // a_sk corresponds to the number: // 0x0F000000000000FF00000000000000FF00000000000000FF00000000000000FF - libsnark::pb_variable_array a_sk = variable_array_from_bit_vector( + libsnark::pb_variable_array a_sk = pb_variable_array_from_bit_vector( + pb, { 0, 0, 0, 0, 1, 1, 1, 1, // 0F 0, 0, 0, 0, 0, 0, 0, 0, // 00 @@ -305,10 +312,11 @@ TEST(TestPRFs, TestPRFPKGadget) 0, 0, 0, 0, 0, 0, 0, 0, // 00 1, 1, 1, 1, 1, 1, 1, 1 // FF }, - ZERO); + "a_sk"); // h_sig: 0x0F000000000000FF00000000000000FF00000000000000FF00000000000000FF - libsnark::pb_variable_array hsig = variable_array_from_bit_vector( + libsnark::pb_variable_array hsig = pb_variable_array_from_bit_vector( + pb, { 0, 0, 0, 0, 1, 1, 1, 1, // 0F 0, 0, 0, 0, 0, 0, 0, 0, // @@ -343,7 +351,7 @@ TEST(TestPRFs, TestPRFPKGadget) 0, 0, 0, 0, 0, 0, 0, 0, // 1, 1, 1, 1, 1, 1, 1, 1 // FF }, - ZERO); + "hsig"); // h_i should equal: // 7ea1525fdbf9462c5144796937e1f80b9dad42369f7d4987c436b2f79257f9ac h_i = @@ -356,10 +364,11 @@ TEST(TestPRFs, TestPRFPKGadget) // blake2s function (we want to make sure that we generate the same digests // both on-chain and off-chain) libsnark::pb_variable_array h_expected0 = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, bit_vector_from_hex("8527fb92081cf832659a188163287f98b8c919401ba619" "d6ebd30dc0f1aedeff"), - ZERO); + "h_expected0"); std::shared_ptr> result0( new digest_variable(pb, Hash::get_digest_len(), "result")); @@ -371,10 +380,11 @@ TEST(TestPRFs, TestPRFPKGadget) prf_pk_gadget0.generate_r1cs_witness(); libsnark::pb_variable_array h_expected1 = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, bit_vector_from_hex("aea510673ff50225bec4bd918c102ea0c9b117b9353464" "4ee70b74522b204b29"), - ZERO); + "h_expected1"); std::shared_ptr> result1( new digest_variable(pb, Hash::get_digest_len(), "result")); @@ -389,7 +399,7 @@ TEST(TestPRFs, TestPRFPKGadget) ASSERT_TRUE(is_valid_witness); ASSERT_EQ(result0->get_digest(), h_expected0.get_bits(pb)); ASSERT_EQ(result1->get_digest(), h_expected1.get_bits(pb)); -}; +} TEST(TestPRFs, TestPRFRhoGadget) { @@ -400,7 +410,8 @@ TEST(TestPRFs, TestPRFRhoGadget) // phi corresponds to the number: // 0x0F000000000000FF00000000000000FF00000000000000FF00000000000000FF - libsnark::pb_variable_array phi = variable_array_from_bit_vector( + libsnark::pb_variable_array phi = pb_variable_array_from_bit_vector( + pb, { 0, 0, 0, 0, 1, 1, 1, 1, // 0F 0, 0, 0, 0, 0, 0, 0, 0, // 00 @@ -435,10 +446,11 @@ TEST(TestPRFs, TestPRFRhoGadget) 0, 0, 0, 0, 0, 0, 0, 0, // 00 1, 1, 1, 1, 1, 1, 1, 1 // FF }, - ZERO); + "phi"); // hsig: 0x0F000000000000FF00000000000000FF00000000000000FF00000000000000FF - libsnark::pb_variable_array hsig = variable_array_from_bit_vector( + libsnark::pb_variable_array hsig = pb_variable_array_from_bit_vector( + pb, { 0, 0, 0, 0, 1, 1, 1, 1, // 0F 0, 0, 0, 0, 0, 0, 0, 0, // @@ -473,7 +485,7 @@ TEST(TestPRFs, TestPRFRhoGadget) 0, 0, 0, 0, 0, 0, 0, 0, // 1, 1, 1, 1, 1, 1, 1, 1 // FF }, - ZERO); + "hsig"); // rho should equal: // a87c47a6c721bdbbb4aa8875c2aa72d4db31b9526aa920656049e00786f7f8a4 @@ -484,10 +496,11 @@ TEST(TestPRFs, TestPRFRhoGadget) // function (we want to make sure that we generate the same digests both // on-chain and off-chain) libsnark::pb_variable_array rho_expected0 = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, bit_vector_from_hex("d7b7c4536bbba1aaca684706ba0df170af95515d573ad9" "3e30015e1c40ebc539"), - ZERO); + "rho_expected0"); std::shared_ptr> result0( new digest_variable(pb, Hash::get_digest_len(), "result")); @@ -499,10 +512,11 @@ TEST(TestPRFs, TestPRFRhoGadget) prf_rho_gadget0.generate_r1cs_witness(); libsnark::pb_variable_array rho_expected1 = - variable_array_from_bit_vector( + pb_variable_array_from_bit_vector( + pb, bit_vector_from_hex("bb17f6088e47a8b2ac8e3d57588d52fed63079dc2b7045" "561d6d5e7288384249"), - ZERO); + "rho_expected1"); std::shared_ptr> result1( new digest_variable(pb, Hash::get_digest_len(), "result")); @@ -517,7 +531,7 @@ TEST(TestPRFs, TestPRFRhoGadget) ASSERT_TRUE(is_valid_witness); ASSERT_EQ(result0->get_digest(), rho_expected0.get_bits(pb)); ASSERT_EQ(result1->get_digest(), rho_expected1.get_bits(pb)); -}; +} } // namespace diff --git a/libzeth/tests/circuits/sha256_test.cpp b/libzeth/tests/circuits/sha256_test.cpp index 9458188e9..143ed67f7 100644 --- a/libzeth/tests/circuits/sha256_test.cpp +++ b/libzeth/tests/circuits/sha256_test.cpp @@ -44,15 +44,6 @@ using HashT = libzeth::sha256_ethereum; namespace { -void dump_bit_vector(std::ostream &out, const libff::bit_vector &v) -{ - out << "{"; - for (size_t i = 0; i < v.size() - 1; ++i) { - out << v[i] << ", "; - } - out << v[v.size() - 1] << "}\n"; -} - TEST(TestSHA256, TestHash) { libsnark::protoboard pb; @@ -61,56 +52,54 @@ TEST(TestSHA256, TestHash) pb.val(ZERO) = Field::zero(); // hex: 0x0F000000000000FF00000000000000FF00000000000000FF00000000000000FF + const std::vector left_bits = { + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // + }; libsnark::pb_variable_array left = - libzeth::variable_array_from_bit_vector( - { - 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // - }, - ZERO); + libzeth::pb_variable_array_from_bit_vector(pb, left_bits, "left"); // hex: 0x43C000000000003FC00000000000003FC00000000000003FC00000000000003F + std::vector right_bits = { + 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, // + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, // + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, // + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, // + }; libsnark::pb_variable_array right = - libzeth::variable_array_from_bit_vector( - { - 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, // - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, // - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, // - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, // - }, - ZERO); + libzeth::pb_variable_array_from_bit_vector(pb, right_bits, "right"); libsnark::digest_variable result( pb, HashT::get_digest_len(), "result"); libsnark::block_variable input_block( pb, {left, right}, "Block_variable"); - libzeth::sha256_ethereum hasher(pb, ZERO, input_block, result); + libzeth::sha256_ethereum hasher(pb, input_block, result); // result should equal: // 0xa4cc8f23d1dfeab58d7af00b3422f22dd60b9c608af5f30744073653236562c3 Since @@ -123,11 +112,13 @@ TEST(TestSHA256, TestHash) // Note: This test vector has been generated by using the solidity sha256 // function (we want to make sure that we generate the same digests both // on-chain and off-chain) Solidity version v0.5.0 - std::string test_vector_res_str = + const std::string expected_hex = "a4cc8f23d1dfeab58d7af00b3422f22dd60b9c608af5f30744073653236562c3"; - libsnark::pb_variable_array expected = - libzeth::variable_array_from_bit_vector( - libzeth::bit_vector_from_hex(test_vector_res_str), ZERO); + const std::vector expected_bits = + libzeth::bit_vector_from_hex(expected_hex); + const libsnark::pb_variable_array expected = + libzeth::pb_variable_array_from_bit_vector( + pb, expected_bits, "expected"); hasher.generate_r1cs_constraints(true); hasher.generate_r1cs_witness(); @@ -135,14 +126,14 @@ TEST(TestSHA256, TestHash) bool is_valid_witness = pb.is_satisfied(); ASSERT_TRUE(is_valid_witness); - std::ostream &stream = std::cout; - std::cout << " -- Result digest -- " << std::endl; - dump_bit_vector(stream, result.get_digest()); - std::cout << " -- Expected digest -- " << std::endl; - dump_bit_vector(stream, expected.get_bits(pb)); + ASSERT_EQ(expected.get_bits(pb), result.get_digest()); - ASSERT_EQ(result.get_digest(), expected.get_bits(pb)); -}; + std::vector input_bits = left_bits; + input_bits.insert(input_bits.end(), right_bits.begin(), right_bits.end()); + ASSERT_EQ( + expected.get_bits(pb), + libzeth::sha256_ethereum::get_hash(input_bits)); +} TEST(TestSHA256, TestHashWithZeroLeg) { @@ -180,7 +171,7 @@ TEST(TestSHA256, TestHashWithZeroLeg) pb, {left, right}, "Block_variable"); libzeth::sha256_ethereum hasher( - pb, ZERO, input_block, result, "Sha256_ethereum"); + pb, input_block, result, "sha256_ethereum"); hasher.generate_r1cs_constraints(true); hasher.generate_r1cs_witness(); @@ -188,18 +179,8 @@ TEST(TestSHA256, TestHashWithZeroLeg) bool is_valid_witness = pb.is_satisfied(); ASSERT_TRUE(is_valid_witness); - std::ostream &stream = std::cout; - std::cout << " -- left -- " << std::endl; - dump_bit_vector(stream, left.get_bits(pb)); - std::cout << " -- right -- " << std::endl; - dump_bit_vector(stream, right.get_bits(pb)); - std::cout << " -- Result digest -- " << std::endl; - dump_bit_vector(stream, result.get_digest()); - std::cout << " -- Expected digest -- " << std::endl; - dump_bit_vector(stream, expected_bits); - ASSERT_EQ(result.get_digest(), expected_bits); -}; +} } // namespace diff --git a/libzeth/tests/core/ec_operation_data_test.cpp b/libzeth/tests/core/ec_operation_data_test.cpp index a6d436eaa..6b35ab761 100644 --- a/libzeth/tests/core/ec_operation_data_test.cpp +++ b/libzeth/tests/core/ec_operation_data_test.cpp @@ -55,8 +55,7 @@ template void operation_test_data() std::stringstream binary_stream; std::cout << " Fr:"; - std::cout << "\n r: " - << bigint_to_hex>(libff::Fr::mod); + std::cout << "\n r: " << libff::bigint_to_hex(libff::Fr::mod); std::cout << "\n 1: "; field_element_write_json(fr_1, std::cout); @@ -69,8 +68,7 @@ template void operation_test_data() field_element_write_bytes(fr_minus_2, binary_stream); std::cout << " Fq:"; - std::cout << "\n q: " - << bigint_to_hex>(libff::Fq::mod); + std::cout << "\n q: " << libff::bigint_to_hex(libff::Fq::mod); std::cout << "\n G1:"; std::cout << "\n 1: "; diff --git a/libzeth/tests/core/field_element_utils_test.cpp b/libzeth/tests/core/field_element_utils_test.cpp index e8c7d0f98..77f0b8dcf 100644 --- a/libzeth/tests/core/field_element_utils_test.cpp +++ b/libzeth/tests/core/field_element_utils_test.cpp @@ -19,26 +19,6 @@ template libff::bigint dummy_bigint() return FieldT::random_element().as_bigint(); } -template void do_bigint_encode_decode_hex_test() -{ - const libff::bigint bi = dummy_bigint(); - const std::string bi_hex = libzeth::bigint_to_hex(bi); - const libff::bigint bi_decoded = - libzeth::bigint_from_hex(bi_hex); - std::cout << "bi_hex: " << bi_hex << std::endl; - std::cout << "bi_decoded_hex: " - << libzeth::bigint_to_hex(bi_decoded) << std::endl; - - ASSERT_EQ(2 * sizeof(bi.data), bi_hex.size()); - ASSERT_EQ(bi, bi_decoded); -} - -template void bigint_encode_decode_hex_test() -{ - do_bigint_encode_decode_hex_test>(); - do_bigint_encode_decode_hex_test>(); -} - template void do_base_field_element_encode_decode_hex_test() { const FieldT fe = FieldT::random_element(); @@ -148,15 +128,6 @@ template void field_element_read_write_bytes_test() do_field_element_read_write_bytes_test>(); } -TEST(FieldElementUtilsTest, BigIntEncodeDecodeHex) -{ - bigint_encode_decode_hex_test(); - bigint_encode_decode_hex_test(); - bigint_encode_decode_hex_test(); - bigint_encode_decode_hex_test(); - bigint_encode_decode_hex_test(); -} - TEST(FieldElementUtilsTest, BaseFieldElementEncodeDecodeHex) { base_field_element_encode_decode_hex_test(); diff --git a/libzeth/tests/mpc/groth16/mpc_test.cpp b/libzeth/tests/mpc/groth16/mpc_test.cpp index 2dfc22943..e7aacaa09 100644 --- a/libzeth/tests/mpc/groth16/mpc_test.cpp +++ b/libzeth/tests/mpc/groth16/mpc_test.cpp @@ -6,7 +6,6 @@ #include "libzeth/circuits/sha256/sha256_ethereum.hpp" #include "libzeth/core/chacha_rng.hpp" #include "libzeth/core/evaluator_from_lagrange.hpp" -#include "libzeth/core/multi_exp.hpp" #include "libzeth/core/utils.hpp" #include "libzeth/mpc/groth16/mpc_utils.hpp" #include "libzeth/mpc/groth16/phase2.hpp" @@ -256,13 +255,15 @@ TEST(MPCTests, Layer2) srs_mpc_phase2_accumulator phase2 = srs_mpc_dummy_phase2(lin_comb, delta, num_inputs).accumulator; - // final keypair - const r1cs_gg_ppzksnark_keypair keypair = mpc_create_key_pair( - std::move(pot), - std::move(lin_comb), - std::move(phase2), - std::move(constraint_system), - qap); + // final keypair (in special-form since it will be used directly, and not + // serialized) + r1cs_gg_ppzksnark_keypair keypair = + mpc_create_key_pair( + std::move(pot), + std::move(lin_comb), + std::move(phase2), + std::move(constraint_system), + qap); // Compare against directly computed values { diff --git a/libzeth/tests/serialization/r1cs_variable_assignment_serialization_test.cpp b/libzeth/tests/serialization/r1cs_variable_assignment_serialization_test.cpp index 715e0c661..369b6f83e 100644 --- a/libzeth/tests/serialization/r1cs_variable_assignment_serialization_test.cpp +++ b/libzeth/tests/serialization/r1cs_variable_assignment_serialization_test.cpp @@ -22,13 +22,19 @@ template bool test_r1cs_variable_assignment_read_write_bytes() for (size_t i = 0; i < assignment_size; ++i) { assignment.push_back(FieldT::random_element()); } + const libsnark::r1cs_primary_input primary( + assignment.begin(), assignment.begin() + primary_size); + const libsnark::r1cs_auxiliary_input auxiliary( + assignment.begin() + primary_size, assignment.end()); + // Write as full assignment std::string buffer = ([&assignment]() { std::stringstream ss; libzeth::r1cs_variable_assignment_write_bytes(assignment, ss); return ss.str(); })(); + // Read as full assignment libsnark::r1cs_variable_assignment assignment2; { std::stringstream ss(buffer); @@ -39,7 +45,7 @@ template bool test_r1cs_variable_assignment_read_write_bytes() return false; } - // Write as separate primary and auxiliary iputs + // Write as separate primary and auxiliary inputs buffer = ([&assignment]() { std::stringstream ss; libzeth::r1cs_variable_assignment_write_bytes( @@ -51,12 +57,31 @@ template bool test_r1cs_variable_assignment_read_write_bytes() return ss.str(); })(); + // Read back as full assignment { std::stringstream ss(buffer); libzeth::r1cs_variable_assignment_read_bytes(assignment2, ss); } - return assignment == assignment2; + if (assignment != assignment2) { + return false; + } + + // Read as separate primary in auxiliary + libsnark::r1cs_primary_input primary2; + libsnark::r1cs_auxiliary_input auxiliary2; + { + std::stringstream ss(buffer); + libzeth::r1cs_variable_assignment_read_bytes( + primary2, auxiliary2, primary_size, ss); + } + + if (primary2 != primary || auxiliary2 != auxiliary) { + return false; + } + + // Passed + return true; } TEST(R1CSVariableAssignementSerializationTest, AssignmentReadWriteBytes) diff --git a/libzeth/tests/snarks/groth16/groth16_snark_test.cpp b/libzeth/tests/snarks/groth16/groth16_snark_test.cpp index 92db02c06..9e58fe334 100644 --- a/libzeth/tests/snarks/groth16/groth16_snark_test.cpp +++ b/libzeth/tests/snarks/groth16/groth16_snark_test.cpp @@ -81,7 +81,7 @@ template void generate_test_data() // Proving key const typename groth16::proving_key pk( - G1::one(), // alpha_g1 = [1]_1 + G1(G1::one()), // alpha_g1 = [1]_1 -G1::one(), // beta_g1 = [-1]_1 -G2::one(), // beta_g2 = [-1]_2 -(G1::one() + G1::one()), // beta_g1 = [-2]_1 diff --git a/mpc/setup.py b/mpc/setup.py index 2965dc6dc..74e93c00a 100644 --- a/mpc/setup.py +++ b/mpc/setup.py @@ -20,7 +20,7 @@ setup( name='coordinator', - version='0.7', + version='0.8', description='MPC Coordinator for Zeth SRS', packages=find_packages(), install_requires=[ diff --git a/mpc_tools/mpc_phase2/CMakeLists.txt b/mpc_tools/mpc_phase2/CMakeLists.txt index 6acadb2f2..c37db77de 100644 --- a/mpc_tools/mpc_phase2/CMakeLists.txt +++ b/mpc_tools/mpc_phase2/CMakeLists.txt @@ -16,6 +16,7 @@ target_include_directories(mpc-cli PUBLIC cli) target_link_libraries( mpc-cli zeth + tool ${Boost_SYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ) diff --git a/mpc_tools/mpc_phase2/cli/mpc_common.cpp b/mpc_tools/mpc_phase2/cli/mpc_common.cpp index bfbcf4709..c006f2bc8 100644 --- a/mpc_tools/mpc_phase2/cli/mpc_common.cpp +++ b/mpc_tools/mpc_phase2/cli/mpc_common.cpp @@ -4,176 +4,51 @@ #include "mpc_common.hpp" -#include - -namespace po = boost::program_options; - -subcommand::subcommand( - const std::string &subcommand_name, const std::string &description) - : subcommand_name(subcommand_name) - , subcommand_description(description) - , verbose(false) - , help(false) -{ -} - -void subcommand::set_global_options( - bool verbose, const ProtoboardInitFn &pb_init) -{ - this->verbose = verbose; - this->protoboard_init = pb_init; -} - -int subcommand::execute(const std::vector &args) -{ - po::options_description options_desc("Options"); - po::options_description all_options_desc(""); - po::positional_options_description positional_options_desc; - - try { - options_desc.add_options()("help,h", "This help"), - initialize_suboptions( - options_desc, all_options_desc, positional_options_desc); - - po::variables_map vm; - po::parsed_options parsed = - po::command_line_parser( - std::vector(args.begin() + 1, args.end())) - .options(all_options_desc) - .positional(positional_options_desc) - .run(); - po::store(parsed, vm); - parse_suboptions(vm); +#include "libtool/run.hpp" - if (vm.count("help")) { - help = true; - usage(options_desc); - return 0; - } - } catch (po::error &error) { - std::cerr << " ERROR: " << error.what() << std::endl; - usage(options_desc); - return 1; - } - - // Execute and handle errors - try { - return execute_subcommand(); - } catch (std::invalid_argument &error) { - std::cerr << " ERROR: " << error.what() << std::endl; - return 1; - } -} - -const std::string &subcommand::description() const -{ - return subcommand_description; -} - -void subcommand::init_protoboard(libsnark::protoboard &pb) const -{ - protoboard_init(pb); -} +#include -void subcommand::usage(const po::options_description &options) +namespace { - subcommand_usage(); - std::cout << description() << "\n\n"; - std::cout << options << std::endl; -} -void list_commands(const std::map &commands) +/// Instantiation of libtool::command which parses the global options for all +/// mpc subcommands. +class mpc_command : public libtool::command { - using entry_t = std::pair; - const size_t cmd_name_padded = - 4 + std::max_element( - commands.begin(), - commands.end(), - [](const entry_t &a, const entry_t &b) { - return a.first.size() < b.first.size(); - }) - ->first.size(); - - for (const auto &cmd : commands) { - const size_t padding = cmd_name_padded - cmd.first.size(); - std::cout << " " << cmd.first << std::string(padding, ' ') - << cmd.second->description() << "\n"; +public: + void initialize_global_options( + boost::program_options::options_description &global, + boost::program_options::options_description &all_options) override + { + global.add_options()("verbose,v", "Verbose output"); + all_options.add(global); } -} - -int mpc_main( - int argc, - char **argv, - const std::map &commands, - const ProtoboardInitFn &pb_init) -{ - libzeth::defaults::pp::init_public_params(); - po::options_description global("Global options"); - global.add_options()("help,h", "This help")("verbose,v", "Verbose output"); - - po::options_description all(""); - all.add(global).add_options()( - "command", po::value(), "Command to execute")( - "subargs", - po::value>(), - "Arguments to command"); - - po::positional_options_description pos; - pos.add("command", 1).add("subargs", -1); - - auto usage = [&argv, &global, &commands]() { - std::cout << "Usage:\n" - << " " << argv[0] - << " [] ...\n\n" - << global; - - std::cout << "\nCommands:\n"; - list_commands(commands); - std::cout << std::endl; - }; - - try { - po::variables_map vm; - po::parsed_options parsed = po::command_line_parser(argc, argv) - .options(all) - .positional(pos) - .allow_unregistered() - .run(); - po::store(parsed, vm); - - if (vm.count("help")) { - usage(); - return 0; - } + void parse_global_options( + global_options &out_options, + const boost::program_options::variables_map &vm) override + { const bool verbose = (bool)vm.count("verbose"); if (!verbose) { libff::inhibit_profiling_info = true; libff::inhibit_profiling_counters = true; } - if (0 == vm.count("command")) { - std::cerr << "error: no command specified\n"; - usage(); - return 1; - } - - const std::string command(vm["command"].as()); - std::vector subargs = - po::collect_unrecognized(parsed.options, po::include_positional); - subargs[0] = std::string(argv[0]) + " " + subargs[0]; + out_options.verbose = verbose; + } +}; - subcommand *sub = commands.find(command)->second; - if (sub == nullptr) { - throw po::error("invalid command"); - } +} // namespace - sub->set_global_options(verbose, pb_init); - return sub->execute(subargs); - } catch (po::error &error) { - std::cerr << " ERROR: " << error.what() << std::endl; - usage(); - } +int mpc_main( + const std::map &subcommands, + const ProtoboardInitFn &pb_init, + int argc, + char **argv) +{ + libzeth::defaults::pp::init_public_params(); - return 1; + global_options options{pb_init, false}; + mpc_command cmd; + return libtool::run_command(cmd, options, subcommands, argc, argv); } diff --git a/mpc_tools/mpc_phase2/cli/mpc_common.hpp b/mpc_tools/mpc_phase2/cli/mpc_common.hpp index 0e2f4c427..79578afec 100644 --- a/mpc_tools/mpc_phase2/cli/mpc_common.hpp +++ b/mpc_tools/mpc_phase2/cli/mpc_common.hpp @@ -7,7 +7,7 @@ #include "libzeth/core/include_libsnark.hpp" #include "libzeth/mpc/groth16/mpc_hash.hpp" -#include "zeth_config.h" +#include "mpc_subcommand.hpp" #include #include @@ -15,45 +15,6 @@ #include #include -using ProtoboardInitFn = - std::function &)>; - -class subcommand -{ -protected: - std::string subcommand_name; - std::string subcommand_description; - bool verbose; - ProtoboardInitFn protoboard_init; - -private: - bool help; - -public: - using Field = libzeth::defaults::Field; - - subcommand( - const std::string &subcommand_name, const std::string &description); - void set_global_options(bool verbose, const ProtoboardInitFn &pb_init); - int execute(const std::vector &args); - const std::string &description() const; - -protected: - void init_protoboard(libsnark::protoboard &pb) const; - -private: - void usage(const boost::program_options::options_description &all_options); - - virtual void initialize_suboptions( - boost::program_options::options_description &options, - boost::program_options::options_description &all_options, - boost::program_options::positional_options_description &pos) = 0; - virtual void parse_suboptions( - const boost::program_options::variables_map &vm) = 0; - virtual void subcommand_usage() = 0; - virtual int execute_subcommand() = 0; -}; - // interface for ReadableT types: // { // static ReadableT read(std::istream &in); @@ -86,19 +47,19 @@ inline ReadableT read_from_file_and_hash( return v; } -extern subcommand *mpc_linear_combination_cmd; -extern subcommand *mpc_dummy_phase2_cmd; -extern subcommand *mpc_phase2_begin_cmd; -extern subcommand *mpc_phase2_contribute_cmd; -extern subcommand *mpc_phase2_verify_contribution_cmd; -extern subcommand *mpc_phase2_verify_transcript_cmd; -extern subcommand *mpc_create_keypair_cmd; +extern mpc_subcommand *mpc_linear_combination_cmd; +extern mpc_subcommand *mpc_dummy_phase2_cmd; +extern mpc_subcommand *mpc_phase2_begin_cmd; +extern mpc_subcommand *mpc_phase2_contribute_cmd; +extern mpc_subcommand *mpc_phase2_verify_contribution_cmd; +extern mpc_subcommand *mpc_phase2_verify_transcript_cmd; +extern mpc_subcommand *mpc_create_keypair_cmd; /// Main entry point into the mpc command for a given circuit. int mpc_main( + const std::map &commands, + const ProtoboardInitFn &pb_init, int argc, - char **argv, - const std::map &commands, - const ProtoboardInitFn &pb_init); + char **argv); #endif // __ZETH_MPC_CLI_COMMON_HPP__ diff --git a/mpc_tools/mpc_phase2/cli/mpc_create_keypair.cpp b/mpc_tools/mpc_phase2/cli/mpc_create_keypair.cpp index bffdb648e..52ad6ce8d 100644 --- a/mpc_tools/mpc_phase2/cli/mpc_create_keypair.cpp +++ b/mpc_tools/mpc_phase2/cli/mpc_create_keypair.cpp @@ -27,7 +27,7 @@ namespace // Options: // -h,--help This message // --pot-degree powersoftau degree (assumed to match linear comb) -class mpc_create_keypair : public subcommand +class mpc_create_keypair : public mpc_subcommand { private: std::string powersoftau_file; @@ -38,7 +38,8 @@ class mpc_create_keypair : public subcommand public: mpc_create_keypair() - : subcommand("create-keypair", "Create a full keypair from MPC output") + : mpc_subcommand( + "create-keypair", "Create a full keypair from MPC output") , powersoftau_file() , lin_comb_file() , phase2_challenge_file() @@ -97,17 +98,18 @@ class mpc_create_keypair : public subcommand vm.count("pot-degree") ? vm["pot-degree"].as() : 0; } - void subcommand_usage() override + void subcommand_usage(const char *argv0) override { std::cout << "Usage:\n" - << " " << subcommand_name << " [] \\\n" + << " " << argv0 << " " << subcommand_name + << " [] \\\n" << " \\\n" << " \n\n"; } - int execute_subcommand() override + int execute_subcommand(const global_options &options) override { - if (verbose) { + if (options.verbose) { std::cout << "powersoftau_file: " << powersoftau_file << "\n" << "lin_comb_file: " << lin_comb_file << "\n" << "phase2_challenge_file: " << phase2_challenge_file @@ -148,7 +150,7 @@ class mpc_create_keypair : public subcommand // Compute circuit libff::enter_block("Generate QAP"); libsnark::protoboard pb; - init_protoboard(pb); + options.protoboard_init(pb); libsnark::r1cs_constraint_system cs = pb.get_constraint_system(); const libsnark::qap_instance qap = libsnark::r1cs_to_qap_instance_map(cs, true); @@ -182,4 +184,4 @@ class mpc_create_keypair : public subcommand } // namespace // Subcommand instance -subcommand *mpc_create_keypair_cmd = new mpc_create_keypair(); +mpc_subcommand *mpc_create_keypair_cmd = new mpc_create_keypair(); diff --git a/mpc_tools/mpc_phase2/cli/mpc_dummy_phase2.cpp b/mpc_tools/mpc_phase2/cli/mpc_dummy_phase2.cpp index 296f6bf81..2a8da01f8 100644 --- a/mpc_tools/mpc_phase2/cli/mpc_dummy_phase2.cpp +++ b/mpc_tools/mpc_phase2/cli/mpc_dummy_phase2.cpp @@ -18,14 +18,15 @@ namespace // mpc dummy_phase2 [