Rework circuit downloader (#882)
* Introduces a start method to prover * Moves backend creation into start method * sets up three paths for backend initialization * Extracts backend initialization to backend-factory * Implements loading backend from cli files or previously downloaded local files * Wires up downloading and unzipping * functional implementation * Fixes testprover.nim * Sets up tests for backendfactory * includes libzip-dev * pulls in updated contracts * removes integration cli tests for r1cs, wasm, and zkey file arguments. * Fixes issue where inner-scope values are lost before returning * sets local proof verification for dist-test images * Adds two traces and bumps nim-ethers * Adds separate path for circuit files * Create circuit dir if not exists * fix: make sure requestStorage is mined * fix: correct place to plug confirm * test: fixing contracts tests * Restores gitmodules * restores nim-datastore reference * Sets up downloader exe * sets up tool skeleton * implements getting of circuit hash * Implements downloader tool * sets up test skeleton * Implements test for cirdl * includes testTools in testAll * Cleanup building.md * cleans up previous downloader implementation * cleans up testbackendfactory * moves start of prover into node.nim * Fills in arguments in example command * Initializes backend in prover constructor * Restores tests * Restores tests for cli instructions * Review comments by Dmitriy, part 1 * Quotes path in download instruction. * replaces curl with chronos http session * Moves cirdl build output to 'build' folder. * Fixes chronicles log output * Add cirdl support to the codex Dockerfile Signed-off-by: Slava <20563034+veaceslavdoina@users.noreply.github.com> * Add cirdl support to the docker entrypoint Signed-off-by: Slava <20563034+veaceslavdoina@users.noreply.github.com> * Add cirdl support to the release workflow Signed-off-by: Slava <20563034+veaceslavdoina@users.noreply.github.com> * Disable verify_circuit flag for releases Signed-off-by: Slava <20563034+veaceslavdoina@users.noreply.github.com> * Removes backendFactory placeholder type * wip * Replaces zip library with status-im/zippy library (which supports zip and tar) * Updates cirdl to not change circuitdir folder * Switches from zip to tar.gz * Review comments by Dmitriy * updates codex-contracts-eth * Adds testTools to CI * Adds check for access to config.circuitdir * Update fixture circuit zkey * Update matrix to run tools tests on Windows * Adds 'deps' dependency for cirdl * Adjust docker-entrypoint.sh to use CODEX_CIRCUIT_DIR env var * Review comments by Giuliano --------- Signed-off-by: Slava <20563034+veaceslavdoina@users.noreply.github.com> Co-authored-by: Adam Uhlíř <adam@uhlir.dev> Co-authored-by: Veaceslav Doina <20563034+veaceslavdoina@users.noreply.github.com>
This commit is contained in:
parent
e8e9820d5b
commit
4e8630791a
|
@ -53,7 +53,7 @@ jobs:
|
||||||
node-version: 18.15
|
node-version: 18.15
|
||||||
|
|
||||||
- name: Start Ethereum node with Codex contracts
|
- name: Start Ethereum node with Codex contracts
|
||||||
if: matrix.tests == 'contract' || matrix.tests == 'integration' || matrix.tests == 'all'
|
if: matrix.tests == 'contract' || matrix.tests == 'integration' || matrix.tests == 'tools' || matrix.tests == 'all'
|
||||||
working-directory: vendor/codex-contracts-eth
|
working-directory: vendor/codex-contracts-eth
|
||||||
env:
|
env:
|
||||||
MSYS2_PATH_TYPE: inherit
|
MSYS2_PATH_TYPE: inherit
|
||||||
|
@ -79,6 +79,11 @@ jobs:
|
||||||
path: tests/integration/logs/
|
path: tests/integration/logs/
|
||||||
retention-days: 1
|
retention-days: 1
|
||||||
|
|
||||||
|
## Part 4 Tools ##
|
||||||
|
- name: Tools tests
|
||||||
|
if: matrix.tests == 'tools' || matrix.tests == 'all'
|
||||||
|
run: make -j${ncpu} testTools
|
||||||
|
|
||||||
status:
|
status:
|
||||||
if: always()
|
if: always()
|
||||||
needs: [build]
|
needs: [build]
|
||||||
|
|
|
@ -33,6 +33,7 @@ jobs:
|
||||||
os {windows}, cpu {amd64}, builder {windows-latest}, tests {unittest}, nim_version {${{ env.nim_version }}}, shell {msys2}
|
os {windows}, cpu {amd64}, builder {windows-latest}, tests {unittest}, nim_version {${{ env.nim_version }}}, shell {msys2}
|
||||||
os {windows}, cpu {amd64}, builder {windows-latest}, tests {contract}, nim_version {${{ env.nim_version }}}, shell {msys2}
|
os {windows}, cpu {amd64}, builder {windows-latest}, tests {contract}, nim_version {${{ env.nim_version }}}, shell {msys2}
|
||||||
os {windows}, cpu {amd64}, builder {windows-latest}, tests {integration}, nim_version {${{ env.nim_version }}}, shell {msys2}
|
os {windows}, cpu {amd64}, builder {windows-latest}, tests {integration}, nim_version {${{ env.nim_version }}}, shell {msys2}
|
||||||
|
os {windows}, cpu {amd64}, builder {windows-latest}, tests {tools}, nim_version {${{ env.nim_version }}}, shell {msys2}
|
||||||
|
|
||||||
build:
|
build:
|
||||||
needs: matrix
|
needs: matrix
|
||||||
|
|
|
@ -24,7 +24,7 @@ jobs:
|
||||||
name: Build and Push
|
name: Build and Push
|
||||||
uses: ./.github/workflows/docker-reusable.yml
|
uses: ./.github/workflows/docker-reusable.yml
|
||||||
with:
|
with:
|
||||||
nimflags: '-d:disableMarchNative -d:codex_enable_api_debug_peers=true -d:codex_enable_proof_failures=true -d:codex_enable_log_counter=true'
|
nimflags: '-d:disableMarchNative -d:codex_enable_api_debug_peers=true -d:codex_enable_proof_failures=true -d:codex_enable_log_counter=true -d:verify_circuit=true'
|
||||||
nat_ip_auto: true
|
nat_ip_auto: true
|
||||||
tag_latest: ${{ github.ref_name == github.event.repository.default_branch || startsWith(github.ref, 'refs/tags/') }}
|
tag_latest: ${{ github.ref_name == github.event.repository.default_branch || startsWith(github.ref, 'refs/tags/') }}
|
||||||
tag_suffix: dist-tests
|
tag_suffix: dist-tests
|
||||||
|
|
|
@ -10,9 +10,10 @@ env:
|
||||||
cache_nonce: 0 # Allows for easily busting actions/cache caches
|
cache_nonce: 0 # Allows for easily busting actions/cache caches
|
||||||
nim_version: pinned
|
nim_version: pinned
|
||||||
rust_version: 1.78.0
|
rust_version: 1.78.0
|
||||||
binary_base: codex
|
codex_binary_base: codex
|
||||||
|
cirdl_binary_base: cirdl
|
||||||
build_dir: build
|
build_dir: build
|
||||||
nim_flags: '-d:verify_circuit=true'
|
nim_flags: ''
|
||||||
windows_libs: 'libstdc++-6.dll libgomp-1.dll libgcc_s_seh-1.dll libwinpthread-1.dll'
|
windows_libs: 'libstdc++-6.dll libgomp-1.dll libgcc_s_seh-1.dll libwinpthread-1.dll'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
@ -70,13 +71,19 @@ jobs:
|
||||||
macos*) os_name="darwin" ;;
|
macos*) os_name="darwin" ;;
|
||||||
windows*) os_name="windows" ;;
|
windows*) os_name="windows" ;;
|
||||||
esac
|
esac
|
||||||
binary="${{ env.binary_base }}-${{ github.ref_name }}-${os_name}-${{ matrix.cpu }}"
|
codex_binary="${{ env.codex_binary_base }}-${{ github.ref_name }}-${os_name}-${{ matrix.cpu }}"
|
||||||
[[ ${os_name} == "windows" ]] && binary="${binary}.exe"
|
cirdl_binary="${{ env.cirdl_binary_base }}-${{ github.ref_name }}-${os_name}-${{ matrix.cpu }}"
|
||||||
echo "binary=${binary}" >>$GITHUB_ENV
|
if [[ ${os_name} == "windows" ]]; then
|
||||||
|
codex_binary="${codex_binary}.exe"
|
||||||
|
cirdl_binary="${cirdl_binary}.exe"
|
||||||
|
fi
|
||||||
|
echo "codex_binary=${codex_binary}" >>$GITHUB_ENV
|
||||||
|
echo "cirdl_binary=${cirdl_binary}" >>$GITHUB_ENV
|
||||||
|
|
||||||
- name: Release - Build
|
- name: Release - Build
|
||||||
run: |
|
run: |
|
||||||
make NIMFLAGS="--out:${{ env.build_dir }}/${{ env.binary }} ${{ env.nim_flags }}"
|
make NIMFLAGS="--out:${{ env.build_dir }}/${{ env.codex_binary }} ${{ env.nim_flags }}"
|
||||||
|
make cirdl NIMFLAGS="--out:${{ env.build_dir }}/${{ env.cirdl_binary }} ${{ env.nim_flags }}"
|
||||||
|
|
||||||
- name: Release - Libraries
|
- name: Release - Libraries
|
||||||
run: |
|
run: |
|
||||||
|
@ -86,11 +93,26 @@ jobs:
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Release - Upload build artifacts
|
- name: Release - Upload codex build artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: release-${{ env.binary }}
|
name: release-${{ env.codex_binary }}
|
||||||
path: ${{ env.build_dir }}/
|
path: ${{ env.build_dir }}/${{ env.codex_binary_base }}*
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
|
- name: Release - Upload cirdl build artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: release-${{ env.cirdl_binary }}
|
||||||
|
path: ${{ env.build_dir }}/${{ env.cirdl_binary_base }}*
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
|
- name: Release - Upload windows libs
|
||||||
|
if: matrix.os == 'windows'
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: release-${{ matrix.os }}-libs
|
||||||
|
path: ${{ env.build_dir }}/*.dll
|
||||||
retention-days: 1
|
retention-days: 1
|
||||||
|
|
||||||
# Release
|
# Release
|
||||||
|
@ -115,9 +137,7 @@ jobs:
|
||||||
}
|
}
|
||||||
|
|
||||||
# Compress and prepare
|
# Compress and prepare
|
||||||
for file in *; do
|
for file in ${{ env.codex_binary_base }}* ${{ env.cirdl_binary_base }}*; do
|
||||||
# Exclude libraries
|
|
||||||
if [[ "${file}" != *".dll"* ]]; then
|
|
||||||
if [[ "${file}" == *".exe"* ]]; then
|
if [[ "${file}" == *".exe"* ]]; then
|
||||||
|
|
||||||
# Windows - binary only
|
# Windows - binary only
|
||||||
|
@ -128,7 +148,7 @@ jobs:
|
||||||
# Windows - binary and libs
|
# Windows - binary and libs
|
||||||
arc="${file%.*}-libs.zip"
|
arc="${file%.*}-libs.zip"
|
||||||
zip "${arc}" "${file}" ${{ env.windows_libs }}
|
zip "${arc}" "${file}" ${{ env.windows_libs }}
|
||||||
rm -f "${file}" ${{ env.windows_libs }}
|
rm -f "${file}"
|
||||||
checksum "${arc}"
|
checksum "${arc}"
|
||||||
else
|
else
|
||||||
|
|
||||||
|
@ -139,8 +159,8 @@ jobs:
|
||||||
rm -f "${file}"
|
rm -f "${file}"
|
||||||
checksum "${arc}"
|
checksum "${arc}"
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
done
|
done
|
||||||
|
rm -f ${{ env.windows_libs }}
|
||||||
|
|
||||||
- name: Release - Upload compressed artifacts and checksums
|
- name: Release - Upload compressed artifacts and checksums
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
|
|
@ -215,3 +215,6 @@
|
||||||
[submodule "vendor/nim-leveldbstatic"]
|
[submodule "vendor/nim-leveldbstatic"]
|
||||||
path = vendor/nim-leveldbstatic
|
path = vendor/nim-leveldbstatic
|
||||||
url = https://github.com/codex-storage/nim-leveldb.git
|
url = https://github.com/codex-storage/nim-leveldb.git
|
||||||
|
[submodule "vendor/nim-zippy"]
|
||||||
|
path = vendor/nim-zippy
|
||||||
|
url = https://github.com/status-im/nim-zippy.git
|
||||||
|
|
12
BUILDING.md
12
BUILDING.md
|
@ -33,7 +33,7 @@ The current implementation of Codex's zero-knowledge proving circuit requires th
|
||||||
On a bare bones installation of Debian (or a distribution derived from Debian, such as Ubuntu), run
|
On a bare bones installation of Debian (or a distribution derived from Debian, such as Ubuntu), run
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
apt-get update && apt-get install build-essential cmake curl git rustc cargo
|
$ apt-get update && apt-get install build-essential cmake curl git rustc cargo
|
||||||
```
|
```
|
||||||
|
|
||||||
Non-Debian distributions have different package managers: `apk`, `dnf`, `pacman`, `rpm`, `yum`, etc.
|
Non-Debian distributions have different package managers: `apk`, `dnf`, `pacman`, `rpm`, `yum`, etc.
|
||||||
|
@ -157,6 +157,16 @@ In Bash run
|
||||||
make test
|
make test
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Tools
|
||||||
|
|
||||||
|
#### Circuit download tool
|
||||||
|
|
||||||
|
To build the circuit download tool located in `tools/cirdl` run:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
make cirdl
|
||||||
|
```
|
||||||
|
|
||||||
### testAll
|
### testAll
|
||||||
|
|
||||||
#### Prerequisites
|
#### Prerequisites
|
||||||
|
|
12
Makefile
12
Makefile
|
@ -74,6 +74,11 @@ all: | build deps
|
||||||
echo -e $(BUILD_MSG) "build/$@" && \
|
echo -e $(BUILD_MSG) "build/$@" && \
|
||||||
$(ENV_SCRIPT) nim codex $(NIM_PARAMS) build.nims
|
$(ENV_SCRIPT) nim codex $(NIM_PARAMS) build.nims
|
||||||
|
|
||||||
|
# Build tools/cirdl
|
||||||
|
cirdl: | deps
|
||||||
|
echo -e $(BUILD_MSG) "build/$@" && \
|
||||||
|
$(ENV_SCRIPT) nim toolsCirdl $(NIM_PARAMS) build.nims
|
||||||
|
|
||||||
# must be included after the default target
|
# must be included after the default target
|
||||||
-include $(BUILD_SYSTEM_DIR)/makefiles/targets.mk
|
-include $(BUILD_SYSTEM_DIR)/makefiles/targets.mk
|
||||||
|
|
||||||
|
@ -124,7 +129,12 @@ testAll: | build deps
|
||||||
# Builds and runs Taiko L2 tests
|
# Builds and runs Taiko L2 tests
|
||||||
testTaiko: | build deps
|
testTaiko: | build deps
|
||||||
echo -e $(BUILD_MSG) "build/$@" && \
|
echo -e $(BUILD_MSG) "build/$@" && \
|
||||||
$(ENV_SCRIPT) nim testTaiko $(NIM_PARAMS) codex.nims
|
$(ENV_SCRIPT) nim testTaiko $(NIM_PARAMS) build.nims
|
||||||
|
|
||||||
|
# Builds and runs tool tests
|
||||||
|
testTools: | cirdl
|
||||||
|
echo -e $(BUILD_MSG) "build/$@" && \
|
||||||
|
$(ENV_SCRIPT) nim testTools $(NIM_PARAMS) build.nims
|
||||||
|
|
||||||
# nim-libbacktrace
|
# nim-libbacktrace
|
||||||
LIBBACKTRACE_MAKE_FLAGS := -C vendor/nim-libbacktrace --no-print-directory BUILD_CXX_LIB=0
|
LIBBACKTRACE_MAKE_FLAGS := -C vendor/nim-libbacktrace --no-print-directory BUILD_CXX_LIB=0
|
||||||
|
|
15
build.nims
15
build.nims
|
@ -1,5 +1,6 @@
|
||||||
mode = ScriptMode.Verbose
|
mode = ScriptMode.Verbose
|
||||||
|
|
||||||
|
import std/os except commandLineParams
|
||||||
|
|
||||||
### Helper functions
|
### Helper functions
|
||||||
proc buildBinary(name: string, srcDir = "./", params = "", lang = "c") =
|
proc buildBinary(name: string, srcDir = "./", params = "", lang = "c") =
|
||||||
|
@ -14,7 +15,11 @@ proc buildBinary(name: string, srcDir = "./", params = "", lang = "c") =
|
||||||
for i in 2..<paramCount():
|
for i in 2..<paramCount():
|
||||||
extra_params &= " " & paramStr(i)
|
extra_params &= " " & paramStr(i)
|
||||||
|
|
||||||
let cmd = "nim " & lang & " --out:build/" & name & " " & extra_params & " " & srcDir & name & ".nim"
|
let
|
||||||
|
# Place build output in 'build' folder, even if name includes a longer path.
|
||||||
|
outName = os.lastPathPart(name)
|
||||||
|
cmd = "nim " & lang & " --out:build/" & outName & " " & extra_params & " " & srcDir & name & ".nim"
|
||||||
|
|
||||||
exec(cmd)
|
exec(cmd)
|
||||||
|
|
||||||
proc test(name: string, srcDir = "tests/", params = "", lang = "c") =
|
proc test(name: string, srcDir = "tests/", params = "", lang = "c") =
|
||||||
|
@ -24,6 +29,9 @@ proc test(name: string, srcDir = "tests/", params = "", lang = "c") =
|
||||||
task codex, "build codex binary":
|
task codex, "build codex binary":
|
||||||
buildBinary "codex", params = "-d:chronicles_runtime_filtering -d:chronicles_log_level=TRACE"
|
buildBinary "codex", params = "-d:chronicles_runtime_filtering -d:chronicles_log_level=TRACE"
|
||||||
|
|
||||||
|
task toolsCirdl, "build tools/cirdl binary":
|
||||||
|
buildBinary "tools/cirdl/cirdl"
|
||||||
|
|
||||||
task testCodex, "Build & run Codex tests":
|
task testCodex, "Build & run Codex tests":
|
||||||
test "testCodex", params = "-d:codex_enable_proof_failures=true"
|
test "testCodex", params = "-d:codex_enable_proof_failures=true"
|
||||||
|
|
||||||
|
@ -40,10 +48,15 @@ task build, "build codex binary":
|
||||||
task test, "Run tests":
|
task test, "Run tests":
|
||||||
testCodexTask()
|
testCodexTask()
|
||||||
|
|
||||||
|
task testTools, "Run Tools tests":
|
||||||
|
toolsCirdlTask()
|
||||||
|
test "testTools"
|
||||||
|
|
||||||
task testAll, "Run all tests (except for Taiko L2 tests)":
|
task testAll, "Run all tests (except for Taiko L2 tests)":
|
||||||
testCodexTask()
|
testCodexTask()
|
||||||
testContractsTask()
|
testContractsTask()
|
||||||
testIntegrationTask()
|
testIntegrationTask()
|
||||||
|
testToolsTask()
|
||||||
|
|
||||||
task testTaiko, "Run Taiko L2 tests":
|
task testTaiko, "Run Taiko L2 tests":
|
||||||
codexTask()
|
codexTask()
|
||||||
|
|
|
@ -67,6 +67,9 @@ when isMainModule:
|
||||||
# permissions are insecure.
|
# permissions are insecure.
|
||||||
quit QuitFailure
|
quit QuitFailure
|
||||||
|
|
||||||
|
if config.prover() and not(checkAndCreateDataDir((config.circuitDir).string)):
|
||||||
|
quit QuitFailure
|
||||||
|
|
||||||
trace "Data dir initialized", dir = $config.dataDir
|
trace "Data dir initialized", dir = $config.dataDir
|
||||||
|
|
||||||
if not(checkAndCreateDataDir((config.dataDir / "repo"))):
|
if not(checkAndCreateDataDir((config.dataDir / "repo"))):
|
||||||
|
|
|
@ -273,32 +273,8 @@ proc new*(
|
||||||
engine = BlockExcEngine.new(repoStore, wallet, network, blockDiscovery, advertiser, peerStore, pendingBlocks)
|
engine = BlockExcEngine.new(repoStore, wallet, network, blockDiscovery, advertiser, peerStore, pendingBlocks)
|
||||||
store = NetworkStore.new(engine, repoStore)
|
store = NetworkStore.new(engine, repoStore)
|
||||||
prover = if config.prover:
|
prover = if config.prover:
|
||||||
if not fileAccessible($config.circomR1cs, {AccessFlags.Read}) and
|
let backend = config.initializeBackend().expect("Unable to create prover backend.")
|
||||||
endsWith($config.circomR1cs, ".r1cs"):
|
some Prover.new(store, backend, config.numProofSamples)
|
||||||
error "Circom R1CS file not accessible"
|
|
||||||
raise (ref Defect)(
|
|
||||||
msg: "r1cs file not readable, doesn't exist or wrong extension (.r1cs)")
|
|
||||||
|
|
||||||
if not fileAccessible($config.circomWasm, {AccessFlags.Read}) and
|
|
||||||
endsWith($config.circomWasm, ".wasm"):
|
|
||||||
error "Circom wasm file not accessible"
|
|
||||||
raise (ref Defect)(
|
|
||||||
msg: "wasm file not readable, doesn't exist or wrong extension (.wasm)")
|
|
||||||
|
|
||||||
let zkey = if not config.circomNoZkey:
|
|
||||||
if not fileAccessible($config.circomZkey, {AccessFlags.Read}) and
|
|
||||||
endsWith($config.circomZkey, ".zkey"):
|
|
||||||
error "Circom zkey file not accessible"
|
|
||||||
raise (ref Defect)(
|
|
||||||
msg: "zkey file not readable, doesn't exist or wrong extension (.zkey)")
|
|
||||||
|
|
||||||
$config.circomZkey
|
|
||||||
else: ""
|
|
||||||
|
|
||||||
some Prover.new(
|
|
||||||
store,
|
|
||||||
CircomCompat.init($config.circomR1cs, $config.circomWasm, zkey),
|
|
||||||
config.numProofSamples)
|
|
||||||
else:
|
else:
|
||||||
none Prover
|
none Prover
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,7 @@ const
|
||||||
codex_enable_log_counter* {.booldefine.} = false
|
codex_enable_log_counter* {.booldefine.} = false
|
||||||
|
|
||||||
DefaultDataDir* = defaultDataDir()
|
DefaultDataDir* = defaultDataDir()
|
||||||
|
DefaultCircuitDir* = defaultDataDir() / "circuits"
|
||||||
|
|
||||||
type
|
type
|
||||||
StartUpCmd* {.pure.} = enum
|
StartUpCmd* {.pure.} = enum
|
||||||
|
@ -303,23 +304,30 @@ type
|
||||||
command }: PersistenceCmd
|
command }: PersistenceCmd
|
||||||
|
|
||||||
of PersistenceCmd.prover:
|
of PersistenceCmd.prover:
|
||||||
|
circuitDir* {.
|
||||||
|
desc: "Directory where Codex will store proof circuit data"
|
||||||
|
defaultValue: DefaultCircuitDir
|
||||||
|
defaultValueDesc: $DefaultCircuitDir
|
||||||
|
abbr: "cd"
|
||||||
|
name: "circuit-dir" }: OutDir
|
||||||
|
|
||||||
circomR1cs* {.
|
circomR1cs* {.
|
||||||
desc: "The r1cs file for the storage circuit"
|
desc: "The r1cs file for the storage circuit"
|
||||||
defaultValue: $DefaultDataDir / "circuits" / "proof_main.r1cs"
|
defaultValue: $DefaultCircuitDir / "proof_main.r1cs"
|
||||||
defaultValueDesc: $DefaultDataDir & "/circuits/proof_main.r1cs"
|
defaultValueDesc: $DefaultCircuitDir & "/proof_main.r1cs"
|
||||||
name: "circom-r1cs"
|
name: "circom-r1cs"
|
||||||
.}: InputFile
|
.}: InputFile
|
||||||
|
|
||||||
circomWasm* {.
|
circomWasm* {.
|
||||||
desc: "The wasm file for the storage circuit"
|
desc: "The wasm file for the storage circuit"
|
||||||
defaultValue: $DefaultDataDir / "circuits" / "proof_main.wasm"
|
defaultValue: $DefaultCircuitDir / "proof_main.wasm"
|
||||||
defaultValueDesc: $DefaultDataDir & "/circuits/proof_main.wasm"
|
defaultValueDesc: $DefaultDataDir & "/circuits/proof_main.wasm"
|
||||||
name: "circom-wasm"
|
name: "circom-wasm"
|
||||||
.}: InputFile
|
.}: InputFile
|
||||||
|
|
||||||
circomZkey* {.
|
circomZkey* {.
|
||||||
desc: "The zkey file for the storage circuit"
|
desc: "The zkey file for the storage circuit"
|
||||||
defaultValue: $DefaultDataDir / "circuits" / "proof_main.zkey"
|
defaultValue: $DefaultCircuitDir / "proof_main.zkey"
|
||||||
defaultValueDesc: $DefaultDataDir & "/circuits/proof_main.zkey"
|
defaultValueDesc: $DefaultDataDir & "/circuits/proof_main.zkey"
|
||||||
name: "circom-zkey"
|
name: "circom-zkey"
|
||||||
.}: InputFile
|
.}: InputFile
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import ./proofs/backends
|
import ./proofs/backends
|
||||||
import ./proofs/prover
|
import ./proofs/prover
|
||||||
|
import ./proofs/backendfactory
|
||||||
|
|
||||||
export circomcompat, prover
|
export circomcompat, prover, backendfactory
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
import os
|
||||||
|
import strutils
|
||||||
|
import pkg/chronos
|
||||||
|
import pkg/chronicles
|
||||||
|
import pkg/questionable
|
||||||
|
import pkg/confutils/defs
|
||||||
|
import pkg/stew/io2
|
||||||
|
import pkg/ethers
|
||||||
|
|
||||||
|
import ../../conf
|
||||||
|
import ./backends
|
||||||
|
import ./backendutils
|
||||||
|
|
||||||
|
proc initializeFromConfig(
|
||||||
|
config: CodexConf,
|
||||||
|
utils: BackendUtils): ?!AnyBackend =
|
||||||
|
if not fileAccessible($config.circomR1cs, {AccessFlags.Read}) or
|
||||||
|
not endsWith($config.circomR1cs, ".r1cs"):
|
||||||
|
return failure("Circom R1CS file not accessible")
|
||||||
|
|
||||||
|
if not fileAccessible($config.circomWasm, {AccessFlags.Read}) or
|
||||||
|
not endsWith($config.circomWasm, ".wasm"):
|
||||||
|
return failure("Circom wasm file not accessible")
|
||||||
|
|
||||||
|
if not fileAccessible($config.circomZkey, {AccessFlags.Read}) or
|
||||||
|
not endsWith($config.circomZkey, ".zkey"):
|
||||||
|
return failure("Circom zkey file not accessible")
|
||||||
|
|
||||||
|
trace "Initialized prover backend from cli config"
|
||||||
|
success(utils.initializeCircomBackend(
|
||||||
|
$config.circomR1cs,
|
||||||
|
$config.circomWasm,
|
||||||
|
$config.circomZkey))
|
||||||
|
|
||||||
|
proc r1csFilePath(config: CodexConf): string =
|
||||||
|
config.circuitDir / "proof_main.r1cs"
|
||||||
|
|
||||||
|
proc wasmFilePath(config: CodexConf): string =
|
||||||
|
config.circuitDir / "proof_main.wasm"
|
||||||
|
|
||||||
|
proc zkeyFilePath(config: CodexConf): string =
|
||||||
|
config.circuitDir / "proof_main.zkey"
|
||||||
|
|
||||||
|
proc initializeFromCircuitDirFiles(
|
||||||
|
config: CodexConf,
|
||||||
|
utils: BackendUtils): ?!AnyBackend =
|
||||||
|
if fileExists(config.r1csFilePath) and
|
||||||
|
fileExists(config.wasmFilePath) and
|
||||||
|
fileExists(config.zkeyFilePath):
|
||||||
|
trace "Initialized prover backend from local files"
|
||||||
|
return success(utils.initializeCircomBackend(
|
||||||
|
config.r1csFilePath,
|
||||||
|
config.wasmFilePath,
|
||||||
|
config.zkeyFilePath))
|
||||||
|
|
||||||
|
failure("Circuit files not found")
|
||||||
|
|
||||||
|
proc suggestDownloadTool(config: CodexConf) =
|
||||||
|
without address =? config.marketplaceAddress:
|
||||||
|
raise (ref Defect)(msg: "Proving backend initializing while marketplace address not set.")
|
||||||
|
|
||||||
|
let
|
||||||
|
tokens = [
|
||||||
|
"cirdl",
|
||||||
|
"\"" & $config.circuitDir & "\"",
|
||||||
|
config.ethProvider,
|
||||||
|
$address
|
||||||
|
]
|
||||||
|
instructions = "'./" & tokens.join(" ") & "'"
|
||||||
|
|
||||||
|
warn "Proving circuit files are not found. Please run the following to download them:", instructions
|
||||||
|
|
||||||
|
proc initializeBackend*(
|
||||||
|
config: CodexConf,
|
||||||
|
utils: BackendUtils = BackendUtils()): ?!AnyBackend =
|
||||||
|
|
||||||
|
without backend =? initializeFromConfig(config, utils), cliErr:
|
||||||
|
info "Could not initialize prover backend from CLI options...", msg = cliErr.msg
|
||||||
|
without backend =? initializeFromCircuitDirFiles(config, utils), localErr:
|
||||||
|
info "Could not initialize prover backend from circuit dir files...", msg = localErr.msg
|
||||||
|
suggestDownloadTool(config)
|
||||||
|
return failure("CircuitFilesNotFound")
|
||||||
|
# Unexpected: value of backend does not survive leaving each scope. (definition does though...)
|
||||||
|
return success(backend)
|
||||||
|
return success(backend)
|
|
@ -1,3 +1,6 @@
|
||||||
import ./backends/circomcompat
|
import ./backends/circomcompat
|
||||||
|
|
||||||
export circomcompat
|
export circomcompat
|
||||||
|
|
||||||
|
type
|
||||||
|
AnyBackend* = CircomCompat
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
import ./backends
|
||||||
|
|
||||||
|
type
|
||||||
|
BackendUtils* = ref object of RootObj
|
||||||
|
|
||||||
|
method initializeCircomBackend*(
|
||||||
|
self: BackendUtils,
|
||||||
|
r1csFile: string,
|
||||||
|
wasmFile: string,
|
||||||
|
zKeyFile: string
|
||||||
|
): AnyBackend {.base.} =
|
||||||
|
CircomCompat.init(r1csFile, wasmFile, zKeyFile)
|
|
@ -21,11 +21,13 @@ import ../../merkletree
|
||||||
import ../../stores
|
import ../../stores
|
||||||
import ../../market
|
import ../../market
|
||||||
import ../../utils/poseidon2digest
|
import ../../utils/poseidon2digest
|
||||||
|
import ../../conf
|
||||||
|
|
||||||
import ../builder
|
import ../builder
|
||||||
import ../sampler
|
import ../sampler
|
||||||
|
|
||||||
import ./backends
|
import ./backends
|
||||||
|
import ./backendfactory
|
||||||
import ../types
|
import ../types
|
||||||
|
|
||||||
export backends
|
export backends
|
||||||
|
@ -34,7 +36,6 @@ logScope:
|
||||||
topics = "codex prover"
|
topics = "codex prover"
|
||||||
|
|
||||||
type
|
type
|
||||||
AnyBackend* = CircomCompat
|
|
||||||
AnyProof* = CircomProof
|
AnyProof* = CircomProof
|
||||||
|
|
||||||
AnySampler* = Poseidon2Sampler
|
AnySampler* = Poseidon2Sampler
|
||||||
|
@ -86,7 +87,6 @@ proc verify*(
|
||||||
inputs: AnyProofInputs): Future[?!bool] {.async.} =
|
inputs: AnyProofInputs): Future[?!bool] {.async.} =
|
||||||
## Prove a statement using backend.
|
## Prove a statement using backend.
|
||||||
## Returns a future that resolves to a proof.
|
## Returns a future that resolves to a proof.
|
||||||
|
|
||||||
self.backend.verify(proof, inputs)
|
self.backend.verify(proof, inputs)
|
||||||
|
|
||||||
proc new*(
|
proc new*(
|
||||||
|
@ -96,6 +96,6 @@ proc new*(
|
||||||
nSamples: int): Prover =
|
nSamples: int): Prover =
|
||||||
|
|
||||||
Prover(
|
Prover(
|
||||||
backend: backend,
|
|
||||||
store: store,
|
store: store,
|
||||||
|
backend: backend,
|
||||||
nSamples: nSamples)
|
nSamples: nSamples)
|
||||||
|
|
|
@ -24,9 +24,9 @@ RUN echo "export PATH=$PATH:$HOME/.cargo/bin" >> $BASH_ENV
|
||||||
|
|
||||||
WORKDIR ${BUILD_HOME}
|
WORKDIR ${BUILD_HOME}
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN make clean
|
|
||||||
RUN make -j ${MAKE_PARALLEL} update
|
RUN make -j ${MAKE_PARALLEL} update
|
||||||
RUN make -j ${MAKE_PARALLEL}
|
RUN make -j ${MAKE_PARALLEL}
|
||||||
|
RUN make -j ${MAKE_PARALLEL} cirdl
|
||||||
|
|
||||||
# Create
|
# Create
|
||||||
FROM ${IMAGE}
|
FROM ${IMAGE}
|
||||||
|
@ -35,10 +35,10 @@ ARG APP_HOME
|
||||||
ARG NAT_IP_AUTO
|
ARG NAT_IP_AUTO
|
||||||
|
|
||||||
WORKDIR ${APP_HOME}
|
WORKDIR ${APP_HOME}
|
||||||
COPY --from=builder ${BUILD_HOME}/build/codex /usr/local/bin
|
COPY --from=builder ${BUILD_HOME}/build/* /usr/local/bin
|
||||||
COPY --from=builder ${BUILD_HOME}/openapi.yaml .
|
COPY --from=builder ${BUILD_HOME}/openapi.yaml .
|
||||||
COPY --from=builder --chmod=0755 ${BUILD_HOME}/docker/docker-entrypoint.sh /
|
COPY --from=builder --chmod=0755 ${BUILD_HOME}/docker/docker-entrypoint.sh /
|
||||||
RUN apt-get update && apt-get install -y libgomp1 bash curl jq && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update && apt-get install -y libgomp1 curl jq && rm -rf /var/lib/apt/lists/*
|
||||||
ENV NAT_IP_AUTO=${NAT_IP_AUTO}
|
ENV NAT_IP_AUTO=${NAT_IP_AUTO}
|
||||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||||
CMD ["codex"]
|
CMD ["codex"]
|
||||||
|
|
|
@ -50,6 +50,21 @@ if [ -n "${PRIV_KEY}" ]; then
|
||||||
echo "Private key set"
|
echo "Private key set"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Circuit downloader
|
||||||
|
# cirdl [circuitPath] [rpcEndpoint] [marketplaceAddress]
|
||||||
|
if [[ "$@" == *"prover"* ]]; then
|
||||||
|
echo "Run Circuit downloader"
|
||||||
|
# Set circuits dir from CODEX_CIRCUIT_DIR variables if set
|
||||||
|
if [[ -z "${CODEX_CIRCUIT_DIR}" ]]; then
|
||||||
|
export CODEX_CIRCUIT_DIR="${CODEX_DATA_DIR}/circuits"
|
||||||
|
fi
|
||||||
|
# Download circuits
|
||||||
|
mkdir -p "${CODEX_CIRCUIT_DIR}"
|
||||||
|
chmod 700 "${CODEX_CIRCUIT_DIR}"
|
||||||
|
cirdl "${CODEX_CIRCUIT_DIR}" "${CODEX_ETH_PROVIDER}" "${CODEX_MARKETPLACE_ADDRESS}"
|
||||||
|
[[ $? -ne 0 ]] && { echo "Failed to download circuit files"; exit 1; }
|
||||||
|
fi
|
||||||
|
|
||||||
# Run
|
# Run
|
||||||
echo "Run Codex node"
|
echo "Run Codex node"
|
||||||
exec "$@"
|
exec "$@"
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,103 @@
|
||||||
|
import os
|
||||||
|
import ../../asynctest
|
||||||
|
|
||||||
|
import pkg/chronos
|
||||||
|
import pkg/confutils/defs
|
||||||
|
import pkg/codex/conf
|
||||||
|
import pkg/codex/slots/proofs/backends
|
||||||
|
import pkg/codex/slots/proofs/backendfactory
|
||||||
|
import pkg/codex/slots/proofs/backendutils
|
||||||
|
|
||||||
|
import ../helpers
|
||||||
|
import ../examples
|
||||||
|
|
||||||
|
type
|
||||||
|
BackendUtilsMock = ref object of BackendUtils
|
||||||
|
argR1csFile: string
|
||||||
|
argWasmFile: string
|
||||||
|
argZKeyFile: string
|
||||||
|
|
||||||
|
method initializeCircomBackend*(
|
||||||
|
self: BackendUtilsMock,
|
||||||
|
r1csFile: string,
|
||||||
|
wasmFile: string,
|
||||||
|
zKeyFile: string
|
||||||
|
): AnyBackend =
|
||||||
|
self.argR1csFile = r1csFile
|
||||||
|
self.argWasmFile = wasmFile
|
||||||
|
self.argZKeyFile = zKeyFile
|
||||||
|
# We return a backend with *something* that's not nil that we can check for.
|
||||||
|
var
|
||||||
|
key = VerifyingKey(icLen: 123)
|
||||||
|
vkpPtr: ptr VerifyingKey = key.addr
|
||||||
|
return CircomCompat(vkp: vkpPtr)
|
||||||
|
|
||||||
|
suite "Test BackendFactory":
|
||||||
|
let
|
||||||
|
utilsMock = BackendUtilsMock()
|
||||||
|
circuitDir = "testecircuitdir"
|
||||||
|
|
||||||
|
setup:
|
||||||
|
createDir(circuitDir)
|
||||||
|
|
||||||
|
teardown:
|
||||||
|
removeDir(circuitDir)
|
||||||
|
|
||||||
|
test "Should create backend from cli config":
|
||||||
|
let
|
||||||
|
config = CodexConf(
|
||||||
|
cmd: StartUpCmd.persistence,
|
||||||
|
nat: ValidIpAddress.init("127.0.0.1"),
|
||||||
|
discoveryIp: ValidIpAddress.init(IPv4_any()),
|
||||||
|
metricsAddress: ValidIpAddress.init("127.0.0.1"),
|
||||||
|
persistenceCmd: PersistenceCmd.prover,
|
||||||
|
marketplaceAddress: EthAddress.example.some,
|
||||||
|
circomR1cs: InputFile("tests/circuits/fixtures/proof_main.r1cs"),
|
||||||
|
circomWasm: InputFile("tests/circuits/fixtures/proof_main.wasm"),
|
||||||
|
circomZkey: InputFile("tests/circuits/fixtures/proof_main.zkey")
|
||||||
|
)
|
||||||
|
backend = config.initializeBackend(utilsMock).tryGet
|
||||||
|
|
||||||
|
check:
|
||||||
|
backend.vkp != nil
|
||||||
|
utilsMock.argR1csFile == $config.circomR1cs
|
||||||
|
utilsMock.argWasmFile == $config.circomWasm
|
||||||
|
utilsMock.argZKeyFile == $config.circomZkey
|
||||||
|
|
||||||
|
test "Should create backend from local files":
|
||||||
|
let
|
||||||
|
config = CodexConf(
|
||||||
|
cmd: StartUpCmd.persistence,
|
||||||
|
nat: ValidIpAddress.init("127.0.0.1"),
|
||||||
|
discoveryIp: ValidIpAddress.init(IPv4_any()),
|
||||||
|
metricsAddress: ValidIpAddress.init("127.0.0.1"),
|
||||||
|
persistenceCmd: PersistenceCmd.prover,
|
||||||
|
marketplaceAddress: EthAddress.example.some,
|
||||||
|
|
||||||
|
# Set the circuitDir such that the tests/circuits/fixtures/ files
|
||||||
|
# will be picked up as local files:
|
||||||
|
circuitDir: OutDir("tests/circuits/fixtures")
|
||||||
|
)
|
||||||
|
backend = config.initializeBackend(utilsMock).tryGet
|
||||||
|
|
||||||
|
check:
|
||||||
|
backend.vkp != nil
|
||||||
|
utilsMock.argR1csFile == config.circuitDir / "proof_main.r1cs"
|
||||||
|
utilsMock.argWasmFile == config.circuitDir / "proof_main.wasm"
|
||||||
|
utilsMock.argZKeyFile == config.circuitDir / "proof_main.zkey"
|
||||||
|
|
||||||
|
test "Should suggest usage of downloader tool when files not available":
|
||||||
|
let
|
||||||
|
config = CodexConf(
|
||||||
|
cmd: StartUpCmd.persistence,
|
||||||
|
nat: ValidIpAddress.init("127.0.0.1"),
|
||||||
|
discoveryIp: ValidIpAddress.init(IPv4_any()),
|
||||||
|
metricsAddress: ValidIpAddress.init("127.0.0.1"),
|
||||||
|
persistenceCmd: PersistenceCmd.prover,
|
||||||
|
marketplaceAddress: EthAddress.example.some,
|
||||||
|
circuitDir: OutDir(circuitDir)
|
||||||
|
)
|
||||||
|
backendResult = config.initializeBackend(utilsMock)
|
||||||
|
|
||||||
|
check:
|
||||||
|
backendResult.isErr
|
|
@ -15,6 +15,8 @@ import pkg/codex/chunker
|
||||||
import pkg/codex/blocktype as bt
|
import pkg/codex/blocktype as bt
|
||||||
import pkg/codex/slots
|
import pkg/codex/slots
|
||||||
import pkg/codex/stores
|
import pkg/codex/stores
|
||||||
|
import pkg/codex/conf
|
||||||
|
import pkg/confutils/defs
|
||||||
import pkg/poseidon2/io
|
import pkg/poseidon2/io
|
||||||
import pkg/codex/utils/poseidon2digest
|
import pkg/codex/utils/poseidon2digest
|
||||||
|
|
||||||
|
@ -29,9 +31,6 @@ suite "Test Prover":
|
||||||
cellSize = DefaultCellSize
|
cellSize = DefaultCellSize
|
||||||
repoTmp = TempLevelDb.new()
|
repoTmp = TempLevelDb.new()
|
||||||
metaTmp = TempLevelDb.new()
|
metaTmp = TempLevelDb.new()
|
||||||
r1cs = "tests/circuits/fixtures/proof_main.r1cs"
|
|
||||||
wasm = "tests/circuits/fixtures/proof_main.wasm"
|
|
||||||
circomBackend = CircomCompat.init(r1cs, wasm)
|
|
||||||
challenge = 1234567.toF.toBytes.toArray32
|
challenge = 1234567.toF.toBytes.toArray32
|
||||||
|
|
||||||
var
|
var
|
||||||
|
@ -42,9 +41,21 @@ suite "Test Prover":
|
||||||
let
|
let
|
||||||
repoDs = repoTmp.newDb()
|
repoDs = repoTmp.newDb()
|
||||||
metaDs = metaTmp.newDb()
|
metaDs = metaTmp.newDb()
|
||||||
|
config = CodexConf(
|
||||||
|
cmd: StartUpCmd.persistence,
|
||||||
|
nat: ValidIpAddress.init("127.0.0.1"),
|
||||||
|
discoveryIp: ValidIpAddress.init(IPv4_any()),
|
||||||
|
metricsAddress: ValidIpAddress.init("127.0.0.1"),
|
||||||
|
persistenceCmd: PersistenceCmd.prover,
|
||||||
|
circomR1cs: InputFile("tests/circuits/fixtures/proof_main.r1cs"),
|
||||||
|
circomWasm: InputFile("tests/circuits/fixtures/proof_main.wasm"),
|
||||||
|
circomZkey: InputFile("tests/circuits/fixtures/proof_main.zkey"),
|
||||||
|
numProofSamples: samples
|
||||||
|
)
|
||||||
|
backend = config.initializeBackend().tryGet()
|
||||||
|
|
||||||
store = RepoStore.new(repoDs, metaDs)
|
store = RepoStore.new(repoDs, metaDs)
|
||||||
prover = Prover.new(store, circomBackend, samples)
|
prover = Prover.new(store, backend, config.numProofSamples)
|
||||||
|
|
||||||
teardown:
|
teardown:
|
||||||
await repoTmp.destroyDb()
|
await repoTmp.destroyDb()
|
||||||
|
|
|
@ -3,5 +3,6 @@ import ./slots/testsampler
|
||||||
import ./slots/testconverters
|
import ./slots/testconverters
|
||||||
import ./slots/testbackends
|
import ./slots/testbackends
|
||||||
import ./slots/testprover
|
import ./slots/testprover
|
||||||
|
import ./slots/testbackendfactory
|
||||||
|
|
||||||
{.warning[UnusedImport]: off.}
|
{.warning[UnusedImport]: off.}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import std/tempfiles
|
||||||
import codex/conf
|
import codex/conf
|
||||||
import codex/utils/fileutils
|
import codex/utils/fileutils
|
||||||
import ./nodes
|
import ./nodes
|
||||||
|
import ../examples
|
||||||
|
|
||||||
suite "Command line interface":
|
suite "Command line interface":
|
||||||
|
|
||||||
|
@ -25,26 +26,32 @@ suite "Command line interface":
|
||||||
node.stop()
|
node.stop()
|
||||||
discard removeFile(unsafeKeyFile)
|
discard removeFile(unsafeKeyFile)
|
||||||
|
|
||||||
test "complains when persistence is enabled without accessible r1cs file":
|
let
|
||||||
let node = startNode(@["persistence", "prover"])
|
marketplaceArg = "--marketplace-address=" & $EthAddress.example
|
||||||
node.waitUntilOutput("r1cs file not readable, doesn't exist or wrong extension (.r1cs)")
|
expectedDownloadInstruction = "Proving circuit files are not found. Please run the following to download them:"
|
||||||
|
|
||||||
|
test "suggests downloading of circuit files when persistence is enabled without accessible r1cs file":
|
||||||
|
let node = startNode(@["persistence", "prover", marketplaceArg])
|
||||||
|
node.waitUntilOutput(expectedDownloadInstruction)
|
||||||
node.stop()
|
node.stop()
|
||||||
|
|
||||||
test "complains when persistence is enabled without accessible wasm file":
|
test "suggests downloading of circuit files when persistence is enabled without accessible wasm file":
|
||||||
let node = startNode(@[
|
let node = startNode(@[
|
||||||
"persistence",
|
"persistence",
|
||||||
"prover",
|
"prover",
|
||||||
|
marketplaceArg,
|
||||||
"--circom-r1cs=tests/circuits/fixtures/proof_main.r1cs"
|
"--circom-r1cs=tests/circuits/fixtures/proof_main.r1cs"
|
||||||
])
|
])
|
||||||
node.waitUntilOutput("wasm file not readable, doesn't exist or wrong extension (.wasm)")
|
node.waitUntilOutput(expectedDownloadInstruction)
|
||||||
node.stop()
|
node.stop()
|
||||||
|
|
||||||
test "complains when persistence is enabled without accessible zkey file":
|
test "suggests downloading of circuit files when persistence is enabled without accessible zkey file":
|
||||||
let node = startNode(@[
|
let node = startNode(@[
|
||||||
"persistence",
|
"persistence",
|
||||||
"prover",
|
"prover",
|
||||||
|
marketplaceArg,
|
||||||
"--circom-r1cs=tests/circuits/fixtures/proof_main.r1cs",
|
"--circom-r1cs=tests/circuits/fixtures/proof_main.r1cs",
|
||||||
"--circom-wasm=tests/circuits/fixtures/proof_main.wasm"
|
"--circom-wasm=tests/circuits/fixtures/proof_main.wasm"
|
||||||
])
|
])
|
||||||
node.waitUntilOutput("zkey file not readable, doesn't exist or wrong extension (.zkey)")
|
node.waitUntilOutput(expectedDownloadInstruction)
|
||||||
node.stop()
|
node.stop()
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
import ./tools/cirdl/testcirdl
|
||||||
|
|
||||||
|
{.warning[UnusedImport]:off.}
|
|
@ -0,0 +1,39 @@
|
||||||
|
import std/os
|
||||||
|
import std/osproc
|
||||||
|
import std/options
|
||||||
|
import pkg/chronos
|
||||||
|
import codex/contracts
|
||||||
|
import ../../integration/marketplacesuite
|
||||||
|
|
||||||
|
marketplacesuite "tools/cirdl":
|
||||||
|
const
|
||||||
|
cirdl = "build" / "cirdl"
|
||||||
|
workdir = "."
|
||||||
|
|
||||||
|
test "circuit download tool":
|
||||||
|
let
|
||||||
|
circuitPath = "testcircuitpath"
|
||||||
|
rpcEndpoint = "ws://localhost:8545"
|
||||||
|
marketplaceAddress = $marketplace.address
|
||||||
|
|
||||||
|
discard existsOrCreateDir(circuitPath)
|
||||||
|
|
||||||
|
let args = [circuitPath, rpcEndpoint, marketplaceAddress]
|
||||||
|
|
||||||
|
let process = osproc.startProcess(
|
||||||
|
cirdl,
|
||||||
|
workdir,
|
||||||
|
args,
|
||||||
|
options={poParentStreams}
|
||||||
|
)
|
||||||
|
|
||||||
|
let returnCode = process.waitForExit()
|
||||||
|
check returnCode == 0
|
||||||
|
|
||||||
|
check:
|
||||||
|
fileExists(circuitPath/"proof_main_verification_key.json")
|
||||||
|
fileExists(circuitPath/"proof_main.r1cs")
|
||||||
|
fileExists(circuitPath/"proof_main.wasm")
|
||||||
|
fileExists(circuitPath/"proof_main.zkey")
|
||||||
|
|
||||||
|
removeDir(circuitPath)
|
|
@ -0,0 +1,128 @@
|
||||||
|
import std/os
|
||||||
|
import std/streams
|
||||||
|
import pkg/chronicles
|
||||||
|
import pkg/chronos
|
||||||
|
import pkg/ethers
|
||||||
|
import pkg/questionable
|
||||||
|
import pkg/questionable/results
|
||||||
|
import pkg/zippy/tarballs
|
||||||
|
import pkg/chronos/apps/http/httpclient
|
||||||
|
import ../../codex/contracts/marketplace
|
||||||
|
|
||||||
|
proc consoleLog(logLevel: LogLevel, msg: LogOutputStr) {.gcsafe.} =
|
||||||
|
try:
|
||||||
|
stdout.write(msg)
|
||||||
|
stdout.flushFile()
|
||||||
|
except IOError as err:
|
||||||
|
logLoggingFailure(cstring(msg), err)
|
||||||
|
|
||||||
|
proc noOutput(logLevel: LogLevel, msg: LogOutputStr) = discard
|
||||||
|
|
||||||
|
defaultChroniclesStream.outputs[0].writer = consoleLog
|
||||||
|
defaultChroniclesStream.outputs[1].writer = noOutput
|
||||||
|
defaultChroniclesStream.outputs[2].writer = noOutput
|
||||||
|
|
||||||
|
proc printHelp() =
|
||||||
|
info "Usage: ./cirdl [circuitPath] [rpcEndpoint] [marketplaceAddress]"
|
||||||
|
info " circuitPath: path where circuit files will be placed."
|
||||||
|
info " rpcEndpoint: URL of web3 RPC endpoint."
|
||||||
|
info " marketplaceAddress: Address of deployed Codex marketplace contracts."
|
||||||
|
|
||||||
|
proc getCircuitHash(rpcEndpoint: string, marketplaceAddress: string): Future[?!string] {.async.} =
|
||||||
|
let provider = JsonRpcProvider.new(rpcEndpoint)
|
||||||
|
without address =? Address.init(marketplaceAddress):
|
||||||
|
return failure("Invalid address: " & marketplaceAddress)
|
||||||
|
|
||||||
|
let marketplace = Marketplace.new(address, provider)
|
||||||
|
let config = await marketplace.config()
|
||||||
|
return success config.proofs.zkeyHash
|
||||||
|
|
||||||
|
proc formatUrl(hash: string): string =
|
||||||
|
"https://circuit.codex.storage/proving-key/" & hash
|
||||||
|
|
||||||
|
proc retrieveUrl(uri: string): Future[seq[byte]] {.async.} =
|
||||||
|
let httpSession = HttpSessionRef.new()
|
||||||
|
try:
|
||||||
|
let resp = await httpSession.fetch(parseUri(uri))
|
||||||
|
return resp.data
|
||||||
|
finally:
|
||||||
|
await noCancel(httpSession.closeWait())
|
||||||
|
|
||||||
|
proc downloadZipfile(url: string, filepath: string): Future[?!void] {.async.} =
|
||||||
|
try:
|
||||||
|
let file = await retrieveUrl(url)
|
||||||
|
var s = newFileStream(filepath, fmWrite)
|
||||||
|
for b in file:
|
||||||
|
s.write(b)
|
||||||
|
s.close()
|
||||||
|
except Exception as exc:
|
||||||
|
return failure(exc.msg)
|
||||||
|
success()
|
||||||
|
|
||||||
|
proc unzip(zipfile: string, targetPath: string): ?!void =
|
||||||
|
try:
|
||||||
|
extractAll(zipfile, targetPath)
|
||||||
|
except Exception as exc:
|
||||||
|
return failure(exc.msg)
|
||||||
|
success()
|
||||||
|
|
||||||
|
proc copyFiles(unpackDir: string, circuitPath: string): ?!void =
|
||||||
|
try:
|
||||||
|
for file in walkDir(unpackDir):
|
||||||
|
copyFileToDir(file.path, circuitPath)
|
||||||
|
except Exception as exc:
|
||||||
|
return failure(exc.msg)
|
||||||
|
success()
|
||||||
|
|
||||||
|
proc main() {.async.} =
|
||||||
|
info "Codex Circuit Downloader, Aww yeah!"
|
||||||
|
let args = os.commandLineParams()
|
||||||
|
if args.len != 3:
|
||||||
|
printHelp()
|
||||||
|
return
|
||||||
|
|
||||||
|
let
|
||||||
|
circuitPath = args[0]
|
||||||
|
rpcEndpoint = args[1]
|
||||||
|
marketplaceAddress = args[2]
|
||||||
|
zipfile = "circuit.tar.gz"
|
||||||
|
unpackFolder = "." / "tempunpackfolder"
|
||||||
|
|
||||||
|
debug "Starting", circuitPath, rpcEndpoint, marketplaceAddress
|
||||||
|
|
||||||
|
if (dirExists(unpackFolder)):
|
||||||
|
removeDir(unpackFolder)
|
||||||
|
|
||||||
|
without circuitHash =? (await getCircuitHash(rpcEndpoint, marketplaceAddress)), err:
|
||||||
|
error "Failed to get circuit hash", msg = err.msg
|
||||||
|
return
|
||||||
|
debug "Got circuithash", circuitHash
|
||||||
|
|
||||||
|
let url = formatUrl(circuitHash)
|
||||||
|
if dlErr =? (await downloadZipfile(url, zipfile)).errorOption:
|
||||||
|
error "Failed to download circuit file", msg = dlErr.msg
|
||||||
|
return
|
||||||
|
debug "Download completed"
|
||||||
|
|
||||||
|
if err =? unzip(zipfile, unpackFolder).errorOption:
|
||||||
|
error "Failed to unzip file", msg = err.msg
|
||||||
|
return
|
||||||
|
debug "Unzip completed"
|
||||||
|
|
||||||
|
# Unpack library cannot unpack into existing directory. We also cannot
|
||||||
|
# delete the targer directory and have the library recreate it because
|
||||||
|
# Codex has likely created it and set correct permissions.
|
||||||
|
# So, we unpack to a temp folder and move the files.
|
||||||
|
if err =? copyFiles(unpackFolder, circuitPath).errorOption:
|
||||||
|
error "Failed to copy files", msg = err.msg
|
||||||
|
return
|
||||||
|
debug "Files copied"
|
||||||
|
|
||||||
|
removeFile(zipfile)
|
||||||
|
removeDir(unpackFolder)
|
||||||
|
|
||||||
|
debug "file and unpack folder removed"
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
waitFor main()
|
||||||
|
info "Done!"
|
|
@ -1 +1 @@
|
||||||
Subproject commit 73a2ca0bd3ba90715ea7e818bafbd82208034a58
|
Subproject commit 558bf645c3dc385437a3e695bba57e7dba1375fb
|
|
@ -1 +1 @@
|
||||||
Subproject commit 4467e310b75aa0749ff28c1572a84ffce57d7c1c
|
Subproject commit e710e4c333f367353aaa1ee82a55a47326b63a65
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 8d6828f090325c5c015f66a438d31aa592a7045d
|
|
@ -1 +1 @@
|
||||||
Subproject commit b2e1fb022f1ee800b439648953e92cc993c1264c
|
Subproject commit fe9bc3f3759ae1add6bf8c899db2e75327f03782
|
Loading…
Reference in New Issue