From bb0a33f4414f77eeb424593a58a7236d16cbe341 Mon Sep 17 00:00:00 2001 From: HristoStaykov <61588673+HristoStaykov@users.noreply.github.com> Date: Tue, 17 Oct 2023 11:27:46 +0300 Subject: [PATCH] Added tooling for compiling zkllvm circuits. (#251) --- .gitmodules | 3 + vendor/zkllvm-metacraft-circuits/README.md | 10 ++ .../zkllvm-metacraft-circuits/scripts/run.sh | 39 ++++++ .../src/CMakeLists.txt | 81 ++++++++++++ .../src/byte_utils.h | 82 ++++++++++++ .../src/compute_shuffled_index.cpp | 56 ++++++++ .../src/compute_shuffled_index.json | 38 ++++++ .../src/compute_shuffled_index_runable.cpp | 120 ++++++++++++++++++ .../zkllvm-metacraft-circuits/zkllvm-template | 1 + 9 files changed, 430 insertions(+) create mode 100644 vendor/zkllvm-metacraft-circuits/README.md create mode 100755 vendor/zkllvm-metacraft-circuits/scripts/run.sh create mode 100644 vendor/zkllvm-metacraft-circuits/src/CMakeLists.txt create mode 100644 vendor/zkllvm-metacraft-circuits/src/byte_utils.h create mode 100644 vendor/zkllvm-metacraft-circuits/src/compute_shuffled_index.cpp create mode 100644 vendor/zkllvm-metacraft-circuits/src/compute_shuffled_index.json create mode 100644 vendor/zkllvm-metacraft-circuits/src/compute_shuffled_index_runable.cpp create mode 160000 vendor/zkllvm-metacraft-circuits/zkllvm-template diff --git a/.gitmodules b/.gitmodules index 9508981fa..10cff206b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -49,3 +49,6 @@ [submodule "vendor/eth2.0-tests"] path = vendor/eth2.0-tests url = git@github.com:ethereum/eth2.0-tests.git +[submodule "vendor/zkllvm-metacraft-circuits/zkllvm-template"] + path = vendor/zkllvm-metacraft-circuits/zkllvm-template + url = https://github.com/NilFoundation/zkllvm-template.git diff --git a/vendor/zkllvm-metacraft-circuits/README.md b/vendor/zkllvm-metacraft-circuits/README.md new file mode 100644 index 000000000..a296a20e1 --- /dev/null +++ b/vendor/zkllvm-metacraft-circuits/README.md @@ -0,0 +1,10 @@ +# zkLLVM template project for circuits compilation + +Template repository for a zk-enabled application project +based on the [zkLLVM toolchain](https://github.com/nilfoundation/zkllvm). +The purpose of this project is to separate the compilation toolchain +from the application circuits. The tooling is added as submodule and we +have a src folder in the projects main folder where the new circuits will +be added. To compile them, use the run.sh scrypt in folder +zkllvm-metacraft-circuits/scripts passing the arguments you would pass to +zkllvm-metacraft-circuits/zkllvm-template/scripts/run.sh. \ No newline at end of file diff --git a/vendor/zkllvm-metacraft-circuits/scripts/run.sh b/vendor/zkllvm-metacraft-circuits/scripts/run.sh new file mode 100755 index 000000000..57abf998a --- /dev/null +++ b/vendor/zkllvm-metacraft-circuits/scripts/run.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +echo $@ + +COPY_SOURCE_FILES=1 + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +REPO_ROOT="$SCRIPT_DIR/.." + +# this function is called when Ctrl-C is sent +function trap_ctrlc () +{ + # perform cleanup here + echo "Ctrl-C caught...performing clean up" + + echo "Doing cleanup" + if [ $COPY_SOURCE_FILES == 0 ] + then + mv $REPO_ROOT/src~ $REPO_ROOT/zkllvm-template/src + cd $SCRIPT_DIR + exit 1 + fi +} + +# initialise trap to call trap_ctrlc function +# when signal 2 (SIGINT) is received +trap "trap_ctrlc" 2 + +echo "SCRIPT_DIR = " $SCRIPT_DIR +echo "REPO_ROOT = " $REPO_ROOT +ls -laht $REPO_ROOT/zkllvm-template/src +mv $REPO_ROOT/zkllvm-template/src $REPO_ROOT/src~ +cp -r $REPO_ROOT/src $REPO_ROOT/zkllvm-template +cd $REPO_ROOT/zkllvm-template +COPY_SOURCE_FILES=0 +scripts/run.sh $@ +cd $SCRIPT_DIR/.. +rm -r $REPO_ROOT/zkllvm-template/src +mv $REPO_ROOT/src~ $REPO_ROOT/zkllvm-template/src diff --git a/vendor/zkllvm-metacraft-circuits/src/CMakeLists.txt b/vendor/zkllvm-metacraft-circuits/src/CMakeLists.txt new file mode 100644 index 000000000..7a7178d0d --- /dev/null +++ b/vendor/zkllvm-metacraft-circuits/src/CMakeLists.txt @@ -0,0 +1,81 @@ +function(add_example example_target) + set(prefix ARG) + set(noValues "") + set(singleValues INPUT) + set(multiValues SOURCES) + cmake_parse_arguments(${prefix} + "${noValues}" + "${singleValues}" + "${multiValues}" + ${ARGN}) + add_circuit(${example_target} + SOURCES ${ARG_SOURCES} + + LINK_LIBRARIES + crypto3::algebra + crypto3::block + crypto3::codec + crypto3::containers + crypto3::hash + crypto3::kdf + crypto3::mac + marshalling::core + marshalling::crypto3_algebra + marshalling::crypto3_multiprecision + marshalling::crypto3_zk + crypto3::math + crypto3::modes + crypto3::multiprecision + crypto3::passhash + crypto3::pbkdf + crypto3::threshold + crypto3::pkpad + crypto3::pubkey + crypto3::random + crypto3::stream + crypto3::vdf + crypto3::zk + + ${Boost_LIBRARIES}) +endfunction() + +add_custom_target(template) + +add_example(compute_shuffled_index SOURCES compute_shuffled_index.cpp INPUT main.inp) + +add_executable(compute_shuffled_index_runable compute_shuffled_index_runable.cpp) + +add_dependencies(template compute_shuffled_index_runable) + +set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address") +set (CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address") + +add_compile_options(-fsanitize=address) +add_link_options(-fsanitize=address) + +target_link_libraries (compute_shuffled_index_runable +crypto3::algebra +crypto3::block +crypto3::codec +crypto3::containers +crypto3::hash +crypto3::kdf +crypto3::mac +marshalling::core +marshalling::crypto3_algebra +marshalling::crypto3_multiprecision +marshalling::crypto3_zk +crypto3::math +crypto3::modes +crypto3::multiprecision +crypto3::passhash +crypto3::pbkdf +crypto3::threshold +crypto3::pkpad +crypto3::pubkey +crypto3::random +crypto3::stream +crypto3::vdf +crypto3::zk + +${Boost_LIBRARIES}) diff --git a/vendor/zkllvm-metacraft-circuits/src/byte_utils.h b/vendor/zkllvm-metacraft-circuits/src/byte_utils.h new file mode 100644 index 000000000..60b09dcc2 --- /dev/null +++ b/vendor/zkllvm-metacraft-circuits/src/byte_utils.h @@ -0,0 +1,82 @@ +using namespace nil::crypto3; + +namespace byte_utils { + + using sha256_t = typename hashes::sha2<256>::block_type; + + #ifdef __ZKLLVM__ + #define assert_true(c) { \ + __builtin_assigner_exit_check(c); \ + } + #else + #define assert_true(c) { \ + assert(c); \ + } + #endif + + bool is_same(sha256_t block0, + sha256_t block1){ + + bool result = true; + for(auto i = 0; i < sizeof(block0)/sizeof(block0[0]) && result; i++) { + printf("Element fount %d\n", i); + result = result && (block0[0] == block1[0]); + } + + return result; + } + + template + char get_nth_byte(const T& val, unsigned int n) { + static_assert(std::is_integral::type>::value, "T must be integral"); + assert_true(n < sizeof(T)); + + return val >> (n * 8); + } + + template + void sha256_to_bytes_array(sha256_t sha, T& out) { + assert_true(out.size() >= sizeof(sha)); + for(int int_count = 0; int_count < sizeof(sha)/sizeof(sha[0]); int_count++) { + + for(int byte_count = 0; byte_count < sizeof(sha[0]); byte_count++) { + out[int_count * sizeof(sha[0]) + byte_count] = get_nth_byte(sha[int_count], byte_count); + } + + } + } + + template + std::array take_n_elements(const std::array& val) { + static_assert(N <= inCount); + std::array ret{}; + for(auto i = 0u; i < N; i++) { + ret[i] = val[i]; + } + return ret; + } + + template + std::array int_to_bytes(const T& paramInt) + { + static_assert(std::is_integral::type>::value, "T must be integral"); + std::array arrayOfByte{}; + for (int i = 0; i < sizeof(T); i++) { + arrayOfByte[sizeof(T) - 1 - i] = get_nth_byte(paramInt, i); + } + return arrayOfByte; + } + + template + T bytes_to_int(const std::array& paramVec) + { + static_assert(std::is_integral::type>::value, "T must be integral"); + T val = 0; + for (int i = sizeof(T) - 1; i >= 0; i--) { + int temp = paramVec[i]; + val |= (temp << ((sizeof(T) - 1 - i) * 8)); + } + return val; + } + +} diff --git a/vendor/zkllvm-metacraft-circuits/src/compute_shuffled_index.cpp b/vendor/zkllvm-metacraft-circuits/src/compute_shuffled_index.cpp new file mode 100644 index 000000000..4b7e8e624 --- /dev/null +++ b/vendor/zkllvm-metacraft-circuits/src/compute_shuffled_index.cpp @@ -0,0 +1,56 @@ +#include +#include + +#include +#include + +#include "byte_utils.h" + +using namespace byte_utils; + +constexpr unsigned char SHUFFLE_ROUND_COUNT = 90; + +[[circuit]] uint64_t compute_shuffled_index( + uint64_t index, + uint64_t index_count, + sha256_t seed) { + assert_true(index < index_count); + + std::array source_buffer; + uint64_t cur_idx_permuted = index; + + sha256_to_bytes_array(seed, source_buffer); + + // Swap or not (https://link.springer.com/content/pdf/10.1007%2F978-3-642-32009-5_1.pdf) + // See the 'generalized domain' algorithm on page 3 + for(unsigned char current_round = 0; current_round < SHUFFLE_ROUND_COUNT; current_round++) { + source_buffer[32] = current_round; + + auto eth2digest = hash>(source_buffer.begin(), source_buffer.begin() + 33); + std::array eth2digest_bytes; + sha256_to_bytes_array(eth2digest, eth2digest_bytes); + auto first8bytes = take_n_elements(eth2digest_bytes); + auto first8bytes_int = bytes_to_int(first8bytes); + auto pivot = first8bytes_int % index_count; + auto flip = ((index_count + pivot) - cur_idx_permuted) % index_count; + auto position = std::max(cur_idx_permuted, flip); + + auto source_buffer_additional_bytes = int_to_bytes(uint32_t(position >> 8)); + for (auto i = 0; i <= 4; i++) { + source_buffer[33 + i] = source_buffer_additional_bytes[i]; + } + + auto source = hash>(source_buffer.begin(), source_buffer.end()); + std::array source_to_bytes; + sha256_to_bytes_array(source, source_to_bytes); + auto byte_value = source_to_bytes[(position % 256) >> 3]; + auto bit = (byte_value >> (position % 8)) % 2; + + if(bit != 0) { + cur_idx_permuted = flip; + } + } + + return cur_idx_permuted; + +} diff --git a/vendor/zkllvm-metacraft-circuits/src/compute_shuffled_index.json b/vendor/zkllvm-metacraft-circuits/src/compute_shuffled_index.json new file mode 100644 index 000000000..be68710f7 --- /dev/null +++ b/vendor/zkllvm-metacraft-circuits/src/compute_shuffled_index.json @@ -0,0 +1,38 @@ +[ + { + "array": [ + [ + "166209954665300884822717121800188038799", + "144783094885247872016525034474730739405" + ], + [ + "316532530640111588187217404778232020911", + "26724093998456942932372011149134879307" + ], + [ + "129016131943024881685044309516733708576", + "301035858936827583230771718648958481107" + ], + [ + "38435942355081927355841277555582070467", + "236468793428173394040239098346085887776" + ], + [ + "155672546387712744663901139927960865151", + "130337062174399240196487120660567896561" + ] + ] + }, + { + "vector": [ + "166209954665300884822717121800188038799", + "144783094885247872016525034474730739405" + ] + }, + { + "vector": [ + "24758149039370610683683259915413762872", + "275362252495473570680232529690834658303" + ] + } +] diff --git a/vendor/zkllvm-metacraft-circuits/src/compute_shuffled_index_runable.cpp b/vendor/zkllvm-metacraft-circuits/src/compute_shuffled_index_runable.cpp new file mode 100644 index 000000000..8833d6c61 --- /dev/null +++ b/vendor/zkllvm-metacraft-circuits/src/compute_shuffled_index_runable.cpp @@ -0,0 +1,120 @@ +#include +#include + +#include +#include + +#include "byte_utils.h" + +using namespace byte_utils; + +constexpr unsigned char SHUFFLE_ROUND_COUNT = 90; + +uint64_t compute_shuffled_index( + uint64_t index, + uint64_t index_count, + sha256_t seed) { + assert_true(index < index_count); + + std::array source_buffer; + uint64_t cur_idx_permuted = index; + + sha256_to_bytes_array(seed, source_buffer); + + // Swap or not (https://link.springer.com/content/pdf/10.1007%2F978-3-642-32009-5_1.pdf) + // See the 'generalized domain' algorithm on page 3 + for(unsigned char current_round = 0; current_round < SHUFFLE_ROUND_COUNT; current_round++) { + source_buffer[32] = current_round; + + auto eth2digest = hash>(source_buffer.begin(), source_buffer.begin() + 33); + std::array eth2digest_bytes; + sha256_to_bytes_array(eth2digest, eth2digest_bytes); + auto first8bytes = take_n_elements(eth2digest_bytes); + auto first8bytes_int = bytes_to_int(first8bytes); + auto pivot = first8bytes_int % index_count; + auto flip = ((index_count + pivot) - cur_idx_permuted) % index_count; + auto position = std::max(cur_idx_permuted, flip); + + auto source_buffer_additional_bytes = int_to_bytes(uint32_t(position >> 8)); + for (auto i = 0; i <= 4; i++) { + source_buffer[33 + i] = source_buffer_additional_bytes[i]; + } + + auto source = hash>(source_buffer.begin(), source_buffer.end()); + std::array source_to_bytes; + sha256_to_bytes_array(source, source_to_bytes); + auto byte_value = source_to_bytes[(position % 256) >> 3]; + auto bit = (byte_value >> (position % 8)) % 2; + + if(bit != 0) { + cur_idx_permuted = flip; + } + } + + return cur_idx_permuted; + +} + +int main(int argc, char* argv[]) { + + for(int i = 0; i < 10000; i++) { + int val = rand(); + printf("starting val = %d\n", val); + int saved = val; + auto myArr = int_to_bytes(val); + val = bytes_to_int(myArr); + printf("after the convertions val = %d\n\n", val); + + assert_true(val == saved); + } + + for(int i = 0; i < 10000; i++) { + uint64_t val = rand(); + printf("starting val64 = %ld\n", val); + int saved = val; + auto myArr = int_to_bytes(val); + val = bytes_to_int(myArr); + printf("after the convertions val64 = %ld\n\n", val); + + assert_true(val == saved); + } + + for(int i = 0; i < 10000; i++) { + unsigned char val = rand(); + printf("starting unsigned char = %d\n", val); + int saved = val; + auto myArr = int_to_bytes(val); + val = bytes_to_int(myArr); + printf("after the convertions unsigned char = %d\n\n", val); + + assert_true(val == saved); + } + + +// ################################################################################################################## + sha256_t seed = {1, 2, 3, 4, 5, 6, 7, 8, 255, 256, 11, 65536, 16777215, 16777216, 167772160, 1677721600}; + std::array source_buffer; + + sha256_to_bytes_array(seed, source_buffer); + + printf("\nDEBUG source_buffer:"); + for(int i = 0; i < 16*4; i++) { + printf("%d ", (int)source_buffer[i]); + } + printf("\n"); +// ################################################################################################################## + + std::array a = {0, 1, 1, 0, 1}; + auto b = take_n_elements(a); + hashes::sha2<256>::digest_type d = hash>(b.begin(), b.end()); + + for(auto it = b.begin(); it != b.end(); it++) { + printf("DEBUG B: %d\n", (int)*it); + } + +// ################################################################################################################## + + // compute_shuffled_index(3, 5, b1); + + return 0; +} diff --git a/vendor/zkllvm-metacraft-circuits/zkllvm-template b/vendor/zkllvm-metacraft-circuits/zkllvm-template new file mode 160000 index 000000000..41dfcf7a6 --- /dev/null +++ b/vendor/zkllvm-metacraft-circuits/zkllvm-template @@ -0,0 +1 @@ +Subproject commit 41dfcf7a6a691e47f17b3c44c910e5d474ff0ae8