Skip to content

Commit

Permalink
Added tooling for compiling zkllvm circuits. (#251)
Browse files Browse the repository at this point in the history
  • Loading branch information
HristoStaykov authored Oct 17, 2023
1 parent cd70426 commit bb0a33f
Show file tree
Hide file tree
Showing 9 changed files with 430 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,6 @@
[submodule "vendor/eth2.0-tests"]
path = vendor/eth2.0-tests
url = [email protected]: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
10 changes: 10 additions & 0 deletions vendor/zkllvm-metacraft-circuits/README.md
Original file line number Diff line number Diff line change
@@ -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.
39 changes: 39 additions & 0 deletions vendor/zkllvm-metacraft-circuits/scripts/run.sh
Original file line number Diff line number Diff line change
@@ -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
81 changes: 81 additions & 0 deletions vendor/zkllvm-metacraft-circuits/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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})
82 changes: 82 additions & 0 deletions vendor/zkllvm-metacraft-circuits/src/byte_utils.h
Original file line number Diff line number Diff line change
@@ -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 <typename T>
char get_nth_byte(const T& val, unsigned int n) {
static_assert(std::is_integral<typename std::remove_reference<T>::type>::value, "T must be integral");
assert_true(n < sizeof(T));

return val >> (n * 8);
}

template <typename T>
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<decltype(sha[int_count])>(sha[int_count], byte_count);
}

}
}

template <typename T, std::size_t inCount, std::size_t N>
std::array<T, N> take_n_elements(const std::array<T, inCount>& val) {
static_assert(N <= inCount);
std::array<T, N> ret{};
for(auto i = 0u; i < N; i++) {
ret[i] = val[i];
}
return ret;
}

template <typename T>
std::array<unsigned char, sizeof(T)> int_to_bytes(const T& paramInt)
{
static_assert(std::is_integral<typename std::remove_reference<T>::type>::value, "T must be integral");
std::array<unsigned char, sizeof(T)> arrayOfByte{};
for (int i = 0; i < sizeof(T); i++) {
arrayOfByte[sizeof(T) - 1 - i] = get_nth_byte(paramInt, i);
}
return arrayOfByte;
}

template <typename T>
T bytes_to_int(const std::array<unsigned char, sizeof(T)>& paramVec)
{
static_assert(std::is_integral<typename std::remove_reference<T>::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;
}

}
56 changes: 56 additions & 0 deletions vendor/zkllvm-metacraft-circuits/src/compute_shuffled_index.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include <nil/crypto3/hash/algorithm/hash.hpp>
#include <nil/crypto3/hash/sha2.hpp>

#include <algorithm>
#include <array>

#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<unsigned char, 32+1+4> 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<hashes::sha2<256>>(source_buffer.begin(), source_buffer.begin() + 33);
std::array<unsigned char, 32> eth2digest_bytes;
sha256_to_bytes_array(eth2digest, eth2digest_bytes);
auto first8bytes = take_n_elements<unsigned char, eth2digest_bytes.size(), 8>(eth2digest_bytes);
auto first8bytes_int = bytes_to_int<uint64_t>(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<hashes::sha2<256>>(source_buffer.begin(), source_buffer.end());
std::array<unsigned char, 32> 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;

}
38 changes: 38 additions & 0 deletions vendor/zkllvm-metacraft-circuits/src/compute_shuffled_index.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[
{
"array": [
[
"166209954665300884822717121800188038799",
"144783094885247872016525034474730739405"
],
[
"316532530640111588187217404778232020911",
"26724093998456942932372011149134879307"
],
[
"129016131943024881685044309516733708576",
"301035858936827583230771718648958481107"
],
[
"38435942355081927355841277555582070467",
"236468793428173394040239098346085887776"
],
[
"155672546387712744663901139927960865151",
"130337062174399240196487120660567896561"
]
]
},
{
"vector": [
"166209954665300884822717121800188038799",
"144783094885247872016525034474730739405"
]
},
{
"vector": [
"24758149039370610683683259915413762872",
"275362252495473570680232529690834658303"
]
}
]
Loading

0 comments on commit bb0a33f

Please sign in to comment.