├── .github └── 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 ├── groth16_cuda.cu ├── logger.cpp ├── logger.hpp ├── logging.hpp ├── main_icicle_msm_test.cu ├── main_icicle_ntt_test.cu ├── main_proofserver.cpp ├── main_prover.cpp ├── main_prover_cuda.cu ├── 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/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | release: 5 | types: [published] 6 | push: 7 | branches: 8 | - main 9 | pull_request: 10 | 11 | jobs: 12 | build-linux: 13 | runs-on: ubuntu-22.04 14 | steps: 15 | - uses: actions/checkout@v4 16 | with: 17 | submodules: "recursive" 18 | 19 | - name: install requirements 20 | uses: awalsh128/cache-apt-pkgs-action@v1 21 | with: 22 | packages: build-essential cmake m4 nasm 23 | version: 1.0 24 | 25 | - name: Cache gmp build 26 | uses: actions/cache@v3 27 | with: 28 | path: | 29 | depends/gmp 30 | depends/gmp-6.2.1.tar.xz 31 | key: ${{ runner.os }}-gmp-${{ hashFiles('build_gmp.sh') }}-2 32 | 33 | - name: build gmp for Android arm64 34 | run: if [[ ! -d "depends/gmp/package_android_arm64" ]]; then ./build_gmp.sh android; fi 35 | 36 | - name: build gmp for Android x86_64 37 | run: if [[ ! -d "depends/gmp/package_android_x86_64" ]]; then ./build_gmp.sh android_x86_64; fi 38 | 39 | - name: build gmp for Linux x86_64 40 | run: if [[ ! -d "depends/gmp/package" ]]; then ./build_gmp.sh host; fi 41 | 42 | - name: Build prover Android ARM64 43 | run: | 44 | mkdir -p build_prover_android && cd build_prover_android 45 | cmake .. -DTARGET_PLATFORM=ANDROID -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_android 46 | make -j4 && make install 47 | 48 | - name: Build prover Android x86_64 49 | run: | 50 | mkdir -p build_prover_android_x86_64 && cd build_prover_android_x86_64 51 | cmake .. -DTARGET_PLATFORM=ANDROID_x86_64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_android_x86_64 52 | make -j4 && make install 53 | 54 | - name: Build prover Linux 55 | run: | 56 | mkdir -p build_prover && cd build_prover 57 | cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package 58 | make -j4 && make install 59 | ctest --rerun-failed --output-on-failure 60 | 61 | - name: test rapidsnark 62 | run: | 63 | set -x 64 | set -e 65 | package/bin/prover testdata/circuit_final.zkey testdata/witness.wtns proof.json public.json 66 | package/bin/verifier testdata/verification_key.json public.json proof.json 67 | # make a wrong public.json by decrementing the first element by 1 68 | (value_0=$(jq '.[0]' public.json | tr -d '"') && value_0=$(echo "$value_0 - 1" | BC_LINE_LENGTH=100 bc) && jq --arg value_0 "$value_0" '.[0] = $value_0' public.json) > public_bad.json 69 | set +e 70 | package/bin/verifier testdata/verification_key.json public_bad.json proof.json 71 | exit_code=$? 72 | set -e 73 | [ $exit_code -ne 0 ] 74 | 75 | - name: upload Linux amd64 dev artifacts 76 | if: github.event_name != 'release' 77 | uses: actions/upload-artifact@v3 78 | with: 79 | name: rapidsnark-linux-amd64 80 | path: | 81 | package 82 | if-no-files-found: error 83 | 84 | - name: upload Android dev artifacts 85 | if: github.event_name != 'release' 86 | uses: actions/upload-artifact@v3 87 | with: 88 | name: rapidsnark-Android 89 | path: | 90 | package_android 91 | if-no-files-found: error 92 | 93 | - name: upload Android x86_64 dev artifacts 94 | if: github.event_name != 'release' 95 | uses: actions/upload-artifact@v3 96 | with: 97 | name: rapidsnark-Android-x86_64 98 | path: | 99 | package_android_x86_64 100 | if-no-files-found: error 101 | 102 | - name: upload Android ARM64 release artifacts 103 | if: github.event_name == 'release' 104 | env: 105 | GH_TOKEN: ${{ github.token }} 106 | run: | 107 | set -x 108 | mkdir -p rapidsnark-android-arm64-${{ github.ref_name }} 109 | cp -r package_android/* rapidsnark-android-arm64-${{ github.ref_name }}/ 110 | zip -r rapidsnark-android-arm64-${{ github.ref_name }}.zip rapidsnark-android-arm64-${{ github.ref_name }} 111 | gh release upload ${{ github.event.release.tag_name }} rapidsnark-android-arm64-${{ github.ref_name }}.zip 112 | 113 | - name: upload Android x86_64 release artifacts 114 | if: github.event_name == 'release' 115 | env: 116 | GH_TOKEN: ${{ github.token }} 117 | run: | 118 | set -x 119 | mkdir -p rapidsnark-android-x86_64-${{ github.ref_name }} 120 | cp -r package_android_x86_64/* rapidsnark-android-x86_64-${{ github.ref_name }}/ 121 | zip -r rapidsnark-android-x86_64-${{ github.ref_name }}.zip rapidsnark-android-x86_64-${{ github.ref_name }} 122 | gh release upload ${{ github.event.release.tag_name }} rapidsnark-android-x86_64-${{ github.ref_name }}.zip 123 | 124 | - name: upload Linux x86_64 release artifacts 125 | if: github.event_name == 'release' 126 | env: 127 | GH_TOKEN: ${{ github.token }} 128 | run: | 129 | set -x 130 | mkdir -p rapidsnark-linux-x86_64-${{ github.ref_name }} 131 | cp -r package/* rapidsnark-linux-x86_64-${{ github.ref_name }}/ 132 | zip -r rapidsnark-linux-x86_64-${{ github.ref_name }}.zip rapidsnark-linux-x86_64-${{ github.ref_name }} 133 | gh release upload ${{ github.event.release.tag_name }} rapidsnark-linux-x86_64-${{ github.ref_name }}.zip 134 | 135 | build-apple-arm64: 136 | runs-on: macos-13-xlarge 137 | steps: 138 | - uses: actions/checkout@v4 139 | with: 140 | submodules: "recursive" 141 | 142 | - name: Cache gmp build 143 | uses: actions/cache@v3 144 | with: 145 | path: | 146 | depends/gmp 147 | depends/gmp-6.2.1.tar.xz 148 | key: ${{ runner.os }}-gmp-arm64-${{ hashFiles('build_gmp.sh') }} 149 | 150 | - name: build 151 | run: | 152 | if [[ ! -d "depends/gmp/package_ios_arm64" ]]; then ./build_gmp.sh ios; fi 153 | if [[ ! -d "depends/gmp/package_iphone_simulator" ]]; then ./build_gmp.sh ios_simulator; fi 154 | if [[ ! -d "depends/gmp/package_macos_arm64" ]]; then ./build_gmp.sh macos_arm64; fi 155 | 156 | mkdir -p build_prover_ios && cd build_prover_ios 157 | cmake .. -GXcode -DTARGET_PLATFORM=IOS -DCMAKE_INSTALL_PREFIX=../package_ios 158 | xcodebuild -destination 'generic/platform=iOS' -scheme rapidsnarkStatic -project rapidsnark.xcodeproj -configuration Release 159 | cp ../depends/gmp/package_ios_arm64/lib/libgmp.a src/Release-iphoneos 160 | cd ../ 161 | 162 | mkdir -p build_prover_ios_simulator && cd build_prover_ios_simulator 163 | cmake .. -GXcode -DTARGET_PLATFORM=IOS -DCMAKE_INSTALL_PREFIX=../package_ios_simulator -DUSE_ASM=NO 164 | xcodebuild -destination 'generic/platform=iOS Simulator' -scheme rapidsnarkStatic -project rapidsnark.xcodeproj 165 | cp ../depends/gmp/package_iphone_simulator/lib/libgmp.a src/Debug-iphonesimulator 166 | cd ../ 167 | 168 | mkdir -p build_prover_macos_arm64 && cd build_prover_macos_arm64 169 | cmake .. -DTARGET_PLATFORM=macos_arm64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_macos_arm64 170 | make -j4 && make install 171 | ctest --rerun-failed --output-on-failure 172 | 173 | - name: test rapidsnark 174 | run: | 175 | set -x 176 | set -e 177 | package_macos_arm64/bin/prover testdata/circuit_final.zkey testdata/witness.wtns proof.json public.json 178 | package_macos_arm64/bin/verifier testdata/verification_key.json public.json proof.json 179 | # make a wrong public.json by decrementing the first element by 1 180 | (value_0=$(jq '.[0]' public.json | tr -d '"') && value_0=$(echo "$value_0 - 1" | BC_LINE_LENGTH=100 bc) && jq --arg value_0 "$value_0" '.[0] = $value_0' public.json) > public_bad.json 181 | set +e 182 | package_macos_arm64/bin/verifier testdata/verification_key.json public_bad.json proof.json 183 | exit_code=$? 184 | set -e 185 | [ $exit_code -ne 0 ] 186 | 187 | - name: upload macOS arm64 dev artifacts 188 | if: github.event_name != 'release' 189 | uses: actions/upload-artifact@v3 190 | with: 191 | name: rapidsnark-macOS-arm64 192 | path: | 193 | package_macos_arm64 194 | if-no-files-found: error 195 | 196 | - name: upload iOS dev artifacts 197 | if: github.event_name != 'release' 198 | uses: actions/upload-artifact@v3 199 | with: 200 | name: rapidsnark-iOS 201 | path: | 202 | build_prover_ios/src/Release-iphoneos 203 | if-no-files-found: error 204 | 205 | - name: upload iOS Simulator dev artifacts 206 | if: github.event_name != 'release' 207 | uses: actions/upload-artifact@v3 208 | with: 209 | name: rapidsnark-iOS-Simulator 210 | path: | 211 | build_prover_ios_simulator/src/Debug-iphonesimulator 212 | if-no-files-found: error 213 | 214 | - name: upload iOS release artifacts 215 | if: github.event_name == 'release' 216 | env: 217 | GH_TOKEN: ${{ github.token }} 218 | run: | 219 | set -x 220 | mkdir -p rapidsnark-iOS-${{ github.ref_name }} 221 | cp -r build_prover_ios/src/Release-iphoneos/* rapidsnark-iOS-${{ github.ref_name }}/ 222 | zip -r rapidsnark-iOS-${{ github.ref_name }}.zip rapidsnark-iOS-${{ github.ref_name }} 223 | gh release upload ${{ github.event.release.tag_name }} rapidsnark-iOS-${{ github.ref_name }}.zip 224 | 225 | - name: upload iOS Simulator release artifacts 226 | if: github.event_name == 'release' 227 | env: 228 | GH_TOKEN: ${{ github.token }} 229 | run: | 230 | set -x 231 | mkdir -p rapidsnark-iOS-Simulator-${{ github.ref_name }} 232 | cp -r build_prover_ios_simulator/src/Debug-iphonesimulator/* rapidsnark-iOS-Simulator-${{ github.ref_name }}/ 233 | zip -r rapidsnark-iOS-Simulator-${{ github.ref_name }}.zip rapidsnark-iOS-Simulator-${{ github.ref_name }} 234 | gh release upload ${{ github.event.release.tag_name }} rapidsnark-iOS-Simulator-${{ github.ref_name }}.zip 235 | 236 | - name: upload macOS arm64 release artifacts 237 | if: github.event_name == 'release' 238 | env: 239 | GH_TOKEN: ${{ github.token }} 240 | run: | 241 | set -x 242 | mkdir -p rapidsnark-macOS-arm64-${{ github.ref_name }} 243 | cp -r package_macos_arm64/* rapidsnark-macOS-arm64-${{ github.ref_name }}/ 244 | zip -r rapidsnark-macOS-arm64-${{ github.ref_name }}.zip rapidsnark-macOS-arm64-${{ github.ref_name }} 245 | gh release upload ${{ github.event.release.tag_name }} rapidsnark-macOS-arm64-${{ github.ref_name }}.zip 246 | 247 | build-apple-x86_64: 248 | runs-on: macos-13 249 | steps: 250 | - uses: actions/checkout@v4 251 | with: 252 | submodules: "recursive" 253 | 254 | - name: Cache gmp build 255 | uses: actions/cache@v3 256 | with: 257 | path: | 258 | depends/gmp 259 | depends/gmp-6.2.1.tar.xz 260 | key: ${{ runner.os }}-gmp-x86_64-${{ hashFiles('build_gmp.sh') }}-2 261 | 262 | - name: install dependencies 263 | run: | 264 | brew install nasm 265 | 266 | - name: build 267 | run: | 268 | if [[ ! -d "depends/gmp/package_macos_x86_64" ]]; then ./build_gmp.sh macos_x86_64; fi 269 | 270 | mkdir -p build_prover_macos_x86_64 && cd build_prover_macos_x86_64 271 | cmake .. -DTARGET_PLATFORM=macos_x86_64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_macos_x86_64 272 | make -j4 && make install 273 | ctest --rerun-failed --output-on-failure 274 | 275 | - name: test rapidsnark 276 | run: | 277 | set -x 278 | set -e 279 | package_macos_x86_64/bin/prover testdata/circuit_final.zkey testdata/witness.wtns proof.json public.json 280 | package_macos_x86_64/bin/verifier testdata/verification_key.json public.json proof.json 281 | # make a wrong public.json by decrementing the first element by 1 282 | (value_0=$(jq '.[0]' public.json | tr -d '"') && value_0=$(echo "$value_0 - 1" | BC_LINE_LENGTH=100 bc) && jq --arg value_0 "$value_0" '.[0] = $value_0' public.json) > public_bad.json 283 | set +e 284 | package_macos_x86_64/bin/verifier testdata/verification_key.json public_bad.json proof.json 285 | exit_code=$? 286 | set -e 287 | [ $exit_code -ne 0 ] 288 | 289 | - name: upload macOS x86_64 dev artifacts 290 | if: github.event_name != 'release' 291 | uses: actions/upload-artifact@v3 292 | with: 293 | name: rapidsnark-macOS-x86_64 294 | path: | 295 | package_macos_x86_64 296 | if-no-files-found: error 297 | 298 | - name: upload macOS x86_64 release artifacts 299 | if: github.event_name == 'release' 300 | env: 301 | GH_TOKEN: ${{ github.token }} 302 | run: | 303 | set -x 304 | mkdir -p rapidsnark-macOS-x86_64-${{ github.ref_name }} 305 | cp -r package_macos_x86_64/* rapidsnark-macOS-x86_64-${{ github.ref_name }}/ 306 | zip -r rapidsnark-macOS-x86_64-${{ github.ref_name }}.zip rapidsnark-macOS-x86_64-${{ github.ref_name }} 307 | gh release upload ${{ github.event.release.tag_name }} rapidsnark-macOS-x86_64-${{ github.ref_name }}.zip 308 | -------------------------------------------------------------------------------- /.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 | [submodule "depends/icicle"] 15 | path = depends/icicle 16 | url = https://github.com/ingonyama-zk/icicle 17 | branch = main 18 | -------------------------------------------------------------------------------- /.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.5) 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 CUDA CXX C ASM) 9 | 10 | set(CMAKE_CXX_STANDARD 17) 11 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 12 | 13 | set(CMAKE_CUDA_STANDARD 17) 14 | set(CMAKE_CUDA_STANDARD_REQUIRED ON) 15 | 16 | message("USE_ASM=" ${USE_ASM}) 17 | message("USE_OPENMP=" ${USE_OPENMP}) 18 | message("CMAKE_CROSSCOMPILING=" ${CMAKE_CROSSCOMPILING}) 19 | 20 | message("GMP_PREFIX=" ${GMP_PREFIX}) 21 | message("GMP_INCLUDE_DIR=" ${GMP_INCLUDE_DIR}) 22 | message("GMP_LIB_DIR=" ${GMP_LIB_DIR}) 23 | 24 | if (NOT EXISTS ${GMP_INCLUDE_FILE_FULLPATH}) 25 | message("WARNING: ${GMP_INCLUDE_FILE_FULLPATH} is not found and so system ${GMP_INCLUDE_FILE} is used.") 26 | endif() 27 | 28 | if (NOT EXISTS ${GMP_LIB_FILE_FULLPATH}) 29 | message("WARNING: ${GMP_LIB_FILE_FULLPATH} is not found and so system ${GMP_LIB_FILE} is used.") 30 | set(GMP_LIB gmp) 31 | endif() 32 | 33 | 34 | include_directories(BEFORE ${GMP_INCLUDE_DIR}) 35 | 36 | 37 | if(USE_OPENMP) 38 | find_package(OpenMP) 39 | 40 | if(OpenMP_CXX_FOUND) 41 | if(TARGET_PLATFORM MATCHES "android") 42 | message("OpenMP is used") 43 | 44 | elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") 45 | message("OpenMP is used") 46 | 47 | else() 48 | set(OpenMP_CXX_FOUND FALSE) 49 | message("OpenMP is not used") 50 | 51 | endif() 52 | endif() 53 | endif() 54 | 55 | 56 | add_subdirectory(src) 57 | 58 | 59 | install(TARGETS icicle_msm_test icicle_ntt_test prover_cuda prover verifier rapidsnark rapidsnarkStatic rapidsnarkStaticFrFq test_prover fr fq 60 | RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin 61 | BUNDLE DESTINATION ${CMAKE_INSTALL_PREFIX}/app 62 | LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) 63 | 64 | install(FILES "${GMP_LIB_DIR}/${GMP_LIB_FILE}" 65 | DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) 66 | 67 | install(FILES src/prover.h src/verifier.h 68 | DESTINATION ${CMAKE_INSTALL_PREFIX}/include) 69 | 70 | enable_testing() 71 | -------------------------------------------------------------------------------- /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 | android: 10 | rm -rf build_prover_android && mkdir build_prover_android && cd build_prover_android && \ 11 | cmake .. -DTARGET_PLATFORM=ANDROID -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_android && \ 12 | make -j$(nproc) -vvv && make install 13 | 14 | android_x86_64: 15 | rm -rf build_prover_android_x86_64 && mkdir build_prover_android_x86_64 && cd build_prover_android_x86_64 && \ 16 | cmake .. -DTARGET_PLATFORM=ANDROID_x86_64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_android_x86_64 && \ 17 | make -j$(nproc) -vvv && make install 18 | 19 | ios: 20 | rm -rf build_prover_ios && mkdir build_prover_ios && cd build_prover_ios && \ 21 | cmake .. -GXcode -DTARGET_PLATFORM=IOS -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_ios && \ 22 | echo "" && echo "Now open Xcode and compile the generated project" && echo "" 23 | 24 | clean: 25 | rm -rf build_prover build_prover_android build_prover_android_x86_64 build_prover_ios package package_android \ 26 | package_android_x86_64 package_ios depends/gmp/package depends/gmp/package_android_arm64 \ 27 | depends/gmp/package_android_x86_64 depends/gmp/package_ios_arm64 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rapidsnark-gpu 2 | 3 | This is a CUDA-accelerated version of [rapidsnark](https://github.com/iden3/rapidsnark.git). 4 | 5 | We provide a prover_cuda program that uses Ingonyama's [ICICLE](https://github.com/ingonyama-zk/icicle.git) GPU library for NTT/MSM to build proof, current only supporting [standalone mode](https://github.com/iden3/rapidsnark?tab=readme-ov-file#compile-prover-for-x86_64-host-machine).This accelerated implementation has notably reduced the building proof's time from 41.757 seconds to 8.443 seconds. 6 | 7 | # Prerequistes 8 | 9 | - CUDA Toolkit version, CMake version and GCC version etc. (please see [ICICLE](https://github.com/ingonyama-zk/icicle?tab=readme-ov-file#prerequisites)) 10 | - Ubuntu 22.04 11 | - x86_64 host machine 12 | 13 | # Dependencies 14 | 15 | ```bash 16 | sudo apt-get install build-essential libgmp-dev libsodium-dev nasm curl m4 17 | ``` 18 | 19 | # Compile prover_cuda 20 | 21 | ```bash 22 | git submodule init 23 | git submodule update 24 | ./build_gmp.sh host 25 | mkdir build_prover && cd build_prover 26 | cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package 27 | make -j$(nproc) && make install 28 | ``` 29 | 30 | # Building proof 31 | 32 | You can replace rapidsnark command: 33 | 34 | ```bash 35 | ./package/bin/prover 36 | ``` 37 | 38 | by this one 39 | 40 | ```bash 41 | ./package/bin/prover_cuda 42 | ``` 43 | 44 | # Results 45 | 46 | Test machine: 47 | GPU — NVIDIA GeForce RTX 4090 24GB 48 | CPU — 2\* AMD EPYC 7763 64-Core Processor 49 | RAM - 256GB 50 | 51 | CPU version: 52 | 53 | ``` 54 | init and set str for altBbn128r: 0 ms 55 | get zkey,zkeyHeader,wtns,wtnsHeader: 0 ms 56 | make prover: 64 ms 57 | get wtnsData: 0 ms 58 | Multiexp A: 1816 ms 59 | Multiexp B1: 2020 ms 60 | Multiexp B2: 2520 ms 61 | Multiexp C: 2775 ms 62 | Initializing a b c A: 59 ms 63 | Processing coefs: 593 ms 64 | Calculating c: 49 ms 65 | Initializing fft: 0 ms 66 | iFFT A: 18158 ms 67 | a After ifft: 0 ms 68 | Shift A: 46 ms 69 | a After shift: 0 ms 70 | FFT A: 3188 ms 71 | a After fft: 0 ms 72 | iFFT B: 1805 ms 73 | b After ifft: 0 ms 74 | Shift B: 45 ms 75 | b After shift: 0 ms 76 | FFT B: 750 ms 77 | b After fft: 0 ms 78 | iFFT C: 971 ms 79 | c After ifft: 0 ms 80 | Shift C: 49 ms 81 | c After shift: 0 ms 82 | FFT C: 779 ms 83 | c After fft: 0 ms 84 | Start ABC: 48 ms 85 | abc: 0 ms 86 | Multiexp H: 4720 ms 87 | generate proof: 40708 ms 88 | write proof to file: 0 ms 89 | write public to file: 0 ms 90 | prover total: 41757 ms 91 | ``` 92 | 93 | GPU version: 94 | 95 | ``` 96 | init and set str for altBbn128r: 0 ms 97 | get zkey,zkeyHeader,wtns,wtnsHeader: 0 ms 98 | make prover: 65 ms 99 | get wtnsData: 0 ms 100 | get MSM config: 0 ms 101 | Multiexp A: 848 ms 102 | Multiexp B1: 679 ms 103 | Multiexp B2: 1080 ms 104 | Multiexp C: 683 ms 105 | Initializing a b c A: 75 ms 106 | Processing coefs: 618 ms 107 | Calculating c: 38 ms 108 | Initializing fft: 148 ms 109 | iFFT A: 291 ms 110 | a After ifft: 0 ms 111 | Shift A: 164 ms 112 | a After shift: 0 ms 113 | FFT A: 294 ms 114 | a After fft: 0 ms 115 | iFFT B: 272 ms 116 | b After ifft: 0 ms 117 | Shift B: 33 ms 118 | b After shift: 0 ms 119 | FFT B: 308 ms 120 | b After fft: 0 ms 121 | iFFT C: 255 ms 122 | c After ifft: 0 ms 123 | Shift C: 28 ms 124 | c After shift: 0 ms 125 | FFT C: 278 ms 126 | c After fft: 0 ms 127 | Start ABC: 46 ms 128 | abc: 0 ms 129 | Multiexp H: 929 ms 130 | generate proof: 7362 ms 131 | write proof to file: 0 ms 132 | write public to file: 0 ms 133 | prover cuda total: 8443 ms 134 | ``` 135 | 136 | # Note 137 | 138 | This project has been tested only under the following configurations: 139 | 140 | - Ubuntu 22.04 141 | - Kernel version 6.5.0-25-generic 142 | - CUDA 12.3 143 | - GCC/G++ 12.3.0 144 | - GPU — NVIDIA GeForce RTX 4090 24GB 145 | - CPU — 2\* AMD EPYC 7763 64-Core Processor 146 | -------------------------------------------------------------------------------- /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 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 | export TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64 132 | 133 | export TARGET=aarch64-linux-android 134 | export API=21 135 | 136 | export AR=$TOOLCHAIN/bin/llvm-ar 137 | export CC=$TOOLCHAIN/bin/$TARGET$API-clang 138 | export AS=$CC 139 | export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++ 140 | export LD=$TOOLCHAIN/bin/ld 141 | export RANLIB=$TOOLCHAIN/bin/llvm-ranlib 142 | export STRIP=$TOOLCHAIN/bin/llvm-strip 143 | 144 | echo "$TOOLCHAIN" 145 | echo "$TARGET" 146 | 147 | rm -rf "$BUILD_DIR" 148 | mkdir "$BUILD_DIR" 149 | cd "$BUILD_DIR" 150 | 151 | ../configure --host $TARGET --prefix="$PACKAGE_DIR" --with-pic --disable-fft && 152 | make -j${NPROC} && 153 | make install 154 | 155 | cd .. 156 | } 157 | 158 | build_android_x86_64() 159 | { 160 | PACKAGE_DIR="$GMP_DIR/package_android_x86_64" 161 | BUILD_DIR=build_android_x86_64 162 | 163 | if [ -d "$PACKAGE_DIR" ]; then 164 | echo "Android package is built already. See $PACKAGE_DIR" 165 | return 1 166 | fi 167 | 168 | if [ -z "$ANDROID_NDK" ]; then 169 | 170 | echo "ERROR: ANDROID_NDK environment variable is not set." 171 | echo " It must be an absolute path to the root directory of Android NDK." 172 | echo " For instance /home/test/Android/Sdk/ndk/23.1.7779620" 173 | return 1 174 | fi 175 | 176 | export TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64 177 | 178 | export TARGET=x86_64-linux-android 179 | export API=21 180 | 181 | export AR=$TOOLCHAIN/bin/llvm-ar 182 | export CC=$TOOLCHAIN/bin/$TARGET$API-clang 183 | export AS=$CC 184 | export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++ 185 | export LD=$TOOLCHAIN/bin/ld 186 | export RANLIB=$TOOLCHAIN/bin/llvm-ranlib 187 | export STRIP=$TOOLCHAIN/bin/llvm-strip 188 | 189 | echo "$TOOLCHAIN" 190 | echo $TARGET 191 | 192 | rm -rf "$BUILD_DIR" 193 | mkdir "$BUILD_DIR" 194 | cd "$BUILD_DIR" 195 | 196 | ../configure --host $TARGET --prefix="$PACKAGE_DIR" --with-pic --disable-fft && 197 | make -j${NPROC} && 198 | make install 199 | 200 | cd .. 201 | } 202 | 203 | build_ios() 204 | { 205 | PACKAGE_DIR="$GMP_DIR/package_ios_arm64" 206 | BUILD_DIR=build_ios_arm64 207 | 208 | if [ -d "$PACKAGE_DIR" ]; then 209 | echo "iOS package is built already. See $PACKAGE_DIR" 210 | return 1 211 | fi 212 | 213 | export SDK="iphoneos" 214 | export TARGET=arm64-apple-darwin 215 | export MIN_IOS_VERSION=8.0 216 | 217 | export ARCH_FLAGS="-arch arm64 -arch arm64e" 218 | export OPT_FLAGS="-O3 -g3 -fembed-bitcode" 219 | HOST_FLAGS="${ARCH_FLAGS} -miphoneos-version-min=${MIN_IOS_VERSION} -isysroot $(xcrun --sdk ${SDK} --show-sdk-path)" 220 | 221 | CC=$(xcrun --find --sdk "${SDK}" clang) 222 | export CC 223 | CXX=$(xcrun --find --sdk "${SDK}" clang++) 224 | export CXX 225 | CPP=$(xcrun --find --sdk "${SDK}" cpp) 226 | export CPP 227 | export CFLAGS="${HOST_FLAGS} ${OPT_FLAGS}" 228 | export CXXFLAGS="${HOST_FLAGS} ${OPT_FLAGS}" 229 | export LDFLAGS="${HOST_FLAGS}" 230 | 231 | echo $TARGET 232 | 233 | rm -rf "$BUILD_DIR" 234 | mkdir "$BUILD_DIR" 235 | cd "$BUILD_DIR" 236 | 237 | ../configure --host $TARGET --prefix="$PACKAGE_DIR" --with-pic --disable-fft --disable-assembly && 238 | make -j${NPROC} && 239 | make install 240 | 241 | cd .. 242 | } 243 | 244 | build_ios_simulator() 245 | { 246 | libs=() 247 | for ARCH in "arm64" "x86_64"; do 248 | case "$ARCH" in 249 | "arm64" ) 250 | echo "Building for iPhone Simulator arm64" 251 | ARCH_FLAGS="-arch arm64 -arch arm64e" 252 | ;; 253 | "x86_64" ) 254 | echo "Building for iPhone Simulator x86_64" 255 | ARCH_FLAGS="-arch x86_64" 256 | ;; 257 | * ) 258 | echo "Incorrect iPhone Simulator arch" 259 | exit 1 260 | esac 261 | 262 | BUILD_DIR="build_iphone_simulator_${ARCH}" 263 | PACKAGE_DIR="$GMP_DIR/package_iphone_simulator_${ARCH}" 264 | libs+=("${PACKAGE_DIR}/lib/libgmp.a") 265 | 266 | if [ -d "$PACKAGE_DIR" ]; then 267 | echo "iPhone Simulator ${ARCH} package is built already. See $PACKAGE_DIR. Skip building this ARCH." 268 | continue 269 | fi 270 | 271 | rm -rf "$BUILD_DIR" 272 | mkdir "$BUILD_DIR" 273 | cd "$BUILD_DIR" 274 | 275 | ../configure --prefix="${PACKAGE_DIR}" \ 276 | CC="$(xcrun --sdk iphonesimulator --find clang)" \ 277 | CFLAGS="-O3 -isysroot $(xcrun --sdk iphonesimulator --show-sdk-path) ${ARCH_FLAGS} -fvisibility=hidden -mios-simulator-version-min=8.0" \ 278 | LDFLAGS="" \ 279 | --host ${ARCH}-apple-darwin --disable-assembly --enable-static --disable-shared --with-pic && 280 | make -j${NPROC} && 281 | make install 282 | 283 | cd .. 284 | done 285 | 286 | mkdir -p "${GMP_DIR}/package_iphone_simulator/lib" 287 | lipo "${libs[@]}" -create -output "${GMP_DIR}/package_iphone_simulator/lib/libgmp.a" 288 | echo "Wrote universal fat library for iPhone Simulator arm64/x86_64 to ${GMP_DIR}/package_iphone_simulator/lib/libgmp.a" 289 | } 290 | 291 | build_macos_arch() 292 | { 293 | ARCH="$1" 294 | case "$ARCH" in 295 | "arm64" ) 296 | ARCH_FLAGS="-arch arm64 -arch arm64e" 297 | ;; 298 | "x86_64" ) 299 | ARCH_FLAGS="-arch x86_64" 300 | ;; 301 | * ) 302 | echo "Incorrect arch" 303 | exit 1 304 | esac 305 | 306 | BUILD_DIR="build_macos_${ARCH}" 307 | PACKAGE_DIR="$GMP_DIR/package_macos_${ARCH}" 308 | if [ -d "$PACKAGE_DIR" ]; then 309 | echo "macOS ${ARCH} package is built already. See $PACKAGE_DIR. Skip building this ARCH." 310 | return 311 | fi 312 | rm -rf "$BUILD_DIR" 313 | mkdir "$BUILD_DIR" 314 | cd "$BUILD_DIR" 315 | ../configure --prefix="${PACKAGE_DIR}" \ 316 | CC="$(xcrun --sdk macosx --find clang)" \ 317 | CFLAGS="-O3 -isysroot $(xcrun --sdk macosx --show-sdk-path) ${ARCH_FLAGS} -fvisibility=hidden -mmacos-version-min=14.0" \ 318 | LDFLAGS="" \ 319 | --host "${ARCH}-apple-darwin" --disable-assembly --enable-static --disable-shared --with-pic && 320 | make -j${NPROC} && 321 | make install 322 | cd .. 323 | } 324 | 325 | build_macos_fat() 326 | { 327 | echo "Building for macOS arm64" 328 | build_macos_arch "arm64" 329 | echo "Building for macOS x86_64" 330 | build_macos_arch "x86_64" 331 | 332 | gmp_lib_arm64="$GMP_DIR/package_macos_arm64/lib/libgmp.a" 333 | gmp_lib_x86_64="$GMP_DIR/package_macos_x86_64/lib/libgmp.a" 334 | gmp_lib_fat="$GMP_DIR/package_macos/lib/libgmp.a" 335 | 336 | mkdir -p "${GMP_DIR}/package_macos/lib" 337 | lipo "${gmp_lib_arm64}" "${gmp_lib_x86_64}" -create -output "${gmp_lib_fat}" 338 | mkdir -p "${GMP_DIR}/package_macos/include" 339 | cp "${GMP_DIR}/package_macos_arm64/include/gmp.h" "${GMP_DIR}/package_macos/include/" 340 | echo "Wrote universal fat library for macOS arm64/x86_64 to ${GMP_DIR}/package_macos/lib/libgmp.a" 341 | } 342 | 343 | if [ $# -ne 1 ]; then 344 | usage 345 | fi 346 | 347 | TARGET_PLATFORM=$(echo "$1" | tr "[:upper:]" "[:lower:]") 348 | 349 | cd depends 350 | 351 | get_gmp 352 | 353 | cd gmp 354 | 355 | GMP_DIR=$PWD 356 | 357 | case "$TARGET_PLATFORM" in 358 | 359 | "ios" ) 360 | echo "Building for ios" 361 | build_ios 362 | ;; 363 | 364 | "ios_simulator" ) 365 | echo "Building for iPhone Simulator" 366 | build_ios_simulator 367 | ;; 368 | 369 | "macos" ) 370 | echo "Building fat library for macOS" 371 | build_macos_fat 372 | ;; 373 | 374 | "macos_arm64" ) 375 | echo "Building library for macOS arm64" 376 | build_macos_arch "arm64" 377 | ;; 378 | 379 | "macos_x86_64" ) 380 | echo "Building library for macOS x86_64" 381 | build_macos_arch "x86_64" 382 | ;; 383 | 384 | "android" ) 385 | echo "Building for android" 386 | build_android 387 | ;; 388 | 389 | "android_x86_64" ) 390 | echo "Building for android x86_64" 391 | build_android_x86_64 392 | ;; 393 | 394 | "host" ) 395 | echo "Building for this host" 396 | build_host 397 | ;; 398 | 399 | "host_noasm" ) 400 | echo "Building for this host without asm optimizations (e.g. needed for macOS)" 401 | build_host_noasm 402 | ;; 403 | 404 | "aarch64" ) 405 | echo "Building for linux aarch64" 406 | build_aarch64 407 | ;; 408 | 409 | * ) 410 | usage 411 | 412 | esac 413 | -------------------------------------------------------------------------------- /cmake/platform.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 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 | else() 44 | set(CMAKE_OSX_ARCHITECTURES arm64) 45 | set(GMP_PREFIX ${GMP_ROOT}/package_ios_arm64) 46 | set(ARCH arm64) 47 | endif() 48 | 49 | elseif(TARGET_PLATFORM MATCHES "aarch64") 50 | 51 | set(GMP_PREFIX ${GMP_ROOT}/package_aarch64) 52 | set(ARCH arm64) 53 | 54 | elseif(TARGET_PLATFORM MATCHES "arm64_host") 55 | 56 | set(GMP_PREFIX ${GMP_ROOT}/package) 57 | set(ARCH arm64) 58 | 59 | elseif(TARGET_PLATFORM MATCHES "macos_x86_64") 60 | 61 | set(CMAKE_OSX_ARCHITECTURES x86_64) 62 | set(GMP_PREFIX ${GMP_ROOT}/package_macos_x86_64) 63 | set(ARCH x86_64) 64 | 65 | elseif(TARGET_PLATFORM MATCHES "macos_arm64") 66 | 67 | set(CMAKE_OSX_ARCHITECTURES arm64) 68 | set(GMP_PREFIX ${GMP_ROOT}/package_macos_arm64) 69 | set(ARCH arm64) 70 | 71 | else() 72 | 73 | set(GMP_PREFIX ${GMP_ROOT}/package) 74 | set(ARCH x86_64) 75 | 76 | endif() 77 | 78 | if (CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin") 79 | set(GMP_DEFINIONS -D_LONG_LONG_LIMB) 80 | endif() 81 | 82 | 83 | set(GMP_INCLUDE_DIR ${GMP_PREFIX}/include) 84 | set(GMP_INCLUDE_FILE gmp.h) 85 | set(GMP_LIB_DIR ${GMP_PREFIX}/lib) 86 | set(GMP_LIB_FILE libgmp.a) 87 | 88 | set(GMP_LIB_FILE_FULLPATH ${CMAKE_SOURCE_DIR}/${GMP_LIB_DIR}/${GMP_LIB_FILE}) 89 | set(GMP_INCLUDE_FILE_FULLPATH ${CMAKE_SOURCE_DIR}/${GMP_INCLUDE_DIR}/${GMP_INCLUDE_FILE}) 90 | 91 | set(GMP_LIB ${GMP_LIB_FILE_FULLPATH}) 92 | 93 | message("CMAKE_HOST_SYSTEM_NAME=" ${CMAKE_HOST_SYSTEM_NAME}) 94 | message("CMAKE_SYSTEM_NAME=" ${CMAKE_SYSTEM_NAME}) 95 | message("ARCH=" ${ARCH}) 96 | -------------------------------------------------------------------------------- /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(USE_ASM AND ARCH MATCHES "x86_64") 14 | 15 | if (CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin") 16 | set(NASM_FLAGS -fmacho64 --prefix _) 17 | else() 18 | set(NASM_FLAGS -felf64 -DPIC) 19 | endif() 20 | 21 | add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/build/fq_asm.o 22 | COMMAND nasm ${NASM_FLAGS} fq.asm -o fq_asm.o 23 | DEPENDS ${CMAKE_SOURCE_DIR}/build/fq.asm 24 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/build) 25 | 26 | add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/build/fr_asm.o 27 | COMMAND nasm ${NASM_FLAGS} fr.asm -o fr_asm.o 28 | DEPENDS ${CMAKE_SOURCE_DIR}/build/fr.asm 29 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/build) 30 | endif() 31 | 32 | set(FR_SOURCES 33 | ../build/fr.hpp 34 | ../build/fr.cpp 35 | ) 36 | 37 | if(USE_ASM) 38 | if(ARCH MATCHES "arm64") 39 | set(FR_SOURCES ${FR_SOURCES} ../build/fr_raw_arm64.s ../build/fr_raw_generic.cpp ../build/fr_generic.cpp) 40 | elseif(ARCH MATCHES "x86_64") 41 | set(FR_SOURCES ${FR_SOURCES} ../build/fr_asm.o) 42 | endif() 43 | else() 44 | set(FR_SOURCES ${FR_SOURCES} ../build/fr_generic.cpp ../build/fr_raw_generic.cpp) 45 | endif() 46 | 47 | add_library(fr STATIC ${FR_SOURCES}) 48 | set_target_properties(fr PROPERTIES POSITION_INDEPENDENT_CODE ON) 49 | 50 | link_libraries(fr) 51 | 52 | set(FQ_SOURCES 53 | ../build/fq.hpp 54 | ../build/fq.cpp 55 | ) 56 | 57 | if(USE_ASM) 58 | if(ARCH MATCHES "arm64") 59 | set(FQ_SOURCES ${FQ_SOURCES} ../build/fq_raw_arm64.s ../build/fq_raw_generic.cpp ../build/fq_generic.cpp) 60 | elseif(ARCH MATCHES "x86_64") 61 | set(FQ_SOURCES ${FQ_SOURCES} ../build/fq_asm.o) 62 | endif() 63 | else() 64 | set(FQ_SOURCES ${FQ_SOURCES} ../build/fq_raw_generic.cpp ../build/fq_generic.cpp) 65 | endif() 66 | 67 | add_library(fq STATIC ${FQ_SOURCES}) 68 | set_target_properties(fq PROPERTIES POSITION_INDEPENDENT_CODE ON) 69 | 70 | link_libraries(fq) 71 | 72 | 73 | if(OpenMP_CXX_FOUND) 74 | add_definitions(-DUSE_OPENMP) 75 | add_compile_options(${OpenMP_CXX_FLAGS}) 76 | endif() 77 | 78 | set(LIB_SOURCES 79 | binfile_utils.hpp 80 | binfile_utils.cpp 81 | zkey_utils.hpp 82 | zkey_utils.cpp 83 | wtns_utils.hpp 84 | wtns_utils.cpp 85 | logger.hpp 86 | logger.cpp 87 | fileloader.cpp 88 | fileloader.hpp 89 | prover.cpp 90 | prover.h 91 | verifier.cpp 92 | verifier.h 93 | ../depends/ffiasm/c/misc.cpp 94 | ../depends/ffiasm/c/naf.cpp 95 | ../depends/ffiasm/c/splitparstr.cpp 96 | ../depends/ffiasm/c/alt_bn128.cpp 97 | ) 98 | 99 | if(USE_LOGGER) 100 | set(LIB_SOURCES ${LIB_SOURCES} logger.cpp) 101 | add_definitions(-DUSE_LOGGER) 102 | endif() 103 | 104 | include_directories( 105 | ../src 106 | ../build 107 | ../depends/ffiasm/c 108 | ../depends/json/single_include) 109 | 110 | add_library(rapidsnarkStatic STATIC ${LIB_SOURCES}) 111 | set_target_properties(rapidsnarkStatic PROPERTIES OUTPUT_NAME rapidsnark) 112 | 113 | add_library(rapidsnarkStaticFrFq STATIC ${LIB_SOURCES} ${FQ_SOURCES} ${FR_SOURCES}) 114 | set_target_properties(rapidsnarkStaticFrFq PROPERTIES POSITION_INDEPENDENT_CODE ON) 115 | set_target_properties(rapidsnarkStaticFrFq PROPERTIES OUTPUT_NAME rapidsnark-fr-fq) 116 | 117 | add_executable(prover main_prover.cpp) 118 | target_link_libraries(prover rapidsnarkStatic) 119 | 120 | if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "12.2") 121 | message(STATUS "Using multi-threaded CUDA compilation.") 122 | set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --split-compile 0") 123 | else() 124 | message(STATUS "Can't use multi-threaded CUDA compilation.") 125 | endif() 126 | 127 | set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --expt-relaxed-constexpr") 128 | set(CMAKE_CUDA_FLAGS_RELEASE "") 129 | set(CMAKE_CUDA_FLAGS_DEBUG "${CMAKE_CUDA_FLAGS_DEBUG} -g -G -O0") 130 | 131 | if (${CMAKE_VERSION} VERSION_LESS "3.24.0") 132 | set(CMAKE_CUDA_ARCHITECTURES ${CUDA_ARCH}) 133 | else() 134 | set(CMAKE_CUDA_ARCHITECTURES native) # on 3.24+, on earlier it is ignored, and the target is not passed 135 | endif () 136 | 137 | add_executable(icicle_ntt_test main_icicle_ntt_test.cu) 138 | target_link_libraries(icicle_ntt_test rapidsnarkStatic) 139 | 140 | 141 | target_include_directories( 142 | icicle_ntt_test 143 | PUBLIC 144 | ../depends/icicle/icicle 145 | ) 146 | find_library(NVML_LIBRARY nvidia-ml PATHS /usr/local/cuda-12.3/targets/x86_64-linux/lib/stubs/ ) 147 | target_link_libraries(icicle_ntt_test ${NVML_LIBRARY}) 148 | set_target_properties(icicle_ntt_test PROPERTIES CUDA_SEPARABLE_COMPILATION ON) 149 | 150 | add_executable(prover_cuda main_prover_cuda.cu) 151 | target_link_libraries(prover_cuda rapidsnarkStatic) 152 | 153 | 154 | target_include_directories( 155 | prover_cuda 156 | PUBLIC 157 | ../depends/icicle/icicle 158 | ) 159 | # find_library(NVML_LIBRARY nvidia-ml PATHS /usr/local/cuda-12.3/targets/x86_64-linux/lib/stubs/ ) 160 | target_link_libraries(prover_cuda ${NVML_LIBRARY}) 161 | set_target_properties(prover_cuda PROPERTIES CUDA_SEPARABLE_COMPILATION ON) 162 | 163 | add_executable(icicle_msm_test main_icicle_msm_test.cu) 164 | target_link_libraries(icicle_msm_test rapidsnarkStatic) 165 | 166 | 167 | target_include_directories( 168 | icicle_msm_test 169 | PUBLIC 170 | ../depends/icicle/icicle 171 | ) 172 | # find_library(NVML_LIBRARY nvidia-ml PATHS /usr/local/cuda-12.3/targets/x86_64-linux/lib/stubs/ ) 173 | target_link_libraries(icicle_msm_test ${NVML_LIBRARY}) 174 | set_target_properties(icicle_msm_test PROPERTIES CUDA_SEPARABLE_COMPILATION ON) 175 | 176 | 177 | 178 | add_executable(verifier main_verifier.cpp) 179 | target_link_libraries(verifier rapidsnarkStatic) 180 | 181 | add_library(rapidsnark SHARED ${LIB_SOURCES}) 182 | 183 | if(USE_LOGGER OR NOT USE_OPENMP) 184 | target_link_libraries(prover pthread) 185 | target_link_libraries(icicle_ntt_test pthread) 186 | target_link_libraries(icicle_msm_test pthread) 187 | target_link_libraries(prover_cuda pthread) 188 | target_link_libraries(verifier pthread) 189 | endif() 190 | 191 | if(USE_SODIUM) 192 | target_link_libraries(prover sodium) 193 | target_link_libraries(icicle_ntt_test sodium) 194 | target_link_libraries(icicle_msm_test sodium) 195 | target_link_libraries(prover_cuda sodium) 196 | endif() 197 | 198 | 199 | enable_testing() 200 | add_executable(test_public_size test_public_size.c) 201 | target_link_libraries(test_public_size rapidsnarkStaticFrFq) 202 | add_test(NAME test_public_size COMMAND test_public_size circuit_final.zkey 86 203 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/testdata) 204 | 205 | if(OpenMP_CXX_FOUND) 206 | 207 | if(TARGET_PLATFORM MATCHES "android") 208 | target_link_libraries(prover -static-openmp -fopenmp) 209 | target_link_libraries(prover_cuda -static-openmp -fopenmp) 210 | target_link_libraries(icicle_ntt_test -static-openmp -fopenmp) 211 | target_link_libraries(icicle_msm_test -static-openmp -fopenmp) 212 | target_link_libraries(verifier -static-openmp -fopenmp) 213 | target_link_libraries(rapidsnark -static-openmp -fopenmp) 214 | 215 | elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") 216 | target_link_libraries(prover OpenMP::OpenMP_CXX) 217 | target_link_libraries(prover_cuda OpenMP::OpenMP_CXX) 218 | target_link_libraries(icicle_ntt_test OpenMP::OpenMP_CXX) 219 | target_link_libraries(icicle_msm_test OpenMP::OpenMP_CXX) 220 | target_link_libraries(verifier OpenMP::OpenMP_CXX) 221 | target_link_libraries(test_public_size OpenMP::OpenMP_CXX) 222 | endif() 223 | 224 | endif() 225 | 226 | 227 | add_executable(test_prover test_prover.cpp) 228 | -------------------------------------------------------------------------------- /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 | 17 | is_fd = true; 18 | struct stat sb; 19 | 20 | fd = open(fileName.c_str(), O_RDONLY); 21 | if (fd == -1) 22 | throw std::system_error(errno, std::generic_category(), "open"); 23 | 24 | 25 | if (fstat(fd, &sb) == -1) /* To obtain file size */ 26 | throw std::system_error(errno, std::generic_category(), "fstat"); 27 | 28 | size = sb.st_size; 29 | 30 | addr = mmap(nullptr, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 31 | if (addr == MAP_FAILED) { 32 | close(fd); 33 | throw std::system_error(errno, std::generic_category(), "mmap failed"); 34 | } 35 | madvise(addr, size, MADV_SEQUENTIAL); 36 | 37 | type.assign((const char *)addr, 4); 38 | pos = 4; 39 | 40 | if (type != _type) { 41 | munmap(addr, size); 42 | close(fd); 43 | throw std::invalid_argument("Invalid file type. It should be " + _type + " and it is " + type + " filename: " + fileName); 44 | } 45 | 46 | version = readU32LE(); 47 | if (version > maxVersion) { 48 | munmap(addr, size); 49 | close(fd); 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 | 56 | for (u_int32_t i=0; i())); 62 | } 63 | 64 | sections[sType].push_back(Section( (void *)((u_int64_t)addr + pos), sSize)); 65 | 66 | pos += sSize; 67 | } 68 | 69 | pos = 0; 70 | readingSection = nullptr; 71 | } 72 | 73 | 74 | BinFile::BinFile(const void *fileData, size_t fileSize, std::string _type, uint32_t maxVersion) { 75 | 76 | is_fd = false; 77 | fd = -1; 78 | 79 | size = fileSize; 80 | addr = malloc(size); 81 | memcpy(addr, fileData, size); 82 | 83 | type.assign((const char *)addr, 4); 84 | pos = 4; 85 | 86 | if (type != _type) { 87 | free(addr); 88 | throw std::invalid_argument("Invalid file type. It should be " + _type + " and it is " + type); 89 | } 90 | 91 | version = readU32LE(); 92 | if (version > maxVersion) { 93 | free(addr); 94 | throw std::invalid_argument("Invalid version. It should be <=" + std::to_string(maxVersion) + " and it is " + std::to_string(version)); 95 | } 96 | 97 | u_int32_t nSections = readU32LE(); 98 | 99 | 100 | for (u_int32_t i=0; i())); 106 | } 107 | 108 | sections[sType].push_back(Section( (void *)((u_int64_t)addr + pos), sSize)); 109 | 110 | pos += sSize; 111 | } 112 | 113 | pos = 0; 114 | readingSection = NULL; 115 | } 116 | 117 | BinFile::~BinFile() { 118 | if (is_fd) { 119 | munmap(addr, size); 120 | close(fd); 121 | } else { 122 | free(addr); 123 | } 124 | } 125 | 126 | void BinFile::startReadSection(u_int32_t sectionId, u_int32_t sectionPos) { 127 | 128 | if (sections.find(sectionId) == sections.end()) { 129 | throw std::range_error("Section does not exist: " + std::to_string(sectionId)); 130 | } 131 | 132 | if (sectionPos >= sections[sectionId].size()) { 133 | 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)); 134 | } 135 | 136 | if (readingSection != NULL) { 137 | throw std::range_error("Already reading a section"); 138 | } 139 | 140 | pos = (u_int64_t)(sections[sectionId][sectionPos].start) - (u_int64_t)addr; 141 | 142 | readingSection = §ions[sectionId][sectionPos]; 143 | } 144 | 145 | void BinFile::endReadSection(bool check) { 146 | if (check) { 147 | if ((u_int64_t)addr + pos - (u_int64_t)(readingSection->start) != readingSection->size) { 148 | throw std::range_error("Invalid section size"); 149 | } 150 | } 151 | readingSection = NULL; 152 | } 153 | 154 | void *BinFile::getSectionData(u_int32_t sectionId, u_int32_t sectionPos) { 155 | 156 | if (sections.find(sectionId) == sections.end()) { 157 | throw std::range_error("Section does not exist: " + std::to_string(sectionId)); 158 | } 159 | 160 | if (sectionPos >= sections[sectionId].size()) { 161 | 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)); 162 | } 163 | 164 | return sections[sectionId][sectionPos].start; 165 | } 166 | 167 | u_int64_t BinFile::getSectionSize(u_int32_t sectionId, u_int32_t sectionPos) { 168 | 169 | if (sections.find(sectionId) == sections.end()) { 170 | throw new std::range_error("Section does not exist: " + std::to_string(sectionId)); 171 | } 172 | 173 | if (sectionPos >= sections[sectionId].size()) { 174 | throw new 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)); 175 | } 176 | 177 | return sections[sectionId][sectionPos].size; 178 | } 179 | 180 | u_int32_t BinFile::readU32LE() { 181 | u_int32_t res = *((u_int32_t *)((u_int64_t)addr + pos)); 182 | pos += 4; 183 | return res; 184 | } 185 | 186 | u_int64_t BinFile::readU64LE() { 187 | u_int64_t res = *((u_int64_t *)((u_int64_t)addr + pos)); 188 | pos += 8; 189 | return res; 190 | } 191 | 192 | void *BinFile::read(u_int64_t len) { 193 | void *res = (void *)((u_int64_t)addr + pos); 194 | pos += len; 195 | return res; 196 | } 197 | 198 | std::unique_ptr openExisting(const std::string& filename, const std::string& type, uint32_t maxVersion) { 199 | return std::unique_ptr(new BinFile(filename, type, maxVersion)); 200 | } 201 | 202 | } // Namespace 203 | 204 | -------------------------------------------------------------------------------- /src/binfile_utils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BINFILE_UTILS_H 2 | #define BINFILE_UTILS_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace BinFileUtils { 9 | 10 | class BinFile { 11 | 12 | bool is_fd; 13 | int fd; 14 | 15 | 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 | 36 | public: 37 | 38 | BinFile(const void *fileData, size_t fileSize, std::string _type, uint32_t maxVersion); 39 | BinFile(const std::string& fileName, const std::string& _type, uint32_t maxVersion); 40 | BinFile(const BinFile&) = delete; 41 | BinFile& operator=(const BinFile&) = delete; 42 | ~BinFile(); 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(const std::string& fileName) 13 | { 14 | struct stat sb; 15 | 16 | fd = open(fileName.c_str(), O_RDONLY); 17 | if (fd == -1) 18 | throw std::system_error(errno, std::generic_category(), "open"); 19 | 20 | 21 | if (fstat(fd, &sb) == -1) { /* To obtain file size */ 22 | close(fd); 23 | throw std::system_error(errno, std::generic_category(), "fstat"); 24 | } 25 | 26 | size = sb.st_size; 27 | 28 | addr = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0); 29 | } 30 | 31 | FileLoader::~FileLoader() 32 | { 33 | munmap(addr, size); 34 | close(fd); 35 | } 36 | 37 | } // Namespace 38 | -------------------------------------------------------------------------------- /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(const std::string& fileName); 13 | ~FileLoader(); 14 | 15 | void* dataBuffer() { return addr; } 16 | size_t dataSize() const { return size; } 17 | 18 | std::string dataAsString() { return std::string((char*)addr, size); } 19 | 20 | private: 21 | void* addr; 22 | size_t size; 23 | int fd; 24 | }; 25 | 26 | } 27 | 28 | #endif // FILELOADER_HPP 29 | -------------------------------------------------------------------------------- /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 | protected: 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_icicle_msm_test.cu: -------------------------------------------------------------------------------- 1 | #include "groth16_cuda.cu" 2 | 3 | __uint128_t g_lehmer64_state = 0xAAAAAAAAAAAAAAAALL; 4 | 5 | // Fast random generator 6 | // https://lemire.me/blog/2019/03/19/the-fastest-conventional-random-number-generator-that-can-pass-big-crush/ 7 | 8 | uint64_t lehmer64() { 9 | g_lehmer64_state *= 0xda942042e4dd58b5LL; 10 | return g_lehmer64_state >> 64; 11 | } 12 | 13 | 14 | int main(int argc, char **argv){ 15 | std::cout << "--------test icicle's msm and rapidsnark's G1.multiMulByScalar-----------" << "\n"; 16 | START_TIMER(prover_cuda_timer); 17 | if (argc != 9) { 18 | std::cerr << "Invalid number of parameters:\n"; 19 | std::cerr << "Usage: icicle_msm_test \n"; 20 | return EXIT_FAILURE; 21 | } 22 | 23 | mpz_t altBbn128r; 24 | 25 | mpz_init(altBbn128r); 26 | mpz_set_str(altBbn128r, "21888242871839275222246405745257275088548364400416034343698204186575808495617", 10); 27 | 28 | try { 29 | std::string zkeyFilename = argv[1]; 30 | std::string wtnsFilename = argv[2]; 31 | 32 | int config_c = atoi(argv[3]); 33 | int bit_size = atoi(argv[4]); 34 | int large_bucket_factor = atoi(argv[5]); 35 | bool are_scalars_montgomery_form = atoi(argv[6])!=0?true:false; 36 | bool are_points_montgomery_form = atoi(argv[7])!=0?true:false; 37 | bool is_big_triangle = atoi(argv[8])!=0?true:false; 38 | std::cout << "config_c: " << config_c << "\n"; 39 | std::cout << "bit_size: " << bit_size << "\n"; 40 | std::cout << "large bucket factor: " << large_bucket_factor << "\n"; 41 | std::cout << "are_scalars_montgomery_form: " << are_scalars_montgomery_form << "\n"; 42 | std::cout << "are_points_montgomery_form: " << are_points_montgomery_form << "\n"; 43 | std::cout << "is_big_triangle: " << is_big_triangle << "\n"; 44 | 45 | 46 | auto zkey = BinFileUtils::openExisting(zkeyFilename, "zkey", 1); 47 | auto zkeyHeader = ZKeyUtils::loadHeader(zkey.get()); 48 | 49 | std::string proofStr; 50 | if (mpz_cmp(zkeyHeader->rPrime, altBbn128r) != 0) { 51 | throw std::invalid_argument( "zkey curve not supported" ); 52 | } 53 | 54 | auto wtns = BinFileUtils::openExisting(wtnsFilename, "wtns", 2); 55 | auto wtnsHeader = WtnsUtils::loadHeader(wtns.get()); 56 | 57 | if (mpz_cmp(wtnsHeader->prime, altBbn128r) != 0) { 58 | throw std::invalid_argument( "different wtns curve" ); 59 | } 60 | 61 | AltBn128::FrElement *wtnsData = (AltBn128::FrElement *)wtns->getSectionData(2); 62 | auto nVars = zkeyHeader->nVars; 63 | // pointsA = (Engine::G1PointAffine *)zkey->getSectionData(5); 64 | // pointsB2 = (Engine::G1PointAffine *)zkey->getSectionData(7); //G2 group 65 | // pointsC = (Engine::G1PointAffine *)zkey->getSectionData(8); 66 | // pointsH = (Engine::G1PointAffine *)zkey->getSectionData(9); 67 | auto pointsB1 = (Engine::G1PointAffine *)zkey->getSectionData(6); 68 | 69 | 70 | device_context::DeviceContext ctx = device_context::get_default_device_context(); 71 | msm::MSMConfig config = { 72 | ctx, // ctx 73 | 0, // points_size 74 | 1, // precompute_factor 75 | config_c, // c 76 | 0, // bitsize 77 | large_bucket_factor, // large_bucket_factor 78 | 1, // batch_size 79 | false, // are_scalars_on_device 80 | are_scalars_montgomery_form, // are_scalars_montgomery_form 81 | false, // are_points_on_device 82 | are_points_montgomery_form, // are_points_montgomery_form 83 | false, // are_results_on_device 84 | is_big_triangle, // is_big_triangle 85 | false, // is_async 86 | }; 87 | Engine::G1Point rapidsnark_res; 88 | Engine::G1Point icicle_res; 89 | 90 | START_TIMER(icicle_g1_msm_timer); 91 | bn254_icicle_cuda_g1_msm(icicle_res, pointsB1, (uint8_t*)wtnsData, nVars, config); 92 | std::cout <<"nVars: " << nVars << "\n"; 93 | END_TIMER(icicle_g1_msm_timer, "icicle g1 msm"); 94 | START_TIMER(rapidsnark_g1_msm_timer); 95 | auto sW = sizeof(wtnsData[0]); 96 | G1.multiMulByScalar(rapidsnark_res, pointsB1, (uint8_t*)wtnsData, sW, nVars); 97 | END_TIMER(rapidsnark_g1_msm_timer, "rapidsnark g1 msm"); 98 | std::cout << "icicle res:" << G1.toString(icicle_res, 10) << "\n"; 99 | std::cout << "rapidsnark res:" << G1.toString(rapidsnark_res, 10) << "\n"; 100 | 101 | //assert(G1.eq(rapidsnark_res, icicle_res)); 102 | std::cout << "compare res: " << G1.eq(rapidsnark_res, icicle_res) << "\n"; 103 | 104 | std::cout << "----------------------random scalars and pointsB1-------------------------------------------" << "\n"; 105 | uint8_t *scalars = new uint8_t[nVars *32]; 106 | // random scalars 107 | for (int i=0; i < nVars * 4; i++){ 108 | uint64_t res = lehmer64(); 109 | 110 | if(i % 4 == 3) { 111 | res &= 0x1fffffffffffffff; 112 | } 113 | *((uint64_t *)(scalars +i*8)) = res; 114 | } 115 | 116 | Engine::G1Point rapidsnark_res1; 117 | Engine::G1Point icicle_res1; 118 | START_TIMER(icicle_g1_msm_timer1); 119 | bn254_icicle_cuda_g1_msm(icicle_res1, pointsB1, (uint8_t*)scalars, nVars, config); 120 | END_TIMER(icicle_g1_msm_timer1, "icicle g1 msm"); 121 | START_TIMER(rapidsnark_g1_msm_timer1); 122 | G1.multiMulByScalar(rapidsnark_res1, pointsB1, (uint8_t*)scalars, sW, nVars); 123 | END_TIMER(rapidsnark_g1_msm_timer1, "rapidsnark g1 msm"); 124 | std::cout << "icicle res:" << G1.toString(icicle_res1, 10) << "\n"; 125 | std::cout << "rapidsnark res:" << G1.toString(rapidsnark_res1, 10) << "\n"; 126 | 127 | //assert(G1.eq(rapidsnark_res, icicle_res)); 128 | std::cout << "compare res: " << G1.eq(rapidsnark_res1, icicle_res1) << "\n"; 129 | 130 | 131 | std::cout << "------------------wtnsData and generate bases-----------------------------" << "\n"; 132 | 133 | Engine::G1PointAffine *bases = new Engine::G1PointAffine[nVars]; 134 | G1.copy(bases[0], G1.one()); 135 | G1.copy(bases[1], G1.one()); 136 | 137 | for (int i=2; iwhat() << '\n'; 178 | return EXIT_FAILURE; 179 | } catch (std::exception& e) { 180 | mpz_clear(altBbn128r); 181 | std::cerr << e.what() << '\n'; 182 | return EXIT_FAILURE; 183 | } 184 | 185 | mpz_clear(altBbn128r); 186 | END_TIMER(prover_cuda_timer, "prover cuda total"); 187 | 188 | exit(EXIT_SUCCESS); 189 | } -------------------------------------------------------------------------------- /src/main_icicle_ntt_test.cu: -------------------------------------------------------------------------------- 1 | #include "groth16_cuda.cu" 2 | 3 | 4 | int main(int argc, char **argv){ 5 | std::cout << "Hello ICICLE" <<"\n"; 6 | 7 | std::cout << "Hello CMAKE" << std::endl; 8 | u_int32_t log_ntt_size = 2; 9 | u_int32_t domainSize = 1 << log_ntt_size; 10 | FFT fft(domainSize); 11 | auto a = new AltBn128::Engine::FrElement[domainSize]; 12 | #pragma omp parallel for 13 | for (u_int32_t i = 0; i < domainSize; i++){ 14 | Fr.fromUI(a[i], i + 1); 15 | } 16 | // auto input = reinterpret_cast(a); 17 | 18 | auto ctx = device_context::get_default_device_context(); 19 | init_icicle_cuda_ntt_ctx(ctx, log_ntt_size); 20 | 21 | // const S basic_root = S::omega(log_ntt_size); 22 | // InitDomain(basic_root, ctx); 23 | 24 | NTTConfig config = DefaultNTTConfig(); 25 | config.ntt_algorithm = NttAlgorithm::MixedRadix; 26 | // config.ntt_algorithm = NttAlgorithm::Radix2; 27 | config.batch_size = 1; 28 | 29 | START_TIMER(MixedRadix); 30 | // cudaError_t err = NTT(input, domainSize, NTTDir::kForward, config, input); 31 | cudaError_t err = icicle_cuda_ntt( 32 | a, 33 | domainSize, 34 | config, 35 | NTTDir::kForward, 36 | ctx 37 | ); 38 | 39 | END_TIMER(MixedRadix, "MixedRadix NTT"); 40 | 41 | fft.printVector(&a[0], domainSize); 42 | delete [] a; 43 | 44 | return 0; 45 | } -------------------------------------------------------------------------------- /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 7 | #include 8 | 9 | #include 10 | #include "binfile_utils.hpp" 11 | #include "zkey_utils.hpp" 12 | #include "wtns_utils.hpp" 13 | #include "groth16.hpp" 14 | 15 | using json = nlohmann::json; 16 | 17 | #define handle_error(msg) \ 18 | do { perror(msg); exit(EXIT_FAILURE); } while (0) 19 | 20 | using FpMilliseconds = std::chrono::duration; 21 | #define START_TIMER(timer) auto timer##_start = std::chrono::high_resolution_clock::now(); 22 | #define END_TIMER(timer, msg) printf("%s: %.0f ms\n", msg, FpMilliseconds(std::chrono::high_resolution_clock::now() - timer##_start).count()); 23 | 24 | int main(int argc, char **argv) 25 | { 26 | START_TIMER(prover_timer); 27 | if (argc != 5) { 28 | std::cerr << "Invalid number of parameters:\n"; 29 | std::cerr << "Usage: prover \n"; 30 | return EXIT_FAILURE; 31 | } 32 | 33 | START_TIMER(altBbn128r_timer); 34 | mpz_t altBbn128r; 35 | 36 | mpz_init(altBbn128r); 37 | mpz_set_str(altBbn128r, "21888242871839275222246405745257275088548364400416034343698204186575808495617", 10); 38 | END_TIMER(altBbn128r_timer, "init and set str for altBbn128r"); 39 | 40 | try { 41 | START_TIMER(get_zkey_wtns_timer); 42 | std::string zkeyFilename = argv[1]; 43 | std::string wtnsFilename = argv[2]; 44 | std::string proofFilename = argv[3]; 45 | std::string publicFilename = argv[4]; 46 | 47 | auto zkey = BinFileUtils::openExisting(zkeyFilename, "zkey", 1); 48 | auto zkeyHeader = ZKeyUtils::loadHeader(zkey.get()); 49 | 50 | std::string proofStr; 51 | if (mpz_cmp(zkeyHeader->rPrime, altBbn128r) != 0) { 52 | throw std::invalid_argument( "zkey curve not supported" ); 53 | } 54 | 55 | auto wtns = BinFileUtils::openExisting(wtnsFilename, "wtns", 2); 56 | auto wtnsHeader = WtnsUtils::loadHeader(wtns.get()); 57 | 58 | if (mpz_cmp(wtnsHeader->prime, altBbn128r) != 0) { 59 | throw std::invalid_argument( "different wtns curve" ); 60 | } 61 | 62 | END_TIMER(get_zkey_wtns_timer, "get zkey,zkeyHeader,wtns,wtnsHeader"); 63 | 64 | START_TIMER(make_prover_timer); 65 | auto prover = Groth16::makeProver( 66 | zkeyHeader->nVars, 67 | zkeyHeader->nPublic, 68 | zkeyHeader->domainSize, 69 | zkeyHeader->nCoefs, 70 | zkeyHeader->vk_alpha1, 71 | zkeyHeader->vk_beta1, 72 | zkeyHeader->vk_beta2, 73 | zkeyHeader->vk_delta1, 74 | zkeyHeader->vk_delta2, 75 | zkey->getSectionData(4), // Coefs 76 | zkey->getSectionData(5), // pointsA 77 | zkey->getSectionData(6), // pointsB1 78 | zkey->getSectionData(7), // pointsB2 79 | zkey->getSectionData(8), // pointsC 80 | zkey->getSectionData(9) // pointsH1 81 | ); 82 | END_TIMER(make_prover_timer, "make prover"); 83 | 84 | START_TIMER(wtnsData_timer); 85 | AltBn128::FrElement *wtnsData = (AltBn128::FrElement *)wtns->getSectionData(2); 86 | END_TIMER(wtnsData_timer, "get wtnsData"); 87 | 88 | START_TIMER(get_proof_timer); 89 | auto proof = prover->prove(wtnsData); 90 | END_TIMER(get_proof_timer, "generate proof"); 91 | 92 | 93 | START_TIMER(write_proof_to_file_timer); 94 | std::ofstream proofFile; 95 | proofFile.open (proofFilename); 96 | proofFile << proof->toJson(); 97 | proofFile.close(); 98 | END_TIMER(write_proof_to_file_timer, "write proof to file"); 99 | 100 | START_TIMER(write_public_to_file_timer); 101 | std::ofstream publicFile; 102 | publicFile.open (publicFilename); 103 | 104 | json jsonPublic; 105 | AltBn128::FrElement aux; 106 | for (int i=1; i<=zkeyHeader->nPublic; i++) { 107 | AltBn128::Fr.toMontgomery(aux, wtnsData[i]); 108 | jsonPublic.push_back(AltBn128::Fr.toString(aux)); 109 | } 110 | 111 | publicFile << jsonPublic; 112 | publicFile.close(); 113 | END_TIMER(write_public_to_file_timer, "write public to file"); 114 | 115 | } catch (std::exception* e) { 116 | mpz_clear(altBbn128r); 117 | std::cerr << e->what() << '\n'; 118 | return EXIT_FAILURE; 119 | } catch (std::exception& e) { 120 | mpz_clear(altBbn128r); 121 | std::cerr << e.what() << '\n'; 122 | return EXIT_FAILURE; 123 | } 124 | 125 | mpz_clear(altBbn128r); 126 | END_TIMER(prover_timer, "prover total"); 127 | 128 | exit(EXIT_SUCCESS); 129 | } 130 | -------------------------------------------------------------------------------- /src/main_prover_cuda.cu: -------------------------------------------------------------------------------- 1 | #include "groth16_cuda.cu" 2 | 3 | int main(int argc, char **argv) 4 | { 5 | START_TIMER(prover_cuda_timer); 6 | if (argc != 5) { 7 | std::cerr << "Invalid number of parameters:\n"; 8 | std::cerr << "Usage: prover_cuda \n"; 9 | return EXIT_FAILURE; 10 | } 11 | 12 | START_TIMER(altBbn128r_timer); 13 | mpz_t altBbn128r; 14 | 15 | mpz_init(altBbn128r); 16 | mpz_set_str(altBbn128r, "21888242871839275222246405745257275088548364400416034343698204186575808495617", 10); 17 | END_TIMER(altBbn128r_timer, "init and set str for altBbn128r"); 18 | 19 | try { 20 | START_TIMER(get_zkey_wtns_timer); 21 | std::string zkeyFilename = argv[1]; 22 | std::string wtnsFilename = argv[2]; 23 | std::string proofFilename = argv[3]; 24 | std::string publicFilename = argv[4]; 25 | 26 | auto zkey = BinFileUtils::openExisting(zkeyFilename, "zkey", 1); 27 | auto zkeyHeader = ZKeyUtils::loadHeader(zkey.get()); 28 | 29 | std::string proofStr; 30 | if (mpz_cmp(zkeyHeader->rPrime, altBbn128r) != 0) { 31 | throw std::invalid_argument( "zkey curve not supported" ); 32 | } 33 | 34 | auto wtns = BinFileUtils::openExisting(wtnsFilename, "wtns", 2); 35 | auto wtnsHeader = WtnsUtils::loadHeader(wtns.get()); 36 | 37 | if (mpz_cmp(wtnsHeader->prime, altBbn128r) != 0) { 38 | throw std::invalid_argument( "different wtns curve" ); 39 | } 40 | 41 | END_TIMER(get_zkey_wtns_timer, "get zkey,zkeyHeader,wtns,wtnsHeader"); 42 | 43 | START_TIMER(make_prover_timer); 44 | auto prover = makeCuda_Prover( 45 | zkeyHeader->nVars, 46 | zkeyHeader->nPublic, 47 | zkeyHeader->domainSize, 48 | zkeyHeader->nCoefs, 49 | zkeyHeader->vk_alpha1, 50 | zkeyHeader->vk_beta1, 51 | zkeyHeader->vk_beta2, 52 | zkeyHeader->vk_delta1, 53 | zkeyHeader->vk_delta2, 54 | zkey->getSectionData(4), // Coefs 55 | zkey->getSectionData(5), // pointsA 56 | zkey->getSectionData(6), // pointsB1 57 | zkey->getSectionData(7), // pointsB2 58 | zkey->getSectionData(8), // pointsC 59 | zkey->getSectionData(9) // pointsH1 60 | ); 61 | END_TIMER(make_prover_timer, "make prover"); 62 | 63 | START_TIMER(wtnsData_timer); 64 | AltBn128::FrElement *wtnsData = (AltBn128::FrElement *)wtns->getSectionData(2); 65 | END_TIMER(wtnsData_timer, "get wtnsData"); 66 | 67 | START_TIMER(get_proof_timer); 68 | auto proof = prover->prove_cuda(wtnsData); 69 | END_TIMER(get_proof_timer, "generate proof"); 70 | 71 | 72 | START_TIMER(write_proof_to_file_timer); 73 | std::ofstream proofFile; 74 | proofFile.open (proofFilename); 75 | proofFile << proof->toJson(); 76 | proofFile.close(); 77 | END_TIMER(write_proof_to_file_timer, "write proof to file"); 78 | 79 | START_TIMER(write_public_to_file_timer); 80 | std::ofstream publicFile; 81 | publicFile.open (publicFilename); 82 | 83 | json jsonPublic; 84 | AltBn128::FrElement aux; 85 | for (int i=1; i<=zkeyHeader->nPublic; i++) { 86 | AltBn128::Fr.toMontgomery(aux, wtnsData[i]); 87 | jsonPublic.push_back(AltBn128::Fr.toString(aux)); 88 | } 89 | 90 | publicFile << jsonPublic; 91 | publicFile.close(); 92 | END_TIMER(write_public_to_file_timer, "write public to file"); 93 | 94 | } catch (std::exception* e) { 95 | mpz_clear(altBbn128r); 96 | std::cerr << e->what() << '\n'; 97 | return EXIT_FAILURE; 98 | } catch (std::exception& e) { 99 | mpz_clear(altBbn128r); 100 | std::cerr << e.what() << '\n'; 101 | return EXIT_FAILURE; 102 | } 103 | 104 | mpz_clear(altBbn128r); 105 | END_TIMER(prover_cuda_timer, "prover cuda total"); 106 | 107 | exit(EXIT_SUCCESS); 108 | } 109 | -------------------------------------------------------------------------------- /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 8 | 9 | #include "prover.h" 10 | #include "zkey_utils.hpp" 11 | #include "wtns_utils.hpp" 12 | #include "groth16.hpp" 13 | #include "binfile_utils.hpp" 14 | #include "fileloader.hpp" 15 | 16 | using json = nlohmann::json; 17 | 18 | static size_t ProofBufferMinSize() 19 | { 20 | return 810; 21 | } 22 | 23 | static size_t PublicBufferMinSize(size_t count) 24 | { 25 | return count * 82 + 4; 26 | } 27 | 28 | static void VerifyPrimes(mpz_srcptr zkey_prime, mpz_srcptr wtns_prime) 29 | { 30 | mpz_t altBbn128r; 31 | 32 | mpz_init(altBbn128r); 33 | mpz_set_str(altBbn128r, "21888242871839275222246405745257275088548364400416034343698204186575808495617", 10); 34 | 35 | if (mpz_cmp(zkey_prime, altBbn128r) != 0) { 36 | throw std::invalid_argument( "zkey curve not supported" ); 37 | } 38 | 39 | if (mpz_cmp(wtns_prime, altBbn128r) != 0) { 40 | throw std::invalid_argument( "different wtns curve" ); 41 | } 42 | 43 | mpz_clear(altBbn128r); 44 | } 45 | 46 | std::string BuildPublicString(AltBn128::FrElement *wtnsData, size_t nPublic) 47 | { 48 | json jsonPublic; 49 | AltBn128::FrElement aux; 50 | for (u_int32_t i=1; i<= nPublic; i++) { 51 | AltBn128::Fr.toMontgomery(aux, wtnsData[i]); 52 | jsonPublic.push_back(AltBn128::Fr.toString(aux)); 53 | } 54 | 55 | return jsonPublic.dump(); 56 | } 57 | 58 | int 59 | groth16_public_size_for_zkey_buf(const void *zkey_buffer, unsigned long zkey_size, 60 | size_t *public_size, 61 | char *error_msg, unsigned long error_msg_maxsize) { 62 | try { 63 | BinFileUtils::BinFile zkey(zkey_buffer, zkey_size, "zkey", 1); 64 | auto zkeyHeader = ZKeyUtils::loadHeader(&zkey); 65 | *public_size = PublicBufferMinSize(zkeyHeader->nPublic); 66 | return PROVER_OK; 67 | } catch (std::exception& e) { 68 | if (error_msg) { 69 | strncpy(error_msg, e.what(), error_msg_maxsize); 70 | } 71 | return PROVER_ERROR; 72 | } catch (...) { 73 | if (error_msg) { 74 | strncpy(error_msg, "unknown error", error_msg_maxsize); 75 | } 76 | return PROVER_ERROR; 77 | } 78 | } 79 | 80 | int 81 | groth16_public_size_for_zkey_file(const char *zkey_fname, 82 | unsigned long *public_size, 83 | char *error_msg, unsigned long error_msg_maxsize) { 84 | try { 85 | auto zkey = BinFileUtils::openExisting(zkey_fname, "zkey", 1); 86 | auto zkeyHeader = ZKeyUtils::loadHeader(zkey.get()); 87 | *public_size = PublicBufferMinSize(zkeyHeader->nPublic); 88 | return PROVER_OK; 89 | } catch (std::exception& e) { 90 | if (error_msg) { 91 | strncpy(error_msg, e.what(), error_msg_maxsize); 92 | } 93 | return PROVER_ERROR; 94 | } catch (...) { 95 | if (error_msg) { 96 | strncpy(error_msg, "unknown error", error_msg_maxsize); 97 | } 98 | return PROVER_ERROR; 99 | } 100 | } 101 | 102 | int 103 | groth16_prover(const void *zkey_buffer, unsigned long zkey_size, 104 | const void *wtns_buffer, unsigned long wtns_size, 105 | char *proof_buffer, unsigned long *proof_size, 106 | char *public_buffer, unsigned long *public_size, 107 | char *error_msg, unsigned long error_msg_maxsize) 108 | { 109 | try { 110 | BinFileUtils::BinFile zkey(zkey_buffer, zkey_size, "zkey", 1); 111 | auto zkeyHeader = ZKeyUtils::loadHeader(&zkey); 112 | 113 | BinFileUtils::BinFile wtns(wtns_buffer, wtns_size, "wtns", 2); 114 | auto wtnsHeader = WtnsUtils::loadHeader(&wtns); 115 | 116 | if (zkeyHeader->nVars != wtnsHeader->nVars) { 117 | snprintf(error_msg, error_msg_maxsize, 118 | "Invalid witness length. Circuit: %u, witness: %u", 119 | zkeyHeader->nVars, wtnsHeader->nVars); 120 | return PROVER_INVALID_WITNESS_LENGTH; 121 | } 122 | 123 | size_t proofMinSize = ProofBufferMinSize(); 124 | size_t publicMinSize = PublicBufferMinSize(zkeyHeader->nPublic); 125 | 126 | if (*proof_size < proofMinSize || *public_size < publicMinSize) { 127 | 128 | if (*proof_size < proofMinSize) { 129 | snprintf(error_msg, error_msg_maxsize, 130 | "Proof buffer is too short. Minimum size: %lu, actual size: %lu", 131 | proofMinSize, *proof_size); 132 | } else { 133 | snprintf(error_msg, error_msg_maxsize, 134 | "Public buffer is too short. Minimum size: %lu, actual size: %lu", 135 | publicMinSize, *public_size); 136 | } 137 | 138 | *proof_size = proofMinSize; 139 | *public_size = publicMinSize; 140 | 141 | return PROVER_ERROR_SHORT_BUFFER; 142 | } 143 | 144 | VerifyPrimes(zkeyHeader->rPrime, wtnsHeader->prime); 145 | 146 | auto prover = Groth16::makeProver( 147 | zkeyHeader->nVars, 148 | zkeyHeader->nPublic, 149 | zkeyHeader->domainSize, 150 | zkeyHeader->nCoefs, 151 | zkeyHeader->vk_alpha1, 152 | zkeyHeader->vk_beta1, 153 | zkeyHeader->vk_beta2, 154 | zkeyHeader->vk_delta1, 155 | zkeyHeader->vk_delta2, 156 | zkey.getSectionData(4), // Coefs 157 | zkey.getSectionData(5), // pointsA 158 | zkey.getSectionData(6), // pointsB1 159 | zkey.getSectionData(7), // pointsB2 160 | zkey.getSectionData(8), // pointsC 161 | zkey.getSectionData(9) // pointsH1 162 | ); 163 | AltBn128::FrElement *wtnsData = (AltBn128::FrElement *)wtns.getSectionData(2); 164 | auto proof = prover->prove(wtnsData); 165 | 166 | std::string stringProof = proof->toJson().dump(); 167 | std::string stringPublic = BuildPublicString(wtnsData, zkeyHeader->nPublic); 168 | 169 | size_t stringProofSize = stringProof.length(); 170 | size_t stringPublicSize = stringPublic.length(); 171 | 172 | if (*proof_size < stringProofSize || *public_size < stringPublicSize) { 173 | 174 | *proof_size = stringProofSize; 175 | *public_size = stringPublicSize; 176 | 177 | return PROVER_ERROR_SHORT_BUFFER; 178 | } 179 | 180 | std::strncpy(proof_buffer, stringProof.data(), *proof_size); 181 | std::strncpy(public_buffer, stringPublic.data(), *public_size); 182 | 183 | } catch (std::exception& e) { 184 | 185 | if (error_msg) { 186 | strncpy(error_msg, e.what(), error_msg_maxsize); 187 | } 188 | return PROVER_ERROR; 189 | 190 | } catch (std::exception *e) { 191 | 192 | if (error_msg) { 193 | strncpy(error_msg, e->what(), error_msg_maxsize); 194 | } 195 | delete e; 196 | return PROVER_ERROR; 197 | 198 | } catch (...) { 199 | if (error_msg) { 200 | strncpy(error_msg, "unknown error", error_msg_maxsize); 201 | } 202 | return PROVER_ERROR; 203 | } 204 | 205 | return PROVER_OK; 206 | } 207 | 208 | int 209 | groth16_prover_zkey_file(const char *zkey_file_path, 210 | const void *wtns_buffer, unsigned long wtns_size, 211 | char *proof_buffer, unsigned long *proof_size, 212 | char *public_buffer, unsigned long *public_size, 213 | char *error_msg, unsigned long error_msg_maxsize) { 214 | 215 | std::string zkey_filename(zkey_file_path); 216 | 217 | BinFileUtils::FileLoader fileLoader(zkey_filename); 218 | 219 | return groth16_prover(fileLoader.dataBuffer(), fileLoader.dataSize(), 220 | wtns_buffer, wtns_size, 221 | proof_buffer, proof_size, 222 | public_buffer, public_size, 223 | error_msg, error_msg_maxsize); 224 | } 225 | -------------------------------------------------------------------------------- /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(const void *zkey_buffer, unsigned long zkey_size, 20 | size_t *public_size, 21 | char *error_msg, unsigned long error_msg_maxsize); 22 | 23 | /** 24 | * groth16_public_size_for_zkey_file calculates minimum buffer size for 25 | * JSON-formatted public signals. The calculated buffer size is written 26 | * to the public_size variable. 27 | * 28 | * @return error code: 29 | * PROVER_OK (0) - in case of success 30 | * PROVER_ERROR - in case of an error, error_msg contains the error message 31 | */ 32 | int 33 | groth16_public_size_for_zkey_file(const char *zkey_fname, 34 | unsigned long *public_size, 35 | char *error_msg, unsigned long error_msg_maxsize); 36 | 37 | /** 38 | * groth16_prover 39 | * @return error code: 40 | * PROVER_OK - in case of success 41 | * PPOVER_ERROR - in case of an error 42 | * PROVER_ERROR_SHORT_BUFFER - in case of a short buffer error, also updates proof_size and public_size with actual proof and public sizess 43 | */ 44 | int 45 | groth16_prover(const void *zkey_buffer, unsigned long zkey_size, 46 | const void *wtns_buffer, unsigned long wtns_size, 47 | char *proof_buffer, unsigned long *proof_size, 48 | char *public_buffer, unsigned long *public_size, 49 | char *error_msg, unsigned long error_msg_maxsize); 50 | 51 | /** 52 | * groth16_prover 53 | * @return error code: 54 | * PROVER_OK - in case of success 55 | * PPOVER_ERROR - in case of an error 56 | * PROVER_ERROR_SHORT_BUFFER - in case of a short buffer error, also updates proof_size and public_size with actual proof and public sizess 57 | */ 58 | int 59 | groth16_prover_zkey_file(const char *zkey_file_path, 60 | const void *wtns_buffer, unsigned long wtns_size, 61 | char *proof_buffer, unsigned long *proof_size, 62 | char *public_buffer, unsigned long *public_size, 63 | char *error_msg, unsigned long error_msg_maxsize); 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif 68 | 69 | 70 | #endif // PROVER_HPP 71 | -------------------------------------------------------------------------------- /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, size_t *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: %lu\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 | size_t *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: %lu\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 | size_t 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: %lu\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: %lu\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 | } 7 | 8 | Header::~Header() { 9 | mpz_clear(prime); 10 | } 11 | 12 | std::unique_ptr
loadHeader(BinFileUtils::BinFile *f) { 13 | Header *h = new Header(); 14 | f->startReadSection(1); 15 | 16 | h->n8 = f->readU32LE(); 17 | mpz_init(h->prime); 18 | mpz_import(h->prime, h->n8, -1, 1, -1, 0, f->read(h->n8)); 19 | 20 | h->nVars = f->readU32LE(); 21 | 22 | f->endReadSection(); 23 | 24 | return std::unique_ptr
(h); 25 | } 26 | 27 | } // NAMESPACE -------------------------------------------------------------------------------- /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 | } 10 | 11 | Header::~Header() { 12 | mpz_clear(qPrime); 13 | mpz_clear(rPrime); 14 | } 15 | 16 | 17 | std::unique_ptr
loadHeader(BinFileUtils::BinFile *f) { 18 | auto h = new Header(); 19 | 20 | f->startReadSection(1); 21 | uint32_t protocol = f->readU32LE(); 22 | if (protocol != 1) { 23 | throw std::invalid_argument( "zkey file is not groth16" ); 24 | } 25 | f->endReadSection(); 26 | 27 | f->startReadSection(2); 28 | 29 | h->n8q = f->readU32LE(); 30 | mpz_init(h->qPrime); 31 | mpz_import(h->qPrime, h->n8q, -1, 1, -1, 0, f->read(h->n8q)); 32 | 33 | h->n8r = f->readU32LE(); 34 | mpz_init(h->rPrime); 35 | mpz_import(h->rPrime, h->n8r , -1, 1, -1, 0, f->read(h->n8r)); 36 | 37 | h->nVars = f->readU32LE(); 38 | h->nPublic = f->readU32LE(); 39 | h->domainSize = f->readU32LE(); 40 | 41 | h->vk_alpha1 = f->read(h->n8q*2); 42 | h->vk_beta1 = f->read(h->n8q*2); 43 | h->vk_beta2 = f->read(h->n8q*4); 44 | h->vk_gamma2 = f->read(h->n8q*4); 45 | h->vk_delta1 = f->read(h->n8q*2); 46 | h->vk_delta2 = f->read(h->n8q*4); 47 | f->endReadSection(); 48 | 49 | h->nCoefs = f->getSectionSize(4) / (12 + h->n8r); 50 | 51 | return std::unique_ptr
(h); 52 | } 53 | 54 | } // namespace 55 | 56 | -------------------------------------------------------------------------------- /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/Orbiter-Finance/rapidsnark/77016322808ac58a3acd25a6235510b55172f967/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/Orbiter-Finance/rapidsnark/77016322808ac58a3acd25a6235510b55172f967/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 | }); --------------------------------------------------------------------------------