├── .github ├── images │ ├── Dockerfile.build │ └── context.build │ │ └── .gitkeep └── workflows │ └── build.yml ├── .gitignore ├── .gitmodules ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── CMakeLists.txt ├── COPYING ├── Makefile ├── README.md ├── build ├── fq.asm ├── fq.cpp ├── fq.hpp ├── fq_element.hpp ├── fq_generic.cpp ├── fq_raw_arm64.s ├── fq_raw_generic.cpp ├── fr.asm ├── fr.cpp ├── fr.hpp ├── fr_element.hpp ├── fr_generic.cpp ├── fr_raw_arm64.s └── fr_raw_generic.cpp ├── build_gmp.sh ├── cmake └── platform.cmake ├── package-lock.json ├── package.json ├── service ├── README.md └── rapidsnark.service ├── src ├── CMakeLists.txt ├── binfile_utils.cpp ├── binfile_utils.hpp ├── fileloader.cpp ├── fileloader.hpp ├── fullprover.cpp ├── fullprover.hpp ├── groth16.cpp ├── groth16.hpp ├── logger.cpp ├── logger.hpp ├── logging.hpp ├── main_proofserver.cpp ├── main_prover.cpp ├── main_verifier.cpp ├── prover.cpp ├── prover.h ├── proverapi.cpp ├── proverapi.hpp ├── random_generator.hpp ├── test_prover.cpp ├── test_public_size.c ├── verifier.cpp ├── verifier.h ├── wtns_utils.cpp ├── wtns_utils.hpp ├── zkey_utils.cpp └── zkey_utils.hpp ├── tasksfile.js ├── testdata ├── circuit_final.zkey ├── verification_key.json └── witness.wtns └── tools └── request.js /.github/images/Dockerfile.build: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN apt-get -y update && \ 4 | apt-get -y install build-essential cmake m4 nasm curl 5 | -------------------------------------------------------------------------------- /.github/images/context.build/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/rapidsnark/998383787ee86bcb6bfb8741e9a638d203c08eae/.github/images/context.build/.gitkeep -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | # build/ 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | tmp 64 | 65 | .DS_Store 66 | 67 | # Workspace files are user-specific 68 | *.sublime-workspace 69 | CMakeLists.txt.user 70 | 71 | depends/gmp* 72 | 73 | build_* 74 | package* 75 | 76 | build/fq_asm.o 77 | build/fr_asm.o 78 | 79 | .idea/ 80 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "depends/pistache"] 2 | path = depends/pistache 3 | url = https://github.com/pistacheio/pistache 4 | [submodule "depends/json"] 5 | path = depends/json 6 | url = https://github.com/nlohmann/json.git 7 | [submodule "depends/ffiasm"] 8 | path = depends/ffiasm 9 | url = https://github.com/iden3/ffiasm 10 | branch = master 11 | [submodule "depends/circom_runtime"] 12 | path = depends/circom_runtime 13 | url = https://github.com/iden3/circom_runtime.git 14 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "proofServer", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/proverServer", 12 | "args": ["/home/jordi/circuits/tools/rollup-376-32-256-64/circuit-376-32-256-64.dat", "/home/jordi/circuits/tools/rollup-376-32-256-64/circuit-376-32-256-64_0001.zkey" ], 13 | "stopAtEntry": false, 14 | "cwd": "${workspaceFolder}/build", 15 | "environment": [], 16 | "externalConsole": false, 17 | "MIMode": "gdb", 18 | "setupCommands": [ 19 | { 20 | "description": "Enable pretty-printing for gdb", 21 | "text": "-enable-pretty-printing", 22 | "ignoreFailures": true 23 | } 24 | ] 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "array": "cpp", 4 | "atomic": "cpp", 5 | "bit": "cpp", 6 | "*.tcc": "cpp", 7 | "bitset": "cpp", 8 | "cctype": "cpp", 9 | "chrono": "cpp", 10 | "clocale": "cpp", 11 | "cmath": "cpp", 12 | "condition_variable": "cpp", 13 | "cstdarg": "cpp", 14 | "cstddef": "cpp", 15 | "cstdint": "cpp", 16 | "cstdio": "cpp", 17 | "cstdlib": "cpp", 18 | "cstring": "cpp", 19 | "ctime": "cpp", 20 | "cwchar": "cpp", 21 | "cwctype": "cpp", 22 | "deque": "cpp", 23 | "forward_list": "cpp", 24 | "list": "cpp", 25 | "map": "cpp", 26 | "unordered_map": "cpp", 27 | "unordered_set": "cpp", 28 | "vector": "cpp", 29 | "exception": "cpp", 30 | "algorithm": "cpp", 31 | "buffer": "cpp", 32 | "executor": "cpp", 33 | "functional": "cpp", 34 | "internet": "cpp", 35 | "io_context": "cpp", 36 | "iterator": "cpp", 37 | "memory": "cpp", 38 | "memory_resource": "cpp", 39 | "netfwd": "cpp", 40 | "numeric": "cpp", 41 | "optional": "cpp", 42 | "random": "cpp", 43 | "ratio": "cpp", 44 | "regex": "cpp", 45 | "socket": "cpp", 46 | "string": "cpp", 47 | "string_view": "cpp", 48 | "system_error": "cpp", 49 | "timer": "cpp", 50 | "tuple": "cpp", 51 | "type_traits": "cpp", 52 | "utility": "cpp", 53 | "fstream": "cpp", 54 | "future": "cpp", 55 | "initializer_list": "cpp", 56 | "iomanip": "cpp", 57 | "iosfwd": "cpp", 58 | "iostream": "cpp", 59 | "istream": "cpp", 60 | "limits": "cpp", 61 | "mutex": "cpp", 62 | "new": "cpp", 63 | "ostream": "cpp", 64 | "shared_mutex": "cpp", 65 | "sstream": "cpp", 66 | "stdexcept": "cpp", 67 | "streambuf": "cpp", 68 | "thread": "cpp", 69 | "cinttypes": "cpp", 70 | "typeinfo": "cpp", 71 | "csignal": "cpp", 72 | "set": "cpp", 73 | "valarray": "cpp", 74 | "variant": "cpp" 75 | } 76 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "buildProverServer", 8 | "type": "shell", 9 | "command": "npx task buildProverServer /home/jordi/circuits/tools/rollup-376-32-256-64/circuit-376-32-256-64.cpp", 10 | "group": { 11 | "kind": "build", 12 | "isDefault": true 13 | }, 14 | "presentation": { 15 | "reveal": "always", 16 | "panel": "new" 17 | }, 18 | "problemMatcher": { 19 | "owner": "cpp", 20 | "fileLocation": [ 21 | "relative", 22 | "${workspaceFolder}/build" 23 | ], 24 | "pattern": [ 25 | { 26 | "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$", 27 | "file": 1, 28 | "line": 2, 29 | "column": 3, 30 | "severity": 4, 31 | "message": 5 32 | } 33 | ] 34 | } 35 | }, 36 | { 37 | "label": "buildProver", 38 | "type": "shell", 39 | "command": "npx task buildProver", 40 | "group": { 41 | "kind": "build", 42 | "isDefault": true 43 | }, 44 | "presentation": { 45 | "reveal": "always", 46 | "panel": "new" 47 | }, 48 | "problemMatcher": { 49 | "owner": "cpp", 50 | "fileLocation": [ 51 | "relative", 52 | "${workspaceFolder}/build" 53 | ], 54 | "pattern": [ 55 | { 56 | "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$", 57 | "file": 1, 58 | "line": 2, 59 | "column": 3, 60 | "severity": 4, 61 | "message": 5 62 | } 63 | ] 64 | } 65 | }, 66 | ] 67 | } -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | include(cmake/platform.cmake) 4 | 5 | set(USE_ASM ON CACHE BOOL "Use asm implementation for Fr and Fq") 6 | set(USE_OPENMP ON CACHE BOOL "Use OpenMP") 7 | 8 | project(rapidsnark LANGUAGES CXX C ASM) 9 | 10 | set(CMAKE_CXX_STANDARD 11) 11 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 12 | 13 | message("BITS_PER_CHUNK=" ${BITS_PER_CHUNK}) 14 | message("USE_ASM=" ${USE_ASM}) 15 | message("USE_OPENMP=" ${USE_OPENMP}) 16 | message("CMAKE_CROSSCOMPILING=" ${CMAKE_CROSSCOMPILING}) 17 | 18 | message("GMP_PREFIX=" ${GMP_PREFIX}) 19 | message("GMP_INCLUDE_DIR=" ${GMP_INCLUDE_DIR}) 20 | message("GMP_LIB_DIR=" ${GMP_LIB_DIR}) 21 | 22 | if (NOT EXISTS ${GMP_INCLUDE_FILE_FULLPATH}) 23 | message("WARNING: ${GMP_INCLUDE_FILE_FULLPATH} is not found and so system ${GMP_INCLUDE_FILE} is used.") 24 | endif() 25 | 26 | if (NOT EXISTS ${GMP_LIB_FILE_FULLPATH}) 27 | message("WARNING: ${GMP_LIB_FILE_FULLPATH} is not found and so system ${GMP_LIB_FILE} is used.") 28 | set(GMP_LIB gmp) 29 | endif() 30 | 31 | 32 | include_directories(BEFORE ${GMP_INCLUDE_DIR}) 33 | 34 | 35 | if(USE_OPENMP) 36 | find_package(OpenMP) 37 | 38 | if(OpenMP_CXX_FOUND) 39 | if(TARGET_PLATFORM MATCHES "android") 40 | message("OpenMP is used") 41 | 42 | elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") 43 | message("OpenMP is used") 44 | 45 | else() 46 | set(OpenMP_CXX_FOUND FALSE) 47 | message("OpenMP is not used") 48 | 49 | endif() 50 | endif() 51 | endif() 52 | 53 | 54 | add_subdirectory(src) 55 | 56 | 57 | install(TARGETS prover verifier rapidsnark rapidsnarkStatic rapidsnarkStaticFrFq test_prover fr fq 58 | RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin 59 | BUNDLE DESTINATION ${CMAKE_INSTALL_PREFIX}/app 60 | LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) 61 | 62 | install(FILES "${GMP_LIB_DIR}/${GMP_LIB_FILE}" 63 | DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) 64 | 65 | install(FILES src/prover.h src/verifier.h 66 | DESTINATION ${CMAKE_INSTALL_PREFIX}/include) 67 | 68 | enable_testing() 69 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ### 2 | 3 | #Build targets 4 | host: 5 | rm -rf build_prover && mkdir build_prover && cd build_prover && \ 6 | cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package && \ 7 | make -j$(nproc) -vvv && make install 8 | 9 | host_noasm: 10 | rm -rf build_prover_noasm && mkdir build_prover_noasm && cd build_prover_noasm && \ 11 | cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_noasm -DUSE_ASM=NO && \ 12 | make -j$(nproc) -vvv && make install 13 | 14 | host_arm64: 15 | rm -rf build_prover_arm64 && mkdir build_prover_arm64 && cd build_prover_arm64 && \ 16 | cmake .. -DTARGET_PLATFORM=aarch64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_arm64 && \ 17 | make -j$(nproc) -vvv && make install 18 | 19 | android: 20 | rm -rf build_prover_android && mkdir build_prover_android && cd build_prover_android && \ 21 | cmake .. -DTARGET_PLATFORM=ANDROID -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_android -DBUILD_TESTS=OFF -DUSE_OPENMP=OFF && \ 22 | make -j$(nproc) -vvv && make install 23 | 24 | android_openmp: 25 | rm -rf build_prover_android_openmp && mkdir build_prover_android_openmp && cd build_prover_android_openmp && \ 26 | cmake .. -DTARGET_PLATFORM=ANDROID -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_android_openmp -DBUILD_TESTS=OFF -DUSE_OPENMP=ON && \ 27 | make -j$(nproc) -vvv && make install 28 | 29 | android_x86_64: 30 | rm -rf build_prover_android_x86_64 && mkdir build_prover_android_x86_64 && cd build_prover_android_x86_64 && \ 31 | cmake .. -DTARGET_PLATFORM=ANDROID_x86_64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_android_x86_64 -DBUILD_TESTS=OFF -DUSE_OPENMP=OFF && \ 32 | make -j$(nproc) -vvv && make install 33 | 34 | android_openmp_x86_64: 35 | rm -rf build_prover_android_openmp_x86_64 && mkdir build_prover_android_openmp_x86_64 && cd build_prover_android_openmp_x86_64 && \ 36 | cmake .. -DTARGET_PLATFORM=ANDROID_x86_64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_android_openmp_x86_64 -DBUILD_TESTS=OFF -DUSE_OPENMP=ON && \ 37 | make -j$(nproc) -vvv && make install 38 | 39 | ios: 40 | @if [ ! -d "./depends/gmp/package_ios_arm64" ]; then echo "Looks like gmp lib is not built. Run './build_gmp.sh ios' first." && exit 1; fi 41 | rm -rf build_prover_ios && mkdir build_prover_ios && cd build_prover_ios && \ 42 | cmake .. -GXcode -DTARGET_PLATFORM=IOS -DCMAKE_INSTALL_PREFIX=../package_ios && \ 43 | xcodebuild -destination 'generic/platform=iOS' -scheme rapidsnarkStatic -project rapidsnark.xcodeproj -configuration Release && \ 44 | xcodebuild -destination 'generic/platform=iOS' -scheme rapidsnark -project rapidsnark.xcodeproj -configuration Release CODE_SIGNING_ALLOWED=NO && \ 45 | cp ../depends/gmp/package_ios_arm64/lib/libgmp.a src/Release-iphoneos && \ 46 | echo "" && echo "iOS Simulator artifacts built in build_prover_ios/src/Release-iphoneos" && echo "" 47 | 48 | ios_simulator: 49 | @if [ ! -d "./depends/gmp/package_iphone_simulator" ]; then echo "Looks like gmp lib is not built. Run './build_gmp.sh ios_simulator' first." && exit 1; fi 50 | rm -rf build_prover_ios_simulator && mkdir build_prover_ios_simulator && cd build_prover_ios_simulator && \ 51 | cmake .. -GXcode -DTARGET_PLATFORM=IOS_SIMULATOR -DCMAKE_INSTALL_PREFIX=../package_ios_simulator -DUSE_ASM=NO && \ 52 | xcodebuild -destination 'generic/platform=iOS Simulator' -scheme rapidsnarkStatic -project rapidsnark.xcodeproj && \ 53 | xcodebuild -destination 'generic/platform=iOS Simulator' -scheme rapidsnark -project rapidsnark.xcodeproj CODE_SIGNING_ALLOWED=NO ARCHS=arm64 && \ 54 | cp ../depends/gmp/package_iphone_simulator/lib/libgmp.a src/Debug-iphonesimulator && \ 55 | echo "" && echo "iOS Simulator artifacts built in build_prover_ios_simulator/src/Debug-iphonesimulator" && echo "" 56 | 57 | macos_arm64: 58 | @if [ ! -d "./depends/gmp/package_macos_arm64" ]; then echo "Looks like gmp lib is not built. Run './build_gmp.sh macos_arm64' first." && exit 1; fi 59 | rm -rf build_prover_macos_arm64 && mkdir build_prover_macos_arm64 && cd build_prover_macos_arm64 && \ 60 | cmake .. -DTARGET_PLATFORM=macos_arm64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_macos_arm64 && \ 61 | make -j$(nproc) -vvv && make install 62 | 63 | macos_x86_64: 64 | @if [ ! -d "./depends/gmp/package_macos_x86_64" ]; then echo "Looks like gmp lib is not built. Run './build_gmp.sh macos_x86_64' first." && exit 1; fi 65 | rm -rf build_prover_macos_x86_64 && mkdir build_prover_macos_x86_64 && cd build_prover_macos_x86_64 && \ 66 | cmake .. -DTARGET_PLATFORM=macos_x86_64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_macos_x86_64 && \ 67 | make -j$(nproc) -vvv && make install 68 | 69 | clean: 70 | rm -rf build_prover \ 71 | build_prover_macos_arm64 \ 72 | build_prover_macos_x86_64 \ 73 | build_prover_android \ 74 | build_prover_android_x86_64 \ 75 | build_prover_ios \ 76 | build_prover_ios_simulator \ 77 | package \ 78 | package_macos_arm64 \ 79 | package_macos_x86_64 \ 80 | package_android \ 81 | package_android_x86_64 \ 82 | package_ios \ 83 | package_ios_simulator \ 84 | depends/gmp/package \ 85 | depends/gmp/package_macos_arm64 \ 86 | depends/gmp/package_macos_x86_64 \ 87 | depends/gmp/package_android_arm64 \ 88 | depends/gmp/package_android_x86_64 \ 89 | depends/gmp/package_ios_arm64 \ 90 | depends/gmp/package_iphone_simulator 91 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Important note 2 | 3 | **This is a new implementation of rapidsnark. The original (and now obsoleted) implemenation is available here: [rapidsnark-old](https://github.com/iden3/rapidsnark-old).** 4 | 5 | # rapidsnark 6 | 7 | Rapidsnark is a zkSnark proof generation written in C++ and intel/arm assembly. That generates proofs created in [circom](https://github.com/iden3/circom) and [snarkjs](https://github.com/iden3/snarkjs) very fast. 8 | 9 | ## Dependencies 10 | 11 | You should have installed gcc, cmake, libsodium, and gmp (development) 12 | 13 | In ubuntu: 14 | 15 | ``` 16 | sudo apt-get install build-essential cmake libgmp-dev libsodium-dev nasm curl m4 17 | ``` 18 | 19 | On MacOS: 20 | 21 | ``` 22 | brew install cmake gmp libsodium nasm 23 | ``` 24 | 25 | ## Compile prover in standalone mode 26 | 27 | ### Compile prover for x86_64 host machine 28 | 29 | ```sh 30 | git submodule init 31 | git submodule update 32 | ./build_gmp.sh host 33 | make host 34 | ``` 35 | 36 | ### Compile prover for macOS arm64 host machine 37 | 38 | ```sh 39 | git submodule init 40 | git submodule update 41 | ./build_gmp.sh macos_arm64 42 | make macos_arm64 43 | ``` 44 | 45 | ### Compile prover for linux arm64 host machine 46 | 47 | ```sh 48 | git submodule init 49 | git submodule update 50 | ./build_gmp.sh host 51 | make host_arm64 52 | ``` 53 | 54 | ### Compile prover for linux arm64 machine 55 | 56 | ```sh 57 | git submodule init 58 | git submodule update 59 | ./build_gmp.sh host 60 | make arm64 61 | ``` 62 | 63 | ### Compile prover for Android 64 | 65 | Install Android NDK from https://developer.android.com/ndk or with help of "SDK Manager" in Android Studio. 66 | 67 | Set the value of ANDROID_NDK environment variable to the absolute path of Android NDK root directory. 68 | 69 | Examples: 70 | 71 | ```sh 72 | export ANDROID_NDK=/home/test/Android/Sdk/ndk/23.1.7779620 # NDK is installed by "SDK Manager" in Android Studio. 73 | export ANDROID_NDK=/home/test/android-ndk-r23b # NDK is installed as a stand-alone package. 74 | ``` 75 | 76 | Prerequisites if build on Ubuntu: 77 | 78 | ```sh 79 | apt-get install curl xz-utils build-essential cmake m4 nasm 80 | ``` 81 | 82 | Compilation: 83 | 84 | ```sh 85 | git submodule init 86 | git submodule update 87 | ./build_gmp.sh android 88 | make android 89 | ``` 90 | 91 | ### Compile prover for iOS 92 | 93 | Install Xcode 94 | 95 | ```sh 96 | git submodule init 97 | git submodule update 98 | ./build_gmp.sh ios 99 | make ios 100 | ``` 101 | Open generated Xcode project and compile prover. 102 | 103 | ## Build for iOS emulator 104 | 105 | Install Xcode 106 | 107 | ```sh 108 | git submodule init 109 | git submodule update 110 | ./build_gmp.sh ios_simulator 111 | make ios_simulator 112 | ``` 113 | 114 | Files that you need to copy to your XCode project to link against Rapidsnark: 115 | * build_prover_ios_simulator/src/Debug-iphonesimulator/librapidsnark.a 116 | * build_prover_ios_simulator/src/Debug-iphonesimulator/libfq.a 117 | * build_prover_ios_simulator/src/Debug-iphonesimulator/libfr.a 118 | * depends/gmp/package_iphone_simulator/lib/libgmp.a 119 | 120 | ## Building proof 121 | 122 | You have a full prover compiled in the build directory. 123 | 124 | So you can replace snarkjs command: 125 | 126 | ```sh 127 | snarkjs groth16 prove 128 | ``` 129 | 130 | by this one 131 | ```sh 132 | ./package/bin/prover 133 | ``` 134 | 135 | ## Compile prover in server mode 136 | 137 | ```sh 138 | npm install 139 | git submodule init 140 | git submodule update 141 | npx task buildPistache 142 | npx task buildProverServer 143 | ``` 144 | 145 | ## Launch prover in server mode 146 | ```sh 147 | ./build/proverServer ... 148 | ``` 149 | 150 | For every `circuit.circom` you have to generate with circom with --c option the `circuit_cpp` and after compilation you have to copy the executable into the `build` folder so the server can generate the witness and then the proof based on this witness. 151 | You have an example of the usage calling the server endpoints to generate the proof with Nodejs in `/tools/request.js`. 152 | 153 | To test a request you should pass an `input.json` as a parameter to the request call. 154 | ```sh 155 | node tools/request.js 156 | ``` 157 | 158 | ## Wrappers 159 | 160 | Rapidsnark can be used with several programming languages and environments through wrappers that provide integration with the original library. Below is a list of available wrappers: 161 | 162 | | Wrapper | Repository Link | 163 | | ------------ |-----------------------------------------| 164 | | Go | https://github.com/iden3/go-rapidsnark | 165 | | iOS | https://github.com/iden3/ios-rapidsnark | 166 | | Android | https://github.com/iden3/android-rapidsnark | 167 | | React Native | https://github.com/iden3/react-native-rapidsnark | 168 | | Flutter | https://github.com/iden3/flutter-rapidsnark | 169 | 170 | ## Benchmark 171 | 172 | This prover parallelizes as much as it can the proof generation. 173 | 174 | The prover is much faster that snarkjs and faster than bellman. 175 | 176 | [TODO] Some comparative tests should be done. 177 | 178 | ## Run tests 179 | 180 | You need to perform all the steps from the 181 | [Compile prover in standalone mode](#compile-prover-in-standalone-mode) section. 182 | After that you can run tests with the following command from the build 183 | directory: 184 | 185 | ```sh 186 | # Make sure you are in the build directory 187 | # ./build_prover for linux, ./build_prover_macos_arm64 for macOS. 188 | cmake --build . --parallel && ctest --rerun-failed --output-on-failure 189 | ``` 190 | 191 | To run just the `test_public_size` test for custom zkey to measure the 192 | performance, you can run the following command from the build directory: 193 | 194 | ```sh 195 | src/test_public_size ../testdata/circuit_final.zkey 86 196 | ``` 197 | 198 | ## License 199 | 200 | rapidsnark is part of the iden3 project copyright 2021 0KIMS association and published with LGPL-3 license. Please check the COPYING file for more details. 201 | -------------------------------------------------------------------------------- /build/fq.cpp: -------------------------------------------------------------------------------- 1 | #include "fq.hpp" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | static mpz_t q; 10 | static mpz_t zero; 11 | static mpz_t one; 12 | static mpz_t mask; 13 | static size_t nBits; 14 | static bool initialized = false; 15 | 16 | void Fq_toMpz(mpz_t r, PFqElement pE) { 17 | FqElement tmp; 18 | Fq_toNormal(&tmp, pE); 19 | if (!(tmp.type & Fq_LONG)) { 20 | mpz_set_si(r, tmp.shortVal); 21 | if (tmp.shortVal<0) { 22 | mpz_add(r, r, q); 23 | } 24 | } else { 25 | mpz_import(r, Fq_N64, -1, 8, -1, 0, (const void *)tmp.longVal); 26 | } 27 | } 28 | 29 | void Fq_fromMpz(PFqElement pE, mpz_t v) { 30 | if (mpz_fits_sint_p(v)) { 31 | pE->type = Fq_SHORT; 32 | pE->shortVal = mpz_get_si(v); 33 | } else { 34 | pE->type = Fq_LONG; 35 | for (int i=0; ilongVal[i] = 0; 36 | mpz_export((void *)(pE->longVal), NULL, -1, 8, -1, 0, v); 37 | } 38 | } 39 | 40 | 41 | bool Fq_init() { 42 | if (initialized) return false; 43 | initialized = true; 44 | mpz_init(q); 45 | mpz_import(q, Fq_N64, -1, 8, -1, 0, (const void *)Fq_q.longVal); 46 | mpz_init_set_ui(zero, 0); 47 | mpz_init_set_ui(one, 1); 48 | nBits = mpz_sizeinbase (q, 2); 49 | mpz_init(mask); 50 | mpz_mul_2exp(mask, one, nBits); 51 | mpz_sub(mask, mask, one); 52 | return true; 53 | } 54 | 55 | void Fq_str2element(PFqElement pE, char const *s, uint base) { 56 | mpz_t mr; 57 | mpz_init_set_str(mr, s, base); 58 | mpz_fdiv_r(mr, mr, q); 59 | Fq_fromMpz(pE, mr); 60 | mpz_clear(mr); 61 | } 62 | 63 | char *Fq_element2str(PFqElement pE) { 64 | FqElement tmp; 65 | mpz_t r; 66 | if (!(pE->type & Fq_LONG)) { 67 | if (pE->shortVal>=0) { 68 | char *r = new char[32]; 69 | sprintf(r, "%d", pE->shortVal); 70 | return r; 71 | } else { 72 | mpz_init_set_si(r, pE->shortVal); 73 | mpz_add(r, r, q); 74 | } 75 | } else { 76 | Fq_toNormal(&tmp, pE); 77 | mpz_init(r); 78 | mpz_import(r, Fq_N64, -1, 8, -1, 0, (const void *)tmp.longVal); 79 | } 80 | char *res = mpz_get_str (0, 10, r); 81 | mpz_clear(r); 82 | return res; 83 | } 84 | 85 | void Fq_idiv(PFqElement r, PFqElement a, PFqElement b) { 86 | mpz_t ma; 87 | mpz_t mb; 88 | mpz_t mr; 89 | mpz_init(ma); 90 | mpz_init(mb); 91 | mpz_init(mr); 92 | 93 | Fq_toMpz(ma, a); 94 | // char *s1 = mpz_get_str (0, 10, ma); 95 | // printf("s1 %s\n", s1); 96 | Fq_toMpz(mb, b); 97 | // char *s2 = mpz_get_str (0, 10, mb); 98 | // printf("s2 %s\n", s2); 99 | mpz_fdiv_q(mr, ma, mb); 100 | // char *sr = mpz_get_str (0, 10, mr); 101 | // printf("r %s\n", sr); 102 | Fq_fromMpz(r, mr); 103 | 104 | mpz_clear(ma); 105 | mpz_clear(mb); 106 | mpz_clear(mr); 107 | } 108 | 109 | void Fq_mod(PFqElement r, PFqElement a, PFqElement b) { 110 | mpz_t ma; 111 | mpz_t mb; 112 | mpz_t mr; 113 | mpz_init(ma); 114 | mpz_init(mb); 115 | mpz_init(mr); 116 | 117 | Fq_toMpz(ma, a); 118 | Fq_toMpz(mb, b); 119 | mpz_fdiv_r(mr, ma, mb); 120 | Fq_fromMpz(r, mr); 121 | 122 | mpz_clear(ma); 123 | mpz_clear(mb); 124 | mpz_clear(mr); 125 | } 126 | 127 | void Fq_pow(PFqElement r, PFqElement a, PFqElement b) { 128 | mpz_t ma; 129 | mpz_t mb; 130 | mpz_t mr; 131 | mpz_init(ma); 132 | mpz_init(mb); 133 | mpz_init(mr); 134 | 135 | Fq_toMpz(ma, a); 136 | Fq_toMpz(mb, b); 137 | mpz_powm(mr, ma, mb, q); 138 | Fq_fromMpz(r, mr); 139 | 140 | mpz_clear(ma); 141 | mpz_clear(mb); 142 | mpz_clear(mr); 143 | } 144 | 145 | void Fq_inv(PFqElement r, PFqElement a) { 146 | mpz_t ma; 147 | mpz_t mr; 148 | mpz_init(ma); 149 | mpz_init(mr); 150 | 151 | Fq_toMpz(ma, a); 152 | mpz_invert(mr, ma, q); 153 | Fq_fromMpz(r, mr); 154 | mpz_clear(ma); 155 | mpz_clear(mr); 156 | } 157 | 158 | void Fq_div(PFqElement r, PFqElement a, PFqElement b) { 159 | FqElement tmp; 160 | Fq_inv(&tmp, b); 161 | Fq_mul(r, a, &tmp); 162 | } 163 | 164 | void Fq_fail() { 165 | throw std::runtime_error("Fq error"); 166 | } 167 | 168 | void Fq_longErr() 169 | { 170 | Fq_fail(); 171 | } 172 | 173 | RawFq::RawFq() { 174 | Fq_init(); 175 | set(fZero, 0); 176 | set(fOne, 1); 177 | neg(fNegOne, fOne); 178 | } 179 | 180 | RawFq::~RawFq() { 181 | } 182 | 183 | void RawFq::fromString(Element &r, const std::string &s, uint32_t radix) { 184 | mpz_t mr; 185 | mpz_init_set_str(mr, s.c_str(), radix); 186 | mpz_fdiv_r(mr, mr, q); 187 | for (int i=0; i>3] & (1 << (p & 0x7))) 259 | void RawFq::exp(Element &r, const Element &base, uint8_t* scalar, unsigned int scalarSize) { 260 | bool oneFound = false; 261 | Element copyBase; 262 | copy(copyBase, base); 263 | for (int i=scalarSize*8-1; i>=0; i--) { 264 | if (!oneFound) { 265 | if ( !BIT_IS_SET(scalar, i) ) continue; 266 | copy(r, copyBase); 267 | oneFound = true; 268 | continue; 269 | } 270 | square(r, r); 271 | if ( BIT_IS_SET(scalar, i) ) { 272 | mul(r, r, copyBase); 273 | } 274 | } 275 | if (!oneFound) { 276 | copy(r, fOne); 277 | } 278 | } 279 | 280 | void RawFq::toMpz(mpz_t r, const Element &a) { 281 | Element tmp; 282 | Fq_rawFromMontgomery(tmp.v, a.v); 283 | mpz_import(r, Fq_N64, -1, 8, -1, 0, (const void *)tmp.v); 284 | } 285 | 286 | void RawFq::fromMpz(Element &r, const mpz_t a) { 287 | for (int i=0; i 6 | #include 7 | #include 8 | 9 | #ifdef __APPLE__ 10 | #include // typedef unsigned int uint; 11 | #endif // __APPLE__ 12 | 13 | extern FqElement Fq_q; 14 | extern FqElement Fq_R2; 15 | extern FqElement Fq_R3; 16 | extern FqRawElement Fq_rawq; 17 | extern FqRawElement Fq_rawR3; 18 | 19 | #ifdef USE_ASM 20 | 21 | #if defined(ARCH_X86_64) 22 | 23 | extern "C" void Fq_copy(PFqElement r, PFqElement a); 24 | extern "C" void Fq_copyn(PFqElement r, PFqElement a, int n); 25 | extern "C" void Fq_add(PFqElement r, PFqElement a, PFqElement b); 26 | extern "C" void Fq_sub(PFqElement r, PFqElement a, PFqElement b); 27 | extern "C" void Fq_neg(PFqElement r, PFqElement a); 28 | extern "C" void Fq_mul(PFqElement r, PFqElement a, PFqElement b); 29 | extern "C" void Fq_square(PFqElement r, PFqElement a); 30 | extern "C" void Fq_band(PFqElement r, PFqElement a, PFqElement b); 31 | extern "C" void Fq_bor(PFqElement r, PFqElement a, PFqElement b); 32 | extern "C" void Fq_bxor(PFqElement r, PFqElement a, PFqElement b); 33 | extern "C" void Fq_bnot(PFqElement r, PFqElement a); 34 | extern "C" void Fq_shl(PFqElement r, PFqElement a, PFqElement b); 35 | extern "C" void Fq_shr(PFqElement r, PFqElement a, PFqElement b); 36 | extern "C" void Fq_eq(PFqElement r, PFqElement a, PFqElement b); 37 | extern "C" void Fq_neq(PFqElement r, PFqElement a, PFqElement b); 38 | extern "C" void Fq_lt(PFqElement r, PFqElement a, PFqElement b); 39 | extern "C" void Fq_gt(PFqElement r, PFqElement a, PFqElement b); 40 | extern "C" void Fq_leq(PFqElement r, PFqElement a, PFqElement b); 41 | extern "C" void Fq_geq(PFqElement r, PFqElement a, PFqElement b); 42 | extern "C" void Fq_land(PFqElement r, PFqElement a, PFqElement b); 43 | extern "C" void Fq_lor(PFqElement r, PFqElement a, PFqElement b); 44 | extern "C" void Fq_lnot(PFqElement r, PFqElement a); 45 | extern "C" void Fq_toNormal(PFqElement r, PFqElement a); 46 | extern "C" void Fq_toLongNormal(PFqElement r, PFqElement a); 47 | extern "C" void Fq_toMontgomery(PFqElement r, PFqElement a); 48 | 49 | extern "C" int Fq_isTrue(PFqElement pE); 50 | extern "C" int Fq_toInt(PFqElement pE); 51 | 52 | extern "C" void Fq_rawCopy(FqRawElement pRawResult, const FqRawElement pRawA); 53 | extern "C" void Fq_rawSwap(FqRawElement pRawResult, FqRawElement pRawA); 54 | extern "C" void Fq_rawAdd(FqRawElement pRawResult, const FqRawElement pRawA, const FqRawElement pRawB); 55 | extern "C" void Fq_rawSub(FqRawElement pRawResult, const FqRawElement pRawA, const FqRawElement pRawB); 56 | extern "C" void Fq_rawNeg(FqRawElement pRawResult, const FqRawElement pRawA); 57 | extern "C" void Fq_rawMMul(FqRawElement pRawResult, const FqRawElement pRawA, const FqRawElement pRawB); 58 | extern "C" void Fq_rawMSquare(FqRawElement pRawResult, const FqRawElement pRawA); 59 | extern "C" void Fq_rawMMul1(FqRawElement pRawResult, const FqRawElement pRawA, uint64_t pRawB); 60 | extern "C" void Fq_rawToMontgomery(FqRawElement pRawResult, const FqRawElement &pRawA); 61 | extern "C" void Fq_rawFromMontgomery(FqRawElement pRawResult, const FqRawElement &pRawA); 62 | extern "C" int Fq_rawIsEq(const FqRawElement pRawA, const FqRawElement pRawB); 63 | extern "C" int Fq_rawIsZero(const FqRawElement pRawB); 64 | extern "C" void Fq_rawShl(FqRawElement r, FqRawElement a, uint64_t b); 65 | extern "C" void Fq_rawShr(FqRawElement r, FqRawElement a, uint64_t b); 66 | 67 | extern "C" void Fq_fail(); 68 | 69 | #elif defined(ARCH_ARM64) 70 | 71 | void Fq_copy(PFqElement r, PFqElement a); 72 | void Fq_mul(PFqElement r, PFqElement a, PFqElement b); 73 | void Fq_toNormal(PFqElement r, PFqElement a); 74 | 75 | void Fq_toLongNormal(PFqElement r, PFqElement a); 76 | int Fq_isTrue(PFqElement pE); 77 | void Fq_copyn(PFqElement r, PFqElement a, int n); 78 | void Fq_lt(PFqElement r, PFqElement a, PFqElement b); 79 | int Fq_toInt(PFqElement pE); 80 | void Fq_shr(PFqElement r, PFqElement a, PFqElement b); 81 | void Fq_shl(PFqElement r, PFqElement a, PFqElement b); 82 | void Fq_band(PFqElement r, PFqElement a, PFqElement b); 83 | void Fq_bor(PFqElement r, PFqElement a, PFqElement b); 84 | void Fq_bxor(PFqElement r, PFqElement a, PFqElement b); 85 | void Fq_bnot(PFqElement r, PFqElement a); 86 | void Fq_sub(PFqElement r, PFqElement a, PFqElement b); 87 | void Fq_eq(PFqElement r, PFqElement a, PFqElement b); 88 | void Fq_neq(PFqElement r, PFqElement a, PFqElement b); 89 | void Fq_add(PFqElement r, PFqElement a, PFqElement b); 90 | void Fq_gt(PFqElement r, PFqElement a, PFqElement b); 91 | void Fq_leq(PFqElement r, PFqElement a, PFqElement b); 92 | void Fq_geq(PFqElement r, PFqElement a, PFqElement b); 93 | void Fq_lor(PFqElement r, PFqElement a, PFqElement b); 94 | void Fq_lnot(PFqElement r, PFqElement a); 95 | void Fq_land(PFqElement r, PFqElement a, PFqElement b); 96 | void Fq_neg(PFqElement r, PFqElement a); 97 | void Fq_toMontgomery(PFqElement r, PFqElement a); 98 | void Fq_square(PFqElement r, PFqElement a); 99 | 100 | extern "C" void Fq_rawCopy(FqRawElement pRawResult, const FqRawElement pRawA); 101 | extern "C" void Fq_rawSwap(FqRawElement pRawResult, FqRawElement pRawA); 102 | extern "C" void Fq_rawAdd(FqRawElement pRawResult, const FqRawElement pRawA, const FqRawElement pRawB); 103 | extern "C" void Fq_rawSub(FqRawElement pRawResult, const FqRawElement pRawA, const FqRawElement pRawB); 104 | extern "C" void Fq_rawNeg(FqRawElement pRawResult, const FqRawElement pRawA); 105 | extern "C" void Fq_rawMMul(FqRawElement pRawResult, const FqRawElement pRawA, const FqRawElement pRawB); 106 | void Fq_rawMSquare(FqRawElement pRawResult, const FqRawElement pRawA); 107 | extern "C" void Fq_rawMMul1(FqRawElement pRawResult, const FqRawElement pRawA, uint64_t pRawB); 108 | void Fq_rawToMontgomery(FqRawElement pRawResult, const FqRawElement &pRawA); 109 | extern "C" void Fq_rawFromMontgomery(FqRawElement pRawResult, const FqRawElement &pRawA); 110 | extern "C" int Fq_rawIsEq(const FqRawElement pRawA, const FqRawElement pRawB); 111 | extern "C" int Fq_rawIsZero(const FqRawElement pRawB); 112 | void Fq_rawZero(FqRawElement pRawResult); 113 | extern "C" void Fq_rawCopyS2L(FqRawElement pRawResult, int64_t val); 114 | extern "C" void Fq_rawAddLS(FqRawElement pRawResult, FqRawElement pRawA, uint64_t rawB); 115 | extern "C" void Fq_rawSubSL(FqRawElement pRawResult, uint64_t rawA, FqRawElement pRawB); 116 | extern "C" void Fq_rawSubLS(FqRawElement pRawResult, FqRawElement pRawA, uint64_t rawB); 117 | extern "C" void Fq_rawNegLS(FqRawElement pRawResult, FqRawElement pRawA, uint64_t rawB); 118 | extern "C" int Fq_rawCmp(FqRawElement pRawA, FqRawElement pRawB); 119 | extern "C" void Fq_rawAnd(FqRawElement pRawResult, FqRawElement pRawA, FqRawElement pRawB); 120 | extern "C" void Fq_rawOr(FqRawElement pRawResult, FqRawElement pRawA, FqRawElement pRawB); 121 | extern "C" void Fq_rawXor(FqRawElement pRawResult, FqRawElement pRawA, FqRawElement pRawB); 122 | extern "C" void Fq_rawShl(FqRawElement r, FqRawElement a, uint64_t b); 123 | extern "C" void Fq_rawShr(FqRawElement r, FqRawElement a, uint64_t b); 124 | extern "C" void Fq_rawNot(FqRawElement pRawResult, FqRawElement pRawA); 125 | extern "C" void Fq_rawSubRegular(FqRawElement pRawResult, FqRawElement pRawA, FqRawElement pRawB); 126 | 127 | void Fq_fail(); 128 | void Fq_longErr(); 129 | 130 | #endif 131 | 132 | #else 133 | 134 | 135 | void Fq_copy(PFqElement r, PFqElement a); 136 | void Fq_mul(PFqElement r, PFqElement a, PFqElement b); 137 | void Fq_toNormal(PFqElement r, PFqElement a); 138 | 139 | void Fq_toLongNormal(PFqElement r, PFqElement a); 140 | int Fq_isTrue(PFqElement pE); 141 | void Fq_copyn(PFqElement r, PFqElement a, int n); 142 | void Fq_lt(PFqElement r, PFqElement a, PFqElement b); 143 | int Fq_toInt(PFqElement pE); 144 | void Fq_shl(PFqElement r, PFqElement a, PFqElement b); 145 | void Fq_shr(PFqElement r, PFqElement a, PFqElement b); 146 | void Fq_band(PFqElement r, PFqElement a, PFqElement b); 147 | void Fq_bor(PFqElement r, PFqElement a, PFqElement b); 148 | void Fq_bxor(PFqElement r, PFqElement a, PFqElement b); 149 | void Fq_bnot(PFqElement r, PFqElement a); 150 | void Fq_sub(PFqElement r, PFqElement a, PFqElement b); 151 | void Fq_eq(PFqElement r, PFqElement a, PFqElement b); 152 | void Fq_neq(PFqElement r, PFqElement a, PFqElement b); 153 | void Fq_add(PFqElement r, PFqElement a, PFqElement b); 154 | void Fq_gt(PFqElement r, PFqElement a, PFqElement b); 155 | void Fq_leq(PFqElement r, PFqElement a, PFqElement b); 156 | void Fq_geq(PFqElement r, PFqElement a, PFqElement b); 157 | void Fq_lor(PFqElement r, PFqElement a, PFqElement b); 158 | void Fq_lnot(PFqElement r, PFqElement a); 159 | void Fq_land(PFqElement r, PFqElement a, PFqElement b); 160 | void Fq_neg(PFqElement r, PFqElement a); 161 | void Fq_toMontgomery(PFqElement r, PFqElement a); 162 | void Fq_square(PFqElement r, PFqElement a); 163 | 164 | void Fq_rawCopy(FqRawElement pRawResult, const FqRawElement pRawA); 165 | void Fq_rawSwap(FqRawElement pRawResult, FqRawElement pRawA); 166 | void Fq_rawAdd(FqRawElement pRawResult, const FqRawElement pRawA, const FqRawElement pRawB); 167 | void Fq_rawSub(FqRawElement pRawResult, const FqRawElement pRawA, const FqRawElement pRawB); 168 | void Fq_rawNeg(FqRawElement pRawResult, const FqRawElement pRawA); 169 | void Fq_rawMMul(FqRawElement pRawResult, const FqRawElement pRawA, const FqRawElement pRawB); 170 | void Fq_rawMSquare(FqRawElement pRawResult, const FqRawElement pRawA); 171 | void Fq_rawMMul1(FqRawElement pRawResult, const FqRawElement pRawA, uint64_t pRawB); 172 | void Fq_rawToMontgomery(FqRawElement pRawResult, const FqRawElement &pRawA); 173 | void Fq_rawFromMontgomery(FqRawElement pRawResult, const FqRawElement &pRawA); 174 | int Fq_rawIsEq(const FqRawElement pRawA, const FqRawElement pRawB); 175 | int Fq_rawIsZero(const FqRawElement pRawB); 176 | void Fq_rawZero(FqRawElement pRawResult); 177 | void Fq_rawCopyS2L(FqRawElement pRawResult, int64_t val); 178 | void Fq_rawAddLS(FqRawElement pRawResult, FqRawElement pRawA, uint64_t rawB); 179 | void Fq_rawSubSL(FqRawElement pRawResult, uint64_t rawA, FqRawElement pRawB); 180 | void Fq_rawSubLS(FqRawElement pRawResult, FqRawElement pRawA, uint64_t rawB); 181 | void Fq_rawNegLS(FqRawElement pRawResult, FqRawElement pRawA, uint64_t rawB); 182 | int Fq_rawCmp(FqRawElement pRawA, FqRawElement pRawB); 183 | void Fq_rawAnd(FqRawElement pRawResult, FqRawElement pRawA, FqRawElement pRawB); 184 | void Fq_rawOr(FqRawElement pRawResult, FqRawElement pRawA, FqRawElement pRawB); 185 | void Fq_rawXor(FqRawElement pRawResult, FqRawElement pRawA, FqRawElement pRawB); 186 | void Fq_rawShl(FqRawElement r, FqRawElement a, uint64_t b); 187 | void Fq_rawShr(FqRawElement r, FqRawElement a, uint64_t b); 188 | void Fq_rawNot(FqRawElement pRawResult, FqRawElement pRawA); 189 | void Fq_rawSubRegular(FqRawElement pRawResult, FqRawElement pRawA, FqRawElement pRawB); 190 | 191 | void Fq_fail(); 192 | void Fq_longErr(); 193 | 194 | #endif 195 | 196 | // Pending functions to convert 197 | 198 | void Fq_str2element(PFqElement pE, char const*s, uint base); 199 | char *Fq_element2str(PFqElement pE); 200 | void Fq_idiv(PFqElement r, PFqElement a, PFqElement b); 201 | void Fq_mod(PFqElement r, PFqElement a, PFqElement b); 202 | void Fq_inv(PFqElement r, PFqElement a); 203 | void Fq_div(PFqElement r, PFqElement a, PFqElement b); 204 | void Fq_pow(PFqElement r, PFqElement a, PFqElement b); 205 | 206 | class RawFq { 207 | 208 | public: 209 | const static int N64 = Fq_N64; 210 | const static int MaxBits = 254; 211 | 212 | 213 | struct Element { 214 | FqRawElement v; 215 | }; 216 | 217 | private: 218 | Element fZero; 219 | Element fOne; 220 | Element fNegOne; 221 | 222 | public: 223 | 224 | RawFq(); 225 | ~RawFq(); 226 | 227 | const Element &zero() { return fZero; }; 228 | const Element &one() { return fOne; }; 229 | const Element &negOne() { return fNegOne; }; 230 | Element set(int value); 231 | void set(Element &r, int value); 232 | 233 | void fromString(Element &r, const std::string &n, uint32_t radix = 10); 234 | std::string toString(const Element &a, uint32_t radix = 10); 235 | 236 | void inline copy(Element &r, const Element &a) { Fq_rawCopy(r.v, a.v); }; 237 | void inline swap(Element &a, Element &b) { Fq_rawSwap(a.v, b.v); }; 238 | void inline add(Element &r, const Element &a, const Element &b) { Fq_rawAdd(r.v, a.v, b.v); }; 239 | void inline sub(Element &r, const Element &a, const Element &b) { Fq_rawSub(r.v, a.v, b.v); }; 240 | void inline mul(Element &r, const Element &a, const Element &b) { Fq_rawMMul(r.v, a.v, b.v); }; 241 | 242 | Element inline add(const Element &a, const Element &b) { Element r; Fq_rawAdd(r.v, a.v, b.v); return r;}; 243 | Element inline sub(const Element &a, const Element &b) { Element r; Fq_rawSub(r.v, a.v, b.v); return r;}; 244 | Element inline mul(const Element &a, const Element &b) { Element r; Fq_rawMMul(r.v, a.v, b.v); return r;}; 245 | 246 | Element inline neg(const Element &a) { Element r; Fq_rawNeg(r.v, a.v); return r; }; 247 | Element inline square(const Element &a) { Element r; Fq_rawMSquare(r.v, a.v); return r; }; 248 | 249 | Element inline add(int a, const Element &b) { return add(set(a), b);}; 250 | Element inline sub(int a, const Element &b) { return sub(set(a), b);}; 251 | Element inline mul(int a, const Element &b) { return mul(set(a), b);}; 252 | 253 | Element inline add(const Element &a, int b) { return add(a, set(b));}; 254 | Element inline sub(const Element &a, int b) { return sub(a, set(b));}; 255 | Element inline mul(const Element &a, int b) { return mul(a, set(b));}; 256 | 257 | void inline mul1(Element &r, const Element &a, uint64_t b) { Fq_rawMMul1(r.v, a.v, b); }; 258 | void inline neg(Element &r, const Element &a) { Fq_rawNeg(r.v, a.v); }; 259 | void inline square(Element &r, const Element &a) { Fq_rawMSquare(r.v, a.v); }; 260 | void inv(Element &r, const Element &a); 261 | void div(Element &r, const Element &a, const Element &b); 262 | void exp(Element &r, const Element &base, uint8_t* scalar, unsigned int scalarSize); 263 | 264 | void inline toMontgomery(Element &r, const Element &a) { Fq_rawToMontgomery(r.v, a.v); }; 265 | void inline fromMontgomery(Element &r, const Element &a) { Fq_rawFromMontgomery(r.v, a.v); }; 266 | int inline eq(const Element &a, const Element &b) { return Fq_rawIsEq(a.v, b.v); }; 267 | int inline isZero(const Element &a) { return Fq_rawIsZero(a.v); }; 268 | 269 | void toMpz(mpz_t r, const Element &a); 270 | void fromMpz(Element &a, const mpz_t r); 271 | 272 | int toRprBE(const Element &element, uint8_t *data, int bytes); 273 | int fromRprBE(Element &element, const uint8_t *data, int bytes); 274 | 275 | int bytes ( void ) { return Fq_N64 * 8; }; 276 | 277 | void fromUI(Element &r, unsigned long int v); 278 | 279 | static RawFq field; 280 | 281 | }; 282 | 283 | 284 | #endif // __FQ_H 285 | 286 | 287 | 288 | -------------------------------------------------------------------------------- /build/fq_element.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FQ_ELEMENT_HPP 2 | #define FQ_ELEMENT_HPP 3 | 4 | #include 5 | 6 | #define Fq_N64 4 7 | #define Fq_SHORT 0x00000000 8 | #define Fq_MONTGOMERY 0x40000000 9 | #define Fq_SHORTMONTGOMERY 0x40000000 10 | #define Fq_LONG 0x80000000 11 | #define Fq_LONGMONTGOMERY 0xC0000000 12 | 13 | typedef uint64_t FqRawElement[Fq_N64]; 14 | 15 | typedef struct __attribute__((__packed__)) { 16 | int32_t shortVal; 17 | uint32_t type; 18 | FqRawElement longVal; 19 | } FqElement; 20 | 21 | typedef FqElement *PFqElement; 22 | 23 | #endif // FQ_ELEMENT_HPP 24 | -------------------------------------------------------------------------------- /build/fq_raw_generic.cpp: -------------------------------------------------------------------------------- 1 | #include "fq_element.hpp" 2 | #include 3 | #include 4 | 5 | static uint64_t Fq_rawq[] = {0x3c208c16d87cfd47,0x97816a916871ca8d,0xb85045b68181585d,0x30644e72e131a029, 0}; 6 | static FqRawElement Fq_rawR2 = {0xf32cfc5b538afa89,0xb5e71911d44501fb,0x47ab1eff0a417ff6,0x06d89f71cab8351f}; 7 | static uint64_t Fq_np = {0x87d20782e4866389}; 8 | static uint64_t lboMask = 0x3fffffffffffffff; 9 | 10 | 11 | void Fq_rawAdd(FqRawElement pRawResult, const FqRawElement pRawA, const FqRawElement pRawB) 12 | { 13 | uint64_t carry = mpn_add_n(pRawResult, pRawA, pRawB, Fq_N64); 14 | 15 | if(carry || mpn_cmp(pRawResult, Fq_rawq, Fq_N64) >= 0) 16 | { 17 | mpn_sub_n(pRawResult, pRawResult, Fq_rawq, Fq_N64); 18 | } 19 | } 20 | 21 | void Fq_rawAddLS(FqRawElement pRawResult, FqRawElement pRawA, uint64_t rawB) 22 | { 23 | uint64_t carry = mpn_add_1(pRawResult, pRawA, Fq_N64, rawB); 24 | 25 | if(carry || mpn_cmp(pRawResult, Fq_rawq, Fq_N64) >= 0) 26 | { 27 | mpn_sub_n(pRawResult, pRawResult, Fq_rawq, Fq_N64); 28 | } 29 | } 30 | 31 | void Fq_rawSub(FqRawElement pRawResult, const FqRawElement pRawA, const FqRawElement pRawB) 32 | { 33 | uint64_t carry = mpn_sub_n(pRawResult, pRawA, pRawB, Fq_N64); 34 | 35 | if(carry) 36 | { 37 | mpn_add_n(pRawResult, pRawResult, Fq_rawq, Fq_N64); 38 | } 39 | } 40 | 41 | void Fq_rawSubRegular(FqRawElement pRawResult, FqRawElement pRawA, FqRawElement pRawB) 42 | { 43 | mpn_sub_n(pRawResult, pRawA, pRawB, Fq_N64); 44 | } 45 | 46 | void Fq_rawSubSL(FqRawElement pRawResult, uint64_t rawA, FqRawElement pRawB) 47 | { 48 | FqRawElement pRawA = {rawA, 0, 0, 0}; 49 | 50 | uint64_t carry = mpn_sub_n(pRawResult, pRawA, pRawB, Fq_N64); 51 | 52 | if(carry) 53 | { 54 | mpn_add_n(pRawResult, pRawResult, Fq_rawq, Fq_N64); 55 | } 56 | } 57 | 58 | void Fq_rawSubLS(FqRawElement pRawResult, FqRawElement pRawA, uint64_t rawB) 59 | { 60 | uint64_t carry = mpn_sub_1(pRawResult, pRawA, Fq_N64, rawB); 61 | 62 | if(carry) 63 | { 64 | mpn_add_n(pRawResult, pRawResult, Fq_rawq, Fq_N64); 65 | } 66 | } 67 | 68 | void Fq_rawNeg(FqRawElement pRawResult, const FqRawElement pRawA) 69 | { 70 | const uint64_t zero[Fq_N64] = {0, 0, 0, 0}; 71 | 72 | if (mpn_cmp(pRawA, zero, Fq_N64) != 0) 73 | { 74 | mpn_sub_n(pRawResult, Fq_rawq, pRawA, Fq_N64); 75 | } 76 | else 77 | { 78 | mpn_copyi(pRawResult, zero, Fq_N64); 79 | } 80 | } 81 | 82 | // Substracts a long element and a short element form 0 83 | void Fq_rawNegLS(FqRawElement pRawResult, FqRawElement pRawA, uint64_t rawB) 84 | { 85 | uint64_t carry1 = mpn_sub_1(pRawResult, Fq_rawq, Fq_N64, rawB); 86 | uint64_t carry2 = mpn_sub_n(pRawResult, pRawResult, pRawA, Fq_N64); 87 | 88 | if (carry1 || carry2) 89 | { 90 | mpn_add_n(pRawResult, pRawResult, Fq_rawq, Fq_N64); 91 | } 92 | } 93 | 94 | void Fq_rawCopy(FqRawElement pRawResult, const FqRawElement pRawA) 95 | { 96 | pRawResult[0] = pRawA[0]; 97 | pRawResult[1] = pRawA[1]; 98 | pRawResult[2] = pRawA[2]; 99 | pRawResult[3] = pRawA[3]; 100 | } 101 | 102 | int Fq_rawIsEq(const FqRawElement pRawA, const FqRawElement pRawB) 103 | { 104 | return mpn_cmp(pRawA, pRawB, Fq_N64) == 0; 105 | } 106 | 107 | void Fq_rawMMul(FqRawElement pRawResult, const FqRawElement pRawA, const FqRawElement pRawB) 108 | { 109 | const mp_size_t N = Fq_N64+1; 110 | const uint64_t *mq = Fq_rawq; 111 | 112 | uint64_t np0; 113 | 114 | uint64_t product0[N] = {0}; 115 | uint64_t product1[N] = {0}; 116 | uint64_t product2[N] = {0}; 117 | uint64_t product3[N] = {0}; 118 | 119 | product0[4] = mpn_mul_1(product0, pRawB, Fq_N64, pRawA[0]); 120 | 121 | np0 = Fq_np * product0[0]; 122 | product1[1] = mpn_addmul_1(product0, mq, N, np0); 123 | 124 | product1[4] = mpn_addmul_1(product1, pRawB, Fq_N64, pRawA[1]); 125 | mpn_add(product1, product1, N, product0+1, N-1); 126 | 127 | np0 = Fq_np * product1[0]; 128 | product2[1] = mpn_addmul_1(product1, mq, N, np0); 129 | 130 | product2[4] = mpn_addmul_1(product2, pRawB, Fq_N64, pRawA[2]); 131 | mpn_add(product2, product2, N, product1+1, N-1); 132 | 133 | np0 = Fq_np * product2[0]; 134 | product3[1] = mpn_addmul_1(product2, mq, N, np0); 135 | 136 | product3[4] = mpn_addmul_1(product3, pRawB, Fq_N64, pRawA[3]); 137 | mpn_add(product3, product3, N, product2+1, N-1); 138 | 139 | np0 = Fq_np * product3[0]; 140 | mpn_addmul_1(product3, mq, N, np0); 141 | 142 | mpn_copyi(pRawResult, product3+1, Fq_N64); 143 | 144 | if (mpn_cmp(pRawResult, mq, Fq_N64) >= 0) 145 | { 146 | mpn_sub_n(pRawResult, pRawResult, mq, Fq_N64); 147 | } 148 | } 149 | 150 | void Fq_rawMSquare(FqRawElement pRawResult, const FqRawElement pRawA) 151 | { 152 | Fq_rawMMul(pRawResult, pRawA, pRawA); 153 | } 154 | 155 | void Fq_rawMMul1(FqRawElement pRawResult, const FqRawElement pRawA, uint64_t pRawB) 156 | { 157 | const mp_size_t N = Fq_N64+1; 158 | const uint64_t *mq = Fq_rawq; 159 | 160 | uint64_t np0; 161 | 162 | uint64_t product0[N] = {0}; 163 | uint64_t product1[N] = {0}; 164 | uint64_t product2[N] = {0}; 165 | uint64_t product3[N] = {0}; 166 | 167 | product0[4] = mpn_mul_1(product0, pRawA, Fq_N64, pRawB); 168 | 169 | np0 = Fq_np * product0[0]; 170 | product1[1] = mpn_addmul_1(product0, mq, N, np0); 171 | mpn_add(product1, product1, N, product0+1, N-1); 172 | 173 | np0 = Fq_np * product1[0]; 174 | product2[1] = mpn_addmul_1(product1, mq, N, np0); 175 | mpn_add(product2, product2, N, product1+1, N-1); 176 | 177 | np0 = Fq_np * product2[0]; 178 | product3[1] = mpn_addmul_1(product2, mq, N, np0); 179 | mpn_add(product3, product3, N, product2+1, N-1); 180 | 181 | np0 = Fq_np * product3[0]; 182 | mpn_addmul_1(product3, mq, N, np0); 183 | 184 | mpn_copyi(pRawResult, product3+1, Fq_N64); 185 | 186 | if (mpn_cmp(pRawResult, mq, Fq_N64) >= 0) 187 | { 188 | mpn_sub_n(pRawResult, pRawResult, mq, Fq_N64); 189 | } 190 | } 191 | 192 | void Fq_rawToMontgomery(FqRawElement pRawResult, const FqRawElement &pRawA) 193 | { 194 | Fq_rawMMul(pRawResult, pRawA, Fq_rawR2); 195 | } 196 | 197 | void Fq_rawFromMontgomery(FqRawElement pRawResult, const FqRawElement &pRawA) 198 | { 199 | const mp_size_t N = Fq_N64+1; 200 | const uint64_t *mq = Fq_rawq; 201 | 202 | uint64_t np0; 203 | 204 | uint64_t product0[N]; 205 | uint64_t product1[N] = {0}; 206 | uint64_t product2[N] = {0}; 207 | uint64_t product3[N] = {0}; 208 | 209 | mpn_copyi(product0, pRawA, Fq_N64); product0[4] = 0; 210 | 211 | np0 = Fq_np * product0[0]; 212 | product1[1] = mpn_addmul_1(product0, mq, N, np0); 213 | mpn_add(product1, product1, N, product0+1, N-1); 214 | 215 | np0 = Fq_np * product1[0]; 216 | product2[1] = mpn_addmul_1(product1, mq, N, np0); 217 | mpn_add(product2, product2, N, product1+1, N-1); 218 | 219 | np0 = Fq_np * product2[0]; 220 | product3[1] = mpn_addmul_1(product2, mq, N, np0); 221 | mpn_add(product3, product3, N, product2+1, N-1); 222 | 223 | np0 = Fq_np * product3[0]; 224 | mpn_addmul_1(product3, mq, N, np0); 225 | 226 | mpn_copyi(pRawResult, product3+1, Fq_N64); 227 | 228 | if (mpn_cmp(pRawResult, mq, Fq_N64) >= 0) 229 | { 230 | mpn_sub_n(pRawResult, pRawResult, mq, Fq_N64); 231 | } 232 | } 233 | 234 | int Fq_rawIsZero(const FqRawElement rawA) 235 | { 236 | return mpn_zero_p(rawA, Fq_N64) ? 1 : 0; 237 | } 238 | 239 | int Fq_rawCmp(FqRawElement pRawA, FqRawElement pRawB) 240 | { 241 | return mpn_cmp(pRawA, pRawB, Fq_N64); 242 | } 243 | 244 | void Fq_rawSwap(FqRawElement pRawResult, FqRawElement pRawA) 245 | { 246 | FqRawElement temp; 247 | 248 | temp[0] = pRawResult[0]; 249 | temp[1] = pRawResult[1]; 250 | temp[2] = pRawResult[2]; 251 | temp[3] = pRawResult[3]; 252 | 253 | pRawResult[0] = pRawA[0]; 254 | pRawResult[1] = pRawA[1]; 255 | pRawResult[2] = pRawA[2]; 256 | pRawResult[3] = pRawA[3]; 257 | 258 | pRawA[0] = temp[0]; 259 | pRawA[1] = temp[1]; 260 | pRawA[2] = temp[2]; 261 | pRawA[3] = temp[3]; 262 | } 263 | 264 | void Fq_rawCopyS2L(FqRawElement pRawResult, int64_t val) 265 | { 266 | pRawResult[0] = val; 267 | pRawResult[1] = 0; 268 | pRawResult[2] = 0; 269 | pRawResult[3] = 0; 270 | 271 | if (val < 0) 272 | { 273 | pRawResult[1] = -1; 274 | pRawResult[2] = -1; 275 | pRawResult[3] = -1; 276 | 277 | mpn_add_n(pRawResult, pRawResult, Fq_rawq, Fq_N64); 278 | } 279 | } 280 | 281 | 282 | void Fq_rawAnd(FqRawElement pRawResult, FqRawElement pRawA, FqRawElement pRawB) 283 | { 284 | mpn_and_n(pRawResult, pRawA, pRawB, Fq_N64); 285 | 286 | pRawResult[3] &= lboMask; 287 | 288 | if (mpn_cmp(pRawResult, Fq_rawq, Fq_N64) >= 0) 289 | { 290 | mpn_sub_n(pRawResult, pRawResult, Fq_rawq, Fq_N64); 291 | } 292 | } 293 | 294 | void Fq_rawOr(FqRawElement pRawResult, FqRawElement pRawA, FqRawElement pRawB) 295 | { 296 | mpn_ior_n(pRawResult, pRawA, pRawB, Fq_N64); 297 | 298 | pRawResult[3] &= lboMask; 299 | 300 | if (mpn_cmp(pRawResult, Fq_rawq, Fq_N64) >= 0) 301 | { 302 | mpn_sub_n(pRawResult, pRawResult, Fq_rawq, Fq_N64); 303 | } 304 | } 305 | 306 | void Fq_rawXor(FqRawElement pRawResult, FqRawElement pRawA, FqRawElement pRawB) 307 | { 308 | mpn_xor_n(pRawResult, pRawA, pRawB, Fq_N64); 309 | 310 | pRawResult[3] &= lboMask; 311 | 312 | if (mpn_cmp(pRawResult, Fq_rawq, Fq_N64) >= 0) 313 | { 314 | mpn_sub_n(pRawResult, pRawResult, Fq_rawq, Fq_N64); 315 | } 316 | } 317 | 318 | void Fq_rawShl(FqRawElement r, FqRawElement a, uint64_t b) 319 | { 320 | uint64_t bit_shift = b % 64; 321 | uint64_t word_shift = b / 64; 322 | uint64_t word_count = Fq_N64 - word_shift; 323 | 324 | mpn_copyi(r + word_shift, a, word_count); 325 | std::memset(r, 0, word_shift * sizeof(uint64_t)); 326 | 327 | if (bit_shift) 328 | { 329 | mpn_lshift(r, r, Fq_N64, bit_shift); 330 | } 331 | 332 | r[3] &= lboMask; 333 | 334 | if (mpn_cmp(r, Fq_rawq, Fq_N64) >= 0) 335 | { 336 | mpn_sub_n(r, r, Fq_rawq, Fq_N64); 337 | } 338 | } 339 | 340 | void Fq_rawShr(FqRawElement r, FqRawElement a, uint64_t b) 341 | { 342 | const uint64_t bit_shift = b % 64; 343 | const uint64_t word_shift = b / 64; 344 | const uint64_t word_count = Fq_N64 - word_shift; 345 | 346 | mpn_copyi(r, a + word_shift, word_count); 347 | std::memset(r + word_count, 0, word_shift * sizeof(uint64_t)); 348 | 349 | if (bit_shift) 350 | { 351 | mpn_rshift(r, r, Fq_N64, bit_shift); 352 | } 353 | } 354 | 355 | void Fq_rawNot(FqRawElement pRawResult, FqRawElement pRawA) 356 | { 357 | mpn_com(pRawResult, pRawA, Fq_N64); 358 | 359 | pRawResult[3] &= lboMask; 360 | 361 | if (mpn_cmp(pRawResult, Fq_rawq, Fq_N64) >= 0) 362 | { 363 | mpn_sub_n(pRawResult, pRawResult, Fq_rawq, Fq_N64); 364 | } 365 | } 366 | -------------------------------------------------------------------------------- /build/fr.cpp: -------------------------------------------------------------------------------- 1 | #include "fr.hpp" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | static mpz_t q; 10 | static mpz_t zero; 11 | static mpz_t one; 12 | static mpz_t mask; 13 | static size_t nBits; 14 | static bool initialized = false; 15 | 16 | void Fr_toMpz(mpz_t r, PFrElement pE) { 17 | FrElement tmp; 18 | Fr_toNormal(&tmp, pE); 19 | if (!(tmp.type & Fr_LONG)) { 20 | mpz_set_si(r, tmp.shortVal); 21 | if (tmp.shortVal<0) { 22 | mpz_add(r, r, q); 23 | } 24 | } else { 25 | mpz_import(r, Fr_N64, -1, 8, -1, 0, (const void *)tmp.longVal); 26 | } 27 | } 28 | 29 | void Fr_fromMpz(PFrElement pE, mpz_t v) { 30 | if (mpz_fits_sint_p(v)) { 31 | pE->type = Fr_SHORT; 32 | pE->shortVal = mpz_get_si(v); 33 | } else { 34 | pE->type = Fr_LONG; 35 | for (int i=0; ilongVal[i] = 0; 36 | mpz_export((void *)(pE->longVal), NULL, -1, 8, -1, 0, v); 37 | } 38 | } 39 | 40 | 41 | bool Fr_init() { 42 | if (initialized) return false; 43 | initialized = true; 44 | mpz_init(q); 45 | mpz_import(q, Fr_N64, -1, 8, -1, 0, (const void *)Fr_q.longVal); 46 | mpz_init_set_ui(zero, 0); 47 | mpz_init_set_ui(one, 1); 48 | nBits = mpz_sizeinbase (q, 2); 49 | mpz_init(mask); 50 | mpz_mul_2exp(mask, one, nBits); 51 | mpz_sub(mask, mask, one); 52 | return true; 53 | } 54 | 55 | void Fr_str2element(PFrElement pE, char const *s, uint base) { 56 | mpz_t mr; 57 | mpz_init_set_str(mr, s, base); 58 | mpz_fdiv_r(mr, mr, q); 59 | Fr_fromMpz(pE, mr); 60 | mpz_clear(mr); 61 | } 62 | 63 | char *Fr_element2str(PFrElement pE) { 64 | FrElement tmp; 65 | mpz_t r; 66 | if (!(pE->type & Fr_LONG)) { 67 | if (pE->shortVal>=0) { 68 | char *r = new char[32]; 69 | sprintf(r, "%d", pE->shortVal); 70 | return r; 71 | } else { 72 | mpz_init_set_si(r, pE->shortVal); 73 | mpz_add(r, r, q); 74 | } 75 | } else { 76 | Fr_toNormal(&tmp, pE); 77 | mpz_init(r); 78 | mpz_import(r, Fr_N64, -1, 8, -1, 0, (const void *)tmp.longVal); 79 | } 80 | char *res = mpz_get_str (0, 10, r); 81 | mpz_clear(r); 82 | return res; 83 | } 84 | 85 | void Fr_idiv(PFrElement r, PFrElement a, PFrElement b) { 86 | mpz_t ma; 87 | mpz_t mb; 88 | mpz_t mr; 89 | mpz_init(ma); 90 | mpz_init(mb); 91 | mpz_init(mr); 92 | 93 | Fr_toMpz(ma, a); 94 | // char *s1 = mpz_get_str (0, 10, ma); 95 | // printf("s1 %s\n", s1); 96 | Fr_toMpz(mb, b); 97 | // char *s2 = mpz_get_str (0, 10, mb); 98 | // printf("s2 %s\n", s2); 99 | mpz_fdiv_q(mr, ma, mb); 100 | // char *sr = mpz_get_str (0, 10, mr); 101 | // printf("r %s\n", sr); 102 | Fr_fromMpz(r, mr); 103 | 104 | mpz_clear(ma); 105 | mpz_clear(mb); 106 | mpz_clear(mr); 107 | } 108 | 109 | void Fr_mod(PFrElement r, PFrElement a, PFrElement b) { 110 | mpz_t ma; 111 | mpz_t mb; 112 | mpz_t mr; 113 | mpz_init(ma); 114 | mpz_init(mb); 115 | mpz_init(mr); 116 | 117 | Fr_toMpz(ma, a); 118 | Fr_toMpz(mb, b); 119 | mpz_fdiv_r(mr, ma, mb); 120 | Fr_fromMpz(r, mr); 121 | 122 | mpz_clear(ma); 123 | mpz_clear(mb); 124 | mpz_clear(mr); 125 | } 126 | 127 | void Fr_pow(PFrElement r, PFrElement a, PFrElement b) { 128 | mpz_t ma; 129 | mpz_t mb; 130 | mpz_t mr; 131 | mpz_init(ma); 132 | mpz_init(mb); 133 | mpz_init(mr); 134 | 135 | Fr_toMpz(ma, a); 136 | Fr_toMpz(mb, b); 137 | mpz_powm(mr, ma, mb, q); 138 | Fr_fromMpz(r, mr); 139 | 140 | mpz_clear(ma); 141 | mpz_clear(mb); 142 | mpz_clear(mr); 143 | } 144 | 145 | void Fr_inv(PFrElement r, PFrElement a) { 146 | mpz_t ma; 147 | mpz_t mr; 148 | mpz_init(ma); 149 | mpz_init(mr); 150 | 151 | Fr_toMpz(ma, a); 152 | mpz_invert(mr, ma, q); 153 | Fr_fromMpz(r, mr); 154 | mpz_clear(ma); 155 | mpz_clear(mr); 156 | } 157 | 158 | void Fr_div(PFrElement r, PFrElement a, PFrElement b) { 159 | FrElement tmp; 160 | Fr_inv(&tmp, b); 161 | Fr_mul(r, a, &tmp); 162 | } 163 | 164 | void Fr_fail() { 165 | throw std::runtime_error("Fr error"); 166 | } 167 | 168 | void Fr_longErr() 169 | { 170 | Fr_fail(); 171 | } 172 | 173 | RawFr::RawFr() { 174 | Fr_init(); 175 | set(fZero, 0); 176 | set(fOne, 1); 177 | neg(fNegOne, fOne); 178 | } 179 | 180 | RawFr::~RawFr() { 181 | } 182 | 183 | void RawFr::fromString(Element &r, const std::string &s, uint32_t radix) { 184 | mpz_t mr; 185 | mpz_init_set_str(mr, s.c_str(), radix); 186 | mpz_fdiv_r(mr, mr, q); 187 | for (int i=0; i>3] & (1 << (p & 0x7))) 259 | void RawFr::exp(Element &r, const Element &base, uint8_t* scalar, unsigned int scalarSize) { 260 | bool oneFound = false; 261 | Element copyBase; 262 | copy(copyBase, base); 263 | for (int i=scalarSize*8-1; i>=0; i--) { 264 | if (!oneFound) { 265 | if ( !BIT_IS_SET(scalar, i) ) continue; 266 | copy(r, copyBase); 267 | oneFound = true; 268 | continue; 269 | } 270 | square(r, r); 271 | if ( BIT_IS_SET(scalar, i) ) { 272 | mul(r, r, copyBase); 273 | } 274 | } 275 | if (!oneFound) { 276 | copy(r, fOne); 277 | } 278 | } 279 | 280 | void RawFr::toMpz(mpz_t r, const Element &a) { 281 | Element tmp; 282 | Fr_rawFromMontgomery(tmp.v, a.v); 283 | mpz_import(r, Fr_N64, -1, 8, -1, 0, (const void *)tmp.v); 284 | } 285 | 286 | void RawFr::fromMpz(Element &r, const mpz_t a) { 287 | for (int i=0; i 6 | #include 7 | #include 8 | 9 | #ifdef __APPLE__ 10 | #include // typedef unsigned int uint; 11 | #endif // __APPLE__ 12 | 13 | extern FrElement Fr_q; 14 | extern FrElement Fr_R2; 15 | extern FrElement Fr_R3; 16 | extern FrRawElement Fr_rawq; 17 | extern FrRawElement Fr_rawR3; 18 | 19 | #ifdef USE_ASM 20 | 21 | #if defined(ARCH_X86_64) 22 | 23 | extern "C" void Fr_copy(PFrElement r, PFrElement a); 24 | extern "C" void Fr_copyn(PFrElement r, PFrElement a, int n); 25 | extern "C" void Fr_add(PFrElement r, PFrElement a, PFrElement b); 26 | extern "C" void Fr_sub(PFrElement r, PFrElement a, PFrElement b); 27 | extern "C" void Fr_neg(PFrElement r, PFrElement a); 28 | extern "C" void Fr_mul(PFrElement r, PFrElement a, PFrElement b); 29 | extern "C" void Fr_square(PFrElement r, PFrElement a); 30 | extern "C" void Fr_band(PFrElement r, PFrElement a, PFrElement b); 31 | extern "C" void Fr_bor(PFrElement r, PFrElement a, PFrElement b); 32 | extern "C" void Fr_bxor(PFrElement r, PFrElement a, PFrElement b); 33 | extern "C" void Fr_bnot(PFrElement r, PFrElement a); 34 | extern "C" void Fr_shl(PFrElement r, PFrElement a, PFrElement b); 35 | extern "C" void Fr_shr(PFrElement r, PFrElement a, PFrElement b); 36 | extern "C" void Fr_eq(PFrElement r, PFrElement a, PFrElement b); 37 | extern "C" void Fr_neq(PFrElement r, PFrElement a, PFrElement b); 38 | extern "C" void Fr_lt(PFrElement r, PFrElement a, PFrElement b); 39 | extern "C" void Fr_gt(PFrElement r, PFrElement a, PFrElement b); 40 | extern "C" void Fr_leq(PFrElement r, PFrElement a, PFrElement b); 41 | extern "C" void Fr_geq(PFrElement r, PFrElement a, PFrElement b); 42 | extern "C" void Fr_land(PFrElement r, PFrElement a, PFrElement b); 43 | extern "C" void Fr_lor(PFrElement r, PFrElement a, PFrElement b); 44 | extern "C" void Fr_lnot(PFrElement r, PFrElement a); 45 | extern "C" void Fr_toNormal(PFrElement r, PFrElement a); 46 | extern "C" void Fr_toLongNormal(PFrElement r, PFrElement a); 47 | extern "C" void Fr_toMontgomery(PFrElement r, PFrElement a); 48 | 49 | extern "C" int Fr_isTrue(PFrElement pE); 50 | extern "C" int Fr_toInt(PFrElement pE); 51 | 52 | extern "C" void Fr_rawCopy(FrRawElement pRawResult, const FrRawElement pRawA); 53 | extern "C" void Fr_rawSwap(FrRawElement pRawResult, FrRawElement pRawA); 54 | extern "C" void Fr_rawAdd(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB); 55 | extern "C" void Fr_rawSub(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB); 56 | extern "C" void Fr_rawNeg(FrRawElement pRawResult, const FrRawElement pRawA); 57 | extern "C" void Fr_rawMMul(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB); 58 | extern "C" void Fr_rawMSquare(FrRawElement pRawResult, const FrRawElement pRawA); 59 | extern "C" void Fr_rawMMul1(FrRawElement pRawResult, const FrRawElement pRawA, uint64_t pRawB); 60 | extern "C" void Fr_rawToMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA); 61 | extern "C" void Fr_rawFromMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA); 62 | extern "C" int Fr_rawIsEq(const FrRawElement pRawA, const FrRawElement pRawB); 63 | extern "C" int Fr_rawIsZero(const FrRawElement pRawB); 64 | extern "C" void Fr_rawShl(FrRawElement r, FrRawElement a, uint64_t b); 65 | extern "C" void Fr_rawShr(FrRawElement r, FrRawElement a, uint64_t b); 66 | 67 | extern "C" void Fr_fail(); 68 | 69 | #elif defined(ARCH_ARM64) 70 | 71 | void Fr_copy(PFrElement r, PFrElement a); 72 | void Fr_mul(PFrElement r, PFrElement a, PFrElement b); 73 | void Fr_toNormal(PFrElement r, PFrElement a); 74 | 75 | void Fr_toLongNormal(PFrElement r, PFrElement a); 76 | int Fr_isTrue(PFrElement pE); 77 | void Fr_copyn(PFrElement r, PFrElement a, int n); 78 | void Fr_lt(PFrElement r, PFrElement a, PFrElement b); 79 | int Fr_toInt(PFrElement pE); 80 | void Fr_shr(PFrElement r, PFrElement a, PFrElement b); 81 | void Fr_shl(PFrElement r, PFrElement a, PFrElement b); 82 | void Fr_band(PFrElement r, PFrElement a, PFrElement b); 83 | void Fr_bor(PFrElement r, PFrElement a, PFrElement b); 84 | void Fr_bxor(PFrElement r, PFrElement a, PFrElement b); 85 | void Fr_bnot(PFrElement r, PFrElement a); 86 | void Fr_sub(PFrElement r, PFrElement a, PFrElement b); 87 | void Fr_eq(PFrElement r, PFrElement a, PFrElement b); 88 | void Fr_neq(PFrElement r, PFrElement a, PFrElement b); 89 | void Fr_add(PFrElement r, PFrElement a, PFrElement b); 90 | void Fr_gt(PFrElement r, PFrElement a, PFrElement b); 91 | void Fr_leq(PFrElement r, PFrElement a, PFrElement b); 92 | void Fr_geq(PFrElement r, PFrElement a, PFrElement b); 93 | void Fr_lor(PFrElement r, PFrElement a, PFrElement b); 94 | void Fr_lnot(PFrElement r, PFrElement a); 95 | void Fr_land(PFrElement r, PFrElement a, PFrElement b); 96 | void Fr_neg(PFrElement r, PFrElement a); 97 | void Fr_toMontgomery(PFrElement r, PFrElement a); 98 | void Fr_square(PFrElement r, PFrElement a); 99 | 100 | extern "C" void Fr_rawCopy(FrRawElement pRawResult, const FrRawElement pRawA); 101 | extern "C" void Fr_rawSwap(FrRawElement pRawResult, FrRawElement pRawA); 102 | extern "C" void Fr_rawAdd(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB); 103 | extern "C" void Fr_rawSub(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB); 104 | extern "C" void Fr_rawNeg(FrRawElement pRawResult, const FrRawElement pRawA); 105 | extern "C" void Fr_rawMMul(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB); 106 | void Fr_rawMSquare(FrRawElement pRawResult, const FrRawElement pRawA); 107 | extern "C" void Fr_rawMMul1(FrRawElement pRawResult, const FrRawElement pRawA, uint64_t pRawB); 108 | void Fr_rawToMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA); 109 | extern "C" void Fr_rawFromMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA); 110 | extern "C" int Fr_rawIsEq(const FrRawElement pRawA, const FrRawElement pRawB); 111 | extern "C" int Fr_rawIsZero(const FrRawElement pRawB); 112 | void Fr_rawZero(FrRawElement pRawResult); 113 | extern "C" void Fr_rawCopyS2L(FrRawElement pRawResult, int64_t val); 114 | extern "C" void Fr_rawAddLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB); 115 | extern "C" void Fr_rawSubSL(FrRawElement pRawResult, uint64_t rawA, FrRawElement pRawB); 116 | extern "C" void Fr_rawSubLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB); 117 | extern "C" void Fr_rawNegLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB); 118 | extern "C" int Fr_rawCmp(FrRawElement pRawA, FrRawElement pRawB); 119 | extern "C" void Fr_rawAnd(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB); 120 | extern "C" void Fr_rawOr(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB); 121 | extern "C" void Fr_rawXor(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB); 122 | extern "C" void Fr_rawShl(FrRawElement r, FrRawElement a, uint64_t b); 123 | extern "C" void Fr_rawShr(FrRawElement r, FrRawElement a, uint64_t b); 124 | extern "C" void Fr_rawNot(FrRawElement pRawResult, FrRawElement pRawA); 125 | extern "C" void Fr_rawSubRegular(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB); 126 | 127 | void Fr_fail(); 128 | void Fr_longErr(); 129 | 130 | #endif 131 | 132 | #else 133 | 134 | 135 | void Fr_copy(PFrElement r, PFrElement a); 136 | void Fr_mul(PFrElement r, PFrElement a, PFrElement b); 137 | void Fr_toNormal(PFrElement r, PFrElement a); 138 | 139 | void Fr_toLongNormal(PFrElement r, PFrElement a); 140 | int Fr_isTrue(PFrElement pE); 141 | void Fr_copyn(PFrElement r, PFrElement a, int n); 142 | void Fr_lt(PFrElement r, PFrElement a, PFrElement b); 143 | int Fr_toInt(PFrElement pE); 144 | void Fr_shl(PFrElement r, PFrElement a, PFrElement b); 145 | void Fr_shr(PFrElement r, PFrElement a, PFrElement b); 146 | void Fr_band(PFrElement r, PFrElement a, PFrElement b); 147 | void Fr_bor(PFrElement r, PFrElement a, PFrElement b); 148 | void Fr_bxor(PFrElement r, PFrElement a, PFrElement b); 149 | void Fr_bnot(PFrElement r, PFrElement a); 150 | void Fr_sub(PFrElement r, PFrElement a, PFrElement b); 151 | void Fr_eq(PFrElement r, PFrElement a, PFrElement b); 152 | void Fr_neq(PFrElement r, PFrElement a, PFrElement b); 153 | void Fr_add(PFrElement r, PFrElement a, PFrElement b); 154 | void Fr_gt(PFrElement r, PFrElement a, PFrElement b); 155 | void Fr_leq(PFrElement r, PFrElement a, PFrElement b); 156 | void Fr_geq(PFrElement r, PFrElement a, PFrElement b); 157 | void Fr_lor(PFrElement r, PFrElement a, PFrElement b); 158 | void Fr_lnot(PFrElement r, PFrElement a); 159 | void Fr_land(PFrElement r, PFrElement a, PFrElement b); 160 | void Fr_neg(PFrElement r, PFrElement a); 161 | void Fr_toMontgomery(PFrElement r, PFrElement a); 162 | void Fr_square(PFrElement r, PFrElement a); 163 | 164 | void Fr_rawCopy(FrRawElement pRawResult, const FrRawElement pRawA); 165 | void Fr_rawSwap(FrRawElement pRawResult, FrRawElement pRawA); 166 | void Fr_rawAdd(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB); 167 | void Fr_rawSub(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB); 168 | void Fr_rawNeg(FrRawElement pRawResult, const FrRawElement pRawA); 169 | void Fr_rawMMul(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB); 170 | void Fr_rawMSquare(FrRawElement pRawResult, const FrRawElement pRawA); 171 | void Fr_rawMMul1(FrRawElement pRawResult, const FrRawElement pRawA, uint64_t pRawB); 172 | void Fr_rawToMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA); 173 | void Fr_rawFromMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA); 174 | int Fr_rawIsEq(const FrRawElement pRawA, const FrRawElement pRawB); 175 | int Fr_rawIsZero(const FrRawElement pRawB); 176 | void Fr_rawZero(FrRawElement pRawResult); 177 | void Fr_rawCopyS2L(FrRawElement pRawResult, int64_t val); 178 | void Fr_rawAddLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB); 179 | void Fr_rawSubSL(FrRawElement pRawResult, uint64_t rawA, FrRawElement pRawB); 180 | void Fr_rawSubLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB); 181 | void Fr_rawNegLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB); 182 | int Fr_rawCmp(FrRawElement pRawA, FrRawElement pRawB); 183 | void Fr_rawAnd(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB); 184 | void Fr_rawOr(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB); 185 | void Fr_rawXor(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB); 186 | void Fr_rawShl(FrRawElement r, FrRawElement a, uint64_t b); 187 | void Fr_rawShr(FrRawElement r, FrRawElement a, uint64_t b); 188 | void Fr_rawNot(FrRawElement pRawResult, FrRawElement pRawA); 189 | void Fr_rawSubRegular(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB); 190 | 191 | void Fr_fail(); 192 | void Fr_longErr(); 193 | 194 | #endif 195 | 196 | // Pending functions to convert 197 | 198 | void Fr_str2element(PFrElement pE, char const*s, uint base); 199 | char *Fr_element2str(PFrElement pE); 200 | void Fr_idiv(PFrElement r, PFrElement a, PFrElement b); 201 | void Fr_mod(PFrElement r, PFrElement a, PFrElement b); 202 | void Fr_inv(PFrElement r, PFrElement a); 203 | void Fr_div(PFrElement r, PFrElement a, PFrElement b); 204 | void Fr_pow(PFrElement r, PFrElement a, PFrElement b); 205 | 206 | class RawFr { 207 | 208 | public: 209 | const static int N64 = Fr_N64; 210 | const static int MaxBits = 254; 211 | 212 | 213 | struct Element { 214 | FrRawElement v; 215 | }; 216 | 217 | private: 218 | Element fZero; 219 | Element fOne; 220 | Element fNegOne; 221 | 222 | public: 223 | 224 | RawFr(); 225 | ~RawFr(); 226 | 227 | const Element &zero() { return fZero; }; 228 | const Element &one() { return fOne; }; 229 | const Element &negOne() { return fNegOne; }; 230 | Element set(int value); 231 | void set(Element &r, int value); 232 | 233 | void fromString(Element &r, const std::string &n, uint32_t radix = 10); 234 | std::string toString(const Element &a, uint32_t radix = 10); 235 | 236 | void inline copy(Element &r, const Element &a) { Fr_rawCopy(r.v, a.v); }; 237 | void inline swap(Element &a, Element &b) { Fr_rawSwap(a.v, b.v); }; 238 | void inline add(Element &r, const Element &a, const Element &b) { Fr_rawAdd(r.v, a.v, b.v); }; 239 | void inline sub(Element &r, const Element &a, const Element &b) { Fr_rawSub(r.v, a.v, b.v); }; 240 | void inline mul(Element &r, const Element &a, const Element &b) { Fr_rawMMul(r.v, a.v, b.v); }; 241 | 242 | Element inline add(const Element &a, const Element &b) { Element r; Fr_rawAdd(r.v, a.v, b.v); return r;}; 243 | Element inline sub(const Element &a, const Element &b) { Element r; Fr_rawSub(r.v, a.v, b.v); return r;}; 244 | Element inline mul(const Element &a, const Element &b) { Element r; Fr_rawMMul(r.v, a.v, b.v); return r;}; 245 | 246 | Element inline neg(const Element &a) { Element r; Fr_rawNeg(r.v, a.v); return r; }; 247 | Element inline square(const Element &a) { Element r; Fr_rawMSquare(r.v, a.v); return r; }; 248 | 249 | Element inline add(int a, const Element &b) { return add(set(a), b);}; 250 | Element inline sub(int a, const Element &b) { return sub(set(a), b);}; 251 | Element inline mul(int a, const Element &b) { return mul(set(a), b);}; 252 | 253 | Element inline add(const Element &a, int b) { return add(a, set(b));}; 254 | Element inline sub(const Element &a, int b) { return sub(a, set(b));}; 255 | Element inline mul(const Element &a, int b) { return mul(a, set(b));}; 256 | 257 | void inline mul1(Element &r, const Element &a, uint64_t b) { Fr_rawMMul1(r.v, a.v, b); }; 258 | void inline neg(Element &r, const Element &a) { Fr_rawNeg(r.v, a.v); }; 259 | void inline square(Element &r, const Element &a) { Fr_rawMSquare(r.v, a.v); }; 260 | void inv(Element &r, const Element &a); 261 | void div(Element &r, const Element &a, const Element &b); 262 | void exp(Element &r, const Element &base, uint8_t* scalar, unsigned int scalarSize); 263 | 264 | void inline toMontgomery(Element &r, const Element &a) { Fr_rawToMontgomery(r.v, a.v); }; 265 | void inline fromMontgomery(Element &r, const Element &a) { Fr_rawFromMontgomery(r.v, a.v); }; 266 | int inline eq(const Element &a, const Element &b) { return Fr_rawIsEq(a.v, b.v); }; 267 | int inline isZero(const Element &a) { return Fr_rawIsZero(a.v); }; 268 | 269 | void toMpz(mpz_t r, const Element &a); 270 | void fromMpz(Element &a, const mpz_t r); 271 | 272 | int toRprBE(const Element &element, uint8_t *data, int bytes); 273 | int fromRprBE(Element &element, const uint8_t *data, int bytes); 274 | 275 | int bytes ( void ) { return Fr_N64 * 8; }; 276 | 277 | void fromUI(Element &r, unsigned long int v); 278 | 279 | static RawFr field; 280 | 281 | }; 282 | 283 | 284 | #endif // __FR_H 285 | 286 | 287 | 288 | -------------------------------------------------------------------------------- /build/fr_element.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FR_ELEMENT_HPP 2 | #define FR_ELEMENT_HPP 3 | 4 | #include 5 | 6 | #define Fr_N64 4 7 | #define Fr_SHORT 0x00000000 8 | #define Fr_MONTGOMERY 0x40000000 9 | #define Fr_SHORTMONTGOMERY 0x40000000 10 | #define Fr_LONG 0x80000000 11 | #define Fr_LONGMONTGOMERY 0xC0000000 12 | 13 | typedef uint64_t FrRawElement[Fr_N64]; 14 | 15 | typedef struct __attribute__((__packed__)) { 16 | int32_t shortVal; 17 | uint32_t type; 18 | FrRawElement longVal; 19 | } FrElement; 20 | 21 | typedef FrElement *PFrElement; 22 | 23 | #endif // FR_ELEMENT_HPP 24 | -------------------------------------------------------------------------------- /build/fr_raw_generic.cpp: -------------------------------------------------------------------------------- 1 | #include "fr_element.hpp" 2 | #include 3 | #include 4 | 5 | static uint64_t Fr_rawq[] = {0x43e1f593f0000001,0x2833e84879b97091,0xb85045b68181585d,0x30644e72e131a029, 0}; 6 | static FrRawElement Fr_rawR2 = {0x1bb8e645ae216da7,0x53fe3ab1e35c59e3,0x8c49833d53bb8085,0x0216d0b17f4e44a5}; 7 | static uint64_t Fr_np = {0xc2e1f593efffffff}; 8 | static uint64_t lboMask = 0x3fffffffffffffff; 9 | 10 | 11 | void Fr_rawAdd(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB) 12 | { 13 | uint64_t carry = mpn_add_n(pRawResult, pRawA, pRawB, Fr_N64); 14 | 15 | if(carry || mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0) 16 | { 17 | mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64); 18 | } 19 | } 20 | 21 | void Fr_rawAddLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB) 22 | { 23 | uint64_t carry = mpn_add_1(pRawResult, pRawA, Fr_N64, rawB); 24 | 25 | if(carry || mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0) 26 | { 27 | mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64); 28 | } 29 | } 30 | 31 | void Fr_rawSub(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB) 32 | { 33 | uint64_t carry = mpn_sub_n(pRawResult, pRawA, pRawB, Fr_N64); 34 | 35 | if(carry) 36 | { 37 | mpn_add_n(pRawResult, pRawResult, Fr_rawq, Fr_N64); 38 | } 39 | } 40 | 41 | void Fr_rawSubRegular(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB) 42 | { 43 | mpn_sub_n(pRawResult, pRawA, pRawB, Fr_N64); 44 | } 45 | 46 | void Fr_rawSubSL(FrRawElement pRawResult, uint64_t rawA, FrRawElement pRawB) 47 | { 48 | FrRawElement pRawA = {rawA, 0, 0, 0}; 49 | 50 | uint64_t carry = mpn_sub_n(pRawResult, pRawA, pRawB, Fr_N64); 51 | 52 | if(carry) 53 | { 54 | mpn_add_n(pRawResult, pRawResult, Fr_rawq, Fr_N64); 55 | } 56 | } 57 | 58 | void Fr_rawSubLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB) 59 | { 60 | uint64_t carry = mpn_sub_1(pRawResult, pRawA, Fr_N64, rawB); 61 | 62 | if(carry) 63 | { 64 | mpn_add_n(pRawResult, pRawResult, Fr_rawq, Fr_N64); 65 | } 66 | } 67 | 68 | void Fr_rawNeg(FrRawElement pRawResult, const FrRawElement pRawA) 69 | { 70 | const uint64_t zero[Fr_N64] = {0, 0, 0, 0}; 71 | 72 | if (mpn_cmp(pRawA, zero, Fr_N64) != 0) 73 | { 74 | mpn_sub_n(pRawResult, Fr_rawq, pRawA, Fr_N64); 75 | } 76 | else 77 | { 78 | mpn_copyi(pRawResult, zero, Fr_N64); 79 | } 80 | } 81 | 82 | // Substracts a long element and a short element form 0 83 | void Fr_rawNegLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB) 84 | { 85 | uint64_t carry1 = mpn_sub_1(pRawResult, Fr_rawq, Fr_N64, rawB); 86 | uint64_t carry2 = mpn_sub_n(pRawResult, pRawResult, pRawA, Fr_N64); 87 | 88 | if (carry1 || carry2) 89 | { 90 | mpn_add_n(pRawResult, pRawResult, Fr_rawq, Fr_N64); 91 | } 92 | } 93 | 94 | void Fr_rawCopy(FrRawElement pRawResult, const FrRawElement pRawA) 95 | { 96 | pRawResult[0] = pRawA[0]; 97 | pRawResult[1] = pRawA[1]; 98 | pRawResult[2] = pRawA[2]; 99 | pRawResult[3] = pRawA[3]; 100 | } 101 | 102 | int Fr_rawIsEq(const FrRawElement pRawA, const FrRawElement pRawB) 103 | { 104 | return mpn_cmp(pRawA, pRawB, Fr_N64) == 0; 105 | } 106 | 107 | void Fr_rawMMul(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB) 108 | { 109 | const mp_size_t N = Fr_N64+1; 110 | const uint64_t *mq = Fr_rawq; 111 | 112 | uint64_t np0; 113 | 114 | uint64_t product0[N] = {0}; 115 | uint64_t product1[N] = {0}; 116 | uint64_t product2[N] = {0}; 117 | uint64_t product3[N] = {0}; 118 | 119 | product0[4] = mpn_mul_1(product0, pRawB, Fr_N64, pRawA[0]); 120 | 121 | np0 = Fr_np * product0[0]; 122 | product1[1] = mpn_addmul_1(product0, mq, N, np0); 123 | 124 | product1[4] = mpn_addmul_1(product1, pRawB, Fr_N64, pRawA[1]); 125 | mpn_add(product1, product1, N, product0+1, N-1); 126 | 127 | np0 = Fr_np * product1[0]; 128 | product2[1] = mpn_addmul_1(product1, mq, N, np0); 129 | 130 | product2[4] = mpn_addmul_1(product2, pRawB, Fr_N64, pRawA[2]); 131 | mpn_add(product2, product2, N, product1+1, N-1); 132 | 133 | np0 = Fr_np * product2[0]; 134 | product3[1] = mpn_addmul_1(product2, mq, N, np0); 135 | 136 | product3[4] = mpn_addmul_1(product3, pRawB, Fr_N64, pRawA[3]); 137 | mpn_add(product3, product3, N, product2+1, N-1); 138 | 139 | np0 = Fr_np * product3[0]; 140 | mpn_addmul_1(product3, mq, N, np0); 141 | 142 | mpn_copyi(pRawResult, product3+1, Fr_N64); 143 | 144 | if (mpn_cmp(pRawResult, mq, Fr_N64) >= 0) 145 | { 146 | mpn_sub_n(pRawResult, pRawResult, mq, Fr_N64); 147 | } 148 | } 149 | 150 | void Fr_rawMSquare(FrRawElement pRawResult, const FrRawElement pRawA) 151 | { 152 | Fr_rawMMul(pRawResult, pRawA, pRawA); 153 | } 154 | 155 | void Fr_rawMMul1(FrRawElement pRawResult, const FrRawElement pRawA, uint64_t pRawB) 156 | { 157 | const mp_size_t N = Fr_N64+1; 158 | const uint64_t *mq = Fr_rawq; 159 | 160 | uint64_t np0; 161 | 162 | uint64_t product0[N] = {0}; 163 | uint64_t product1[N] = {0}; 164 | uint64_t product2[N] = {0}; 165 | uint64_t product3[N] = {0}; 166 | 167 | product0[4] = mpn_mul_1(product0, pRawA, Fr_N64, pRawB); 168 | 169 | np0 = Fr_np * product0[0]; 170 | product1[1] = mpn_addmul_1(product0, mq, N, np0); 171 | mpn_add(product1, product1, N, product0+1, N-1); 172 | 173 | np0 = Fr_np * product1[0]; 174 | product2[1] = mpn_addmul_1(product1, mq, N, np0); 175 | mpn_add(product2, product2, N, product1+1, N-1); 176 | 177 | np0 = Fr_np * product2[0]; 178 | product3[1] = mpn_addmul_1(product2, mq, N, np0); 179 | mpn_add(product3, product3, N, product2+1, N-1); 180 | 181 | np0 = Fr_np * product3[0]; 182 | mpn_addmul_1(product3, mq, N, np0); 183 | 184 | mpn_copyi(pRawResult, product3+1, Fr_N64); 185 | 186 | if (mpn_cmp(pRawResult, mq, Fr_N64) >= 0) 187 | { 188 | mpn_sub_n(pRawResult, pRawResult, mq, Fr_N64); 189 | } 190 | } 191 | 192 | void Fr_rawToMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA) 193 | { 194 | Fr_rawMMul(pRawResult, pRawA, Fr_rawR2); 195 | } 196 | 197 | void Fr_rawFromMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA) 198 | { 199 | const mp_size_t N = Fr_N64+1; 200 | const uint64_t *mq = Fr_rawq; 201 | 202 | uint64_t np0; 203 | 204 | uint64_t product0[N]; 205 | uint64_t product1[N] = {0}; 206 | uint64_t product2[N] = {0}; 207 | uint64_t product3[N] = {0}; 208 | 209 | mpn_copyi(product0, pRawA, Fr_N64); product0[4] = 0; 210 | 211 | np0 = Fr_np * product0[0]; 212 | product1[1] = mpn_addmul_1(product0, mq, N, np0); 213 | mpn_add(product1, product1, N, product0+1, N-1); 214 | 215 | np0 = Fr_np * product1[0]; 216 | product2[1] = mpn_addmul_1(product1, mq, N, np0); 217 | mpn_add(product2, product2, N, product1+1, N-1); 218 | 219 | np0 = Fr_np * product2[0]; 220 | product3[1] = mpn_addmul_1(product2, mq, N, np0); 221 | mpn_add(product3, product3, N, product2+1, N-1); 222 | 223 | np0 = Fr_np * product3[0]; 224 | mpn_addmul_1(product3, mq, N, np0); 225 | 226 | mpn_copyi(pRawResult, product3+1, Fr_N64); 227 | 228 | if (mpn_cmp(pRawResult, mq, Fr_N64) >= 0) 229 | { 230 | mpn_sub_n(pRawResult, pRawResult, mq, Fr_N64); 231 | } 232 | } 233 | 234 | int Fr_rawIsZero(const FrRawElement rawA) 235 | { 236 | return mpn_zero_p(rawA, Fr_N64) ? 1 : 0; 237 | } 238 | 239 | int Fr_rawCmp(FrRawElement pRawA, FrRawElement pRawB) 240 | { 241 | return mpn_cmp(pRawA, pRawB, Fr_N64); 242 | } 243 | 244 | void Fr_rawSwap(FrRawElement pRawResult, FrRawElement pRawA) 245 | { 246 | FrRawElement temp; 247 | 248 | temp[0] = pRawResult[0]; 249 | temp[1] = pRawResult[1]; 250 | temp[2] = pRawResult[2]; 251 | temp[3] = pRawResult[3]; 252 | 253 | pRawResult[0] = pRawA[0]; 254 | pRawResult[1] = pRawA[1]; 255 | pRawResult[2] = pRawA[2]; 256 | pRawResult[3] = pRawA[3]; 257 | 258 | pRawA[0] = temp[0]; 259 | pRawA[1] = temp[1]; 260 | pRawA[2] = temp[2]; 261 | pRawA[3] = temp[3]; 262 | } 263 | 264 | void Fr_rawCopyS2L(FrRawElement pRawResult, int64_t val) 265 | { 266 | pRawResult[0] = val; 267 | pRawResult[1] = 0; 268 | pRawResult[2] = 0; 269 | pRawResult[3] = 0; 270 | 271 | if (val < 0) 272 | { 273 | pRawResult[1] = -1; 274 | pRawResult[2] = -1; 275 | pRawResult[3] = -1; 276 | 277 | mpn_add_n(pRawResult, pRawResult, Fr_rawq, Fr_N64); 278 | } 279 | } 280 | 281 | void Fr_rawAnd(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB) 282 | { 283 | mpn_and_n(pRawResult, pRawA, pRawB, Fr_N64); 284 | 285 | pRawResult[3] &= lboMask; 286 | 287 | if (mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0) 288 | { 289 | mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64); 290 | } 291 | } 292 | 293 | void Fr_rawOr(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB) 294 | { 295 | mpn_ior_n(pRawResult, pRawA, pRawB, Fr_N64); 296 | 297 | pRawResult[3] &= lboMask; 298 | 299 | if (mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0) 300 | { 301 | mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64); 302 | } 303 | } 304 | 305 | void Fr_rawXor(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB) 306 | { 307 | mpn_xor_n(pRawResult, pRawA, pRawB, Fr_N64); 308 | 309 | pRawResult[3] &= lboMask; 310 | 311 | if (mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0) 312 | { 313 | mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64); 314 | } 315 | } 316 | 317 | void Fr_rawShl(FrRawElement r, FrRawElement a, uint64_t b) 318 | { 319 | uint64_t bit_shift = b % 64; 320 | uint64_t word_shift = b / 64; 321 | uint64_t word_count = Fr_N64 - word_shift; 322 | 323 | mpn_copyi(r + word_shift, a, word_count); 324 | std::memset(r, 0, word_shift * sizeof(uint64_t)); 325 | 326 | if (bit_shift) 327 | { 328 | mpn_lshift(r, r, Fr_N64, bit_shift); 329 | } 330 | 331 | r[3] &= lboMask; 332 | 333 | if (mpn_cmp(r, Fr_rawq, Fr_N64) >= 0) 334 | { 335 | mpn_sub_n(r, r, Fr_rawq, Fr_N64); 336 | } 337 | } 338 | 339 | void Fr_rawShr(FrRawElement r, FrRawElement a, uint64_t b) 340 | { 341 | const uint64_t bit_shift = b % 64; 342 | const uint64_t word_shift = b / 64; 343 | const uint64_t word_count = Fr_N64 - word_shift; 344 | 345 | mpn_copyi(r, a + word_shift, word_count); 346 | std::memset(r + word_count, 0, word_shift * sizeof(uint64_t)); 347 | 348 | if (bit_shift) 349 | { 350 | mpn_rshift(r, r, Fr_N64, bit_shift); 351 | } 352 | } 353 | 354 | void Fr_rawNot(FrRawElement pRawResult, FrRawElement pRawA) 355 | { 356 | mpn_com(pRawResult, pRawA, Fr_N64); 357 | 358 | pRawResult[3] &= lboMask; 359 | 360 | if (mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0) 361 | { 362 | mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64); 363 | } 364 | } 365 | -------------------------------------------------------------------------------- /build_gmp.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | NPROC=8 6 | fetch_cmd=$( (type wget > /dev/null 2>&1 && echo "wget") || echo "curl -O" ) 7 | 8 | usage() 9 | { 10 | echo "USAGE: $0 " 11 | echo "where target is one of:" 12 | echo " ios: build for iOS arm64" 13 | echo " ios_simulator: build for iPhone Simulator for arm64/x86_64 (fat binary)" 14 | echo " macos: build for macOS for arm64/x86_64 (fat binary)" 15 | echo " macos_arm64: build for macOS arm64" 16 | echo " macos_x86_64: build for macOS x86_64" 17 | echo " android: build for Android arm64" 18 | echo " android_x86_64: build for Android x86_64" 19 | echo " host: build for this host" 20 | echo " host_noasm: build for this host without asm optimizations (e.g. needed for macOS)" 21 | echo " aarch64: build for Linux aarch64" 22 | 23 | exit 1 24 | } 25 | 26 | get_gmp() 27 | { 28 | GMP_NAME=gmp-6.2.1 29 | GMP_ARCHIVE=${GMP_NAME}.tar.xz 30 | GMP_URL=https://ftp.gnu.org/gnu/gmp/${GMP_ARCHIVE} 31 | 32 | if [ ! -f ${GMP_ARCHIVE} ]; then 33 | 34 | $fetch_cmd ${GMP_URL} 35 | fi 36 | 37 | 38 | if [ ! -d gmp ]; then 39 | 40 | tar -xvf ${GMP_ARCHIVE} 41 | mv ${GMP_NAME} gmp 42 | fi 43 | } 44 | 45 | build_aarch64() 46 | { 47 | PACKAGE_DIR="$GMP_DIR/package_aarch64" 48 | BUILD_DIR=build_aarch64 49 | 50 | if [ -d "$PACKAGE_DIR" ]; then 51 | echo "aarch64 package is built already. See $PACKAGE_DIR" 52 | return 1 53 | fi 54 | 55 | 56 | export TARGET=aarch64-linux-gnu 57 | 58 | echo $TARGET 59 | 60 | rm -rf "$BUILD_DIR" 61 | mkdir "$BUILD_DIR" 62 | cd "$BUILD_DIR" 63 | 64 | ../configure --host $TARGET --prefix="$PACKAGE_DIR" --with-pic --disable-fft && 65 | make -j${NPROC} && 66 | make install 67 | 68 | cd .. 69 | } 70 | 71 | build_host() 72 | { 73 | PACKAGE_DIR="$GMP_DIR/package" 74 | BUILD_DIR=build 75 | 76 | if [ -d "$PACKAGE_DIR" ]; then 77 | echo "Host package is built already. See $PACKAGE_DIR" 78 | return 1 79 | fi 80 | 81 | rm -rf "$BUILD_DIR" 82 | mkdir "$BUILD_DIR" 83 | cd "$BUILD_DIR" 84 | 85 | ../configure --prefix="$PACKAGE_DIR" --with-pic --disable-fft && 86 | make -j${NPROC} && 87 | make install 88 | 89 | cd .. 90 | } 91 | 92 | build_host_noasm() 93 | { 94 | PACKAGE_DIR="$GMP_DIR/package" 95 | BUILD_DIR=build 96 | 97 | if [ -d "$PACKAGE_DIR" ]; then 98 | echo "Host package is built already. See $PACKAGE_DIR" 99 | return 1 100 | fi 101 | 102 | rm -rf "$BUILD_DIR" 103 | mkdir "$BUILD_DIR" 104 | cd "$BUILD_DIR" 105 | 106 | ../configure --prefix="$PACKAGE_DIR" --with-pic --disable-fft --disable-assembly && 107 | make -j${NPROC} && 108 | make install 109 | 110 | cd .. 111 | } 112 | 113 | build_android() 114 | { 115 | PACKAGE_DIR="$GMP_DIR/package_android_arm64" 116 | BUILD_DIR=build_android_arm64 117 | 118 | if [ -d "$PACKAGE_DIR" ]; then 119 | echo "Android package is built already. See $PACKAGE_DIR" 120 | return 1 121 | fi 122 | 123 | if [ -z "$ANDROID_NDK" ]; then 124 | 125 | echo "ERROR: ANDROID_NDK environment variable is not set." 126 | echo " It must be an absolute path to the root directory of Android NDK." 127 | echo " For instance /home/test/Android/Sdk/ndk/23.1.7779620" 128 | return 1 129 | fi 130 | 131 | if [ "$(uname)" == "Darwin" ]; then 132 | export TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/darwin-x86_64 133 | else 134 | export TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64 135 | fi 136 | 137 | export TARGET=aarch64-linux-android 138 | export API=21 139 | 140 | export AR=$TOOLCHAIN/bin/llvm-ar 141 | export CC=$TOOLCHAIN/bin/$TARGET$API-clang 142 | export AS=$CC 143 | export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++ 144 | export LD=$TOOLCHAIN/bin/ld 145 | export RANLIB=$TOOLCHAIN/bin/llvm-ranlib 146 | export STRIP=$TOOLCHAIN/bin/llvm-strip 147 | 148 | echo "$TOOLCHAIN" 149 | echo "$TARGET" 150 | 151 | rm -rf "$BUILD_DIR" 152 | mkdir "$BUILD_DIR" 153 | cd "$BUILD_DIR" 154 | 155 | ../configure --host $TARGET --prefix="$PACKAGE_DIR" --with-pic --disable-fft && 156 | make -j${NPROC} && 157 | make install 158 | 159 | cd .. 160 | } 161 | 162 | build_android_x86_64() 163 | { 164 | PACKAGE_DIR="$GMP_DIR/package_android_x86_64" 165 | BUILD_DIR=build_android_x86_64 166 | 167 | if [ -d "$PACKAGE_DIR" ]; then 168 | echo "Android package is built already. See $PACKAGE_DIR" 169 | return 1 170 | fi 171 | 172 | if [ -z "$ANDROID_NDK" ]; then 173 | 174 | echo "ERROR: ANDROID_NDK environment variable is not set." 175 | echo " It must be an absolute path to the root directory of Android NDK." 176 | echo " For instance /home/test/Android/Sdk/ndk/23.1.7779620" 177 | return 1 178 | fi 179 | 180 | if [ "$(uname)" == "Darwin" ]; then 181 | export TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/darwin-x86_64 182 | else 183 | export TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64 184 | fi 185 | 186 | export TARGET=x86_64-linux-android 187 | export API=21 188 | 189 | export AR=$TOOLCHAIN/bin/llvm-ar 190 | export CC=$TOOLCHAIN/bin/$TARGET$API-clang 191 | export AS=$CC 192 | export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++ 193 | export LD=$TOOLCHAIN/bin/ld 194 | export RANLIB=$TOOLCHAIN/bin/llvm-ranlib 195 | export STRIP=$TOOLCHAIN/bin/llvm-strip 196 | 197 | echo "$TOOLCHAIN" 198 | echo $TARGET 199 | 200 | rm -rf "$BUILD_DIR" 201 | mkdir "$BUILD_DIR" 202 | cd "$BUILD_DIR" 203 | 204 | ../configure --host $TARGET --prefix="$PACKAGE_DIR" --with-pic --disable-fft && 205 | make -j${NPROC} && 206 | make install 207 | 208 | cd .. 209 | } 210 | 211 | build_ios() 212 | { 213 | PACKAGE_DIR="$GMP_DIR/package_ios_arm64" 214 | BUILD_DIR=build_ios_arm64 215 | 216 | if [ -d "$PACKAGE_DIR" ]; then 217 | echo "iOS package is built already. See $PACKAGE_DIR" 218 | return 1 219 | fi 220 | 221 | export SDK="iphoneos" 222 | export TARGET=arm64-apple-darwin 223 | export MIN_IOS_VERSION=8.0 224 | 225 | export ARCH_FLAGS="-arch arm64 -arch arm64e" 226 | export OPT_FLAGS="-O3 -g3 -fembed-bitcode" 227 | HOST_FLAGS="${ARCH_FLAGS} -miphoneos-version-min=${MIN_IOS_VERSION} -isysroot $(xcrun --sdk ${SDK} --show-sdk-path)" 228 | 229 | CC=$(xcrun --find --sdk "${SDK}" clang) 230 | export CC 231 | CXX=$(xcrun --find --sdk "${SDK}" clang++) 232 | export CXX 233 | CPP=$(xcrun --find --sdk "${SDK}" cpp) 234 | export CPP 235 | export CFLAGS="${HOST_FLAGS} ${OPT_FLAGS}" 236 | export CXXFLAGS="${HOST_FLAGS} ${OPT_FLAGS}" 237 | export LDFLAGS="${HOST_FLAGS}" 238 | 239 | echo $TARGET 240 | 241 | rm -rf "$BUILD_DIR" 242 | mkdir "$BUILD_DIR" 243 | cd "$BUILD_DIR" 244 | 245 | ../configure --host $TARGET --prefix="$PACKAGE_DIR" --with-pic --disable-fft --disable-assembly && 246 | make -j${NPROC} && 247 | make install 248 | 249 | cd .. 250 | } 251 | 252 | build_ios_simulator() 253 | { 254 | libs=() 255 | for ARCH in "arm64" "x86_64"; do 256 | case "$ARCH" in 257 | "arm64" ) 258 | echo "Building for iPhone Simulator arm64" 259 | ARCH_FLAGS="-arch arm64 -arch arm64e" 260 | ;; 261 | "x86_64" ) 262 | echo "Building for iPhone Simulator x86_64" 263 | ARCH_FLAGS="-arch x86_64" 264 | ;; 265 | * ) 266 | echo "Incorrect iPhone Simulator arch" 267 | exit 1 268 | esac 269 | 270 | BUILD_DIR="build_iphone_simulator_${ARCH}" 271 | PACKAGE_DIR="$GMP_DIR/package_iphone_simulator_${ARCH}" 272 | libs+=("${PACKAGE_DIR}/lib/libgmp.a") 273 | 274 | if [ -d "$PACKAGE_DIR" ]; then 275 | echo "iPhone Simulator ${ARCH} package is built already. See $PACKAGE_DIR. Skip building this ARCH." 276 | continue 277 | fi 278 | 279 | rm -rf "$BUILD_DIR" 280 | mkdir "$BUILD_DIR" 281 | cd "$BUILD_DIR" 282 | 283 | ../configure --prefix="${PACKAGE_DIR}" \ 284 | CC="$(xcrun --sdk iphonesimulator --find clang)" \ 285 | CFLAGS="-O3 -isysroot $(xcrun --sdk iphonesimulator --show-sdk-path) ${ARCH_FLAGS} -fvisibility=hidden -mios-simulator-version-min=8.0" \ 286 | LDFLAGS="" \ 287 | --host ${ARCH}-apple-darwin --disable-assembly --enable-static --disable-shared --with-pic && 288 | make -j${NPROC} && 289 | make install 290 | 291 | cd .. 292 | done 293 | 294 | mkdir -p "${GMP_DIR}/package_iphone_simulator/lib" 295 | lipo "${libs[@]}" -create -output "${GMP_DIR}/package_iphone_simulator/lib/libgmp.a" 296 | echo "Wrote universal fat library for iPhone Simulator arm64/x86_64 to ${GMP_DIR}/package_iphone_simulator/lib/libgmp.a" 297 | } 298 | 299 | build_macos_arch() 300 | { 301 | ARCH="$1" 302 | case "$ARCH" in 303 | "arm64" ) 304 | ARCH_FLAGS="-arch arm64 -arch arm64e" 305 | ;; 306 | "x86_64" ) 307 | ARCH_FLAGS="-arch x86_64" 308 | ;; 309 | * ) 310 | echo "Incorrect arch" 311 | exit 1 312 | esac 313 | 314 | BUILD_DIR="build_macos_${ARCH}" 315 | PACKAGE_DIR="$GMP_DIR/package_macos_${ARCH}" 316 | if [ -d "$PACKAGE_DIR" ]; then 317 | echo "macOS ${ARCH} package is built already. See $PACKAGE_DIR. Skip building this ARCH." 318 | return 319 | fi 320 | rm -rf "$BUILD_DIR" 321 | mkdir "$BUILD_DIR" 322 | cd "$BUILD_DIR" 323 | ../configure --prefix="${PACKAGE_DIR}" \ 324 | CC="$(xcrun --sdk macosx --find clang)" \ 325 | CFLAGS="-O3 -isysroot $(xcrun --sdk macosx --show-sdk-path) ${ARCH_FLAGS} -fvisibility=hidden -mmacos-version-min=14.0" \ 326 | LDFLAGS="" \ 327 | --host "${ARCH}-apple-darwin" --disable-assembly --enable-static --disable-shared --with-pic && 328 | make -j${NPROC} && 329 | make install 330 | cd .. 331 | } 332 | 333 | build_macos_fat() 334 | { 335 | echo "Building for macOS arm64" 336 | build_macos_arch "arm64" 337 | echo "Building for macOS x86_64" 338 | build_macos_arch "x86_64" 339 | 340 | gmp_lib_arm64="$GMP_DIR/package_macos_arm64/lib/libgmp.a" 341 | gmp_lib_x86_64="$GMP_DIR/package_macos_x86_64/lib/libgmp.a" 342 | gmp_lib_fat="$GMP_DIR/package_macos/lib/libgmp.a" 343 | 344 | mkdir -p "${GMP_DIR}/package_macos/lib" 345 | lipo "${gmp_lib_arm64}" "${gmp_lib_x86_64}" -create -output "${gmp_lib_fat}" 346 | mkdir -p "${GMP_DIR}/package_macos/include" 347 | cp "${GMP_DIR}/package_macos_arm64/include/gmp.h" "${GMP_DIR}/package_macos/include/" 348 | echo "Wrote universal fat library for macOS arm64/x86_64 to ${GMP_DIR}/package_macos/lib/libgmp.a" 349 | } 350 | 351 | if [ $# -ne 1 ]; then 352 | usage 353 | fi 354 | 355 | TARGET_PLATFORM=$(echo "$1" | tr "[:upper:]" "[:lower:]") 356 | 357 | cd depends 358 | 359 | get_gmp 360 | 361 | cd gmp 362 | 363 | GMP_DIR=$PWD 364 | 365 | case "$TARGET_PLATFORM" in 366 | 367 | "ios" ) 368 | echo "Building for ios" 369 | build_ios 370 | ;; 371 | 372 | "ios_simulator" ) 373 | echo "Building for iPhone Simulator" 374 | build_ios_simulator 375 | ;; 376 | 377 | "macos" ) 378 | echo "Building fat library for macOS" 379 | build_macos_fat 380 | ;; 381 | 382 | "macos_arm64" ) 383 | echo "Building library for macOS arm64" 384 | build_macos_arch "arm64" 385 | ;; 386 | 387 | "macos_x86_64" ) 388 | echo "Building library for macOS x86_64" 389 | build_macos_arch "x86_64" 390 | ;; 391 | 392 | "android" ) 393 | echo "Building for android" 394 | build_android 395 | ;; 396 | 397 | "android_x86_64" ) 398 | echo "Building for android x86_64" 399 | build_android_x86_64 400 | ;; 401 | 402 | "host" ) 403 | echo "Building for this host" 404 | build_host 405 | ;; 406 | 407 | "host_noasm" ) 408 | echo "Building for this host without asm optimizations (e.g. needed for macOS)" 409 | build_host_noasm 410 | ;; 411 | 412 | "aarch64" ) 413 | echo "Building for linux aarch64" 414 | build_aarch64 415 | ;; 416 | 417 | * ) 418 | usage 419 | 420 | esac 421 | -------------------------------------------------------------------------------- /cmake/platform.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | string(TOLOWER "${TARGET_PLATFORM}" TARGET_PLATFORM) 4 | 5 | message("Building for " ${TARGET_PLATFORM}) 6 | 7 | set(GMP_ROOT depends/gmp) 8 | 9 | if(TARGET_PLATFORM MATCHES "android") 10 | 11 | if(NOT DEFINED ENV{ANDROID_NDK}) 12 | message("ANDROID_NDK environment variable is not set.") 13 | message("It must be an absolute path to the root directory of Android NDK.") 14 | message(" For instance /home/test/Android/Sdk/ndk/23.1.7779620") 15 | message(FATAL_ERROR "Build failed.") 16 | else() 17 | message("Android NDK path is " $ENV{ANDROID_NDK}) 18 | endif() 19 | 20 | set(CMAKE_SYSTEM_NAME Android) 21 | set(CMAKE_SYSTEM_VERSION 23) # API level 22 | 23 | if(TARGET_PLATFORM MATCHES "android_x86_64") 24 | set(CMAKE_ANDROID_ARCH_ABI x86_64) 25 | set(GMP_PREFIX ${GMP_ROOT}/package_android_x86_64) 26 | set(ARCH x86_64) 27 | else() 28 | set(CMAKE_ANDROID_ARCH_ABI arm64-v8a) 29 | set(GMP_PREFIX ${GMP_ROOT}/package_android_arm64) 30 | set(ARCH arm64) 31 | endif() 32 | 33 | message("CMAKE_ANDROID_ARCH_ABI=" ${CMAKE_ANDROID_ARCH_ABI}) 34 | 35 | elseif(TARGET_PLATFORM MATCHES "ios") 36 | 37 | set(CMAKE_SYSTEM_NAME iOS) 38 | 39 | if(TARGET_PLATFORM MATCHES "ios_x86_64") 40 | set(CMAKE_OSX_ARCHITECTURES x86_64) 41 | set(GMP_PREFIX ${GMP_ROOT}/package_ios_x86_64) 42 | set(ARCH x86_64) 43 | elseif(TARGET_PLATFORM MATCHES "ios_simulator") 44 | set(CMAKE_OSX_ARCHITECTURES arm64) 45 | set(GMP_PREFIX ${GMP_ROOT}/package_iphone_simulator_arm64) 46 | set(ARCH x86_64) 47 | else() 48 | set(CMAKE_OSX_ARCHITECTURES arm64) 49 | set(GMP_PREFIX ${GMP_ROOT}/package_ios_arm64) 50 | set(ARCH arm64) 51 | endif() 52 | 53 | elseif(TARGET_PLATFORM MATCHES "aarch64") 54 | 55 | set(GMP_PREFIX ${GMP_ROOT}/package_aarch64) 56 | set(ARCH arm64) 57 | 58 | elseif(TARGET_PLATFORM MATCHES "macos_x86_64") 59 | 60 | set(CMAKE_OSX_ARCHITECTURES x86_64) 61 | set(GMP_PREFIX ${GMP_ROOT}/package_macos_x86_64) 62 | set(ARCH x86_64) 63 | 64 | elseif(TARGET_PLATFORM MATCHES "macos_arm64") 65 | 66 | set(CMAKE_OSX_ARCHITECTURES arm64) 67 | set(GMP_PREFIX ${GMP_ROOT}/package_macos_arm64) 68 | set(ARCH arm64) 69 | 70 | else() 71 | 72 | set(GMP_PREFIX ${GMP_ROOT}/package) 73 | set(ARCH x86_64) 74 | 75 | endif() 76 | 77 | if (CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin" AND NOT TARGET_PLATFORM MATCHES "^android(_x86_64)?") 78 | set(GMP_DEFINIONS -D_LONG_LONG_LIMB) 79 | endif() 80 | 81 | 82 | set(GMP_INCLUDE_DIR ${GMP_PREFIX}/include) 83 | set(GMP_INCLUDE_FILE gmp.h) 84 | set(GMP_LIB_DIR ${GMP_PREFIX}/lib) 85 | set(GMP_LIB_FILE libgmp.a) 86 | 87 | set(GMP_LIB_FILE_FULLPATH ${CMAKE_SOURCE_DIR}/${GMP_LIB_DIR}/${GMP_LIB_FILE}) 88 | set(GMP_INCLUDE_FILE_FULLPATH ${CMAKE_SOURCE_DIR}/${GMP_INCLUDE_DIR}/${GMP_INCLUDE_FILE}) 89 | 90 | set(GMP_LIB ${GMP_LIB_FILE_FULLPATH}) 91 | 92 | message("CMAKE_HOST_SYSTEM_NAME=" ${CMAKE_HOST_SYSTEM_NAME}) 93 | message("CMAKE_SYSTEM_NAME=" ${CMAKE_SYSTEM_NAME}) 94 | message("ARCH=" ${ARCH}) 95 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rapidsnark", 3 | "version": "0.0.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@pawelgalazka/cli": { 8 | "version": "2.0.3", 9 | "resolved": "https://registry.npmjs.org/@pawelgalazka/cli/-/cli-2.0.3.tgz", 10 | "integrity": "sha512-PjR8WGDfd8KLFdRS0ceZC/V99xCMN+z6MVThoaqODEOrgwSyP1qA1nVc8JXOI5cxGQ5OBvSDikrvulXYnzgIjg==", 11 | "dev": true, 12 | "requires": { 13 | "@pawelgalazka/cli-args": "1.1.3", 14 | "@pawelgalazka/middleware": "1.0.0", 15 | "chalk": "2.4.2", 16 | "lodash": "4.17.15" 17 | }, 18 | "dependencies": { 19 | "lodash": { 20 | "version": "4.17.15", 21 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 22 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", 23 | "dev": true 24 | } 25 | } 26 | }, 27 | "@pawelgalazka/cli-args": { 28 | "version": "1.1.3", 29 | "resolved": "https://registry.npmjs.org/@pawelgalazka/cli-args/-/cli-args-1.1.3.tgz", 30 | "integrity": "sha512-snkj9nX11F/2+7t/aQUbGC4iYMMZ2BQMoSsJ0IUUimzkOM9jb12QFAGubsOo9TibmfTN/g0DJ+ciOgXB/YEClQ==", 31 | "dev": true 32 | }, 33 | "@pawelgalazka/middleware": { 34 | "version": "1.0.0", 35 | "resolved": "https://registry.npmjs.org/@pawelgalazka/middleware/-/middleware-1.0.0.tgz", 36 | "integrity": "sha512-BHE0ZFTDhfrAWzeoeUkhKXCjh0NFcd7dYJJiekW6sp3xbhaWTVBoaJbyZthWJEeow4FHJInjeEIBwbkGKqZzRg==", 37 | "dev": true 38 | }, 39 | "@pawelgalazka/shell": { 40 | "version": "2.0.0", 41 | "resolved": "https://registry.npmjs.org/@pawelgalazka/shell/-/shell-2.0.0.tgz", 42 | "integrity": "sha512-MsNuS9M2vVbJNW3+YSiz9eF0/U2ZPlEEVC4ky8QJnxFlU4H7DZOH5A1hDQUfF5DV/pYwBD76dkF3+mrzZTJ3Tw==", 43 | "dev": true 44 | }, 45 | "ansi-styles": { 46 | "version": "3.2.1", 47 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 48 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 49 | "dev": true, 50 | "requires": { 51 | "color-convert": "^1.9.0" 52 | } 53 | }, 54 | "chalk": { 55 | "version": "2.4.2", 56 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 57 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 58 | "dev": true, 59 | "requires": { 60 | "ansi-styles": "^3.2.1", 61 | "escape-string-regexp": "^1.0.5", 62 | "supports-color": "^5.3.0" 63 | } 64 | }, 65 | "color-convert": { 66 | "version": "1.9.3", 67 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 68 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 69 | "dev": true, 70 | "requires": { 71 | "color-name": "1.1.3" 72 | } 73 | }, 74 | "color-name": { 75 | "version": "1.1.3", 76 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 77 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 78 | "dev": true 79 | }, 80 | "escape-string-regexp": { 81 | "version": "1.0.5", 82 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 83 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 84 | "dev": true 85 | }, 86 | "has-flag": { 87 | "version": "3.0.0", 88 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 89 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 90 | "dev": true 91 | }, 92 | "node-fetch": { 93 | "version": "2.6.1", 94 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", 95 | "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" 96 | }, 97 | "supports-color": { 98 | "version": "5.5.0", 99 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 100 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 101 | "dev": true, 102 | "requires": { 103 | "has-flag": "^3.0.0" 104 | } 105 | }, 106 | "tasksfile": { 107 | "version": "5.1.1", 108 | "resolved": "https://registry.npmjs.org/tasksfile/-/tasksfile-5.1.1.tgz", 109 | "integrity": "sha512-G5d3pT8qHgRy3L2zUj+SJMr1C44k2tr+68e1gRxPs6bFHDq/qr3l6BmT2O7OcaGryOHrHIMhwnU3ZTjXGvsXxQ==", 110 | "dev": true, 111 | "requires": { 112 | "@pawelgalazka/cli": "2.0.3", 113 | "@pawelgalazka/shell": "2.0.0", 114 | "chalk": "2.3.0" 115 | }, 116 | "dependencies": { 117 | "chalk": { 118 | "version": "2.3.0", 119 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", 120 | "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", 121 | "dev": true, 122 | "requires": { 123 | "ansi-styles": "^3.1.0", 124 | "escape-string-regexp": "^1.0.5", 125 | "supports-color": "^4.0.0" 126 | } 127 | }, 128 | "has-flag": { 129 | "version": "2.0.0", 130 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", 131 | "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", 132 | "dev": true 133 | }, 134 | "supports-color": { 135 | "version": "4.5.0", 136 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", 137 | "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", 138 | "dev": true, 139 | "requires": { 140 | "has-flag": "^2.0.0" 141 | } 142 | } 143 | } 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rapidsnark", 3 | "version": "0.0.1", 4 | "description": "Snark implementation in C++", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "task": "node ./tasksfile.js" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.io/iden3/rapidsnark" 13 | }, 14 | "keywords": [ 15 | "snark", 16 | "prover", 17 | "ethereum", 18 | "rollup", 19 | "zksnark", 20 | "zero", 21 | "knowledge", 22 | "fast" 23 | ], 24 | "author": "Jordi Baylina", 25 | "license": "GPL-3.0", 26 | "devDependencies": { 27 | "tasksfile": "^5.1.1" 28 | }, 29 | "dependencies": { 30 | "node-fetch": "^2.6.1" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /service/README.md: -------------------------------------------------------------------------------- 1 | # RapidSnark as a Service 2 | 3 | This folder contains the config file to use `proverServer` as a service 4 | at Linux, with `systemd`. 5 | 6 | Just copy the file `rapidsnark.service` to `/etc/systemd/system/rapidsnark.service` 7 | and update the `ExecStart` parameter with the correct path for binary, `.dat` file 8 | and `.zkey` file. 9 | 10 | After save the file run: 11 | 12 | ``` 13 | $ sudo systemctl daemon-reload 14 | ``` 15 | 16 | And you can 17 | 18 | ``` 19 | $ sudo service rapidsnark start | stop | reload | status 20 | ``` 21 | 22 | -------------------------------------------------------------------------------- /service/rapidsnark.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=RapidSnark 3 | StartLimitIntervalSec=600 4 | 5 | [Service] 6 | Type=simple 7 | Restart=always 8 | RestartSec=50 9 | ExecStart=/home/ubuntu/rapidsnark/build/proverServer400 /home/ubuntu/circuit-400-32-256-64.dat /home/ubuntu/circuit-400-32-256-64_hez4_final.zkey 10 | KillMode=process 11 | StandardOutput=append:/home/ubuntu/proverServer400.log 12 | StandardError=append:/home/ubuntu/proverServer400.log 13 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | link_libraries(${GMP_LIB}) 2 | 3 | add_definitions(${GMP_DEFINIONS}) 4 | 5 | if(USE_ASM) 6 | if(ARCH MATCHES "arm64") 7 | add_definitions(-DUSE_ASM -DARCH_ARM64) 8 | elseif(ARCH MATCHES "x86_64") 9 | add_definitions(-DUSE_ASM -DARCH_X86_64) 10 | endif() 11 | endif() 12 | 13 | if(DEFINED BITS_PER_CHUNK) 14 | add_definitions(-DMSM_BITS_PER_CHUNK=${BITS_PER_CHUNK}) 15 | endif() 16 | 17 | if(USE_ASM AND ARCH MATCHES "x86_64") 18 | 19 | if (CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin" AND NOT TARGET_PLATFORM MATCHES "^android(_x86_64)?") 20 | set(NASM_FLAGS -fmacho64 --prefix _) 21 | else() 22 | set(NASM_FLAGS -felf64 -DPIC) 23 | endif() 24 | 25 | add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/build/fq_asm.o 26 | COMMAND nasm ${NASM_FLAGS} fq.asm -o fq_asm.o 27 | DEPENDS ${CMAKE_SOURCE_DIR}/build/fq.asm 28 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/build) 29 | 30 | add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/build/fr_asm.o 31 | COMMAND nasm ${NASM_FLAGS} fr.asm -o fr_asm.o 32 | DEPENDS ${CMAKE_SOURCE_DIR}/build/fr.asm 33 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/build) 34 | endif() 35 | 36 | set(FR_SOURCES 37 | ../build/fr.hpp 38 | ../build/fr.cpp 39 | ) 40 | 41 | if(USE_ASM) 42 | if(ARCH MATCHES "arm64") 43 | set(FR_SOURCES ${FR_SOURCES} ../build/fr_raw_arm64.s ../build/fr_raw_generic.cpp ../build/fr_generic.cpp) 44 | elseif(ARCH MATCHES "x86_64") 45 | set(FR_SOURCES ${FR_SOURCES} ../build/fr_asm.o) 46 | endif() 47 | else() 48 | set(FR_SOURCES ${FR_SOURCES} ../build/fr_generic.cpp ../build/fr_raw_generic.cpp) 49 | endif() 50 | 51 | add_library(fr STATIC ${FR_SOURCES}) 52 | set_target_properties(fr PROPERTIES POSITION_INDEPENDENT_CODE ON) 53 | 54 | link_libraries(fr) 55 | 56 | set(FQ_SOURCES 57 | ../build/fq.hpp 58 | ../build/fq.cpp 59 | ) 60 | 61 | if(USE_ASM) 62 | if(ARCH MATCHES "arm64") 63 | set(FQ_SOURCES ${FQ_SOURCES} ../build/fq_raw_arm64.s ../build/fq_raw_generic.cpp ../build/fq_generic.cpp) 64 | elseif(ARCH MATCHES "x86_64") 65 | set(FQ_SOURCES ${FQ_SOURCES} ../build/fq_asm.o) 66 | endif() 67 | else() 68 | set(FQ_SOURCES ${FQ_SOURCES} ../build/fq_raw_generic.cpp ../build/fq_generic.cpp) 69 | endif() 70 | 71 | add_library(fq STATIC ${FQ_SOURCES}) 72 | set_target_properties(fq PROPERTIES POSITION_INDEPENDENT_CODE ON) 73 | 74 | link_libraries(fq) 75 | 76 | 77 | if(OpenMP_CXX_FOUND) 78 | add_definitions(-DUSE_OPENMP) 79 | add_compile_options(${OpenMP_CXX_FLAGS}) 80 | endif() 81 | 82 | set(LIB_SOURCES 83 | binfile_utils.hpp 84 | binfile_utils.cpp 85 | zkey_utils.hpp 86 | zkey_utils.cpp 87 | wtns_utils.hpp 88 | wtns_utils.cpp 89 | logger.hpp 90 | logger.cpp 91 | fileloader.cpp 92 | fileloader.hpp 93 | prover.cpp 94 | prover.h 95 | verifier.cpp 96 | verifier.h 97 | ../depends/ffiasm/c/misc.cpp 98 | ../depends/ffiasm/c/naf.cpp 99 | ../depends/ffiasm/c/splitparstr.cpp 100 | ../depends/ffiasm/c/alt_bn128.cpp 101 | ) 102 | 103 | if(USE_LOGGER) 104 | set(LIB_SOURCES ${LIB_SOURCES} logger.cpp) 105 | add_definitions(-DUSE_LOGGER) 106 | endif() 107 | 108 | include_directories( 109 | ../src 110 | ../build 111 | ../depends/ffiasm/c 112 | ../depends/json/single_include) 113 | 114 | add_library(rapidsnarkStatic STATIC ${LIB_SOURCES}) 115 | set_target_properties(rapidsnarkStatic PROPERTIES OUTPUT_NAME rapidsnark) 116 | 117 | add_library(rapidsnarkStaticFrFq STATIC ${LIB_SOURCES} ${FQ_SOURCES} ${FR_SOURCES}) 118 | set_target_properties(rapidsnarkStaticFrFq PROPERTIES POSITION_INDEPENDENT_CODE ON) 119 | set_target_properties(rapidsnarkStaticFrFq PROPERTIES OUTPUT_NAME rapidsnark-fr-fq) 120 | 121 | add_executable(prover main_prover.cpp) 122 | target_link_libraries(prover rapidsnarkStatic) 123 | 124 | add_executable(verifier main_verifier.cpp) 125 | target_link_libraries(verifier rapidsnarkStatic) 126 | 127 | add_library(rapidsnark SHARED ${LIB_SOURCES}) 128 | 129 | if((USE_LOGGER OR NOT USE_OPENMP) AND NOT TARGET_PLATFORM MATCHES "android") 130 | target_link_libraries(prover pthread) 131 | target_link_libraries(verifier pthread) 132 | endif() 133 | 134 | if(USE_SODIUM) 135 | target_link_libraries(prover sodium) 136 | endif() 137 | 138 | option(BUILD_TESTS "Build the tests" ON) 139 | 140 | if(BUILD_TESTS) 141 | enable_testing() 142 | add_executable(test_public_size test_public_size.c) 143 | target_link_libraries(test_public_size rapidsnarkStaticFrFq pthread) 144 | add_test(NAME test_public_size COMMAND test_public_size circuit_final.zkey 86 145 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/testdata) 146 | endif() 147 | 148 | if(OpenMP_CXX_FOUND) 149 | 150 | if(TARGET_PLATFORM MATCHES "android") 151 | target_link_libraries(prover -static-openmp -fopenmp) 152 | target_link_libraries(verifier -static-openmp -fopenmp) 153 | target_link_libraries(rapidsnark -static-openmp -fopenmp) 154 | 155 | elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") 156 | target_link_libraries(prover OpenMP::OpenMP_CXX) 157 | target_link_libraries(verifier OpenMP::OpenMP_CXX) 158 | target_link_libraries(test_public_size OpenMP::OpenMP_CXX) 159 | endif() 160 | 161 | endif() 162 | 163 | 164 | add_executable(test_prover test_prover.cpp) 165 | -------------------------------------------------------------------------------- /src/binfile_utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "binfile_utils.hpp" 11 | #include "fileloader.hpp" 12 | 13 | namespace BinFileUtils { 14 | 15 | BinFile::BinFile(const std::string& fileName, const std::string& _type, uint32_t maxVersion) 16 | : fileLoader(fileName) 17 | { 18 | addr = fileLoader.dataBuffer(); 19 | size = fileLoader.dataSize(); 20 | 21 | readFileData(_type, maxVersion); 22 | } 23 | 24 | BinFile::BinFile(const void *fileData, size_t fileSize, std::string _type, uint32_t maxVersion) { 25 | 26 | addr = fileData; 27 | size = fileSize; 28 | 29 | readFileData(_type, maxVersion); 30 | } 31 | 32 | void BinFile::readFileData(std::string _type, uint32_t maxVersion) { 33 | 34 | const u_int64_t headerSize = 12; 35 | const u_int64_t minSectionSize = 12; 36 | 37 | if (size < headerSize) { 38 | throw std::range_error("File is too short."); 39 | } 40 | 41 | type.assign((const char *)addr, 4); 42 | pos = 4; 43 | 44 | if (type != _type) { 45 | throw std::invalid_argument("Invalid file type. It should be " + _type + " and it is " + type); 46 | } 47 | 48 | version = readU32LE(); 49 | if (version > maxVersion) { 50 | throw std::invalid_argument("Invalid version. It should be <=" + std::to_string(maxVersion) + " and it is " + std::to_string(version)); 51 | } 52 | 53 | u_int32_t nSections = readU32LE(); 54 | 55 | if (size < headerSize + nSections * minSectionSize) { 56 | throw std::range_error("File is too short to contain " + std::to_string(nSections) + " sections."); 57 | } 58 | 59 | for (u_int32_t i=0; i())); 65 | } 66 | 67 | sections[sType].push_back(Section( (void *)((u_int64_t)addr + pos), sSize)); 68 | 69 | pos += sSize; 70 | 71 | if (pos > size) { 72 | throw std::range_error("Section #" + std::to_string(i) + " is invalid." 73 | ". It ends at pos " + std::to_string(pos) + 74 | " but should end before " + std::to_string(size) + "."); 75 | } 76 | } 77 | 78 | pos = 0; 79 | readingSection = nullptr; 80 | } 81 | 82 | 83 | void BinFile::startReadSection(u_int32_t sectionId, u_int32_t sectionPos) { 84 | 85 | if (sections.find(sectionId) == sections.end()) { 86 | throw std::range_error("Section does not exist: " + std::to_string(sectionId)); 87 | } 88 | 89 | if (sectionPos >= sections[sectionId].size()) { 90 | throw std::range_error("Section pos too big. There are " + std::to_string(sections[sectionId].size()) + " and it's trying to access section: " + std::to_string(sectionPos)); 91 | } 92 | 93 | if (readingSection != nullptr) { 94 | throw std::range_error("Already reading a section"); 95 | } 96 | 97 | pos = (u_int64_t)(sections[sectionId][sectionPos].start) - (u_int64_t)addr; 98 | 99 | readingSection = §ions[sectionId][sectionPos]; 100 | } 101 | 102 | void BinFile::endReadSection(bool check) { 103 | if (check) { 104 | if ((u_int64_t)addr + pos - (u_int64_t)(readingSection->start) != readingSection->size) { 105 | throw std::range_error("Invalid section size"); 106 | } 107 | } 108 | readingSection = nullptr; 109 | } 110 | 111 | void *BinFile::getSectionData(u_int32_t sectionId, u_int32_t sectionPos) { 112 | 113 | if (sections.find(sectionId) == sections.end()) { 114 | throw std::range_error("Section does not exist: " + std::to_string(sectionId)); 115 | } 116 | 117 | if (sectionPos >= sections[sectionId].size()) { 118 | throw std::range_error("Section pos too big. There are " + std::to_string(sections[sectionId].size()) + " and it's trying to access section: " + std::to_string(sectionPos)); 119 | } 120 | 121 | return sections[sectionId][sectionPos].start; 122 | } 123 | 124 | u_int64_t BinFile::getSectionSize(u_int32_t sectionId, u_int32_t sectionPos) { 125 | 126 | if (sections.find(sectionId) == sections.end()) { 127 | throw std::range_error("Section does not exist: " + std::to_string(sectionId)); 128 | } 129 | 130 | if (sectionPos >= sections[sectionId].size()) { 131 | throw std::range_error("Section pos too big. There are " + std::to_string(sections[sectionId].size()) + " and it's trying to access section: " + std::to_string(sectionPos)); 132 | } 133 | 134 | return sections[sectionId][sectionPos].size; 135 | } 136 | 137 | u_int32_t BinFile::readU32LE() { 138 | const u_int64_t new_pos = pos + 4; 139 | 140 | if (new_pos > size) { 141 | throw std::range_error("File pos is too big. There are " + std::to_string(size) + " bytes and it's trying to access byte " + std::to_string(new_pos)); 142 | } 143 | 144 | u_int32_t res = *((u_int32_t *)((u_int64_t)addr + pos)); 145 | pos = new_pos; 146 | return res; 147 | } 148 | 149 | u_int64_t BinFile::readU64LE() { 150 | const u_int64_t new_pos = pos + 8; 151 | 152 | if (new_pos > size) { 153 | throw std::range_error("File pos is too big. There are " + std::to_string(size) + " bytes and it's trying to access byte " + std::to_string(new_pos)); 154 | } 155 | 156 | u_int64_t res = *((u_int64_t *)((u_int64_t)addr + pos)); 157 | pos = new_pos; 158 | return res; 159 | } 160 | 161 | void *BinFile::read(u_int64_t len) { 162 | const u_int64_t new_pos = pos + len; 163 | 164 | if (new_pos > size) { 165 | throw std::range_error("File pos is too big. There are " + std::to_string(size) + " bytes and it's trying to access byte " + std::to_string(new_pos)); 166 | } 167 | 168 | void *res = (void *)((u_int64_t)addr + pos); 169 | pos = new_pos; 170 | return res; 171 | } 172 | 173 | std::unique_ptr openExisting(const std::string& filename, const std::string& type, uint32_t maxVersion) { 174 | return std::unique_ptr(new BinFile(filename, type, maxVersion)); 175 | } 176 | 177 | } // Namespace 178 | 179 | -------------------------------------------------------------------------------- /src/binfile_utils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BINFILE_UTILS_H 2 | #define BINFILE_UTILS_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "fileloader.hpp" 8 | 9 | namespace BinFileUtils { 10 | 11 | class BinFile { 12 | 13 | FileLoader fileLoader; 14 | 15 | const void *addr; 16 | u_int64_t size; 17 | u_int64_t pos; 18 | 19 | class Section { 20 | void *start; 21 | u_int64_t size; 22 | 23 | public: 24 | 25 | friend BinFile; 26 | Section(void *_start, u_int64_t _size) : start(_start), size(_size) {}; 27 | }; 28 | 29 | std::map> sections; 30 | std::string type; 31 | u_int32_t version; 32 | 33 | Section *readingSection; 34 | 35 | void readFileData(std::string _type, uint32_t maxVersion); 36 | 37 | public: 38 | 39 | BinFile(const void *fileData, size_t fileSize, std::string _type, uint32_t maxVersion); 40 | BinFile(const std::string& fileName, const std::string& _type, uint32_t maxVersion); 41 | BinFile(const BinFile&) = delete; 42 | BinFile& operator=(const BinFile&) = delete; 43 | 44 | void startReadSection(u_int32_t sectionId, u_int32_t setionPos = 0); 45 | void endReadSection(bool check = true); 46 | 47 | void *getSectionData(u_int32_t sectionId, u_int32_t sectionPos = 0); 48 | u_int64_t getSectionSize(u_int32_t sectionId, u_int32_t sectionPos = 0); 49 | 50 | u_int32_t readU32LE(); 51 | u_int64_t readU64LE(); 52 | 53 | void *read(uint64_t l); 54 | }; 55 | 56 | std::unique_ptr openExisting(const std::string& filename, const std::string& type, uint32_t maxVersion); 57 | } 58 | 59 | #endif // BINFILE_UTILS_H 60 | -------------------------------------------------------------------------------- /src/fileloader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "fileloader.hpp" 9 | 10 | namespace BinFileUtils { 11 | 12 | FileLoader::FileLoader() 13 | : fd(-1) 14 | { 15 | } 16 | 17 | FileLoader::FileLoader(const std::string& fileName) 18 | : fd(-1) 19 | { 20 | load(fileName); 21 | } 22 | 23 | void FileLoader::load(const std::string& fileName) 24 | { 25 | if (fd != -1) { 26 | throw std::invalid_argument("file already loaded"); 27 | } 28 | 29 | struct stat sb; 30 | 31 | fd = open(fileName.c_str(), O_RDONLY); 32 | if (fd == -1) 33 | throw std::system_error(errno, std::generic_category(), "open"); 34 | 35 | 36 | if (fstat(fd, &sb) == -1) { /* To obtain file size */ 37 | close(fd); 38 | throw std::system_error(errno, std::generic_category(), "fstat"); 39 | } 40 | 41 | size = sb.st_size; 42 | 43 | addr = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0); 44 | 45 | if (addr == MAP_FAILED) { 46 | close(fd); 47 | throw std::system_error(errno, std::generic_category(), "mmap failed"); 48 | } 49 | 50 | madvise(addr, size, MADV_SEQUENTIAL); 51 | } 52 | 53 | FileLoader::~FileLoader() 54 | { 55 | if (fd != -1) { 56 | munmap(addr, size); 57 | close(fd); 58 | } 59 | } 60 | 61 | } // Namespace 62 | -------------------------------------------------------------------------------- /src/fileloader.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FILELOADER_HPP 2 | #define FILELOADER_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace BinFileUtils { 8 | 9 | class FileLoader 10 | { 11 | public: 12 | FileLoader(); 13 | FileLoader(const std::string& fileName); 14 | ~FileLoader(); 15 | 16 | void load(const std::string& fileName); 17 | 18 | void* dataBuffer() { return addr; } 19 | size_t dataSize() const { return size; } 20 | 21 | std::string dataAsString() { return std::string((char*)addr, size); } 22 | 23 | private: 24 | void* addr; 25 | size_t size; 26 | int fd; 27 | }; 28 | 29 | } 30 | 31 | #endif // FILELOADER_HPP 32 | -------------------------------------------------------------------------------- /src/fullprover.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "fullprover.hpp" 7 | #include "fr.hpp" 8 | 9 | #include "logger.hpp" 10 | #include "wtns_utils.hpp" 11 | 12 | using namespace CPlusPlusLogging; 13 | 14 | std::string getfilename(std::string path) 15 | { 16 | path = path.substr(path.find_last_of("/\\") + 1); 17 | size_t dot_i = path.find_last_of('.'); 18 | return path.substr(0, dot_i); 19 | } 20 | 21 | FullProver::FullProver(std::string zkeyFileNames[], int size) { 22 | pendingInput=""; 23 | pendingCircuit=""; 24 | canceled = false; 25 | 26 | mpz_init(altBbn128r); 27 | mpz_set_str(altBbn128r, "21888242871839275222246405745257275088548364400416034343698204186575808495617", 10); 28 | 29 | for(int i = 0; i < size; i++) { 30 | std::string circuit = getfilename(zkeyFileNames[i]); 31 | zKeys[circuit] = BinFileUtils::openExisting(zkeyFileNames[i], "zkey", 1); 32 | zkHeaders[circuit] = ZKeyUtils::loadHeader(zKeys[circuit].get()); 33 | 34 | std::string proofStr; 35 | if (mpz_cmp(zkHeaders[circuit]->rPrime, altBbn128r) != 0) { 36 | throw std::invalid_argument( "zkey curve not supported" ); 37 | } 38 | 39 | std::ostringstream ss1; 40 | ss1 << "circuit: " << circuit; 41 | LOG_DEBUG(ss1); 42 | 43 | provers[circuit] = Groth16::makeProver( 44 | zkHeaders[circuit]->nVars, 45 | zkHeaders[circuit]->nPublic, 46 | zkHeaders[circuit]->domainSize, 47 | zkHeaders[circuit]->nCoefs, 48 | zkHeaders[circuit]->vk_alpha1, 49 | zkHeaders[circuit]->vk_beta1, 50 | zkHeaders[circuit]->vk_beta2, 51 | zkHeaders[circuit]->vk_delta1, 52 | zkHeaders[circuit]->vk_delta2, 53 | zKeys[circuit]->getSectionData(4), // Coefs 54 | zKeys[circuit]->getSectionData(5), // pointsA 55 | zKeys[circuit]->getSectionData(6), // pointsB1 56 | zKeys[circuit]->getSectionData(7), // pointsB2 57 | zKeys[circuit]->getSectionData(8), // pointsC 58 | zKeys[circuit]->getSectionData(9) // pointsH1 59 | ); 60 | } 61 | 62 | status = ready; 63 | } 64 | 65 | FullProver::~FullProver() { 66 | mpz_clear(altBbn128r); 67 | } 68 | 69 | void FullProver::startProve(std::string input, std::string circuit) { 70 | LOG_TRACE("FullProver::startProve begin"); 71 | LOG_DEBUG(input); 72 | std::lock_guard guard(mtx); 73 | pendingInput = input; 74 | pendingCircuit = circuit; 75 | if (status == busy) { 76 | abort(); 77 | } 78 | checkPending(); 79 | LOG_TRACE("FullProver::startProve end"); 80 | } 81 | 82 | void FullProver::checkPending() { 83 | LOG_TRACE("FullProver::checkPending begin"); 84 | if (status != busy) { 85 | std::string input = pendingInput; 86 | std::string circuit = pendingCircuit; 87 | if (input != "" && circuit != "") { 88 | status = busy; 89 | executingInput = pendingInput; 90 | executingCircuit = pendingCircuit; 91 | pendingInput = ""; 92 | pendingCircuit = ""; 93 | errString = ""; 94 | canceled = false; 95 | proof = nlohmann::detail::value_t::null; 96 | std::thread th(&FullProver::thread_calculateProve, this); 97 | th.detach(); 98 | } 99 | } 100 | LOG_TRACE("FullProver::checkPending end"); 101 | } 102 | 103 | void FullProver::thread_calculateProve() { 104 | LOG_TRACE("FullProver::thread_calculateProve start"); 105 | 106 | try { 107 | LOG_TRACE(executingInput); 108 | // Generate witness 109 | json j = json::parse(executingInput); 110 | std::string circuit = executingCircuit; 111 | 112 | std::ofstream file("./build/input_"+ circuit +".json"); 113 | file << j; 114 | file.close(); 115 | 116 | std::string witnessFile("./build/" + circuit + ".wtns"); 117 | std::string command("./build/" + circuit + " ./build/input_"+ circuit +".json " + witnessFile); 118 | LOG_TRACE(command); 119 | std::array buffer; 120 | std::string result; 121 | 122 | // std::cout << "Opening reading pipe" << std::endl; 123 | FILE* pipe = popen(command.c_str(), "r"); 124 | if (!pipe) 125 | { 126 | std::cerr << "Couldn't start command." << std::endl; 127 | } 128 | while (fgets(buffer.data(), 128, pipe) != NULL) { 129 | // std::cout << "Reading..." << std::endl; 130 | result += buffer.data(); 131 | } 132 | auto returnCode = pclose(pipe); 133 | 134 | std::cout << result << std::endl; 135 | std::cout << returnCode << std::endl; 136 | 137 | // Load witness 138 | auto wtns = BinFileUtils::openExisting(witnessFile, "wtns", 2); 139 | auto wtnsHeader = WtnsUtils::loadHeader(wtns.get()); 140 | 141 | if (mpz_cmp(wtnsHeader->prime, altBbn128r) != 0) { 142 | throw std::invalid_argument( "different wtns curve" ); 143 | } 144 | 145 | AltBn128::FrElement *wtnsData = (AltBn128::FrElement *)wtns->getSectionData(2); 146 | 147 | pubData.clear(); 148 | AltBn128::FrElement aux; 149 | for (int i=1; i<=zkHeaders[circuit]->nPublic; i++) { 150 | AltBn128::Fr.toMontgomery(aux, wtnsData[i]); 151 | pubData.push_back(AltBn128::Fr.toString(aux)); 152 | } 153 | 154 | if (!isCanceled()) { 155 | proof = provers[circuit]->prove(wtnsData)->toJson(); 156 | } else { 157 | LOG_TRACE("AVOIDING prove"); 158 | proof = {}; 159 | } 160 | 161 | 162 | calcFinished(); 163 | } catch (std::runtime_error e) { 164 | if (!isCanceled()) { 165 | errString = e.what(); 166 | } 167 | calcFinished(); 168 | } 169 | 170 | LOG_TRACE("FullProver::thread_calculateProve end"); 171 | } 172 | 173 | 174 | void FullProver::calcFinished() { 175 | std::lock_guard guard(mtx); 176 | LOG_TRACE("FullProver::calcFinished start"); 177 | if (canceled) { 178 | LOG_TRACE("FullProver::calcFinished aborted"); 179 | status = aborted; 180 | } else if (errString != "") { 181 | LOG_TRACE("FullProver::calcFinished failed"); 182 | status = failed; 183 | } else { 184 | LOG_TRACE("FullProver::calcFinished success"); 185 | status = success; 186 | } 187 | canceled = false; 188 | executingInput = ""; 189 | checkPending(); 190 | LOG_TRACE("FullProver::calcFinished end"); 191 | } 192 | 193 | 194 | bool FullProver::isCanceled() { 195 | std::lock_guard guard(mtx); 196 | LOG_TRACE("FullProver::isCanceled start"); 197 | if (canceled) { 198 | LOG_TRACE("FullProver::isCanceled canceled==true"); 199 | } 200 | LOG_TRACE("FullProver::isCanceled end"); 201 | return canceled; 202 | } 203 | 204 | void FullProver::abort() { 205 | std::lock_guard guard(mtx); 206 | LOG_TRACE("FullProver::abort start"); 207 | if (status!= busy) { 208 | LOG_TRACE("FullProver::abort end -> not usy"); 209 | return; 210 | } 211 | canceled = true; 212 | LOG_TRACE("FullProver::abort end -> canceled=true"); 213 | } 214 | 215 | 216 | json FullProver::getStatus() { 217 | LOG_TRACE("FullProver::getStatus start"); 218 | json st; 219 | if (status == ready) { 220 | LOG_TRACE("ready"); 221 | st["status"] = "ready"; 222 | } else if (status == aborted) { 223 | LOG_TRACE("aborted"); 224 | st["status"] = "aborted"; 225 | } else if (status == failed) { 226 | LOG_TRACE("failed"); 227 | st["status"] = "failed"; 228 | st["error"] = errString; 229 | } else if (status == success) { 230 | LOG_TRACE("success"); 231 | st["status"] = "success"; 232 | st["proof"] = proof.dump(); 233 | st["pubData"] = pubData.dump(); 234 | } else if (status == busy) { 235 | LOG_TRACE("busy"); 236 | st["status"] = "busy"; 237 | } 238 | LOG_TRACE("FullProver::getStatus end"); 239 | return st; 240 | } 241 | -------------------------------------------------------------------------------- /src/fullprover.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FULLPROVER_H 2 | #define FULLPROVER_H 3 | 4 | #include 5 | using json = nlohmann::json; 6 | 7 | #include 8 | #include "alt_bn128.hpp" 9 | #include "groth16.hpp" 10 | #include "binfile_utils.hpp" 11 | #include "zkey_utils.hpp" 12 | 13 | class FullProver { 14 | enum Status {aborted = -2, busy = -1, failed = 0, success = 1, unverified =2, uninitialized=3, initializing=5, ready=6 }; 15 | Status status; 16 | std::mutex mtx; 17 | 18 | std::string pendingInput; 19 | std::string executingInput; 20 | std::string pendingCircuit; 21 | std::string executingCircuit; 22 | 23 | std::map>> provers; 24 | std::map> zkHeaders; 25 | std::map> zKeys; 26 | 27 | mpz_t altBbn128r; 28 | 29 | json proof; 30 | json pubData; 31 | std::string errString; 32 | 33 | bool canceled; 34 | 35 | bool isCanceled(); 36 | void calcFinished(); 37 | void thread_calculateProve(); 38 | void checkPending(); 39 | 40 | 41 | 42 | public: 43 | FullProver(std::string zkeyFileNames[], int size); 44 | ~FullProver(); 45 | void startProve(std::string input, std::string circuit); 46 | void abort(); 47 | json getStatus(); 48 | std::string &getErrString() { return errString; }; 49 | 50 | 51 | }; 52 | 53 | #endif // FULLPROVER_H -------------------------------------------------------------------------------- /src/groth16.hpp: -------------------------------------------------------------------------------- 1 | #ifndef GROTH16_HPP 2 | #define GROTH16_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | using json = nlohmann::json; 8 | 9 | #include "fft.hpp" 10 | 11 | namespace Groth16 { 12 | 13 | template 14 | class Proof { 15 | Engine &E; 16 | public: 17 | typename Engine::G1PointAffine A; 18 | typename Engine::G2PointAffine B; 19 | typename Engine::G1PointAffine C; 20 | 21 | Proof(Engine &_E) : E(_E) { } 22 | std::string toJsonStr(); 23 | json toJson(); 24 | void fromJson(const json& proof); 25 | }; 26 | 27 | template 28 | class VerificationKey { 29 | Engine &E; 30 | public: 31 | typename Engine::G1PointAffine Alpha; 32 | typename Engine::G2PointAffine Beta; 33 | typename Engine::G2PointAffine Gamma; 34 | typename Engine::G2PointAffine Delta; 35 | std::vector IC; 36 | 37 | VerificationKey(Engine &_E) : E(_E) { } 38 | void fromJson(const json& proof); 39 | }; 40 | 41 | #pragma pack(push, 1) 42 | template 43 | struct Coef { 44 | u_int32_t m; 45 | u_int32_t c; 46 | u_int32_t s; 47 | typename Engine::FrElement coef; 48 | }; 49 | #pragma pack(pop) 50 | 51 | template 52 | class Prover { 53 | 54 | Engine &E; 55 | u_int32_t nVars; 56 | u_int32_t nPublic; 57 | u_int32_t domainSize; 58 | u_int64_t nCoefs; 59 | typename Engine::G1PointAffine &vk_alpha1; 60 | typename Engine::G1PointAffine &vk_beta1; 61 | typename Engine::G2PointAffine &vk_beta2; 62 | typename Engine::G1PointAffine &vk_delta1; 63 | typename Engine::G2PointAffine &vk_delta2; 64 | Coef *coefs; 65 | typename Engine::G1PointAffine *pointsA; 66 | typename Engine::G1PointAffine *pointsB1; 67 | typename Engine::G2PointAffine *pointsB2; 68 | typename Engine::G1PointAffine *pointsC; 69 | typename Engine::G1PointAffine *pointsH; 70 | 71 | FFT *fft; 72 | public: 73 | Prover( 74 | Engine &_E, 75 | u_int32_t _nVars, 76 | u_int32_t _nPublic, 77 | u_int32_t _domainSize, 78 | u_int64_t _nCoefs, 79 | typename Engine::G1PointAffine &_vk_alpha1, 80 | typename Engine::G1PointAffine &_vk_beta1, 81 | typename Engine::G2PointAffine &_vk_beta2, 82 | typename Engine::G1PointAffine &_vk_delta1, 83 | typename Engine::G2PointAffine &_vk_delta2, 84 | Coef *_coefs, 85 | typename Engine::G1PointAffine *_pointsA, 86 | typename Engine::G1PointAffine *_pointsB1, 87 | typename Engine::G2PointAffine *_pointsB2, 88 | typename Engine::G1PointAffine *_pointsC, 89 | typename Engine::G1PointAffine *_pointsH 90 | ) : 91 | E(_E), 92 | nVars(_nVars), 93 | nPublic(_nPublic), 94 | domainSize(_domainSize), 95 | nCoefs(_nCoefs), 96 | vk_alpha1(_vk_alpha1), 97 | vk_beta1(_vk_beta1), 98 | vk_beta2(_vk_beta2), 99 | vk_delta1(_vk_delta1), 100 | vk_delta2(_vk_delta2), 101 | coefs(_coefs), 102 | pointsA(_pointsA), 103 | pointsB1(_pointsB1), 104 | pointsB2(_pointsB2), 105 | pointsC(_pointsC), 106 | pointsH(_pointsH) 107 | { 108 | fft = new FFT(domainSize*2); 109 | } 110 | 111 | ~Prover() { 112 | delete fft; 113 | } 114 | 115 | std::unique_ptr> prove(typename Engine::FrElement *wtns); 116 | }; 117 | 118 | template 119 | std::unique_ptr> makeProver( 120 | u_int32_t nVars, 121 | u_int32_t nPublic, 122 | u_int32_t domainSize, 123 | u_int64_t nCoefs, 124 | void *vk_alpha1, 125 | void *vk_beta1, 126 | void *vk_beta2, 127 | void *vk_delta1, 128 | void *vk_delta2, 129 | void *coefs, 130 | void *pointsA, 131 | void *pointsB1, 132 | void *pointsB2, 133 | void *pointsC, 134 | void *pointsH 135 | ); 136 | 137 | template 138 | class Verifier { 139 | 140 | typedef std::vector InputsVector; 141 | typedef std::array G1PointArray; 142 | typedef std::array G2PointArray; 143 | 144 | Engine &E; 145 | 146 | public: 147 | Verifier(); 148 | 149 | bool verify( 150 | Proof &proof, 151 | InputsVector &inputs, 152 | VerificationKey &key); 153 | 154 | private: 155 | bool pairingCheck(G1PointArray& g1, G2PointArray& g2); 156 | 157 | typename Engine::F12Element miller(typename Engine::G2Point& b, typename Engine::G1Point& a); 158 | 159 | typename Engine::F12Element finalExponentiation(typename Engine::F12Element& in); 160 | 161 | void lineFunctionDouble( 162 | typename Engine::G2Point& r, 163 | typename Engine::G1PointAffine& q, 164 | typename Engine::F2Element& a, 165 | typename Engine::F2Element& b, 166 | typename Engine::F2Element& c, 167 | typename Engine::G2Point& rOut); 168 | 169 | void lineFunctionAdd( 170 | typename Engine::G2Point& r, 171 | typename Engine::G2PointAffine& p, 172 | typename Engine::G1PointAffine& q, 173 | typename Engine::F2Element& r2, 174 | typename Engine::F2Element& a, 175 | typename Engine::F2Element& b, 176 | typename Engine::F2Element& c, 177 | typename Engine::G2Point& rOut); 178 | 179 | void mulLine( 180 | typename Engine::F12Element& ret, 181 | typename Engine::F2Element& a, 182 | typename Engine::F2Element& b, 183 | typename Engine::F2Element& c); 184 | 185 | private: 186 | typename Engine::F2Element xiToPMinus1Over3; 187 | typename Engine::F2Element xiToPMinus1Over2; 188 | typename Engine::F1Element xiToPSquaredMinus1Over3; 189 | }; 190 | } 191 | 192 | 193 | #include "groth16.cpp" 194 | 195 | #endif 196 | -------------------------------------------------------------------------------- /src/logger.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // @File Name: Logger.cpp // 3 | // @Author: Pankaj Choudhary // 4 | // @Version: 0.0.1 // 5 | // @L.M.D: 13th April 2015 // 6 | // @Description: For Logging into file // 7 | // // 8 | // Detail Description: // 9 | // Implemented complete logging mechanism, Supporting multiple logging type // 10 | // like as file based logging, console base logging etc. It also supported // 11 | // for different log type. // 12 | // // 13 | // Thread Safe logging mechanism. Compatible with VC++ (Windows platform) // 14 | // as well as G++ (Linux platform) // 15 | // // 16 | // Supported Log Type: ERROR, ALARM, ALWAYS, INFO, BUFFER, TRACE, DEBUG // 17 | // // 18 | // No control for ERROR, ALRAM and ALWAYS messages. These type of messages // 19 | // should be always captured. // 20 | // // 21 | // BUFFER log type should be use while logging raw buffer or raw messages // 22 | // // 23 | // Having direct interface as well as C++ Singleton inface. can use // 24 | // whatever interface want. // 25 | // // 26 | /////////////////////////////////////////////////////////////////////////////// 27 | 28 | // C++ Header File(s) 29 | #include 30 | #include 31 | #include 32 | 33 | // Code Specific Header Files(s) 34 | #include "logger.hpp" 35 | 36 | using namespace std; 37 | using namespace CPlusPlusLogging; 38 | 39 | Logger* Logger::m_Instance = 0; 40 | 41 | // Log file name. File name should be change from here only 42 | const string logFileName = "MyLogFile.log"; 43 | 44 | Logger::Logger() 45 | { 46 | m_File.open(logFileName.c_str(), ios::out|ios::app); 47 | m_LogLevel = LOG_LEVEL_TRACE; 48 | m_LogType = FILE_LOG; 49 | 50 | // Initialize mutex 51 | #ifdef WIN32 52 | InitializeCriticalSection(&m_Mutex); 53 | #else 54 | int ret=0; 55 | ret = pthread_mutexattr_init(&m_Attr); // TODO: Pull request - Add this change to the common repo 56 | if (ret != 0) 57 | { 58 | printf("Logger::Logger() -- Mutex attribute could not initialize!!\n"); 59 | exit(0); 60 | } 61 | ret = pthread_mutexattr_settype(&m_Attr, PTHREAD_MUTEX_ERRORCHECK); 62 | if(ret != 0) 63 | { 64 | printf("Logger::Logger() -- Mutex attribute could not set type!!\n"); 65 | exit(0); 66 | } 67 | ret = pthread_mutex_init(&m_Mutex,&m_Attr); 68 | if(ret != 0) 69 | { 70 | printf("Logger::Logger() -- Mutex not initialize!!\n"); 71 | exit(0); 72 | } 73 | #endif 74 | } 75 | 76 | Logger::~Logger() 77 | { 78 | m_File.close(); 79 | #ifdef WIN32 80 | DeleteCriticalSection(&m_Mutex); 81 | #else 82 | pthread_mutexattr_destroy(&m_Attr); 83 | pthread_mutex_destroy(&m_Mutex); 84 | #endif 85 | } 86 | 87 | Logger* Logger::getInstance() throw () 88 | { 89 | if (m_Instance == 0) 90 | { 91 | m_Instance = new Logger(); 92 | } 93 | return m_Instance; 94 | } 95 | 96 | void Logger::lock() 97 | { 98 | #ifdef WIN32 99 | EnterCriticalSection(&m_Mutex); 100 | #else 101 | pthread_mutex_lock(&m_Mutex); 102 | #endif 103 | } 104 | 105 | void Logger::unlock() 106 | { 107 | #ifdef WIN32 108 | LeaveCriticalSection(&m_Mutex); 109 | #else 110 | pthread_mutex_unlock(&m_Mutex); 111 | #endif 112 | } 113 | 114 | void Logger::logIntoFile(std::string& data) 115 | { 116 | lock(); 117 | m_File << getCurrentTime() << " " << data << endl; 118 | unlock(); 119 | } 120 | 121 | void Logger::logOnConsole(std::string& data) 122 | { 123 | cout << getCurrentTime() << " " << data << endl; 124 | } 125 | 126 | string Logger::getCurrentTime() 127 | { 128 | string currTime; 129 | //Current date/time based on current time 130 | time_t now = time(0); 131 | // Convert current time to string 132 | currTime.assign(ctime(&now)); 133 | 134 | // Last charactor of currentTime is "\n", so remove it 135 | string currentTime = currTime.substr(0, currTime.size()-1); 136 | return currentTime; 137 | } 138 | 139 | // Interface for Error Log 140 | void Logger::error(const char* text) throw() 141 | { 142 | string data; 143 | data.append("[ERROR]: "); 144 | data.append(text); 145 | 146 | // ERROR must be capture 147 | if(m_LogType == FILE_LOG) 148 | { 149 | logIntoFile(data); 150 | } 151 | else if(m_LogType == CONSOLE) 152 | { 153 | logOnConsole(data); 154 | } 155 | } 156 | 157 | void Logger::error(std::string& text) throw() 158 | { 159 | error(text.data()); 160 | } 161 | 162 | void Logger::error(std::ostringstream& stream) throw() 163 | { 164 | string text = stream.str(); 165 | error(text.data()); 166 | } 167 | 168 | // Interface for Alarm Log 169 | void Logger::alarm(const char* text) throw() 170 | { 171 | string data; 172 | data.append("[ALARM]: "); 173 | data.append(text); 174 | 175 | // ALARM must be capture 176 | if(m_LogType == FILE_LOG) 177 | { 178 | logIntoFile(data); 179 | } 180 | else if(m_LogType == CONSOLE) 181 | { 182 | logOnConsole(data); 183 | } 184 | } 185 | 186 | void Logger::alarm(std::string& text) throw() 187 | { 188 | alarm(text.data()); 189 | } 190 | 191 | void Logger::alarm(std::ostringstream& stream) throw() 192 | { 193 | string text = stream.str(); 194 | alarm(text.data()); 195 | } 196 | 197 | // Interface for Always Log 198 | void Logger::always(const char* text) throw() 199 | { 200 | string data; 201 | data.append("[ALWAYS]: "); 202 | data.append(text); 203 | 204 | // No check for ALWAYS logs 205 | if(m_LogType == FILE_LOG) 206 | { 207 | logIntoFile(data); 208 | } 209 | else if(m_LogType == CONSOLE) 210 | { 211 | logOnConsole(data); 212 | } 213 | } 214 | 215 | void Logger::always(std::string& text) throw() 216 | { 217 | always(text.data()); 218 | } 219 | 220 | void Logger::always(std::ostringstream& stream) throw() 221 | { 222 | string text = stream.str(); 223 | always(text.data()); 224 | } 225 | 226 | // Interface for Buffer Log 227 | void Logger::buffer(const char* text) throw() 228 | { 229 | // Buffer is the special case. So don't add log level 230 | // and timestamp in the buffer message. Just log the raw bytes. 231 | if((m_LogType == FILE_LOG) && (m_LogLevel >= LOG_LEVEL_BUFFER)) 232 | { 233 | lock(); 234 | m_File << text << endl; 235 | unlock(); 236 | } 237 | else if((m_LogType == CONSOLE) && (m_LogLevel >= LOG_LEVEL_BUFFER)) 238 | { 239 | cout << text << endl; 240 | } 241 | } 242 | 243 | void Logger::buffer(std::string& text) throw() 244 | { 245 | buffer(text.data()); 246 | } 247 | 248 | void Logger::buffer(std::ostringstream& stream) throw() 249 | { 250 | string text = stream.str(); 251 | buffer(text.data()); 252 | } 253 | 254 | // Interface for Info Log 255 | void Logger::info(const char* text) throw() 256 | { 257 | string data; 258 | data.append("[INFO]: "); 259 | data.append(text); 260 | 261 | if((m_LogType == FILE_LOG) && (m_LogLevel >= LOG_LEVEL_INFO)) 262 | { 263 | logIntoFile(data); 264 | } 265 | else if((m_LogType == CONSOLE) && (m_LogLevel >= LOG_LEVEL_INFO)) 266 | { 267 | logOnConsole(data); 268 | } 269 | } 270 | 271 | void Logger::info(std::string& text) throw() 272 | { 273 | info(text.data()); 274 | } 275 | 276 | void Logger::info(std::ostringstream& stream) throw() 277 | { 278 | string text = stream.str(); 279 | info(text.data()); 280 | } 281 | 282 | // Interface for Trace Log 283 | void Logger::trace(const char* text) throw() 284 | { 285 | string data; 286 | data.append("[TRACE]: "); 287 | data.append(text); 288 | 289 | if((m_LogType == FILE_LOG) && (m_LogLevel >= LOG_LEVEL_TRACE)) 290 | { 291 | logIntoFile(data); 292 | } 293 | else if((m_LogType == CONSOLE) && (m_LogLevel >= LOG_LEVEL_TRACE)) 294 | { 295 | logOnConsole(data); 296 | } 297 | } 298 | 299 | void Logger::trace(std::string& text) throw() 300 | { 301 | trace(text.data()); 302 | } 303 | 304 | void Logger::trace(std::ostringstream& stream) throw() 305 | { 306 | string text = stream.str(); 307 | trace(text.data()); 308 | } 309 | 310 | // Interface for Debug Log 311 | void Logger::debug(const char* text) throw() 312 | { 313 | string data; 314 | data.append("[DEBUG]: "); 315 | data.append(text); 316 | 317 | if((m_LogType == FILE_LOG) && (m_LogLevel >= LOG_LEVEL_DEBUG)) 318 | { 319 | logIntoFile(data); 320 | } 321 | else if((m_LogType == CONSOLE) && (m_LogLevel >= LOG_LEVEL_DEBUG)) 322 | { 323 | logOnConsole(data); 324 | } 325 | } 326 | 327 | void Logger::debug(std::string& text) throw() 328 | { 329 | debug(text.data()); 330 | } 331 | 332 | void Logger::debug(std::ostringstream& stream) throw() 333 | { 334 | string text = stream.str(); 335 | debug(text.data()); 336 | } 337 | 338 | // Interfaces to control log levels 339 | void Logger::updateLogLevel(LogLevel logLevel) 340 | { 341 | m_LogLevel = logLevel; 342 | } 343 | 344 | // Enable all log levels 345 | void Logger::enaleLog() 346 | { 347 | m_LogLevel = ENABLE_LOG; 348 | } 349 | 350 | // Disable all log levels, except error and alarm 351 | void Logger:: disableLog() 352 | { 353 | m_LogLevel = DISABLE_LOG; 354 | } 355 | 356 | // Interfaces to control log Types 357 | void Logger::updateLogType(LogType logType) 358 | { 359 | m_LogType = logType; 360 | } 361 | 362 | void Logger::enableConsoleLogging() 363 | { 364 | m_LogType = CONSOLE; 365 | } 366 | 367 | void Logger::enableFileLogging() 368 | { 369 | m_LogType = FILE_LOG ; 370 | } 371 | 372 | -------------------------------------------------------------------------------- /src/logger.hpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // @File Name: Logger.h // 3 | // @Author: Pankaj Choudhary // 4 | // @Version: 0.0.1 // 5 | // @L.M.D: 13th April 2015 // 6 | // @Description: For Logging into file // 7 | // // 8 | // Detail Description: // 9 | // Implemented complete logging mechanism, Supporting multiple logging type // 10 | // like as file based logging, console base logging etc. It also supported // 11 | // for different log type. // 12 | // // 13 | // Thread Safe logging mechanism. Compatible with VC++ (Windows platform) // 14 | // as well as G++ (Linux platform) // 15 | // // 16 | // Supported Log Type: ERROR, ALARM, ALWAYS, INFO, BUFFER, TRACE, DEBUG // 17 | // // 18 | // No control for ERROR, ALRAM and ALWAYS messages. These type of messages // 19 | // should be always captured. // 20 | // // 21 | // BUFFER log type should be use while logging raw buffer or raw messages // 22 | // // 23 | // Having direct interface as well as C++ Singleton inface. can use // 24 | // whatever interface want. // 25 | // // 26 | /////////////////////////////////////////////////////////////////////////////// 27 | 28 | #ifndef _LOGGER_H_ 29 | #define _LOGGER_H_ 30 | 31 | // C++ Header File(s) 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #ifdef WIN32 38 | // Win Socket Header File(s) 39 | #include 40 | #include 41 | #else 42 | // POSIX Socket Header File(s) 43 | #include 44 | #include 45 | #endif 46 | 47 | namespace CPlusPlusLogging 48 | { 49 | // Direct Interface for logging into log file or console using MACRO(s) 50 | #define LOG_ERROR(x) Logger::getInstance()->error(x) 51 | #define LOG_ALARM(x) Logger::getInstance()->alarm(x) 52 | #define LOG_ALWAYS(x) Logger::getInstance()->always(x) 53 | #define LOG_INFO(x) Logger::getInstance()->info(x) 54 | #define LOG_BUFFER(x) Logger::getInstance()->buffer(x) 55 | #define LOG_TRACE(x) Logger::getInstance()->trace(x) 56 | #define LOG_DEBUG(x) Logger::getInstance()->debug(x) 57 | 58 | // enum for LOG_LEVEL 59 | typedef enum LOG_LEVEL 60 | { 61 | DISABLE_LOG = 1, 62 | LOG_LEVEL_INFO = 2, 63 | LOG_LEVEL_BUFFER = 3, 64 | LOG_LEVEL_TRACE = 4, 65 | LOG_LEVEL_DEBUG = 5, 66 | ENABLE_LOG = 6, 67 | }LogLevel; 68 | 69 | // enum for LOG_TYPE 70 | typedef enum LOG_TYPE 71 | { 72 | NO_LOG = 1, 73 | CONSOLE = 2, 74 | FILE_LOG = 3, 75 | }LogType; 76 | 77 | class Logger 78 | { 79 | public: 80 | static Logger* getInstance() throw (); 81 | 82 | // Interface for Error Log 83 | void error(const char* text) throw(); 84 | void error(std::string& text) throw(); 85 | void error(std::ostringstream& stream) throw(); 86 | 87 | // Interface for Alarm Log 88 | void alarm(const char* text) throw(); 89 | void alarm(std::string& text) throw(); 90 | void alarm(std::ostringstream& stream) throw(); 91 | 92 | // Interface for Always Log 93 | void always(const char* text) throw(); 94 | void always(std::string& text) throw(); 95 | void always(std::ostringstream& stream) throw(); 96 | 97 | // Interface for Buffer Log 98 | void buffer(const char* text) throw(); 99 | void buffer(std::string& text) throw(); 100 | void buffer(std::ostringstream& stream) throw(); 101 | 102 | // Interface for Info Log 103 | void info(const char* text) throw(); 104 | void info(std::string& text) throw(); 105 | void info(std::ostringstream& stream) throw(); 106 | 107 | // Interface for Trace log 108 | void trace(const char* text) throw(); 109 | void trace(std::string& text) throw(); 110 | void trace(std::ostringstream& stream) throw(); 111 | 112 | // Interface for Debug log 113 | void debug(const char* text) throw(); 114 | void debug(std::string& text) throw(); 115 | void debug(std::ostringstream& stream) throw(); 116 | 117 | // Error and Alarm log must be always enable 118 | // Hence, there is no interfce to control error and alarm logs 119 | 120 | // Interfaces to control log levels 121 | void updateLogLevel(LogLevel logLevel); 122 | void enaleLog(); // Enable all log levels 123 | void disableLog(); // Disable all log levels, except error and alarm 124 | 125 | // Interfaces to control log Types 126 | void updateLogType(LogType logType); 127 | void enableConsoleLogging(); 128 | void enableFileLogging(); 129 | 130 | protected: 131 | Logger(); 132 | ~Logger(); 133 | 134 | // Wrapper function for lock/unlock 135 | // For Extensible feature, lock and unlock should be in protected 136 | void lock(); 137 | void unlock(); 138 | 139 | std::string getCurrentTime(); 140 | 141 | private: 142 | void logIntoFile(std::string& data); 143 | void logOnConsole(std::string& data); 144 | Logger(const Logger& obj) {} 145 | void operator=(const Logger& obj) {} 146 | 147 | private: 148 | static Logger* m_Instance; 149 | std::ofstream m_File; 150 | 151 | #ifdef WIN32 152 | CRITICAL_SECTION m_Mutex; 153 | #else 154 | pthread_mutexattr_t m_Attr; 155 | pthread_mutex_t m_Mutex; 156 | #endif 157 | 158 | LogLevel m_LogLevel; 159 | LogType m_LogType; 160 | }; 161 | 162 | } // End of namespace 163 | 164 | #endif // End of _LOGGER_H_ 165 | 166 | -------------------------------------------------------------------------------- /src/logging.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LOGGING_HPP 2 | #define LOGGING_HPP 3 | 4 | #ifdef USE_LOGGER 5 | 6 | #include "logger.hpp" 7 | 8 | using namespace CPlusPlusLogging; 9 | 10 | #else 11 | 12 | #define LOG_ERROR(x) 13 | #define LOG_ALARM(x) 14 | #define LOG_ALWAYS(x) 15 | #define LOG_INFO(x) 16 | #define LOG_BUFFER(x) 17 | #define LOG_TRACE(x) 18 | #define LOG_DEBUG(x) 19 | 20 | #endif // USE_LOGGER 21 | 22 | #endif // LOGGING_HPP 23 | -------------------------------------------------------------------------------- /src/main_proofserver.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "proverapi.hpp" 4 | #include "fullprover.hpp" 5 | #include "logger.hpp" 6 | 7 | using namespace CPlusPlusLogging; 8 | using namespace Pistache; 9 | using namespace Pistache::Rest; 10 | 11 | int main(int argc, char **argv) { 12 | if (argc < 3) { 13 | std::cerr << "Invalid number of parameters:\n"; 14 | std::cerr << "Usage: proverServer ... \n"; 15 | return -1; 16 | } 17 | 18 | Logger::getInstance()->enableConsoleLogging(); 19 | Logger::getInstance()->updateLogLevel(LOG_LEVEL_DEBUG); 20 | LOG_INFO("Initializing server..."); 21 | int port = std::stoi(argv[1]); // parse port 22 | // parse the zkeys 23 | std::string zkeyFileNames[argc - 2]; 24 | for (int i = 0; i < argc - 2; i++) { 25 | zkeyFileNames[i] = argv[i + 2]; 26 | } 27 | 28 | FullProver fullProver(zkeyFileNames, argc - 2); 29 | ProverAPI proverAPI(fullProver); 30 | Address addr(Ipv4::any(), Port(port)); 31 | 32 | auto opts = Http::Endpoint::options().threads(1).maxRequestSize(128000000); 33 | Http::Endpoint server(addr); 34 | server.init(opts); 35 | Router router; 36 | Routes::Get(router, "/status", Routes::bind(&ProverAPI::getStatus, &proverAPI)); 37 | Routes::Post(router, "/start", Routes::bind(&ProverAPI::postStart, &proverAPI)); 38 | Routes::Post(router, "/stop", Routes::bind(&ProverAPI::postStop, &proverAPI)); 39 | Routes::Post(router, "/input/:circuit", Routes::bind(&ProverAPI::postInput, &proverAPI)); 40 | Routes::Post(router, "/cancel", Routes::bind(&ProverAPI::postCancel, &proverAPI)); 41 | server.setHandler(router.handler()); 42 | std::string serverReady("Server ready on port " + std::to_string(port) + "..."); 43 | LOG_INFO(serverReady); 44 | server.serve(); 45 | } 46 | -------------------------------------------------------------------------------- /src/main_prover.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "prover.h" 7 | #include "fileloader.hpp" 8 | 9 | int main(int argc, char **argv) 10 | { 11 | if (argc != 5) { 12 | std::cerr << "Invalid number of parameters" << std::endl; 13 | std::cerr << "Usage: prover " << std::endl; 14 | return EXIT_FAILURE; 15 | } 16 | 17 | try { 18 | const std::string zkeyFilename = argv[1]; 19 | const std::string wtnsFilename = argv[2]; 20 | const std::string proofFilename = argv[3]; 21 | const std::string publicFilename = argv[4]; 22 | 23 | BinFileUtils::FileLoader zkeyFile(zkeyFilename); 24 | BinFileUtils::FileLoader wtnsFile(wtnsFilename); 25 | std::vector publicBuffer; 26 | std::vector proofBuffer; 27 | unsigned long long publicSize = 0; 28 | unsigned long long proofSize = 0; 29 | char errorMsg[1024]; 30 | 31 | int error = groth16_public_size_for_zkey_buf( 32 | zkeyFile.dataBuffer(), 33 | zkeyFile.dataSize(), 34 | &publicSize, 35 | errorMsg, 36 | sizeof(errorMsg)); 37 | 38 | if (error != PROVER_OK) { 39 | throw std::runtime_error(errorMsg); 40 | } 41 | 42 | groth16_proof_size(&proofSize); 43 | 44 | publicBuffer.resize(publicSize); 45 | proofBuffer.resize(proofSize); 46 | 47 | error = groth16_prover( 48 | zkeyFile.dataBuffer(), 49 | zkeyFile.dataSize(), 50 | wtnsFile.dataBuffer(), 51 | wtnsFile.dataSize(), 52 | proofBuffer.data(), 53 | &proofSize, 54 | publicBuffer.data(), 55 | &publicSize, 56 | errorMsg, 57 | sizeof(errorMsg)); 58 | 59 | if (error != PROVER_OK) { 60 | throw std::runtime_error(errorMsg); 61 | } 62 | 63 | std::ofstream proofFile(proofFilename); 64 | proofFile.write(proofBuffer.data(), proofSize); 65 | 66 | std::ofstream publicFile(publicFilename); 67 | publicFile.write(publicBuffer.data(), publicSize); 68 | 69 | } catch (std::exception& e) { 70 | std::cerr << "Error: " << e.what() << std::endl; 71 | return EXIT_FAILURE; 72 | 73 | } 74 | 75 | exit(EXIT_SUCCESS); 76 | } 77 | -------------------------------------------------------------------------------- /src/main_verifier.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "fileloader.hpp" 5 | #include "verifier.h" 6 | 7 | int main(int argc, char **argv) 8 | { 9 | if (argc != 4) { 10 | std::cerr << "Invalid number of parameters:\n"; 11 | std::cerr << "Usage: verifier \n"; 12 | return EXIT_FAILURE; 13 | } 14 | 15 | try { 16 | const std::string keyFilename = argv[1]; 17 | const std::string inputsFilename = argv[2]; 18 | const std::string proofFilename = argv[3]; 19 | 20 | BinFileUtils::FileLoader proof(proofFilename); 21 | BinFileUtils::FileLoader inputs(inputsFilename); 22 | BinFileUtils::FileLoader key(keyFilename); 23 | 24 | char errorMessage[256]; 25 | 26 | const int error = groth16_verify(proof.dataAsString().c_str(), 27 | inputs.dataAsString().c_str(), 28 | key.dataAsString().c_str(), 29 | errorMessage, sizeof(errorMessage)); 30 | 31 | if (error == VERIFIER_VALID_PROOF) { 32 | 33 | std::cerr << "Result: Valid proof" << std::endl; 34 | return EXIT_SUCCESS; 35 | 36 | } else if (error == VERIFIER_INVALID_PROOF) { 37 | 38 | std::cerr << "Result: Invalid proof" << std::endl; 39 | return EXIT_FAILURE; 40 | 41 | } else { 42 | std::cerr << "Error: " << errorMessage << '\n'; 43 | return EXIT_FAILURE; 44 | } 45 | 46 | } catch (std::exception* e) { 47 | std::cerr << "Error: " << e->what() << std::endl; 48 | return EXIT_FAILURE; 49 | 50 | } catch (std::exception& e) { 51 | std::cerr << "Error: " << e.what() << std::endl; 52 | return EXIT_FAILURE; 53 | } 54 | 55 | return EXIT_FAILURE; 56 | } 57 | -------------------------------------------------------------------------------- /src/prover.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "prover.h" 8 | #include "groth16.hpp" 9 | #include "zkey_utils.hpp" 10 | #include "wtns_utils.hpp" 11 | #include "binfile_utils.hpp" 12 | #include "fileloader.hpp" 13 | 14 | using json = nlohmann::json; 15 | 16 | 17 | class ShortBufferException : public std::invalid_argument 18 | { 19 | public: 20 | explicit ShortBufferException(const std::string &msg) 21 | : std::invalid_argument(msg) {} 22 | }; 23 | 24 | class InvalidWitnessLengthException : public std::invalid_argument 25 | { 26 | public: 27 | explicit InvalidWitnessLengthException(const std::string &msg) 28 | : std::invalid_argument(msg) {} 29 | }; 30 | 31 | static void 32 | CopyError( 33 | char *error_msg, 34 | unsigned long long error_msg_maxsize, 35 | const std::exception &e) 36 | { 37 | if (error_msg) { 38 | strncpy(error_msg, e.what(), error_msg_maxsize); 39 | } 40 | } 41 | 42 | static void 43 | CopyError( 44 | char *error_msg, 45 | unsigned long long error_msg_maxsize, 46 | const char *str) 47 | { 48 | if (error_msg) { 49 | strncpy(error_msg, str, error_msg_maxsize); 50 | } 51 | } 52 | 53 | static unsigned long long 54 | ProofBufferMinSize() 55 | { 56 | return 810; 57 | } 58 | 59 | static unsigned long long 60 | PublicBufferMinSize(unsigned long long count) 61 | { 62 | return count * 82 + 4; 63 | } 64 | 65 | static bool 66 | PrimeIsValid(mpz_srcptr prime) 67 | { 68 | mpz_t altBbn128r; 69 | 70 | mpz_init(altBbn128r); 71 | mpz_set_str(altBbn128r, "21888242871839275222246405745257275088548364400416034343698204186575808495617", 10); 72 | 73 | const bool is_valid = (mpz_cmp(prime, altBbn128r) == 0); 74 | 75 | mpz_clear(altBbn128r); 76 | 77 | return is_valid; 78 | } 79 | 80 | static std::string 81 | BuildPublicString(AltBn128::FrElement *wtnsData, uint32_t nPublic) 82 | { 83 | json jsonPublic; 84 | AltBn128::FrElement aux; 85 | for (u_int32_t i=1; i<= nPublic; i++) { 86 | AltBn128::Fr.toMontgomery(aux, wtnsData[i]); 87 | jsonPublic.push_back(AltBn128::Fr.toString(aux)); 88 | } 89 | 90 | return jsonPublic.dump(); 91 | } 92 | 93 | static void 94 | CheckAndUpdateBufferSizes( 95 | unsigned long long proofCalcSize, 96 | unsigned long long *proofSize, 97 | unsigned long long publicCalcSize, 98 | unsigned long long *publicSize, 99 | const std::string &type) 100 | { 101 | if (*proofSize < proofCalcSize || *publicSize < publicCalcSize) { 102 | 103 | *proofSize = proofCalcSize; 104 | *publicSize = publicCalcSize; 105 | 106 | if (*proofSize < proofCalcSize) { 107 | throw ShortBufferException("Proof buffer is too short. " + type + " size: " 108 | + std::to_string(proofCalcSize) + 109 | ", actual size: " 110 | + std::to_string(*proofSize)); 111 | } else { 112 | throw ShortBufferException("Public buffer is too short. " + type + " size: " 113 | + std::to_string(proofCalcSize) + 114 | ", actual size: " 115 | + std::to_string(*proofSize)); 116 | } 117 | } 118 | } 119 | 120 | class Groth16Prover 121 | { 122 | BinFileUtils::BinFile zkey; 123 | std::unique_ptr zkeyHeader; 124 | std::unique_ptr> prover; 125 | 126 | public: 127 | Groth16Prover(const void *zkey_buffer, 128 | unsigned long long zkey_size) 129 | 130 | : zkey(zkey_buffer, zkey_size, "zkey", 1), 131 | zkeyHeader(ZKeyUtils::loadHeader(&zkey)) 132 | { 133 | if (!PrimeIsValid(zkeyHeader->rPrime)) { 134 | throw std::invalid_argument("zkey curve not supported"); 135 | } 136 | 137 | prover = Groth16::makeProver( 138 | zkeyHeader->nVars, 139 | zkeyHeader->nPublic, 140 | zkeyHeader->domainSize, 141 | zkeyHeader->nCoefs, 142 | zkeyHeader->vk_alpha1, 143 | zkeyHeader->vk_beta1, 144 | zkeyHeader->vk_beta2, 145 | zkeyHeader->vk_delta1, 146 | zkeyHeader->vk_delta2, 147 | zkey.getSectionData(4), // Coefs 148 | zkey.getSectionData(5), // pointsA 149 | zkey.getSectionData(6), // pointsB1 150 | zkey.getSectionData(7), // pointsB2 151 | zkey.getSectionData(8), // pointsC 152 | zkey.getSectionData(9) // pointsH1 153 | ); 154 | } 155 | 156 | void prove(const void *wtns_buffer, 157 | unsigned long long wtns_size, 158 | std::string &stringProof, 159 | std::string &stringPublic) 160 | { 161 | BinFileUtils::BinFile wtns(wtns_buffer, wtns_size, "wtns", 2); 162 | auto wtnsHeader = WtnsUtils::loadHeader(&wtns); 163 | 164 | if (zkeyHeader->nVars != wtnsHeader->nVars) { 165 | throw InvalidWitnessLengthException("Invalid witness length. Circuit: " 166 | + std::to_string(zkeyHeader->nVars) 167 | + ", witness: " 168 | + std::to_string(wtnsHeader->nVars)); 169 | } 170 | 171 | if (!PrimeIsValid(wtnsHeader->prime)) { 172 | throw std::invalid_argument("different wtns curve"); 173 | } 174 | 175 | AltBn128::FrElement *wtnsData = (AltBn128::FrElement *)wtns.getSectionData(2); 176 | 177 | auto proof = prover->prove(wtnsData); 178 | 179 | stringProof = proof->toJson().dump(); 180 | stringPublic = BuildPublicString(wtnsData, zkeyHeader->nPublic); 181 | } 182 | 183 | unsigned long long proofBufferMinSize() const 184 | { 185 | return ProofBufferMinSize(); 186 | } 187 | 188 | unsigned long long publicBufferMinSize() const 189 | { 190 | return PublicBufferMinSize(zkeyHeader->nPublic); 191 | } 192 | }; 193 | 194 | int 195 | groth16_public_size_for_zkey_buf( 196 | const void *zkey_buffer, 197 | unsigned long long zkey_size, 198 | unsigned long long *public_size, 199 | char *error_msg, 200 | unsigned long long error_msg_maxsize) 201 | { 202 | try { 203 | BinFileUtils::BinFile zkey(zkey_buffer, zkey_size, "zkey", 1); 204 | auto zkeyHeader = ZKeyUtils::loadHeader(&zkey); 205 | 206 | *public_size = PublicBufferMinSize(zkeyHeader->nPublic); 207 | 208 | } catch (std::exception& e) { 209 | CopyError(error_msg, error_msg_maxsize, e); 210 | return PROVER_ERROR; 211 | 212 | } catch (...) { 213 | CopyError(error_msg, error_msg_maxsize, "unknown error"); 214 | return PROVER_ERROR; 215 | } 216 | 217 | return PROVER_OK; 218 | } 219 | 220 | int 221 | groth16_public_size_for_zkey_file( 222 | const char *zkey_fname, 223 | unsigned long long *public_size, 224 | char *error_msg, 225 | unsigned long long error_msg_maxsize) 226 | { 227 | try { 228 | auto zkey = BinFileUtils::openExisting(zkey_fname, "zkey", 1); 229 | auto zkeyHeader = ZKeyUtils::loadHeader(zkey.get()); 230 | 231 | *public_size = PublicBufferMinSize(zkeyHeader->nPublic); 232 | 233 | } catch (std::exception& e) { 234 | CopyError(error_msg, error_msg_maxsize, e); 235 | return PROVER_ERROR; 236 | 237 | } catch (...) { 238 | CopyError(error_msg, error_msg_maxsize, "unknown error"); 239 | return PROVER_ERROR; 240 | } 241 | 242 | return PROVER_OK; 243 | } 244 | 245 | void 246 | groth16_proof_size( 247 | unsigned long long *proof_size) 248 | { 249 | *proof_size = ProofBufferMinSize(); 250 | } 251 | 252 | int 253 | groth16_prover_create( 254 | void **prover_object, 255 | const void *zkey_buffer, 256 | unsigned long long zkey_size, 257 | char *error_msg, 258 | unsigned long long error_msg_maxsize) 259 | { 260 | try { 261 | if (prover_object == NULL) { 262 | throw std::invalid_argument("Null prover object"); 263 | } 264 | 265 | if (zkey_buffer == NULL) { 266 | throw std::invalid_argument("Null zkey buffer"); 267 | } 268 | 269 | Groth16Prover *prover = new Groth16Prover(zkey_buffer, zkey_size); 270 | 271 | *prover_object = prover; 272 | 273 | } catch (std::exception& e) { 274 | CopyError(error_msg, error_msg_maxsize, e); 275 | return PROVER_ERROR; 276 | 277 | } catch (std::exception *e) { 278 | CopyError(error_msg, error_msg_maxsize, *e); 279 | delete e; 280 | return PROVER_ERROR; 281 | 282 | } catch (...) { 283 | CopyError(error_msg, error_msg_maxsize, "unknown error"); 284 | return PROVER_ERROR; 285 | } 286 | 287 | return PROVER_OK; 288 | } 289 | 290 | int 291 | groth16_prover_create_zkey_file( 292 | void **prover_object, 293 | const char *zkey_file_path, 294 | char *error_msg, 295 | unsigned long long error_msg_maxsize) 296 | { 297 | BinFileUtils::FileLoader fileLoader; 298 | 299 | try { 300 | fileLoader.load(zkey_file_path); 301 | 302 | } catch (std::exception& e) { 303 | CopyError(error_msg, error_msg_maxsize, e); 304 | return PROVER_ERROR; 305 | } 306 | 307 | return groth16_prover_create( 308 | prover_object, 309 | fileLoader.dataBuffer(), 310 | fileLoader.dataSize(), 311 | error_msg, 312 | error_msg_maxsize); 313 | } 314 | 315 | int 316 | groth16_prover_prove( 317 | void *prover_object, 318 | const void *wtns_buffer, 319 | unsigned long long wtns_size, 320 | char *proof_buffer, 321 | unsigned long long *proof_size, 322 | char *public_buffer, 323 | unsigned long long *public_size, 324 | char *error_msg, 325 | unsigned long long error_msg_maxsize) 326 | { 327 | try { 328 | if (prover_object == NULL) { 329 | throw std::invalid_argument("Null prover object"); 330 | } 331 | 332 | if (wtns_buffer == NULL) { 333 | throw std::invalid_argument("Null witness buffer"); 334 | } 335 | 336 | if (proof_buffer == NULL) { 337 | throw std::invalid_argument("Null proof buffer"); 338 | } 339 | 340 | if (proof_size == NULL) { 341 | throw std::invalid_argument("Null proof size"); 342 | } 343 | 344 | if (public_buffer == NULL) { 345 | throw std::invalid_argument("Null public buffer"); 346 | } 347 | 348 | if (public_size == NULL) { 349 | throw std::invalid_argument("Null public size"); 350 | } 351 | 352 | Groth16Prover *prover = static_cast(prover_object); 353 | 354 | CheckAndUpdateBufferSizes(prover->proofBufferMinSize(), proof_size, 355 | prover->publicBufferMinSize(), public_size, 356 | "Minimum"); 357 | 358 | std::string stringProof; 359 | std::string stringPublic; 360 | 361 | prover->prove(wtns_buffer, wtns_size, stringProof, stringPublic); 362 | 363 | CheckAndUpdateBufferSizes(stringProof.length(), proof_size, 364 | stringPublic.length(), public_size, 365 | "Required"); 366 | 367 | std::strncpy(proof_buffer, stringProof.c_str(), *proof_size); 368 | std::strncpy(public_buffer, stringPublic.c_str(), *public_size); 369 | 370 | } catch(InvalidWitnessLengthException& e) { 371 | CopyError(error_msg, error_msg_maxsize, e); 372 | return PROVER_INVALID_WITNESS_LENGTH; 373 | 374 | } catch(ShortBufferException& e) { 375 | CopyError(error_msg, error_msg_maxsize, e); 376 | return PROVER_ERROR_SHORT_BUFFER; 377 | 378 | } catch (std::exception& e) { 379 | CopyError(error_msg, error_msg_maxsize, e); 380 | return PROVER_ERROR; 381 | 382 | } catch (std::exception *e) { 383 | CopyError(error_msg, error_msg_maxsize, *e); 384 | delete e; 385 | return PROVER_ERROR; 386 | 387 | } catch (...) { 388 | CopyError(error_msg, error_msg_maxsize, "unknown error"); 389 | return PROVER_ERROR; 390 | } 391 | 392 | return PROVER_OK; 393 | } 394 | 395 | void 396 | groth16_prover_destroy(void *prover_object) 397 | { 398 | if (prover_object != NULL) { 399 | Groth16Prover *prover = static_cast(prover_object); 400 | 401 | delete prover; 402 | } 403 | } 404 | 405 | int 406 | groth16_prover( 407 | const void *zkey_buffer, 408 | unsigned long long zkey_size, 409 | const void *wtns_buffer, 410 | unsigned long long wtns_size, 411 | char *proof_buffer, 412 | unsigned long long *proof_size, 413 | char *public_buffer, 414 | unsigned long long *public_size, 415 | char *error_msg, 416 | unsigned long long error_msg_maxsize) 417 | { 418 | void *prover = NULL; 419 | 420 | int error = groth16_prover_create( 421 | &prover, 422 | zkey_buffer, 423 | zkey_size, 424 | error_msg, 425 | error_msg_maxsize); 426 | 427 | if (error != PROVER_OK) { 428 | return error; 429 | } 430 | 431 | error = groth16_prover_prove( 432 | prover, 433 | wtns_buffer, 434 | wtns_size, 435 | proof_buffer, 436 | proof_size, 437 | public_buffer, 438 | public_size, 439 | error_msg, 440 | error_msg_maxsize); 441 | 442 | groth16_prover_destroy(prover); 443 | 444 | return error; 445 | } 446 | 447 | int 448 | groth16_prover_zkey_file( 449 | const char *zkey_file_path, 450 | const void *wtns_buffer, 451 | unsigned long long wtns_size, 452 | char *proof_buffer, 453 | unsigned long long *proof_size, 454 | char *public_buffer, 455 | unsigned long long *public_size, 456 | char *error_msg, 457 | unsigned long long error_msg_maxsize) 458 | { 459 | BinFileUtils::FileLoader fileLoader; 460 | 461 | try { 462 | fileLoader.load(zkey_file_path); 463 | 464 | } catch (std::exception& e) { 465 | CopyError(error_msg, error_msg_maxsize, e); 466 | return PROVER_ERROR; 467 | } 468 | 469 | return groth16_prover( 470 | fileLoader.dataBuffer(), 471 | fileLoader.dataSize(), 472 | wtns_buffer, 473 | wtns_size, 474 | proof_buffer, 475 | proof_size, 476 | public_buffer, 477 | public_size, 478 | error_msg, 479 | error_msg_maxsize); 480 | } 481 | -------------------------------------------------------------------------------- /src/prover.h: -------------------------------------------------------------------------------- 1 | #ifndef PROVER_HPP 2 | #define PROVER_HPP 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | //Error codes returned by the functions. 9 | #define PROVER_OK 0x0 10 | #define PROVER_ERROR 0x1 11 | #define PROVER_ERROR_SHORT_BUFFER 0x2 12 | #define PROVER_INVALID_WITNESS_LENGTH 0x3 13 | 14 | /** 15 | * Calculates buffer size to output public signals as json string 16 | * @returns PROVER_OK in case of success, and the size of public buffer is written to public_size 17 | */ 18 | int 19 | groth16_public_size_for_zkey_buf( 20 | const void *zkey_buffer, 21 | unsigned long long zkey_size, 22 | unsigned long long *public_size, 23 | char *error_msg, 24 | unsigned long long error_msg_maxsize); 25 | 26 | /** 27 | * groth16_public_size_for_zkey_file calculates minimum buffer size for 28 | * JSON-formatted public signals. The calculated buffer size is written 29 | * to the public_size variable. 30 | * 31 | * @return error code: 32 | * PROVER_OK (0) - in case of success 33 | * PROVER_ERROR - in case of an error, error_msg contains the error message 34 | */ 35 | int 36 | groth16_public_size_for_zkey_file( 37 | const char *zkey_fname, 38 | unsigned long long *public_size, 39 | char *error_msg, 40 | unsigned long long error_msg_maxsize); 41 | 42 | /** 43 | * Returns buffer size to output proof as json string 44 | */ 45 | void 46 | groth16_proof_size( 47 | unsigned long long *proof_size); 48 | 49 | /** 50 | * Initializes 'prover_object' with a pointer to a new prover object. 51 | * @return error code: 52 | * PROVER_OK - in case of success 53 | * PPOVER_ERROR - in case of an error 54 | */ 55 | int 56 | groth16_prover_create( 57 | void **prover_object, 58 | const void *zkey_buffer, 59 | unsigned long long zkey_size, 60 | char *error_msg, 61 | unsigned long long error_msg_maxsize); 62 | 63 | /** 64 | * Initializes 'prover_object' with a pointer to a new prover object. 65 | * @return error code: 66 | * PROVER_OK - in case of success 67 | * PPOVER_ERROR - in case of an error 68 | */ 69 | int 70 | groth16_prover_create_zkey_file( 71 | void **prover_object, 72 | const char *zkey_file_path, 73 | char *error_msg, 74 | unsigned long long error_msg_maxsize); 75 | 76 | /** 77 | * Proves 'wtns_buffer' and saves results to 'proof_buffer' and 'public_buffer'. 78 | * @return error code: 79 | * PROVER_OK - in case of success 80 | * PPOVER_ERROR - in case of an error 81 | * PROVER_ERROR_SHORT_BUFFER - in case of a short buffer error, also updates proof_size and public_size with actual proof and public sizes 82 | */ 83 | int 84 | groth16_prover_prove( 85 | void *prover_object, 86 | const void *wtns_buffer, 87 | unsigned long long wtns_size, 88 | char *proof_buffer, 89 | unsigned long long *proof_size, 90 | char *public_buffer, 91 | unsigned long long *public_size, 92 | char *error_msg, 93 | unsigned long long error_msg_maxsize); 94 | 95 | /** 96 | * Destroys 'prover_object'. 97 | */ 98 | void 99 | groth16_prover_destroy(void *prover_object); 100 | 101 | /** 102 | * groth16_prover 103 | * @return error code: 104 | * PROVER_OK - in case of success 105 | * PPOVER_ERROR - in case of an error 106 | * PROVER_ERROR_SHORT_BUFFER - in case of a short buffer error, also updates proof_size and public_size with actual proof and public sizes 107 | */ 108 | int 109 | groth16_prover( 110 | const void *zkey_buffer, 111 | unsigned long long zkey_size, 112 | const void *wtns_buffer, 113 | unsigned long long wtns_size, 114 | char *proof_buffer, 115 | unsigned long long *proof_size, 116 | char *public_buffer, 117 | unsigned long long *public_size, 118 | char *error_msg, 119 | unsigned long long error_msg_maxsize); 120 | 121 | /** 122 | * groth16_prover_zkey_file 123 | * @return error code: 124 | * PROVER_OK - in case of success 125 | * PPOVER_ERROR - in case of an error 126 | * PROVER_ERROR_SHORT_BUFFER - in case of a short buffer error, also updates proof_size and public_size with actual proof and public sizes 127 | */ 128 | int 129 | groth16_prover_zkey_file( 130 | const char *zkey_file_path, 131 | const void *wtns_buffer, 132 | unsigned long long wtns_size, 133 | char *proof_buffer, 134 | unsigned long long *proof_size, 135 | char *public_buffer, 136 | unsigned long long *public_size, 137 | char *error_msg, 138 | unsigned long long error_msg_maxsize); 139 | 140 | #ifdef __cplusplus 141 | } 142 | #endif 143 | 144 | 145 | #endif // PROVER_HPP 146 | -------------------------------------------------------------------------------- /src/proverapi.cpp: -------------------------------------------------------------------------------- 1 | #include "proverapi.hpp" 2 | #include "nlohmann/json.hpp" 3 | #include "logger.hpp" 4 | 5 | using namespace Pistache; 6 | using json = nlohmann::json; 7 | 8 | 9 | void ProverAPI::postInput(const Rest::Request& request, Http::ResponseWriter response) { 10 | std::string circuit(request.param(":circuit").as()); 11 | LOG_TRACE(circuit); 12 | fullProver.startProve(request.body(), circuit); 13 | response.send(Http::Code::Ok); 14 | } 15 | 16 | void ProverAPI::postCancel(const Rest::Request& request, Http::ResponseWriter response) { 17 | fullProver.abort(); 18 | response.send(Http::Code::Ok); 19 | } 20 | 21 | void ProverAPI::getStatus(const Rest::Request& request, Http::ResponseWriter response) { 22 | json j = fullProver.getStatus(); 23 | LOG_DEBUG(j.dump().c_str()); 24 | response.send(Http::Code::Ok, j.dump(), MIME(Application, Json)); 25 | } 26 | 27 | void ProverAPI::postStart(const Rest::Request& request, Http::ResponseWriter response) { 28 | response.send(Http::Code::Ok); 29 | } 30 | 31 | void ProverAPI::postStop(const Rest::Request& request, Http::ResponseWriter response) { 32 | response.send(Http::Code::Ok); 33 | } 34 | 35 | void ProverAPI::getConfig(const Rest::Request& request, Http::ResponseWriter response) { 36 | response.send(Http::Code::Ok); 37 | } 38 | 39 | void ProverAPI::postConfig(const Rest::Request& request, Http::ResponseWriter response) { 40 | response.send(Http::Code::Ok); 41 | } 42 | 43 | -------------------------------------------------------------------------------- /src/proverapi.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "fullprover.hpp" 4 | 5 | using namespace Pistache; 6 | 7 | class ProverAPI { 8 | FullProver &fullProver; 9 | public: 10 | ProverAPI(FullProver &_fullProver) : fullProver(_fullProver) {}; 11 | void postStart(const Rest::Request& request, Http::ResponseWriter response); 12 | void postStop(const Rest::Request& request, Http::ResponseWriter response); 13 | void postInput(const Rest::Request& request, Http::ResponseWriter response); 14 | void postCancel(const Rest::Request& request, Http::ResponseWriter response); 15 | void getStatus(const Rest::Request& request, Http::ResponseWriter response); 16 | 17 | void getConfig(const Rest::Request& request, Http::ResponseWriter response); 18 | void postConfig(const Rest::Request& request, Http::ResponseWriter response); 19 | 20 | }; -------------------------------------------------------------------------------- /src/random_generator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef RANDOM_GENERATOR_H 2 | #define RANDOM_GENERATOR_H 3 | 4 | #ifdef USE_SODIUM 5 | 6 | #include 7 | 8 | #else 9 | 10 | #include 11 | 12 | inline void 13 | randombytes_buf(void * const buf, const size_t size) 14 | { 15 | std::random_device engine; 16 | std::uniform_int_distribution distr; 17 | 18 | uint8_t *buffer = static_cast(buf); 19 | 20 | for(size_t i = 0; i < size; i++) { 21 | buffer[i] = distr(engine); 22 | } 23 | } 24 | 25 | #endif //USE_SODIUM 26 | 27 | #endif // RANDOM_GENERATOR_H 28 | -------------------------------------------------------------------------------- /src/test_public_size.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Test functions groth16_public_size_for_zkey_file and 3 | * groth16_public_size_for_zkey_buf. 4 | * 5 | * Run it as 6 | * ./test_public_size 7 | * it will calculate the required public signals buffer size from the zkey file 8 | * and compare it with the expected one. Return 0 if success. 9 | * Return 1 if failure. Also prints the time taken by each function. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "prover.h" 20 | 21 | int 22 | test_groth16_public_size(const char *zkey_fname, unsigned long long *public_size) { 23 | int ret_val = 0; 24 | const int error_sz = 256; 25 | char error_msg[error_sz]; 26 | 27 | int fd = open(zkey_fname, O_RDONLY); 28 | if (fd == -1) { 29 | printf("Error: %s\n", "open"); 30 | ret_val = 1; 31 | goto cleanup; 32 | } 33 | 34 | struct stat sb = {0}; 35 | if (fstat(fd, &sb) == -1) { 36 | printf("Error: %s\n", "fstat"); 37 | ret_val = 1; 38 | goto cleanup; 39 | } 40 | 41 | void *buf = malloc(sb.st_size); 42 | if (buf == NULL) { 43 | printf("Error: %s\n", "malloc"); 44 | ret_val = 1; 45 | goto cleanup; 46 | } 47 | 48 | ssize_t bytes_read = read(fd, buf, sb.st_size); 49 | if (bytes_read != sb.st_size) { 50 | printf("Error: %s\n", "read"); 51 | ret_val = 1; 52 | goto cleanup; 53 | } 54 | 55 | int ok = groth16_public_size_for_zkey_buf(buf, sb.st_size, public_size, error_msg, error_sz); 56 | if (ok == 0) { 57 | printf("Public size: %llu\n", *public_size); 58 | } else { 59 | printf("Error: %s\n", error_msg); 60 | ret_val = 1; 61 | goto cleanup; 62 | } 63 | 64 | cleanup: 65 | 66 | if (fd != -1) 67 | if (close(fd) == -1) 68 | printf("Error: %s\n", "close"); 69 | 70 | return ret_val; 71 | } 72 | 73 | int 74 | test_groth16_public_size_for_zkey_file(const char *zkey_fname, 75 | unsigned long long *public_size) { 76 | const int err_ln = 256; 77 | char error_msg[err_ln]; 78 | int ret = groth16_public_size_for_zkey_file(zkey_fname, public_size, error_msg, err_ln); 79 | 80 | if (ret == 0) { 81 | printf("Public size: %llu\n", *public_size); 82 | } else { 83 | printf("Error: %s\n", error_msg); 84 | } 85 | return ret; 86 | } 87 | 88 | int 89 | main(int argc, char *argv[]) { 90 | if (argc < 3) { 91 | printf("Usage: %s \n", argv[0]); 92 | return 1; 93 | } 94 | 95 | long want_pub_size = 0; 96 | want_pub_size = strtol(argv[2], NULL, 10); 97 | 98 | int ret_val = 0; 99 | clock_t start = clock(); 100 | 101 | unsigned long long public_size = 0; 102 | 103 | int test_groth16_public_size_ok = 104 | test_groth16_public_size(argv[1], &public_size); 105 | if (test_groth16_public_size_ok) { 106 | printf("test_groth16_public_size failed\n"); 107 | ret_val = 1; 108 | } else { 109 | clock_t end = clock(); 110 | printf("test_groth16_public_size succeeded in %f seconds\n", 111 | (double)(end - start) / CLOCKS_PER_SEC); 112 | } 113 | 114 | if (public_size != want_pub_size) { 115 | printf("test_groth16_public_size expected public signals buf size: %ld\n", 116 | want_pub_size); 117 | printf("test_groth16_public_size actual public signals buf size: %llu\n", 118 | public_size); 119 | ret_val = 1; 120 | } 121 | 122 | public_size = 0; 123 | start = clock(); 124 | int test_groth16_public_size_for_zkey_file_ok = 125 | test_groth16_public_size_for_zkey_file(argv[1], &public_size); 126 | if (test_groth16_public_size_for_zkey_file_ok) { 127 | printf("test_groth16_public_size_for_zkey_file failed\n"); 128 | ret_val = 1; 129 | } else { 130 | clock_t end = clock(); 131 | printf("test_groth16_public_size_for_zkey_file succeeded in %f seconds\n", 132 | (double)(end - start) / CLOCKS_PER_SEC); 133 | } 134 | 135 | if (public_size != want_pub_size) { 136 | printf("test_groth16_public_size_for_zkey_file expected public signals buf size: %ld\n", 137 | want_pub_size); 138 | printf("test_groth16_public_size_for_zkey_file actual public signals buf size: %llu\n", 139 | public_size); 140 | ret_val = 1; 141 | } 142 | 143 | return ret_val; 144 | } 145 | 146 | -------------------------------------------------------------------------------- /src/verifier.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "verifier.h" 7 | #include "groth16.hpp" 8 | 9 | using json = nlohmann::json; 10 | 11 | static Groth16::Proof 12 | parse_proof(const char *proof_str) 13 | { 14 | Groth16::Proof proof(AltBn128::Engine::engine); 15 | 16 | try { 17 | json proof_json = json::parse(proof_str); 18 | 19 | std::string protocol = proof_json["protocol"].template get(); 20 | 21 | if (protocol != "groth16") { 22 | throw std::invalid_argument("invalid proof data"); 23 | } 24 | 25 | proof.fromJson(proof_json); 26 | 27 | } catch(...) { 28 | throw std::invalid_argument("invalid proof data") ; 29 | } 30 | 31 | return proof; 32 | } 33 | 34 | static std::vector 35 | parse_inputs(const char *inputs_str) 36 | { 37 | std::vector inputs; 38 | 39 | try { 40 | json inputs_json = json::parse(inputs_str); 41 | 42 | auto inputs_str_vec = inputs_json.template get>(); 43 | 44 | if (inputs_str_vec.empty()) { 45 | throw std::invalid_argument("invalid inputs data"); 46 | } 47 | 48 | inputs.reserve(inputs_str_vec.size()); 49 | 50 | for (const auto& elem: inputs_str_vec) { 51 | AltBn128::FrElement aux; 52 | 53 | AltBn128::Fr.fromString(aux, elem); 54 | inputs.push_back(aux); 55 | } 56 | 57 | } catch(...) { 58 | throw std::invalid_argument("invalid inputs data") ; 59 | } 60 | 61 | return inputs; 62 | } 63 | 64 | static Groth16::VerificationKey 65 | parse_key(const char *key_str) 66 | { 67 | Groth16::VerificationKey key(AltBn128::Engine::engine); 68 | 69 | try { 70 | json key_json = json::parse(key_str); 71 | 72 | auto protocol = key_json["protocol"].template get(); 73 | auto curve = key_json["curve"].template get(); 74 | auto nPublic = key_json["nPublic"].template get(); 75 | 76 | if (protocol != "groth16" || curve != "bn128") { 77 | throw std::invalid_argument("invalid verification key data"); 78 | } 79 | 80 | key.fromJson(key_json); 81 | 82 | if (key.IC.empty()) { 83 | throw std::invalid_argument("invalid verification key data"); 84 | } 85 | 86 | } catch(...) { 87 | throw std::invalid_argument("invalid verification key data"); 88 | } 89 | 90 | return key; 91 | } 92 | 93 | int 94 | groth16_verify(const char *proof, 95 | const char *inputs, 96 | const char *verification_key, 97 | char *error_msg, 98 | unsigned long error_msg_maxsize) 99 | { 100 | try { 101 | 102 | auto proof_value = parse_proof(proof); 103 | auto inputs_value = parse_inputs(inputs); 104 | auto key_value = parse_key(verification_key); 105 | 106 | Groth16::Verifier verifier; 107 | 108 | bool valid = verifier.verify(proof_value, inputs_value, key_value); 109 | 110 | return valid ? VERIFIER_VALID_PROOF : VERIFIER_INVALID_PROOF; 111 | 112 | } catch (std::exception& e) { 113 | 114 | if (error_msg) { 115 | strncpy(error_msg, e.what(), error_msg_maxsize); 116 | } 117 | return VERIFIER_ERROR; 118 | 119 | } catch (std::exception *e) { 120 | 121 | if (error_msg) { 122 | strncpy(error_msg, e->what(), error_msg_maxsize); 123 | } 124 | delete e; 125 | return VERIFIER_ERROR; 126 | 127 | } catch (...) { 128 | if (error_msg) { 129 | strncpy(error_msg, "unknown error", error_msg_maxsize); 130 | } 131 | return VERIFIER_ERROR; 132 | } 133 | 134 | return VERIFIER_INVALID_PROOF; 135 | } 136 | -------------------------------------------------------------------------------- /src/verifier.h: -------------------------------------------------------------------------------- 1 | #ifndef VERIFIER_HPP 2 | #define VERIFIER_HPP 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | //Error codes returned by the functions. 9 | #define VERIFIER_VALID_PROOF 0x0 10 | #define VERIFIER_INVALID_PROOF 0x1 11 | #define VERIFIER_ERROR 0x2 12 | 13 | /** 14 | * 'proof', 'inputs' and 'verification_key' are null-terminated json strings. 15 | * 16 | * @return error code: 17 | * VERIFIER_VALID_PROOF - in case of valid 'proof'. 18 | * VERIFIER_INVALID_PROOF - in case of invalid 'proof'. 19 | VERIFIER_ERROR - in case of an error 20 | */ 21 | 22 | int 23 | groth16_verify(const char *proof, 24 | const char *inputs, 25 | const char *verification_key, 26 | char *error_msg, 27 | unsigned long error_msg_maxsize); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | 34 | #endif // VERIFIER_HPP 35 | -------------------------------------------------------------------------------- /src/wtns_utils.cpp: -------------------------------------------------------------------------------- 1 | #include "wtns_utils.hpp" 2 | 3 | namespace WtnsUtils { 4 | 5 | Header::Header() { 6 | mpz_init(prime); 7 | } 8 | 9 | Header::~Header() { 10 | mpz_clear(prime); 11 | } 12 | 13 | std::unique_ptr
loadHeader(BinFileUtils::BinFile *f) { 14 | std::unique_ptr
h(new Header()); 15 | 16 | f->startReadSection(1); 17 | 18 | h->n8 = f->readU32LE(); 19 | mpz_import(h->prime, h->n8, -1, 1, -1, 0, f->read(h->n8)); 20 | 21 | h->nVars = f->readU32LE(); 22 | 23 | f->endReadSection(); 24 | 25 | return h; 26 | } 27 | 28 | } // NAMESPACE 29 | -------------------------------------------------------------------------------- /src/wtns_utils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WTNS_UTILS 2 | #define WTNS_UTILS 3 | 4 | #include 5 | 6 | #include "binfile_utils.hpp" 7 | 8 | namespace WtnsUtils { 9 | 10 | class Header { 11 | public: 12 | u_int32_t n8; 13 | mpz_t prime; 14 | 15 | u_int32_t nVars; 16 | 17 | Header(); 18 | ~Header(); 19 | }; 20 | 21 | std::unique_ptr
loadHeader(BinFileUtils::BinFile *f); 22 | 23 | } 24 | 25 | #endif // ZKEY_UTILS_H -------------------------------------------------------------------------------- /src/zkey_utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "zkey_utils.hpp" 4 | 5 | namespace ZKeyUtils { 6 | 7 | 8 | Header::Header() { 9 | mpz_init(qPrime); 10 | mpz_init(rPrime); 11 | } 12 | 13 | Header::~Header() { 14 | mpz_clear(qPrime); 15 | mpz_clear(rPrime); 16 | } 17 | 18 | 19 | std::unique_ptr
loadHeader(BinFileUtils::BinFile *f) { 20 | 21 | std::unique_ptr
h(new Header()); 22 | 23 | f->startReadSection(1); 24 | uint32_t protocol = f->readU32LE(); 25 | if (protocol != 1) { 26 | throw std::invalid_argument( "zkey file is not groth16" ); 27 | } 28 | f->endReadSection(); 29 | 30 | f->startReadSection(2); 31 | 32 | h->n8q = f->readU32LE(); 33 | mpz_import(h->qPrime, h->n8q, -1, 1, -1, 0, f->read(h->n8q)); 34 | 35 | h->n8r = f->readU32LE(); 36 | mpz_import(h->rPrime, h->n8r , -1, 1, -1, 0, f->read(h->n8r)); 37 | 38 | h->nVars = f->readU32LE(); 39 | h->nPublic = f->readU32LE(); 40 | h->domainSize = f->readU32LE(); 41 | 42 | h->vk_alpha1 = f->read(h->n8q*2); 43 | h->vk_beta1 = f->read(h->n8q*2); 44 | h->vk_beta2 = f->read(h->n8q*4); 45 | h->vk_gamma2 = f->read(h->n8q*4); 46 | h->vk_delta1 = f->read(h->n8q*2); 47 | h->vk_delta2 = f->read(h->n8q*4); 48 | f->endReadSection(); 49 | 50 | h->nCoefs = f->getSectionSize(4) / (12 + h->n8r); 51 | 52 | return h; 53 | } 54 | 55 | } // namespace 56 | 57 | -------------------------------------------------------------------------------- /src/zkey_utils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ZKEY_UTILS_H 2 | #define ZKEY_UTILS_H 3 | 4 | #include 5 | #include 6 | 7 | #include "binfile_utils.hpp" 8 | 9 | namespace ZKeyUtils { 10 | 11 | class Header { 12 | 13 | 14 | public: 15 | u_int32_t n8q; 16 | mpz_t qPrime; 17 | u_int32_t n8r; 18 | mpz_t rPrime; 19 | 20 | u_int32_t nVars; 21 | u_int32_t nPublic; 22 | u_int32_t domainSize; 23 | u_int64_t nCoefs; 24 | 25 | void *vk_alpha1; 26 | void *vk_beta1; 27 | void *vk_beta2; 28 | void *vk_gamma2; 29 | void *vk_delta1; 30 | void *vk_delta2; 31 | 32 | Header(); 33 | ~Header(); 34 | }; 35 | 36 | std::unique_ptr
loadHeader(BinFileUtils::BinFile *f); 37 | } 38 | 39 | #endif // ZKEY_UTILS_H 40 | -------------------------------------------------------------------------------- /tasksfile.js: -------------------------------------------------------------------------------- 1 | const { sh, cli } = require("tasksfile"); 2 | 3 | function cleanAll() { 4 | sh("rm -rf build"); 5 | } 6 | 7 | function createFieldSources() { 8 | sh("mkdir -p build"); 9 | sh("npm install", {cwd: "depends/ffiasm"}); 10 | sh("node ../depends/ffiasm/src/buildzqfield.js -q 21888242871839275222246405745257275088696311157297823662689037894645226208583 -n Fq", {cwd: "build"}); 11 | sh("node ../depends/ffiasm/src/buildzqfield.js -q 21888242871839275222246405745257275088548364400416034343698204186575808495617 -n Fr", {cwd: "build"}); 12 | 13 | if (process.platform === "darwin") { 14 | sh("nasm -fmacho64 --prefix _ fq.asm", {cwd: "build"}); 15 | } else if (process.platform === "linux") { 16 | sh("nasm -felf64 fq.asm", {cwd: "build"}); 17 | } else throw("Unsupported platform"); 18 | 19 | if (process.platform === "darwin") { 20 | sh("nasm -fmacho64 --prefix _ fr.asm", {cwd: "build"}); 21 | } else if (process.platform === "linux") { 22 | sh("nasm -felf64 fr.asm", {cwd: "build"}); 23 | } else throw("Unsupported platform"); 24 | } 25 | 26 | function buildPistache() { 27 | sh("git submodule init && git submodule update"); 28 | sh("mkdir -p build", {cwd: "depends/pistache"}); 29 | sh("cmake -G \"Unix Makefiles\" -DCMAKE_BUILD_TYPE=Release ..", {cwd: "depends/pistache/build"}); 30 | sh("make", {cwd: "depends/pistache/build"}); 31 | } 32 | 33 | 34 | function buildProverServer() { 35 | sh("g++" + 36 | " -I."+ 37 | " -I../src"+ 38 | " -I../depends/pistache/include"+ 39 | " -I../depends/json/single_include"+ 40 | " -I../depends/ffiasm/c"+ 41 | " ../src/main_proofserver.cpp"+ 42 | " ../src/proverapi.cpp"+ 43 | " ../src/fullprover.cpp"+ 44 | " ../src/binfile_utils.cpp"+ 45 | " ../src/wtns_utils.cpp"+ 46 | " ../src/zkey_utils.cpp"+ 47 | " ../src/logger.cpp"+ 48 | " ../depends/ffiasm/c/misc.cpp"+ 49 | " ../depends/ffiasm/c/naf.cpp"+ 50 | " ../depends/ffiasm/c/splitparstr.cpp"+ 51 | " ../depends/ffiasm/c/alt_bn128.cpp"+ 52 | " fq.cpp"+ 53 | " fq.o"+ 54 | " fr.cpp"+ 55 | " fr.o"+ 56 | " -L../depends/pistache/build/src -lpistache"+ 57 | " -o proverServer"+ 58 | " -fmax-errors=5 -pthread -std=c++17 -fopenmp -lgmp -lsodium -g -DSANITY_CHECK", {cwd: "build", nopipe: true} 59 | ); 60 | } 61 | 62 | 63 | function buildProver() { 64 | sh("g++" + 65 | " -I."+ 66 | " -I../src"+ 67 | " -I../depends/ffiasm/c"+ 68 | " -I../depends/json/single_include"+ 69 | " ../src/main_prover.cpp"+ 70 | " ../src/binfile_utils.cpp"+ 71 | " ../src/zkey_utils.cpp"+ 72 | " ../src/wtns_utils.cpp"+ 73 | " ../src/logger.cpp"+ 74 | " ../depends/ffiasm/c/misc.cpp"+ 75 | " ../depends/ffiasm/c/naf.cpp"+ 76 | " ../depends/ffiasm/c/splitparstr.cpp"+ 77 | " ../depends/ffiasm/c/alt_bn128.cpp"+ 78 | " fq.cpp"+ 79 | " fq.o"+ 80 | " fr.cpp"+ 81 | " fr.o"+ 82 | " -o prover" + 83 | " -fmax-errors=5 -std=c++17 -pthread -lgmp -lsodium -O3 -fopenmp", {cwd: "build", nopipe: true} 84 | ); 85 | } 86 | 87 | 88 | cli({ 89 | cleanAll, 90 | createFieldSources, 91 | buildPistache, 92 | buildProverServer, 93 | buildProver 94 | }); 95 | -------------------------------------------------------------------------------- /testdata/circuit_final.zkey: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/rapidsnark/998383787ee86bcb6bfb8741e9a638d203c08eae/testdata/circuit_final.zkey -------------------------------------------------------------------------------- /testdata/verification_key.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": "groth16", 3 | "curve": "bn128", 4 | "nPublic": 1, 5 | "vk_alpha_1": [ 6 | "20491192805390485299153009773594534940189261866228447918068658471970481763042", 7 | "9383485363053290200918347156157836566562967994039712273449902621266178545958", 8 | "1" 9 | ], 10 | "vk_beta_2": [ 11 | [ 12 | "6375614351688725206403948262868962793625744043794305715222011528459656738731", 13 | "4252822878758300859123897981450591353533073413197771768651442665752259397132" 14 | ], 15 | [ 16 | "10505242626370262277552901082094356697409835680220590971873171140371331206856", 17 | "21847035105528745403288232691147584728191162732299865338377159692350059136679" 18 | ], 19 | [ 20 | "1", 21 | "0" 22 | ] 23 | ], 24 | "vk_gamma_2": [ 25 | [ 26 | "10857046999023057135944570762232829481370756359578518086990519993285655852781", 27 | "11559732032986387107991004021392285783925812861821192530917403151452391805634" 28 | ], 29 | [ 30 | "8495653923123431417604973247489272438418190587263600148770280649306958101930", 31 | "4082367875863433681332203403145435568316851327593401208105741076214120093531" 32 | ], 33 | [ 34 | "1", 35 | "0" 36 | ] 37 | ], 38 | "vk_delta_2": [ 39 | [ 40 | "10056322322891219854268402349413163241212310059164911282424429574909837055562", 41 | "12530590306125500264744927194515711435185554567505632685219127544784956548143" 42 | ], 43 | [ 44 | "3198185062701173616088252494763783302271691955806883740290181107756211891848", 45 | "5935918403904311654026004102721758093545898651591152833499461744182771134433" 46 | ], 47 | [ 48 | "1", 49 | "0" 50 | ] 51 | ], 52 | "vk_alphabeta_12": [ 53 | [ 54 | [ 55 | "2029413683389138792403550203267699914886160938906632433982220835551125967885", 56 | "21072700047562757817161031222997517981543347628379360635925549008442030252106" 57 | ], 58 | [ 59 | "5940354580057074848093997050200682056184807770593307860589430076672439820312", 60 | "12156638873931618554171829126792193045421052652279363021382169897324752428276" 61 | ], 62 | [ 63 | "7898200236362823042373859371574133993780991612861777490112507062703164551277", 64 | "7074218545237549455313236346927434013100842096812539264420499035217050630853" 65 | ] 66 | ], 67 | [ 68 | [ 69 | "7077479683546002997211712695946002074877511277312570035766170199895071832130", 70 | "10093483419865920389913245021038182291233451549023025229112148274109565435465" 71 | ], 72 | [ 73 | "4595479056700221319381530156280926371456704509942304414423590385166031118820", 74 | "19831328484489333784475432780421641293929726139240675179672856274388269393268" 75 | ], 76 | [ 77 | "11934129596455521040620786944827826205713621633706285934057045369193958244500", 78 | "8037395052364110730298837004334506829870972346962140206007064471173334027475" 79 | ] 80 | ] 81 | ], 82 | "IC": [ 83 | [ 84 | "11932556748928578545728995536027201108657542124050415478292462831771509095304", 85 | "9149370873483970774321348444196634478850132879039205704924275954730380431457", 86 | "1" 87 | ], 88 | [ 89 | "17482596306642470706171849523416052476936601967698452358356767181693176975875", 90 | "16875289648181723199466955981261105815550134487513330320459939834929279218791", 91 | "1" 92 | ] 93 | ] 94 | } -------------------------------------------------------------------------------- /testdata/witness.wtns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iden3/rapidsnark/998383787ee86bcb6bfb8741e9a638d203c08eae/testdata/witness.wtns -------------------------------------------------------------------------------- /tools/request.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const fetch = require('node-fetch'); 3 | 4 | const input = fs.readFileSync(process.argv[2], "utf8"); 5 | const circuit = process.argv[3]; 6 | 7 | async function callInput() { 8 | const rawResponse = await fetch(`http://localhost:9080/input/${circuit}`, { 9 | method: 'POST', 10 | headers: { 11 | 'Accept': 'application/json', 12 | 'Content-Type': 'application/json' 13 | }, 14 | body: input 15 | }); 16 | if (rawResponse.ok) { 17 | return true; 18 | } else { 19 | throw new Error(rawResponse.status); 20 | } 21 | }; 22 | 23 | 24 | async function getStatus() { 25 | const rawResponse = await fetch('http://localhost:9080/status', { 26 | method: 'GET', 27 | headers: { 28 | 'Accept': 'application/json' 29 | } 30 | }); 31 | if (!rawResponse.ok) { 32 | throw new Error(rawResponse.status); 33 | } 34 | return rawResponse.json(); 35 | } 36 | 37 | async function run() { 38 | await callInput(); 39 | let st; 40 | st = await getStatus(); 41 | while (st.status == "busy") { 42 | st = await getStatus(); 43 | } 44 | console.log(JSON.stringify(st, null,1)); 45 | } 46 | 47 | run().then(() => { 48 | process.exit(0); 49 | }, (err) => { 50 | console.log("ERROR"); 51 | console.log(err); 52 | process.exit(1); 53 | }); --------------------------------------------------------------------------------