Merge pull request #89 from logos-co/Circom

Circom circuits added
This commit is contained in:
thomaslavaur 2025-09-01 15:26:26 +02:00 committed by GitHub
commit 3f66449b0c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
55 changed files with 3639 additions and 7829 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,104 @@
###
#Build targets
host:
rm -rf build_prover && mkdir build_prover && cd build_prover && \
cmake .. \
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_INSTALL_PREFIX=../package && \
make -j$(nproc) -vvv && make install
# Copy of the original host target, with specific flags for Windows x86_64 to add patches, missing libraries and
# include paths
host_windows_x86_64:
rm -rf build_prover && mkdir build_prover && cd build_prover && \
cmake .. \
-DUSE_ASM=OFF \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=../package \
-DCMAKE_EXE_LINKER_FLAGS="-L/lib -lmman" \
-DCMAKE_CXX_FLAGS="-I/include -include mman_patch.hpp -include cstdint -Duint=unsigned\ int -Du_int32_t=uint32_t -Du_int64_t=uint64_t" && \
make -j$(nproc) -vvv && make install
host_noasm:
rm -rf build_prover_noasm && mkdir build_prover_noasm && cd build_prover_noasm && \
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_noasm -DUSE_ASM=NO && \
make -j$(nproc) -vvv && make install
host_arm64:
rm -rf build_prover_arm64 && mkdir build_prover_arm64 && cd build_prover_arm64 && \
cmake .. -DTARGET_PLATFORM=aarch64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_arm64 && \
make -j$(nproc) -vvv && make install
android:
rm -rf build_prover_android && mkdir build_prover_android && cd build_prover_android && \
cmake .. -DTARGET_PLATFORM=ANDROID -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_android -DBUILD_TESTS=OFF -DUSE_OPENMP=OFF && \
make -j$(nproc) -vvv && make install
android_openmp:
rm -rf build_prover_android_openmp && mkdir build_prover_android_openmp && cd build_prover_android_openmp && \
cmake .. -DTARGET_PLATFORM=ANDROID -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_android_openmp -DBUILD_TESTS=OFF -DUSE_OPENMP=ON && \
make -j$(nproc) -vvv && make install
android_x86_64:
rm -rf build_prover_android_x86_64 && mkdir build_prover_android_x86_64 && cd build_prover_android_x86_64 && \
cmake .. -DTARGET_PLATFORM=ANDROID_x86_64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_android_x86_64 -DBUILD_TESTS=OFF -DUSE_OPENMP=OFF && \
make -j$(nproc) -vvv && make install
android_openmp_x86_64:
rm -rf build_prover_android_openmp_x86_64 && mkdir build_prover_android_openmp_x86_64 && cd build_prover_android_openmp_x86_64 && \
cmake .. -DTARGET_PLATFORM=ANDROID_x86_64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_android_openmp_x86_64 -DBUILD_TESTS=OFF -DUSE_OPENMP=ON && \
make -j$(nproc) -vvv && make install
ios:
@if [ ! -d "./depends/gmp/package_ios_arm64" ]; then echo "Looks like gmp lib is not built. Run './build_gmp.sh ios' first." && exit 1; fi
rm -rf build_prover_ios && mkdir build_prover_ios && cd build_prover_ios && \
cmake .. -GXcode -DTARGET_PLATFORM=IOS -DCMAKE_INSTALL_PREFIX=../package_ios && \
xcodebuild -destination 'generic/platform=iOS' -scheme rapidsnarkStatic -project rapidsnark.xcodeproj -configuration Release && \
xcodebuild -destination 'generic/platform=iOS' -scheme rapidsnark -project rapidsnark.xcodeproj -configuration Release CODE_SIGNING_ALLOWED=NO && \
cp ../depends/gmp/package_ios_arm64/lib/libgmp.a src/Release-iphoneos && \
echo "" && echo "iOS Simulator artifacts built in build_prover_ios/src/Release-iphoneos" && echo ""
ios_simulator:
@if [ ! -d "./depends/gmp/package_iphone_simulator" ]; then echo "Looks like gmp lib is not built. Run './build_gmp.sh ios_simulator' first." && exit 1; fi
rm -rf build_prover_ios_simulator && mkdir build_prover_ios_simulator && cd build_prover_ios_simulator && \
cmake .. -GXcode -DTARGET_PLATFORM=IOS_SIMULATOR -DCMAKE_INSTALL_PREFIX=../package_ios_simulator -DUSE_ASM=NO && \
xcodebuild -destination 'generic/platform=iOS Simulator' -scheme rapidsnarkStatic -project rapidsnark.xcodeproj && \
xcodebuild -destination 'generic/platform=iOS Simulator' -scheme rapidsnark -project rapidsnark.xcodeproj CODE_SIGNING_ALLOWED=NO ARCHS=arm64 && \
cp ../depends/gmp/package_iphone_simulator/lib/libgmp.a src/Debug-iphonesimulator && \
echo "" && echo "iOS Simulator artifacts built in build_prover_ios_simulator/src/Debug-iphonesimulator" && echo ""
macos_arm64:
@if [ ! -d "./depends/gmp/package_macos_arm64" ]; then echo "Looks like gmp lib is not built. Run './build_gmp.sh macos_arm64' first." && exit 1; fi
rm -rf build_prover_macos_arm64 && mkdir build_prover_macos_arm64 && cd build_prover_macos_arm64 && \
cmake .. -DTARGET_PLATFORM=macos_arm64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_macos_arm64 && \
make -j$(nproc) -vvv && make install
macos_x86_64:
@if [ ! -d "./depends/gmp/package_macos_x86_64" ]; then echo "Looks like gmp lib is not built. Run './build_gmp.sh macos_x86_64' first." && exit 1; fi
rm -rf build_prover_macos_x86_64 && mkdir build_prover_macos_x86_64 && cd build_prover_macos_x86_64 && \
cmake .. -DTARGET_PLATFORM=macos_x86_64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../package_macos_x86_64 && \
make -j$(nproc) -vvv && make install
clean:
rm -rf build_prover \
build_prover_macos_arm64 \
build_prover_macos_x86_64 \
build_prover_android \
build_prover_android_x86_64 \
build_prover_ios \
build_prover_ios_simulator \
package \
package_macos_arm64 \
package_macos_x86_64 \
package_android \
package_android_x86_64 \
package_ios \
package_ios_simulator \
depends/gmp/package \
depends/gmp/package_macos_arm64 \
depends/gmp/package_macos_x86_64 \
depends/gmp/package_android_arm64 \
depends/gmp/package_android_x86_64 \
depends/gmp/package_ios_arm64 \
depends/gmp/package_iphone_simulator

423
.github/resources/prover/windows.build_gmp.sh vendored Executable file
View File

@ -0,0 +1,423 @@
#!/usr/bin/env bash
set -e
NPROC=8
fetch_cmd=$( (type wget > /dev/null 2>&1 && echo "wget") || echo "curl -O" )
usage()
{
echo "USAGE: $0 <target>"
echo "where target is one of:"
echo " ios: build for iOS arm64"
echo " ios_simulator: build for iPhone Simulator for arm64/x86_64 (fat binary)"
echo " macos: build for macOS for arm64/x86_64 (fat binary)"
echo " macos_arm64: build for macOS arm64"
echo " macos_x86_64: build for macOS x86_64"
echo " android: build for Android arm64"
echo " android_x86_64: build for Android x86_64"
echo " host: build for this host"
echo " host_noasm: build for this host without asm optimizations (e.g. needed for macOS)"
echo " aarch64: build for Linux aarch64"
exit 1
}
get_gmp()
{
GMP_NAME=gmp-6.2.1
GMP_ARCHIVE=${GMP_NAME}.tar.xz
GMP_URL=https://ftp.gnu.org/gnu/gmp/${GMP_ARCHIVE}
if [ ! -f ${GMP_ARCHIVE} ]; then
$fetch_cmd ${GMP_URL}
fi
if [ ! -d gmp ]; then
tar -xvf ${GMP_ARCHIVE}
mv ${GMP_NAME} gmp
fi
}
build_aarch64()
{
PACKAGE_DIR="$GMP_DIR/package_aarch64"
BUILD_DIR=build_aarch64
if [ -d "$PACKAGE_DIR" ]; then
echo "aarch64 package is built already. See $PACKAGE_DIR"
return 1
fi
export TARGET=aarch64-linux-gnu
echo $TARGET
rm -rf "$BUILD_DIR"
mkdir "$BUILD_DIR"
cd "$BUILD_DIR"
../configure --host $TARGET --prefix="$PACKAGE_DIR" --with-pic --disable-fft &&
make -j${NPROC} &&
make install
cd ..
}
build_host()
{
PACKAGE_DIR="$GMP_DIR/package"
BUILD_DIR=build
if [ -d "$PACKAGE_DIR" ]; then
echo "Host package is built already. See $PACKAGE_DIR"
return 1
fi
rm -rf "$BUILD_DIR"
mkdir "$BUILD_DIR"
cd "$BUILD_DIR"
# The following line is a workaround for the Windows build due to an existing incompatibility with current compiler
# when building GMP.
CFLAGS="-O2 -std=gnu17" CXXFLAGS="-O2 -std=gnu++17" \
../configure --prefix="$PACKAGE_DIR" --with-pic --disable-fft &&
make -j${NPROC} &&
make install
cd ..
}
build_host_noasm()
{
PACKAGE_DIR="$GMP_DIR/package"
BUILD_DIR=build
if [ -d "$PACKAGE_DIR" ]; then
echo "Host package is built already. See $PACKAGE_DIR"
return 1
fi
rm -rf "$BUILD_DIR"
mkdir "$BUILD_DIR"
cd "$BUILD_DIR"
../configure --prefix="$PACKAGE_DIR" --with-pic --disable-fft --disable-assembly &&
make -j${NPROC} &&
make install
cd ..
}
build_android()
{
PACKAGE_DIR="$GMP_DIR/package_android_arm64"
BUILD_DIR=build_android_arm64
if [ -d "$PACKAGE_DIR" ]; then
echo "Android package is built already. See $PACKAGE_DIR"
return 1
fi
if [ -z "$ANDROID_NDK" ]; then
echo "ERROR: ANDROID_NDK environment variable is not set."
echo " It must be an absolute path to the root directory of Android NDK."
echo " For instance /home/test/Android/Sdk/ndk/23.1.7779620"
return 1
fi
if [ "$(uname)" == "Darwin" ]; then
export TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/darwin-x86_64
else
export TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64
fi
export TARGET=aarch64-linux-android
export API=21
export AR=$TOOLCHAIN/bin/llvm-ar
export CC=$TOOLCHAIN/bin/$TARGET$API-clang
export AS=$CC
export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++
export LD=$TOOLCHAIN/bin/ld
export RANLIB=$TOOLCHAIN/bin/llvm-ranlib
export STRIP=$TOOLCHAIN/bin/llvm-strip
echo "$TOOLCHAIN"
echo "$TARGET"
rm -rf "$BUILD_DIR"
mkdir "$BUILD_DIR"
cd "$BUILD_DIR"
../configure --host $TARGET --prefix="$PACKAGE_DIR" --with-pic --disable-fft &&
make -j${NPROC} &&
make install
cd ..
}
build_android_x86_64()
{
PACKAGE_DIR="$GMP_DIR/package_android_x86_64"
BUILD_DIR=build_android_x86_64
if [ -d "$PACKAGE_DIR" ]; then
echo "Android package is built already. See $PACKAGE_DIR"
return 1
fi
if [ -z "$ANDROID_NDK" ]; then
echo "ERROR: ANDROID_NDK environment variable is not set."
echo " It must be an absolute path to the root directory of Android NDK."
echo " For instance /home/test/Android/Sdk/ndk/23.1.7779620"
return 1
fi
if [ "$(uname)" == "Darwin" ]; then
export TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/darwin-x86_64
else
export TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64
fi
export TARGET=x86_64-linux-android
export API=21
export AR=$TOOLCHAIN/bin/llvm-ar
export CC=$TOOLCHAIN/bin/$TARGET$API-clang
export AS=$CC
export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++
export LD=$TOOLCHAIN/bin/ld
export RANLIB=$TOOLCHAIN/bin/llvm-ranlib
export STRIP=$TOOLCHAIN/bin/llvm-strip
echo "$TOOLCHAIN"
echo $TARGET
rm -rf "$BUILD_DIR"
mkdir "$BUILD_DIR"
cd "$BUILD_DIR"
../configure --host $TARGET --prefix="$PACKAGE_DIR" --with-pic --disable-fft &&
make -j${NPROC} &&
make install
cd ..
}
build_ios()
{
PACKAGE_DIR="$GMP_DIR/package_ios_arm64"
BUILD_DIR=build_ios_arm64
if [ -d "$PACKAGE_DIR" ]; then
echo "iOS package is built already. See $PACKAGE_DIR"
return 1
fi
export SDK="iphoneos"
export TARGET=arm64-apple-darwin
export MIN_IOS_VERSION=8.0
export ARCH_FLAGS="-arch arm64 -arch arm64e"
export OPT_FLAGS="-O3 -g3 -fembed-bitcode"
HOST_FLAGS="${ARCH_FLAGS} -miphoneos-version-min=${MIN_IOS_VERSION} -isysroot $(xcrun --sdk ${SDK} --show-sdk-path)"
CC=$(xcrun --find --sdk "${SDK}" clang)
export CC
CXX=$(xcrun --find --sdk "${SDK}" clang++)
export CXX
CPP=$(xcrun --find --sdk "${SDK}" cpp)
export CPP
export CFLAGS="${HOST_FLAGS} ${OPT_FLAGS}"
export CXXFLAGS="${HOST_FLAGS} ${OPT_FLAGS}"
export LDFLAGS="${HOST_FLAGS}"
echo $TARGET
rm -rf "$BUILD_DIR"
mkdir "$BUILD_DIR"
cd "$BUILD_DIR"
../configure --host $TARGET --prefix="$PACKAGE_DIR" --with-pic --disable-fft --disable-assembly &&
make -j${NPROC} &&
make install
cd ..
}
build_ios_simulator()
{
libs=()
for ARCH in "arm64" "x86_64"; do
case "$ARCH" in
"arm64" )
echo "Building for iPhone Simulator arm64"
ARCH_FLAGS="-arch arm64 -arch arm64e"
;;
"x86_64" )
echo "Building for iPhone Simulator x86_64"
ARCH_FLAGS="-arch x86_64"
;;
* )
echo "Incorrect iPhone Simulator arch"
exit 1
esac
BUILD_DIR="build_iphone_simulator_${ARCH}"
PACKAGE_DIR="$GMP_DIR/package_iphone_simulator_${ARCH}"
libs+=("${PACKAGE_DIR}/lib/libgmp.a")
if [ -d "$PACKAGE_DIR" ]; then
echo "iPhone Simulator ${ARCH} package is built already. See $PACKAGE_DIR. Skip building this ARCH."
continue
fi
rm -rf "$BUILD_DIR"
mkdir "$BUILD_DIR"
cd "$BUILD_DIR"
../configure --prefix="${PACKAGE_DIR}" \
CC="$(xcrun --sdk iphonesimulator --find clang)" \
CFLAGS="-O3 -isysroot $(xcrun --sdk iphonesimulator --show-sdk-path) ${ARCH_FLAGS} -fvisibility=hidden -mios-simulator-version-min=8.0" \
LDFLAGS="" \
--host ${ARCH}-apple-darwin --disable-assembly --enable-static --disable-shared --with-pic &&
make -j${NPROC} &&
make install
cd ..
done
mkdir -p "${GMP_DIR}/package_iphone_simulator/lib"
lipo "${libs[@]}" -create -output "${GMP_DIR}/package_iphone_simulator/lib/libgmp.a"
echo "Wrote universal fat library for iPhone Simulator arm64/x86_64 to ${GMP_DIR}/package_iphone_simulator/lib/libgmp.a"
}
build_macos_arch()
{
ARCH="$1"
case "$ARCH" in
"arm64" )
ARCH_FLAGS="-arch arm64 -arch arm64e"
;;
"x86_64" )
ARCH_FLAGS="-arch x86_64"
;;
* )
echo "Incorrect arch"
exit 1
esac
BUILD_DIR="build_macos_${ARCH}"
PACKAGE_DIR="$GMP_DIR/package_macos_${ARCH}"
if [ -d "$PACKAGE_DIR" ]; then
echo "macOS ${ARCH} package is built already. See $PACKAGE_DIR. Skip building this ARCH."
return
fi
rm -rf "$BUILD_DIR"
mkdir "$BUILD_DIR"
cd "$BUILD_DIR"
../configure --prefix="${PACKAGE_DIR}" \
CC="$(xcrun --sdk macosx --find clang)" \
CFLAGS="-O3 -isysroot $(xcrun --sdk macosx --show-sdk-path) ${ARCH_FLAGS} -fvisibility=hidden -mmacos-version-min=14.0" \
LDFLAGS="" \
--host "${ARCH}-apple-darwin" --disable-assembly --enable-static --disable-shared --with-pic &&
make -j${NPROC} &&
make install
cd ..
}
build_macos_fat()
{
echo "Building for macOS arm64"
build_macos_arch "arm64"
echo "Building for macOS x86_64"
build_macos_arch "x86_64"
gmp_lib_arm64="$GMP_DIR/package_macos_arm64/lib/libgmp.a"
gmp_lib_x86_64="$GMP_DIR/package_macos_x86_64/lib/libgmp.a"
gmp_lib_fat="$GMP_DIR/package_macos/lib/libgmp.a"
mkdir -p "${GMP_DIR}/package_macos/lib"
lipo "${gmp_lib_arm64}" "${gmp_lib_x86_64}" -create -output "${gmp_lib_fat}"
mkdir -p "${GMP_DIR}/package_macos/include"
cp "${GMP_DIR}/package_macos_arm64/include/gmp.h" "${GMP_DIR}/package_macos/include/"
echo "Wrote universal fat library for macOS arm64/x86_64 to ${GMP_DIR}/package_macos/lib/libgmp.a"
}
if [ $# -ne 1 ]; then
usage
fi
TARGET_PLATFORM=$(echo "$1" | tr "[:upper:]" "[:lower:]")
cd depends
get_gmp
cd gmp
GMP_DIR=$PWD
case "$TARGET_PLATFORM" in
"ios" )
echo "Building for ios"
build_ios
;;
"ios_simulator" )
echo "Building for iPhone Simulator"
build_ios_simulator
;;
"macos" )
echo "Building fat library for macOS"
build_macos_fat
;;
"macos_arm64" )
echo "Building library for macOS arm64"
build_macos_arch "arm64"
;;
"macos_x86_64" )
echo "Building library for macOS x86_64"
build_macos_arch "x86_64"
;;
"android" )
echo "Building for android"
build_android
;;
"android_x86_64" )
echo "Building for android x86_64"
build_android_x86_64
;;
"host" )
echo "Building for this host"
build_host
;;
"host_noasm" )
echo "Building for this host without asm optimizations (e.g. needed for macOS)"
build_host_noasm
;;
"aarch64" )
echo "Building for linux aarch64"
build_aarch64
;;
* )
usage
esac

View File

@ -0,0 +1,7 @@
// Workaround for Windows where some mman functions are not defined
#ifdef _WIN32
#include <cstddef>
inline int madvise(void*, size_t, int) { return 0; }
#define MADV_SEQUENTIAL 0
#endif

View File

@ -0,0 +1,181 @@
# Workaround for CMake on Windows to
# Added explicit linking (e.g., mman), which are otherwise resolved transitively on Linux and macOS.
find_library(MMAN_LIB mman PATHS /lib NO_DEFAULT_PATH REQUIRED)
link_libraries(${GMP_LIB})
add_definitions(${GMP_DEFINIONS})
if(USE_ASM)
if(ARCH MATCHES "arm64")
add_definitions(-DUSE_ASM -DARCH_ARM64)
elseif(ARCH MATCHES "x86_64")
add_definitions(-DUSE_ASM -DARCH_X86_64)
endif()
endif()
if(DEFINED BITS_PER_CHUNK)
add_definitions(-DMSM_BITS_PER_CHUNK=${BITS_PER_CHUNK})
endif()
if(USE_ASM AND ARCH MATCHES "x86_64")
if (CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin" AND NOT TARGET_PLATFORM MATCHES "^android(_x86_64)?")
set(NASM_FLAGS -fmacho64 --prefix _)
else()
set(NASM_FLAGS -felf64 -DPIC)
endif()
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/build/fq_asm.o
COMMAND nasm ${NASM_FLAGS} fq.asm -o fq_asm.o
DEPENDS ${CMAKE_SOURCE_DIR}/build/fq.asm
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/build)
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/build/fr_asm.o
COMMAND nasm ${NASM_FLAGS} fr.asm -o fr_asm.o
DEPENDS ${CMAKE_SOURCE_DIR}/build/fr.asm
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/build)
endif()
set(FR_SOURCES
../build/fr.hpp
../build/fr.cpp
)
if(USE_ASM)
if(ARCH MATCHES "arm64")
set(FR_SOURCES ${FR_SOURCES} ../build/fr_raw_arm64.s ../build/fr_raw_generic.cpp ../build/fr_generic.cpp)
elseif(ARCH MATCHES "x86_64")
set(FR_SOURCES ${FR_SOURCES} ../build/fr_asm.o)
endif()
else()
set(FR_SOURCES ${FR_SOURCES} ../build/fr_generic.cpp ../build/fr_raw_generic.cpp)
endif()
add_library(fr STATIC ${FR_SOURCES})
set_target_properties(fr PROPERTIES POSITION_INDEPENDENT_CODE ON)
link_libraries(fr)
set(FQ_SOURCES
../build/fq.hpp
../build/fq.cpp
)
if(USE_ASM)
if(ARCH MATCHES "arm64")
set(FQ_SOURCES ${FQ_SOURCES} ../build/fq_raw_arm64.s ../build/fq_raw_generic.cpp ../build/fq_generic.cpp)
elseif(ARCH MATCHES "x86_64")
set(FQ_SOURCES ${FQ_SOURCES} ../build/fq_asm.o)
endif()
else()
set(FQ_SOURCES ${FQ_SOURCES} ../build/fq_raw_generic.cpp ../build/fq_generic.cpp)
endif()
add_library(fq STATIC ${FQ_SOURCES})
set_target_properties(fq PROPERTIES POSITION_INDEPENDENT_CODE ON)
link_libraries(fq)
if(OpenMP_CXX_FOUND)
add_definitions(-DUSE_OPENMP)
add_compile_options(${OpenMP_CXX_FLAGS})
endif()
set(LIB_SOURCES
binfile_utils.hpp
binfile_utils.cpp
zkey_utils.hpp
zkey_utils.cpp
wtns_utils.hpp
wtns_utils.cpp
logger.hpp
logger.cpp
fileloader.cpp
fileloader.hpp
prover.cpp
prover.h
verifier.cpp
verifier.h
../depends/ffiasm/c/misc.cpp
../depends/ffiasm/c/naf.cpp
../depends/ffiasm/c/splitparstr.cpp
../depends/ffiasm/c/alt_bn128.cpp
)
if(USE_LOGGER)
set(LIB_SOURCES ${LIB_SOURCES} logger.cpp)
add_definitions(-DUSE_LOGGER)
endif()
include_directories(
../src
../build
../depends/ffiasm/c
../depends/json/single_include
/include
)
add_library(rapidsnarkStatic STATIC ${LIB_SOURCES})
set_target_properties(rapidsnarkStatic PROPERTIES OUTPUT_NAME rapidsnark)
add_library(rapidsnarkStaticFrFq STATIC ${LIB_SOURCES} ${FQ_SOURCES} ${FR_SOURCES})
set_target_properties(rapidsnarkStaticFrFq PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(rapidsnarkStaticFrFq PROPERTIES OUTPUT_NAME rapidsnark-fr-fq)
add_executable(prover main_prover.cpp)
target_link_libraries(
prover rapidsnarkStatic
fr fq ${MMAN_LIB} # Explicit linking
)
add_executable(verifier main_verifier.cpp)
target_link_libraries(
verifier rapidsnarkStatic
fr fq ${MMAN_LIB} # Explicit linking
)
add_library(rapidsnark SHARED ${LIB_SOURCES})
target_link_libraries(rapidsnark ${MMAN_LIB}) # Explicit linking
if((USE_LOGGER OR NOT USE_OPENMP) AND NOT TARGET_PLATFORM MATCHES "android")
target_link_libraries(prover pthread)
target_link_libraries(verifier pthread)
endif()
if(USE_SODIUM)
target_link_libraries(prover sodium)
endif()
option(BUILD_TESTS "Build the tests" ON)
if(BUILD_TESTS)
enable_testing()
add_executable(test_public_size test_public_size.c)
target_link_libraries(
test_public_size rapidsnarkStaticFrFq pthread
${MMAN_LIB} # Explicit linking
)
add_test(NAME test_public_size COMMAND test_public_size circuit_final.zkey 86
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/testdata)
endif()
if(OpenMP_CXX_FOUND)
if(TARGET_PLATFORM MATCHES "android")
target_link_libraries(prover -static-openmp -fopenmp)
target_link_libraries(verifier -static-openmp -fopenmp)
target_link_libraries(rapidsnark -static-openmp -fopenmp)
elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
target_link_libraries(prover OpenMP::OpenMP_CXX)
target_link_libraries(verifier OpenMP::OpenMP_CXX)
target_link_libraries(test_public_size OpenMP::OpenMP_CXX)
endif()
endif()
add_executable(test_prover test_prover.cpp)

19
.github/resources/prover/windows.uio.h vendored Normal file
View File

@ -0,0 +1,19 @@
// Workaround for Windows UIO header, as it's not available by default
#ifndef SYS_UIO_H
#define SYS_UIO_H
#include <inttypes.h>
#include <unistd.h>
struct iovec
{
void *iov_base;
size_t iov_len;
};
ssize_t readv(int fildes, const struct iovec *iov, int iovcnt);
ssize_t writev(int fildes, const struct iovec *iov, int iovcnt);
#endif

View File

@ -0,0 +1,17 @@
CC = g++
CFLAGS = -std=c++11 -O3 -I. -I/opt/homebrew/include -include gmp_patch.hpp
LDFLAGS = -L/opt/homebrew/lib -lgmp
DEPS_HPP = circom.hpp calcwit.hpp fr.hpp pol.cpp
DEPS_O = main.o calcwit.o fr.o pol.o
all: pol
%.o: %.cpp $(DEPS_HPP)
$(CC) -Wno-address-of-packed-member -c $< $(CFLAGS) -o $@
pol: $(DEPS_O)
$(CC) -o pol $(DEPS_O) $(LDFLAGS)
clean:
rm -f *.o pol

View File

@ -0,0 +1,150 @@
// Workaround for a known macOS issue where certain GMP functions fail to compile
// due to strict type checking, despite uint64_t and mp_limb_t being the same size.
// These wrappers explicitly cast uint64_t parameters to mp_limb_t to resolve the mismatch.
#ifndef GMP_PATCH_CAST_HPP
#define GMP_PATCH_CAST_HPP
#include <gmp.h>
#include <cstdint>
// Arithmetic Wrappers
inline mp_limb_t gmp_add_n_cast(uint64_t* rp, const uint64_t* up, const uint64_t* vp, mp_size_t n) {
return mpn_add_n(reinterpret_cast<mp_limb_t*>(rp),
reinterpret_cast<const mp_limb_t*>(up),
reinterpret_cast<const mp_limb_t*>(vp),
n);
}
inline mp_limb_t gmp_sub_n_cast(uint64_t* rp, const uint64_t* up, const uint64_t* vp, mp_size_t n) {
return mpn_sub_n(reinterpret_cast<mp_limb_t*>(rp),
reinterpret_cast<const mp_limb_t*>(up),
reinterpret_cast<const mp_limb_t*>(vp),
n);
}
inline mp_limb_t gmp_add_1_cast(uint64_t* rp, const uint64_t* up, mp_size_t n, mp_limb_t b) {
return mpn_add_1(reinterpret_cast<mp_limb_t*>(rp),
reinterpret_cast<const mp_limb_t*>(up),
n, b);
}
inline mp_limb_t gmp_sub_1_cast(uint64_t* rp, const uint64_t* up, mp_size_t n, mp_limb_t b) {
return mpn_sub_1(reinterpret_cast<mp_limb_t*>(rp),
reinterpret_cast<const mp_limb_t*>(up),
n, b);
}
inline int gmp_cmp_cast(const uint64_t* up, const uint64_t* vp, mp_size_t n) {
return mpn_cmp(reinterpret_cast<const mp_limb_t*>(up),
reinterpret_cast<const mp_limb_t*>(vp),
n);
}
inline void gmp_copyi_cast(uint64_t* dst, const uint64_t* src, mp_size_t n) {
mpn_copyi(reinterpret_cast<mp_limb_t*>(dst),
reinterpret_cast<const mp_limb_t*>(src),
n);
}
inline mp_limb_t gmp_mul_1_cast(uint64_t* rp, const uint64_t* up, mp_size_t n, mp_limb_t b) {
return mpn_mul_1(reinterpret_cast<mp_limb_t*>(rp),
reinterpret_cast<const mp_limb_t*>(up),
n, b);
}
inline mp_limb_t gmp_addmul_1_cast(uint64_t* rp, const uint64_t* up, mp_size_t n, mp_limb_t b) {
return mpn_addmul_1(reinterpret_cast<mp_limb_t*>(rp),
reinterpret_cast<const mp_limb_t*>(up),
n, b);
}
inline mp_limb_t gmp_add_cast(uint64_t* rp, const uint64_t* up, mp_size_t un, const uint64_t* vp, mp_size_t vn) {
return mpn_add(reinterpret_cast<mp_limb_t*>(rp),
reinterpret_cast<const mp_limb_t*>(up), un,
reinterpret_cast<const mp_limb_t*>(vp), vn);
}
// Logic/Bitwise Wrappers
inline int gmp_zero_p_cast(const uint64_t* up, mp_size_t n) {
return mpn_zero_p(reinterpret_cast<const mp_limb_t*>(up), n);
}
inline void gmp_and_n_cast(uint64_t* rp, const uint64_t* up, const uint64_t* vp, mp_size_t n) {
mpn_and_n(reinterpret_cast<mp_limb_t*>(rp),
reinterpret_cast<const mp_limb_t*>(up),
reinterpret_cast<const mp_limb_t*>(vp),
n);
}
inline void gmp_com_cast(uint64_t* rp, const uint64_t* up, mp_size_t n) {
mpn_com(reinterpret_cast<mp_limb_t*>(rp),
reinterpret_cast<const mp_limb_t*>(up),
n);
}
inline void gmp_ior_n_cast(uint64_t* rp, const uint64_t* up, const uint64_t* vp, mp_size_t n) {
mpn_ior_n(reinterpret_cast<mp_limb_t*>(rp),
reinterpret_cast<const mp_limb_t*>(up),
reinterpret_cast<const mp_limb_t*>(vp),
n);
}
inline void gmp_xor_n_cast(uint64_t* rp, const uint64_t* up, const uint64_t* vp, mp_size_t n) {
mpn_xor_n(reinterpret_cast<mp_limb_t*>(rp),
reinterpret_cast<const mp_limb_t*>(up),
reinterpret_cast<const mp_limb_t*>(vp),
n);
}
// Shift Wrappers
inline mp_limb_t gmp_lshift_cast(uint64_t* rp, const uint64_t* up, mp_size_t n, unsigned int cnt) {
return mpn_lshift(reinterpret_cast<mp_limb_t*>(rp),
reinterpret_cast<const mp_limb_t*>(up),
n, cnt);
}
inline mp_limb_t gmp_rshift_cast(uint64_t* rp, const uint64_t* up, mp_size_t n, unsigned int cnt) {
return mpn_rshift(reinterpret_cast<mp_limb_t*>(rp),
reinterpret_cast<const mp_limb_t*>(up),
n, cnt);
}
// Undefine existing GMP macros
#undef mpn_add_n
#undef mpn_sub_n
#undef mpn_add_1
#undef mpn_sub_1
#undef mpn_cmp
#undef mpn_copyi
#undef mpn_mul_1
#undef mpn_addmul_1
#undef mpn_add
#undef mpn_zero_p
#undef mpn_and_n
#undef mpn_com
#undef mpn_ior_n
#undef mpn_xor_n
#undef mpn_lshift
#undef mpn_rshift
// Redefine GMP macros to wrappers
#define mpn_add_n gmp_add_n_cast
#define mpn_sub_n gmp_sub_n_cast
#define mpn_add_1 gmp_add_1_cast
#define mpn_sub_1 gmp_sub_1_cast
#define mpn_cmp gmp_cmp_cast
#define mpn_copyi gmp_copyi_cast
#define mpn_mul_1 gmp_mul_1_cast
#define mpn_addmul_1 gmp_addmul_1_cast
#define mpn_add gmp_add_cast
#define mpn_zero_p gmp_zero_p_cast
#define mpn_and_n gmp_and_n_cast
#define mpn_com gmp_com_cast
#define mpn_ior_n gmp_ior_n_cast
#define mpn_xor_n gmp_xor_n_cast
#define mpn_lshift gmp_lshift_cast
#define mpn_rshift gmp_rshift_cast
#endif // GMP_PATCH_CAST_HPP

View File

@ -0,0 +1,17 @@
CC = g++
CFLAGS = -std=c++11 -O3 -I. -I/include -Duint="unsigned int"
LDFLAGS = -L/lib -lgmp -lmman
DEPS_HPP = circom.hpp calcwit.hpp fr.hpp pol.cpp
DEPS_O = main.o calcwit.o fr.o pol.o
all: pol.exe
%.o: %.cpp $(DEPS_HPP)
$(CC) -Wno-address-of-packed-member -c $< $(CFLAGS) -o $@
pol.exe: $(DEPS_O)
$(CC) -o pol.exe $(DEPS_O) $(LDFLAGS)
clean:
rm -f *.o pol.exe

538
.github/workflows/build-circuits.yml vendored Normal file
View File

@ -0,0 +1,538 @@
name: Build Circuits
on:
push:
branches:
- main
tags:
- "v*.*.*"
workflow_dispatch:
inputs:
version:
description: "Version to release. Must follow the format of 'vX.Y.Z'."
required: true
pull_request: # For testing purposes
jobs:
setup:
name: Configure Environment
runs-on: ubuntu-latest
outputs:
version: ${{ steps.define-version.outputs.version }}
steps:
- name: Define version
id: define-version
env:
# Use the tag name if it is available, otherwise use the input version.
# If neither is available, default to the commit hash.
VERSION: ${{ github.event.release.tag_name || inputs.version }}
run: |
if [ -z "$VERSION" ]; then
echo "No version tag found. Defaulting to commit hash."
VERSION=$GITHUB_SHA
elif [[ ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "VERSION must follow the format of 'vX.Y.Z'. Value: '$VERSION'."
exit 1
fi
# Export the version to be used in the following jobs.
echo "version=$VERSION" >> $GITHUB_OUTPUT
build-linux:
name: Build Linux Binaries (Native)
runs-on: ubuntu-latest
needs:
- setup
env:
VERSION: ${{ needs.setup.outputs.version }}
OS: linux
ARCH: x86_64
steps:
- name: Install Rust Toolchain
uses: actions-rust-lang/setup-rust-toolchain@fb51252c7ba57d633bc668f941da052e410add48
with:
toolchain: stable
cache: false
- name: Install Circom
run: |
git clone https://github.com/iden3/circom.git
cd circom
RUSTFLAGS="-A dead_code" cargo build --release
RUSTFLAGS="-A dead_code" cargo install --path circom
circom --version
- name: Checkout
uses: actions/checkout@8edcb1bdb4e267140fa742c62e395cd74f332709
with:
path: repo
- name: Initialise Submodules
working-directory: repo
run: git submodule update --init --recursive
- name: Setup Dependencies
working-directory: repo/circom_circuits/rapidsnark
run: sudo apt update -y
- name: Install Dependencies [Prover]
run: sudo apt install -y build-essential cmake libgmp-dev libsodium-dev nasm curl m4
- name: Install Dependencies [Witness Generator]
run: sudo apt install nlohmann-json3-dev
- name: Compile Prover and Verifier
working-directory: repo/circom_circuits/rapidsnark
run: |
./build_gmp.sh host
make host
- name: Generate Witness Generator's C++ Circuit
working-directory: repo/circom_circuits/Mantle
run: circom --c --r1cs --no_asm --O2 pol.circom
- name: Compile Witness Generator
working-directory: repo/circom_circuits/Mantle/pol_cpp
run: make pol
- name: Bundle Rapidsnark Prover
working-directory: repo
env:
BINARY_NAME: prover
BUNDLE_NAME: prover-${{ env.OS }}-${{ env.ARCH }}
RAPIDSNARK_DIR: circom_circuits/rapidsnark/package
run: |
BUNDLE_DIR="${BUNDLE_NAME}/${BINARY_NAME}"
mkdir -p "$BUNDLE_DIR"
mv "${RAPIDSNARK_DIR}"/bin/${BINARY_NAME} "$BUNDLE_DIR/"
tar -czf "${BUNDLE_NAME}.tar.gz" "${BUNDLE_NAME}"
- name: Bundle Rapidsnark Verifier
working-directory: repo
env:
BINARY_NAME: verifier
BUNDLE_NAME: verifier-${{ env.OS }}-${{ env.ARCH }}
RAPIDSNARK_DIR: circom_circuits/rapidsnark/package
run: |
BUNDLE_DIR="${BUNDLE_NAME}/${BINARY_NAME}"
mkdir -p "$BUNDLE_DIR"
mv "${RAPIDSNARK_DIR}"/bin/${BINARY_NAME} "$BUNDLE_DIR/"
tar -czf "${BUNDLE_NAME}.tar.gz" "${BUNDLE_NAME}"
- name: Bundle Pol Witness Generator
working-directory: repo
env:
BUNDLE_NAME: pol-${{ env.OS }}-${{ env.ARCH }}
WITNESS_GENERATOR_DIR: circom_circuits/Mantle/pol_cpp
run: |
BUNDLE_DIR="${BUNDLE_NAME}/witness-generator"
mkdir -p "$BUNDLE_DIR"
mv "${WITNESS_GENERATOR_DIR}"/{pol,pol.dat} "$BUNDLE_DIR/"
tar -czf "${BUNDLE_NAME}.tar.gz" "${BUNDLE_NAME}"
- name: Upload Rapidsnark Prover
uses: actions/upload-artifact@de65e23aa2b7e23d713bb51fbfcb6d502f8667d8
with:
name: prover-${{ env.OS }}-${{ env.ARCH }}.tar.gz
path: repo/prover-${{ env.OS }}-${{ env.ARCH }}.tar.gz
- name: Upload Rapidsnark Verifier
uses: actions/upload-artifact@de65e23aa2b7e23d713bb51fbfcb6d502f8667d8
with:
name: verifier-${{ env.OS }}-${{ env.ARCH }}.tar.gz
path: repo/verifier-${{ env.OS }}-${{ env.ARCH }}.tar.gz
- name: Upload Pol Witness Generator
uses: actions/upload-artifact@de65e23aa2b7e23d713bb51fbfcb6d502f8667d8
with:
name: pol-${{ env.OS }}-${{ env.ARCH }}.tar.gz
path: repo/pol-${{ env.OS }}-${{ env.ARCH }}.tar.gz
build-windows:
name: Build Windows Binaries (Native)
runs-on: windows-latest
needs:
- setup
env:
VERSION: ${{ needs.setup.outputs.version }}
OS: windows
ARCH: x86_64
steps:
- name: Setup MSYS2
uses: msys2/setup-msys2@v2.28.0 # FIXME: Ideally use the hash to avoid supply chain attacks. Currently unable to.
with:
update: true
install: >-
base-devel
mingw-w64-x86_64-toolchain
make
git
- name: Install Rust Toolchain
uses: actions-rust-lang/setup-rust-toolchain@fb51252c7ba57d633bc668f941da052e410add48
with:
toolchain: stable
cache: false
- name: Install Circom
run: |
git clone https://github.com/iden3/circom.git
cd circom
$env:RUSTFLAGS="-A dead_code"; cargo build --release
$env:RUSTFLAGS="-A dead_code"; cargo install --path circom
circom --version
- name: Checkout
uses: actions/checkout@8edcb1bdb4e267140fa742c62e395cd74f332709
with:
path: repo
- name: Initialise Submodules
working-directory: repo
run: git submodule update --init --recursive
- name: Install Dependencies [Witness Generator]
shell: msys2 {0}
run: |
# nlohmann/json
mkdir -p /include/nlohmann/
wget -O /include/nlohmann/json.hpp https://github.com/nlohmann/json/releases/download/v3.12.0/json.hpp
# mman-win32
git clone https://github.com/alitrack/mman-win32.git
pushd mman-win32
./configure --prefix= # Path: /
make
make install
popd
- name: Install Dependencies [Prover]
shell: msys2 {0}
run: pacman --noconfirm -Sy --needed cmake nasm mingw-w64-ucrt-x86_64-libsodium
- name: Replace Prover Makefile # TODO: Make a fork generate the appropriate Windows Makefile
shell: msys2 {0}
working-directory: repo
run: cp .github/resources/prover/${{ env.OS }}.Makefile circom_circuits/rapidsnark/Makefile
- name: Replace Prover CMakeLists
shell: msys2 {0}
working-directory: repo
run: cp .github/resources/prover/${{ env.OS }}.src-CMakeLists.txt circom_circuits/rapidsnark/src/CMakeLists.txt
- name: Patch Windows mman
shell: msys2 {0}
working-directory: repo
run: cp .github/resources/prover/${{ env.OS }}.mman_patch.hpp /include/mman_patch.hpp
- name: Add uio.h headers
shell: msys2 {0}
working-directory: repo
run: cp .github/resources/prover/${{ env.OS }}.uio.h /include/sys/uio.h
- name: Replace build_gmp
shell: msys2 {0}
working-directory: repo
run: cp .github/resources/prover/${{ env.OS }}.build_gmp.sh circom_circuits/rapidsnark/build_gmp.sh
- name: Compile Prover
shell: msys2 {0}
working-directory: repo/circom_circuits/rapidsnark
run: |
./build_gmp.sh host
make host_windows_x86_64
- name: Generate Witness Generator's C++ Circuit
working-directory: repo/circom_circuits/Mantle
run: circom --c --r1cs --no_asm pol.circom
- name: Replace Witness Generator Makefile # TODO: Make a fork generate the appropriate Windows Makefile
shell: msys2 {0}
working-directory: repo
run: cp .github/resources/witness-generator/${{ env.OS }}.Makefile circom_circuits/Mantle/pol_cpp/Makefile
- name: Compile Witness Generator
shell: msys2 {0}
working-directory: repo/circom_circuits/Mantle/pol_cpp
run: make pol.exe
- name: Bundle Rapidsnark Prover
shell: msys2 {0}
working-directory: repo
env:
BINARY_NAME: prover
BUNDLE_NAME: prover-${{ env.OS }}-${{ env.ARCH }}
RAPIDSNARK_DIR: circom_circuits/rapidsnark/package
run: |
BUNDLE_DIR="${BUNDLE_NAME}/${BINARY_NAME}"
mkdir -p "$BUNDLE_DIR"
MINGW_BASE_DIR="/${MSYSTEM,,}"
MINGW_DLL_DIR="$MINGW_BASE_DIR/bin"
cp "$MINGW_DLL_DIR"/{libgcc_s_seh-1.dll,libwinpthread-1.dll,libstdc++-6.dll} "$BUNDLE_DIR/"
mv "${RAPIDSNARK_DIR}"/bin/${BINARY_NAME}.exe "$BUNDLE_DIR/"
tar -czf "${BUNDLE_NAME}.tar.gz" "${BUNDLE_NAME}"
- name: Bundle Rapidsnark Verifier
shell: msys2 {0}
working-directory: repo
env:
BINARY_NAME: verifier
BUNDLE_NAME: verifier-${{ env.OS }}-${{ env.ARCH }}
RAPIDSNARK_DIR: circom_circuits/rapidsnark/package
run: |
BUNDLE_DIR="${BUNDLE_NAME}/${BINARY_NAME}"
mkdir -p "$BUNDLE_DIR"
MINGW_BASE_DIR="/${MSYSTEM,,}"
MINGW_DLL_DIR="$MINGW_BASE_DIR/bin"
cp "$MINGW_DLL_DIR"/{libgcc_s_seh-1.dll,libwinpthread-1.dll,libstdc++-6.dll} "$BUNDLE_DIR/"
mv "${RAPIDSNARK_DIR}"/bin/${BINARY_NAME}.exe "$BUNDLE_DIR/"
tar -czf "${BUNDLE_NAME}.tar.gz" "${BUNDLE_NAME}"
- name: Bundle Pol Witness Generator
shell: msys2 {0}
working-directory: repo
env:
BUNDLE_NAME: pol-${{ env.OS }}-${{ env.ARCH }}
WITNESS_GENERATOR_DIR: circom_circuits/Mantle/pol_cpp
run: |
BUNDLE_DIR="${BUNDLE_NAME}/witness-generator"
mkdir -p "$BUNDLE_DIR"
MINGW_BASE_DIR="/${MSYSTEM,,}"
MINGW_DLL_DIR="$MINGW_BASE_DIR/bin"
cp "$MINGW_DLL_DIR"/{libgcc_s_seh-1.dll,libwinpthread-1.dll,libstdc++-6.dll,libgmp-10.dll} "$BUNDLE_DIR/"
mv "${WITNESS_GENERATOR_DIR}/pol" "$BUNDLE_DIR/pol.exe"
mv "${WITNESS_GENERATOR_DIR}/pol.dat" "$BUNDLE_DIR/pol.exe.dat"
tar -czf "${BUNDLE_NAME}.tar.gz" "${BUNDLE_NAME}"
- name: Upload Rapidsnark Prover
uses: actions/upload-artifact@de65e23aa2b7e23d713bb51fbfcb6d502f8667d8
with:
name: prover-${{ env.OS }}-${{ env.ARCH }}.tar.gz
path: repo/prover-${{ env.OS }}-${{ env.ARCH }}.tar.gz
- name: Upload Rapidsnark Verifier
uses: actions/upload-artifact@de65e23aa2b7e23d713bb51fbfcb6d502f8667d8
with:
name: verifier-${{ env.OS }}-${{ env.ARCH }}.tar.gz
path: repo/verifier-${{ env.OS }}-${{ env.ARCH }}.tar.gz
- name: Upload Pol Witness Generator
uses: actions/upload-artifact@de65e23aa2b7e23d713bb51fbfcb6d502f8667d8
with:
name: pol-${{ env.OS }}-${{ env.ARCH }}.tar.gz
path: repo/pol-${{ env.OS }}-${{ env.ARCH }}.tar.gz
build-macos:
name: Build MacOS Binaries (Native)
runs-on: macos-latest
needs:
- setup
env:
VERSION: ${{ needs.setup.outputs.version }}
ARCH: arm64
OS: macos
steps:
- name: Install Rust Toolchain
uses: actions-rust-lang/setup-rust-toolchain@fb51252c7ba57d633bc668f941da052e410add48
with:
toolchain: stable
cache: false
- name: Install Circom
run: |
git clone https://github.com/iden3/circom.git
cd circom
RUSTFLAGS="-A dead_code" cargo build --release
RUSTFLAGS="-A dead_code" cargo install --path circom
circom --version
- name: Checkout
uses: actions/checkout@8edcb1bdb4e267140fa742c62e395cd74f332709
with:
path: repo
- name: Initialise Submodules
working-directory: repo
run: git submodule update --init --recursive
- name: Setup Dependencies
run: mkdir include
- name: Install Dependencies [Witness Generator]
run: brew install nlohmann-json
- name: Install Dependencies [Prover]
run: brew install cmake nasm m4
- name: Compile Prover
working-directory: repo/circom_circuits/rapidsnark
run: |
./build_gmp.sh macos_arm64
make macos_arm64
- name: Generate Witness Generator's C++ Circuit
working-directory: repo/circom_circuits/Mantle
run: circom --c --r1cs --no_asm --O2 pol.circom
- name: Replace Witness Generator's Makefile # TODO: Make a fork generate the appropriate MacOS Makefile
working-directory: repo
run: cp .github/resources/witness-generator/${{ env.OS }}.Makefile circom_circuits/Mantle/pol_cpp/Makefile
- name: Patch MacOS GMP
working-directory: repo
run: cp .github/resources/witness-generator/${{ env.OS }}.gmp_patch.hpp circom_circuits/Mantle/pol_cpp/gmp_patch.hpp
- name: Compile Witness Generator
working-directory: repo/circom_circuits/Mantle/pol_cpp
run: make pol
- name: Bundle Rapidsnark Prover
working-directory: repo
env:
BINARY_NAME: prover
BUNDLE_NAME: prover-${{ env.OS }}-${{ env.ARCH }}
RAPIDSNARK_DIR: circom_circuits/rapidsnark/package_macos_arm64
run: |
BUNDLE_DIR="${BUNDLE_NAME}/${BINARY_NAME}"
mkdir -p "$BUNDLE_DIR"
mv "${RAPIDSNARK_DIR}/bin/${BINARY_NAME}" "$BUNDLE_DIR/"
tar -czf "${BUNDLE_NAME}.tar.gz" "${BUNDLE_NAME}"
- name: Bundle Rapidsnark Verifier
working-directory: repo
env:
BINARY_NAME: verifier
BUNDLE_NAME: verifier-${{ env.OS }}-${{ env.ARCH }}
RAPIDSNARK_DIR: circom_circuits/rapidsnark/package_macos_arm64
run: |
BUNDLE_DIR="${BUNDLE_NAME}/${BINARY_NAME}"
mkdir -p "$BUNDLE_DIR"
mv "${RAPIDSNARK_DIR}/bin/${BINARY_NAME}" "$BUNDLE_DIR/"
tar -czf "${BUNDLE_NAME}.tar.gz" "${BUNDLE_NAME}"
- name: Bundle Pol Witness Generator
working-directory: repo
env:
BUNDLE_NAME: pol-${{ env.OS }}-${{ env.ARCH }}
WITNESS_GENERATOR_DIR: circom_circuits/Mantle/pol_cpp
run: |
BUNDLE_DIR="${BUNDLE_NAME}/witness-generator"
mkdir -p "$BUNDLE_DIR"
mv "${WITNESS_GENERATOR_DIR}"/{pol,pol.dat} "$BUNDLE_DIR/"
tar -czf "${BUNDLE_NAME}.tar.gz" "${BUNDLE_NAME}"
- name: Upload Rapidsnark Prover
uses: actions/upload-artifact@de65e23aa2b7e23d713bb51fbfcb6d502f8667d8
with:
name: prover-${{ env.OS }}-${{ env.ARCH }}.tar.gz
path: repo/prover-${{ env.OS }}-${{ env.ARCH }}.tar.gz
- name: Upload Rapidsnark Verifier
uses: actions/upload-artifact@de65e23aa2b7e23d713bb51fbfcb6d502f8667d8
with:
name: verifier-${{ env.OS }}-${{ env.ARCH }}.tar.gz
path: repo/verifier-${{ env.OS }}-${{ env.ARCH }}.tar.gz
- name: Upload Pol Witness Generator
uses: actions/upload-artifact@de65e23aa2b7e23d713bb51fbfcb6d502f8667d8
with:
name: pol-${{ env.OS }}-${{ env.ARCH }}.tar.gz
path: repo/pol-${{ env.OS }}-${{ env.ARCH }}.tar.gz
publish-release:
name: Create Release
runs-on: ubuntu-latest
needs:
- setup
- build-linux
- build-windows
- build-macos
env:
VERSION: ${{ needs.setup.outputs.version }}
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
steps:
- name: Create Release
uses: actions/create-release@4c11c9fe1dcd9636620a16455165783b20fc7ea0
id: create_release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ env.VERSION }}
release_name: Circom Circuits ${{ env.VERSION }}
body: |
This is a release of Circom Circuits ${{ env.VERSION }}.
## Changelog
- feature(X): new feature
- fix(Y): bug description
- feature: performance improvement on Z
## Checklist
Before publishing please ensure:
- [ ] Description is complete
- [ ] Changelog is correct
- [ ] Assets for all platforms exist
- [ ] Pre-release is checked if necessary
- [ ] Remove this checklist before publishing the release.
draft: true
prerelease: true
upload-artifacts:
name: Upload Artifacts to Release
runs-on: ubuntu-latest
needs:
- setup
- publish-release
strategy:
fail-fast: false
matrix:
platform:
- os: linux
arch: x86_64
- os: macos
arch: arm64
- os: windows
arch: x86_64
artifact:
- prover
- verifier
- pol
env:
VERSION: ${{ needs.setup.outputs.version }}
UPLOAD_URL: ${{ needs.publish-release.outputs.upload_url }}
ARTIFACT_NAME: ${{ matrix.artifact }}-${{ matrix.platform.os }}-${{ matrix.platform.arch }}.tar.gz
steps:
- name: Download Artifacts
uses: actions/download-artifact@448e3f862ab3ef47aa50ff917776823c9946035b
with:
name: ${{ env.ARTIFACT_NAME }}
- name: Upload Artifacts to Release
uses: actions/upload-release-asset@ef2adfe8cb8ebfa540930c452c576b3819990faa
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ env.UPLOAD_URL }}
asset_path: ${{ env.ARTIFACT_NAME }}
asset_name: ${{ env.ARTIFACT_NAME }}
asset_content_type: application/octet-stream

3
.gitmodules vendored
View File

@ -1,3 +1,6 @@
[submodule "circomlib"]
path = circom_circuits/circomlib
url = https://github.com/iden3/circomlib.git
[submodule "circom_circuits/rapidsnark"]
path = circom_circuits/rapidsnark
url = https://github.com/iden3/rapidsnark

View File

@ -0,0 +1,328 @@
from sage.all import *
p = 21888242871839275222246405745257275088548364400416034343698204186575808495617
F = FiniteField(p)
def poseidon2_hash(data):
return PoseidonSponge(data,2,1)[0]
def Poseidon2_sponge_hash_rate_1(data, n):
return PoseidonSponge(data,3,2,n,1)
def Poseidon2_sponge_hash_rate_2(data, n):
return PoseidonSponge(data,3,1,n,1)
def SBox(inp):
return inp**5
def InternalRound(inp, i):
round_consts = [
0x1a1d063e54b1e764b63e1855bff015b8cedd192f47308731499573f23597d4b5,
0x26abc66f3fdf8e68839d10956259063708235dccc1aa3793b91b002c5b257c37,
0x0c7c64a9d887385381a578cfed5aed370754427aabca92a70b3c2b12ff4d7be8,
0x1cf5998769e9fab79e17f0b6d08b2d1eba2ebac30dc386b0edd383831354b495,
0x0f5e3a8566be31b7564ca60461e9e08b19828764a9669bc17aba0b97e66b0109,
0x18df6a9d19ea90d895e60e4db0794a01f359a53a180b7d4b42bf3d7a531c976e,
0x04f7bf2c5c0538ac6e4b782c3c6e601ad0ea1d3a3b9d25ef4e324055fa3123dc,
0x29c76ce22255206e3c40058523748531e770c0584aa2328ce55d54628b89ebe6,
0x198d425a45b78e85c053659ab4347f5d65b1b8e9c6108dbe00e0e945dbc5ff15,
0x25ee27ab6296cd5e6af3cc79c598a1daa7ff7f6878b3c49d49d3a9a90c3fdf74,
0x138ea8e0af41a1e024561001c0b6eb1505845d7d0c55b1b2c0f88687a96d1381,
0x306197fb3fab671ef6e7c2cba2eefd0e42851b5b9811f2ca4013370a01d95687,
0x1a0c7d52dc32a4432b66f0b4894d4f1a21db7565e5b4250486419eaf00e8f620,
0x2b46b418de80915f3ff86a8e5c8bdfccebfbe5f55163cd6caa52997da2c54a9f,
0x12d3e0dc0085873701f8b777b9673af9613a1af5db48e05bfb46e312b5829f64,
0x263390cf74dc3a8870f5002ed21d089ffb2bf768230f648dba338a5cb19b3a1f,
0x0a14f33a5fe668a60ac884b4ca607ad0f8abb5af40f96f1d7d543db52b003dcd,
0x28ead9c586513eab1a5e86509d68b2da27be3a4f01171a1dd847df829bc683b9,
0x1c6ab1c328c3c6430972031f1bdb2ac9888f0ea1abe71cffea16cda6e1a7416c,
0x1fc7e71bc0b819792b2500239f7f8de04f6decd608cb98a932346015c5b42c94,
0x03e107eb3a42b2ece380e0d860298f17c0c1e197c952650ee6dd85b93a0ddaa8,
0x2d354a251f381a4669c0d52bf88b772c46452ca57c08697f454505f6941d78cd,
0x094af88ab05d94baf687ef14bc566d1c522551d61606eda3d14b4606826f794b,
0x19705b783bf3d2dc19bcaeabf02f8ca5e1ab5b6f2e3195a9d52b2d249d1396f7,
0x09bf4acc3a8bce3f1fcc33fee54fc5b28723b16b7d740a3e60cef6852271200e,
0x1803f8200db6013c50f83c0c8fab62843413732f301f7058543a073f3f3b5e4e,
0x0f80afb5046244de30595b160b8d1f38bf6fb02d4454c0add41f7fef2faf3e5c,
0x126ee1f8504f15c3d77f0088c1cfc964abcfcf643f4a6fea7dc3f98219529d78,
0x23c203d10cfcc60f69bfb3d919552ca10ffb4ee63175ddf8ef86f991d7d0a591,
0x2a2ae15d8b143709ec0d09705fa3a6303dec1ee4eec2cf747c5a339f7744fb94,
0x07b60dee586ed6ef47e5c381ab6343ecc3d3b3006cb461bbb6b5d89081970b2b,
0x27316b559be3edfd885d95c494c1ae3d8a98a320baa7d152132cfe583c9311bd,
0x1d5c49ba157c32b8d8937cb2d3f84311ef834cc2a743ed662f5f9af0c0342e76,
0x2f8b124e78163b2f332774e0b850b5ec09c01bf6979938f67c24bd5940968488,
0x1e6843a5457416b6dc5b7aa09a9ce21b1d4cba6554e51d84665f75260113b3d5,
0x11cdf00a35f650c55fca25c9929c8ad9a68daf9ac6a189ab1f5bc79f21641d4b,
0x21632de3d3bbc5e42ef36e588158d6d4608b2815c77355b7e82b5b9b7eb560bc,
0x0de625758452efbd97b27025fbd245e0255ae48ef2a329e449d7b5c51c18498a,
0x2ad253c053e75213e2febfd4d976cc01dd9e1e1c6f0fb6b09b09546ba0838098,
0x1d6b169ed63872dc6ec7681ec39b3be93dd49cdd13c813b7d35702e38d60b077,
0x1660b740a143664bb9127c4941b67fed0be3ea70a24d5568c3a54e706cfef7fe,
0x0065a92d1de81f34114f4ca2deef76e0ceacdddb12cf879096a29f10376ccbfe,
0x1f11f065202535987367f823da7d672c353ebe2ccbc4869bcf30d50a5871040d,
0x26596f5c5dd5a5d1b437ce7b14a2c3dd3bd1d1a39b6759ba110852d17df0693e,
0x16f49bc727e45a2f7bf3056efcf8b6d38539c4163a5f1e706743db15af91860f,
0x1abe1deb45b3e3119954175efb331bf4568feaf7ea8b3dc5e1a4e7438dd39e5f,
0x0e426ccab66984d1d8993a74ca548b779f5db92aaec5f102020d34aea15fba59,
0x0e7c30c2e2e8957f4933bd1942053f1f0071684b902d534fa841924303f6a6c6,
0x0812a017ca92cf0a1622708fc7edff1d6166ded6e3528ead4c76e1f31d3fc69d,
0x21a5ade3df2bc1b5bba949d1db96040068afe5026edd7a9c2e276b47cf010d54,
0x01f3035463816c84ad711bf1a058c6c6bd101945f50e5afe72b1a5233f8749ce,
0x0b115572f038c0e2028c2aafc2d06a5e8bf2f9398dbd0fdf4dcaa82b0f0c1c8b,
0x1c38ec0b99b62fd4f0ef255543f50d2e27fc24db42bc910a3460613b6ef59e2f,
0x1c89c6d9666272e8425c3ff1f4ac737b2f5d314606a297d4b1d0b254d880c53e,
0x03326e643580356bf6d44008ae4c042a21ad4880097a5eb38b71e2311bb88f8f,
0x268076b0054fb73f67cee9ea0e51e3ad50f27a6434b5dceb5bdde2299910a4c9,
]
sb = SBox(inp[0] + round_consts[i])
out = [F(0) for i in range(3)]
out[0] = 2*sb + inp[1] + inp[2];
out[1] = sb + 2*inp[1] + inp[2];
out[2] = sb + inp[1] + 3*inp[2];
return out
def ExternalRound(inp, i):
out = [F(0) for j in range(3)]
round_consts = [ [F(0x1d066a255517b7fd8bddd3a93f7804ef7f8fcde48bb4c37a59a09a1a97052816)
, F(0x29daefb55f6f2dc6ac3f089cebcc6120b7c6fef31367b68eb7238547d32c1610)
, F(0x1f2cb1624a78ee001ecbd88ad959d7012572d76f08ec5c4f9e8b7ad7b0b4e1d1)
]
, [ F(0x0aad2e79f15735f2bd77c0ed3d14aa27b11f092a53bbc6e1db0672ded84f31e5)
, F(0x2252624f8617738cd6f661dd4094375f37028a98f1dece66091ccf1595b43f28)
, F(0x1a24913a928b38485a65a84a291da1ff91c20626524b2b87d49f4f2c9018d735)
]
, [ F(0x22fc468f1759b74d7bfc427b5f11ebb10a41515ddff497b14fd6dae1508fc47a)
, F(0x1059ca787f1f89ed9cd026e9c9ca107ae61956ff0b4121d5efd65515617f6e4d)
, F(0x02be9473358461d8f61f3536d877de982123011f0bf6f155a45cbbfae8b981ce)
]
, [ F(0x0ec96c8e32962d462778a749c82ed623aba9b669ac5b8736a1ff3a441a5084a4)
, F(0x292f906e073677405442d9553c45fa3f5a47a7cdb8c99f9648fb2e4d814df57e)
, F(0x274982444157b86726c11b9a0f5e39a5cc611160a394ea460c63f0b2ffe5657e)
]
, [ F(0x1acd63c67fbc9ab1626ed93491bda32e5da18ea9d8e4f10178d04aa6f8747ad0)
, F(0x19f8a5d670e8ab66c4e3144be58ef6901bf93375e2323ec3ca8c86cd2a28b5a5)
, F(0x1c0dc443519ad7a86efa40d2df10a011068193ea51f6c92ae1cfbb5f7b9b6893)
]
, [ F(0x14b39e7aa4068dbe50fe7190e421dc19fbeab33cb4f6a2c4180e4c3224987d3d)
, F(0x1d449b71bd826ec58f28c63ea6c561b7b820fc519f01f021afb1e35e28b0795e)
, F(0x1ea2c9a89baaddbb60fa97fe60fe9d8e89de141689d1252276524dc0a9e987fc)
]
, [ F(0x0478d66d43535a8cb57e9c1c3d6a2bd7591f9a46a0e9c058134d5cefdb3c7ff1)
, F(0x19272db71eece6a6f608f3b2717f9cd2662e26ad86c400b21cde5e4a7b00bebe)
, F(0x14226537335cab33c749c746f09208abb2dd1bd66a87ef75039be846af134166)
]
, [ F(0x01fd6af15956294f9dfe38c0d976a088b21c21e4a1c2e823f912f44961f9a9ce)
, F(0x18e5abedd626ec307bca190b8b2cab1aaee2e62ed229ba5a5ad8518d4e5f2a57)
, F(0x0fc1bbceba0590f5abbdffa6d3b35e3297c021a3a409926d0e2d54dc1c84fda6)
]]
sb = [F(0) for j in range(3)]
for j in range(3):
sb[j] = SBox(F(inp[j] + round_consts[i][j]))
out = [F(0) for j in range(3)]
out[0] = 2*sb[0] + sb[1] + sb[2]
out[1] = sb[0] + 2*sb[1] + sb[2]
out[2] = sb[0]+ sb[1] + 2*sb[2]
return out
def LinearLayer(inp):
out = [F(0) for i in range(3)]
out[0] = 2*inp[0] + inp[1] + inp[2]
out[1] = inp[0] + 2*inp[1] + inp[2]
out[2] = inp[0] + inp[1] + 2*inp[2]
return out
def Permutation(inp):
out = [F(0) for i in range(3)]
state = LinearLayer(inp)
for k in range(4):
state = ExternalRound(state, k)
for k in range(56):
state = InternalRound(state, k)
for k in range(4):
state = ExternalRound(state, k+4)
return state
def Compression(inp):
return Permutation([inp[0],inp[1],F(0)])
def PoseidonSponge(data, capacity, output_len):
rate = 3 - capacity;
output = [F(0) for i in range(output_len)]
assert( capacity > 0 )
assert( rate > 0 )
assert( capacity < 3 )
assert( rate < 3 )
# round up to rate the input + 1 field element ("10*" padding)
nblocks = ((len(data) + 1) + (rate-1)) // rate;
nout = (output_len + (rate-1)) // rate;
padded_len = nblocks * rate;
padded = []
for i in range(len(data)):
padded.append(F(data[i]))
padded.append(F(1))
for i in range(len(data)+1,padded_len):
padded.append(F(0))
civ = F(0)
state = [F(0),F(0),F(civ)]
sorbed = [F(0) for j in range(rate)]
for m in range(nblocks):
for i in range(rate):
a = state[i]
b = padded[m*rate+i]
sorbed[i] = a + b
state = Permutation(sorbed[0:rate] + state[rate:3])
q = min(rate, output_len)
for i in range(q):
output[i] = state[i]
out_ptr = rate
for n in range(1,nout):
state[nblocks+n] = Permutation(state[nblocks+n-1])
q = min(rate, output_len-out_ptr)
for i in range(q):
output[out_ptr+i] = state[nblocks+n][i]
out_ptr += rate
return output
# ———————————————————————
# Main
# ———————————————————————
if len(sys.argv) != 5:
print("Usage: python3 generate_inputs_for_poq.py <session> <core_quota> <leader_quota> <core (0) or leader (1)>")
sys.exit(1)
session = int(sys.argv[1])
Qc = int(sys.argv[2])
Ql = int(sys.argv[3])
core_or_leader = int(sys.argv[4])
if not core_or_leader in [0,1]:
print("core or leader must be 0 or 1")
sys.exit(1)
# 1) Corenode registry Merkleproof
# pick a random core_sk and derive its public key
core_sk = F(randrange(0,p,1))
pk_core = poseidon2_hash([ F(1296193216988918402894), core_sk ])
core_selectors = randrange(0,2**20,1)
core_selectors = format(int(core_selectors),'020b')
core_nodes = [F(randrange(0,p,1)) for i in range(20)]
core_root = pk_core
for i in range(20):
if int(core_selectors[19-i]) == 0:
core_root = poseidon2_hash([core_root,core_nodes[i]])
else:
core_root = poseidon2_hash([core_nodes[i],core_root])
#pk_root, core_path, core_selectors = merkle_root_and_path(pk_core, 20)
# 2) PoL inputs (broadened from pol script)
epoch_nonce = F(randrange(0, p,1))
slot_number = F(randrange(0, 2**32,1))
total_stake = F(5000)
t0 = F(0x27b6fe27507ca57ca369280400c79b5d2f58ff94d87cb0fbfc8294eb69eb1ea)
t1 = F(0x104bfd09ebdd0a57772289d0973489b62662a4dc6f09da8b4af3c5cfb1dcdd)
value = F(total_stake / 100)
threshold = (t0 + t1 * value) * value
starting_slot = randrange(max(0,slot_number-2**25+1),slot_number,1)
slot_secret = F(randrange(0,p,1))
slot_secret_indexes = format(int(slot_number - starting_slot),'025b')
tx_hash = F(randrange(0,p,1))
output_number = F(randrange(0,50,1))
slot_secret_path = [F(randrange(0,p,1)) for i in range(25)]
secret_root = slot_secret
for i in range(25):
if int(slot_secret_indexes[24-i]) == 0:
secret_root = poseidon2_hash([secret_root,slot_secret_path[i]])
else:
secret_root = poseidon2_hash([slot_secret_path[i],secret_root])
sk = poseidon2_hash([F(256174383281726064679014503048630094),starting_slot,secret_root])
pk = poseidon2_hash([F(1296193216988918402894),sk])
note_id = poseidon2_hash([F(65580641562429851895355409762135920462),tx_hash,output_number,value,pk])
ticket = poseidon2_hash([F(13887241025832268),F(epoch_nonce),F(slot_number),note_id,sk])
while(ticket > threshold):
output_number += 1
note_id = poseidon2_hash([F(65580641562429851895355409762135920462),tx_hash,output_number,value,pk])
ticket = poseidon2_hash([F(13887241025832268),F(epoch_nonce),F(slot_number),note_id,sk])
aged_nodes = [F(randrange(0,p,1)) for i in range(32)]
aged_selectors = randrange(0,2**32,1)
aged_selectors = format(aged_selectors,'032b')
aged_root = note_id
for i in range(32):
if int(aged_selectors[31-i]) == 0:
aged_root = poseidon2_hash([aged_root,aged_nodes[i]])
else:
aged_root = poseidon2_hash([aged_nodes[i],aged_root])
# 3) Choose branch & index
index = randrange(0, Ql if core_or_leader else Qc,1)
# 4) Onetime key
K_one = F(randrange(0,p,1))
K_two = F(randrange(0,p,1))
# 5) Assemble JSON
inp = {
"session": str(session),
"core_quota": str(Qc),
"leader_quota": str(Ql),
"core_root": str(core_root),
"pol_ledger_aged": str(aged_root),
"K_part_one": str(K_one),
"K_part_two": str(K_two),
"selector": str(core_or_leader),
"index": str(index),
"core_sk": str(core_sk),
"core_path": [str(x) for x in core_nodes],
"core_path_selectors": [str(x) for x in core_selectors],
"pol_sl": str(slot_number),
"pol_epoch_nonce": str(epoch_nonce),
"pol_t0": str(t0),
"pol_t1": str(t1),
"pol_slot_secret": str(slot_secret),
"pol_slot_secret_path": [str(x) for x in slot_secret_path],
"pol_noteid_path": [str(x) for x in aged_nodes],
"pol_noteid_path_selectors": [str(x) for x in aged_selectors],
"pol_note_tx_hash": str(tx_hash),
"pol_note_output_number": str(output_number),
"pol_sk_starting_slot": str(starting_slot),
"pol_note_value": str(value)
}
if core_or_leader == 0:
inp["pol_ledger_aged"] = randrange(0,p,1)
else:
inp["core_root"] = randrange(0,p,1)
import json
with open("input.json","w") as f:
json.dump(inp, f, indent=2)
print("Wrote input_poq.json")

View File

@ -0,0 +1,137 @@
// PoQ.circom
pragma circom 2.1.9;
include "../hash_bn/poseidon2_hash.circom";
include "../misc/constants.circom"; // defines NOMOS_KDF, SELECTION_RANDOMNESS, PROOF_NULLIFIER
include "../misc/comparator.circom";
include "../circomlib/circuits/bitify.circom";
include "../Mantle/pol.circom"; // defines proof_of_leadership
include "../ledger/notes.circom";
/**
* ProofOfQuota(nLevelsPK, nLevelsPol)
*
* - nLevelsPK : depth of the core-node public-key registry Merkle tree
* - nLevelsPol : depth of the slot-secret tree used in PoL (25)
* - bitsQuota : bit-width for the index comparator
*/
template ProofOfQuota(nLevelsPK, nLevelsPol, bitsQuota) {
// Public Inputs
signal input session; // session s
signal input core_quota;
signal input leader_quota;
signal input core_root;
signal input pol_ledger_aged; // PoL: aged notes root
signal input K_part_one; // Blend: one-time signature public key
signal input K_part_two; // Blend: one-time signature public key
// dummy constraints to avoid unused public input to be erased after compilation optimisation
signal dummy_one;
dummy_one <== K_part_one * K_part_one;
signal dummy_two;
dummy_two <== K_part_two * K_part_two;
signal output key_nullifier; //key_nullifier
// Private Inputs
signal input selector; // 0 = core, 1 = leader
signal input index; // nullifier index
// Core-nodes inputs
signal input core_sk; // core node secret key
signal input core_path[nLevelsPK]; // Merkle path for core PK
signal input core_path_selectors[nLevelsPK]; // path selectors (bits)
// PoL branch inputs (all the PoL private data)
signal input pol_sl;
signal input pol_epoch_nonce;
signal input pol_t0;
signal input pol_t1;
signal input pol_slot_secret;
signal input pol_slot_secret_path[nLevelsPol];
signal input pol_noteid_path[32];
signal input pol_noteid_path_selectors[32];
signal input pol_note_tx_hash;
signal input pol_note_output_number;
signal input pol_sk_starting_slot;
signal input pol_note_value;
// Constraint the selector to be a bit
selector * (1 - selector) === 0;
// Quota check: index < core_quota if core, index < leader_quota if leader
component cmp = SafeLessThan(bitsQuota);
cmp.in[0] <== index;
cmp.in[1] <== selector * (leader_quota - core_quota) + core_quota;
cmp.out === 1;
// derive zk_id
component zk_id = derive_public_key();
zk_id.secret_key <== core_sk;
// Merkleverify zk_id in core_root
component is_registered = proof_of_membership(nLevelsPK);
for (var i = 0; i < nLevelsPK; i++) {
//check that the selectors are indeed bits
core_path_selectors[i] * (1 - core_path_selectors[i]) === 0;
//call the merkle proof checker
is_registered.nodes[i] <== core_path[i];
is_registered.selector[i] <== core_path_selectors[i];
}
is_registered.root <== core_root;
is_registered.leaf <== zk_id.out;
// enforce potential PoL (without verification that the note is unspent)
// (All constraints inside pol ensure LeadershipVerify)
component would_win = would_win_leadership(nLevelsPol);
would_win.slot <== pol_sl;
would_win.epoch_nonce <== pol_epoch_nonce;
would_win.t0 <== pol_t0;
would_win.t1 <== pol_t1;
would_win.slot_secret <== pol_slot_secret;
for (var i = 0; i < nLevelsPol; i++) {
would_win.slot_secret_path[i] <== pol_slot_secret_path[i];
}
for (var i = 0; i < 32; i++) {
would_win.aged_nodes[i] <== pol_noteid_path[i];
would_win.aged_selectors[i] <== pol_noteid_path_selectors[i];
}
would_win.aged_root <== pol_ledger_aged;
would_win.transaction_hash <== pol_note_tx_hash;
would_win.output_number <== pol_note_output_number;
would_win.starting_slot <== pol_sk_starting_slot;
would_win.value <== pol_note_value;
// Enforce the selected role is correct
selector * (would_win.out - is_registered.out) + is_registered.out === 1;
// Derive selection_randomness
component selection_randomness = Poseidon2_hash(4);
component dstSel = SELECTION_RANDOMNESS_V1();
selection_randomness.inp[0] <== dstSel.out;
// choose core_sk or pol.secret_key:
selection_randomness.inp[1] <== selector * (would_win.secret_key - core_sk ) + core_sk;
selection_randomness.inp[2] <== index;
selection_randomness.inp[3] <== session;
// Derive key_nullifier
component nf = Poseidon2_hash(2);
component dstNF = KEY_NULLIFIER_V1();
nf.inp[0] <== dstNF.out;
nf.inp[1] <== selection_randomness.out;
key_nullifier <== nf.out;
}
// Instantiate with chosen depths: 20 for core PK tree, 25 for PoL secret slot tree
component main { public [ session, core_quota, leader_quota, core_root, pol_ledger_aged, K_part_one, K_part_two ] }
= ProofOfQuota(20, 25, 20);

View File

@ -1,197 +0,0 @@
/*
Copyright 2018 0KIMS association.
This file is part of circom (Zero Knowledge Circuit Compiler).
circom is a free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
circom is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with circom. If not, see <https://www.gnu.org/licenses/>.
*/
pragma circom 2.0.0;
include "montgomeryJubjub.circom";
include "jubjub.circom";
include "../../circom_circuits/circomlib/circuits/comparators.circom";
template Multiplexor2() {
signal input sel;
signal input in[2][2];
signal output out[2];
out[0] <== (in[1][0] - in[0][0])*sel + in[0][0];
out[1] <== (in[1][1] - in[0][1])*sel + in[0][1];
}
template BitElementMulAny() {
signal input sel;
signal input dblIn[2];
signal input addIn[2];
signal output dblOut[2];
signal output addOut[2];
component doubler = MontgomeryDouble();
component adder = MontgomeryAdd();
component selector = Multiplexor2();
sel ==> selector.sel;
dblIn[0] ==> doubler.in[0];
dblIn[1] ==> doubler.in[1];
doubler.out[0] ==> adder.in1[0];
doubler.out[1] ==> adder.in1[1];
addIn[0] ==> adder.in2[0];
addIn[1] ==> adder.in2[1];
addIn[0] ==> selector.in[0][0];
addIn[1] ==> selector.in[0][1];
adder.out[0] ==> selector.in[1][0];
adder.out[1] ==> selector.in[1][1];
doubler.out[0] ==> dblOut[0];
doubler.out[1] ==> dblOut[1];
selector.out[0] ==> addOut[0];
selector.out[1] ==> addOut[1];
}
// p is montgomery point
// n must be <= 248
// returns out in twisted edwards
// Double is in montgomery to be linked;
template SegmentMulAny(n) {
signal input e[n];
signal input p[2];
signal output out[2];
signal output dbl[2];
component bits[n-1];
component e2m = Edwards2Montgomery();
p[0] ==> e2m.in[0];
p[1] ==> e2m.in[1];
var i;
bits[0] = BitElementMulAny();
e2m.out[0] ==> bits[0].dblIn[0];
e2m.out[1] ==> bits[0].dblIn[1];
e2m.out[0] ==> bits[0].addIn[0];
e2m.out[1] ==> bits[0].addIn[1];
e[1] ==> bits[0].sel;
for (i=1; i<n-1; i++) {
bits[i] = BitElementMulAny();
bits[i-1].dblOut[0] ==> bits[i].dblIn[0];
bits[i-1].dblOut[1] ==> bits[i].dblIn[1];
bits[i-1].addOut[0] ==> bits[i].addIn[0];
bits[i-1].addOut[1] ==> bits[i].addIn[1];
e[i+1] ==> bits[i].sel;
}
bits[n-2].dblOut[0] ==> dbl[0];
bits[n-2].dblOut[1] ==> dbl[1];
component m2e = Montgomery2Edwards();
bits[n-2].addOut[0] ==> m2e.in[0];
bits[n-2].addOut[1] ==> m2e.in[1];
component eadder = JubjubAdd();
m2e.out[0] ==> eadder.x1;
m2e.out[1] ==> eadder.y1;
-p[0] ==> eadder.x2;
p[1] ==> eadder.y2;
component lastSel = Multiplexor2();
e[0] ==> lastSel.sel;
eadder.xout ==> lastSel.in[0][0];
eadder.yout ==> lastSel.in[0][1];
m2e.out[0] ==> lastSel.in[1][0];
m2e.out[1] ==> lastSel.in[1][1];
lastSel.out[0] ==> out[0];
lastSel.out[1] ==> out[1];
}
// This function assumes that p is in the subgroup and it is different to 0
template EscalarMulAny(n) {
signal input e[n]; // Input in binary format
signal input p[2]; // Point (Twisted format)
signal output out[2]; // Point (Twisted format)
var nsegments = (n-1)\148 +1;
var nlastsegment = n - (nsegments-1)*148;
component segments[nsegments];
component doublers[nsegments-1];
component m2e[nsegments-1];
component adders[nsegments-1];
component zeropoint = IsZero();
zeropoint.in <== p[0];
var s;
var i;
var nseg;
for (s=0; s<nsegments; s++) {
nseg = (s < nsegments-1) ? 148 : nlastsegment;
segments[s] = SegmentMulAny(nseg);
for (i=0; i<nseg; i++) {
e[s*148+i] ==> segments[s].e[i];
}
if (s==0) {
// force G8 point if input point is zero
segments[s].p[0] <== p[0] + (0x11dafe5d23e1218086a365b99fbf3d3be72f6afd7d1f72623e6b071492d1122b - p[0])*zeropoint.out;
segments[s].p[1] <== p[1] + (0x1d523cf1ddab1a1793132e78c866c0c33e26ba5cc220fed7cc3f870e59d292aa - p[1])*zeropoint.out;
} else {
doublers[s-1] = MontgomeryDouble();
m2e[s-1] = Montgomery2Edwards();
adders[s-1] = JubjubAdd();
segments[s-1].dbl[0] ==> doublers[s-1].in[0];
segments[s-1].dbl[1] ==> doublers[s-1].in[1];
doublers[s-1].out[0] ==> m2e[s-1].in[0];
doublers[s-1].out[1] ==> m2e[s-1].in[1];
m2e[s-1].out[0] ==> segments[s].p[0];
m2e[s-1].out[1] ==> segments[s].p[1];
if (s==1) {
segments[s-1].out[0] ==> adders[s-1].x1;
segments[s-1].out[1] ==> adders[s-1].y1;
} else {
adders[s-2].xout ==> adders[s-1].x1;
adders[s-2].yout ==> adders[s-1].y1;
}
segments[s].out[0] ==> adders[s-1].x2;
segments[s].out[1] ==> adders[s-1].y2;
}
}
if (nsegments == 1) {
segments[0].out[0]*(1-zeropoint.out) ==> out[0];
segments[0].out[1]+(1-segments[0].out[1])*zeropoint.out ==> out[1];
} else {
adders[nsegments-2].xout*(1-zeropoint.out) ==> out[0];
adders[nsegments-2].yout+(1-adders[nsegments-2].yout)*zeropoint.out ==> out[1];
}
}

View File

@ -1,63 +0,0 @@
/*
Copyright 2018 0KIMS association.
This file is part of circom (Zero Knowledge Circuit Compiler).
circom is a free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
circom is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with circom. If not, see <https://www.gnu.org/licenses/>.
*/
pragma circom 2.1.9;
template JubjubAdd() {
signal input x1;
signal input y1;
signal input x2;
signal input y2;
signal output xout;
signal output yout;
signal beta;
signal gamma;
signal delta;
signal tau;
var a = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000;
var d = 0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1;
beta <== x1*y2;
gamma <== y1*x2;
delta <== (-a*x1+y1)*(x2 + y2);
tau <== beta * gamma;
xout <-- (beta + gamma) / (1+ d*tau);
(1+ d*tau) * xout === (beta + gamma);
yout <-- (delta + a*beta - gamma) / (1-d*tau);
(1-d*tau)*yout === (delta + a*beta - gamma);
}
template JubjubDbl() {
signal input x;
signal input y;
signal output xout;
signal output yout;
component adder = JubjubAdd();
adder.x1 <== x;
adder.y1 <== y;
adder.x2 <== x;
adder.y2 <== y;
adder.xout ==> xout;
adder.yout ==> yout;
}

View File

@ -1,142 +0,0 @@
/*
Copyright 2018 0KIMS association.
This file is part of circom (Zero Knowledge Circuit Compiler).
circom is a free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
circom is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with circom. If not, see <https://www.gnu.org/licenses/>.
*/
/*
Source: https://en.wikipedia.org/wiki/Montgomery_curve
1 + y 1 + y
[u, v] = [ ------- , ---------- ]
1 - y (1 - y)x
*/
pragma circom 2.0.0;
template Edwards2Montgomery() {
signal input in[2];
signal output out[2];
out[0] <-- (1 + in[1]) / (1 - in[1]);
out[1] <-- out[0] / in[0];
out[0] * (1-in[1]) === (1 + in[1]);
out[1] * in[0] === out[0];
}
/*
u u - 1
[x, y] = [ ---, ------- ]
v u + 1
*/
template Montgomery2Edwards() {
signal input in[2];
signal output out[2];
out[0] <-- in[0] / in[1];
out[1] <-- (in[0] - 1) / (in[0] + 1);
out[0] * in[1] === in[0];
out[1] * (in[0] + 1) === in[0] - 1;
}
/*
x2 - x1
lamda = ---------
y2 - y1
x3 + A + x1 + x2
x3 = B * lamda^2 - A - x1 -x2 => lamda^2 = ------------------
B
y3 = (2*x1 + x2 + A)*lamda - B*lamda^3 - y1 =>
=> y3 = lamda * ( 2*x1 + x2 + A - x3 - A - x1 - x2) - y1 =>
=> y3 = lamda * ( x1 - x3 ) - y1
----------
y2 - y1
lamda = ---------
x2 - x1
x3 = B * lamda^2 - A - x1 -x2
y3 = lamda * ( x1 - x3 ) - y1
*/
template MontgomeryAdd() {
signal input in1[2];
signal input in2[2];
signal output out[2];
var a = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000;
var d = 0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1;
var A = (2 * (a + d)) / (a - d);
var B = 4 / (a - d);
signal lamda;
lamda <-- (in2[1] - in1[1]) / (in2[0] - in1[0]);
lamda * (in2[0] - in1[0]) === (in2[1] - in1[1]);
out[0] <== B*lamda*lamda - A - in1[0] -in2[0];
out[1] <== lamda * (in1[0] - out[0]) - in1[1];
}
/*
x1_2 = x1*x1
3*x1_2 + 2*A*x1 + 1
lamda = ---------------------
2*B*y1
x3 = B * lamda^2 - A - x1 -x1
y3 = lamda * ( x1 - x3 ) - y1
*/
template MontgomeryDouble() {
signal input in[2];
signal output out[2];
var a = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000;
var d = 0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1;
var A = (2 * (a + d)) / (a - d);
var B = 4 / (a - d);
signal lamda;
signal x1_2;
x1_2 <== in[0] * in[0];
lamda <-- (3*x1_2 + 2*A*in[0] + 1 ) / (2*B*in[1]);
lamda * (2*B*in[1]) === (3*x1_2 + 2*A*in[0] + 1 );
out[0] <== B*lamda*lamda - A - 2*in[0];
out[1] <== lamda * (in[0] - out[0]) - in[1];
}

View File

@ -0,0 +1,305 @@
#!/usr/bin/sage
# -*- mode: python ; -*-
from sage.all import *
p = 21888242871839275222246405745257275088548364400416034343698204186575808495617
F = FiniteField(p)
def poseidon2_hash(data):
return PoseidonSponge(data,2,1)[0]
def Poseidon2_sponge_hash_rate_1(data, n):
return PoseidonSponge(data,3,2,n,1)
def Poseidon2_sponge_hash_rate_2(data, n):
return PoseidonSponge(data,3,1,n,1)
def SBox(inp):
return inp**5
def InternalRound(inp, i):
round_consts = [
0x1a1d063e54b1e764b63e1855bff015b8cedd192f47308731499573f23597d4b5,
0x26abc66f3fdf8e68839d10956259063708235dccc1aa3793b91b002c5b257c37,
0x0c7c64a9d887385381a578cfed5aed370754427aabca92a70b3c2b12ff4d7be8,
0x1cf5998769e9fab79e17f0b6d08b2d1eba2ebac30dc386b0edd383831354b495,
0x0f5e3a8566be31b7564ca60461e9e08b19828764a9669bc17aba0b97e66b0109,
0x18df6a9d19ea90d895e60e4db0794a01f359a53a180b7d4b42bf3d7a531c976e,
0x04f7bf2c5c0538ac6e4b782c3c6e601ad0ea1d3a3b9d25ef4e324055fa3123dc,
0x29c76ce22255206e3c40058523748531e770c0584aa2328ce55d54628b89ebe6,
0x198d425a45b78e85c053659ab4347f5d65b1b8e9c6108dbe00e0e945dbc5ff15,
0x25ee27ab6296cd5e6af3cc79c598a1daa7ff7f6878b3c49d49d3a9a90c3fdf74,
0x138ea8e0af41a1e024561001c0b6eb1505845d7d0c55b1b2c0f88687a96d1381,
0x306197fb3fab671ef6e7c2cba2eefd0e42851b5b9811f2ca4013370a01d95687,
0x1a0c7d52dc32a4432b66f0b4894d4f1a21db7565e5b4250486419eaf00e8f620,
0x2b46b418de80915f3ff86a8e5c8bdfccebfbe5f55163cd6caa52997da2c54a9f,
0x12d3e0dc0085873701f8b777b9673af9613a1af5db48e05bfb46e312b5829f64,
0x263390cf74dc3a8870f5002ed21d089ffb2bf768230f648dba338a5cb19b3a1f,
0x0a14f33a5fe668a60ac884b4ca607ad0f8abb5af40f96f1d7d543db52b003dcd,
0x28ead9c586513eab1a5e86509d68b2da27be3a4f01171a1dd847df829bc683b9,
0x1c6ab1c328c3c6430972031f1bdb2ac9888f0ea1abe71cffea16cda6e1a7416c,
0x1fc7e71bc0b819792b2500239f7f8de04f6decd608cb98a932346015c5b42c94,
0x03e107eb3a42b2ece380e0d860298f17c0c1e197c952650ee6dd85b93a0ddaa8,
0x2d354a251f381a4669c0d52bf88b772c46452ca57c08697f454505f6941d78cd,
0x094af88ab05d94baf687ef14bc566d1c522551d61606eda3d14b4606826f794b,
0x19705b783bf3d2dc19bcaeabf02f8ca5e1ab5b6f2e3195a9d52b2d249d1396f7,
0x09bf4acc3a8bce3f1fcc33fee54fc5b28723b16b7d740a3e60cef6852271200e,
0x1803f8200db6013c50f83c0c8fab62843413732f301f7058543a073f3f3b5e4e,
0x0f80afb5046244de30595b160b8d1f38bf6fb02d4454c0add41f7fef2faf3e5c,
0x126ee1f8504f15c3d77f0088c1cfc964abcfcf643f4a6fea7dc3f98219529d78,
0x23c203d10cfcc60f69bfb3d919552ca10ffb4ee63175ddf8ef86f991d7d0a591,
0x2a2ae15d8b143709ec0d09705fa3a6303dec1ee4eec2cf747c5a339f7744fb94,
0x07b60dee586ed6ef47e5c381ab6343ecc3d3b3006cb461bbb6b5d89081970b2b,
0x27316b559be3edfd885d95c494c1ae3d8a98a320baa7d152132cfe583c9311bd,
0x1d5c49ba157c32b8d8937cb2d3f84311ef834cc2a743ed662f5f9af0c0342e76,
0x2f8b124e78163b2f332774e0b850b5ec09c01bf6979938f67c24bd5940968488,
0x1e6843a5457416b6dc5b7aa09a9ce21b1d4cba6554e51d84665f75260113b3d5,
0x11cdf00a35f650c55fca25c9929c8ad9a68daf9ac6a189ab1f5bc79f21641d4b,
0x21632de3d3bbc5e42ef36e588158d6d4608b2815c77355b7e82b5b9b7eb560bc,
0x0de625758452efbd97b27025fbd245e0255ae48ef2a329e449d7b5c51c18498a,
0x2ad253c053e75213e2febfd4d976cc01dd9e1e1c6f0fb6b09b09546ba0838098,
0x1d6b169ed63872dc6ec7681ec39b3be93dd49cdd13c813b7d35702e38d60b077,
0x1660b740a143664bb9127c4941b67fed0be3ea70a24d5568c3a54e706cfef7fe,
0x0065a92d1de81f34114f4ca2deef76e0ceacdddb12cf879096a29f10376ccbfe,
0x1f11f065202535987367f823da7d672c353ebe2ccbc4869bcf30d50a5871040d,
0x26596f5c5dd5a5d1b437ce7b14a2c3dd3bd1d1a39b6759ba110852d17df0693e,
0x16f49bc727e45a2f7bf3056efcf8b6d38539c4163a5f1e706743db15af91860f,
0x1abe1deb45b3e3119954175efb331bf4568feaf7ea8b3dc5e1a4e7438dd39e5f,
0x0e426ccab66984d1d8993a74ca548b779f5db92aaec5f102020d34aea15fba59,
0x0e7c30c2e2e8957f4933bd1942053f1f0071684b902d534fa841924303f6a6c6,
0x0812a017ca92cf0a1622708fc7edff1d6166ded6e3528ead4c76e1f31d3fc69d,
0x21a5ade3df2bc1b5bba949d1db96040068afe5026edd7a9c2e276b47cf010d54,
0x01f3035463816c84ad711bf1a058c6c6bd101945f50e5afe72b1a5233f8749ce,
0x0b115572f038c0e2028c2aafc2d06a5e8bf2f9398dbd0fdf4dcaa82b0f0c1c8b,
0x1c38ec0b99b62fd4f0ef255543f50d2e27fc24db42bc910a3460613b6ef59e2f,
0x1c89c6d9666272e8425c3ff1f4ac737b2f5d314606a297d4b1d0b254d880c53e,
0x03326e643580356bf6d44008ae4c042a21ad4880097a5eb38b71e2311bb88f8f,
0x268076b0054fb73f67cee9ea0e51e3ad50f27a6434b5dceb5bdde2299910a4c9,
]
sb = SBox(inp[0] + round_consts[i])
out = [F(0) for i in range(3)]
out[0] = 2*sb + inp[1] + inp[2];
out[1] = sb + 2*inp[1] + inp[2];
out[2] = sb + inp[1] + 3*inp[2];
return out
def ExternalRound(inp, i):
out = [F(0) for j in range(3)]
round_consts = [ [F(0x1d066a255517b7fd8bddd3a93f7804ef7f8fcde48bb4c37a59a09a1a97052816)
, F(0x29daefb55f6f2dc6ac3f089cebcc6120b7c6fef31367b68eb7238547d32c1610)
, F(0x1f2cb1624a78ee001ecbd88ad959d7012572d76f08ec5c4f9e8b7ad7b0b4e1d1)
]
, [ F(0x0aad2e79f15735f2bd77c0ed3d14aa27b11f092a53bbc6e1db0672ded84f31e5)
, F(0x2252624f8617738cd6f661dd4094375f37028a98f1dece66091ccf1595b43f28)
, F(0x1a24913a928b38485a65a84a291da1ff91c20626524b2b87d49f4f2c9018d735)
]
, [ F(0x22fc468f1759b74d7bfc427b5f11ebb10a41515ddff497b14fd6dae1508fc47a)
, F(0x1059ca787f1f89ed9cd026e9c9ca107ae61956ff0b4121d5efd65515617f6e4d)
, F(0x02be9473358461d8f61f3536d877de982123011f0bf6f155a45cbbfae8b981ce)
]
, [ F(0x0ec96c8e32962d462778a749c82ed623aba9b669ac5b8736a1ff3a441a5084a4)
, F(0x292f906e073677405442d9553c45fa3f5a47a7cdb8c99f9648fb2e4d814df57e)
, F(0x274982444157b86726c11b9a0f5e39a5cc611160a394ea460c63f0b2ffe5657e)
]
, [ F(0x1acd63c67fbc9ab1626ed93491bda32e5da18ea9d8e4f10178d04aa6f8747ad0)
, F(0x19f8a5d670e8ab66c4e3144be58ef6901bf93375e2323ec3ca8c86cd2a28b5a5)
, F(0x1c0dc443519ad7a86efa40d2df10a011068193ea51f6c92ae1cfbb5f7b9b6893)
]
, [ F(0x14b39e7aa4068dbe50fe7190e421dc19fbeab33cb4f6a2c4180e4c3224987d3d)
, F(0x1d449b71bd826ec58f28c63ea6c561b7b820fc519f01f021afb1e35e28b0795e)
, F(0x1ea2c9a89baaddbb60fa97fe60fe9d8e89de141689d1252276524dc0a9e987fc)
]
, [ F(0x0478d66d43535a8cb57e9c1c3d6a2bd7591f9a46a0e9c058134d5cefdb3c7ff1)
, F(0x19272db71eece6a6f608f3b2717f9cd2662e26ad86c400b21cde5e4a7b00bebe)
, F(0x14226537335cab33c749c746f09208abb2dd1bd66a87ef75039be846af134166)
]
, [ F(0x01fd6af15956294f9dfe38c0d976a088b21c21e4a1c2e823f912f44961f9a9ce)
, F(0x18e5abedd626ec307bca190b8b2cab1aaee2e62ed229ba5a5ad8518d4e5f2a57)
, F(0x0fc1bbceba0590f5abbdffa6d3b35e3297c021a3a409926d0e2d54dc1c84fda6)
]]
sb = [F(0) for j in range(3)]
for j in range(3):
sb[j] = SBox(F(inp[j] + round_consts[i][j]))
out = [F(0) for j in range(3)]
out[0] = 2*sb[0] + sb[1] + sb[2]
out[1] = sb[0] + 2*sb[1] + sb[2]
out[2] = sb[0]+ sb[1] + 2*sb[2]
return out
def LinearLayer(inp):
out = [F(0) for i in range(3)]
out[0] = 2*inp[0] + inp[1] + inp[2]
out[1] = inp[0] + 2*inp[1] + inp[2]
out[2] = inp[0] + inp[1] + 2*inp[2]
return out
def Permutation(inp):
out = [F(0) for i in range(3)]
state = LinearLayer(inp)
for k in range(4):
state = ExternalRound(state, k)
for k in range(56):
state = InternalRound(state, k)
for k in range(4):
state = ExternalRound(state, k+4)
return state
def Compression(inp):
return Permutation([inp[0],inp[1],F(0)])
def PoseidonSponge(data, capacity, output_len):
rate = 3 - capacity;
output = [F(0) for i in range(output_len)]
assert( capacity > 0 )
assert( rate > 0 )
assert( capacity < 3 )
assert( rate < 3 )
# round up to rate the input + 1 field element ("10*" padding)
nblocks = ((len(data) + 1) + (rate-1)) // rate;
nout = (output_len + (rate-1)) // rate;
padded_len = nblocks * rate;
padded = []
for i in range(len(data)):
padded.append(F(data[i]))
padded.append(F(1))
for i in range(len(data)+1,padded_len):
padded.append(F(0))
civ = F(0)
state = [F(0),F(0),F(civ)]
sorbed = [F(0) for j in range(rate)]
for m in range(nblocks):
for i in range(rate):
a = state[i]
b = padded[m*rate+i]
sorbed[i] = a + b
state = Permutation(sorbed[0:rate] + state[rate:3])
q = min(rate, output_len)
for i in range(q):
output[i] = state[i]
out_ptr = rate
for n in range(1,nout):
state[nblocks+n] = Permutation(state[nblocks+n-1])
q = min(rate, output_len-out_ptr)
for i in range(q):
output[out_ptr+i] = state[nblocks+n][i]
out_ptr += rate
return output
if len(sys.argv) != Integer(4):
print("Usage: <script> <epoch_nonce> <slot_number> <total_stake>")
exit()
epoch_nonce = int(sys.argv[Integer(1)])
slot_number = int(sys.argv[Integer(2)])
total_stake = int(sys.argv[Integer(3)])
if epoch_nonce >= p:
print("epoch nonce must be less than p")
exit()
if total_stake >= p:
print("total stake must be less than p")
exit()
t0 = F(0x27b6fe27507ca57ca369280400c79b5d2f58ff94d87cb0fbfc8294eb69eb1ea)
t1 = F(0x104bfd09ebdd0a57772289d0973489b62662a4dc6f09da8b4af3c5cfb1dcdd)
value = F(total_stake / 100)
threshold = (t0 + t1 * value) * value
starting_slot = randrange(max(0,slot_number-2**25+1),slot_number,1)
slot_secret = F(randrange(0,p,1))
slot_secret_indexes = format(int(slot_number - starting_slot),'025b')
tx_hash = F(randrange(0,p,1))
output_number = F(randrange(0,50,1))
slot_secret_path = [F(randrange(0,p,1)) for i in range(25)]
secret_root = slot_secret
for i in range(25):
if int(slot_secret_indexes[24-i]) == 0:
secret_root = poseidon2_hash([secret_root,slot_secret_path[i]])
else:
secret_root = poseidon2_hash([slot_secret_path[i],secret_root])
sk = poseidon2_hash([F(256174383281726064679014503048630094),starting_slot,secret_root])
pk = poseidon2_hash([F(1296193216988918402894),sk])
note_id = poseidon2_hash([F(65580641562429851895355409762135920462),tx_hash,output_number,value,pk])
ticket = poseidon2_hash([F(13887241025832268),F(epoch_nonce),F(slot_number),note_id,sk])
while(ticket > threshold):
output_number += 1
note_id = poseidon2_hash([F(65580641562429851895355409762135920462),tx_hash,output_number,value,pk])
ticket = poseidon2_hash([F(13887241025832268),F(epoch_nonce),F(slot_number),note_id,sk])
aged_nodes = [F(randrange(0,p,1)) for i in range(32)]
aged_selectors = randrange(0,2**32,1)
aged_selectors = format(aged_selectors,'032b')
aged_root = note_id
for i in range(32):
if int(aged_selectors[31-i]) == 0:
aged_root = poseidon2_hash([aged_root,aged_nodes[i]])
else:
aged_root = poseidon2_hash([aged_nodes[i],aged_root])
unspent_nodes = [F(randrange(0,p,1)) for i in range(32)]
unspent_selectors = randrange(0,2**32,1)
unspent_selectors = format(unspent_selectors,'032b')
latest_root = note_id
for i in range(32):
if int(unspent_selectors[31-i]) == 0:
latest_root = poseidon2_hash([latest_root,unspent_nodes[i]])
else:
latest_root = poseidon2_hash([unspent_nodes[i],latest_root])
# 5) Assemble JSON
inp = {
"sl": str(slot_number),
"epoch_nonce": str(epoch_nonce),
"t0": str(t0),
"t1": str(t1),
"slot_secret": str(slot_secret),
"P_lead_part_one": str(F(123456)),
"P_lead_part_two": str(F(654321)),
"slot_secret_path": [str(x) for x in slot_secret_path],
"noteid_aged_path": [str(x) for x in aged_nodes],
"noteid_aged_selectors": [str(x) for x in aged_selectors],
"ledger_aged": str(aged_root),
"note_tx_hash": str(tx_hash),
"note_output_number": str(output_number),
"noteid_latest_path": [str(x) for x in unspent_nodes],
"noteid_latest_selectors": [str(x) for x in unspent_selectors],
"ledger_latest": str(latest_root),
"starting_slot": str(starting_slot),
"v": str(value)
}
import json
with open("input.json","w") as f:
json.dump(inp, f, indent=2)
print("Wrote input of pol")

View File

@ -0,0 +1,238 @@
#!/usr/bin/sage
# -*- mode: python ; -*-
from sage.all import *
p = 21888242871839275222246405745257275088548364400416034343698204186575808495617
F = FiniteField(p)
def poseidon2_hash(data):
return PoseidonSponge(data,2,1)[0]
def Poseidon2_sponge_hash_rate_1(data, n):
return PoseidonSponge(data,3,2,n,1)
def Poseidon2_sponge_hash_rate_2(data, n):
return PoseidonSponge(data,3,1,n,1)
def SBox(inp):
return inp**5
def InternalRound(inp, i):
round_consts = [
0x1a1d063e54b1e764b63e1855bff015b8cedd192f47308731499573f23597d4b5,
0x26abc66f3fdf8e68839d10956259063708235dccc1aa3793b91b002c5b257c37,
0x0c7c64a9d887385381a578cfed5aed370754427aabca92a70b3c2b12ff4d7be8,
0x1cf5998769e9fab79e17f0b6d08b2d1eba2ebac30dc386b0edd383831354b495,
0x0f5e3a8566be31b7564ca60461e9e08b19828764a9669bc17aba0b97e66b0109,
0x18df6a9d19ea90d895e60e4db0794a01f359a53a180b7d4b42bf3d7a531c976e,
0x04f7bf2c5c0538ac6e4b782c3c6e601ad0ea1d3a3b9d25ef4e324055fa3123dc,
0x29c76ce22255206e3c40058523748531e770c0584aa2328ce55d54628b89ebe6,
0x198d425a45b78e85c053659ab4347f5d65b1b8e9c6108dbe00e0e945dbc5ff15,
0x25ee27ab6296cd5e6af3cc79c598a1daa7ff7f6878b3c49d49d3a9a90c3fdf74,
0x138ea8e0af41a1e024561001c0b6eb1505845d7d0c55b1b2c0f88687a96d1381,
0x306197fb3fab671ef6e7c2cba2eefd0e42851b5b9811f2ca4013370a01d95687,
0x1a0c7d52dc32a4432b66f0b4894d4f1a21db7565e5b4250486419eaf00e8f620,
0x2b46b418de80915f3ff86a8e5c8bdfccebfbe5f55163cd6caa52997da2c54a9f,
0x12d3e0dc0085873701f8b777b9673af9613a1af5db48e05bfb46e312b5829f64,
0x263390cf74dc3a8870f5002ed21d089ffb2bf768230f648dba338a5cb19b3a1f,
0x0a14f33a5fe668a60ac884b4ca607ad0f8abb5af40f96f1d7d543db52b003dcd,
0x28ead9c586513eab1a5e86509d68b2da27be3a4f01171a1dd847df829bc683b9,
0x1c6ab1c328c3c6430972031f1bdb2ac9888f0ea1abe71cffea16cda6e1a7416c,
0x1fc7e71bc0b819792b2500239f7f8de04f6decd608cb98a932346015c5b42c94,
0x03e107eb3a42b2ece380e0d860298f17c0c1e197c952650ee6dd85b93a0ddaa8,
0x2d354a251f381a4669c0d52bf88b772c46452ca57c08697f454505f6941d78cd,
0x094af88ab05d94baf687ef14bc566d1c522551d61606eda3d14b4606826f794b,
0x19705b783bf3d2dc19bcaeabf02f8ca5e1ab5b6f2e3195a9d52b2d249d1396f7,
0x09bf4acc3a8bce3f1fcc33fee54fc5b28723b16b7d740a3e60cef6852271200e,
0x1803f8200db6013c50f83c0c8fab62843413732f301f7058543a073f3f3b5e4e,
0x0f80afb5046244de30595b160b8d1f38bf6fb02d4454c0add41f7fef2faf3e5c,
0x126ee1f8504f15c3d77f0088c1cfc964abcfcf643f4a6fea7dc3f98219529d78,
0x23c203d10cfcc60f69bfb3d919552ca10ffb4ee63175ddf8ef86f991d7d0a591,
0x2a2ae15d8b143709ec0d09705fa3a6303dec1ee4eec2cf747c5a339f7744fb94,
0x07b60dee586ed6ef47e5c381ab6343ecc3d3b3006cb461bbb6b5d89081970b2b,
0x27316b559be3edfd885d95c494c1ae3d8a98a320baa7d152132cfe583c9311bd,
0x1d5c49ba157c32b8d8937cb2d3f84311ef834cc2a743ed662f5f9af0c0342e76,
0x2f8b124e78163b2f332774e0b850b5ec09c01bf6979938f67c24bd5940968488,
0x1e6843a5457416b6dc5b7aa09a9ce21b1d4cba6554e51d84665f75260113b3d5,
0x11cdf00a35f650c55fca25c9929c8ad9a68daf9ac6a189ab1f5bc79f21641d4b,
0x21632de3d3bbc5e42ef36e588158d6d4608b2815c77355b7e82b5b9b7eb560bc,
0x0de625758452efbd97b27025fbd245e0255ae48ef2a329e449d7b5c51c18498a,
0x2ad253c053e75213e2febfd4d976cc01dd9e1e1c6f0fb6b09b09546ba0838098,
0x1d6b169ed63872dc6ec7681ec39b3be93dd49cdd13c813b7d35702e38d60b077,
0x1660b740a143664bb9127c4941b67fed0be3ea70a24d5568c3a54e706cfef7fe,
0x0065a92d1de81f34114f4ca2deef76e0ceacdddb12cf879096a29f10376ccbfe,
0x1f11f065202535987367f823da7d672c353ebe2ccbc4869bcf30d50a5871040d,
0x26596f5c5dd5a5d1b437ce7b14a2c3dd3bd1d1a39b6759ba110852d17df0693e,
0x16f49bc727e45a2f7bf3056efcf8b6d38539c4163a5f1e706743db15af91860f,
0x1abe1deb45b3e3119954175efb331bf4568feaf7ea8b3dc5e1a4e7438dd39e5f,
0x0e426ccab66984d1d8993a74ca548b779f5db92aaec5f102020d34aea15fba59,
0x0e7c30c2e2e8957f4933bd1942053f1f0071684b902d534fa841924303f6a6c6,
0x0812a017ca92cf0a1622708fc7edff1d6166ded6e3528ead4c76e1f31d3fc69d,
0x21a5ade3df2bc1b5bba949d1db96040068afe5026edd7a9c2e276b47cf010d54,
0x01f3035463816c84ad711bf1a058c6c6bd101945f50e5afe72b1a5233f8749ce,
0x0b115572f038c0e2028c2aafc2d06a5e8bf2f9398dbd0fdf4dcaa82b0f0c1c8b,
0x1c38ec0b99b62fd4f0ef255543f50d2e27fc24db42bc910a3460613b6ef59e2f,
0x1c89c6d9666272e8425c3ff1f4ac737b2f5d314606a297d4b1d0b254d880c53e,
0x03326e643580356bf6d44008ae4c042a21ad4880097a5eb38b71e2311bb88f8f,
0x268076b0054fb73f67cee9ea0e51e3ad50f27a6434b5dceb5bdde2299910a4c9,
]
sb = SBox(inp[0] + round_consts[i])
out = [F(0) for i in range(3)]
out[0] = 2*sb + inp[1] + inp[2];
out[1] = sb + 2*inp[1] + inp[2];
out[2] = sb + inp[1] + 3*inp[2];
return out
def ExternalRound(inp, i):
out = [F(0) for j in range(3)]
round_consts = [ [F(0x1d066a255517b7fd8bddd3a93f7804ef7f8fcde48bb4c37a59a09a1a97052816)
, F(0x29daefb55f6f2dc6ac3f089cebcc6120b7c6fef31367b68eb7238547d32c1610)
, F(0x1f2cb1624a78ee001ecbd88ad959d7012572d76f08ec5c4f9e8b7ad7b0b4e1d1)
]
, [ F(0x0aad2e79f15735f2bd77c0ed3d14aa27b11f092a53bbc6e1db0672ded84f31e5)
, F(0x2252624f8617738cd6f661dd4094375f37028a98f1dece66091ccf1595b43f28)
, F(0x1a24913a928b38485a65a84a291da1ff91c20626524b2b87d49f4f2c9018d735)
]
, [ F(0x22fc468f1759b74d7bfc427b5f11ebb10a41515ddff497b14fd6dae1508fc47a)
, F(0x1059ca787f1f89ed9cd026e9c9ca107ae61956ff0b4121d5efd65515617f6e4d)
, F(0x02be9473358461d8f61f3536d877de982123011f0bf6f155a45cbbfae8b981ce)
]
, [ F(0x0ec96c8e32962d462778a749c82ed623aba9b669ac5b8736a1ff3a441a5084a4)
, F(0x292f906e073677405442d9553c45fa3f5a47a7cdb8c99f9648fb2e4d814df57e)
, F(0x274982444157b86726c11b9a0f5e39a5cc611160a394ea460c63f0b2ffe5657e)
]
, [ F(0x1acd63c67fbc9ab1626ed93491bda32e5da18ea9d8e4f10178d04aa6f8747ad0)
, F(0x19f8a5d670e8ab66c4e3144be58ef6901bf93375e2323ec3ca8c86cd2a28b5a5)
, F(0x1c0dc443519ad7a86efa40d2df10a011068193ea51f6c92ae1cfbb5f7b9b6893)
]
, [ F(0x14b39e7aa4068dbe50fe7190e421dc19fbeab33cb4f6a2c4180e4c3224987d3d)
, F(0x1d449b71bd826ec58f28c63ea6c561b7b820fc519f01f021afb1e35e28b0795e)
, F(0x1ea2c9a89baaddbb60fa97fe60fe9d8e89de141689d1252276524dc0a9e987fc)
]
, [ F(0x0478d66d43535a8cb57e9c1c3d6a2bd7591f9a46a0e9c058134d5cefdb3c7ff1)
, F(0x19272db71eece6a6f608f3b2717f9cd2662e26ad86c400b21cde5e4a7b00bebe)
, F(0x14226537335cab33c749c746f09208abb2dd1bd66a87ef75039be846af134166)
]
, [ F(0x01fd6af15956294f9dfe38c0d976a088b21c21e4a1c2e823f912f44961f9a9ce)
, F(0x18e5abedd626ec307bca190b8b2cab1aaee2e62ed229ba5a5ad8518d4e5f2a57)
, F(0x0fc1bbceba0590f5abbdffa6d3b35e3297c021a3a409926d0e2d54dc1c84fda6)
]]
sb = [F(0) for j in range(3)]
for j in range(3):
sb[j] = SBox(F(inp[j] + round_consts[i][j]))
out = [F(0) for j in range(3)]
out[0] = 2*sb[0] + sb[1] + sb[2]
out[1] = sb[0] + 2*sb[1] + sb[2]
out[2] = sb[0]+ sb[1] + 2*sb[2]
return out
def LinearLayer(inp):
out = [F(0) for i in range(3)]
out[0] = 2*inp[0] + inp[1] + inp[2]
out[1] = inp[0] + 2*inp[1] + inp[2]
out[2] = inp[0] + inp[1] + 2*inp[2]
return out
def Permutation(inp):
out = [F(0) for i in range(3)]
state = LinearLayer(inp)
for k in range(4):
state = ExternalRound(state, k)
for k in range(56):
state = InternalRound(state, k)
for k in range(4):
state = ExternalRound(state, k+4)
return state
def Compression(inp):
return Permutation([inp[0],inp[1],F(0)])
def PoseidonSponge(data, capacity, output_len):
rate = 3 - capacity;
output = [F(0) for i in range(output_len)]
assert( capacity > 0 )
assert( rate > 0 )
assert( capacity < 3 )
assert( rate < 3 )
# round up to rate the input + 1 field element ("10*" padding)
nblocks = ((len(data) + 1) + (rate-1)) // rate;
nout = (output_len + (rate-1)) // rate;
padded_len = nblocks * rate;
padded = []
for i in range(len(data)):
padded.append(F(data[i]))
padded.append(F(1))
for i in range(len(data)+1,padded_len):
padded.append(F(0))
civ = F(0)
state = [F(0),F(0),F(civ)]
sorbed = [F(0) for j in range(rate)]
for m in range(nblocks):
for i in range(rate):
a = state[i]
b = padded[m*rate+i]
sorbed[i] = a + b
state = Permutation(sorbed[0:rate] + state[rate:3])
q = min(rate, output_len)
for i in range(q):
output[i] = state[i]
out_ptr = rate
for n in range(1,nout):
state[nblocks+n] = Permutation(state[nblocks+n-1])
q = min(rate, output_len-out_ptr)
for i in range(q):
output[out_ptr+i] = state[nblocks+n][i]
out_ptr += rate
return output
secret_voucher = F(randrange(0,p,1))
reward_voucher = poseidon2_hash([F(1668646695034522932676805048878418),secret_voucher])
merkle_nodes = [F(randrange(0,p,1)) for i in range(32)]
selectors = randrange(0,2**32,1)
selectors = format(selectors,'032b')
voucher_root = reward_voucher
for i in range(32):
if int(selectors[31-i]) == 0:
voucher_root = poseidon2_hash([voucher_root,merkle_nodes[i]])
else:
voucher_root = poseidon2_hash([merkle_nodes[i],voucher_root])
data_msg = F(randrange(0,p,1))
inp = {
"secret_voucher": str(secret_voucher),
"voucher_merkle_path":[str(x) for x in merkle_nodes],
"voucher_merkle_path_selectors": [str(x) for x in selectors],
"mantle_tx_hash": str(data_msg),
"voucher_root": str(voucher_root)
}
import json
with open("input.json","w") as f:
json.dump(inp, f, indent=2)
print("Wrote input of proof of claim")

View File

@ -0,0 +1,232 @@
#!/usr/bin/sage
# -*- mode: python ; -*-
from sage.all import *
p = 21888242871839275222246405745257275088548364400416034343698204186575808495617
F = FiniteField(p)
def poseidon2_hash(data):
return PoseidonSponge(data,2,1)[0]
def Poseidon2_sponge_hash_rate_1(data, n):
return PoseidonSponge(data,3,2,n,1)
def Poseidon2_sponge_hash_rate_2(data, n):
return PoseidonSponge(data,3,1,n,1)
def SBox(inp):
return inp**5
def InternalRound(inp, i):
round_consts = [
0x1a1d063e54b1e764b63e1855bff015b8cedd192f47308731499573f23597d4b5,
0x26abc66f3fdf8e68839d10956259063708235dccc1aa3793b91b002c5b257c37,
0x0c7c64a9d887385381a578cfed5aed370754427aabca92a70b3c2b12ff4d7be8,
0x1cf5998769e9fab79e17f0b6d08b2d1eba2ebac30dc386b0edd383831354b495,
0x0f5e3a8566be31b7564ca60461e9e08b19828764a9669bc17aba0b97e66b0109,
0x18df6a9d19ea90d895e60e4db0794a01f359a53a180b7d4b42bf3d7a531c976e,
0x04f7bf2c5c0538ac6e4b782c3c6e601ad0ea1d3a3b9d25ef4e324055fa3123dc,
0x29c76ce22255206e3c40058523748531e770c0584aa2328ce55d54628b89ebe6,
0x198d425a45b78e85c053659ab4347f5d65b1b8e9c6108dbe00e0e945dbc5ff15,
0x25ee27ab6296cd5e6af3cc79c598a1daa7ff7f6878b3c49d49d3a9a90c3fdf74,
0x138ea8e0af41a1e024561001c0b6eb1505845d7d0c55b1b2c0f88687a96d1381,
0x306197fb3fab671ef6e7c2cba2eefd0e42851b5b9811f2ca4013370a01d95687,
0x1a0c7d52dc32a4432b66f0b4894d4f1a21db7565e5b4250486419eaf00e8f620,
0x2b46b418de80915f3ff86a8e5c8bdfccebfbe5f55163cd6caa52997da2c54a9f,
0x12d3e0dc0085873701f8b777b9673af9613a1af5db48e05bfb46e312b5829f64,
0x263390cf74dc3a8870f5002ed21d089ffb2bf768230f648dba338a5cb19b3a1f,
0x0a14f33a5fe668a60ac884b4ca607ad0f8abb5af40f96f1d7d543db52b003dcd,
0x28ead9c586513eab1a5e86509d68b2da27be3a4f01171a1dd847df829bc683b9,
0x1c6ab1c328c3c6430972031f1bdb2ac9888f0ea1abe71cffea16cda6e1a7416c,
0x1fc7e71bc0b819792b2500239f7f8de04f6decd608cb98a932346015c5b42c94,
0x03e107eb3a42b2ece380e0d860298f17c0c1e197c952650ee6dd85b93a0ddaa8,
0x2d354a251f381a4669c0d52bf88b772c46452ca57c08697f454505f6941d78cd,
0x094af88ab05d94baf687ef14bc566d1c522551d61606eda3d14b4606826f794b,
0x19705b783bf3d2dc19bcaeabf02f8ca5e1ab5b6f2e3195a9d52b2d249d1396f7,
0x09bf4acc3a8bce3f1fcc33fee54fc5b28723b16b7d740a3e60cef6852271200e,
0x1803f8200db6013c50f83c0c8fab62843413732f301f7058543a073f3f3b5e4e,
0x0f80afb5046244de30595b160b8d1f38bf6fb02d4454c0add41f7fef2faf3e5c,
0x126ee1f8504f15c3d77f0088c1cfc964abcfcf643f4a6fea7dc3f98219529d78,
0x23c203d10cfcc60f69bfb3d919552ca10ffb4ee63175ddf8ef86f991d7d0a591,
0x2a2ae15d8b143709ec0d09705fa3a6303dec1ee4eec2cf747c5a339f7744fb94,
0x07b60dee586ed6ef47e5c381ab6343ecc3d3b3006cb461bbb6b5d89081970b2b,
0x27316b559be3edfd885d95c494c1ae3d8a98a320baa7d152132cfe583c9311bd,
0x1d5c49ba157c32b8d8937cb2d3f84311ef834cc2a743ed662f5f9af0c0342e76,
0x2f8b124e78163b2f332774e0b850b5ec09c01bf6979938f67c24bd5940968488,
0x1e6843a5457416b6dc5b7aa09a9ce21b1d4cba6554e51d84665f75260113b3d5,
0x11cdf00a35f650c55fca25c9929c8ad9a68daf9ac6a189ab1f5bc79f21641d4b,
0x21632de3d3bbc5e42ef36e588158d6d4608b2815c77355b7e82b5b9b7eb560bc,
0x0de625758452efbd97b27025fbd245e0255ae48ef2a329e449d7b5c51c18498a,
0x2ad253c053e75213e2febfd4d976cc01dd9e1e1c6f0fb6b09b09546ba0838098,
0x1d6b169ed63872dc6ec7681ec39b3be93dd49cdd13c813b7d35702e38d60b077,
0x1660b740a143664bb9127c4941b67fed0be3ea70a24d5568c3a54e706cfef7fe,
0x0065a92d1de81f34114f4ca2deef76e0ceacdddb12cf879096a29f10376ccbfe,
0x1f11f065202535987367f823da7d672c353ebe2ccbc4869bcf30d50a5871040d,
0x26596f5c5dd5a5d1b437ce7b14a2c3dd3bd1d1a39b6759ba110852d17df0693e,
0x16f49bc727e45a2f7bf3056efcf8b6d38539c4163a5f1e706743db15af91860f,
0x1abe1deb45b3e3119954175efb331bf4568feaf7ea8b3dc5e1a4e7438dd39e5f,
0x0e426ccab66984d1d8993a74ca548b779f5db92aaec5f102020d34aea15fba59,
0x0e7c30c2e2e8957f4933bd1942053f1f0071684b902d534fa841924303f6a6c6,
0x0812a017ca92cf0a1622708fc7edff1d6166ded6e3528ead4c76e1f31d3fc69d,
0x21a5ade3df2bc1b5bba949d1db96040068afe5026edd7a9c2e276b47cf010d54,
0x01f3035463816c84ad711bf1a058c6c6bd101945f50e5afe72b1a5233f8749ce,
0x0b115572f038c0e2028c2aafc2d06a5e8bf2f9398dbd0fdf4dcaa82b0f0c1c8b,
0x1c38ec0b99b62fd4f0ef255543f50d2e27fc24db42bc910a3460613b6ef59e2f,
0x1c89c6d9666272e8425c3ff1f4ac737b2f5d314606a297d4b1d0b254d880c53e,
0x03326e643580356bf6d44008ae4c042a21ad4880097a5eb38b71e2311bb88f8f,
0x268076b0054fb73f67cee9ea0e51e3ad50f27a6434b5dceb5bdde2299910a4c9,
]
sb = SBox(inp[0] + round_consts[i])
out = [F(0) for i in range(3)]
out[0] = 2*sb + inp[1] + inp[2];
out[1] = sb + 2*inp[1] + inp[2];
out[2] = sb + inp[1] + 3*inp[2];
return out
def ExternalRound(inp, i):
out = [F(0) for j in range(3)]
round_consts = [ [F(0x1d066a255517b7fd8bddd3a93f7804ef7f8fcde48bb4c37a59a09a1a97052816)
, F(0x29daefb55f6f2dc6ac3f089cebcc6120b7c6fef31367b68eb7238547d32c1610)
, F(0x1f2cb1624a78ee001ecbd88ad959d7012572d76f08ec5c4f9e8b7ad7b0b4e1d1)
]
, [ F(0x0aad2e79f15735f2bd77c0ed3d14aa27b11f092a53bbc6e1db0672ded84f31e5)
, F(0x2252624f8617738cd6f661dd4094375f37028a98f1dece66091ccf1595b43f28)
, F(0x1a24913a928b38485a65a84a291da1ff91c20626524b2b87d49f4f2c9018d735)
]
, [ F(0x22fc468f1759b74d7bfc427b5f11ebb10a41515ddff497b14fd6dae1508fc47a)
, F(0x1059ca787f1f89ed9cd026e9c9ca107ae61956ff0b4121d5efd65515617f6e4d)
, F(0x02be9473358461d8f61f3536d877de982123011f0bf6f155a45cbbfae8b981ce)
]
, [ F(0x0ec96c8e32962d462778a749c82ed623aba9b669ac5b8736a1ff3a441a5084a4)
, F(0x292f906e073677405442d9553c45fa3f5a47a7cdb8c99f9648fb2e4d814df57e)
, F(0x274982444157b86726c11b9a0f5e39a5cc611160a394ea460c63f0b2ffe5657e)
]
, [ F(0x1acd63c67fbc9ab1626ed93491bda32e5da18ea9d8e4f10178d04aa6f8747ad0)
, F(0x19f8a5d670e8ab66c4e3144be58ef6901bf93375e2323ec3ca8c86cd2a28b5a5)
, F(0x1c0dc443519ad7a86efa40d2df10a011068193ea51f6c92ae1cfbb5f7b9b6893)
]
, [ F(0x14b39e7aa4068dbe50fe7190e421dc19fbeab33cb4f6a2c4180e4c3224987d3d)
, F(0x1d449b71bd826ec58f28c63ea6c561b7b820fc519f01f021afb1e35e28b0795e)
, F(0x1ea2c9a89baaddbb60fa97fe60fe9d8e89de141689d1252276524dc0a9e987fc)
]
, [ F(0x0478d66d43535a8cb57e9c1c3d6a2bd7591f9a46a0e9c058134d5cefdb3c7ff1)
, F(0x19272db71eece6a6f608f3b2717f9cd2662e26ad86c400b21cde5e4a7b00bebe)
, F(0x14226537335cab33c749c746f09208abb2dd1bd66a87ef75039be846af134166)
]
, [ F(0x01fd6af15956294f9dfe38c0d976a088b21c21e4a1c2e823f912f44961f9a9ce)
, F(0x18e5abedd626ec307bca190b8b2cab1aaee2e62ed229ba5a5ad8518d4e5f2a57)
, F(0x0fc1bbceba0590f5abbdffa6d3b35e3297c021a3a409926d0e2d54dc1c84fda6)
]]
sb = [F(0) for j in range(3)]
for j in range(3):
sb[j] = SBox(F(inp[j] + round_consts[i][j]))
out = [F(0) for j in range(3)]
out[0] = 2*sb[0] + sb[1] + sb[2]
out[1] = sb[0] + 2*sb[1] + sb[2]
out[2] = sb[0]+ sb[1] + 2*sb[2]
return out
def LinearLayer(inp):
out = [F(0) for i in range(3)]
out[0] = 2*inp[0] + inp[1] + inp[2]
out[1] = inp[0] + 2*inp[1] + inp[2]
out[2] = inp[0] + inp[1] + 2*inp[2]
return out
def Permutation(inp):
out = [F(0) for i in range(3)]
state = LinearLayer(inp)
for k in range(4):
state = ExternalRound(state, k)
for k in range(56):
state = InternalRound(state, k)
for k in range(4):
state = ExternalRound(state, k+4)
return state
def Compression(inp):
return Permutation([inp[0],inp[1],F(0)])
def PoseidonSponge(data, capacity, output_len):
rate = 3 - capacity;
output = [F(0) for i in range(output_len)]
assert( capacity > 0 )
assert( rate > 0 )
assert( capacity < 3 )
assert( rate < 3 )
# round up to rate the input + 1 field element ("10*" padding)
nblocks = ((len(data) + 1) + (rate-1)) // rate;
nout = (output_len + (rate-1)) // rate;
padded_len = nblocks * rate;
padded = []
for i in range(len(data)):
padded.append(F(data[i]))
padded.append(F(1))
for i in range(len(data)+1,padded_len):
padded.append(F(0))
civ = F(0)
state = [F(0),F(0),F(civ)]
sorbed = [F(0) for j in range(rate)]
for m in range(nblocks):
for i in range(rate):
a = state[i]
b = padded[m*rate+i]
sorbed[i] = a + b
state = Permutation(sorbed[0:rate] + state[rate:3])
q = min(rate, output_len)
for i in range(q):
output[i] = state[i]
out_ptr = rate
for n in range(1,nout):
state[nblocks+n] = Permutation(state[nblocks+n-1])
q = min(rate, output_len-out_ptr)
for i in range(q):
output[out_ptr+i] = state[nblocks+n][i]
out_ptr += rate
return output
if len(sys.argv) != Integer(2):
print("Usage: <script> <number of input>")
exit()
nInput = int(sys.argv[Integer(1)])
sk = [F(randrange(0,p,1)) for i in range(nInput)]
data_msg = F(randrange(0,p,1))
if nInput == 1:
inp = {
"secret_keys": str(sk[0]),
"msg": str(data_msg)
}
else:
inp = {
"secret_keys": [str(x) for x in sk],
"msg": str(data_msg)
}
import json
with open("input.json","w") as f:
json.dump(inp, f, indent=2)
print("Wrote input of ZkSignature")

View File

@ -0,0 +1,250 @@
//test
pragma circom 2.1.9;
include "../hash_bn/poseidon2_hash.circom";
include "../ledger/notes.circom";
include "../hash_bn/merkle.circom";
include "../misc/comparator.circom";
include "../circomlib/circuits/bitify.circom";
include "../misc/constants.circom";
template ticket_calculator(){
signal input epoch_nonce;
signal input slot;
signal input note_id;
signal input secret_key;
signal output out;
component hash = Poseidon2_hash(5);
component dst = LEAD_V1();
hash.inp[0] <== dst.out;
hash.inp[1] <== epoch_nonce;
hash.inp[2] <== slot;
hash.inp[3] <== note_id;
hash.inp[4] <== secret_key;
out <== hash.out;
}
template derive_entropy(){
signal input slot;
signal input note_id;
signal input secret_key;
signal output out;
component hash = Poseidon2_hash(4);
component dst = NOMOS_NONCE_CONTRIB_V1();
hash.inp[0] <== dst.out;
hash.inp[1] <== slot;
hash.inp[2] <== note_id;
hash.inp[3] <== secret_key;
out <== hash.out;
}
template would_win_leadership(secret_depth){
signal input slot;
signal input epoch_nonce;
signal input t0;
signal input t1;
signal input slot_secret;
signal input slot_secret_path[secret_depth];
//Part of the note id proof of membership to prove aged
signal input aged_nodes[32];
signal input aged_selectors[32]; // must be bits
signal input aged_root;
//Used to derive the note identifier
signal input transaction_hash;
signal input output_number;
//Part of the secret key
signal input starting_slot;
// The winning note value
signal input value;
signal output out;
signal output note_identifier;
signal output secret_key;
// Derivation of the secrets root from the slot secret at position slot - starting_slot
// Verify that the substraction wont underflow (starting_slot < slot)
component checker = SafeFullLessThan();
checker.a <== starting_slot;
checker.b <== slot;
// Compute the positions related to slot - starting_slot and make sure slot - starting_slot is a 25 bits number
component bits = Num2Bits(secret_depth);
bits.in <== slot - starting_slot;
// Derive the secrets root
component secrets_root = compute_merkle_root(secret_depth);
for(var i=0; i<secret_depth; i++){
secrets_root.nodes[i] <== slot_secret_path[i];
secrets_root.selector[i] <== bits.out[secret_depth-1-i];
}
secrets_root.leaf <== slot_secret;
// Derive the secret key
component sk = derive_secret_key();
sk.starting_slot <== starting_slot;
sk.secrets_root <== secrets_root.root;
// Derive the public key from the secret key
component pk = derive_public_key();
pk.secret_key <== sk.out;
// Derive the note id
component note_id = Poseidon2_hash(5);
component dst_note_id = NOMOS_NOTE_ID_V1();
note_id.inp[0] <== dst_note_id.out;
note_id.inp[1] <== transaction_hash;
note_id.inp[2] <== output_number;
note_id.inp[3] <== value;
note_id.inp[4] <== pk.out;
// Check the note ID is aged enough
//First check selectors are indeed bits
for(var i = 0; i < 32; i++){
aged_selectors[i] * (1 - aged_selectors[i]) === 0;
}
//Then check the proof of membership
component aged_membership = proof_of_membership(32);
for(var i = 0; i < 32; i++){
aged_membership.nodes[i] <== aged_nodes[i];
aged_membership.selector[i] <== aged_selectors[i];
}
aged_membership.root <== aged_root;
aged_membership.leaf <== note_id.out;
// Compute the lottery ticket
component ticket = ticket_calculator();
ticket.epoch_nonce <== epoch_nonce;
ticket.slot <== slot;
ticket.note_id <== note_id.out;
ticket.secret_key <== sk.out;
// Compute the lottery threshold
signal intermediate;
signal threshold;
intermediate <== t1 * value;
threshold <== value * (t0 + intermediate);
// Check that the ticket is winning
component winning = SafeFullLessThan();
winning.a <== ticket.out;
winning.b <== threshold;
// Check that every constraint holds
signal intermediate_out;
intermediate_out <== aged_membership.out * winning.out;
out <== intermediate_out * checker.out;
note_identifier <== note_id.out;
secret_key <== sk.out;
}
template proof_of_leadership(secret_depth){
signal input sl;
signal input epoch_nonce; // the epoch nonce eta
signal input t0;
signal input t1;
signal input slot_secret; // This is r_sl
signal input slot_secret_path[secret_depth];
//Part of the note id proof of membership to prove aged
signal input noteid_aged_path[32];
signal input noteid_aged_selectors[32]; // must be bits
signal input ledger_aged;
//Used to derive the note identifier
signal input note_tx_hash;
signal input note_output_number;
//Part of the note id proof of membership to prove it's unspent
signal input noteid_latest_path[32];
signal input noteid_latest_selectors[32]; // must be bits
signal input ledger_latest;
//Part of the secret key
signal input starting_slot;
// The winning note. The unit is supposed to be NMO and the ZoneID is MANTLE
signal input v; // value of the note
// Verify the note is winning the lottery
component lottery_checker = would_win_leadership(secret_depth);
lottery_checker.slot <== sl;
lottery_checker.epoch_nonce <== epoch_nonce;
lottery_checker.t0 <== t0;
lottery_checker.t1 <== t1;
lottery_checker.slot_secret <== slot_secret;
for(var i = 0; i < secret_depth; i++){
lottery_checker.slot_secret_path[i] <== slot_secret_path[i];
}
for(var i = 0; i < 32; i++){
lottery_checker.aged_nodes[i] <== noteid_aged_path[i];
lottery_checker.aged_selectors[i] <== noteid_aged_selectors[i];
}
lottery_checker.aged_root <== ledger_aged;
lottery_checker.transaction_hash <== note_tx_hash;
lottery_checker.output_number <== note_output_number;
lottery_checker.starting_slot <== starting_slot;
lottery_checker.value <== v;
// One time signing key used to sign the block proposal and the block
signal input P_lead_part_one;
signal input P_lead_part_two;
//Avoid the circom optimisation that removes unused public input
signal dummy_one;
signal dummy_two;
dummy_one <== P_lead_part_one * P_lead_part_one;
dummy_two <== P_lead_part_two * P_lead_part_two;
signal output entropy_contribution; // This is rho_lead
// Check that the note is unspent
//First check selectors are indeed bits
for(var i = 0; i < 32; i++){
noteid_latest_selectors[i] * (1 - noteid_latest_selectors[i]) === 0;
}
//Then check the note id is in the latest ledger state
component unspent_membership = proof_of_membership(32);
for(var i = 0; i < 32; i++){
unspent_membership.nodes[i] <== noteid_latest_path[i];
unspent_membership.selector[i] <== noteid_latest_selectors[i];
}
unspent_membership.root <== ledger_latest;
unspent_membership.leaf <== lottery_checker.note_identifier;
lottery_checker.out * unspent_membership.out === 1;
// Compute the entropy contribution
component entropy = derive_entropy();
entropy.slot <== sl;
entropy.note_id <== lottery_checker.note_identifier;
entropy.secret_key <== lottery_checker.secret_key;
entropy_contribution <== entropy.out;
}
component main {public [sl,epoch_nonce,t0,t1,ledger_aged,ledger_latest,P_lead_part_one,P_lead_part_two]}= proof_of_leadership(25);

View File

@ -0,0 +1,74 @@
//test
pragma circom 2.1.9;
include "../hash_bn/poseidon2_hash.circom";
include "../hash_bn/merkle.circom";
include "../misc/constants.circom";
template derive_voucher_nullifier(){
signal input secret_voucher;
signal output out;
component hash = Poseidon2_hash(2);
component dst = VOUCHER_NF();
hash.inp[0] <== dst.out;
hash.inp[1] <== secret_voucher;
out <== hash.out;
}
template derive_reward_voucher(){
signal input secret_voucher;
signal output out;
component hash = Poseidon2_hash(2);
component dst = REWARD_VOUCHER();
hash.inp[0] <== dst.out;
hash.inp[1] <== secret_voucher;
out <== hash.out;
}
template proof_of_claim(){
signal input secret_voucher;
signal input voucher_merkle_path[32];
signal input voucher_merkle_path_selectors[32];
signal input mantle_tx_hash;
signal input voucher_root;
signal output voucher_nullifier;
//derive the reward voucher
component reward_voucher = derive_reward_voucher();
reward_voucher.secret_voucher <== secret_voucher;
//Check reward voucher membership
//First check selectors are indeed bits
for(var i = 0; i < 32; i++){
voucher_merkle_path_selectors[i] * (1 - voucher_merkle_path_selectors[i]) === 0;
}
//Then check the proof of membership
component reward_membership = proof_of_membership(32);
for(var i = 0; i < 32; i++){
reward_membership.nodes[i] <== voucher_merkle_path[i];
reward_membership.selector[i] <== voucher_merkle_path_selectors[i];
}
reward_membership.root <== voucher_root;
reward_membership.leaf <== reward_voucher.out;
reward_membership.out === 1;
//derive the reward nullifier
component reward_nullifier = derive_voucher_nullifier();
reward_nullifier.secret_voucher <== secret_voucher;
voucher_nullifier <== reward_nullifier.out;
// dummy constraint to avoid unused public input to be erased after compilation optimisation
signal dummy;
dummy <== mantle_tx_hash * mantle_tx_hash;
}
component main {public [voucher_root,mantle_tx_hash]}= proof_of_claim();

View File

@ -0,0 +1,24 @@
//test
pragma circom 2.1.9;
include "../ledger/notes.circom";
include "../misc/constants.circom";
template zkSignature(maxInput){
signal input secret_keys[maxInput];
signal input msg;
signal output public_keys[maxInput];
component pk[maxInput];
for(var i =0; i<maxInput; i++){
pk[i] = derive_public_key();
pk[i].secret_key <== secret_keys[i];
public_keys[i] <== pk[i].out;
}
// dummy constraint to avoid unused public input to be erased after compilation optimisation
signal dummy;
dummy <== msg * msg;
}
component main {public [msg]}= zkSignature(32);

View File

@ -1,184 +0,0 @@
//test
pragma circom 2.1.9;
include "anemoi_Jubjub_16_to_1_constants.circom";
template ark_layer_16_to_1(round_number) {
assert(round_number < 10);
signal input in[16];
signal output out[16];
var C[10][8] = C_16_to_1();
var D[10][8] = D_16_to_1();
for(var i=0; i<8; i++){
out[i] <== in[i] + C[round_number][i];
out[8+i] <== in[8+i] + D[round_number][i];
}
}
template pow_alpha_16_to_1() { // ALPHA = 5
signal input in;
signal output out;
signal in2;
signal in4;
in2 <== in*in;
in4 <== in2 * in2;
out <== in4 * in;
}
template mds_layer_16_to_1() {
signal input in[16];
signal output out[16];
/* M_x= [1 2 3 5 7 8 8 9]
[9 1 2 3 5 7 8 8]
[8 9 1 2 3 5 7 8]
[8 8 9 1 2 3 5 7]
[7 8 8 9 1 2 3 5]
[5 7 8 8 9 1 2 3]
[3 5 7 8 8 9 1 2]
[2 3 5 7 8 8 9 1] */
signal x[8];
signal y[8];
x[0] <== 1*in[0] + 2*in[1] + 3*in[2] + 5*in[3] + 7*in[4] + 8*in[5] + 8*in[6] + 9*in[7];
x[1] <== 9*in[0] + 1*in[1] + 2*in[2] + 3*in[3] + 5*in[4] + 7*in[5] + 8*in[6] + 8*in[7];
x[2] <== 8*in[0] + 9*in[1] + 1*in[2] + 2*in[3] + 3*in[4] + 5*in[5] + 7*in[6] + 8*in[7];
x[3] <== 8*in[0] + 8*in[1] + 9*in[2] + 1*in[3] + 2*in[4] + 3*in[5] + 5*in[6] + 7*in[7];
x[4] <== 7*in[0] + 8*in[1] + 8*in[2] + 9*in[3] + 1*in[4] + 2*in[5] + 3*in[6] + 5*in[7];
x[5] <== 5*in[0] + 7*in[1] + 8*in[2] + 8*in[3] + 9*in[4] + 1*in[5] + 2*in[6] + 3*in[7];
x[6] <== 3*in[0] + 5*in[1] + 7*in[2] + 8*in[3] + 8*in[4] + 9*in[5] + 1*in[6] + 2*in[7];
x[7] <== 2*in[0] + 3*in[1] + 5*in[2] + 7*in[3] + 8*in[4] + 8*in[5] + 9*in[6] + 1*in[7];
y[0] <== 1*in[9] + 2*in[10] + 3*in[11] + 5*in[12] + 7*in[13] + 8*in[14] + 8*in[15] + 9*in[8];
y[1] <== 9*in[9] + 1*in[10] + 2*in[11] + 3*in[12] + 5*in[13] + 7*in[14] + 8*in[15] + 8*in[8];
y[2] <== 8*in[9] + 9*in[10] + 1*in[11] + 2*in[12] + 3*in[13] + 5*in[14] + 7*in[15] + 8*in[8];
y[3] <== 8*in[9] + 8*in[10] + 9*in[11] + 1*in[12] + 2*in[13] + 3*in[14] + 5*in[15] + 7*in[8];
y[4] <== 7*in[9] + 8*in[10] + 8*in[11] + 9*in[12] + 1*in[13] + 2*in[14] + 3*in[15] + 5*in[8];
y[5] <== 5*in[9] + 7*in[10] + 8*in[11] + 8*in[12] + 9*in[13] + 1*in[14] + 2*in[15] + 3*in[8];
y[6] <== 3*in[9] + 5*in[10] + 7*in[11] + 8*in[12] + 8*in[13] + 9*in[14] + 1*in[15] + 2*in[8];
y[7] <== 2*in[9] + 3*in[10] + 5*in[11] + 7*in[12] + 8*in[13] + 8*in[14] + 9*in[15] + 1*in[8];
for(var i=0; i<8; i++){
out[8+i] <== x[i] + y[i];
out[i] <== x[i] + out[8+i];
}
}
template s_box_16_to_1() {
signal input in[16];
signal output out[16];
//Computation using open Flystel
var x[8];
var y[8];
for(var i=0; i<8; i++){
x[i] = in[i];
y[i] = in[8+i];
x[i] = x[i] - 7 * (y[i]**2);
y[i] = y[i] - (x[i]**20974350070050476191779096203274386335076221000211055129041463479975432473805); // 1/ALPHA
x[i] = x[i] + 7 * (y[i]**2) + 14981678621464625851270783002338847382197300714436467949315331057125308909861; // DELTA
out[i] <-- x[i];
out[8+i] <-- y[i];
}
//Verification using closed Flystel
component pow[8];
signal y2[8];
signal v2[8];
for(var i=0; i<8; i++){
pow[i] = pow_alpha_16_to_1();
pow[i].in <== in[8+i] - out[8+i];
y2[i] <== in[8+i]*in[8+i];
v2[i] <== out[8+i]*out[8+i];
in[i] === pow[i].out + 7 * y2[i];
out[i] === pow[i].out + 7 * v2[i] + 14981678621464625851270783002338847382197300714436467949315331057125308909861;// DELTA
}
}
template round_16_to_1(round_number) {
signal input in[16];
signal output out[16];
component cst = ark_layer_16_to_1(round_number);
component mds = mds_layer_16_to_1();
component sbox = s_box_16_to_1();
for(var i=0; i<16; i++){
cst.in[i] <== in[i];
}
for(var i=0; i<16; i++){
mds.in[i] <== cst.out[i];
}
for(var i=0; i<16; i++){
sbox.in[i] <== mds.out[i];
}
for(var i=0; i<16; i++){
out[i] <== sbox.out[i];
}
}
template permutation_16_to_1(){
signal input in[16];
signal output out[16];
component rounds[10];
component mds = mds_layer_16_to_1();
for(var i = 0; i<10; i++){ //10 rounds
rounds[i] = round_16_to_1(i);
if(i==0){
for(var j=0; j<16; j++){
rounds[i].in[j] <== in[j];
}
} else {
for(var j=0; j<16; j++){
rounds[i].in[j] <== rounds[i-1].out[j];
}
}
}
for(var i=0; i<16; i++){
mds.in[i] <== rounds[9].out[i];
}
for(var i=0; i<16; i++){
out[i] <== mds.out[i];
}
}
template hash_16_to_1(){
signal input in[16];
signal output out;
component perm = permutation_16_to_1();
for(var i=0; i<16; i++){
perm.in[i] <== in[i];
}
out <== in[0] + perm.out[0] +
in[1] + perm.out[1] +
in[2] + perm.out[2] +
in[3] + perm.out[3] +
in[4] + perm.out[4] +
in[5] + perm.out[5] +
in[6] + perm.out[6] +
in[7] + perm.out[7] +
in[8] + perm.out[8] +
in[9] + perm.out[9] +
in[10] + perm.out[10] +
in[11] + perm.out[11] +
in[12] + perm.out[12] +
in[13] + perm.out[13] +
in[14] + perm.out[14] +
in[15] + perm.out[15];
}
//component main = hash_16_to_1();

View File

@ -1,122 +0,0 @@
//test
pragma circom 2.1.9;
include "anemoi_Jubjub_2_to_1_constants.circom";
template ark_layer_2_to_1(round_number) {
assert(round_number < 21);
signal input in[2];
signal output out[2];
var C[21] = C_2_to_1();
var D[21] = D_2_to_1();
out[0] <== in[0] + C[round_number];
out[1] <== in[1] + D[round_number];
}
template pow_alpha_2_to_1() { // ALPHA = 5
signal input in;
signal output out;
signal in2;
signal in4;
in2 <== in*in;
in4 <== in2 * in2;
out <== in4 * in;
}
template mds_layer_2_to_1() {
signal input in[2];
signal output out[2];
out[1] <== in[1] + in[0];
out[0] <== in[0] + out[1];
}
template s_box_2_to_1() {
signal input in[2];
signal output out[2];
//Calculation using open Flystel
var x;
var y;
x = in[0];
y = in[1];
x = x - 7 * (y**2);
y = y - (x**20974350070050476191779096203274386335076221000211055129041463479975432473805); // 1/ALPHA
x = x + 7 * (y**2) + 14981678621464625851270783002338847382197300714436467949315331057125308909861; //DELTA
out[0] <-- x;
out[1] <-- y;
//Verification using closed Flystel
component pow = pow_alpha_2_to_1();
pow.in <== in[1] - out[1];
signal y2;
signal v2;
y2 <== in[1]*in[1];
v2 <==out[1]*out[1];
in[0] === pow.out + 7 * y2;
out[0] === pow.out + 7 * v2 + 14981678621464625851270783002338847382197300714436467949315331057125308909861;// DELTA
}
template round_2_to_1(round_number) {
signal input in[2];
signal output out[2];
component cst = ark_layer_2_to_1(round_number);
component mds = mds_layer_2_to_1();
component sbox = s_box_2_to_1();
cst.in[0] <== in[0];
cst.in[1] <== in[1];
mds.in[0] <== cst.out[0];
mds.in[1] <== cst.out[1];
sbox.in[0] <== mds.out[0];
sbox.in[1] <== mds.out[1];
out[0] <== sbox.out[0];
out[1] <== sbox.out[1];
}
template permutation_2_to_1(){
signal input in[2];
signal output out[2];
component rounds[21];
component mds = mds_layer_2_to_1();
for(var i = 0; i<21; i++){ //21 rounds
rounds[i] = round_2_to_1(i);
if(i==0){
rounds[i].in[0] <== in[0];
rounds[i].in[1] <== in[1];
} else {
rounds[i].in[0] <== rounds[i-1].out[0];
rounds[i].in[1] <== rounds[i-1].out[1];
}
}
mds.in[0] <== rounds[20].out[0];
mds.in[1] <== rounds[20].out[1];
out[0] <== mds.out[0];
out[1] <== mds.out[1];
}
template hash_2_to_1(){
signal input in[2];
signal output out;
component perm = permutation_2_to_1();
perm.in[0] <== in[0];
perm.in[1] <== in[1];
out <== in[0] + perm.out[0] + in[1] + perm.out[1];
}
//component main = hash_2_to_1();

View File

@ -1,179 +0,0 @@
//test
pragma circom 2.1.9;
include "anemoi_Jubjub_4_to_1_constants.circom";
template ark_layer_4_to_1(round_number) {
assert(round_number < 14);
signal input in[4];
signal output out[4];
var C[14][2] = C_4_to_1();
var D[14][2] = D_4_to_1();
out[0] <== in[0] + C[round_number][0];
out[1] <== in[1] + C[round_number][1];
out[2] <== in[2] + D[round_number][0];
out[3] <== in[3] + D[round_number][1];
}
template pow_alpha_4_to_1() { // ALPHA = 5
signal input in;
signal output out;
signal in2;
signal in4;
in2 <== in*in;
in4 <== in2 * in2;
out <== in4 * in;
}
template mds_layer_4_to_1() {
signal input in[4];
signal output out[4];
signal x0;
signal x1;
signal y0;
signal y1;
x0 <== in[0] + 7*in[1];
x1 <== 7*in[0] + 50*in[1];
y0 <== in[3] + 7*in[2];
y1 <== 7*in[3] + 50*in[2];
out[2] <== y0 + x0;
out[3] <== y1 + x1;
out[0] <== x0 + out[2];
out[1] <== x1 + out[3];
}
template s_box_4_to_1() {
signal input in[4];
signal output out[4];
//Calculation using open Flystel
var x0;
var y0;
x0 = in[0];
y0 = in[2];
x0 = x0 - 7 * (y0**2);
y0 = y0 - (x0**20974350070050476191779096203274386335076221000211055129041463479975432473805); // 1/ALPHA
x0 = x0 + 7 * (y0**2) + 14981678621464625851270783002338847382197300714436467949315331057125308909861; //DELTA
var x1;
var y1;
x1 = in[1];
y1 = in[3];
x1 = x1 - 7 * (y1**2);
y1 = y1 - (x1**20974350070050476191779096203274386335076221000211055129041463479975432473805); // 1/ALPHA
x1 = x1 + 7 * (y1**2) + 14981678621464625851270783002338847382197300714436467949315331057125308909861; //DELTA
out[0] <-- x0;
out[1] <-- x1;
out[2] <-- y0;
out[3] <-- y1;
//Verification using closed Flystel
component pow[2];
pow[0] = pow_alpha_4_to_1();
pow[1] = pow_alpha_4_to_1();
pow[0].in <== in[2] - out[2];
signal y0_2;
signal v0_2;
y0_2 <== in[2]*in[2];
v0_2 <==out[2]*out[2];
in[0] === pow[0].out + 7 * y0_2;
out[0] === pow[0].out + 7 * v0_2 + 14981678621464625851270783002338847382197300714436467949315331057125308909861;// DELTA
pow[1].in <== in[3] - out[3];
signal y1_2;
signal v1_2;
y1_2 <== in[3]*in[3];
v1_2 <==out[3]*out[3];
in[1] === pow[1].out + 7 * y1_2;
out[1] === pow[1].out + 7 * v1_2 + 14981678621464625851270783002338847382197300714436467949315331057125308909861;// DELTA
}
template round_4_to_1(round_number) {
signal input in[4];
signal output out[4];
component cst = ark_layer_4_to_1(round_number);
component mds = mds_layer_4_to_1();
component sbox = s_box_4_to_1();
cst.in[0] <== in[0];
cst.in[1] <== in[1];
cst.in[2] <== in[2];
cst.in[3] <== in[3];
mds.in[0] <== cst.out[0];
mds.in[1] <== cst.out[1];
mds.in[2] <== cst.out[2];
mds.in[3] <== cst.out[3];
sbox.in[0] <== mds.out[0];
sbox.in[1] <== mds.out[1];
sbox.in[2] <== mds.out[2];
sbox.in[3] <== mds.out[3];
out[0] <== sbox.out[0];
out[1] <== sbox.out[1];
out[2] <== sbox.out[2];
out[3] <== sbox.out[3];
}
template permutation_4_to_1(){
signal input in[4];
signal output out[4];
component rounds[14];
component mds = mds_layer_4_to_1();
for(var i = 0; i<14; i++){ //14 rounds
rounds[i] = round_4_to_1(i);
if(i==0){
rounds[i].in[0] <== in[0];
rounds[i].in[1] <== in[1];
rounds[i].in[2] <== in[2];
rounds[i].in[3] <== in[3];
} else {
rounds[i].in[0] <== rounds[i-1].out[0];
rounds[i].in[1] <== rounds[i-1].out[1];
rounds[i].in[2] <== rounds[i-1].out[2];
rounds[i].in[3] <== rounds[i-1].out[3];
}
}
mds.in[0] <== rounds[13].out[0];
mds.in[1] <== rounds[13].out[1];
mds.in[2] <== rounds[13].out[2];
mds.in[3] <== rounds[13].out[3];
out[0] <== mds.out[0];
out[1] <== mds.out[1];
out[2] <== mds.out[2];
out[3] <== mds.out[3];
}
template hash_4_to_1(){
signal input in[4];
signal output out;
component perm = permutation_4_to_1();
perm.in[0] <== in[0];
perm.in[1] <== in[1];
perm.in[2] <== in[2];
perm.in[3] <== in[3];
out <== in[0] + perm.out[0] + in[1] + perm.out[1] + in[2] + perm.out[2] + in[3] + perm.out[3];
}
//component main = hash_4_to_1();

View File

@ -1,174 +0,0 @@
//test
pragma circom 2.1.9;
function C_16_to_1() {
return
[
[39,
17756515227822460609684409997111995494590448775258437999344446424780281143353,
10188916128123599964772546147951904500865009616764646948187915341627970346879,
3814237141406755457246679946340702245820791055503616462386588886553626328449,
31231358838611540266091127386940316382485316827738464579249222989762089961618,
3726010289701932654130304682574596267996890432970838266711107863585526844332,
36992578177313978374320714629037014712724552282717071185860782184820525992055,
6539662723010541897260760345121608837413747021964775102659796495628351576700],
[41362478282768062297187132445775312675360473883834860695283235286481594490621,
3384073892082712848969991795331397937188893616190315628722966662742467187281,
38536464596998108028197905645250196649287447208374169339784649587982292038621,
37592197675289757358471908199906415982484124338112374453435292524131427342810,
23880328728725835218995126249367316438768592574548525705412373412647097582882,
48825064577758348008118486787590853038041005302054740877940928369291358302191,
50534173420081783859714292066423124353911378857266355124747257390448683204724,
7428946804745276726594228607058422733621008211707460976374155647815125702793],
[9548818195234740988996233204400874453525674173109474205108603996010297049928,
51311880822158488881090781617710146800056386303122657365679608608648067582435,
24596965950552905296088269899880882549715354660832391374009234980535928382152,
34036826250287807194659359129722586818079652442547178531030410684351456041117,
47245638746867242507412562212796342461134942817161752237394648503282879275118,
31300595906266724771648800100316060631685700019604649908550024867487861705279,
3785144237087232802472944225009874259820952161256157218342463192641540401693,
13192072039732854032991114991329331830093509159172499125522354840599160152710],
[25365440569177822667580105183435418073995888230868180942004497015015045856900,
29347609441914902330741511702270026847909178228078752565372729158237774700914,
14356478667385969079309349540394948109414829921001045845599553435706989367858,
9488013611624811735432450930006811652991761655550510302915118428283918068143,
46788925259457988525082226160565541608877312582477767975013905645120335169226,
39167900530643229840202791109535532972977251341471019870612379478843295475401,
35468869056801697991539514623685427699753784556397696975236370718172619478088,
10386758415207822166675671630819234802877311049149240741713298889822859300210],
[34023498397393406644117994167986720327178154686105264833093891093045919619309,
2339620320400167830454536231899316133967303509954474267430948538955691907104,
12136748919666286297989154404429099226154686992028401568133058190732008277996,
19442569822772655270268482835742480365499256802520510905846953360427433130058,
6121842489566508888444793919988648467487285035515564826894797322329857604679,
52423305139993282549959548255411402052505266722715464547641713196825757370045,
721115880708783722056278375691123676170968994983418732948150001331611213553,
28368777671879812853105774722579268517023359292257929653599900440020077784493],
[38816051319719761886041858113129205506758421478656182868737326994635468402951,
27338042530319738113354246208426108832239651080023276643867223794985578055610,
15580674179713644540398409523441814073810768449493940562136422009899312699155,
4362660876979205605782410963041525734654031488177761934879852229226211686053,
11650586156654079013116836535888803264128748996614961532114710040258230535152,
19531964257180260867876509318520389540889883401661971174170106848135773712126,
28219700779483915272028450015085470411949576744039967576016029120273878374251,
33474277480452546775130924043517012470949538154685955521260479155699441559340],
[35167418087531820804128377095512663922179887277669504047069913414630376083753,
42192983528513372869128514327443204912824559545179630597589572656156258515752,
47389212411441573266379092392931599970417884729397156841216318364858334633325,
41487656259632727393098274178738763934249662924287956242704596746920012242443,
47585046162349898019384381324380934361400616741262019467964248889992556789636,
22864477306086472394102077909444955034170624450796904926669386049666664492257,
13351050514115985199153581050320477287713057625178307041078042677800880924875,
37405300160039662564807777381564989963058089105400420537288945543199341594301],
[25885868839756469722325652387535232478219821850603640827385444642154834700231,
42721818980548514490325424436763032046927347769153393863616095871384405840432,
5855288403637341107158034195599277569854359593529752399086836976954392351035,
18845851722124019325834426094831743068408557621685658713002749358354699910772,
33256528590007803378062158842587476459976080810702643409997408348306082386089,
2234591446681396008493892860306849390171100567645872660203494363121541667798,
194686086885408743916631695867994306362987352657004869135407425114760399927,
28761022534147935351682915336446217569572759443228321225221961720692449395484],
[8867588811641202981080659274007552529205713737251862066053445622305818871963,
23473499332437056484066006746048591864129988909190267521144125882222313735740,
5696063807157149622355481994320806474692190935543821893362808351446578125354,
48558031599255072862103809681060565464555437399403822458902024251997890071747,
29805490370918962312941798594103721605222271424104745148638516522088829641991,
37489036434356676843050473824100415300808075220521554146913930229334867812254,
11631357050894820069054650807562155039191303868752185889040197345022629525927,
24660767228992591228910666543569781024799661249145320635218341313794706416082],
[36439756010140137556111047750162544185710881404522379792044818039722752946048,
16497366583607480604161417644040292299204496829635795525393416854929276060989,
31479323495970113713816467604460499675889579912370034974841212556442942086146,
52327065242455117582590188333899352706031813782154293138553490341266149456684,
22462223600300108924276123720518708580622354327562062947406284488847554180931,
40996278729170725855966064159584167091102415184996744640950022676164065046834,
19430817579416357934148820670939901668848861606295052060308554899051486801548,
12483379002100433076591219143638049458199676871775181258981956241115974881163]
];
}
function D_16_to_1() {
return
[
[14981678621464625851270783002338847382197300714436467949315331057125308909900,
48720959343719104324739338388885839802998711550637402773896395605948383052052,
11709610427641952476226704950218052763560489079301307464225164120801969364960,
3188799073106888901912065951229864304299742047220134499402570163601813730969,
35055566170683830204685883433867693478135114051401583710007741398997412970579,
41969389849183863090802087476567191363990360356945841340095187311995419576515,
7556226394164164334481570938023506204252451033715203682883249970224239802922,
17176882240248932567902590122153974429675966351354956648777145117980813990398],
[28253420209785428420233456008091632509255652343634529984400816700490470131093,
6257781313532096835800460747082714697295034136932481743077166200794135826591,
11966422202069200811427605007493817363680804416274031195624148724039857787313,
8876022912542631074912834764773050492660953075192093830253524158063181475941,
52049674541477055908813163364458131823806820044102483998576800878704568506967,
6541832267666828237118069633374954748041800470865307468523599474646236580472,
45442960117610900571098429443573054134827707854155326784175634232674544930715,
42411304802662598148459339452254226615271657786988481684897413326989736031615],
[51511939407083344002778208487678590135577660247075600880835916725469990319313,
4386017178186728799761421274050927732938229436976005221436222062273391481632,
663227665329044490605880474899933274574966982371072793854806732105730575244,
7956955597245727322388196907364651338722736293265717471854714933795446618648,
25615413494197319129070770032476622018948872899826892271961489884914005459090,
44089542881006441891384034667061558189843302802581673885742427288293557612473,
1330235044321395925144992814935234051203536271783948441776912650379638572084,
50810734147355221866144137049300565722210413848092339398051685135286006925932],
[46291121544435738125248657675097664742296276807186696922340332893747842754587,
13820180736478645172746469075181304604729976364812127548341524461074783412926,
21821175320697611197161277831984495658213397245419754392657307036488476373765,
14806577897118234786495606424219372997573800509149076370951604526939593458489,
4121259770197377590627011188630352152939645167495297314189270176024564981500,
30919407268792259403824602884665561517383256626800433152413305048922095010897,
11976519627445173558098140421995318477384771169277877503279343325183821276781,
26967980286239502443715270897174999681242618240421470318851152333782809701734],
[3650460179273129580093806058710273018999560093475503119057680216309578390988,
40385222771838099109662234020243831589690223478794847201235014486200724862134,
20738601554725926373596082603265918636164823648026470243422423735982938342408,
25898290090014076279086638237202313571292864987698437102115051403552551578909,
17027208157180086391192319363486696710451739452640092116905432497642111659971,
45311967859890310071336359937788702458122841339624237957674250711373999964046,
30801797608226447725817644589434252152704077439970597211826393252750837255264,
46087155524659491087900373896182305256600235815109519358969365828449471244522],
[45802223370746268123059159806400152299867771061127345631244786118574025749328,
50306980075778262214155693291132052551559962723436936231611301042966928400825,
9105861908793877437599087016640061747418296780065295891365798855886560153752,
48177591413367409915642056167048753041735583848456612607691620273026228709602,
7479286918288249337458111273748279770690595088312775476065356516306801980629,
49779837246224071690294810803445084047795402193671669060746314363358914880825,
43223717601022172097383565523190027152080076863600432708834283672429421806147,
36115990427252817831519272511481477474123806352110831880569955844865152409554],
[11798621276624967315721748990709309216351696098813162382053396097866233042733,
34806952212038537244506031612074847133207330427265785757809673463434908473570,
10559431278588446438155840088055546145087872298641007742921718770142881700525,
2511742758961381498086249076485723904703122022711664665388729650078747694082,
13058778062050708618301726264166109369024922071632328984390918925338427847716,
22757381433196923491096449596295348042138602481479098385721617124187105273559,
50435973648847072778532507268536698366596569483938905568975979489192305153887,
9692044244906573895772196051455153467294816541497792469074445791662352057118],
[42372918959432199162670834641599336326433006968669415662488070504036922966492,
22755759419530071315007011572076166983660942447634027701351681157370705921018,
8881354201366797207686592249590682298565723459695719800911380560885170725516,
19725785152035256359574211351446161592903393017031483635806025440159666669692,
38586107420291196905731314141240110021641762437995069426543221562298184751450,
41983342504374430034240074906024700952180454895250182619374868616288213756381,
24699580977072888772599627764765708101597323007812082074548828715213834751707,
40903613549597429611399144365203839627850863176247809657126605147801691165582],
[52181371244193189669553521955614617990714056725501643636576377752669773323445,
30334172084294870556875274308904688414158741457854908094300017436690480001547,
35548861917762862971011720475855172816698712671893796030607658203859222685056,
23828822166916376664523534857031979764654878164406016294521947902346141831375,
9525926338952422609290893812113350942492558421053540078000977304624217008060,
51628644629799777637476595789175262638422034917782233018901952051044824901545,
10527109078832366866417586795816864610030244893563632007270266203664988878415,
11194215382192152257306835491684398858682370351821177979939632309447233186888],
[23791984554824031672195249524658580601428376029501889159059009332107176394097,
19832360622723392584029764807971325641132953515557801717644226271356492507876,
5370567718707734490084045178883836972105253285449736908577321570876055642415,
24072177097374519292068993110945703798030958684413852593268331853573451397392,
51092856030717857607132039047789240547482897962295861318467321833280572912593,
51610208211871924557451265725733951220616079019514789132032962359833072317205,
14800890894612002638570836260269548031587506768363863797633541619652896335116,
47927023617684282491494208201013569921672642612236042045401823798666133017562]
];
}

View File

@ -1,56 +0,0 @@
//test
pragma circom 2.1.9;
function C_2_to_1() {
return
[
39,
41362478282768062297187132445775312675360473883834860695283235286481594490621,
9548818195234740988996233204400874453525674173109474205108603996010297049928,
25365440569177822667580105183435418073995888230868180942004497015015045856900,
34023498397393406644117994167986720327178154686105264833093891093045919619309,
38816051319719761886041858113129205506758421478656182868737326994635468402951,
35167418087531820804128377095512663922179887277669504047069913414630376083753,
25885868839756469722325652387535232478219821850603640827385444642154834700231,
8867588811641202981080659274007552529205713737251862066053445622305818871963,
36439756010140137556111047750162544185710881404522379792044818039722752946048,
7788624504122357216765350546787885309160020166693449889975992574536033007374,
3134147137704626983201116226440762775442116005053282329971088789984415999550,
50252287380741824818995733304361249016282047978221591906573165442023106203143,
48434698978712278012409706205559577163572452744833134361195687109159129985373,
32960510617530186159512413633821386297955642598241661044178889571655571939473,
12850897859166761094422335671106280470381427571695744605265713866647560628356,
14578036872634298798382048587794204613583128573535557156943783762854124345644,
21588109842058901916690548710649523388049643745013696896704903154857389904594,
35731638686520516424752846654442973203189295883541072759390882351699754104989,
34141830003233180772153845227433233456603143306530920011579259084215824391544,
30272543670850635882116596228256005460817517173808721139136515002908946750291
];
}
function D_2_to_1() {
return
[
14981678621464625851270783002338847382197300714436467949315331057125308909900,
28253420209785428420233456008091632509255652343634529984400816700490470131093,
51511939407083344002778208487678590135577660247075600880835916725469990319313,
46291121544435738125248657675097664742296276807186696922340332893747842754587,
3650460179273129580093806058710273018999560093475503119057680216309578390988,
45802223370746268123059159806400152299867771061127345631244786118574025749328,
11798621276624967315721748990709309216351696098813162382053396097866233042733,
42372918959432199162670834641599336326433006968669415662488070504036922966492,
52181371244193189669553521955614617990714056725501643636576377752669773323445,
23791984554824031672195249524658580601428376029501889159059009332107176394097,
33342520831620303764059548442834699069640109058400548818586964467754352720368,
16791548253207744974576845515705461794133799104808996134617754018912057476556,
11087343419860825311828133337767238110556416596687749174422888171911517001265,
11931207770538477937808955037363240956790374856666237106403111503668796872571,
3296943608590459582451043049934874894049468383833500962645016062634514172805,
7080580976521357573320018355401935489220216583936865937104131954142364033647,
25990144965911478244481527888046366474489820502460615136523859419965697796405,
33907313384235729375566529911940467295099705980234607934575786561097199483218,
25996950265608465541351207283024962044374873682152889814392533334239395044136,
17878892320641464292190655092475335317049416605865175118054314040434534086821,
25443622609028754422863910981890932539396181992608938932620284900889552530362
];
}

View File

@ -1,70 +0,0 @@
//test
pragma circom 2.1.9;
function C_4_to_1() {
return
[
[39,
17756515227822460609684409997111995494590448775258437999344446424780281143353],
[41362478282768062297187132445775312675360473883834860695283235286481594490621,
3384073892082712848969991795331397937188893616190315628722966662742467187281],
[9548818195234740988996233204400874453525674173109474205108603996010297049928,
51311880822158488881090781617710146800056386303122657365679608608648067582435],
[25365440569177822667580105183435418073995888230868180942004497015015045856900,
29347609441914902330741511702270026847909178228078752565372729158237774700914],
[34023498397393406644117994167986720327178154686105264833093891093045919619309,
2339620320400167830454536231899316133967303509954474267430948538955691907104],
[38816051319719761886041858113129205506758421478656182868737326994635468402951,
27338042530319738113354246208426108832239651080023276643867223794985578055610],
[35167418087531820804128377095512663922179887277669504047069913414630376083753,
42192983528513372869128514327443204912824559545179630597589572656156258515752],
[25885868839756469722325652387535232478219821850603640827385444642154834700231,
42721818980548514490325424436763032046927347769153393863616095871384405840432],
[8867588811641202981080659274007552529205713737251862066053445622305818871963,
23473499332437056484066006746048591864129988909190267521144125882222313735740],
[36439756010140137556111047750162544185710881404522379792044818039722752946048,
16497366583607480604161417644040292299204496829635795525393416854929276060989],
[7788624504122357216765350546787885309160020166693449889975992574536033007374,
16727395967350522643500778393489915391834352737211416857240725807058479128000],
[3134147137704626983201116226440762775442116005053282329971088789984415999550,
46525506418681456193255596516104416743523037046982280449529426136392814992763],
[50252287380741824818995733304361249016282047978221591906573165442023106203143,
46030886964045328670650579467522042981756109464584907077434772786649263902996],
[48434698978712278012409706205559577163572452744833134361195687109159129985373,
19216533213230709497947223526297848065365334472367022650183395435586190711770]
];
}
function D_4_to_1() {
return
[
[14981678621464625851270783002338847382197300714436467949315331057125308909900,
48720959343719104324739338388885839802998711550637402773896395605948383052052],
[28253420209785428420233456008091632509255652343634529984400816700490470131093,
6257781313532096835800460747082714697295034136932481743077166200794135826591],
[51511939407083344002778208487678590135577660247075600880835916725469990319313,
4386017178186728799761421274050927732938229436976005221436222062273391481632],
[46291121544435738125248657675097664742296276807186696922340332893747842754587,
13820180736478645172746469075181304604729976364812127548341524461074783412926],
[3650460179273129580093806058710273018999560093475503119057680216309578390988,
40385222771838099109662234020243831589690223478794847201235014486200724862134],
[45802223370746268123059159806400152299867771061127345631244786118574025749328,
50306980075778262214155693291132052551559962723436936231611301042966928400825],
[11798621276624967315721748990709309216351696098813162382053396097866233042733,
34806952212038537244506031612074847133207330427265785757809673463434908473570],
[42372918959432199162670834641599336326433006968669415662488070504036922966492,
22755759419530071315007011572076166983660942447634027701351681157370705921018],
[52181371244193189669553521955614617990714056725501643636576377752669773323445,
30334172084294870556875274308904688414158741457854908094300017436690480001547],
[23791984554824031672195249524658580601428376029501889159059009332107176394097,
19832360622723392584029764807971325641132953515557801717644226271356492507876],
[33342520831620303764059548442834699069640109058400548818586964467754352720368,
5828182614154296575131381170785760240834851189333374788484657124381010655319],
[16791548253207744974576845515705461794133799104808996134617754018912057476556,
23729797853490401568967730686618146850735129707152853256809050789424668284094],
[11087343419860825311828133337767238110556416596687749174422888171911517001265,
22848708497596347027267124890363029002241440143993561170521113640580467699956],
[11931207770538477937808955037363240956790374856666237106403111503668796872571,
51131682674615117766578358255722474622484771145670260043231096654077231782319]
];
}

View File

@ -1,49 +0,0 @@
#!/bin/bash
set -e
TAU=../../../keys/powersOfTau20_BLS_final.ptau
circom "$1.circom" --r1cs --wasm -p bls12381
cd "$1_js/"
node generate_witness.js "$1.wasm" ../input.json ../witness.wtns
cd ..
rm -R "$1_js/"
snarkjs groth16 setup "$1.r1cs" $TAU circuit_0000.zkey -v
snarkjs zkey contribute circuit_0000.zkey circuit_0001.zkey --name="1st Contributor Name" -e="entropy" -v
snarkjs zkey beacon circuit_0001.zkey "$1.zkey" 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 10 -n="Final Beacon phase2" -v
snarkjs zkey export verificationkey "$1.zkey" verification_key.json -v
rm circuit_0*
#for i in `seq 1 20`;
#do
# ../../../rapidsnark/package/bin/prover "$1.zkey" witness.wtns proof.json public.json
snarkjs groth16 prove "$1.zkey" witness.wtns proof.json public.json
#done
#start=$(date +%s%6N)
#for i in `seq 1 100`;
#do
snarkjs groth16 prove "$1.zkey" witness.wtns proof.json public.json
#../../../rapidsnark/package/bin/prover "$1.zkey" witness.wtns proof.json public.json
#done
#end=$(date +%s%6N)
rm witness.wtns
snarkjs groth16 verify verification_key.json public.json proof.json
#temps=$((($end-$start)/100))
#echo "Temps de la preuve: $temps micro secondes "
rm "$1.zkey"

View File

@ -1,473 +0,0 @@
//test
pragma circom 2.1.9;
include "poseidon_Jubjub_16_to_1_constants.circom";
template external_linear_layer_16_to_1() {
signal input in[16];
signal output out[16];
// Matrix is [10 14 2 6 5 7 1 3 5 7 1 3 5 7 1 3]
// [ 8 12 2 2 4 6 1 1 4 6 1 1 4 6 1 1]
// [ 2 6 10 14 1 3 5 7 1 3 5 7 1 3 5 7]
// [ 2 2 8 12 1 1 4 6 1 1 4 6 1 1 4 6]
// [ 5 7 1 3 10 14 2 6 5 7 1 3 5 7 1 3]
// [ 4 6 1 1 8 12 2 2 4 6 1 1 4 6 1 1]
// [ 1 3 5 7 2 6 10 14 1 3 5 7 1 3 5 7]
// [ 1 1 4 6 2 2 8 12 1 1 4 6 1 1 4 6]
// [ 5 7 1 3 5 7 1 3 10 14 2 6 5 7 1 3]
// [ 4 6 1 1 4 6 1 1 8 12 2 2 4 6 1 1]
// [ 1 3 5 7 1 3 5 7 2 6 10 14 1 3 5 7]
// [ 1 1 4 6 1 1 4 6 2 2 8 12 1 1 4 6]
// [ 5 7 1 3 5 7 1 3 5 7 1 3 10 14 2 6]
// [ 4 6 1 1 4 6 1 1 4 6 1 1 8 12 2 2]
// [ 1 3 5 7 1 3 5 7 1 3 5 7 2 6 10 14]
// [ 1 1 4 6 1 1 4 6 1 1 4 6 2 2 8 12]
out[0] <== in[0] +in[0] +in[0] +in[0] +in[0] +in[0] +in[0] +in[0] +in[0] +in[0] +
in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +
in[2] +in[2] +
in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +
in[4] +in[4] +in[4] +in[4] +in[4] +
in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +
in[6] +
in[7] +in[7] +in[7] +
in[8] +in[8] +in[8] +in[8] +in[8] +
in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +
in[10] +
in[11] +in[11] +in[11] +
in[12] +in[12] +in[12] +in[12] +in[12] +
in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +
in[14] +
in[15] +in[15] +in[15];
out[1] <== in[0] +in[0] +in[0] +in[0] +in[0] +in[0] +in[0] +in[0] +
in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +
in[2] +in[2] +
in[3] +in[3] +
in[4] +in[4] +in[4] +in[4] +
in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +
in[6] +
in[7] +
in[8] +in[8] +in[8] +in[8] +
in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +
in[10] +
in[11] +
in[12] +in[12] +in[12] +in[12] +
in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +
in[14] +
in[15];
out[2] <== in[0] +in[0] +
in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +
in[2] +in[2] +in[2] +in[2] +in[2] +in[2] +in[2] +in[2] +in[2] +in[2] +
in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +
in[4] +
in[5] +in[5] +in[5] +
in[6] +in[6] +in[6] +in[6] +in[6] +
in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +
in[8] +
in[9] +in[9] +in[9] +
in[10] +in[10] +in[10] +in[10] +in[10] +
in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +
in[12] +
in[13] +in[13] +in[13] +
in[14] +in[14] +in[14] +in[14] +in[14] +
in[15] +in[15] +in[15] +in[15] +in[15] +in[15] +in[15];
out[3] <== in[0] +in[0] +
in[1] +in[1] +
in[2] +in[2] +in[2] +in[2] +in[2] +in[2] +in[2] +in[2] +
in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +
in[4] +
in[5] +
in[6] +in[6] +in[6] +in[6] +
in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +
in[8] +
in[9] +
in[10] +in[10] +in[10] +in[10] +
in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +
in[12] +
in[13] +
in[14] +in[14] +in[14] +in[14] +
in[15] +in[15] +in[15] +in[15] +in[15] +in[15];
out[4] <== in[0] +in[0] +in[0] +in[0] +in[0] +
in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +
in[2] +
in[3] +in[3] +in[3] +
in[4] +in[4] +in[4] +in[4] +in[4] +in[4] +in[4] +in[4] +in[4] +in[4] +
in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +
in[6] +in[6] +
in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +
in[8] +in[8] +in[8] +in[8] +in[8] +
in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +
in[10] +
in[11] +in[11] +in[11] +
in[12] +in[12] +in[12] +in[12] +in[12] +
in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +
in[14] +
in[15] +in[15] +in[15];
out[5] <== in[0] +in[0] +in[0] +in[0] +
in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +
in[2] +
in[3] +
in[4] +in[4] +in[4] +in[4] +in[4] +in[4] +in[4] +in[4] +
in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +
in[6] +in[6] +
in[7] +in[7] +
in[8] +in[8] +in[8] +in[8] +
in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +
in[10] +
in[11] +
in[12] +in[12] +in[12] +in[12] +
in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +
in[14] +
in[15];
out[6] <== in[0] +
in[1] +in[1] +in[1] +
in[2] +in[2] +in[2] +in[2] +in[2] +
in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +
in[4] +in[4] +
in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +
in[6] +in[6] +in[6] +in[6] +in[6] +in[6] +in[6] +in[6] +in[6] +in[6] +
in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +
in[8] +
in[9] +in[9] +in[9] +
in[10] +in[10] +in[10] +in[10] +in[10] +
in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +
in[12] +
in[13] +in[13] +in[13] +
in[14] +in[14] +in[14] +in[14] +in[14] +
in[15] +in[15] +in[15] +in[15] +in[15] +in[15] +in[15];
out[7] <== in[0] +
in[1] +
in[2] +in[2] +in[2] +in[2] +
in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +
in[4] +in[4] +
in[5] +in[5] +
in[6] +in[6] +in[6] +in[6] +in[6] +in[6] +in[6] +in[6] +
in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +
in[8] +
in[9] +
in[10] +in[10] +in[10] +in[10] +
in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +
in[12] +
in[13] +
in[14] +in[14] +in[14] +in[14] +
in[15] +in[15] +in[15] +in[15] +in[15] +in[15];
out[8] <== in[0] +in[0] +in[0] +in[0] +in[0] +
in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +
in[2] +
in[3] +in[3] +in[3] +
in[4] +in[4] +in[4] +in[4] +in[4] +
in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +
in[6] +
in[7] +in[7] +in[7] +
in[8] +in[8] +in[8] +in[8] +in[8] +in[8] +in[8] +in[8] +in[8] +in[8] +
in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +
in[10] +in[10] +
in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +
in[12] +in[12] +in[12] +in[12] +in[12] +
in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +
in[14] +
in[15] +in[15] +in[15];
out[9] <== in[0] +in[0] +in[0] +in[0] +
in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +
in[2] +
in[3] +
in[4] +in[4] +in[4] +in[4] +
in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +
in[6] +
in[7] +
in[8] +in[8] +in[8] +in[8] +in[8] +in[8] +in[8] +in[8] +
in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +
in[10] +in[10] +
in[11] +in[11] +
in[12] +in[12] +in[12] +in[12] +
in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +
in[14] +
in[15];
out[10] <== in[0] +
in[1] +in[1] +in[1] +
in[2] +in[2] +in[2] +in[2] +in[2] +
in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +
in[4] +
in[5] +in[5] +in[5] +
in[6] +in[6] +in[6] +in[6] +in[6] +
in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +
in[8] +in[8] +
in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +
in[10] +in[10] +in[10] +in[10] +in[10] +in[10] +in[10] +in[10] +in[10] +in[10] +
in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +
in[12] +
in[13] +in[13] +in[13] +
in[14] +in[14] +in[14] +in[14] +in[14] +
in[15] +in[15] +in[15] +in[15] +in[15] +in[15] +in[15];
out[11] <== in[0] +
in[1] +
in[2] +in[2] +in[2] +in[2] +
in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +
in[4] +
in[5] +
in[6] +in[6] +in[6] +in[6] +
in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +
in[8] +in[8] +
in[9] +in[9] +
in[10] +in[10] +in[10] +in[10] +in[10] +in[10] +in[10] +in[10] +
in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +
in[12] +
in[13] +
in[14] +in[14] +in[14] +in[14] +
in[15] +in[15] +in[15] +in[15] +in[15] +in[15];
out[12] <== in[0] +in[0] +in[0] +in[0] +in[0] +
in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +
in[2] +
in[3] +in[3] +in[3] +
in[4] +in[4] +in[4] +in[4] +in[4] +
in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +
in[6] +
in[7] +in[7] +in[7] +
in[8] +in[8] +in[8] +in[8] +in[8] +
in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +
in[10] +
in[11] +in[11] +in[11] +
in[12] +in[12] +in[12] +in[12] +in[12] +in[12] +in[12] +in[12] +in[12] +in[12] +
in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +
in[14] +in[14] +
in[15] +in[15] +in[15] +in[15] +in[15] +in[15];
out[13] <== in[0] +in[0] +in[0] +in[0] +
in[1] +in[1] +in[1] +in[1] +in[1] +in[1] +
in[2] +
in[3] +
in[4] +in[4] +in[4] +in[4] +
in[5] +in[5] +in[5] +in[5] +in[5] +in[5] +
in[6] +
in[7] +
in[8] +in[8] +in[8] +in[8] +
in[9] +in[9] +in[9] +in[9] +in[9] +in[9] +
in[10] +
in[11] +
in[12] +in[12] +in[12] +in[12] +in[12] +in[12] +in[12] +in[12] +
in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +
in[14] +in[14] +
in[15] +in[15];
out[14] <== in[0] +
in[1] +in[1] +in[1] +
in[2] +in[2] +in[2] +in[2] +in[2] +
in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +
in[4] +
in[5] +in[5] +in[5] +
in[6] +in[6] +in[6] +in[6] +in[6] +
in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +
in[8] +
in[9] +in[9] +in[9] +
in[10] +in[10] +in[10] +in[10] +in[10] +
in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +
in[12] +in[12] +
in[13] +in[13] +in[13] +in[13] +in[13] +in[13] +
in[14] +in[14] +in[14] +in[14] +in[14] +in[14] +in[14] +in[14] +in[14] +in[14] +
in[15] +in[15] +in[15] +in[15] +in[15] +in[15] +in[15] +in[15] +in[15] +in[15] +in[15] +in[15] +in[15] +in[15];
out[15] <== in[0] +
in[1] +
in[2] +in[2] +in[2] +in[2] +
in[3] +in[3] +in[3] +in[3] +in[3] +in[3] +
in[4] +
in[5] +
in[6] +in[6] +in[6] +in[6] +
in[7] +in[7] +in[7] +in[7] +in[7] +in[7] +
in[8] +
in[9] +
in[10] +in[10] +in[10] +in[10] +
in[11] +in[11] +in[11] +in[11] +in[11] +in[11] +
in[12] +in[12] +
in[13] +in[13] +
in[14] +in[14] +in[14] +in[14] +in[14] +in[14] +in[14] +in[14] +
in[15] +in[15] +in[15] +in[15] +in[15] +in[15] +in[15] +in[15] +in[15] +in[15] +in[15] +in[15];
}
template internal_linear_layer_16_to_1() {
signal input in[16];
signal output out[16];
signal sum <== in[0] + in[1] + in[2] + in[3] + in[4] + in[5] + in[6] + in[7] + in[8] + in[9] + in[10] + in[11] + in[12] + in[13] + in[14] + in[15];
out[0] <== in[0] * 67 + sum;
out[1] <== in[1] * 84 + sum;
out[2] <== in[2] * 80 + sum;
out[3] <== in[3] * 94 + sum;
out[4] <== in[4] * 57 + sum;
out[5] <== in[5] * 89 + sum;
out[6] <== in[6] * 92 + sum;
out[7] <== in[7] * 39 + sum;
out[8] <== in[8] * 34 + sum;
out[9] <== in[9] * 24 + sum;
out[10] <== in[10] + sum;
out[11] <== in[11] * 95 + sum;
out[12] <== in[12] * 21 + sum;
out[13] <== in[13] * 73 + sum;
out[14] <== in[14] * 68 + sum;
out[15] <== in[15] * 52 + sum;
}
template sbox_16_to_1() { // ALPHA = 5
signal input in;
signal output out;
signal in2;
signal in4;
in2 <== in*in;
in4 <== in2 * in2;
out <== in4 * in;
}
template ARC_16_to_1(index){
signal input in;
signal output out;
var constants[185] = round_constant_16_to_1();
out <== in + constants[index];
}
template partial_round_16_to_1(round_number) {
signal input in[16];
signal output out[16];
component add_constant = ARC_16_to_1(round_number + 60);
add_constant.in <== in[0];
component exp = sbox_16_to_1();
exp.in <== add_constant.out;
component matrix = internal_linear_layer_16_to_1();
matrix.in[0] <== exp.out;
for(var i=1; i<16; i++){
matrix.in[i] <== in[i];
}
for(var i=0; i<16; i++){
out[i] <== matrix.out[i];
}
}
template full_rounds_16_to_1(round_number){
signal input in[16];
signal output out[16];
component add_constant[16];
if(round_number < 4) {
for(var i=0; i<16; i++){
add_constant[i] = ARC_16_to_1(round_number*16+i);
}
} else {
for(var i=0; i<16; i++){
add_constant[i] = ARC_16_to_1((round_number - 61) * 16 + i + 121);
}
}
for(var i=0; i<16; i++){
add_constant[i].in <== in[i];
}
component exp[16];
for(var i=0; i<16; i++){
exp[i] = sbox_16_to_1();
exp[i].in <== add_constant[i].out;
}
component matrix = external_linear_layer_16_to_1();
for(var i=0; i<16; i++){
matrix.in[i] <== exp[i].out;
}
for(var i=0; i<16; i++){
out[i] <== matrix.out[i];
}
}
template permutation_16_to_1(){
signal input in[16];
signal output out[16];
component full_rounds_16_to_1[8];
component partial_round_16_to_1s[57];
component matrix = external_linear_layer_16_to_1();
for(var i=0; i<16; i++){
matrix.in[i] <== in[i];
}
for(var i=0; i<65; i++){
if(i < 4) {
full_rounds_16_to_1[i] = full_rounds_16_to_1(i);
} else {
if(i<61) {
partial_round_16_to_1s[i-4] = partial_round_16_to_1(i);
} else {
full_rounds_16_to_1[i-57] = full_rounds_16_to_1(i);
}
}
}
for(var i=0; i<16; i++){
full_rounds_16_to_1[0].in[i] <== matrix.out[i];
}
for(var i=1; i<4; i++){
for(var j=0; j<16; j++){
full_rounds_16_to_1[i].in[j] <== full_rounds_16_to_1[i-1].out[j];
}
}
for(var i=0; i<16; i++){
partial_round_16_to_1s[0].in[i] <== full_rounds_16_to_1[3].out[i];
}
for(var i=1; i<57; i++){
for(var j=0; j<16; j++){
partial_round_16_to_1s[i].in[j] <== partial_round_16_to_1s[i-1].out[j];
}
}
for(var i=0; i<16; i++){
full_rounds_16_to_1[4].in[i] <== partial_round_16_to_1s[56].out[i];
}
for(var i=5; i<8; i++){
for(var j=0; j<16; j++){
full_rounds_16_to_1[i].in[j] <== full_rounds_16_to_1[i-1].out[j];
}
}
for(var i=0; i<16; i++){
out[i] <== full_rounds_16_to_1[7].out[i];
}
}
template hash_16_to_1(){
signal input in[16];
signal output out;
component perm = permutation_16_to_1();
for(var i=0; i<16; i++){
perm.in[i] <== in[i];
}
out <== in[0] + perm.out[0];
}
//component main = hash_16_to_1();

View File

@ -1,147 +0,0 @@
//test
pragma circom 2.1.9;
include "poseidon_Jubjub_2_to_1_constants.circom";
template linear_layer_2_to_1() {
signal input in[2];
signal output out[2];
out[0] <== in[0] + in[0] + in[1];
out[1] <== in[0] + in[1] + in[1];
}
template sbox_2_to_1() { // ALPHA = 5
signal input in;
signal output out;
signal in2;
signal in4;
in2 <== in*in;
in4 <== in2 * in2;
out <== in4 * in;
}
template ARC_2_to_1(index){
signal input in;
signal output out;
var constants[72] = round_constant_2_to_1();
out <== in + constants[index];
}
template partial_round_2_to_1(round_number) {
signal input in[2];
signal output out[2];
component add_constant = ARC_2_to_1(round_number + 4);
add_constant.in <== in[0];
component exp = sbox_2_to_1();
exp.in <== add_constant.out;
component matrix = linear_layer_2_to_1();
matrix.in[0] <== exp.out;
matrix.in[1] <== in[1];
out[0] <== matrix.out[0];
out[1] <== matrix.out[1];
}
template full_rounds_2_to_1(round_number){
signal input in[2];
signal output out[2];
component add_constant[2];
if(round_number < 4) {
add_constant[0] = ARC_2_to_1(round_number*2);
add_constant[1] = ARC_2_to_1(round_number*2 +1);
} else {
add_constant[0] = ARC_2_to_1((round_number - 60) * 2 + 64);
add_constant[1] = ARC_2_to_1((round_number - 60) * 2 + 65);
}
add_constant[0].in <== in[0];
add_constant[1].in <== in[1];
component exp[2];
exp[0] = sbox_2_to_1();
exp[1] = sbox_2_to_1();
exp[0].in <== add_constant[0].out;
exp[1].in <== add_constant[1].out;
component matrix = linear_layer_2_to_1();
matrix.in[0] <== exp[0].out;
matrix.in[1] <== exp[1].out;
out[0] <== matrix.out[0];
out[1] <== matrix.out[1];
}
template permutation_2_to_1(){
signal input in[2];
signal output out[2];
component full_rounds_2_to_1[8];
component partial_round_2_to_1s[56];
component matrix = linear_layer_2_to_1();
matrix.in[0] <== in[0];
matrix.in[1] <== in[1];
for(var i=0; i<64; i++){
if(i < 4) {
full_rounds_2_to_1[i] = full_rounds_2_to_1(i);
} else {
if(i<60) {
partial_round_2_to_1s[i-4] = partial_round_2_to_1(i);
} else {
full_rounds_2_to_1[i-56] = full_rounds_2_to_1(i);
}
}
}
full_rounds_2_to_1[0].in[0] <== matrix.out[0];
full_rounds_2_to_1[0].in[1] <== matrix.out[1];
for(var i=1; i<4; i++){
full_rounds_2_to_1[i].in[0] <== full_rounds_2_to_1[i-1].out[0];
full_rounds_2_to_1[i].in[1] <== full_rounds_2_to_1[i-1].out[1];
}
partial_round_2_to_1s[0].in[0] <== full_rounds_2_to_1[3].out[0];
partial_round_2_to_1s[0].in[1] <== full_rounds_2_to_1[3].out[1];
for(var i=1; i<56; i++){
partial_round_2_to_1s[i].in[0] <== partial_round_2_to_1s[i-1].out[0];
partial_round_2_to_1s[i].in[1] <== partial_round_2_to_1s[i-1].out[1];
}
full_rounds_2_to_1[4].in[0] <== partial_round_2_to_1s[55].out[0];
full_rounds_2_to_1[4].in[1] <== partial_round_2_to_1s[55].out[1];
for(var i=5; i<8; i++){
full_rounds_2_to_1[i].in[0] <== full_rounds_2_to_1[i-1].out[0];
full_rounds_2_to_1[i].in[1] <== full_rounds_2_to_1[i-1].out[1];
}
out[0] <== full_rounds_2_to_1[7].out[0];
out[1] <== full_rounds_2_to_1[7].out[1];
}
template hash_2_to_1(){
signal input in[2];
signal output out;
component perm = permutation_2_to_1();
perm.in[0] <== in[0];
perm.in[1] <== in[1];
out <== in[0] + perm.out[0];
}
//component main = hash_2_to_1();

View File

@ -1,188 +0,0 @@
//test
pragma circom 2.1.9;
include "poseidon_Jubjub_4_to_1_constants.circom";
template external_linear_layer_4_to_1() {
signal input in[4];
signal output out[4];
out[3] <== in[0] + in[0] + in[0] + in[0] + in[0] + in[1] + in[1] + in[1] + in[1] + in[1] + in[1] + in[1] + in[2] + in[3] + in[3] + in[3];
out[1] <== in[0] + in[0] + in[0] + in[0] + in[1] + in[1] + in[1] + in[1] + in[1] + in[1] + in[2] + in[3];
out[0] <== in[0] + in[1] + in[1] + in[1] + in[2] + in[2] + in[2] + in[2] + in[2] + in[3] + in[3] + in[3] + in[3] + in[3] + in[3] + in[3];
out[2] <== in[0] + in[1] + in[2] + in[2] + in[2] + in[2] + in[3] + in[3] + in[3] + in[3] + in[3] + in[3];
}
template internal_linear_layer_4_to_1() {
signal input in[4];
signal output out[4];
out[0] <== in[0] + in[0] + in[1] + in[2] + in[3];
out[1] <== in[1] + in[0] + in[1] + in[2] + in[3];
out[2] <== in[2] + in[2] + in[2] + in[0] + in[1] + in[2] + in[3];
out[3] <== in[3] + in[3] + in[3] + in[3] + in[3] + in[3] + in[3] + in[0] + in[1] + in[2] + in[3];
}
template sbox_4_to_1() { // ALPHA = 5
signal input in;
signal output out;
signal in2;
signal in4;
in2 <== in*in;
in4 <== in2 * in2;
out <== in4 * in;
}
template ARC_4_to_1(index){
signal input in;
signal output out;
var constants[88] = round_constant_4_to_1();
out <== in + constants[index];
}
template partial_round_4_to_1(round_number) {
signal input in[4];
signal output out[4];
component add_constant = ARC_4_to_1(round_number + 12);
add_constant.in <== in[0];
component exp = sbox_4_to_1();
exp.in <== add_constant.out;
component matrix = internal_linear_layer_4_to_1();
matrix.in[0] <== exp.out;
matrix.in[1] <== in[1];
matrix.in[2] <== in[2];
matrix.in[3] <== in[3];
out[0] <== matrix.out[0];
out[1] <== matrix.out[1];
out[2] <== matrix.out[2];
out[3] <== matrix.out[3];
}
template full_rounds_4_to_1(round_number){
signal input in[4];
signal output out[4];
component add_constant[4];
if(round_number < 4) {
add_constant[0] = ARC_4_to_1(round_number*4);
add_constant[1] = ARC_4_to_1(round_number*4 +1);
add_constant[2] = ARC_4_to_1(round_number*4 +2);
add_constant[3] = ARC_4_to_1(round_number*4 +3);
} else {
add_constant[0] = ARC_4_to_1((round_number - 60) * 4 + 72);
add_constant[1] = ARC_4_to_1((round_number - 60) * 4 + 73);
add_constant[2] = ARC_4_to_1((round_number - 60) * 4 + 74);
add_constant[3] = ARC_4_to_1((round_number - 60) * 4 + 75);
}
add_constant[0].in <== in[0];
add_constant[1].in <== in[1];
add_constant[2].in <== in[2];
add_constant[3].in <== in[3];
component exp[4];
exp[0] = sbox_4_to_1();
exp[1] = sbox_4_to_1();
exp[2] = sbox_4_to_1();
exp[3] = sbox_4_to_1();
exp[0].in <== add_constant[0].out;
exp[1].in <== add_constant[1].out;
exp[2].in <== add_constant[2].out;
exp[3].in <== add_constant[3].out;
component matrix = external_linear_layer_4_to_1();
matrix.in[0] <== exp[0].out;
matrix.in[1] <== exp[1].out;
matrix.in[2] <== exp[2].out;
matrix.in[3] <== exp[3].out;
out[0] <== matrix.out[0];
out[1] <== matrix.out[1];
out[2] <== matrix.out[2];
out[3] <== matrix.out[3];
}
template permutation_4_to_1(){
signal input in[4];
signal output out[4];
component full_rounds_4_to_1[8];
component partial_round_4_to_1s[56];
component matrix = external_linear_layer_4_to_1();
matrix.in[0] <== in[0];
matrix.in[1] <== in[1];
matrix.in[2] <== in[2];
matrix.in[3] <== in[3];
for(var i=0; i<64; i++){
if(i < 4) {
full_rounds_4_to_1[i] = full_rounds_4_to_1(i);
} else {
if(i<60) {
partial_round_4_to_1s[i-4] = partial_round_4_to_1(i);
} else {
full_rounds_4_to_1[i-56] = full_rounds_4_to_1(i);
}
}
}
for(var i=0; i<4; i++){
full_rounds_4_to_1[0].in[i] <== matrix.out[i];
}
for(var i=1; i<4; i++){
for(var j=0; j<4; j++){
full_rounds_4_to_1[i].in[j] <== full_rounds_4_to_1[i-1].out[j];
}
}
for(var i=0; i<4; i++){
partial_round_4_to_1s[0].in[i] <== full_rounds_4_to_1[3].out[i];
}
for(var i=1; i<56; i++){
for(var j=0; j<4; j++){
partial_round_4_to_1s[i].in[j] <== partial_round_4_to_1s[i-1].out[j];
}
}
for(var i=0; i<4; i++){
full_rounds_4_to_1[4].in[i] <== partial_round_4_to_1s[55].out[i];
}
for(var i=5; i<8; i++){
for(var j=0; j<4; j++){
full_rounds_4_to_1[i].in[j] <== full_rounds_4_to_1[i-1].out[j];
}
}
for(var i=0; i<4; i++){
out[i] <== full_rounds_4_to_1[7].out[i];
}
}
template hash_4_to_1(){
signal input in[4];
signal output out;
component perm = permutation_4_to_1();
perm.in[0] <== in[0];
perm.in[1] <== in[1];
perm.in[2] <== in[2];
perm.in[3] <== in[3];
out <== in[0] + perm.out[0];
}
//component main = hash_4_to_1();

View File

@ -1,193 +0,0 @@
//test
pragma circom 2.1.9;
function round_constant_16_to_1() {
return
[
39725799400017827115953999199803965513668921247606107843235739645000498452181,
42966428960558994593504354654034020585855169251008976179361555763424614464338,
1902577049757491257818576950592390026062184527103985176709404045325719879153,
44431672934524375006946320990995907220611992982569305140824479722873832750184,
39726183949244760384768131039650643342100328144953562677717530936076214603575,
47922249389084318636163655667342945193486098112364797914711366318805271081986,
1862870272947949400931550187895813583996084263112126758587127421895920740217,
4609552006052426829558648842629624826577232105300129098751251434249497379415,
35588143488957689566276930373759329909335354222484070944945535758095890233602,
31992851211763793548423275170246297274462525072830105768609534303798701174374,
10431109178659867018016774068824625279897747730577584847579124215705854088752,
1949666570245048798153069638552026706752846020986409274673577266743024227986,
26013146320492118585809324011747055383255013664810283913111923543378165512435,
24326326384498087823059984407171843358848416830861907662385192677188116053544,
22319685994625011021753350147173406654223939569203496437101532456482753075879,
50557239558368781744228704045005139069258908206255515650400270553037541504198,
8150349453804124148576142676639616213878444242674057629308915686941165448719,
48208850819924081505370182430049176104131115325038330030896851480045955495846,
23292055228237110741391983617517431423114804124284097964494568447865687504083,
41624195613852190072343927309438239744583865875755371975404916906916622520312,
35035764767249963834124347515646744980548162618519514861977709647292192162935,
4779348796643887084014079273412324900195658451616750603184150546614709227590,
33367047533960399900339953965992791362189146117008495287189183308885826514987,
47818152023063189199872106125697047204743569529570459808477570336306405682618,
42796246674763432543587686312218067656639355734975037053737259369488219415432,
10957190869792979750714342710039883244593973691851341486138757518667861871308,
2841790402482039728028394542789470351099439451234544313142331893197703007354,
16616683520944631525798957628064854348665295295102366742591213566889088018633,
33567370488316680379461825404457605756079279555675131093451020281219258632141,
20149108407482774388930550024591991805677394222603241325670591147763821350175,
26521955033333972827600806868235450804729772994352860271090218480508888628468,
30420917495722730561485028971813175058988495495112448737909833585405582002453,
28826298253194385387635350229770135429043506867664273190337060583321839575111,
17917025733340975563320009027981039582040740238333569779892727038742964339095,
7141322642265363206186621258281581108534976046127258038741170240455221165198,
19418423356096329136327193014171723261000987171654451855537930843119849003480,
4435246673426368856651403911455319600556213204117162371080963632405613232527,
19632896986964074847700416879011202636067522051661757108806676985789880273707,
27046963462399353439595827223611516072637119359583733706532920096544318625175,
46022420944605380770914903892871308087212302911540340258773948901501361016991,
47210247379686065208769144617004411377616699091411215517824991959313614962397,
10113618698993232512425817656261980665816667005776383524586380129027083138291,
35517438329843448024913764440686318451400431892618552836051616554728503908001,
15621081553202567263286903894992975334527971102321162065809849644051230558156,
29674547690110160534416981628193785576251233526911087635787729103482288097393,
48072441526206759351688872909792052037070864282054279767041551741286737196367,
41744043803776630924388673324290707208134439478043126394378048339212169592401,
9628276074092566929694879552911540910341944885042275367756464425374067624509,
20632626646113120307999197184021140185329277351497138331616553936227435116058,
20792210528194122935550939155383235642592438080224243249333876170013316543401,
40415491313636855559381927040556471386850767350804210034574345185034062472388,
42065986796325477298062230949689861704213331366919061593388137948694441619250,
40821207536769008545206744063766400532504619210533302382117795523897539697933,
25553665219208663753910822024028906032034541099513008737546655361577447316484,
19736663029664934322245808384029169299382853413147390505477065761633976373362,
41037270906646381161943193245472673282253590700725246354740042685574618941505,
26465673628980636091049213717769341512445753008415873261263203826832299352951,
37036784788783168689308644616358821855616430701564621669397983274253847911044,
16882309834972349171728263406452316383132803207143172570189837375172214690963,
49236009794362178305819055463654400779656334164463557593816047235183326696206,
39126492963181209630544294313956192397928968809823631059639413986679789778216,
43658389378690206885714590070566109002458688834417247158444257250935092974665,
16333104498316984295745962415236263230477082737132070203651697035209925593266,
2343404888674146320460570191540978518333195833255755810571688909855019156349,
24634045350057319695041104791403403368011675948761890270733136933077818947573,
24387229815091645818728740871562656675244609698356948940855886553509325623218,
34856435078036813743723173976791961760363416490222768467602434757897150562809,
22463928646505673196264844647723745514489344400622648158270067812328221291172,
38337547475660790190067897986042722249254601625800102257245591381379028610987,
30884758170575514019575313258747378429451169785327990741538528539964746232511,
407062347257081198418184706020217550797090175697390265997395699504028840069,
46072527669630030314941843287930470349120547732416735746099013950369555752487,
26598420173680844002096268043589508593110520210883302319058895397482348813138,
5468186730708689095665003796421147031372937271113374556364693295567666309881,
20408443200377694476685908188621206365577738334727573068844969120059071063384,
46981234183655934922934842049383026387012791700440415493493702691352740266098,
33551792494519814298680232023513160371021410923276291252829879529580574549607,
44191750214736553132933384320160073484141698637542792822319467448466449199959,
52082663085085422534369913780529050462333401292522763448650886744352341477846,
43609725693554764598774802211508572436819354508573541391712385270827954088014,
5509314597941212988576665300843166762362117860942586466472903661374654433047,
5559029914528165704027960512924831270184459421996344081783499760333465840454,
33524678638941473952008777383950476291303669122863259465508971654565607710124,
45645434759869537782219495003520693614316744086502894675070357053578529462611,
21634412361943063812483816878212759698145592627132630568177240468236243443997,
17296076019245918134776233380747899670718046224411673517180705100767962406954,
51440070128252977573576752509509289893411386048688470945863901737258119109741,
3594222373894239759942466635754825806993182513993455014470212549644348436736,
47959769456918498933526528689384868494120276948030111429507861237362437496210,
33000764793048989170342190628396476268404452069453776919602031823454420654656,
42826490422129152698636386897788577399393533635964594559886553174637239521118,
52295329105725197789753101315429895369766102629019133090017712989241053783558,
47880622238513674104247747676583724803255466382975859845069693487703628947714,
43936946713208191402441184330937985658846334880823513129204372649490118165491,
40251165390594695927371248080107666232732935108005358445481599233717782638896,
4374561185857417857316731922491353498974134405011029557830297994813315862559,
36035028519117241692429568027060454516008330481155302030640451954673337039870,
17169679336575379664065214518686885005225695064353947035596355048982268831028,
15880917696586343406953592641564615996605082216639892270189959812763710888748,
44053791831887360310582759225296188780718960772971991969178524168816504578804,
17891697801976794338721931255832783817787274947410906666444514892619618334272,
41860684084301922118560078323296728501588433716011882280914057750677004252514,
39634237355488544158215275263851269921534055658196710011242793797355974120931,
17147446725471655980188874591608844349450837795690392086436662207272648235970,
19402693173125609969856950331264436884921152880190529800026177590116055294038,
10691603198079109355998270513275267963583839999640707229593969158192066085397,
47540627356602773888603132684733863602762111482745208345804634126586257262607,
5915674545476155673196233396217928914866410645604699985302660208523245942237,
111251938011213760763774859243277527837142141250061606873636423012197111197,
35063286980316874255015992522343006303508619821794962259547057506813060931773,
4955838234826402705564139094252802999139115369004968713576517960060305039082,
13792409982596927634720969816052864004355280343403291329940320489270508883803,
35825741100880023876488868468112742657673252321462610504266451341355067205610,
28460915945533593428542040906830378549800618474095963851867763677018897302929,
9713844506249087416664024364428812240068094374028199286225738527757038112467,
40679805732400884118723774115665481614915421978306297159251228478606230752474,
29757946798627258745416990533455815630324656030573466209153051560180917776353,
48357362019104750186375328819952102172608585465016965207540831676602884269263,
32940491071431805169868501574465967021193902185553749640148719707932598780469,
7473125368630470049034003737446766486818477818719886735195316440180323968735,
49797314418731632305394406125363649977467316746705136554158771555038756351980,
29423812245635343436136357631167744312439395772431168176499761020256672974116,
17752952597488467689955328967514036081230334268062286286791238444994797946364,
11187314008830530006226896925828877981837282277801039676209354309840830166312,
1460570367181490316969148060693926446394822620570366788008558284806968117734,
2845512215983531260468619146202988365036283019984734085030635808663534080897,
13678775934492824068869109923010846046122089274150470818447401546000515089448,
41560010339997824874371372926655493150700423413706122338193288307311885566768,
44104701369840880307377204949341973251175518351389507661546336745348450403920,
16099171949124285044549692766555664705752094379574657435086067387762269145164,
10885502210016683506969436609216522437947532105991633231562168011909638111557,
52156298020032266431787014754649280499452461532044760665828040879517728539708,
33945410025064742625417443716276958550285900443924582459678703741650438534809,
42330185455056468790993939554345514151954186453281863597765777627606599578516,
4657049000824091386723963460476049183867985168345526464398818750489141737163,
21923801997589000370088914236235074435502416056621470668050389849529574106202,
15805689248891728058742321832039785423037087284565290950005114696831443231147,
45984185687363711365029866793756997560497628108006072393015670720821342880668,
39156427118840011190894400331617643276463742427839568112463350872444907680494,
17893081445111736451083202165540649827781358816986209263756161212394728333001,
36437118588111746025389127729913810175419804691977510411734238734357426423809,
48260118028483684631326190969379716083209813670977725322552249653459435387882,
40486986020827308332276345571616851806907994309632663940769016980912192516960,
35099819227656121544999230187647432362290129526704475429625894785506342902690,
27580239951806652383156459031577005530932247841092109348006802746879132126644,
23271341957819036356728305748625419304831156372249949335195015298360923297133,
42515055996716749819345238125802133364043851479046925751568447538867534641232,
28714009840464082058245378340345146078016662568993921795177048501158035190256,
1111216851713657365641977385220157904693120725668727899264987734176843126786,
34412967565386968523345579224490035779382635330951678114018655424976710134202,
42139998487524182591996890653589805817774015986629937281031206233447268328582,
21691713516840627241183176855164665841929652491546118303064101066110796188953,
27652419528236676047196125264032473043981854331278230828308077279941937298620,
31211569185747715573358506785717075277547885839683427922002064474550453938720,
12885686250323264975654813526936397901419023857524625007681452625820802164214,
38368208456555528544874775339563689416708041768804542366734634684956870468665,
17014127458377497594462762243899040828274799467801458439796258262209705848999,
18339473410858561688021816579378042667435599228737095147372090986285098295729,
30243070523454822835312974811746059176298060623371243491658504828859436915867,
6856623016702194887799030091421067262770379379384975426793372305588238369793,
14584928177339868798941696431226120632338622678933396299538143948251685736857,
28963568590115676917816187714525023427152141272289632646661816895205441501344,
15821449895801494782675541871540375313851597664972871699624592153555269853492,
26870110211337166665285488169972107901304782738602697811217352528389112713316,
29654640625766553122308126800147704038633411112031981115431401674463728957870,
45387771697529877530693987615375947783672003547457057946997587632853767376485,
51530073844213986083224257489799416809305283668200085363164553259742628578601,
39500637489121678568797859105259741238785871932514496730971686474963916800838,
34638632655721665381292046101540251812987268394182233780890406749905123665498,
47558773840542513144047273382754220597014222776549583477762891202886304283558,
34464683426026223214818536296789584915103714217643035512538086729011924346398,
50661423324933414471281644339552326226886136985713868196538700335246118227921,
16026951337367383175610820246210183497734025720194433489132017234538604936414,
33572475268799564642745000649407837861228346301126684294541252715366099579094,
26220434981437976873498592303656146371158505657662010285451539733034399969825,
31040488125858696173362986090795905945928951823554908571888900564555975057860,
47286385036886749775224009536390346046643937618292722852399698152345906543537,
20950917282535983122464307959293663918938997314569186126689031705635737272062,
16685712499755301665281386819771726363157372904949135525550583883571962834528,
18683291445525541017294795892345078328382688847480507122165708511223740177458,
2608268839331669212463985078421319322001352992807108968314090990777368891770,
40037105172855926626375817902131326490267684706159606232991633054381953553026,
21626330967116418140505001603028197974177240574915763170077069271066169546158,
35330469786033362269122965704661462637931218147681429112041541870602933338162,
7959740499179483922969783988740981409045430979967212583073048384801003055527
];
}

View File

@ -1,80 +0,0 @@
//test
pragma circom 2.1.9;
function round_constant_2_to_1() {
return
[
44510337639712444877093863969199054965277800588455612249278638908194748645831,
21803715039317278198490310228838761820084178670568647145430631061363562182159,
7624865858307587153533893753671854337113466346291121078558552645350285711947,
40816250157678830542785454550323790288400761867270997552332922267166370848099,
26700489303136047462599262740180012654857443933973506452655094204874268181798,
29300041198680547975810813644545348954050411371551740473502764872245855641482,
26494260871076350781917504826961109818301921647993891506179327799406892257760,
51471943067203395853539598076816386277188697473371359746626216561944728278869,
48874150250826827063647140518997592549563417409147246235831213929889330889464,
4957296567799842922524759318027693610815701909959689401077625970883603151110,
49787130886622940646628207982474849305464467960406760686521606845929813913147,
38626507234346048667761615866199783635070759234617387640403950557591257611930,
43672937506493322470130890010227422460105683953151094688032165492686807529714,
10282858088808039236495153687326481750629167926398528104702176163827531439774,
5929373583590601619353793840106929273025491048347772550388315300478156302480,
40523767159781096993564794726793344971416282562716017669035314514589021856544,
35087653160263082011551011896785452178273871331090954735353760094574180797326,
44066134544197993553720315073514236799698542066082224906667320314729128689851,
46811190561503483095087189032015959148465356044838419985597715002375968521789,
35502138198479058392251639631217384470706251578088034693745546686222031522574,
3011951966042824356793101436014075881633742606023423824609791334873649401619,
36441783079799715976603149530703751751672873737838939240893549516900746063885,
5949000965032854376013985161729805610095473216976505768565157587449663833146,
39334547265154726054631299624100840161191136653442409769156478840344483284117,
44407194440944549422962884120864337491414458688079798116475114348830479824132,
17726376508115223453307205134714318843193912409715438117420622264717671262663,
756868613004458973360577644537468651009832005811964377612175868388980341238,
3421893741771938128946389260799798658478598753415463644298734220953059738355,
13293243933107737951928282334791569607692876620282367672054893180625816893632,
11906453198605884256628058547608350794281153234160543833653104246224561572116,
41007993900563419378450318427807675773574107233531791780559911428122060668864,
48053112103639043655338341411293547635466618118313162578053483741000954697443,
32234194819559922425974652761643838211443296225838831687358769666643041225472,
48939529425812404248175324082406620877605698116805848434311747711965735603142,
23172302197508009638107441698229967178757578829167657081073715837516157038684,
26828245904250884987904133111377098838723772557669646848196202419087853870872,
36025164071480125389137319620343252251920437049927443652919962965645042660420,
42147865145919705097445974287709456827305052297675196211654971979806749888911,
20585606416170880487041307637777839232517038894653375498347934603702403525799,
1047663270527934381838445994762652910090839507177449076034186708210288801902,
49864990265274912108645272682223261996354786042911445790248422528668444967688,
20274910123179255493744356413243132767746258718293295072669857132542604950741,
39934722872842035804029775488645871956511886709858512717725127998627130523912,
33295937568441654166303959882114891655347924209941192993151592385097862772126,
39198754144978337534654702520273605486297255614756323128663775493042981926264,
48114214484211668830722398263059235215883885642960292320018016482221617479308,
20857205525756474383857323509517945359548153106777905032259140536596758842151,
20481512031474492331394869498229505122694442073123511672315331466779200648987,
5512348932066875222255592673449822544023582557729178288775446420395599163714,
14748707870289380337081091822758247948394420380976550635416667891847265434773,
20722592968207591585193709289557966995643707360519106502308701025990663556112,
30345071158541998337681526950804671230825251993252779307899796752848528236301,
37998633152333475045376762610205951441947316428701472139959038991258723083573,
25187075483245106412039082847435291293567789993240499080077480139071082713811,
19421269742609173994970218921590288196829015512476170234735579602917648585528,
44645626649350902490681022627010246390651823839290377812847048196342039743308,
38015410591674700109176981164929629504879929166582206795827935147005325179107,
15907673084411204300870039215095416489657280867726923876605554605918361454411,
4839910768263945909615643698821897421248623201436406727882801614226282796736,
11993166323725114372511567048380837525145267539902083755578961856890086640616,
13920948384274828210917386586592591296235909076917892178237942711445546791673,
890670937435713979056767019654860866935017937714294844928044822115961948695,
17228860181078068965008756660486864527552317469394243328944319614877053158985,
10077644153064320976006893555780056518106113458749153233744229760482343163199,
49940012233787551970719440300197866554675665187348390484098206972627022147562,
46156268877611784805956766593634373731938578230585206172333523828368963221701,
22953533088186447995354081903847946065608888217162100116127853233026059928601,
52274456635025394989373456728632213614198023598074828050923870917877714774032,
10763107301772445560209819564880953581415947909035345171575074311681161298071,
18925434003927090811791086956853651992753402455627802833236246367412669605539,
44640541969065703218376218137336488126193962189090743983027473909004591005110,
6325804276918590364991192431609508508777152352802958405080031341778877821773
];
}

View File

@ -1,96 +0,0 @@
//test
pragma circom 2.1.9;
function round_constant_4_to_1() {
return
[
11865901593870436687704696210307853465124332568266803587887584059192277437537,
37413344849675497106163505103761203874617077416461933389729149896951619083615,
32493856687297537788073517556470839888070933486712636845483468275561142904504,
8106572321306448561272383558012749963748358844705299406391447161298410877832,
11707331945334514286120137391947350087632085623772869951863164361695922976568,
50176353669915139758684707864014381736527453065793678083699453978150986704353,
7614231165138437703715796351400512419034157550777684039873810826440625723695,
17108745804308684637964438487237723214541645477949369557189249702220750722331,
28482709556494724328894800736802198653800073555798724636385135549439085356742,
22084621272529558534346674593668266856649195963035162420257478396107381285157,
11065046937453971018193111360820446155970823623967390073553725256595768408791,
20163386569362559253936962862374791389308839238220230985809310822791529262025,
3941572053547598429065422950522133819874343789089916995553450661687375302109,
26478286544099137612981910043301624023925078357447813396543283503388535703096,
20695873604353009531429015276900191600064214090812802713214397507580078182919,
13125722302273298866746961565666978849814465870768123336569424431819752980076,
36198064501926046106576802008779486932990788729159233810880339338049275796987,
44304460846758155168737768840994398685118878625607355725968797162919830864102,
33427295080737122973704388239917504856466726697805464799279074730831006493899,
33676819385378678616140345579679379172852136878360832374035200947147349341877,
44698579309865383047943970651850256651158236406641741596599260270592257060333,
9785548396072733556484927856146778907814788851086349315764873426432645263872,
13443943788901083053739342733252043423900693132812974385986650498262359453435,
50643729733611061821734405325096960434556494526582143101458996741611494836986,
9762302758250004682914036756566790454206292929079802149918241419991743778078,
19475373737975172049750799347581927313285945820087657933615778552974211829387,
26326676308398320579169539788392437654921007121904386041440053251920191437301,
33434337088018971767011967694326287068660679954245122268447231545106574191053,
21854837019991553667332010956652219921642250105983660108852707854862240766704,
1855873836256370364169888814967543928768577071445146807885001909257610924575,
48105724357874736702308498318239595022868478610964925776544998873327877770469,
6893757226114776013992120610353413647048965744053221939747330482283347049271,
49492933790401867565879330847407697876101917412920943837692305231776568086150,
43522959518323197786977932091172575965428037444858136419745890338308804820810,
39369220628770987071776708725487093142438968678975788148890686830600891659237,
24332002500271167754445178113059124234684848763578719088484322891936508359054,
32863475623207582419161401899951874256189430526558709698459253237664899579477,
8315390532973093090228198037973187268458339671135900692256692995983001224287,
41596164941281344945126840056611498785955123869980989807278169650894369778621,
41140021013127548285923961611241892352480288807646515822914427245468443615449,
42624333566444295089232230699974262280460377983015559040916764999567317327294,
29425841969458336716648866633284898031574592123216791821970989517602546368463,
20194832349178074328255630030474794676357522951312816945265283318496141911576,
33508834389330212986852784163678812323448884912646004437785005736522859730449,
20197489266521008707527755143868210833027985912465941510937472218208331469324,
38189796622106345878699238475711002255025750905901925248625120562682573353793,
48437331749916394313065146750618123382683254942785601073233866557242834888501,
34815884667490928168338620954175830688114531237099462583592020572423301193334,
1316079587764339149090919530288539945185249635387918305928554726824292235069,
33564480841331620167847153616337187248054503582700661803825728035418602546478,
4635634898381888421672273828316335969974599848444510316738469345444620659008,
8644506076646842294589324870931361199184791348209582052726445382015132439419,
39498585060657083972778194861599167626335350278223243726925173218749695943806,
42901602831339057007425445486193581840749112246589631302873671293308101878875,
20119933204882102974459031584507100339282292349398588923453836079377072829543,
7917862289043363038204972116125424279857433068189510615392330392863075948512,
41284417024025222157952919191031968108126105524670279472881067727309802924938,
11213861995768467857413038001306057240793870929626059934261458727946548965379,
2291742710611132809700323762125675349484016058554275673428643410085506076100,
30099159053997341705317995418169313532098300934328131162175924134794709943047,
447035513285578307783519781307142266645679652807941291454847780415896684065,
19941446202184504378547837635870560393064630187876613630546846906393007677289,
7595261399959684629699197426920893479848768772071384660164934610968891053864,
51598580281806900142260694365187051410317675046136337884836978415482902327015,
12450848281586712352554721829724230078424064515794153380314705783292880037478,
5237102499670441785007944785581992844697685968922355014280712201430686167152,
1412524057853628881005630586377727487233247150373319518286783509614859257068,
38519766408760192821848550196157518411386556623071006612683448412823634200875,
11338671486975802181674275776989710780888734229624346786700048285586675342901,
23124572501783393477231165425714476214042723292141825213493635111951207504070,
21528356110015199451243279738115385806356940590132503530639630620611521954326,
6284174238932569340060925799940162325946442751185026413727709496271066916876,
48373517651545249281510690416218268384343400250317171450103976311090286221260,
27752440147182328733098243645400559151338503658043397110598417983425635093551,
43156725395743020846958899706072234263962738024394096815001388170789961679788,
48906049704561774201639151262665470255437206145980347197443063657678740507943,
24918160465086526594937065443815615610757370328053649165018481775513828479869,
36462368786443951186110721729238677880688318912401935278190656741197184273952,
37367696075403883562827939745268661270924157618310868295845006320225084994632,
42130603320119794983803262970740129474583503116320676437504579920473229006778,
12096038367976885628335054904138821822550042039079703385879844461517464118581,
34671362090033614505367959844073659507869267381932134573786004532584171425818,
15908652423714359894720614650322760756461828514699821946843077879932200328081,
7518568119601342737128460613704294443674406422237476295695786631549469567412,
33513737101700389003254558060695049730922342329295390135821890558696123720054,
49765425774819103826723198731734445691737353182147628471479513204868044796119,
48731721046471530891684818884908827036844194399863789073273030545326532602503,
1994879948378542466338304292753049990663872919840272992167645879411261807091
];
}

View File

@ -0,0 +1,55 @@
//test
pragma circom 2.1.9;
include "../hash_bn/poseidon2_hash.circom";
include "../circomlib/circuits/comparators.circom";
// compute a merkle root of depth n
// /!\ To call this function, it's important to check that each selector is a bit before!!!
template compute_merkle_root(n) {
signal input nodes[n]; // The Merkle path
signal input selector[n]; // it's the leaf's indice in big endian bits indicating if complementary nodes are left or right
signal input leaf;
signal output root;
component compression_hash[n];
compression_hash[0] = Poseidon2_hash(2);
compression_hash[0].inp[0] <== leaf - selector[n-1] * (leaf - nodes[0]);
compression_hash[0].inp[1] <== nodes[0] - selector[n-1] * (nodes[0] - leaf);
for(var i=1; i<n; i++){
compression_hash[i] = Poseidon2_hash(2);
compression_hash[i].inp[0] <== compression_hash[i-1].out - selector[n-1-i] * (compression_hash[i-1].out - nodes[i]);
compression_hash[i].inp[1] <== nodes[i] - selector[n-1-i] * (nodes[i] - compression_hash[i-1].out);
}
root <== compression_hash[n-1].out;
}
// Verify a Merkle proof of depth n
// /!\ To call this function, it's important to check that each selector is a bit before!!!
template proof_of_membership(n) {
signal input nodes[n]; // The Merkle path
signal input selector[n]; // it's the leaf's indice in big endian bits indicating if complementary nodes are left or right
signal input root;
signal input leaf;
signal output out;
component root_calculator = compute_merkle_root(n);
for(var i=0; i<n; i++){
root_calculator.nodes[i] <== nodes[i];
root_calculator.selector[i] <== selector[i];
}
root_calculator.leaf <== leaf;
component eq = IsEqual();
eq.in[0] <== root_calculator.root;
eq.in[1] <== root;
out <== eq.out;
}

View File

@ -0,0 +1,19 @@
//
pragma circom 2.1.9;
include "poseidon2_sponge.circom";
//------------------------------------------------------------------------------
// Hash `n` field elements into 1, with approximately 254 bits of preimage security (?)
// (assuming bn128 scalar field. We use capacity=2, rate=1, t=3).
template Poseidon2_hash(n) {
signal input inp[n];
signal output out;
component sponge = PoseidonSponge(3,2,n,1);
sponge.inp <== inp;
sponge.out[0] ==> out;
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,217 @@
//
pragma circom 2.1.9;
//
// The Poseidon2 permutation for bn128 and t=3
//
//------------------------------------------------------------------------------
// The S-box
template SBox() {
signal input inp;
signal output out;
signal x2 <== inp*inp;
signal x4 <== x2*x2;
out <== inp*x4;
}
//------------------------------------------------------------------------------
// partial or internal round
template InternalRound(i) {
signal input inp[3];
signal output out[3];
var round_consts[56] =
[0x1a1d063e54b1e764b63e1855bff015b8cedd192f47308731499573f23597d4b5,
0x26abc66f3fdf8e68839d10956259063708235dccc1aa3793b91b002c5b257c37,
0x0c7c64a9d887385381a578cfed5aed370754427aabca92a70b3c2b12ff4d7be8,
0x1cf5998769e9fab79e17f0b6d08b2d1eba2ebac30dc386b0edd383831354b495,
0x0f5e3a8566be31b7564ca60461e9e08b19828764a9669bc17aba0b97e66b0109,
0x18df6a9d19ea90d895e60e4db0794a01f359a53a180b7d4b42bf3d7a531c976e,
0x04f7bf2c5c0538ac6e4b782c3c6e601ad0ea1d3a3b9d25ef4e324055fa3123dc,
0x29c76ce22255206e3c40058523748531e770c0584aa2328ce55d54628b89ebe6,
0x198d425a45b78e85c053659ab4347f5d65b1b8e9c6108dbe00e0e945dbc5ff15,
0x25ee27ab6296cd5e6af3cc79c598a1daa7ff7f6878b3c49d49d3a9a90c3fdf74,
0x138ea8e0af41a1e024561001c0b6eb1505845d7d0c55b1b2c0f88687a96d1381,
0x306197fb3fab671ef6e7c2cba2eefd0e42851b5b9811f2ca4013370a01d95687,
0x1a0c7d52dc32a4432b66f0b4894d4f1a21db7565e5b4250486419eaf00e8f620,
0x2b46b418de80915f3ff86a8e5c8bdfccebfbe5f55163cd6caa52997da2c54a9f,
0x12d3e0dc0085873701f8b777b9673af9613a1af5db48e05bfb46e312b5829f64,
0x263390cf74dc3a8870f5002ed21d089ffb2bf768230f648dba338a5cb19b3a1f,
0x0a14f33a5fe668a60ac884b4ca607ad0f8abb5af40f96f1d7d543db52b003dcd,
0x28ead9c586513eab1a5e86509d68b2da27be3a4f01171a1dd847df829bc683b9,
0x1c6ab1c328c3c6430972031f1bdb2ac9888f0ea1abe71cffea16cda6e1a7416c,
0x1fc7e71bc0b819792b2500239f7f8de04f6decd608cb98a932346015c5b42c94,
0x03e107eb3a42b2ece380e0d860298f17c0c1e197c952650ee6dd85b93a0ddaa8,
0x2d354a251f381a4669c0d52bf88b772c46452ca57c08697f454505f6941d78cd,
0x094af88ab05d94baf687ef14bc566d1c522551d61606eda3d14b4606826f794b,
0x19705b783bf3d2dc19bcaeabf02f8ca5e1ab5b6f2e3195a9d52b2d249d1396f7,
0x09bf4acc3a8bce3f1fcc33fee54fc5b28723b16b7d740a3e60cef6852271200e,
0x1803f8200db6013c50f83c0c8fab62843413732f301f7058543a073f3f3b5e4e,
0x0f80afb5046244de30595b160b8d1f38bf6fb02d4454c0add41f7fef2faf3e5c,
0x126ee1f8504f15c3d77f0088c1cfc964abcfcf643f4a6fea7dc3f98219529d78,
0x23c203d10cfcc60f69bfb3d919552ca10ffb4ee63175ddf8ef86f991d7d0a591,
0x2a2ae15d8b143709ec0d09705fa3a6303dec1ee4eec2cf747c5a339f7744fb94,
0x07b60dee586ed6ef47e5c381ab6343ecc3d3b3006cb461bbb6b5d89081970b2b,
0x27316b559be3edfd885d95c494c1ae3d8a98a320baa7d152132cfe583c9311bd,
0x1d5c49ba157c32b8d8937cb2d3f84311ef834cc2a743ed662f5f9af0c0342e76,
0x2f8b124e78163b2f332774e0b850b5ec09c01bf6979938f67c24bd5940968488,
0x1e6843a5457416b6dc5b7aa09a9ce21b1d4cba6554e51d84665f75260113b3d5,
0x11cdf00a35f650c55fca25c9929c8ad9a68daf9ac6a189ab1f5bc79f21641d4b,
0x21632de3d3bbc5e42ef36e588158d6d4608b2815c77355b7e82b5b9b7eb560bc,
0x0de625758452efbd97b27025fbd245e0255ae48ef2a329e449d7b5c51c18498a,
0x2ad253c053e75213e2febfd4d976cc01dd9e1e1c6f0fb6b09b09546ba0838098,
0x1d6b169ed63872dc6ec7681ec39b3be93dd49cdd13c813b7d35702e38d60b077,
0x1660b740a143664bb9127c4941b67fed0be3ea70a24d5568c3a54e706cfef7fe,
0x0065a92d1de81f34114f4ca2deef76e0ceacdddb12cf879096a29f10376ccbfe,
0x1f11f065202535987367f823da7d672c353ebe2ccbc4869bcf30d50a5871040d,
0x26596f5c5dd5a5d1b437ce7b14a2c3dd3bd1d1a39b6759ba110852d17df0693e,
0x16f49bc727e45a2f7bf3056efcf8b6d38539c4163a5f1e706743db15af91860f,
0x1abe1deb45b3e3119954175efb331bf4568feaf7ea8b3dc5e1a4e7438dd39e5f,
0x0e426ccab66984d1d8993a74ca548b779f5db92aaec5f102020d34aea15fba59,
0x0e7c30c2e2e8957f4933bd1942053f1f0071684b902d534fa841924303f6a6c6,
0x0812a017ca92cf0a1622708fc7edff1d6166ded6e3528ead4c76e1f31d3fc69d,
0x21a5ade3df2bc1b5bba949d1db96040068afe5026edd7a9c2e276b47cf010d54,
0x01f3035463816c84ad711bf1a058c6c6bd101945f50e5afe72b1a5233f8749ce,
0x0b115572f038c0e2028c2aafc2d06a5e8bf2f9398dbd0fdf4dcaa82b0f0c1c8b,
0x1c38ec0b99b62fd4f0ef255543f50d2e27fc24db42bc910a3460613b6ef59e2f,
0x1c89c6d9666272e8425c3ff1f4ac737b2f5d314606a297d4b1d0b254d880c53e,
0x03326e643580356bf6d44008ae4c042a21ad4880097a5eb38b71e2311bb88f8f,
0x268076b0054fb73f67cee9ea0e51e3ad50f27a6434b5dceb5bdde2299910a4c9];
component sb = SBox();
sb.inp <== inp[0] + round_consts[i];
out[0] <== 2*sb.out + inp[1] + inp[2];
out[1] <== sb.out + 2*inp[1] + inp[2];
out[2] <== sb.out + inp[1] + 3*inp[2];
}
//------------------------------------------------------------------------------
// external rounds
template ExternalRound(i) {
signal input inp[3];
signal output out[3];
var round_consts[8][3] =
[ [ 0x1d066a255517b7fd8bddd3a93f7804ef7f8fcde48bb4c37a59a09a1a97052816
, 0x29daefb55f6f2dc6ac3f089cebcc6120b7c6fef31367b68eb7238547d32c1610
, 0x1f2cb1624a78ee001ecbd88ad959d7012572d76f08ec5c4f9e8b7ad7b0b4e1d1
]
, [ 0x0aad2e79f15735f2bd77c0ed3d14aa27b11f092a53bbc6e1db0672ded84f31e5
, 0x2252624f8617738cd6f661dd4094375f37028a98f1dece66091ccf1595b43f28
, 0x1a24913a928b38485a65a84a291da1ff91c20626524b2b87d49f4f2c9018d735
]
, [ 0x22fc468f1759b74d7bfc427b5f11ebb10a41515ddff497b14fd6dae1508fc47a
, 0x1059ca787f1f89ed9cd026e9c9ca107ae61956ff0b4121d5efd65515617f6e4d
, 0x02be9473358461d8f61f3536d877de982123011f0bf6f155a45cbbfae8b981ce
]
, [ 0x0ec96c8e32962d462778a749c82ed623aba9b669ac5b8736a1ff3a441a5084a4
, 0x292f906e073677405442d9553c45fa3f5a47a7cdb8c99f9648fb2e4d814df57e
, 0x274982444157b86726c11b9a0f5e39a5cc611160a394ea460c63f0b2ffe5657e
]
, [ 0x1acd63c67fbc9ab1626ed93491bda32e5da18ea9d8e4f10178d04aa6f8747ad0
, 0x19f8a5d670e8ab66c4e3144be58ef6901bf93375e2323ec3ca8c86cd2a28b5a5
, 0x1c0dc443519ad7a86efa40d2df10a011068193ea51f6c92ae1cfbb5f7b9b6893
]
, [ 0x14b39e7aa4068dbe50fe7190e421dc19fbeab33cb4f6a2c4180e4c3224987d3d
, 0x1d449b71bd826ec58f28c63ea6c561b7b820fc519f01f021afb1e35e28b0795e
, 0x1ea2c9a89baaddbb60fa97fe60fe9d8e89de141689d1252276524dc0a9e987fc
]
, [ 0x0478d66d43535a8cb57e9c1c3d6a2bd7591f9a46a0e9c058134d5cefdb3c7ff1
, 0x19272db71eece6a6f608f3b2717f9cd2662e26ad86c400b21cde5e4a7b00bebe
, 0x14226537335cab33c749c746f09208abb2dd1bd66a87ef75039be846af134166
]
, [ 0x01fd6af15956294f9dfe38c0d976a088b21c21e4a1c2e823f912f44961f9a9ce
, 0x18e5abedd626ec307bca190b8b2cab1aaee2e62ed229ba5a5ad8518d4e5f2a57
, 0x0fc1bbceba0590f5abbdffa6d3b35e3297c021a3a409926d0e2d54dc1c84fda6
]
];
component sb[3];
for(var j=0; j<3; j++) {
sb[j] = SBox();
sb[j].inp <== inp[j] + round_consts[i][j];
}
out[0] <== 2*sb[0].out + sb[1].out + sb[2].out;
out[1] <== sb[0].out + 2*sb[1].out + sb[2].out;
out[2] <== sb[0].out + sb[1].out + 2*sb[2].out;
}
//------------------------------------------------------------------------------
// the initial linear layer
template LinearLayer() {
signal input inp[3];
signal output out[3];
out[0] <== 2*inp[0] + inp[1] + inp[2];
out[1] <== inp[0] + 2*inp[1] + inp[2];
out[2] <== inp[0] + inp[1] + 2*inp[2];
}
//------------------------------------------------------------------------------
// the Poseidon2 permutation for t=3
template Permutation() {
signal input inp[3];
signal output out[3];
signal aux[65][3];
component ll = LinearLayer();
for(var j=0; j<3; j++) { ll.inp[j] <== inp[j]; }
for(var j=0; j<3; j++) { ll.out[j] ==> aux[0][j]; }
component ext[8];
for(var k=0; k<8; k++) { ext[k] = ExternalRound(k); }
component int[56];
for(var k=0; k<56; k++) { int[k] = InternalRound(k); }
// first 4 external rounds
for(var k=0; k<4; k++) {
for(var j=0; j<3; j++) { ext[k].inp[j] <== aux[k ][j]; }
for(var j=0; j<3; j++) { ext[k].out[j] ==> aux[k+1][j]; }
}
// the 56 internal rounds
for(var k=0; k<56; k++) {
for(var j=0; j<3; j++) { int[k].inp[j] <== aux[k+4][j]; }
for(var j=0; j<3; j++) { int[k].out[j] ==> aux[k+5][j]; }
}
// last 4 external rounds
for(var k=0; k<4; k++) {
for(var j=0; j<3; j++) { ext[k+4].inp[j] <== aux[k+60][j]; }
for(var j=0; j<3; j++) { ext[k+4].out[j] ==> aux[k+61][j]; }
}
for(var j=0; j<3; j++) { out[j] <== aux[64][j]; }
}
//------------------------------------------------------------------------------
// the "compression function" takes 2 field elements as input and produces
// 1 field element as output. It is a trivial application of the permutation.
template Compression() {
signal input inp[2];
signal output out;
component perm = Permutation();
perm.inp[0] <== inp[0];
perm.inp[1] <== inp[1];
perm.inp[2] <== 0;
perm.out[0] ==> out;
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,123 @@
//
pragma circom 2.1.9;
include "poseidon2_perm.circom";
//------------------------------------------------------------------------------
function min(a,b) {
return (a <= b) ? a : b;
}
//------------------------------------------------------------------------------
//
// Poseidon sponge construction
//
// t = size of state (currently fixed to 3)
// c = capacity (1 or 2)
// r = rate = t - c
//
// everything is measured in number of field elements
//
// we use the padding `10*` from the original Poseidon paper,
// and initial state constant zero. Note that this is different
// from the "SAFE padding" recommended in the Poseidon2 paper
// (which uses `0*` padding and a nontrivial initial state)
//
template PoseidonSponge(t, capacity, input_len, output_len) {
var rate = t - capacity;
assert( t == 3);
assert( capacity > 0 );
assert( rate > 0 );
assert( capacity < t );
assert( rate < t );
signal input inp[ input_len];
signal output out[output_len];
// round up to rate the input + 1 field element ("10*" padding)
var nblocks = ((input_len + 1) + (rate-1)) \ rate;
var nout = (output_len + (rate-1)) \ rate;
var padded_len = nblocks * rate;
signal padded[padded_len];
for(var i=0; i<input_len; i++) { padded[i] <== inp[i]; }
padded[input_len ] <== 1;
for(var i=input_len+1; i<padded_len; i++) { padded[i] <== 0; }
signal state [nblocks+nout][t ];
signal sorbed[nblocks ][rate];
// initialize state
for(var i=0; i<t; i++) { state[0][i] <== 0; }
component absorb [nblocks];
component squeeze[nout-1];
for(var m=0; m<nblocks; m++) {
for(var i=0; i<rate; i++) {
var a = state [m][i];
var b = padded[m*rate+i];
sorbed[m][i] <== a + b;
}
absorb[m] = Permutation();
for(var j=0 ; j<rate; j++) { absorb[m].inp[j] <== sorbed[m][j]; }
for(var j=rate; j<t ; j++) { absorb[m].inp[j] <== state [m][j]; }
absorb[m].out ==> state[m+1];
}
var q = min(rate, output_len);
for(var i=0; i<q; i++) {
state[nblocks][i] ==> out[i];
}
var out_ptr = rate;
for(var n=1; n<nout; n++) {
squeeze[n-1] = Permutation();
squeeze[n-1].inp <== state[nblocks+n-1];
squeeze[n-1].out ==> state[nblocks+n ];
var q = min(rate, output_len-out_ptr);
for(var i=0; i<q; i++) {
state[nblocks+n][i] ==> out[out_ptr+i];
}
out_ptr += rate;
}
}
//------------------------------------------------------------------------------
//
// sponge hash with rate=1
//
template Poseidon2_sponge_hash_rate_1(n) {
signal input inp[n];
signal output out;
component sponge = PoseidonSponge(3, 2, n, 1);
sponge.inp <== inp;
sponge.out[0] ==> out;
}
//
// sponge hash with rate=2
//
template Poseidon2_sponge_hash_rate_2(n) {
signal input inp[n];
signal output out;
component sponge = PoseidonSponge(3, 1, n, 1);
sponge.inp <== inp;
sponge.out[0] ==> out;
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,30 @@
//test
pragma circom 2.1.9;
include "../hash_bn/poseidon2_hash.circom";
include "../misc/constants.circom";
template derive_secret_key(){
signal input starting_slot;
signal input secrets_root;
signal output out;
component hash = Poseidon2_hash(3);
component dst = NOMOS_POL_SK_V1();
hash.inp[0] <== dst.out;
hash.inp[1] <== starting_slot;
hash.inp[2] <== secrets_root;
out <== hash.out;
}
template derive_public_key(){
signal input secret_key;
signal output out;
component hash = Poseidon2_hash(2);
component dst = NOMOS_KDF();
hash.inp[0] <== dst.out;
hash.inp[1] <== secret_key;
out <== hash.out;
}

View File

@ -0,0 +1,80 @@
//test
pragma circom 2.1.9;
include "../circomlib/circuits/bitify.circom";
include "../circomlib/circuits/comparators.circom";
// If a or b isn't guaranteed to be less than p use SafeFullComparator
// See https://www.notion.so/nomos-tech/Comparisons-1fd261aa09df81feae1ff3e6612b92a0
template SafeFullLessThan() {
signal input a;
signal input b;
signal output out;
component bitifier_a = Num2Bits_strict();
component bitifier_b = Num2Bits_strict();
bitifier_a.in <== a;
bitifier_b.in <== b;
component numifier_a = Bits2Num(252);
component numifier_b = Bits2Num(252);
for(var i =0; i<252; i++){
numifier_a.in[i] <== bitifier_a.out[i+2];
numifier_b.in[i] <== bitifier_b.out[i+2];
}
component A = LessThan(252);
A.in[0] <== numifier_b.out;
A.in[1] <== numifier_a.out;
component B = IsEqual();
B.in[0] <== numifier_a.out;
B.in[1] <== numifier_b.out;
component C = IsEqual();
C.in[0] <== bitifier_a.out[1];
C.in[1] <== bitifier_b.out[1];
component D = IsEqual();
D.in[0] <== bitifier_a.out[1];
D.in[1] <== 1;
component E = IsEqual();
E.in[0] <== bitifier_a.out[0];
E.in[1] <== bitifier_b.out[0];
component F = IsEqual();
F.in[0] <== bitifier_a.out[0];
F.in[1] <== 1;
signal intermediate_results[4];
intermediate_results[0] <== (1 - C.out) * (1-D.out);
intermediate_results[1] <== (1 - C.out) * (1-E.out);
intermediate_results[2] <== intermediate_results[1] * (1- F.out);
intermediate_results[3] <== B.out * (intermediate_results[0] + intermediate_results[2]);
out <== (1 - A.out) * ((1 - B.out) + intermediate_results[3]);
}
// Safely compare two n-bit numbers
// Performs range checks on the inputs to avoid overflow. Range is n <= 252
template SafeLessThan(n) {
assert(n <= 252);
signal input in[2];
signal output out;
component aInRange = Num2Bits(n);
aInRange.in <== in[0];
component bInRange = Num2Bits(n);
bInRange.in <== in[1];
component lt = LessThan(n);
lt.in[0] <== in[0];
lt.in[1] <== in[1];
out <== lt.out;
}

View File

@ -0,0 +1,67 @@
//test
pragma circom 2.1.9;
include "../circomlib/circuits/bitify.circom";
include "../circomlib/circuits/comparators.circom";
// int.from_bytes(b"LEAD_V1", byteorder="little") = 13887241025832268
template LEAD_V1(){
signal output out;
out <== 13887241025832268;
}
// int.from_bytes(b"NOMOS_POL_SK_V1", byteorder="little") = 256174383281726064679014503048630094
template NOMOS_POL_SK_V1(){
signal output out;
out <== 256174383281726064679014503048630094;
}
// int.from_bytes(b"NOMOS_NONCE_CONTRIB_V1", byteorder="little") = 18459309511848927313552932915476467038165525790019406
template NOMOS_NONCE_CONTRIB_V1(){
signal output out;
out <== 18459309511848927313552932915476467038165525790019406;
}
// int.from_bytes(b"NOMOS_KDF", byteorder="little") = 1296193216988918402894
template NOMOS_KDF(){
signal output out;
out <== 1296193216988918402894;
}
// int.from_bytes(b"NOMOS_NOTE_ID_V1", byteorder="little") = 65580641562429851895355409762135920462
template NOMOS_NOTE_ID_V1(){
signal output out;
out <== 65580641562429851895355409762135920462;
}
// int.from_bytes(b"SELECTION_RANDOMNESS_V1", byteorder="little") = 4725583332308041445519605499429790922252397838206780755
template SELECTION_RANDOMNESS_V1(){
signal output out;
out <== 4725583332308041445519605499429790922252397838206780755;
}
// int.from_bytes(b"KEY_NULLIFIER_V1", byteorder="little") = 65580642670359595206974785265459610955
template KEY_NULLIFIER_V1(){
signal output out;
out <== 65580642670359595206974785265459610955;
}
// int.from_bytes(b"REWARD_VOUCHER", byteorder="little") = 1668646695034522932676805048878418
template REWARD_VOUCHER(){
signal output out;
out <== 1668646695034522932676805048878418;
}
// int.from_bytes(b"VOUCHER_NF", byteorder="little") = 332011368467182873038678
template VOUCHER_NF(){
signal output out;
out <== 332011368467182873038678;
}

@ -0,0 +1 @@
Subproject commit 998383787ee86bcb6bfb8741e9a638d203c08eae

View File

@ -1,103 +0,0 @@
//test
pragma circom 2.1.9;
include "../../circom_circuits/hash/poseidon/poseidon_16_to_1_Jubjub.circom";
include "../../circom_circuits/hash/poseidon/poseidon_4_to_1_Jubjub.circom";
template coefficient_hash(){
signal input coefficients[2048];
signal output hash;
component hasher[136];
hasher[0] = permutation_16_to_1();
hasher[0].in[0] <== 0;
for(var i = 1; i<16; i++){
hasher[0].in[i] <== coefficients[i-1];
}
for(var i = 1; i<136; i++){
hasher[i] = permutation_16_to_1();
hasher[i].in[0] <== hasher[i-1].out[0];
for(var j = 1; j<16; j++){
hasher[i].in[j] <== hasher[i-1].out[j] + coefficients[15*i+j-1];
}
}
component final_hasher = hash_16_to_1();
for (var i =0; i<8; i++){
final_hasher.in[i] <== hasher[135].out[i] + coefficients[2040+i];
}
for (var i =8; i<16; i++){
final_hasher.in[i] <== hasher[135].out[i];
}
hash <== final_hasher.out;
}
template drawn_random_point(){
signal input da_commitment[2];
signal input hash_of_data;
signal output x_0;
component final_hasher = hash_4_to_1();
final_hasher.in[0] <== 0;
final_hasher.in[1] <== da_commitment[0];
final_hasher.in[2] <== da_commitment[1];
final_hasher.in[3] <== hash_of_data;
x_0 <== final_hasher.out;
}
template evaluate_polynomial(){
signal input coefficients[2048];
signal input evaluation_point;
signal output result;
signal intermediate_values[2046];
intermediate_values[2045] <== coefficients[2047] * evaluation_point + coefficients[2046];
for(var i = 2044; i >= 0; i--){
intermediate_values[i] <== coefficients[i + 1] + intermediate_values[i+1] * evaluation_point;
}
result <== coefficients[0] + intermediate_values[0] * evaluation_point;
}
template proof_of_equivalence(){
signal input coefficients[2048];
signal input da_commitment[2];
signal output x_0;
signal output y_0;
signal output coefficients_hash;
//Hash of the coefficients
component coefficient_hasher = coefficient_hash();
for(var i = 0; i<2048; i++){
coefficient_hasher.coefficients[i] <== coefficients[i];
}
coefficients_hash <== coefficient_hasher.hash;
//Hash the coefficient hash with the da_commitment
component point_drawer = drawn_random_point();
point_drawer.da_commitment[0] <== da_commitment[0];
point_drawer.da_commitment[1] <== da_commitment[1];
point_drawer.hash_of_data <== coefficients_hash;
x_0 <== point_drawer.x_0;
//Evaluate the polynomial at x_0
component evaluator = evaluate_polynomial();
evaluator.evaluation_point <== x_0;
for(var i =0; i<2048; i++){
evaluator.coefficients[i] <== coefficients[i];
}
y_0 <== evaluator.result;
}
component main {public [da_commitment]} = proof_of_equivalence();

File diff suppressed because it is too large Load Diff

View File

@ -1,301 +0,0 @@
//test
pragma circom 2.1.9;
include "../../circom_circuits/hash/anemoi/anemoi_2_to_1_Jubjub.circom";
include "../../circom_circuits/hash/anemoi/anemoi_4_to_1_Jubjub.circom";
include "../../circom_circuits/hash/anemoi/anemoi_16_to_1_Jubjub.circom";
include "../../circom_circuits/circomlib/circuits/bitify.circom";
template BLSLessThan(n) {
assert(n <= 253);
signal input in[2];
signal output out;
component n2b = Num2Bits(n+1);
n2b.in <== in[0]+ (1<<n) - in[1];
out <== 1-n2b.out[n];
}
template BLSNum2Bits_strict() {
signal input in;
signal output out[255];
component check_range = CompConstant(23487852865797141623554994256013988874373056334117496812739262697960298774528); // -1 - 2**254 (p-1 without its first bit)
component n2b = Num2Bits(255);
in ==> n2b.in;
for (var i=0; i<255; i++) {
n2b.out[i] ==> out[i];
if(i != 0){
n2b.out[i] ==> check_range.in[i-1];
}
}
check_range.out * (n2b.out[0]) === 0; //must be zero exept if the first bit is 0 => then in is on 254 bits and p-1 on 255
}
template BLSBits2Num_strict() {
signal input in[255];
signal output out;
component check_range = CompConstant(23487852865797141623554994256013988874373056334117496812739262697960298774528);
component b2n = Bits2Num(255);
for (var i=0; i<255; i++) {
in[i] ==> b2n.in[i];
if(i != 0){
in[i] ==> check_range.in[i-1];
}
}
check_range.out * in[0] === 0;
b2n.out ==> out;
}
template check_bits(n){
signal input bits[n];
for(var i=0; i<n; i++){
bits[i] * (1-bits[i]) === 0;
}
}
template check_lottery(){
signal input epoch_nonce;
signal input slot_number;
signal input t0;
signal input t1; // The precomputed threshold values
signal input constraints;
signal input value;
signal input unit;
signal input state;
signal input note_nonce;
signal input nullifier_secret_key;
signal input randomness;
component hash = hash_16_to_1();
//The b"lead" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 1818583396;
hash.in[1] <== epoch_nonce;
hash.in[2] <== slot_number;
hash.in[3] <== constraints;
hash.in[4] <== value;
hash.in[5] <== unit;
hash.in[6] <== state;
hash.in[7] <== note_nonce;
hash.in[8] <== nullifier_secret_key;
hash.in[9] <== randomness;
for(var i=10; i<16; i++){
hash.in[i] <== 0;
}
// As p-1 is divisible by 4, if X follows a uniform distribution between 0 and p-1
// Y = X % (p-1)/4 nearly follows a uniform distribution between 0 and ((p-1)/4)-1 (exept that 0 has 20% more chance to appear than another element which is negligible)
// So we transform the hash of a maximum of 255 to a hash of a maximum of 253 bits by taking its modulo
// (p-1)/4 = 13108968793781547619861935127046491459422638125131909455650914674984645296128
// TODO: check this part to ensure it is secure
signal quotient;
signal ticket;
quotient <-- hash.out \ 13108968793781547619861935127046491459422638125131909455650914674984645296128;
ticket <-- hash.out % 13108968793781547619861935127046491459422638125131909455650914674984645296128;
//check that quotient is 0,1,2 or 3
signal check_quotient[2];
check_quotient[0] <== quotient * (1-quotient);
check_quotient[1] <== (2-quotient)*(3-quotient);
check_quotient[0] * check_quotient[1] === 0;
//check the correctness of the division
ticket + quotient * 13108968793781547619861935127046491459422638125131909455650914674984645296128 === hash.out;
//check that the ticket is less than the divisor
component isLess = CompConstant(13108968793781547619861935127046491459422638125131909455650914674984645296128);
component bitifier = BLSNum2Bits_strict();
bitifier.in <== ticket;
bitifier.out[254] === 0;
for(var i=0; i<254; i++){
isLess.in[i] <== bitifier.out[i];
}
isLess.out === 0;
// Compute the threshold
signal intermediate_value;
signal threshold;
intermediate_value <== t0 + t1 * value;
threshold <== intermediate_value * value;
// Ensure that the ticket is winning
component isLess2 = BLSLessThan(253);
isLess2.in[0] <== ticket;
isLess2.in[1] <== threshold;
isLess2.out === 1;
}
template nullifier_computer(){
signal input note_nonce;
signal input nullifier_secret_key;
signal input value;
signal output nullifier;
component hash = hash_4_to_1();
//The b"coin-nullifier" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 2016785505923014207119328528655730;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_secret_key;
hash.in[3] <== value;
nullifier <== hash.out;
}
template commitment_computer(){ // TODO: ensure all field are hash
signal input note_nonce;
signal input nullifier_public_key;
signal input value;
signal output commitment;
component hash = hash_4_to_1();
//The b"coin-commitment" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 516297089516239580383111224192495220;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_public_key;
hash.in[3] <== value;
commitment <== hash.out;
}
template nonce_updater(){
signal input note_nonce;
signal input nullifier_secret_key;
signal output updated_nonce;
component hash = hash_4_to_1();
//The b"coin-evolve" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 120209783668687835891529317;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_secret_key;
hash.in[3] <== 0;
updated_nonce <== hash.out;
}
template membership_checker(){
signal input leaf; //The note commitment
signal input root; //The root of the Merkle Tree (of depth 32)
signal input index[32]; //Position of the note commitment in bits in big endian
signal input node[32]; //Complementary hashes
component hash[32];
for(var i=0; i<32; i++){
hash[i] = hash_2_to_1();
}
hash[0].in[0] <== leaf - index[31] * (leaf - node[0]);
hash[0].in[1] <== node[0] - index[31] * (node[0] - leaf);
for(var i=1; i<32; i++){
hash[i].in[0] <== hash[i-1].out - index[31-i] * (hash[i-1].out - node[i]);
hash[i].in[1] <== node[i] - index[31-i] * (node[i] - hash[i-1].out);
}
root === hash[31].out;
}
template anemoi_proof_of_leadership(){
signal input epoch_nonce; //F_p (BLS12-381 scalar field)
signal input slot_number; //F_p (BLS12-381 scalar field)
signal input t0; // Precomputed threshold elements in F_p
signal input t1;
signal input commitments_root;
// Note variables
signal input constraints; // Every note field represented as F_p elements for now (constraints are represented by their Merkle root)
signal input value;
signal input unit;
signal input state;
signal input note_nonce;
signal input nullifier_secret_key;
signal input randomness;
signal input index[32]; //Position of the note commitment in bits in big endian
signal input nodes[32]; //Merkle proof of the commitment
signal output nullifier;
signal output updated_commiment;
// Check that index inputs are indeed bits
component bit_checker = check_bits(32);
for(var i=0; i<32; i++){
bit_checker.bits[i] <== index[i];
}
// Check that r < threshold
component lottery_checker = check_lottery();
lottery_checker.epoch_nonce <== epoch_nonce;
lottery_checker.slot_number <== slot_number;
lottery_checker.t0 <== t0;
lottery_checker.t1 <== t1;
lottery_checker.constraints <== constraints;
lottery_checker.value <== value;
lottery_checker.unit <== unit;
lottery_checker.state <== state;
lottery_checker.note_nonce <== note_nonce;
lottery_checker.nullifier_secret_key <== nullifier_secret_key;
lottery_checker.randomness <== randomness;
// Compute the note commitment
component note_committer = commitment_computer();
note_committer.note_nonce <== note_nonce;
note_committer.nullifier_public_key <== nullifier_secret_key; // TODO: reflect the nullifier public key computation later when defined
note_committer.value <== value;
// Check the commitment membership
component membership_checker = membership_checker();
membership_checker.leaf <== note_committer.commitment;
membership_checker.root <== commitments_root;
for(var i =0; i<32; i++){
membership_checker.index[i] <== index[i];
membership_checker.node[i] <== nodes[i];
}
// Compute the note nullifier
component nullifier_computer = nullifier_computer();
nullifier_computer.note_nonce <== note_nonce;
nullifier_computer.nullifier_secret_key <== nullifier_secret_key;
nullifier_computer.value <== value;
nullifier <== nullifier_computer.nullifier;
// Compute the evolved nonce
component nonce_updater = nonce_updater();
nonce_updater.note_nonce <== note_nonce;
nonce_updater.nullifier_secret_key <== nullifier_secret_key;
// Compute the new note commitment
component updated_note_committer = commitment_computer();
updated_note_committer.note_nonce <== nonce_updater.updated_nonce;
updated_note_committer.nullifier_public_key <== nullifier_secret_key; // TODO: reflect the nullifier public key computation later when defined
updated_note_committer.value <== value;
updated_commiment <== updated_note_committer.commitment;
}
component main {public [epoch_nonce, slot_number, t0, t1, commitments_root]} = anemoi_proof_of_leadership();

View File

@ -1,317 +0,0 @@
//test
pragma circom 2.1.9;
include "../../circom_circuits/hash/anemoi/anemoi_2_to_1_Jubjub.circom";
include "../../circom_circuits/hash/anemoi/anemoi_4_to_1_Jubjub.circom";
include "../../circom_circuits/hash/anemoi/anemoi_16_to_1_Jubjub.circom";
include "../../circom_circuits/circomlib/circuits/bitify.circom";
include "../../circom_circuits/circomlib/circuits/sha256/sha256.circom";
template BLSLessThan(n) {
assert(n <= 253);
signal input in[2];
signal output out;
component n2b = Num2Bits(n+1);
n2b.in <== in[0]+ (1<<n) - in[1];
out <== 1-n2b.out[n];
}
template BLSNum2Bits_strict() {
signal input in;
signal output out[255];
component check_range = CompConstant(23487852865797141623554994256013988874373056334117496812739262697960298774528); // -1 - 2**254 (p-1 without its first bit)
component n2b = Num2Bits(255);
in ==> n2b.in;
for (var i=0; i<255; i++) {
n2b.out[i] ==> out[i];
if(i != 0){
n2b.out[i] ==> check_range.in[i-1];
}
}
check_range.out * (n2b.out[0]) === 0; //must be zero exept if the first bit is 0 => then in is on 254 bits and p-1 on 255
}
template BLSBits2Num_strict() {
signal input in[255];
signal output out;
component check_range = CompConstant(23487852865797141623554994256013988874373056334117496812739262697960298774528);
component b2n = Bits2Num(255);
for (var i=0; i<255; i++) {
in[i] ==> b2n.in[i];
if(i != 0){
in[i] ==> check_range.in[i-1];
}
}
check_range.out * in[0] === 0;
b2n.out ==> out;
}
template check_bits(n){
signal input bits[n];
for(var i=0; i<n; i++){
bits[i] * (1-bits[i]) === 0;
}
}
template check_lottery(){
signal input epoch_nonce;
signal input slot_number;
signal input t0;
signal input t1; // The precomputed threshold values
signal input constraints;
signal input value;
signal input unit;
signal input state;
signal input note_nonce;
signal input nullifier_secret_key;
signal input randomness;
component hash = Sha256(2336);
component bitifier[9];
for(var i=0; i<9; i++){
bitifier[i] = BLSNum2Bits_strict();
}
bitifier[0].in <== epoch_nonce;
bitifier[1].in <== slot_number;
bitifier[2].in <== constraints;
bitifier[3].in <== value;
bitifier[4].in <== unit;
bitifier[5].in <== state;
bitifier[6].in <== note_nonce;
bitifier[7].in <== nullifier_secret_key;
bitifier[8].in <== randomness;
//The b"lead" Tag in bits with big endian order
hash.in[0] <== 0;
hash.in[1] <== 1;
hash.in[2] <== 1;
hash.in[3] <== 0;
hash.in[4] <== 1;
hash.in[5] <== 1;
hash.in[6] <== 0;
hash.in[7] <== 0;
hash.in[8] <== 0;
hash.in[9] <== 1;
hash.in[10] <== 1;
hash.in[11] <== 0;
hash.in[12] <== 0;
hash.in[13] <== 1;
hash.in[14] <== 0;
hash.in[15] <== 1;
hash.in[16] <== 0;
hash.in[17] <== 1;
hash.in[18] <== 1;
hash.in[19] <== 0;
hash.in[20] <== 0;
hash.in[21] <== 0;
hash.in[22] <== 0;
hash.in[23] <== 1;
hash.in[24] <== 0;
hash.in[25] <== 1;
hash.in[26] <== 1;
hash.in[27] <== 0;
hash.in[28] <== 0;
hash.in[29] <== 1;
hash.in[30] <== 0;
hash.in[31] <== 0;
for(var i=0; i<256; i++){
for(var j=0; j<9; j++){
if(i != 0){
hash.in[32+256*j+i] <== bitifier[j].out[255-i];
} else {
hash.in[32+256*j] <== 0;
}
}
}
component intifier = Bits2Num(253); //Because if the scalar field is 255 bits, we support every number of 254 bits (not all of 255) and we can only compare numbers of 253 bits since we need 1 bit for sign.
for(var i=0; i<253; i++){
intifier.in[i] <== hash.out[253-i];
}
// Compute the threshold
signal intermediate_value;
signal threshold;
intermediate_value <== t0 + t1 * value;
threshold <== intermediate_value * value;
// Ensure that the ticket is winning
component isLess2 = BLSLessThan(253);
isLess2.in[0] <== intifier.out;
isLess2.in[1] <== threshold;
isLess2.out === 1;
}
template nullifier_computer(){
signal input note_nonce;
signal input nullifier_secret_key;
signal input value;
signal output nullifier;
component hash = hash_4_to_1();
//The b"coin-nullifier" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 2016785505923014207119328528655730;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_secret_key;
hash.in[3] <== value;
nullifier <== hash.out;
}
template commitment_computer(){ // TODO: ensure all field are hash
signal input note_nonce;
signal input nullifier_public_key;
signal input value;
signal output commitment;
component hash = hash_4_to_1();
//The b"coin-commitment" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 516297089516239580383111224192495220;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_public_key;
hash.in[3] <== value;
commitment <== hash.out;
}
template nonce_updater(){
signal input note_nonce;
signal input nullifier_secret_key;
signal output updated_nonce;
component hash = hash_4_to_1();
//The b"coin-evolve" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 120209783668687835891529317;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_secret_key;
hash.in[3] <== 0;
updated_nonce <== hash.out;
}
template membership_checker(){
signal input leaf; //The note commitment
signal input root; //The root of the Merkle Tree (of depth 32)
signal input index[32]; //Position of the note commitment in bits in big endian
signal input node[32]; //Complementary hashes
component hash[32];
for(var i=0; i<32; i++){
hash[i] = hash_2_to_1();
}
hash[0].in[0] <== leaf - index[31] * (leaf - node[0]);
hash[0].in[1] <== node[0] - index[31] * (node[0] - leaf);
for(var i=1; i<32; i++){
hash[i].in[0] <== hash[i-1].out - index[31-i] * (hash[i-1].out - node[i]);
hash[i].in[1] <== node[i] - index[31-i] * (node[i] - hash[i-1].out);
}
root === hash[31].out;
}
template anemoi_sha_proof_of_leadership(){
signal input epoch_nonce; //F_p (BLS12-381 scalar field)
signal input slot_number; //F_p (BLS12-381 scalar field)
signal input t0; // Precomputed threshold elements in F_p
signal input t1;
signal input commitments_root;
// Note variables
signal input constraints; // Every note field represented as F_p elements for now (constraints are represented by their Merkle root)
signal input value;
signal input unit;
signal input state;
signal input note_nonce;
signal input nullifier_secret_key;
signal input randomness;
signal input index[32]; //Position of the note commitment in bits in big endian
signal input nodes[32]; //Merkle proof of the commitment
signal output nullifier;
signal output updated_commiment;
// Check that index inputs are indeed bits
component bit_checker = check_bits(32);
for(var i=0; i<32; i++){
bit_checker.bits[i] <== index[i];
}
// Check that r < threshold
component lottery_checker = check_lottery();
lottery_checker.epoch_nonce <== epoch_nonce;
lottery_checker.slot_number <== slot_number;
lottery_checker.t0 <== t0;
lottery_checker.t1 <== t1;
lottery_checker.constraints <== constraints;
lottery_checker.value <== value;
lottery_checker.unit <== unit;
lottery_checker.state <== state;
lottery_checker.note_nonce <== note_nonce;
lottery_checker.nullifier_secret_key <== nullifier_secret_key;
lottery_checker.randomness <== randomness;
// Compute the note commitment
component note_committer = commitment_computer();
note_committer.note_nonce <== note_nonce;
note_committer.nullifier_public_key <== nullifier_secret_key; // TODO: reflect the nullifier public key computation later when defined
note_committer.value <== value;
// Check the commitment membership
component membership_checker = membership_checker();
membership_checker.leaf <== note_committer.commitment;
membership_checker.root <== commitments_root;
for(var i =0; i<32; i++){
membership_checker.index[i] <== index[i];
membership_checker.node[i] <== nodes[i];
}
// Compute the note nullifier
component nullifier_computer = nullifier_computer();
nullifier_computer.note_nonce <== note_nonce;
nullifier_computer.nullifier_secret_key <== nullifier_secret_key;
nullifier_computer.value <== value;
nullifier <== nullifier_computer.nullifier;
// Compute the evolved nonce
component nonce_updater = nonce_updater();
nonce_updater.note_nonce <== note_nonce;
nonce_updater.nullifier_secret_key <== nullifier_secret_key;
// Compute the new note commitment
component updated_note_committer = commitment_computer();
updated_note_committer.note_nonce <== nonce_updater.updated_nonce;
updated_note_committer.nullifier_public_key <== nullifier_secret_key; // TODO: reflect the nullifier public key computation later when defined
updated_note_committer.value <== value;
updated_commiment <== updated_note_committer.commitment;
}
component main {public [epoch_nonce, slot_number, t0, t1, commitments_root]} = anemoi_sha_proof_of_leadership();

View File

@ -1,301 +0,0 @@
//test
pragma circom 2.1.9;
include "../../circom_circuits/hash/poseidon/poseidon_2_to_1_Jubjub.circom";
include "../../circom_circuits/hash/poseidon/poseidon_4_to_1_Jubjub.circom";
include "../../circom_circuits/hash/poseidon/poseidon_16_to_1_Jubjub.circom";
include "../../circom_circuits/circomlib/circuits/bitify.circom";
template BLSLessThan(n) {
assert(n <= 253);
signal input in[2];
signal output out;
component n2b = Num2Bits(n+1);
n2b.in <== in[0]+ (1<<n) - in[1];
out <== 1-n2b.out[n];
}
template BLSNum2Bits_strict() {
signal input in;
signal output out[255];
// Ensure that out is lower than p
component check_range = CompConstant(23487852865797141623554994256013988874373056334117496812739262697960298774528); // -1 - 2**254 (p-1 without its first bit)
component n2b = Num2Bits(255);
in ==> n2b.in;
for (var i=0; i<255; i++) {
n2b.out[i] ==> out[i];
if(i != 0){
n2b.out[i] ==> check_range.in[i-1];
}
}
check_range.out * (n2b.out[0]) === 0; //must be zero exept if the first bit is 0 => then in is on 254 bits and p-1 on 255
}
template BLSBits2Num_strict() {
signal input in[255];
signal output out;
//ensure that in is not greater than p
component check_range = CompConstant(23487852865797141623554994256013988874373056334117496812739262697960298774528);
component b2n = Bits2Num(255);
for (var i=0; i<255; i++) {
in[i] ==> b2n.in[i];
if(i != 0){
in[i] ==> check_range.in[i-1];
}
}
check_range.out * in[0] === 0;
b2n.out ==> out;
}
template check_bits(n){
signal input bits[n];
for(var i=0; i<n; i++){
bits[i] * (1-bits[i]) === 0;
}
}
template check_lottery(){
signal input epoch_nonce;
signal input slot_number;
signal input t0;
signal input t1; // The precomputed threshold values
signal input constraints;
signal input value;
signal input unit;
signal input state;
signal input note_nonce;
signal input nullifier_secret_key;
signal input randomness;
component hash = hash_16_to_1();
//The b"lead" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 1818583396;
hash.in[1] <== epoch_nonce;
hash.in[2] <== slot_number;
hash.in[3] <== constraints;
hash.in[4] <== value;
hash.in[5] <== unit;
hash.in[6] <== state;
hash.in[7] <== note_nonce;
hash.in[8] <== nullifier_secret_key;
hash.in[9] <== randomness;
for(var i=10; i<16; i++){
hash.in[i] <== 0;
}
// As p-1 is divisible by 4, if X follows a uniform distribution between 0 and p-1
// Y = X % (p-1)/4 nearly follows a uniform distribution between 0 and ((p-1)/4)-1 (exept that 0 has 20% more chance to appear than another element which is negligible)
// So we transform the hash of a maximum of 255 to a hash of a maximum of 253 bits by taking its modulo
// (p-1)/4 = 13108968793781547619861935127046491459422638125131909455650914674984645296128
// TODO: check this part to ensure it is secure
signal quotient;
signal ticket;
quotient <-- hash.out \ 13108968793781547619861935127046491459422638125131909455650914674984645296128;
ticket <-- hash.out % 13108968793781547619861935127046491459422638125131909455650914674984645296128;
//check that quotient is 0,1,2 or 3
signal check_quotient[2];
check_quotient[0] <== quotient * (1-quotient);
check_quotient[1] <== (2-quotient)*(3-quotient);
check_quotient[0] * check_quotient[1] === 0;
//check the correctness of the division
ticket + quotient * 13108968793781547619861935127046491459422638125131909455650914674984645296128 === hash.out;
//check that the ticket is less than the divisor
component isLess = CompConstant(13108968793781547619861935127046491459422638125131909455650914674984645296128);
component bitifier = BLSNum2Bits_strict();
bitifier.in <== ticket;
bitifier.out[254] === 0;
for(var i=0; i<254; i++){
isLess.in[i] <== bitifier.out[i];
}
isLess.out === 0;
// Compute the threshold
signal intermediate_value;
signal threshold;
intermediate_value <== t0 + t1 * value;
threshold <== intermediate_value * value;
// Ensure that the ticket is indeed 253 bits and that the ticket is winning
component isLess2 = BLSLessThan(253);
isLess2.in[0] <== ticket;
isLess2.in[1] <== threshold;
isLess2.out === 1;
}
template nullifier_computer(){
signal input note_nonce;
signal input nullifier_secret_key;
signal input value;
signal output nullifier;
component hash = hash_4_to_1();
//The b"coin-nullifier" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 2016785505923014207119328528655730;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_secret_key;
hash.in[3] <== value;
nullifier <== hash.out;
}
template commitment_computer(){ // TODO: ensure all field are hash
signal input note_nonce;
signal input nullifier_public_key;
signal input value;
signal output commitment;
component hash = hash_4_to_1();
//The b"coin-commitment" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 516297089516239580383111224192495220;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_public_key;
hash.in[3] <== value;
commitment <== hash.out;
}
template nonce_updater(){
signal input note_nonce;
signal input nullifier_secret_key;
signal output updated_nonce;
component hash = hash_4_to_1();
//The b"coin-evolve" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 120209783668687835891529317;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_secret_key;
hash.in[3] <== 0;
updated_nonce <== hash.out;
}
template membership_checker(){
signal input leaf; //The note commitment
signal input root; //The root of the Merkle Tree (of depth 32)
signal input index[32]; //Position of the note commitment in bits in big endian
signal input node[32]; //Complementary hashes
component hash[32];
for(var i=0; i<32; i++){
hash[i] = hash_2_to_1();
}
hash[0].in[0] <== leaf - index[31] * (leaf - node[0]);
hash[0].in[1] <== node[0] - index[31] * (node[0] - leaf);
for(var i=1; i<32; i++){
hash[i].in[0] <== hash[i-1].out - index[31-i] * (hash[i-1].out - node[i]);
hash[i].in[1] <== node[i] - index[31-i] * (node[i] - hash[i-1].out);
}
root === hash[31].out;
}
template poseidon_proof_of_leadership(){
signal input epoch_nonce; //F_p (BLS12-381 scalar field)
signal input slot_number; //F_p (BLS12-381 scalar field)
signal input t0; // Precomputed threshold elements in F_p
signal input t1;
signal input commitments_root;
// Note variables
signal input constraints; // Every note field represented as F_p elements for now (constraints are represented by their Merkle root)
signal input value;
signal input unit;
signal input state;
signal input note_nonce;
signal input nullifier_secret_key;
signal input randomness;
signal input index[32]; //Position of the note commitment in bits in big endian
signal input nodes[32]; //Merkle proof of the commitment
signal output nullifier;
signal output updated_commiment;
// Check that index inputs are indeed bits
component bit_checker = check_bits(32);
for(var i=0; i<32; i++){
bit_checker.bits[i] <== index[i];
}
// Check that r < threshold
component lottery_checker = check_lottery();
lottery_checker.epoch_nonce <== epoch_nonce;
lottery_checker.slot_number <== slot_number;
lottery_checker.t0 <== t0;
lottery_checker.t1 <== t1;
lottery_checker.constraints <== constraints;
lottery_checker.value <== value;
lottery_checker.unit <== unit;
lottery_checker.state <== state;
lottery_checker.note_nonce <== note_nonce;
lottery_checker.nullifier_secret_key <== nullifier_secret_key;
lottery_checker.randomness <== randomness;
// Compute the note commitment
component note_committer = commitment_computer();
note_committer.note_nonce <== note_nonce;
note_committer.nullifier_public_key <== nullifier_secret_key; // TODO: reflect the nullifier public key computation later when defined
note_committer.value <== value;
// Check the commitment membership
component membership_checker = membership_checker();
membership_checker.leaf <== note_committer.commitment;
membership_checker.root <== commitments_root;
for(var i =0; i<32; i++){
membership_checker.index[i] <== index[i];
membership_checker.node[i] <== nodes[i];
}
// Compute the note nullifier
component nullifier_computer = nullifier_computer();
nullifier_computer.note_nonce <== note_nonce;
nullifier_computer.nullifier_secret_key <== nullifier_secret_key;
nullifier_computer.value <== value;
nullifier <== nullifier_computer.nullifier;
// Compute the evolved nonce
component nonce_updater = nonce_updater();
nonce_updater.note_nonce <== note_nonce;
nonce_updater.nullifier_secret_key <== nullifier_secret_key;
// Compute the new note commitment
component updated_note_committer = commitment_computer();
updated_note_committer.note_nonce <== nonce_updater.updated_nonce;
updated_note_committer.nullifier_public_key <== nullifier_secret_key; // TODO: reflect the nullifier public key computation later when defined
updated_note_committer.value <== value;
updated_commiment <== updated_note_committer.commitment;
}
component main {public [epoch_nonce, slot_number, t0, t1, commitments_root]} = poseidon_proof_of_leadership();

View File

@ -1,318 +0,0 @@
//test
pragma circom 2.1.9;
include "../../circom_circuits/hash/poseidon/poseidon_2_to_1_Jubjub.circom";
include "../../circom_circuits/hash/poseidon/poseidon_4_to_1_Jubjub.circom";
include "../../circom_circuits/hash/poseidon/poseidon_16_to_1_Jubjub.circom";
include "../../circom_circuits/circomlib/circuits/bitify.circom";
include "../../circom_circuits/circomlib/circuits/sha256/sha256.circom";
template BLSLessThan(n) {
assert(n <= 253);
signal input in[2];
signal output out;
component n2b = Num2Bits(n+1);
n2b.in <== in[0]+ (1<<n) - in[1];
out <== 1-n2b.out[n];
}
template BLSNum2Bits_strict() {
signal input in;
signal output out[255];
// Ensure that out is lower than p
component check_range = CompConstant(23487852865797141623554994256013988874373056334117496812739262697960298774528); // -1 - 2**254 (p-1 without its first bit)
component n2b = Num2Bits(255);
in ==> n2b.in;
for (var i=0; i<255; i++) {
n2b.out[i] ==> out[i];
if(i != 0){
n2b.out[i] ==> check_range.in[i-1];
}
}
check_range.out * (n2b.out[0]) === 0; //must be zero exept if the first bit is 0 => then in is on 254 bits and p-1 on 255
}
template BLSBits2Num_strict() {
signal input in[255];
signal output out;
//ensure that in is not greater than p
component check_range = CompConstant(23487852865797141623554994256013988874373056334117496812739262697960298774528);
component b2n = Bits2Num(255);
for (var i=0; i<255; i++) {
in[i] ==> b2n.in[i];
if(i != 0){
in[i] ==> check_range.in[i-1];
}
}
check_range.out * in[0] === 0;
b2n.out ==> out;
}
template check_bits(n){
signal input bits[n];
for(var i=0; i<n; i++){
bits[i] * (1-bits[i]) === 0;
}
}
template check_lottery(){
signal input epoch_nonce;
signal input slot_number;
signal input t0;
signal input t1; // The precomputed threshold values
signal input constraints;
signal input value;
signal input unit;
signal input state;
signal input note_nonce;
signal input nullifier_secret_key;
signal input randomness;
component hash = Sha256(2336);
component bitifier[9];
for(var i=0; i<9; i++){
bitifier[i] = BLSNum2Bits_strict();
}
bitifier[0].in <== epoch_nonce;
bitifier[1].in <== slot_number;
bitifier[2].in <== constraints;
bitifier[3].in <== value;
bitifier[4].in <== unit;
bitifier[5].in <== state;
bitifier[6].in <== note_nonce;
bitifier[7].in <== nullifier_secret_key;
bitifier[8].in <== randomness;
//The b"lead" Tag in bits with big endian order
hash.in[0] <== 0;
hash.in[1] <== 1;
hash.in[2] <== 1;
hash.in[3] <== 0;
hash.in[4] <== 1;
hash.in[5] <== 1;
hash.in[6] <== 0;
hash.in[7] <== 0;
hash.in[8] <== 0;
hash.in[9] <== 1;
hash.in[10] <== 1;
hash.in[11] <== 0;
hash.in[12] <== 0;
hash.in[13] <== 1;
hash.in[14] <== 0;
hash.in[15] <== 1;
hash.in[16] <== 0;
hash.in[17] <== 1;
hash.in[18] <== 1;
hash.in[19] <== 0;
hash.in[20] <== 0;
hash.in[21] <== 0;
hash.in[22] <== 0;
hash.in[23] <== 1;
hash.in[24] <== 0;
hash.in[25] <== 1;
hash.in[26] <== 1;
hash.in[27] <== 0;
hash.in[28] <== 0;
hash.in[29] <== 1;
hash.in[30] <== 0;
hash.in[31] <== 0;
for(var i=0; i<256; i++){
for(var j=0; j<9; j++){
if(i != 0){
hash.in[32+256*j+i] <== bitifier[j].out[255-i];
} else {
hash.in[32+256*j] <== 0;
}
}
}
component intifier = Bits2Num(253); //Because if the scalar field is 255 bits, we support every number of 254 bits (not all of 255) and we can only compare numbers of 253 bits since we need 1 bit for sign.
for(var i=0; i<253; i++){
intifier.in[i] <== hash.out[253-i];
}
// Compute the threshold
signal intermediate_value;
signal threshold;
intermediate_value <== t0 + t1 * value;
threshold <== intermediate_value * value;
// Ensure that the ticket is winning
component isLess2 = BLSLessThan(253);
isLess2.in[0] <== intifier.out;
isLess2.in[1] <== threshold;
//isLess2.out === 1;
}
template nullifier_computer(){
signal input note_nonce;
signal input nullifier_secret_key;
signal input value;
signal output nullifier;
component hash = hash_4_to_1();
//The b"coin-nullifier" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 2016785505923014207119328528655730;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_secret_key;
hash.in[3] <== value;
nullifier <== hash.out;
}
template commitment_computer(){ // TODO: ensure all field are hash
signal input note_nonce;
signal input nullifier_public_key;
signal input value;
signal output commitment;
component hash = hash_4_to_1();
//The b"coin-commitment" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 516297089516239580383111224192495220;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_public_key;
hash.in[3] <== value;
commitment <== hash.out;
}
template nonce_updater(){
signal input note_nonce;
signal input nullifier_secret_key;
signal output updated_nonce;
component hash = hash_4_to_1();
//The b"coin-evolve" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 120209783668687835891529317;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_secret_key;
hash.in[3] <== 0;
updated_nonce <== hash.out;
}
template membership_checker(){
signal input leaf; //The note commitment
signal input root; //The root of the Merkle Tree (of depth 32)
signal input index[32]; //Position of the note commitment in bits in big endian
signal input node[32]; //Complementary hashes
component hash[32];
for(var i=0; i<32; i++){
hash[i] = hash_2_to_1();
}
hash[0].in[0] <== leaf - index[31] * (leaf - node[0]);
hash[0].in[1] <== node[0] - index[31] * (node[0] - leaf);
for(var i=1; i<32; i++){
hash[i].in[0] <== hash[i-1].out - index[31-i] * (hash[i-1].out - node[i]);
hash[i].in[1] <== node[i] - index[31-i] * (node[i] - hash[i-1].out);
}
//root === hash[31].out;
}
template poseidon_sha_proof_of_leadership(){
signal input epoch_nonce; //F_p (BLS12-381 scalar field)
signal input slot_number; //F_p (BLS12-381 scalar field)
signal input t0; // Precomputed threshold elements in F_p
signal input t1;
signal input commitments_root;
// Note variables
signal input constraints; // Every note field represented as F_p elements for now (constraints are represented by their Merkle root)
signal input value;
signal input unit;
signal input state;
signal input note_nonce;
signal input nullifier_secret_key;
signal input randomness;
signal input index[32]; //Position of the note commitment in bits in big endian
signal input nodes[32]; //Merkle proof of the commitment
signal output nullifier;
signal output updated_commiment;
// Check that index inputs are indeed bits
component bit_checker = check_bits(32);
for(var i=0; i<32; i++){
bit_checker.bits[i] <== index[i];
}
// Check that r < threshold
component lottery_checker = check_lottery();
lottery_checker.epoch_nonce <== epoch_nonce;
lottery_checker.slot_number <== slot_number;
lottery_checker.t0 <== t0;
lottery_checker.t1 <== t1;
lottery_checker.constraints <== constraints;
lottery_checker.value <== value;
lottery_checker.unit <== unit;
lottery_checker.state <== state;
lottery_checker.note_nonce <== note_nonce;
lottery_checker.nullifier_secret_key <== nullifier_secret_key;
lottery_checker.randomness <== randomness;
// Compute the note commitment
component note_committer = commitment_computer();
note_committer.note_nonce <== note_nonce;
note_committer.nullifier_public_key <== nullifier_secret_key; // TODO: reflect the nullifier public key computation later when defined
note_committer.value <== value;
// Check the commitment membership
component membership_checker = membership_checker();
membership_checker.leaf <== note_committer.commitment;
membership_checker.root <== commitments_root;
for(var i =0; i<32; i++){
membership_checker.index[i] <== index[i];
membership_checker.node[i] <== nodes[i];
}
// Compute the note nullifier
component nullifier_computer = nullifier_computer();
nullifier_computer.note_nonce <== note_nonce;
nullifier_computer.nullifier_secret_key <== nullifier_secret_key;
nullifier_computer.value <== value;
nullifier <== nullifier_computer.nullifier;
// Compute the evolved nonce
component nonce_updater = nonce_updater();
nonce_updater.note_nonce <== note_nonce;
nonce_updater.nullifier_secret_key <== nullifier_secret_key;
// Compute the new note commitment
component updated_note_committer = commitment_computer();
updated_note_committer.note_nonce <== nonce_updater.updated_nonce;
updated_note_committer.nullifier_public_key <== nullifier_secret_key; // TODO: reflect the nullifier public key computation later when defined
updated_note_committer.value <== value;
updated_commiment <== updated_note_committer.commitment;
}
component main {public [epoch_nonce, slot_number, t0, t1, commitments_root]} = poseidon_sha_proof_of_leadership();

View File

@ -1,683 +0,0 @@
//test
pragma circom 2.1.9;
include "../../circom_circuits/circomlib/circuits/sha256/sha256.circom";
include "../../circom_circuits/circomlib/circuits/bitify.circom";
template BLSLessThan(n) {
assert(n <= 253);
signal input in[2];
signal output out;
component n2b = Num2Bits(n+1);
n2b.in <== in[0]+ (1<<n) - in[1];
out <== 1-n2b.out[n];
}
template lottery_ticket() {
signal input epoch_nonce[256]; //F_p (BLS12-381 scalar field)
signal input slot_number[64]; //F_p (BLS12-381 scalar field)
signal input note_nonce[256];
signal input nullifier_secret_key[256];
signal output r; //The lottery ticket in F_p
component hash = Sha256(864);
//The b"lead" Tag in bits with big endian order
hash.in[0] <== 0;
hash.in[1] <== 1;
hash.in[2] <== 1;
hash.in[3] <== 0;
hash.in[4] <== 1;
hash.in[5] <== 1;
hash.in[6] <== 0;
hash.in[7] <== 0;
hash.in[8] <== 0;
hash.in[9] <== 1;
hash.in[10] <== 1;
hash.in[11] <== 0;
hash.in[12] <== 0;
hash.in[13] <== 1;
hash.in[14] <== 0;
hash.in[15] <== 1;
hash.in[16] <== 0;
hash.in[17] <== 1;
hash.in[18] <== 1;
hash.in[19] <== 0;
hash.in[20] <== 0;
hash.in[21] <== 0;
hash.in[22] <== 0;
hash.in[23] <== 1;
hash.in[24] <== 0;
hash.in[25] <== 1;
hash.in[26] <== 1;
hash.in[27] <== 0;
hash.in[28] <== 0;
hash.in[29] <== 1;
hash.in[30] <== 0;
hash.in[31] <== 0;
for(var i=0; i<256; i++){
hash.in[32+i] <== epoch_nonce[i];
if(i<64){
hash.in[288+i] <== slot_number[i];
}
hash.in[352+i] <== nullifier_secret_key[i];
hash.in[608+i] <== note_nonce[i];
}
component intifier = Bits2Num(253); //Because if the scalar field is 255 bits, we support every number of 254 bits (not all of 255) and we can only compare numbers of 253 bits since we need 1 bit for sign.
for(var i=0; i<253; i++){
intifier.in[i] <== hash.out[253-i];
}
r <== intifier.out;
}
template check_lottery(){
signal input pre_computed_threshold; //253 bits
signal input v; //253 bits max
signal input epoch_nonce[256];
signal input slot_number[64];
signal input nullifier_secret_key[256];
signal input note_nonce[256];
component ticket = lottery_ticket();
for(var i=0; i<256; i++){
ticket.epoch_nonce[i] <== epoch_nonce[i];
if(i<64){
ticket.slot_number[i] <== slot_number[i];
}
ticket.nullifier_secret_key[i] <== nullifier_secret_key[i];
ticket.note_nonce[i] <== note_nonce[i];
}
component isLess = BLSLessThan(253);
isLess.in[0] <== ticket.r;
isLess.in[1] <== pre_computed_threshold * v;
//isLess.out === 1;
}
template nullifier_computer(){
signal input note_nonce[256];
signal input nullifier_public_key[256];
signal input v[256];
signal output nullifier[256];
component hash = Sha256(880);
//The b"coin-nullifier" Tag in bits with big endian order
hash.in[0] <== 0;
hash.in[1] <== 1;
hash.in[2] <== 1;
hash.in[3] <== 0;
hash.in[4] <== 0;
hash.in[5] <== 0;
hash.in[6] <== 1;
hash.in[7] <== 1;
hash.in[8] <== 0;
hash.in[9] <== 1;
hash.in[10] <== 1;
hash.in[11] <== 0;
hash.in[12] <== 1;
hash.in[13] <== 1;
hash.in[14] <== 1;
hash.in[15] <== 1;
hash.in[16] <== 0;
hash.in[17] <== 1;
hash.in[18] <== 1;
hash.in[19] <== 0;
hash.in[20] <== 1;
hash.in[21] <== 0;
hash.in[22] <== 0;
hash.in[23] <== 1;
hash.in[24] <== 0;
hash.in[25] <== 1;
hash.in[26] <== 1;
hash.in[27] <== 0;
hash.in[28] <== 1;
hash.in[29] <== 1;
hash.in[30] <== 1;
hash.in[31] <== 0;
hash.in[32] <== 0;
hash.in[33] <== 0;
hash.in[34] <== 1;
hash.in[35] <== 0;
hash.in[36] <== 1;
hash.in[37] <== 1;
hash.in[38] <== 0;
hash.in[39] <== 1;
hash.in[40] <== 0;
hash.in[41] <== 1;
hash.in[42] <== 1;
hash.in[43] <== 0;
hash.in[44] <== 1;
hash.in[45] <== 1;
hash.in[46] <== 1;
hash.in[47] <== 0;
hash.in[48] <== 0;
hash.in[49] <== 1;
hash.in[50] <== 1;
hash.in[51] <== 1;
hash.in[52] <== 0;
hash.in[53] <== 1;
hash.in[54] <== 0;
hash.in[55] <== 1;
hash.in[56] <== 0;
hash.in[57] <== 1;
hash.in[58] <== 1;
hash.in[59] <== 0;
hash.in[60] <== 1;
hash.in[61] <== 1;
hash.in[62] <== 0;
hash.in[63] <== 0;
hash.in[64] <== 0;
hash.in[65] <== 1;
hash.in[66] <== 1;
hash.in[67] <== 0;
hash.in[68] <== 1;
hash.in[69] <== 1;
hash.in[70] <== 0;
hash.in[71] <== 0;
hash.in[72] <== 0;
hash.in[73] <== 1;
hash.in[74] <== 1;
hash.in[75] <== 0;
hash.in[76] <== 1;
hash.in[77] <== 0;
hash.in[78] <== 0;
hash.in[79] <== 1;
hash.in[80] <== 0;
hash.in[81] <== 1;
hash.in[82] <== 1;
hash.in[83] <== 0;
hash.in[84] <== 0;
hash.in[85] <== 1;
hash.in[86] <== 1;
hash.in[87] <== 0;
hash.in[88] <== 0;
hash.in[89] <== 1;
hash.in[90] <== 1;
hash.in[91] <== 0;
hash.in[92] <== 1;
hash.in[93] <== 0;
hash.in[94] <== 0;
hash.in[95] <== 1;
hash.in[96] <== 0;
hash.in[97] <== 1;
hash.in[98] <== 1;
hash.in[99] <== 0;
hash.in[100] <== 0;
hash.in[101] <== 1;
hash.in[102] <== 0;
hash.in[103] <== 1;
hash.in[104] <== 0;
hash.in[105] <== 1;
hash.in[106] <== 1;
hash.in[107] <== 1;
hash.in[108] <== 0;
hash.in[109] <== 0;
hash.in[110] <== 1;
hash.in[111] <== 0;
for(var i=0; i<256; i++){
hash.in[112+i] <== note_nonce[i];
hash.in[368+i] <== nullifier_public_key[i];
hash.in[624+i] <== v[i];
}
for(var i=0; i<256; i++){
nullifier[i] <== hash.out[i];
}
}
template commitment_computer(){ // TODO: ensure all field are hash
signal input note_nonce[256];
signal input nullifier_public_key[256];
signal input v[256];
signal output commitment[256];
component hash = Sha256(888);
//The b"coin-commitment" Tag in bits with big endian order
hash.in[0] <== 0;
hash.in[1] <== 1;
hash.in[2] <== 1;
hash.in[3] <== 0;
hash.in[4] <== 0;
hash.in[5] <== 0;
hash.in[6] <== 1;
hash.in[7] <== 1;
hash.in[8] <== 0;
hash.in[9] <== 1;
hash.in[10] <== 1;
hash.in[11] <== 0;
hash.in[12] <== 1;
hash.in[13] <== 1;
hash.in[14] <== 1;
hash.in[15] <== 1;
hash.in[16] <== 0;
hash.in[17] <== 1;
hash.in[18] <== 1;
hash.in[19] <== 0;
hash.in[20] <== 1;
hash.in[21] <== 0;
hash.in[22] <== 0;
hash.in[23] <== 1;
hash.in[24] <== 0;
hash.in[25] <== 1;
hash.in[26] <== 1;
hash.in[27] <== 0;
hash.in[28] <== 1;
hash.in[29] <== 1;
hash.in[30] <== 1;
hash.in[31] <== 0;
hash.in[32] <== 0;
hash.in[33] <== 0;
hash.in[34] <== 1;
hash.in[35] <== 0;
hash.in[36] <== 1;
hash.in[37] <== 1;
hash.in[38] <== 0;
hash.in[39] <== 1;
hash.in[40] <== 0;
hash.in[41] <== 1;
hash.in[42] <== 1;
hash.in[43] <== 0;
hash.in[44] <== 0;
hash.in[45] <== 0;
hash.in[46] <== 1;
hash.in[47] <== 1;
hash.in[48] <== 0;
hash.in[49] <== 1;
hash.in[50] <== 1;
hash.in[51] <== 0;
hash.in[52] <== 1;
hash.in[53] <== 1;
hash.in[54] <== 1;
hash.in[55] <== 1;
hash.in[56] <== 0;
hash.in[57] <== 1;
hash.in[58] <== 1;
hash.in[59] <== 0;
hash.in[60] <== 1;
hash.in[61] <== 1;
hash.in[62] <== 0;
hash.in[63] <== 1;
hash.in[64] <== 0;
hash.in[65] <== 1;
hash.in[66] <== 1;
hash.in[67] <== 0;
hash.in[68] <== 1;
hash.in[69] <== 1;
hash.in[70] <== 0;
hash.in[71] <== 1;
hash.in[72] <== 0;
hash.in[73] <== 1;
hash.in[74] <== 1;
hash.in[75] <== 0;
hash.in[76] <== 1;
hash.in[77] <== 0;
hash.in[78] <== 0;
hash.in[79] <== 1;
hash.in[80] <== 0;
hash.in[81] <== 1;
hash.in[82] <== 1;
hash.in[83] <== 1;
hash.in[84] <== 0;
hash.in[85] <== 1;
hash.in[86] <== 0;
hash.in[87] <== 0;
hash.in[88] <== 0;
hash.in[89] <== 1;
hash.in[90] <== 1;
hash.in[91] <== 0;
hash.in[92] <== 1;
hash.in[93] <== 1;
hash.in[94] <== 0;
hash.in[95] <== 1;
hash.in[96] <== 0;
hash.in[97] <== 1;
hash.in[98] <== 1;
hash.in[99] <== 0;
hash.in[100] <== 0;
hash.in[101] <== 1;
hash.in[102] <== 0;
hash.in[103] <== 1;
hash.in[104] <== 0;
hash.in[105] <== 1;
hash.in[106] <== 1;
hash.in[107] <== 0;
hash.in[108] <== 1;
hash.in[109] <== 1;
hash.in[110] <== 1;
hash.in[111] <== 0;
hash.in[112] <== 0;
hash.in[113] <== 1;
hash.in[114] <== 1;
hash.in[115] <== 1;
hash.in[116] <== 0;
hash.in[117] <== 1;
hash.in[118] <== 0;
hash.in[119] <== 0;
for(var i=0; i<256; i++){
hash.in[120+i] <== note_nonce[i];
hash.in[376+i] <== nullifier_public_key[i];
hash.in[632+i] <== v[i];
}
for(var i=0; i<256; i++){
commitment[i] <== hash.out[i];
}
}
template nonce_updater(){
signal input note_nonce[256];
signal input nullifier_secret_key[256];
signal output updated_nonce[256];
component hash = Sha256(600);
//The b"coin-evolve" Tag in bits with big endian order
hash.in[0] <== 0;
hash.in[1] <== 1;
hash.in[2] <== 1;
hash.in[3] <== 0;
hash.in[4] <== 0;
hash.in[5] <== 0;
hash.in[6] <== 1;
hash.in[7] <== 1;
hash.in[8] <== 0;
hash.in[9] <== 1;
hash.in[10] <== 1;
hash.in[11] <== 0;
hash.in[12] <== 1;
hash.in[13] <== 1;
hash.in[14] <== 1;
hash.in[15] <== 1;
hash.in[16] <== 0;
hash.in[17] <== 1;
hash.in[18] <== 1;
hash.in[19] <== 0;
hash.in[20] <== 1;
hash.in[21] <== 0;
hash.in[22] <== 0;
hash.in[23] <== 1;
hash.in[24] <== 0;
hash.in[25] <== 1;
hash.in[26] <== 1;
hash.in[27] <== 0;
hash.in[28] <== 1;
hash.in[29] <== 1;
hash.in[30] <== 1;
hash.in[31] <== 0;
hash.in[32] <== 0;
hash.in[33] <== 0;
hash.in[34] <== 1;
hash.in[35] <== 0;
hash.in[36] <== 1;
hash.in[37] <== 1;
hash.in[38] <== 0;
hash.in[39] <== 1;
hash.in[40] <== 0;
hash.in[41] <== 1;
hash.in[42] <== 1;
hash.in[43] <== 0;
hash.in[44] <== 0;
hash.in[45] <== 1;
hash.in[46] <== 0;
hash.in[47] <== 1;
hash.in[48] <== 0;
hash.in[49] <== 1;
hash.in[50] <== 1;
hash.in[51] <== 1;
hash.in[52] <== 0;
hash.in[53] <== 1;
hash.in[54] <== 1;
hash.in[55] <== 0;
hash.in[56] <== 0;
hash.in[57] <== 1;
hash.in[58] <== 1;
hash.in[59] <== 0;
hash.in[60] <== 1;
hash.in[61] <== 1;
hash.in[62] <== 1;
hash.in[63] <== 1;
hash.in[64] <== 0;
hash.in[65] <== 1;
hash.in[66] <== 1;
hash.in[67] <== 0;
hash.in[68] <== 1;
hash.in[69] <== 1;
hash.in[70] <== 0;
hash.in[71] <== 0;
hash.in[72] <== 0;
hash.in[73] <== 1;
hash.in[74] <== 1;
hash.in[75] <== 1;
hash.in[76] <== 0;
hash.in[77] <== 1;
hash.in[78] <== 1;
hash.in[79] <== 0;
hash.in[80] <== 0;
hash.in[81] <== 1;
hash.in[82] <== 1;
hash.in[83] <== 0;
hash.in[84] <== 0;
hash.in[85] <== 1;
hash.in[86] <== 0;
hash.in[87] <== 1;
for(var i=0; i<256; i++){
hash.in[88+i] <== note_nonce[i];
hash.in[344+i] <== nullifier_secret_key[i];
}
for(var i=0; i<256; i++){
updated_nonce[i] <== hash.out[i];
}
}
template sha_2_to_1(){
signal input a[256];
signal input b[256];
signal output hash_ab[256];
component hash = Sha256(512);
for(var i=0; i<256; i++){
hash.in[i] <== a[i];
hash.in[i+256] <== b[i];
}
for(var i=0;i<256;i++){
hash_ab[i] <== hash.out[i];
}
}
template membership_checker(){
signal input commitment[256]; //The note commitment
signal input commitments_root[256]; //The root of the Merkle Tree containing every commitments (of depth 32)
signal input index[32]; //Position of the note commitment in bits in big endian
signal input node[32][256]; //Complementary hashes
component hash[32];
for(var i=0; i<32; i++){
hash[i] = sha_2_to_1();
}
for(var i=0; i<256; i++){
hash[0].a[i] <== commitment[i] - index[31] * (commitment[i] - node[0][i]);
hash[0].b[i] <== node[0][i] - index[31] * (node[0][i] - commitment[i]);
}
for(var i=1; i<32; i++){
for(var j=0; j<256; j++){
hash[i].a[j] <== hash[i-1].hash_ab[j] - index[31] * (hash[i-1].hash_ab[j] - node[i][j]);
hash[i].b[j] <== node[i][j] - index[31] * (node[i][j] - hash[i-1].hash_ab[j]);
}
}
for(var i=0; i<256; i++){
//commitments_root[i] === hash[31].hash_ab[i];
}
}
template bits2num_253(){
signal input bits[253];
signal output value;
signal intermediate_value[252];
intermediate_value[0] <== bits[0] * 2;
for(var i=1; i<252; i++){
intermediate_value[i] <== intermediate_value[i-1] * 2 + bits[i];
}
value <== intermediate_value[251] * 2 + bits[252];
}
template check_bits(n){
signal input bits[n];
for(var i=0; i<n; i++){
bits[i] * (1-bits[i]) === 0;
}
}
template sha_proof_of_leadership(){
signal input epoch_nonce[256]; //256 bits
signal input slot_number[64]; //64 bits
signal input pre_computed_threshold; //253 bits
signal input commitments_root[256]; //The root of the Merkle Tree containing every commitments (of depth 32) 256 bits
signal input note_nonce[256];
signal input nullifier_secret_key[256];
signal input v[253]; //253 bits
signal input index[32]; //Position of the note commitment in bits in big endian
signal input node[32][256]; //Complementary hashes
signal output nullifier[256];
signal output updated_commiment[256];
// Check that private inputs are indeed bits
component bit_checker[36];
for(var i=0; i<34; i++){
bit_checker[i] = check_bits(256);
if(i<32){
for(var j=0; j<256; j++){
bit_checker[i].bits[j] <== node[i][j];
}
}
}
bit_checker[34] = check_bits(253);
bit_checker[35] = check_bits(32);
for(var i=0; i<256; i++){
bit_checker[32].bits[i] <== note_nonce[i];
bit_checker[33].bits[i] <== nullifier_secret_key[i];
if(i<253){
bit_checker[34].bits[i] <== v[i];
}
if(i<32){
bit_checker[35].bits[i] <== index[i];
}
}
// Compute the value of v
component bits2num = bits2num_253();
for(var i=0; i<253; i++){
bits2num.bits[i] <== v[i];
}
// Check that r < threshold
component lottery_checker = check_lottery();
lottery_checker.pre_computed_threshold <== pre_computed_threshold;
lottery_checker.v <== bits2num.value;
for(var i=0; i<256; i++){
lottery_checker.epoch_nonce[i] <== epoch_nonce[i];
if(i<64){
lottery_checker.slot_number[i] <== slot_number[i];
}
lottery_checker.nullifier_secret_key[i] <== nullifier_secret_key[i];
lottery_checker.note_nonce[i] <== note_nonce[i];
}
// Compute the note commitment
component note_committer = commitment_computer();
for(var i=0; i<256; i++){
note_committer.note_nonce[i] <== note_nonce[i];
note_committer.nullifier_public_key[i] <== nullifier_secret_key[i]; // TODO: reflect the nullifier public key computation later when defined
}
note_committer.v[0] <== 0;
note_committer.v[1] <== 0;
note_committer.v[2] <== 0;
for(var i=0; i<253; i++){
note_committer.v[i+3] <== v[i];
}
// Check the commitment membership
component membership_checker = membership_checker();
for(var i=0; i<256; i++){
membership_checker.commitment[i] <== note_committer.commitment[i];
membership_checker.commitments_root[i] <== commitments_root[i];
for(var j=0; j<32; j++){
if(i==0){
membership_checker.index[j] <== index[j];
}
membership_checker.node[j][i] <== node[j][i];
}
}
// Compute the note nullifier
component nullifier_computer = nullifier_computer();
for(var i=0; i<256; i++){
nullifier_computer.note_nonce[i] <== note_nonce[i];
nullifier_computer.nullifier_public_key[i] <== nullifier_secret_key[i]; // TODO: reflect the nullifier public key computation later when defined
}
nullifier_computer.v[0] <== 0;
nullifier_computer.v[1] <== 0;
nullifier_computer.v[2] <== 0;
for(var i=0; i<253; i++){
nullifier_computer.v[i+3] <== v[i];
}
for(var i=0; i<256; i++){
nullifier[i] <== nullifier_computer.nullifier[i];
}
// Compute the evolved nonce
component nonce_updater = nonce_updater();
for(var i=0; i<256; i++){
nonce_updater.note_nonce[i] <== note_nonce[i];
nonce_updater.nullifier_secret_key[i] <== nullifier_secret_key[i];
}
// Compute the new note commitment
component updated_note_committer = commitment_computer();
for(var i=0; i<256; i++){
updated_note_committer.note_nonce[i] <== nonce_updater.updated_nonce[i];
updated_note_committer.nullifier_public_key[i] <== nullifier_secret_key[i]; // TODO: reflect the nullifier public key computation later when defined
}
updated_note_committer.v[0] <== 0;
updated_note_committer.v[1] <== 0;
updated_note_committer.v[2] <== 0;
for(var i=0; i<253; i++){
updated_note_committer.v[i+3] <== v[i];
}
for(var i =0; i<256; i++){
updated_commiment[i] <== updated_note_committer.commitment[i];
}
}
component main {public [epoch_nonce, slot_number, pre_computed_threshold, commitments_root]} = sha_proof_of_leadership();

View File

@ -1,6 +0,0 @@
{
"cells": [],
"metadata": {},
"nbformat": 4,
"nbformat_minor": 5
}

File diff suppressed because it is too large Load Diff

View File

@ -1,209 +0,0 @@
//test
pragma circom 2.1.9;
include "../../circom_circuits/hash/anemoi/anemoi_2_to_1_Jubjub.circom";
include "../../circom_circuits/hash/anemoi/anemoi_4_to_1_Jubjub.circom";
include "../../circom_circuits/hash/anemoi/anemoi_16_to_1_Jubjub.circom";
include "../../circom_circuits/circomlib/circuits/bitify.circom";
include "../../circom_circuits/circomlib/circuits/comparators.circom";
include "../../circom_circuits/Jubjub/escalarmulanyJubjub.circom";
include "../../circom_circuits/Jubjub/jubjub.circom";
template BLSLessThan(n) {
assert(n <= 253);
signal input in[2];
signal output out;
component n2b = Num2Bits(n+1);
n2b.in <== in[0]+ (1<<n) - in[1];
out <== 1-n2b.out[n];
}
template BLSNum2Bits_strict() {
signal input in;
signal output out[255];
component check_range = CompConstant(23487852865797141623554994256013988874373056334117496812739262697960298774528); // -1 - 2**254 (p-1 without its first bit)
component n2b = Num2Bits(255);
in ==> n2b.in;
for (var i=0; i<255; i++) {
n2b.out[i] ==> out[i];
if(i != 0){
n2b.out[i] ==> check_range.in[i-1];
}
}
check_range.out * (n2b.out[0]) === 0; //must be zero exept if the first bit is 0 => then in is on 254 bits and p-1 on 255
}
template check_bits(n){
signal input bits[n];
for(var i=0; i<n; i++){
bits[i] * (1-bits[i]) === 0;
}
}
template commitment_computer(){
signal input note_nonce;
signal input nullifier_public_key;
signal input value;
signal input constraints;
signal input unit;
signal input state;
signal output commitment;
component hash = hash_16_to_1();
//The b"coin-commitment" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 516297089516239580383111224192495220;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_public_key;
hash.in[3] <== value;
hash.in[4] <== constraints;
hash.in[5] <== unit;
hash.in[6] <== state;
for(var i=7; i<16; i++){
hash.in[i] <== 0;
}
commitment <== hash.out;
}
template nonce_updater(){
signal input note_nonce;
signal input nullifier_secret_key;
signal output updated_nonce;
component hash = hash_4_to_1();
//The b"coin-evolve" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 120209783668687835891529317;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_secret_key;
hash.in[3] <== 0;
updated_nonce <== hash.out;
}
template nullifier_computer(){
signal input note_nonce;
signal input nullifier_secret_key;
signal input value;
signal output nullifier;
component hash = hash_4_to_1();
//The b"coin-nullifier" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 2016785505923014207119328528655730;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_secret_key;
hash.in[3] <== value;
nullifier <== hash.out;
}
template membership_checker(){
signal input note_commitment;
signal input pedersen_randomness;
signal input pedersen_commitment[2];
signal input h_curve_point[2];
component note_commitment_bitifier = Num2Bits(255);
component pedersen_randomness_bitifier = BLSNum2Bits_strict();
note_commitment_bitifier.in <== note_commitment;
pedersen_randomness_bitifier.in <== pedersen_randomness;
// A is note_cm * G and B is r * H
component A = EscalarMulAny(255);
component B = EscalarMulAny(255);
A.p[0] <== 0x11dafe5d23e1218086a365b99fbf3d3be72f6afd7d1f72623e6b071492d1122b;
A.p[1] <== 0x1d523cf1ddab1a1793132e78c866c0c33e26ba5cc220fed7cc3f870e59d292aa;
B.p[0] <== h_curve_point[0];
B.p[1] <== h_curve_point[1];
for(var i =0; i<255; i++){
A.e[i] <== note_commitment_bitifier.out[i];
B.e[i] <== pedersen_randomness_bitifier.out[i];
}
component pedersen = JubjubAdd();
pedersen.x1 <== A.out[0];
pedersen.y1 <== A.out[1];
pedersen.x2 <== B.out[0];
pedersen.y2 <== B.out[1];
pedersen.xout === pedersen_commitment[0];
pedersen.yout === pedersen_commitment[1];
}
template caulk_proof_of_validator(minimum_stake){ //TODO: put minimum_stake in the input to change it dynamically
signal input pedersen_commitment[2];
signal input h_curve_point[2];
// Note variables
signal input constraints; // Every note field represented as F_p elements for now (constraints are represented by their Merkle root)
signal input value; // 0 if no more notes needed
signal input unit;
signal input state; // This field hold the identity of the owner (its public key or ID) and is revealed
signal input note_nonce;
signal input nullifier_secret_key;
signal input pedersen_randomness;
signal output nullifiers;
signal output updated_commiments;
// Compute the note commitments
component note_committer = commitment_computer();
note_committer.note_nonce <== note_nonce;
note_committer.nullifier_public_key <== nullifier_secret_key; // TODO: reflect the nullifier public key computation later when defined
note_committer.value <== value;
note_committer.constraints <== constraints;
note_committer.unit <== unit;
note_committer.state <== state;
// Check the commitments membership
component membership_checker = membership_checker();
membership_checker.note_commitment <== note_committer.commitment;
membership_checker.pedersen_randomness <== pedersen_randomness;
membership_checker.pedersen_commitment[0] <== pedersen_commitment[0];
membership_checker.pedersen_commitment[1] <== pedersen_commitment[1];
membership_checker.h_curve_point[0] <== h_curve_point[0];
membership_checker.h_curve_point[1] <== h_curve_point[1];
// Check that the value exceed the minimum stake
component isLess = BLSLessThan(253);
isLess.in[0] <== minimum_stake;
isLess.in[1] <== value;
isLess.out === 1;
// Compute the note nullifiers
component nullifier_computer = nullifier_computer();
nullifier_computer.note_nonce <== note_nonce;
nullifier_computer.nullifier_secret_key <== nullifier_secret_key;
nullifier_computer.value <== value;
nullifiers <== nullifier_computer.nullifier;
// Compute the evolved nonces
component nonce_updater = nonce_updater();
nonce_updater.note_nonce <== note_nonce;
nonce_updater.nullifier_secret_key <== nullifier_secret_key;
// Compute the new note commitments
component updated_note_committer = commitment_computer();
updated_note_committer.note_nonce <== nonce_updater.updated_nonce;
updated_note_committer.nullifier_public_key <== nullifier_secret_key; // TODO: reflect the nullifier public key computation later when defined
updated_note_committer.value <== value;
updated_note_committer.constraints <== constraints;
updated_note_committer.unit <== unit;
updated_note_committer.state <== state;
updated_commiments <== updated_note_committer.commitment;
}
component main {public [state,pedersen_commitment,h_curve_point]} = caulk_proof_of_validator(10000);

View File

@ -1,226 +0,0 @@
//test
pragma circom 2.1.9;
include "../../circom_circuits/hash/anemoi/anemoi_2_to_1_Jubjub.circom";
include "../../circom_circuits/hash/anemoi/anemoi_4_to_1_Jubjub.circom";
include "../../circom_circuits/hash/anemoi/anemoi_16_to_1_Jubjub.circom";
include "../../circom_circuits/circomlib/circuits/bitify.circom";
include "../../circom_circuits/circomlib/circuits/comparators.circom";
template BLSLessThan(n) {
assert(n <= 253);
signal input in[2];
signal output out;
component n2b = Num2Bits(n+1);
n2b.in <== in[0]+ (1<<n) - in[1];
out <== 1-n2b.out[n];
}
template check_bits(n){
signal input bits[n];
for(var i=0; i<n; i++){
bits[i] * (1-bits[i]) === 0;
}
}
template commitment_computer(){
signal input note_nonce;
signal input nullifier_public_key;
signal input value;
signal input constraints;
signal input unit;
signal input state;
signal output commitment;
component hash = hash_16_to_1();
//The b"coin-commitment" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 516297089516239580383111224192495220;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_public_key;
hash.in[3] <== value;
hash.in[4] <== constraints;
hash.in[5] <== unit;
hash.in[6] <== state;
for(var i=7; i<16; i++){
hash.in[i] <== 0;
}
commitment <== hash.out;
}
template nonce_updater(){
signal input note_nonce;
signal input nullifier_secret_key;
signal output updated_nonce;
component hash = hash_4_to_1();
//The b"coin-evolve" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 120209783668687835891529317;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_secret_key;
hash.in[3] <== 0;
updated_nonce <== hash.out;
}
template nullifier_computer(){
signal input note_nonce;
signal input nullifier_secret_key;
signal input value;
signal output nullifier;
component hash = hash_4_to_1();
//The b"coin-nullifier" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 2016785505923014207119328528655730;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_secret_key;
hash.in[3] <== value;
nullifier <== hash.out;
}
template membership_checker(){
signal input leaf; //The note commitment
signal input root; //The root of the Merkle Tree (of depth 32)
signal input index[32]; //Position of the note commitment in bits in big endian
signal input node[32]; //Complementary hashes
signal input is_null; //If is_null is 1 we don't check the membership (any value of node and index will be correct)
component hash[32];
for(var i=0; i<32; i++){
hash[i] = hash_2_to_1();
}
hash[0].in[0] <== leaf - index[31] * (leaf - node[0]);
hash[0].in[1] <== node[0] - index[31] * (node[0] - leaf);
for(var i=1; i<32; i++){
hash[i].in[0] <== hash[i-1].out - index[31-i] * (hash[i-1].out - node[i]);
hash[i].in[1] <== node[i] - index[31-i] * (node[i] - hash[i-1].out);
}
root === hash[31].out * (1 - is_null);
}
template anemoi_proof_of_validator(max_notes){
signal input commitments_root;
signal input minimum_stake;
// Note variables
signal input constraints[max_notes]; // Every note field represented as F_p elements for now (constraints are represented by their Merkle root)
signal input value[max_notes]; // 0 if no more notes needed
signal input unit[max_notes];
signal input state[max_notes]; // This field hold the identity of the owner (its public key or ID)
signal input note_nonce[max_notes];
signal input nullifier_secret_key[max_notes];
signal input index[max_notes][32]; //Position of the note commitment in bits in big endian
signal input nodes[max_notes][32]; //Merkle proof of the commitment
signal output identity;
signal output nullifiers[max_notes];
signal output updated_commiments[max_notes];
// Check that index inputs are indeed bits
component bit_checker[max_notes];
for(var i=0; i<max_notes; i++){
bit_checker[i] = check_bits(32);
for(var j=0; j<32; j++){
bit_checker[i].bits[j] <== index[i][j];
}
}
// Compute the note commitments
component note_committer[max_notes];
for(var i=0; i<max_notes; i++){
note_committer[i] = commitment_computer();
note_committer[i].note_nonce <== note_nonce[i];
note_committer[i].nullifier_public_key <== nullifier_secret_key[i]; // TODO: reflect the nullifier public key computation later when defined
note_committer[i].value <== value[i];
note_committer[i].constraints <== constraints[i];
note_committer[i].unit <== unit[i];
note_committer[i].state <== state[i];
}
//check the identity between the notes
identity <== state[0]; // The first note must not be null
component is_null[max_notes];
is_null[0] = IsZero();
is_null[0].in <== value[0];
is_null[0].out === 0;
signal intermediate[max_notes-1];
for(var i=1; i<max_notes; i++){
is_null[i] = IsZero();
is_null[i].in <== value[i];
intermediate[i-1] <== identity * (1 - is_null[i].out);
intermediate[i-1] === state[i] * (1 - is_null[i].out);
}
// Check the commitments membership
component membership_checker[max_notes];
for(var i=0; i<max_notes; i++){
membership_checker[i] = membership_checker();
membership_checker[i].leaf <== note_committer[i].commitment;
membership_checker[i].root <== commitments_root * (1- is_null[i].out); // Set the root at 0 is note is null
membership_checker[i].is_null <== is_null[i].out;
for(var j =0; j<32; j++){
membership_checker[i].index[j] <== index[i][j];
membership_checker[i].node[j] <== nodes[i][j];
}
}
// Check that the value exceed the minimum stake
signal sum[max_notes-1];
sum[0] <== value[0] + value[1];
for(var i = 1; i<max_notes-1; i++){
sum[i] <== sum[i-1] + value[i+1];
}
component isLess = BLSLessThan(253);
isLess.in[0] <== minimum_stake;
isLess.in[1] <== sum[max_notes-2];
isLess.out === 1;
// Compute the note nullifiers
component nullifier_computer[max_notes];
for(var i=0; i<max_notes; i++){
nullifier_computer[i] = nullifier_computer();
nullifier_computer[i].note_nonce <== note_nonce[i];
nullifier_computer[i].nullifier_secret_key <== nullifier_secret_key[i];
nullifier_computer[i].value <== value[i];
nullifiers[i] <== nullifier_computer[i].nullifier;
}
// Compute the evolved nonces
component nonce_updater[max_notes];
for(var i=0; i<max_notes; i++) {
nonce_updater[i] = nonce_updater();
nonce_updater[i].note_nonce <== note_nonce[i];
nonce_updater[i].nullifier_secret_key <== nullifier_secret_key[i];
}
// Compute the new note commitments
component updated_note_committer[max_notes];
for(var i=0; i<max_notes; i++) {
updated_note_committer[i] = commitment_computer();
updated_note_committer[i].note_nonce <== nonce_updater[i].updated_nonce;
updated_note_committer[i].nullifier_public_key <== nullifier_secret_key[i]; // TODO: reflect the nullifier public key computation later when defined
updated_note_committer[i].value <== value[i];
updated_note_committer[i].constraints <== constraints[i];
updated_note_committer[i].unit <== unit[i];
updated_note_committer[i].state <== state[i];
updated_commiments[i] <== updated_note_committer[i].commitment;
}
}
component main {public [commitments_root, minimum_stake]} = anemoi_proof_of_validator(50);

View File

@ -1,227 +0,0 @@
//test
pragma circom 2.1.9;
include "../../circom_circuits/hash/poseidon/poseidon_2_to_1_Jubjub.circom";
include "../../circom_circuits/hash/poseidon/poseidon_4_to_1_Jubjub.circom";
include "../../circom_circuits/hash/poseidon/poseidon_16_to_1_Jubjub.circom";
include "../../circom_circuits/circomlib/circuits/bitify.circom";
include "../../circom_circuits/circomlib/circuits/comparators.circom";
template BLSLessThan(n) {
assert(n <= 253);
signal input in[2];
signal output out;
component n2b = Num2Bits(n+1);
n2b.in <== in[0]+ (1<<n) - in[1];
out <== 1-n2b.out[n];
}
template check_bits(n){
signal input bits[n];
for(var i=0; i<n; i++){
bits[i] * (1-bits[i]) === 0;
}
}
template commitment_computer(){
signal input note_nonce;
signal input nullifier_public_key;
signal input value;
signal input constraints;
signal input unit;
signal input state;
signal output commitment;
component hash = hash_16_to_1();
//The b"coin-commitment" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 516297089516239580383111224192495220;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_public_key;
hash.in[3] <== value;
hash.in[4] <== constraints;
hash.in[5] <== unit;
hash.in[6] <== state;
for(var i=7; i<16; i++){
hash.in[i] <== 0;
}
commitment <== hash.out;
}
template nullifier_computer(){
signal input note_nonce;
signal input nullifier_secret_key;
signal input value;
signal output nullifier;
component hash = hash_4_to_1();
//The b"coin-nullifier" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 2016785505923014207119328528655730;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_secret_key;
hash.in[3] <== value;
nullifier <== hash.out;
}
template nonce_updater(){
signal input note_nonce;
signal input nullifier_secret_key;
signal output updated_nonce;
component hash = hash_4_to_1();
//The b"coin-evolve" Tag converted in F_p element (from bits with big endian order)
hash.in[0] <== 120209783668687835891529317;
hash.in[1] <== note_nonce;
hash.in[2] <== nullifier_secret_key;
hash.in[3] <== 0;
updated_nonce <== hash.out;
}
template membership_checker(){
signal input leaf; //The note commitment
signal input root; //The root of the Merkle Tree (of depth 32)
signal input index[32]; //Position of the note commitment in bits in big endian
signal input node[32]; //Complementary hashes
signal input is_null; //If is_null is 1 we don't check the membership (any value of node and index will be correct)
component hash[32];
for(var i=0; i<32; i++){
hash[i] = hash_2_to_1();
}
hash[0].in[0] <== leaf - index[31] * (leaf - node[0]);
hash[0].in[1] <== node[0] - index[31] * (node[0] - leaf);
for(var i=1; i<32; i++){
hash[i].in[0] <== hash[i-1].out - index[31-i] * (hash[i-1].out - node[i]);
hash[i].in[1] <== node[i] - index[31-i] * (node[i] - hash[i-1].out);
}
root === hash[31].out * (1 - is_null);
}
template poseidon_proof_of_validator(max_notes){
signal input commitments_root;
signal input minimum_stake;
// Note variables
signal input constraints[max_notes]; // Every note field represented as F_p elements for now (constraints are represented by their Merkle root)
signal input value[max_notes]; // 0 if no more notes needed
signal input unit[max_notes];
signal input state[max_notes]; // This field hold the identity of the owner (its public key or ID)
signal input note_nonce[max_notes];
signal input nullifier_secret_key[max_notes];
signal input index[max_notes][32]; //Position of the note commitment in bits in big endian
signal input nodes[max_notes][32]; //Merkle proof of the commitment
signal output identity;
signal output nullifiers[max_notes];
signal output updated_commiments[max_notes];
// Check that index inputs are indeed bits
component bit_checker[max_notes];
for(var i=0; i<max_notes; i++){
bit_checker[i] = check_bits(32);
for(var j=0; j<32; j++){
bit_checker[i].bits[j] <== index[i][j];
}
}
// Compute the note commitments
component note_committer[max_notes];
for(var i=0; i<max_notes; i++){
note_committer[i] = commitment_computer();
note_committer[i].note_nonce <== note_nonce[i];
note_committer[i].nullifier_public_key <== nullifier_secret_key[i]; // TODO: reflect the nullifier public key computation later when defined
note_committer[i].value <== value[i];
note_committer[i].constraints <== constraints[i];
note_committer[i].unit <== unit[i];
note_committer[i].state <== state[i];
}
//check the identity between the notes
identity <== state[0]; // The first note must not be null
component is_null[max_notes];
is_null[0] = IsZero();
is_null[0].in <== value[0];
is_null[0].out === 0;
signal intermediate[max_notes-1];
for(var i=1; i<max_notes; i++){
is_null[i] = IsZero();
is_null[i].in <== value[i];
intermediate[i-1] <== identity * (1 - is_null[i].out);
intermediate[i-1] === state[i] * (1 - is_null[i].out);
}
// Check the commitments membership
component membership_checker[max_notes];
for(var i=0; i<max_notes; i++){
membership_checker[i] = membership_checker();
membership_checker[i].leaf <== note_committer[i].commitment;
membership_checker[i].root <== commitments_root * (1- is_null[i].out); // Set the root at 0 is note is null
membership_checker[i].is_null <== is_null[i].out;
for(var j =0; j<32; j++){
membership_checker[i].index[j] <== index[i][j];
membership_checker[i].node[j] <== nodes[i][j];
}
}
// Check that the value exceed the minimum stake
signal sum[max_notes-1];
sum[0] <== value[0] + value[1];
for(var i = 1; i<max_notes-1; i++){
sum[i] <== sum[i-1] + value[i+1];
}
component isLess = BLSLessThan(253);
isLess.in[0] <== minimum_stake;
isLess.in[1] <== sum[max_notes-2];
isLess.out === 1;
// Compute the note nullifiers
component nullifier_computer[max_notes];
for(var i=0; i<max_notes; i++){
nullifier_computer[i] = nullifier_computer();
nullifier_computer[i].note_nonce <== note_nonce[i];
nullifier_computer[i].nullifier_secret_key <== nullifier_secret_key[i];
nullifier_computer[i].value <== value[i];
nullifiers[i] <== nullifier_computer[i].nullifier;
}
// Compute the evolved nonces
component nonce_updater[max_notes];
for(var i=0; i<max_notes; i++) {
nonce_updater[i] = nonce_updater();
nonce_updater[i].note_nonce <== note_nonce[i];
nonce_updater[i].nullifier_secret_key <== nullifier_secret_key[i];
}
// Compute the new note commitments
component updated_note_committer[max_notes];
for(var i=0; i<max_notes; i++) {
updated_note_committer[i] = commitment_computer();
updated_note_committer[i].note_nonce <== nonce_updater[i].updated_nonce;
updated_note_committer[i].nullifier_public_key <== nullifier_secret_key[i]; // TODO: reflect the nullifier public key computation later when defined
updated_note_committer[i].value <== value[i];
updated_note_committer[i].constraints <== constraints[i];
updated_note_committer[i].unit <== unit[i];
updated_note_committer[i].state <== state[i];
updated_commiments[i] <== updated_note_committer[i].commitment;
}
}
component main {public [commitments_root, minimum_stake]} = poseidon_proof_of_validator(50);