Skip to content

Commit

Permalink
Review comments addressed.
Browse files Browse the repository at this point in the history
Usage of tests from vendor/consensus-spec-tests.
Code formatting applied.
Removed unnecessary copying of buffer.
Add ssz files not part of consensus-spec-tests.
Added scripts for code formatting, compilation + tests run
and running arbitrary processes in a container with all environment.
  • Loading branch information
HristoStaykov committed Jan 24, 2024
1 parent 351e50e commit 600c1f3
Show file tree
Hide file tree
Showing 24 changed files with 762 additions and 190,265 deletions.
18 changes: 18 additions & 0 deletions vendor/zkllvm-metacraft-circuits/scripts/compile_and_run_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env bash

echo "using nilfoundation/zkllvm-template:${ZKLLVM_VERSION:=0.0.86}"

SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
echo "SCRIPT_DIR = " $SCRIPT_DIR

CURRENT_DIR=$(pwd)

echo "CURRENT_DIR = " $CURRENT_DIR

cd $SCRIPT_DIR/../docker && docker build -t zcli:latest -f Dockerfile_zcli . && docker run -v $SCRIPT_DIR/../../:/DendrETH zcli:latest

cd $CURRENT_DIR

bash ${SCRIPT_DIR}/run.sh --docker compile

bash ${SCRIPT_DIR}/docker_run.sh make test
13 changes: 13 additions & 0 deletions vendor/zkllvm-metacraft-circuits/scripts/docker_run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash

echo "using nilfoundation/zkllvm-template:${ZKLLVM_VERSION:=0.0.86}"

SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )

docker run --rm -it --name zk_executable_tests \
--volume ${SCRIPT_DIR}/../zkllvm-template/build:/build \
--volume ${SCRIPT_DIR}/../../consensus-spec-tests/:/consensus-spec-tests \
--user $(id -u ${USER}):$(id -g ${USER}) \
-w /build \
ghcr.io/nilfoundation/zkllvm-template:${ZKLLVM_VERSION} \
$@
13 changes: 13 additions & 0 deletions vendor/zkllvm-metacraft-circuits/scripts/format_code.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh
echo "using nilfoundation/zkllvm-template:${ZKLLVM_VERSION:=0.0.86}"

SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
CURRENT_DIR=$(pwd)
COMMAND='for v in $(find -iname "*.cpp" -o -iname "*.hpp" -o -iname "*.h" -o -iname "*.c" | grep -v json.hpp); do echo "applying format to" $v; clang-format -i $v; done'

docker run --rm -it --name code_formatter \
--volume ${SCRIPT_DIR}/../src:/src \
--user $(id -u ${USER}):$(id -g ${USER}) \
-w /src \
ghcr.io/nilfoundation/zkllvm-template:${ZKLLVM_VERSION} \
/bin/bash -c "$COMMAND"
37 changes: 22 additions & 15 deletions vendor/zkllvm-metacraft-circuits/src/circuit_utils/base_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <stdint.h>
#include <cstring>
#include "constants.h"

//!!!TODO: Use assertion in circuits when introduced in tooling
#ifdef __ZKLLVM__
Expand All @@ -11,17 +12,19 @@
{ assert(c); }
#endif

// This assertion is meant to be applied only when the code is compiled as executable.
// When compiling as circuit, it will have no effect for performance reasons.
#ifdef __ZKLLVM__
#define assert_in_executable(c)
#else
#define assert_in_executable(c) \
{ assert(c); }
#endif

using Byte = unsigned char;
using Bytes32 = std::array<Byte, 32>;
using Bytes64 = std::array<Byte, 64>;

template<typename>
struct array_size;
template<typename T, size_t N>
struct array_size<std::array<T, N>> {
static size_t const size = N;
};

using Epoch = uint64_t;
using Slot = uint64_t;
using Root = Bytes32;
Expand All @@ -39,23 +42,25 @@ struct CheckpointVariable {
};

struct JustificationBitsVariable {

std::array<bool, 4> bits;

void shift_left(size_t n) {
assert_true(n > 0);
assert_true(n <= bits.size());
assert_in_executable(n > 0);
assert_in_executable(n <= bits.size());
memmove(&bits[0], &bits[n], sizeof(bool) * (bits.size() - n));
memset(&bits[bits.size() - n], 0, sizeof(bool) * n);
}
void shift_right(size_t n) {
assert_true(n > 0);
assert_true(n <= bits.size());
assert_in_executable(n > 0);
assert_in_executable(n <= bits.size());
memmove(&bits[n], &bits[0], sizeof(bool) * (bits.size() - n));
memset(&bits[0], 0, sizeof(bool) * n);
}
bool test_range(const size_t lower_bound, const size_t upper_bound_non_inclusive) const {
assert_true(lower_bound < upper_bound_non_inclusive);
assert_true(lower_bound >= 0);
assert_true(upper_bound_non_inclusive <= bits.size());
assert_in_executable(lower_bound < upper_bound_non_inclusive);
assert_in_executable(lower_bound >= 0);
assert_in_executable(upper_bound_non_inclusive <= bits.size());
bool result = true;
for (size_t i = lower_bound; i < upper_bound_non_inclusive; i++) {
result = result && bits[i];
Expand All @@ -67,4 +72,6 @@ struct JustificationBitsVariable {
}
};

constexpr unsigned int MAX_MERKLE_DEPTH = 512;
Epoch get_current_epoch(Slot slot) {
return slot / SLOTS_PER_EPOCH;
}
175 changes: 137 additions & 38 deletions vendor/zkllvm-metacraft-circuits/src/circuit_utils/circuit_byte_utils.h
Original file line number Diff line number Diff line change
@@ -1,92 +1,191 @@
#pragma once

#include <nil/crypto3/hash/algorithm/hash.hpp>
#include <nil/crypto3/hash/sha2.hpp>
#include "base_types.h"
#include "../utils/picosha2.h"

using namespace nil::crypto3;

namespace circuit_byte_utils {

using sha256_t = typename hashes::sha2<256>::block_type;
#define countof(array) (sizeof(array) / sizeof(array[0]))

bool is_same(sha256_t block0, sha256_t block1) {
using sha256_t = typename hashes::sha2<256>::block_type;

bool sha256_equals(sha256_t hash1, sha256_t hash2) {
bool result = true;
for (auto i = 0; i < sizeof(block0) / sizeof(block0[0]) && result; i++) {
printf("Element found %d\n", i);
result = result && (block0[0] == block1[0]);
for (auto i = 0; i < countof(hash1); ++i) {
result = result && (hash1[i] == hash2[i]);
}

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");
Byte get_nth_byte(const T val, unsigned int n) {
static_assert(std::is_integral_v<typename std::remove_reference_t<T>>, "T must be integral");
assert_true(n < sizeof(T));

return val >> (n * 8);
return Byte(val >> (n * 8));
}

Byte get_nth_byte(sha256_t val, size_t int_count, size_t byte_count) {
// TODO: implement when we start using crypto3's sha256
return Byte {};
}

unsigned char get_nth_bit(uint64_t gindex, short i) {
return 1 & (gindex >> i);
bool get_nth_bit(uint64_t value, short i) {
return bool(1 & (value >> i));
}

void set_nth_bit(Byte& gindex, short i) {
Byte set_nth_bit(Byte& value, short i) {
assert_true(i < 8);
gindex = gindex | (Byte(1) << i);
return value | (Byte(1) << i);
}

template<typename T>
void sha256_to_bytes_array(sha256_t sha, T& out) {
Bytes32 sha256_to_bytes_array(sha256_t sha) {
Bytes32 out;
assert_true(out.size() >= sizeof(sha));
for (int int_count = 0; int_count < sizeof(sha) / sizeof(sha[0]); int_count++) {
for (int int_count = 0; int_count < countof(sha); 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);
out[int_count * sizeof(sha[0]) + byte_count] = get_nth_byte(sha, int_count, byte_count);
}
}
return out;
}

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);
template<std::size_t N, typename T, std::size_t InputSize>
std::array<T, N> take(const std::array<T, InputSize>& val) {
static_assert(N <= InputSize);
std::array<T, N> ret {};
for (auto i = 0u; i < N; i++) {
ret[i] = val[i];
}
std::copy(val.begin(), val.begin() + N, ret.begin());

return ret;
}

template<typename T>
std::array<Byte, sizeof(T)> int_to_bytes(const T& paramInt, bool little_endian = true) {
static_assert(std::is_integral<typename std::remove_reference<T>::type>::value, "T must be integral");
std::array<Byte, sizeof(T)> arrayOfByte {};
if (little_endian) {
for (int i = 0; i < sizeof(T); i++) {
arrayOfByte[i] = (paramInt >> (i * 8));
template<typename T, bool LittleEndian = true>
std::array<Byte, sizeof(T)> int_to_bytes(const T& paramInt) {
static_assert(std::is_integral_v<typename std::remove_reference_t<T>>, "T must be integral");
std::array<Byte, sizeof(T)> bytes {};
if constexpr (LittleEndian) {
for (int i = 0; i < sizeof(T); ++i) {
bytes[i] = (paramInt >> (i * 8));
}
} else {
for (int i = sizeof(T) - 1; i >= 0; i--) {
arrayOfByte[i] = (paramInt >> (i * 8));
bytes[i] = (paramInt >> (i * 8));
}
}
return arrayOfByte;
return bytes;
}

template<typename T>
T bytes_to_int(const std::array<Byte, sizeof(T)>& paramVec, bool little_endian = true) {
static_assert(std::is_integral<typename std::remove_reference<T>::type>::value, "T must be integral");
template<typename T, bool LittleEndian = true>
T bytes_to_int(const std::array<Byte, sizeof(T)>& bytes) {
static_assert(std::is_integral_v<typename std::remove_reference_t<T>>, "T must be integral");
T result = 0;
if (little_endian) {
if constexpr (LittleEndian) {
for (int i = sizeof(T) - 1; i >= 0; i--) {
result = (result << 8) + paramVec[i];
result = (result << 8) + bytes[i];
}
} else {
for (unsigned i = 0; i < sizeof(T); i++) {
result = (result << 8) + paramVec[i];
for (unsigned i = 0; i < sizeof(T); ++i) {
result = (result << 8) + bytes[i];
}
}
return result;
}

template<typename... Args>
struct SizeSum;

// Partial specialization for an empty parameter pack (base case)
template<>
struct SizeSum<> {
static constexpr size_t value = 0; // Sum is 0 when there are no arguments
};

// Recursive partial specialization for non-empty parameter pack
template<typename First, typename... Rest>
struct SizeSum<First, Rest...> {
static constexpr size_t value = sizeof(First) + SizeSum<Rest...>::value;
};

template<typename T>
struct HasPadding : std::conditional_t<std::has_unique_object_representations_v<T> || std::is_same_v<T, float> ||
std::is_same_v<T, double>,
std::false_type, std::true_type> { };

template<typename T>
struct CanConvertToBytes : std::false_type { };
template<>
struct CanConvertToBytes<Byte> : std::true_type { };
template<>
struct CanConvertToBytes<int> : std::true_type { };
template<>
struct CanConvertToBytes<size_t> : std::true_type { };
template<size_t N>
struct CanConvertToBytes<std::array<Byte, N>> : std::true_type { };

#define ASSERT_IS_HASHABLE(T) \
using PureType = std::remove_cv_t<std::remove_reference_t<T>>; \
static_assert(!std::is_pointer_v<PureType>, "The argument must not be a pointer."); \
static_assert(CanConvertToBytes<PureType>::value, "The argument cannot be serialized."); \
static_assert(!HasPadding<PureType>::value, "The argument must not contain padding.");

template<typename T, size_t N>
void to_bytes(const T& val, std::array<Byte, N>& buffer, size_t offset) {
ASSERT_IS_HASHABLE(T);
memcpy(&buffer[offset], (char*)&val, sizeof(T));
}

template<typename T, size_t N>
void to_bytes(const T& val, std::array<Byte, N>& buffer, size_t offset, size_t total_bytes) {
ASSERT_IS_HASHABLE(T);
assert_true(N >= offset + total_bytes);
memcpy(&buffer[offset], (char*)&val, total_bytes);
}

template<size_t NBytesToHash>
void hash_recursive(std::array<Byte, NBytesToHash>& buffer, size_t& offset) {
}

template<size_t NBytesToHash, typename First, typename... Rest>
void hash_recursive(std::array<Byte, NBytesToHash>& buffer, size_t& offset, const First& first,
const Rest&... rest) {
to_bytes(first, buffer, offset);
offset += sizeof(First);
hash_recursive(buffer, offset, rest...);
}

template<typename... Args>
Bytes32 sha256(const Args&... args) {
std::array<Byte, SizeSum<Args...>::value> buffer;
size_t offset = 0;
hash_recursive(buffer, offset, args...);

// TODO: use crypto3 sha after stack smash bug is fixed.
//!!! auto digest = hash<hashes::sha2<256>>();
//!!! sha256_to_bytes();

Bytes32 hashed;
picosha2::hash256(buffer.begin(), buffer.end(), hashed.begin(), hashed.end());
return hashed;
}

template<size_t NBytesToHash, typename Arg>
Bytes32 sha256(const Arg& arg, size_t offset = 0) {
std::array<Byte, NBytesToHash> buffer;
to_bytes(arg, buffer, offset, NBytesToHash);

// TODO: use crypto3 sha after stack smash bug is fixed.
//!!! auto digest = hash<hashes::sha2<256>>();
//!!! sha256_to_bytes();

Bytes32 hashed;
picosha2::hash256(buffer.begin(), buffer.begin() + NBytesToHash, hashed.begin(), hashed.end());
return hashed;
}

} // namespace circuit_byte_utils
Loading

0 comments on commit 600c1f3

Please sign in to comment.