aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWei-Ning Huang <w@dexon.org>2019-04-11 18:32:33 +0800
committerGitHub <noreply@github.com>2019-04-11 18:32:33 +0800
commitb7ca8e6c9bafda89c91aa3d35a8feb3f9f6bab25 (patch)
tree59d29630eba2f02e452960a70b7bea7e6d32e592
parent2922460b04b4378ce202e5fdb92ff6ad9607ab89 (diff)
downloaddexon-b7ca8e6c9bafda89c91aa3d35a8feb3f9f6bab25.tar.gz
dexon-b7ca8e6c9bafda89c91aa3d35a8feb3f9f6bab25.tar.zst
dexon-b7ca8e6c9bafda89c91aa3d35a8feb3f9f6bab25.zip
vendor: use BLS-12_384 curve and update dependencies (#356)
-rw-r--r--Dockerfile7
-rw-r--r--Dockerfile.alltools3
-rw-r--r--Makefile10
-rw-r--r--vendor/github.com/dexon-foundation/bls/.gitignore7
-rw-r--r--vendor/github.com/dexon-foundation/bls/.travis.yml39
-rw-r--r--vendor/github.com/dexon-foundation/bls/CMakeLists.txt33
-rw-r--r--vendor/github.com/dexon-foundation/bls/Makefile108
-rw-r--r--vendor/github.com/dexon-foundation/bls/bin/.emptydir0
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/cs/App.config6
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/cs/Properties/AssemblyInfo.cs36
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/cs/bls.cs351
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/cs/bls.csproj97
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/cs/bls.sln25
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.cs298
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.csproj62
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.sln22
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/cs/bls256_test.cs126
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/cs/bls_test.cs176
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/cs/readme-ja.md188
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/cs/readme.md185
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/go/bls/bls.go127
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/go/bls/bls_test.go690
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/go/bls/callback.go12
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/go/bls/config.h6
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/go/bls/dummy.cpp3
-rw-r--r--vendor/github.com/dexon-foundation/bls/ffi/go/bls/mcl.go16
-rw-r--r--vendor/github.com/dexon-foundation/bls/images/bls-go-alpine/Dockerfile12
-rw-r--r--vendor/github.com/dexon-foundation/bls/include/bls/bls.h51
-rw-r--r--vendor/github.com/dexon-foundation/bls/include/bls/bls.hpp44
-rw-r--r--vendor/github.com/dexon-foundation/bls/mk.bat1
-rw-r--r--vendor/github.com/dexon-foundation/bls/mklib.bat4
-rw-r--r--vendor/github.com/dexon-foundation/bls/readme.md23
-rw-r--r--vendor/github.com/dexon-foundation/bls/sample/bls_smpl.cpp168
-rwxr-xr-xvendor/github.com/dexon-foundation/bls/setvar.bat4
-rw-r--r--vendor/github.com/dexon-foundation/bls/src/bls_c384_256.cpp4
-rw-r--r--vendor/github.com/dexon-foundation/bls/src/bls_c_impl.hpp299
-rw-r--r--vendor/github.com/dexon-foundation/bls/test/bls256_test.cpp3
-rw-r--r--vendor/github.com/dexon-foundation/bls/test/bls384_256_test.cpp4
-rw-r--r--vendor/github.com/dexon-foundation/bls/test/bls384_test.cpp3
-rw-r--r--vendor/github.com/dexon-foundation/bls/test/bls_c256_test.cpp2
-rw-r--r--vendor/github.com/dexon-foundation/bls/test/bls_c384_256_test.cpp3
-rw-r--r--vendor/github.com/dexon-foundation/bls/test/bls_c384_test.cpp2
-rw-r--r--vendor/github.com/dexon-foundation/bls/test/bls_c_test.hpp437
-rw-r--r--vendor/github.com/dexon-foundation/bls/test/bls_test.hpp545
-rw-r--r--vendor/github.com/dexon-foundation/bls/test/proj/bls_test/bls_test.vcxproj88
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/crypto/dkg/constant.go2
-rw-r--r--vendor/github.com/dexon-foundation/mcl/.gitignore13
-rw-r--r--vendor/github.com/dexon-foundation/mcl/.travis.yml17
-rw-r--r--vendor/github.com/dexon-foundation/mcl/CMakeLists.txt16
-rw-r--r--vendor/github.com/dexon-foundation/mcl/Makefile66
-rw-r--r--vendor/github.com/dexon-foundation/mcl/common.mk2
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/cs/App.config6
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/cs/Properties/AssemblyInfo.cs36
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.cs475
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.csproj62
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.sln22
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256_test.cs149
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/go/mcl/mcl.go659
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/go/mcl/mcl_test.go157
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/java/Bn256Test.java104
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/java/ElgamalTest.java144
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/java/Makefile64
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/java/bn256.i31
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/java/bn256_impl.hpp249
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/java/bn256_wrap.cxx1542
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal.i28
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal_impl.hpp147
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal_wrap.cxx1129
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/java/java.md95
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/java/make_wrap.bat23
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/java/run-bn256.bat9
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/java/run-elgamal.bat9
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/java/set-java-path.bat8
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/js/export-functions.py73
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/js/pre-mcl.js5
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/python/pairing.py80
-rw-r--r--vendor/github.com/dexon-foundation/mcl/ffi/python/she.py298
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/cybozu/random_generator.hpp34
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/cybozu/sha2.hpp345
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/cybozu/xorshift.hpp113
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/mcl/array.hpp25
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/mcl/bn.h62
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/mcl/bn.hpp119
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/mcl/curve_type.h19
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/mcl/ec.hpp104
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/mcl/ecparam.hpp51
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/mcl/elgamal.hpp18
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/mcl/fp.hpp66
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/mcl/fp_tower.hpp330
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/mcl/gmp_util.hpp95
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/mcl/impl/bn_c_impl.hpp643
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/mcl/lagrange.hpp22
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/mcl/op.hpp24
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/mcl/randgen.hpp58
-rw-r--r--vendor/github.com/dexon-foundation/mcl/include/mcl/vint.hpp71
-rw-r--r--vendor/github.com/dexon-foundation/mcl/misc/bench.txt21
-rw-r--r--vendor/github.com/dexon-foundation/mcl/misc/karatsuba.cpp75
-rw-r--r--vendor/github.com/dexon-foundation/mcl/misc/mul.cpp58
-rw-r--r--vendor/github.com/dexon-foundation/mcl/misc/precompute.cpp30
-rw-r--r--vendor/github.com/dexon-foundation/mcl/misc/she/bench.sh6
-rw-r--r--vendor/github.com/dexon-foundation/mcl/misc/she/bench4.txt99
-rw-r--r--vendor/github.com/dexon-foundation/mcl/misc/she/bench6.txt99
-rw-r--r--vendor/github.com/dexon-foundation/mcl/misc/she/bench8.txt99
-rw-r--r--vendor/github.com/dexon-foundation/mcl/misc/she/nizkp.pdfbin0 -> 28787 bytes
-rw-r--r--vendor/github.com/dexon-foundation/mcl/misc/she/she-api-ja.md314
-rw-r--r--vendor/github.com/dexon-foundation/mcl/misc/she/she-api.md322
-rw-r--r--vendor/github.com/dexon-foundation/mcl/misc/she/she.pdfbin0 -> 25716 bytes
-rw-r--r--vendor/github.com/dexon-foundation/mcl/mklib.bat5
-rw-r--r--vendor/github.com/dexon-foundation/mcl/readme.md140
-rw-r--r--vendor/github.com/dexon-foundation/mcl/sample/bench.cpp233
-rw-r--r--vendor/github.com/dexon-foundation/mcl/sample/bls_sig.cpp70
-rw-r--r--vendor/github.com/dexon-foundation/mcl/sample/ecdh.cpp64
-rw-r--r--vendor/github.com/dexon-foundation/mcl/sample/large.cpp125
-rw-r--r--vendor/github.com/dexon-foundation/mcl/sample/pairing.cpp56
-rw-r--r--vendor/github.com/dexon-foundation/mcl/sample/pairing_c.c52
-rw-r--r--vendor/github.com/dexon-foundation/mcl/sample/random.cpp29
-rw-r--r--vendor/github.com/dexon-foundation/mcl/sample/rawbench.cpp180
-rw-r--r--vendor/github.com/dexon-foundation/mcl/sample/she_make_dlp_table.cpp69
-rw-r--r--vendor/github.com/dexon-foundation/mcl/sample/she_smpl.cpp125
-rw-r--r--vendor/github.com/dexon-foundation/mcl/sample/tri-dh.cpp97
-rw-r--r--vendor/github.com/dexon-foundation/mcl/sample/vote.cpp206
-rw-r--r--vendor/github.com/dexon-foundation/mcl/src/bn_c256.cpp2
-rw-r--r--vendor/github.com/dexon-foundation/mcl/src/bn_c384.cpp2
-rw-r--r--vendor/github.com/dexon-foundation/mcl/src/bn_c384_256.cpp2
-rw-r--r--vendor/github.com/dexon-foundation/mcl/src/bn_c512.cpp2
-rw-r--r--vendor/github.com/dexon-foundation/mcl/src/fp.cpp83
-rw-r--r--vendor/github.com/dexon-foundation/mcl/src/fp_generator.hpp1460
-rw-r--r--vendor/github.com/dexon-foundation/mcl/src/she_c_impl.hpp2
-rw-r--r--vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak.h53
-rw-r--r--vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak_mnemonic.h2
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/aggregate_sig_test.cpp74
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/array_test.cpp104
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/base_test.cpp392
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/bench.hpp192
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/bls12_test.cpp720
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/bn384_test.cpp83
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/bn512_test.cpp68
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/bn_c256_test.cpp6
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/bn_c384_256_test.cpp7
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/bn_c384_test.cpp6
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/bn_c512_test.cpp6
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/bn_c_test.hpp699
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/bn_test.cpp408
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/conversion_test.cpp96
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/ec_test.cpp573
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/ecdsa_c_test.cpp51
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/ecdsa_test.cpp69
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/elgamal_test.cpp155
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/fp_generator_test.cpp207
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/fp_test.cpp1046
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/fp_tower_test.cpp477
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/fp_util_test.cpp270
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/glv_test.cpp209
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/gmp_test.cpp70
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/low_test.cpp73
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/mk32.sh1
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/modp_test.cpp37
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/mont_fp_test.cpp332
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/paillier_test.cpp24
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/proj/bn_test/bn_test.vcxproj88
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/proj/ec_test/ec_test.vcxproj88
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/proj/fp_test/fp_test.vcxproj88
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/proj/fp_tower_test/fp_tower_test.vcxproj88
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/she_c256_test.cpp2
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/she_c384_test.cpp2
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/she_c_test.hpp535
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/she_test.cpp756
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/sq_test.cpp21
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/vint_test.cpp1353
-rw-r--r--vendor/github.com/dexon-foundation/mcl/test/window_method_test.cpp70
-rw-r--r--vendor/vendor.json42
171 files changed, 24751 insertions, 1268 deletions
diff --git a/Dockerfile b/Dockerfile
index 01490d5b8..89bf55ecc 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,14 +1,15 @@
FROM golang:1.12-alpine as builder
-RUN apk add --no-cache make gcc musl-dev linux-headers g++ gmp-dev openssl-dev pkgconfig
+RUN apk add --no-cache make gcc musl-dev linux-headers g++ gmp-dev pkgconfig
ADD . /dexon
-RUN cd /dexon && make clean && DOCKER=alpine make gdex all
+RUN cd /dexon && make clean-cgo && DOCKER=alpine make gdex
+RUN cd /dexon && build/env.sh go build -o build/bin/bootnode ./cmd/bootnode
# Pull Gdex into a second stage deploy alpine container
FROM alpine:latest
-RUN apk add --no-cache ca-certificates libstdc++ curl gmp openssl
+RUN apk add --no-cache ca-certificates curl
COPY --from=builder /dexon/build/bin/gdex /usr/local/bin/
COPY --from=builder /dexon/build/bin/bootnode /usr/local/bin/
diff --git a/Dockerfile.alltools b/Dockerfile.alltools
index 9c85a8802..1809f797d 100644
--- a/Dockerfile.alltools
+++ b/Dockerfile.alltools
@@ -1,7 +1,7 @@
# Build Geth in a stock Go builder container
FROM golang:1.12-alpine as builder
-RUN apk add --no-cache make gcc musl-dev linux-headers g++ gmp-dev openssl-dev pkgconfig
+RUN apk add --no-cache make gcc musl-dev linux-headers g++ gmp-dev pkgconfig
ADD . /dexon
RUN cd /dexon && make clean && DOCKER=alpine make all
@@ -9,7 +9,6 @@ RUN cd /dexon && make clean && DOCKER=alpine make all
# Pull all binaries into a second stage deploy alpine container
FROM alpine:latest
-RUN apk add --no-cache ca-certificates libstdc++ gmp openssl
COPY --from=builder /dexon/build/bin/* /usr/local/bin/
EXPOSE 8545 8546 30303 30303/udp
diff --git a/Makefile b/Makefile
index 9cdd9e5b0..14f79c8ef 100644
--- a/Makefile
+++ b/Makefile
@@ -41,14 +41,16 @@ lint: ## Run linters.
build/env.sh go run build/ci.go lint
libbls:
- make -C vendor/github.com/dexon-foundation/bls lib/libbls384.a
+ make -C vendor/github.com/dexon-foundation/bls MCL_USE_OPENSSL=0 lib/libbls384.a
-clean:
- ./build/clean_go_build_cache.sh
- rm -fr build/_workspace/pkg/ $(GOBIN)/*
+clean-cgo:
make -C vendor/github.com/dexon-foundation/bls clean
make -C vendor/github.com/dexon-foundation/mcl clean
+clean: clean-cgo
+ ./build/clean_go_build_cache.sh
+ rm -fr build/_workspace/pkg/ $(GOBIN)/*
+
# The devtools target installs tools required for 'go generate'.
# You need to put $GOBIN (or $GOPATH/bin) in your PATH to use 'go generate'.
diff --git a/vendor/github.com/dexon-foundation/bls/.gitignore b/vendor/github.com/dexon-foundation/bls/.gitignore
new file mode 100644
index 000000000..dacdfc906
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/.gitignore
@@ -0,0 +1,7 @@
+CVS
+bin/*.exe
+lib/*.a
+lib/*.so
+lib/*.dylib
+obj/*.d
+obj/*.o
diff --git a/vendor/github.com/dexon-foundation/bls/.travis.yml b/vendor/github.com/dexon-foundation/bls/.travis.yml
new file mode 100644
index 000000000..71a667a2e
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/.travis.yml
@@ -0,0 +1,39 @@
+sudo: true
+dist: xenial
+services:
+- docker
+env:
+ global:
+ - IMAGE_TAG=dexonfoundation/bls-go-alpine
+ - DOCKER_USER=spiderpowadeploy
+ - secure: mqNCngWukyjE3UARxaPjqS0xgC1dsnWfmPhpH2mq7nR6S2cGfJ3xBfyiTS//Clz//7sAL+Tp62r3fxyMjDogrSHZUUssCAwf17RM6vnALqaVbc3wXcTNudiDB5cVKe9C9gZqn1Ivd+qbmtuCezSrOG5Xih1gh4bPTyiFvU1sp9C2icMHkJZkjsP0QqCbHlQrMeECSIPlEGIOXUUSp+WmrZAdi2rHezKeZxuaT73RX1+N/+1RfWXo2MR4ydQU3eALl5s5UA9JweQO+MYIVr8EEpGNqJRYUyURx/5G/Sy2v6Z3imUvXZv1J5aplW/UDls92Olla1JHuvFW6ptRO+PHITNwvEkhxPFj+HcOpqEuSISsdk9rkHUrM0wEYPv6A4vQPUjMHrLQs2tQShVCelM1HtNvDDjttKMmVyRLusFP9eS7uvmmXu2l6efJjsMSFkY5WKbu2U0MQ1j708KH9k2WunU6sjJ+b74PkkZVtkQMIqgTokC0IOqbbrnwh4I9PpVpHAQrewRimMH+lDHk+HlMUCWk7/IcIFUl+mh6RzW2vkZTTr2ctSBI6QzK5smdPmqQpp2lqkGv/hQCBp5ICzFSkU6Djqe3hG8ta3+/Zhi10fPU2HcHDi+gR79CG8dvy+iOeTS2csXZx+YoN2BVkfu9AnrjZ9Kjkf9BMay4CehBUWE=
+language: cpp
+compiler:
+- gcc
+- clang
+addons:
+ apt:
+ packages:
+ - libgmp-dev
+install:
+- git clone --depth 1 https://github.com/dexon-foundation/mcl.git $TRAVIS_BUILD_DIR/../mcl
+script:
+- make -j3
+- make test_ci DISABLE_THREAD_TEST=1
+- make test_go
+- env LD_LIBRARY_PATH=../mcl/lib bin/bls_c384_test.exe
+- make clean && make -C ../mcl clean
+- make -j3 MCL_USE_OPENSSL=0
+- make test_ci DISABLE_THREAD_TEST=1 MCL_USE_OPENSSL=0
+- docker build --tag "$IMAGE_TAG" . -f images/bls-go-alpine/Dockerfile --no-cache
+before_deploy:
+- echo "$DOCKER_PASS" | docker login -u "$DOCKER_USER" --password-stdin
+- git_commit="$(git rev-parse --short HEAD)"
+- docker tag "$IMAGE_TAG" "${IMAGE_TAG}:${git_commit}"
+- docker tag "$IMAGE_TAG" "${IMAGE_TAG}:latest"
+deploy:
+ provider: script
+ script: docker push "${IMAGE_TAG}:latest" && docker push "${IMAGE_TAG}:${git_commit}"
+ on:
+ branch: dev
+ condition: "$CC = gcc"
diff --git a/vendor/github.com/dexon-foundation/bls/CMakeLists.txt b/vendor/github.com/dexon-foundation/bls/CMakeLists.txt
new file mode 100644
index 000000000..30fb90fd5
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/CMakeLists.txt
@@ -0,0 +1,33 @@
+cmake_minimum_required (VERSION 2.6)
+project(bls CXX ASM)
+
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+
+set(LIBS mcl gmp)
+
+include_directories(include/)
+
+add_library(bls_c256 SHARED src/bls_c256.cpp)
+add_library(bls_c384 SHARED src/bls_c384.cpp)
+add_library(bls_c384_256 SHARED src/bls_c384_256.cpp)
+target_link_libraries(bls_c256 ${LIBS})
+target_link_libraries(bls_c384 ${LIBS})
+target_link_libraries(bls_c384_256 ${LIBS})
+
+file(GLOB BLS_HEADERS include/bls/bls.h include/bls/bls.hpp)
+
+install(TARGETS bls_c256 DESTINATION lib)
+install(TARGETS bls_c384 DESTINATION lib)
+install(TARGETS bls_c384_256 DESTINATION lib)
+install(FILES ${BLS_HEADERS} DESTINATION include/bls)
+
+set(TEST_LIBS pthread gmpxx)
+
+add_executable(bls_c256_test test/bls_c256_test.cpp)
+target_link_libraries(bls_c256_test bls_c256 ${TEST_LIBS})
+add_executable(bls_c384_test test/bls_c384_test.cpp)
+target_link_libraries(bls_c384_test bls_c384 ${TEST_LIBS})
+add_executable(bls_c384_256_test test/bls_c384_256_test.cpp)
+target_link_libraries(bls_c384_256_test bls_c384_256 ${TEST_LIBS})
diff --git a/vendor/github.com/dexon-foundation/bls/Makefile b/vendor/github.com/dexon-foundation/bls/Makefile
index 556f625ec..efea22274 100644
--- a/vendor/github.com/dexon-foundation/bls/Makefile
+++ b/vendor/github.com/dexon-foundation/bls/Makefile
@@ -1,55 +1,73 @@
-include ../mcl/common.mk
+ifeq ($(findstring MINGW64,$(shell uname -s)),MINGW64)
+ # cgo accepts not '/c/path' but 'c:/path'
+ PWD=$(shell pwd|sed s'@^/\([a-z]\)@\1:@')
+else
+ PWD=$(shell pwd)
+endif
+MCL_DIR?=$(PWD)/../mcl
+include $(MCL_DIR)/common.mk
LIB_DIR=lib
OBJ_DIR=obj
EXE_DIR=bin
CFLAGS += -std=c++11
LDFLAGS += -lpthread
-SRC_SRC=bls_c256.cpp bls_c384.cpp
-TEST_SRC=bls256_test.cpp bls384_test.cpp bls_c256_test.cpp bls_c384_test.cpp
+SRC_SRC=bls_c256.cpp bls_c384.cpp bls_c384_256.cpp
+TEST_SRC=bls256_test.cpp bls384_test.cpp bls384_256_test.cpp bls_c256_test.cpp bls_c384_test.cpp bls_c384_256_test.cpp
SAMPLE_SRC=bls256_smpl.cpp bls384_smpl.cpp
-CFLAGS+=-I../mcl/include -I./
+CFLAGS+=-I$(MCL_DIR)/include
ifneq ($(MCL_MAX_BIT_SIZE),)
CFLAGS+=-DMCL_MAX_BIT_SIZE=$(MCL_MAX_BIT_SIZE)
endif
ifeq ($(DISABLE_THREAD_TEST),1)
CFLAGS+=-DDISABLE_THREAD_TEST
endif
-
-SHARE_BASENAME_SUF?=_dy
+ifeq ($(BLS_SWAP_G),1)
+ CFLAGS+=-DBLS_SWAP_G
+endif
BLS256_LIB=$(LIB_DIR)/libbls256.a
BLS384_LIB=$(LIB_DIR)/libbls384.a
-BLS256_SNAME=bls256$(SHARE_BASENAME_SUF)
-BLS384_SNAME=bls384$(SHARE_BASENAME_SUF)
+BLS384_256_LIB=$(LIB_DIR)/libbls384_256.a
+BLS256_SNAME=bls256
+BLS384_SNAME=bls384
+BLS384_256_SNAME=bls384_256
BLS256_SLIB=$(LIB_DIR)/lib$(BLS256_SNAME).$(LIB_SUF)
BLS384_SLIB=$(LIB_DIR)/lib$(BLS384_SNAME).$(LIB_SUF)
-all: $(BLS256_LIB) $(BLS256_SLIB) $(BLS384_LIB) $(BLS384_SLIB)
+BLS384_256_SLIB=$(LIB_DIR)/lib$(BLS384_256_SNAME).$(LIB_SUF)
+all: $(BLS256_LIB) $(BLS256_SLIB) $(BLS384_LIB) $(BLS384_SLIB) $(BLS384_256_LIB) $(BLS384_256_SLIB)
-MCL_LIB=../mcl/lib/libmcl.a
+MCL_LIB=$(MCL_DIR)/lib/libmcl.a
$(MCL_LIB):
- $(MAKE) -C ../mcl lib/libmcl.a
+ $(MAKE) -C $(MCL_DIR)
-$(BLS256_LIB): $(OBJ_DIR)/bls_c256.o
+$(BLS256_LIB): $(OBJ_DIR)/bls_c256.o $(MCL_LIB)
$(AR) $@ $<
$(BLS384_LIB): $(OBJ_DIR)/bls_c384.o $(MCL_LIB)
$(AR) $@ $<
+$(BLS384_256_LIB): $(OBJ_DIR)/bls_c384_256.o $(MCL_LIB)
+ $(AR) $@ $<
ifneq ($(findstring $(OS),mac/mingw64),)
- BLS256_SLIB_LDFLAGS+=-lgmpxx -lgmp -lcrypto -lstdc++
- BLS384_SLIB_LDFLAGS+=-lgmpxx -lgmp -lcrypto -lstdc++
+ COMMON_LIB=$(GMP_LIB) $(OPENSSL_LIB) -lstdc++
+ BLS256_SLIB_LDFLAGS+=$(COMMON_LIB)
+ BLS384_SLIB_LDFLAGS+=$(COMMON_LIB)
+ BLS384_256_SLIB_LDFLAGS+=$(COMMON_LIB)
endif
ifeq ($(OS),mingw64)
- CFLAGS+=-I../mcl
+ CFLAGS+=-I$(MCL_DIR)
BLS256_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(BLS256_SNAME).a
BLS384_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(BLS384_SNAME).a
+ BLS384_256_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(BLS384_256_SNAME).a
endif
$(BLS256_SLIB): $(OBJ_DIR)/bls_c256.o $(MCL_LIB)
- $(PRE)$(CXX) -shared -o $@ $< $(MCL_LIB) $(BLS256_SLIB_LDFLAGS)
+ $(PRE)$(CXX) -shared -o $@ $< -L$(MCL_DIR)/lib -lmcl $(BLS256_SLIB_LDFLAGS) $(LDFLAGS)
$(BLS384_SLIB): $(OBJ_DIR)/bls_c384.o $(MCL_LIB)
- $(PRE)$(CXX) -shared -o $@ $< $(MCL_LIB) $(BLS384_SLIB_LDFLAGS)
+ $(PRE)$(CXX) -shared -o $@ $< -L$(MCL_DIR)/lib -lmcl $(BLS384_SLIB_LDFLAGS) $(LDFLAGS)
+$(BLS384_256_SLIB): $(OBJ_DIR)/bls_c384_256.o $(MCL_LIB)
+ $(PRE)$(CXX) -shared -o $@ $< -L$(MCL_DIR)/lib -lmcl $(BLS384_256_SLIB_LDFLAGS) $(LDFLAGS)
VPATH=test sample src
@@ -58,35 +76,58 @@ VPATH=test sample src
$(OBJ_DIR)/%.o: %.cpp
$(PRE)$(CXX) $(CFLAGS) -c $< -o $@ -MMD -MP -MF $(@:.o=.d)
+$(EXE_DIR)/%384_256_test.exe: $(OBJ_DIR)/%384_256_test.o $(BLS384_256_LIB) $(MCL_LIB)
+ $(PRE)$(CXX) $< -o $@ $(BLS384_256_LIB) -L$(MCL_DIR)/lib -lmcl $(LDFLAGS)
+
$(EXE_DIR)/%384_test.exe: $(OBJ_DIR)/%384_test.o $(BLS384_LIB) $(MCL_LIB)
- $(PRE)$(CXX) $< -o $@ $(BLS384_LIB) -lmcl -L../mcl/lib $(LDFLAGS)
+ $(PRE)$(CXX) $< -o $@ $(BLS384_LIB) -L$(MCL_DIR)/lib -lmcl $(LDFLAGS)
$(EXE_DIR)/%256_test.exe: $(OBJ_DIR)/%256_test.o $(BLS256_LIB) $(MCL_LIB)
- $(PRE)$(CXX) $< -o $@ $(BLS256_LIB) -lmcl -L../mcl/lib $(LDFLAGS)
+ $(PRE)$(CXX) $< -o $@ $(BLS256_LIB) -L$(MCL_DIR)/lib -lmcl $(LDFLAGS)
# sample exe links libbls256.a
$(EXE_DIR)/%.exe: $(OBJ_DIR)/%.o $(BLS256_LIB) $(MCL_LIB)
- $(PRE)$(CXX) $< -o $@ $(BLS256_LIB) -lmcl -L../mcl/lib $(LDFLAGS)
+ $(PRE)$(CXX) $< -o $@ $(BLS256_LIB) -L$(MCL_DIR)/lib -lmcl $(LDFLAGS)
+ifeq ($(OS),mac)
+ install_name_tool bin/bls_smpl.exe -change lib/libmcl.dylib $(MCL_DIR)/lib/libmcl.dylib
+endif
SAMPLE_EXE=$(addprefix $(EXE_DIR)/,$(SAMPLE_SRC:.cpp=.exe))
sample: $(SAMPLE_EXE)
TEST_EXE=$(addprefix $(EXE_DIR)/,$(TEST_SRC:.cpp=.exe))
+ifeq ($(OS),mac)
+ LIBPATH_KEY=DYLD_LIBRARY_PATH
+else
+ LIBPATH_KEY=LD_LIBRARY_PATH
+endif
+test_ci: $(TEST_EXE)
+ @sh -ec 'for i in $(TEST_EXE); do echo $$i; env PATH=$$PATH:../mcl/lib $(LIBPATH_KEY)=../mcl/lib LSAN_OPTIONS=verbosity=1 log_threads=1 $$i; done'
+ $(MAKE) sample_test
+
test: $(TEST_EXE)
@echo test $(TEST_EXE)
- @sh -ec 'for i in $(TEST_EXE); do $$i|grep "ctest:name"; done' > result.txt
+ @sh -ec 'for i in $(TEST_EXE); do env PATH=$$PATH:../mcl/lib $(LIBPATH_KEY)=../mcl/lib $$i|grep "ctest:name"; done' > result.txt
@grep -v "ng=0, exception=0" result.txt; if [ $$? -eq 1 ]; then echo "all unit tests succeed"; else exit 1; fi
$(MAKE) sample_test
sample_test: $(EXE_DIR)/bls_smpl.exe
- python bls_smpl.py
-
-ifeq ($(OS),mac)
- MAC_GO_LDFLAGS="-ldflags=-s"
-endif
-# PATH is for mingw, LD_RUN_PATH is for linux, DYLD_LIBRARY_PATH is for mac
-test_go: ffi/go/bls/bls.go ffi/go/bls/bls_test.go $(BLS384_LIB)
- cd ffi/go/bls && go test $(MAC_GO_LDFLAGS) .
+ env PATH=$$PATH:../mcl/lib $(LIBPATH_KEY)=../mcl/lib python bls_smpl.py
+
+# PATH is for mingw, LD_LIBRARY_PATH is for linux, DYLD_LIBRARY_PATH is for mac
+COMMON_LIB_PATH="../../../lib:../../../../mcl/lib"
+PATH_VAL=$$PATH:$(COMMON_LIB_PATH) LD_LIBRARY_PATH=$(COMMON_LIB_PATH) DYLD_LIBRARY_PATH=$(COMMON_LIB_PATH)
+test_go256: ffi/go/bls/bls.go ffi/go/bls/bls_test.go $(BLS256_LIB)
+ cd ffi/go/bls && env PATH=$(PATH_VAL) go test -tags bn256 .
+test_go384: ffi/go/bls/bls.go ffi/go/bls/bls_test.go $(BLS384_LIB)
+ cd ffi/go/bls && env PATH=$(PATH_VAL) go test -tags bn384 .
+test_go384_256: ffi/go/bls/bls.go ffi/go/bls/bls_test.go $(BLS384_256_LIB)
+ cd ffi/go/bls && env PATH=$(PATH_VAL) go test -tags bn384_256 .
+
+test_go:
+ $(MAKE) test_go256
+ $(MAKE) test_go384
+ $(MAKE) test_go384_256
EMCC_OPT=-I./include -I./src -I../mcl/include -I./ -Wall -Wextra
EMCC_OPT+=-O3 -DNDEBUG
@@ -103,12 +144,19 @@ bls-wasm:
$(MAKE) ../bls-wasm/bls_c.js
clean:
- $(RM) $(OBJ_DIR)/*.d $(OBJ_DIR)/*.o $(EXE_DIR)/*.exe $(GEN_EXE) $(ASM_SRC) $(ASM_OBJ) $(LLVM_SRC) $(BLS256_LIB) $(BLS256_SLIB) $(BLS384_LIB) $(BLS384_SLIB)
+ $(RM) $(OBJ_DIR)/*.d $(OBJ_DIR)/*.o $(EXE_DIR)/*.exe $(GEN_EXE) $(ASM_SRC) $(ASM_OBJ) $(LLVM_SRC) $(BLS256_LIB) $(BLS256_SLIB) $(BLS384_LIB) $(BLS384_SLIB) $(BLS384_256_LIB) $(BLS384_256_SLIB)
ALL_SRC=$(SRC_SRC) $(TEST_SRC) $(SAMPLE_SRC)
DEPEND_FILE=$(addprefix $(OBJ_DIR)/, $(ALL_SRC:.cpp=.d))
-include $(DEPEND_FILE)
+PREFIX?=/usr/local
+install: lib/libbls256.a lib/libbls256.$(LIB_SUF) lib/libbls384.a lib/libbls384.$(LIB_SUF) lib/libbls384_256.a lib/libbls384_256.$(LIB_SUF)
+ $(MKDIR) $(PREFIX)/include/bls
+ cp -a include/bls/ $(PREFIX)/include/
+ $(MKDIR) $(PREFIX)/lib
+ cp -a lib/libbls256.a lib/libbls256.$(LIB_SUF) lib/libbls384.a lib/libbls384.$(LIB_SUF) lib/libbls384_256.a lib/libbls384_256.$(LIB_SUF) $(PREFIX)/lib/
+
.PHONY: test bls-wasm
# don't remove these files automatically
diff --git a/vendor/github.com/dexon-foundation/bls/bin/.emptydir b/vendor/github.com/dexon-foundation/bls/bin/.emptydir
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/bin/.emptydir
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/App.config b/vendor/github.com/dexon-foundation/bls/ffi/cs/App.config
new file mode 100644
index 000000000..8d234373a
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/App.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <startup>
+ <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
+ </startup>
+</configuration>
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/Properties/AssemblyInfo.cs b/vendor/github.com/dexon-foundation/bls/ffi/cs/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..201222c55
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// アセンブリã«é–¢ã™ã‚‹ä¸€èˆ¬æƒ…å ±ã¯ä»¥ä¸‹ã®å±žæ€§ã‚»ãƒƒãƒˆã‚’ã¨ãŠã—ã¦åˆ¶å¾¡ã•ã‚Œã¾ã™ã€‚
+// アセンブリã«é–¢é€£ä»˜ã‘られã¦ã„る情報を変更ã™ã‚‹ã«ã¯ã€
+// ã“れらã®å±žæ€§å€¤ã‚’変更ã—ã¦ãã ã•ã„。
+[assembly: AssemblyTitle("bls256")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("bls256")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// ComVisible ã‚’ false ã«è¨­å®šã™ã‚‹ã¨ã€ãã®åž‹ã¯ã“ã®ã‚¢ã‚»ãƒ³ãƒ–リ内㧠COM コンãƒãƒ¼ãƒãƒ³ãƒˆã‹ã‚‰
+// å‚ç…§ä¸å¯èƒ½ã«ãªã‚Šã¾ã™ã€‚COM ã‹ã‚‰ã“ã®ã‚¢ã‚»ãƒ³ãƒ–リ内ã®åž‹ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹å ´åˆã¯ã€
+// ãã®åž‹ã® ComVisible 属性を true ã«è¨­å®šã—ã¦ãã ã•ã„。
+[assembly: ComVisible(false)]
+
+// ã“ã®ãƒ—ロジェクト㌠COM ã«å…¬é–‹ã•ã‚Œã‚‹å ´åˆã€æ¬¡ã® GUID ㌠typelib ã® ID ã«ãªã‚Šã¾ã™
+[assembly: Guid("e9d06b1b-ea22-4ef4-ba4b-422f7625966c")]
+
+// アセンブリã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã¯æ¬¡ã® 4 ã¤ã®å€¤ã§æ§‹æˆã•ã‚Œã¦ã„ã¾ã™:
+//
+// メジャー ãƒãƒ¼ã‚¸ãƒ§ãƒ³
+// マイナー ãƒãƒ¼ã‚¸ãƒ§ãƒ³
+// ビルド番å·
+// Revision
+//
+// ã™ã¹ã¦ã®å€¤ã‚’指定ã™ã‚‹ã‹ã€ä¸‹ã®ã‚ˆã†ã« '*' を使ã£ã¦ãƒ“ルドãŠã‚ˆã³ãƒªãƒ“ジョン番å·ã‚’
+// 既定値ã«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.cs b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.cs
new file mode 100644
index 000000000..6bcaf07fb
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.cs
@@ -0,0 +1,351 @@
+þ½Ž¿using System;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace mcl
+{
+ class BLS
+ {
+ public const int BN254 = 0;
+ public const int BLS12_381 = 5;
+
+ const int IoEcComp = 512; // fixed byte representation
+ public const int FR_UNIT_SIZE = 4;
+ public const int FP_UNIT_SIZE = 6; // 4 if bls256.dll is used
+ public const int COMPILED_TIME_VAR = FR_UNIT_SIZE * 10 + FP_UNIT_SIZE;
+
+ public const int ID_UNIT_SIZE = FR_UNIT_SIZE;
+ public const int SECRETKEY_UNIT_SIZE = FR_UNIT_SIZE;
+ public const int PUBLICKEY_UNIT_SIZE = FP_UNIT_SIZE * 3 * 2;
+ public const int SIGNATURE_UNIT_SIZE = FP_UNIT_SIZE * 3;
+
+ public const int ID_SERIALIZE_SIZE = FR_UNIT_SIZE * 8;
+ public const int SECRETKEY_SERIALIZE_SIZE = FR_UNIT_SIZE * 8;
+ public const int PUBLICKEY_SERIALIZE_SIZE = FP_UNIT_SIZE * 8 * 2;
+ public const int SIGNATURE_SERIALIZE_SIZE = FP_UNIT_SIZE * 8;
+
+ public const string dllName = FP_UNIT_SIZE == 4 ? "bls256.dll" : "bls384_256.dll";
+ [DllImport(dllName)]
+ public static extern int blsInit(int curveType, int compiledTimeVar);
+
+ [DllImport(dllName)] public static extern void blsIdSetInt(ref Id id, int x);
+ [DllImport(dllName)] public static extern int blsIdSetDecStr(ref Id id, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ [DllImport(dllName)] public static extern int blsIdSetHexStr(ref Id id, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ [DllImport(dllName)] public static extern ulong blsIdGetDecStr([Out]StringBuilder buf, ulong maxBufSize, in Id id);
+ [DllImport(dllName)] public static extern ulong blsIdGetHexStr([Out]StringBuilder buf, ulong maxBufSize, in Id id);
+
+ [DllImport(dllName)] public static extern ulong blsIdSerialize([Out]byte[] buf, ulong maxBufSize, in Id id);
+ [DllImport(dllName)] public static extern ulong blsSecretKeySerialize([Out]byte[] buf, ulong maxBufSize, in SecretKey sec);
+ [DllImport(dllName)] public static extern ulong blsPublicKeySerialize([Out]byte[] buf, ulong maxBufSize, in PublicKey pub);
+ [DllImport(dllName)] public static extern ulong blsSignatureSerialize([Out]byte[] buf, ulong maxBufSize, in Signature sig);
+ [DllImport(dllName)] public static extern ulong blsIdDeserialize(ref Id id, [In]byte[] buf, ulong bufSize);
+ [DllImport(dllName)] public static extern ulong blsSecretKeyDeserialize(ref SecretKey sec, [In]byte[] buf, ulong bufSize);
+ [DllImport(dllName)] public static extern ulong blsPublicKeyDeserialize(ref PublicKey pub, [In]byte[] buf, ulong bufSize);
+ [DllImport(dllName)] public static extern ulong blsSignatureDeserialize(ref Signature sig, [In]byte[] buf, ulong bufSize);
+
+ [DllImport(dllName)] public static extern int blsIdIsEqual(in Id lhs, in Id rhs);
+ [DllImport(dllName)] public static extern int blsSecretKeyIsEqual(in SecretKey lhs, in SecretKey rhs);
+ [DllImport(dllName)] public static extern int blsPublicKeyIsEqual(in PublicKey lhs, in PublicKey rhs);
+ [DllImport(dllName)] public static extern int blsSignatureIsEqual(in Signature lhs, in Signature rhs);
+ // add
+ [DllImport(dllName)] public static extern void blsSecretKeyAdd(ref SecretKey sec, in SecretKey rhs);
+ [DllImport(dllName)] public static extern void blsPublicKeyAdd(ref PublicKey pub, in PublicKey rhs);
+ [DllImport(dllName)] public static extern void blsSignatureAdd(ref Signature sig, in Signature rhs);
+ // hash buf and set
+ [DllImport(dllName)] public static extern int blsHashToSecretKey(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ /*
+ set secretKey if system has /dev/urandom or CryptGenRandom
+ return 0 if success else -1
+ */
+ [DllImport(dllName)] public static extern int blsSecretKeySetByCSPRNG(ref SecretKey sec);
+
+ [DllImport(dllName)] public static extern void blsGetPublicKey(ref PublicKey pub, in SecretKey sec);
+ [DllImport(dllName)] public static extern void blsGetPop(ref Signature sig, in SecretKey sec);
+
+ // return 0 if success
+ [DllImport(dllName)] public static extern int blsSecretKeyShare(ref SecretKey sec, in SecretKey msk, ulong k, in Id id);
+ [DllImport(dllName)] public static extern int blsPublicKeyShare(ref PublicKey pub, in PublicKey mpk, ulong k, in Id id);
+
+
+ [DllImport(dllName)] public static extern int blsSecretKeyRecover(ref SecretKey sec, in SecretKey secVec, in Id idVec, ulong n);
+ [DllImport(dllName)] public static extern int blsPublicKeyRecover(ref PublicKey pub, in PublicKey pubVec, in Id idVec, ulong n);
+ [DllImport(dllName)] public static extern int blsSignatureRecover(ref Signature sig, in Signature sigVec, in Id idVec, ulong n);
+
+ [DllImport(dllName)] public static extern void blsSign(ref Signature sig, in SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string m, ulong size);
+
+ // return 1 if valid
+ [DllImport(dllName)] public static extern int blsVerify(in Signature sig, in PublicKey pub, [In][MarshalAs(UnmanagedType.LPStr)] string m, ulong size);
+ [DllImport(dllName)] public static extern int blsVerifyPop(in Signature sig, in PublicKey pub);
+
+ //////////////////////////////////////////////////////////////////////////
+ // the following apis will be removed
+
+ // mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r
+ [DllImport(dllName)] public static extern int blsIdSetLittleEndian(ref Id id, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ /*
+ return written byte size if success else 0
+ */
+ [DllImport(dllName)] public static extern ulong blsIdGetLittleEndian([Out]StringBuilder buf, ulong maxBufSize, in Id id);
+
+ // return 0 if success
+ // mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r
+ [DllImport(dllName)] public static extern int blsSecretKeySetLittleEndian(ref SecretKey sec, [In]byte[] buf, ulong bufSize);
+ [DllImport(dllName)] public static extern int blsSecretKeySetDecStr(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ [DllImport(dllName)] public static extern int blsSecretKeySetHexStr(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ /*
+ return written byte size if success else 0
+ */
+ [DllImport(dllName)] public static extern ulong blsSecretKeyGetLittleEndian([Out]byte[] buf, ulong maxBufSize, in SecretKey sec);
+ /*
+ return strlen(buf) if success else 0
+ buf is '\0' terminated
+ */
+ [DllImport(dllName)] public static extern ulong blsSecretKeyGetDecStr([Out]StringBuilder buf, ulong maxBufSize, in SecretKey sec);
+ [DllImport(dllName)] public static extern ulong blsSecretKeyGetHexStr([Out]StringBuilder buf, ulong maxBufSize, in SecretKey sec);
+ [DllImport(dllName)] public static extern int blsPublicKeySetHexStr(ref PublicKey pub, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ [DllImport(dllName)] public static extern ulong blsPublicKeyGetHexStr([Out]StringBuilder buf, ulong maxBufSize, in PublicKey pub);
+ [DllImport(dllName)] public static extern int blsSignatureSetHexStr(ref Signature sig, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ [DllImport(dllName)] public static extern ulong blsSignatureGetHexStr([Out]StringBuilder buf, ulong maxBufSize, in Signature sig);
+
+ public static void Init(int curveType = BN254) {
+ if (!System.Environment.Is64BitProcess) {
+ throw new PlatformNotSupportedException("not 64-bit system");
+ }
+ int err = blsInit(curveType, COMPILED_TIME_VAR);
+ if (err != 0) {
+ throw new ArgumentException("blsInit");
+ }
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ public unsafe struct Id
+ {
+ private fixed ulong v[ID_UNIT_SIZE];
+ public byte[] Serialize() {
+ byte[] buf = new byte[ID_SERIALIZE_SIZE];
+ ulong n = blsIdSerialize(buf, (ulong)buf.Length, this);
+ if (n == 0) {
+ throw new ArithmeticException("blsIdSerialize");
+ }
+ return buf;
+ }
+ public void Deserialize(byte[] buf) {
+ ulong n = blsIdDeserialize(ref this, buf, (ulong)buf.Length);
+ if (n == 0) {
+ throw new ArithmeticException("blsIdDeserialize");
+ }
+ }
+ public bool IsEqual(in Id rhs) {
+ return blsIdIsEqual(this, rhs) != 0;
+ }
+ public void SetDecStr(string s) {
+ if (blsIdSetDecStr(ref this, s, (ulong)s.Length) != 0) {
+ throw new ArgumentException("blsIdSetDecSt:" + s);
+ }
+ }
+ public void SetHexStr(string s) {
+ if (blsIdSetHexStr(ref this, s, (ulong)s.Length) != 0) {
+ throw new ArgumentException("blsIdSetHexStr:" + s);
+ }
+ }
+ public void SetInt(int x) {
+ blsIdSetInt(ref this, x);
+ }
+ public string GetDecStr() {
+ StringBuilder sb = new StringBuilder(1024);
+ ulong size = blsIdGetDecStr(sb, (ulong)sb.Capacity, this);
+ if (size == 0) {
+ throw new ArgumentException("blsIdGetDecStr");
+ }
+ return sb.ToString(0, (int)size);
+ }
+ public string GetHexStr() {
+ StringBuilder sb = new StringBuilder(1024);
+ ulong size = blsIdGetHexStr(sb, (ulong)sb.Capacity, this);
+ if (size == 0) {
+ throw new ArgumentException("blsIdGetHexStr");
+ }
+ return sb.ToString(0, (int)size);
+ }
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ public unsafe struct SecretKey
+ {
+ private fixed ulong v[SECRETKEY_UNIT_SIZE];
+ public byte[] Serialize() {
+ byte[] buf = new byte[SECRETKEY_SERIALIZE_SIZE];
+ ulong n = blsSecretKeySerialize(buf, (ulong)buf.Length, this);
+ if (n == 0) {
+ throw new ArithmeticException("blsSecretKeySerialize");
+ }
+ return buf;
+ }
+ public void Deserialize(byte[] buf) {
+ ulong n = blsSecretKeyDeserialize(ref this, buf, (ulong)buf.Length);
+ if (n == 0) {
+ throw new ArithmeticException("blsSecretKeyDeserialize");
+ }
+ }
+ public bool IsEqual(in SecretKey rhs) {
+ return blsSecretKeyIsEqual(this, rhs) != 0;
+ }
+ public void SetHexStr(string s) {
+ if (blsSecretKeySetHexStr(ref this, s, (ulong)s.Length) != 0) {
+ throw new ArgumentException("blsSecretKeySetHexStr:" + s);
+ }
+ }
+ public string GetHexStr() {
+ StringBuilder sb = new StringBuilder(1024);
+ ulong size = blsSecretKeyGetHexStr(sb, (ulong)sb.Capacity, this);
+ if (size == 0) {
+ throw new ArgumentException("mclBnFr_getStr");
+ }
+ return sb.ToString(0, (int)size);
+ }
+ public void Add(in SecretKey rhs) {
+ blsSecretKeyAdd(ref this, rhs);
+ }
+ public void SetByCSPRNG() {
+ blsSecretKeySetByCSPRNG(ref this);
+ }
+ public void SetHashOf(string s) {
+ if (blsHashToSecretKey(ref this, s, (ulong)s.Length) != 0) {
+ throw new ArgumentException("blsHashToSecretKey");
+ }
+ }
+ public PublicKey GetPublicKey() {
+ PublicKey pub;
+ blsGetPublicKey(ref pub, this);
+ return pub;
+ }
+ public Signature Sign(string m) {
+ Signature sig;
+ blsSign(ref sig, this, m, (ulong)m.Length);
+ return sig;
+ }
+ public Signature GetPop() {
+ Signature sig;
+ blsGetPop(ref sig, this);
+ return sig;
+ }
+ }
+ // secretKey = sum_{i=0}^{msk.Length - 1} msk[i] * id^i
+ public static SecretKey ShareSecretKey(in SecretKey[] msk, in Id id) {
+ SecretKey sec;
+ if (blsSecretKeyShare(ref sec, msk[0], (ulong)msk.Length, id) != 0) {
+ throw new ArgumentException("GetSecretKeyForId:" + id.ToString());
+ }
+ return sec;
+ }
+ public static SecretKey RecoverSecretKey(in SecretKey[] secVec, in Id[] idVec) {
+ SecretKey sec;
+ if (blsSecretKeyRecover(ref sec, secVec[0], idVec[0], (ulong)secVec.Length) != 0) {
+ throw new ArgumentException("Recover");
+ }
+ return sec;
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ public unsafe struct PublicKey
+ {
+ private fixed ulong v[PUBLICKEY_UNIT_SIZE];
+ public byte[] Serialize() {
+ byte[] buf = new byte[PUBLICKEY_SERIALIZE_SIZE];
+ ulong n = blsPublicKeySerialize(buf, (ulong)buf.Length, this);
+ if (n == 0) {
+ throw new ArithmeticException("blsPublicKeySerialize");
+ }
+ return buf;
+ }
+ public void Deserialize(byte[] buf) {
+ ulong n = blsPublicKeyDeserialize(ref this, buf, (ulong)buf.Length);
+ if (n == 0) {
+ throw new ArithmeticException("blsPublicKeyDeserialize");
+ }
+ }
+ public bool IsEqual(in PublicKey rhs) {
+ return blsPublicKeyIsEqual(this, rhs) != 0;
+ }
+ public void SetStr(string s) {
+ if (blsPublicKeySetHexStr(ref this, s, (ulong)s.Length) != 0) {
+ throw new ArgumentException("blsPublicKeySetStr:" + s);
+ }
+ }
+ public string GetHexStr() {
+ StringBuilder sb = new StringBuilder(1024);
+ ulong size = blsPublicKeyGetHexStr(sb, (ulong)sb.Capacity, this);
+ if (size == 0) {
+ throw new ArgumentException("blsPublicKeyGetStr");
+ }
+ return sb.ToString(0, (int)size);
+ }
+ public void Add(in PublicKey rhs) {
+ blsPublicKeyAdd(ref this, rhs);
+ }
+ public bool Verify(in Signature sig, string m) {
+ return blsVerify(sig, this, m, (ulong)m.Length) == 1;
+ }
+ public bool VerifyPop(in Signature pop) {
+ return blsVerifyPop(pop, this) == 1;
+ }
+ }
+ // publicKey = sum_{i=0}^{mpk.Length - 1} mpk[i] * id^i
+ public static PublicKey SharePublicKey(in PublicKey[] mpk, in Id id) {
+ PublicKey pub;
+ if (blsPublicKeyShare(ref pub, mpk[0], (ulong)mpk.Length, id) != 0) {
+ throw new ArgumentException("GetPublicKeyForId:" + id.ToString());
+ }
+ return pub;
+ }
+ public static PublicKey RecoverPublicKey(in PublicKey[] pubVec, in Id[] idVec) {
+ PublicKey pub;
+ if (blsPublicKeyRecover(ref pub, pubVec[0], idVec[0], (ulong)pubVec.Length) != 0) {
+ throw new ArgumentException("Recover");
+ }
+ return pub;
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ public unsafe struct Signature
+ {
+ private fixed ulong v[SIGNATURE_UNIT_SIZE];
+ public byte[] Serialize() {
+ byte[] buf = new byte[SIGNATURE_SERIALIZE_SIZE];
+ ulong n = blsSignatureSerialize(buf, (ulong)buf.Length, this);
+ if (n == 0) {
+ throw new ArithmeticException("blsSignatureSerialize");
+ }
+ return buf;
+ }
+ public void Deserialize(byte[] buf) {
+ ulong n = blsSignatureDeserialize(ref this, buf, (ulong)buf.Length);
+ if (n == 0) {
+ throw new ArithmeticException("blsSignatureDeserialize");
+ }
+ }
+ public bool IsEqual(in Signature rhs) {
+ return blsSignatureIsEqual(this, rhs) != 0;
+ }
+ public void SetStr(string s) {
+ if (blsSignatureSetHexStr(ref this, s, (ulong)s.Length) != 0) {
+ throw new ArgumentException("blsSignatureSetStr:" + s);
+ }
+ }
+ public string GetHexStr() {
+ StringBuilder sb = new StringBuilder(1024);
+ ulong size = blsSignatureGetHexStr(sb, (ulong)sb.Capacity, this);
+ if (size == 0) {
+ throw new ArgumentException("blsSignatureGetStr");
+ }
+ return sb.ToString(0, (int)size);
+ }
+ public void Add(in Signature rhs) {
+ blsSignatureAdd(ref this, rhs);
+ }
+ }
+ public static Signature RecoverSign(in Signature[] sigVec, in Id[] idVec) {
+ Signature sig;
+ if (blsSignatureRecover(ref sig, sigVec[0], idVec[0], (ulong)sigVec.Length) != 0) {
+ throw new ArgumentException("Recover");
+ }
+ return sig;
+ }
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.csproj b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.csproj
new file mode 100644
index 000000000..c03afa436
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.csproj
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{E9D06B1B-EA22-4EF4-BA4B-422F7625966D}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>bls</RootNamespace>
+ <AssemblyName>bls</AssemblyName>
+ <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ <TargetFrameworkProfile />
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>..\..\bin\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <LangVersion>7.2</LangVersion>
+ <Prefer32Bit>false</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ <OutputPath>..\..\bin\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>false</Prefer32Bit>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <LangVersion>7.2</LangVersion>
+ </PropertyGroup>
+ <PropertyGroup>
+ <NoWin32Manifest>true</NoWin32Manifest>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="bls.cs" />
+ <Compile Include="bls_test.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include=".NETFramework,Version=v4.5.2">
+ <Visible>False</Visible>
+ <ProductName>Microsoft .NET Framework 4.5.2 %28x86 ãŠã‚ˆã³ x64%29</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.sln b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.sln
new file mode 100644
index 000000000..7c3dfba7b
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.28307.539
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bls", "bls.csproj", "{E9D06B1B-EA22-4EF4-BA4B-422F7625966D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E9D06B1B-EA22-4EF4-BA4B-422F7625966D}.Debug|x64.ActiveCfg = Debug|x64
+ {E9D06B1B-EA22-4EF4-BA4B-422F7625966D}.Debug|x64.Build.0 = Debug|x64
+ {E9D06B1B-EA22-4EF4-BA4B-422F7625966D}.Release|x64.ActiveCfg = Release|x64
+ {E9D06B1B-EA22-4EF4-BA4B-422F7625966D}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {1935C301-6478-4F82-9587-6A66B531E327}
+ EndGlobalSection
+EndGlobal
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.cs b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.cs
new file mode 100644
index 000000000..3ef5fab9a
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.cs
@@ -0,0 +1,298 @@
+þ½Ž¿using System;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace mcl {
+ class BLS256 {
+ const int IoEcComp = 512; // fixed byte representation
+ public const int MCLBN_FR_UNIT_SIZE = 4;
+ public const int MCLBN_FP_UNIT_SIZE = 4;
+ public const int MCLBN_COMPILED_TIME_VAR = MCLBN_FR_UNIT_SIZE * 10 + MCLBN_FP_UNIT_SIZE;
+ [DllImport("bls256.dll")]
+ public static extern int blsInit(int curve, int compiledTimeVar);
+
+ [DllImport("bls256.dll")] public static extern void blsIdSetInt(ref Id id, int x);
+ [DllImport("bls256.dll")] public static extern int blsIdSetDecStr(ref Id id, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ [DllImport("bls256.dll")] public static extern int blsIdSetHexStr(ref Id id, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ [DllImport("bls256.dll")] public static extern ulong blsIdGetDecStr([Out]StringBuilder buf, ulong maxBufSize, ref Id id);
+ [DllImport("bls256.dll")] public static extern ulong blsIdGetHexStr([Out]StringBuilder buf, ulong maxBufSize, ref Id id);
+
+
+ [DllImport("bls256.dll")] public static extern ulong blsIdSerialize([Out]StringBuilder buf, ulong maxBufSize, ref Id id);
+ [DllImport("bls256.dll")] public static extern ulong blsSecretKeySerialize([Out]StringBuilder buf, ulong maxBufSize, ref SecretKey sec);
+ [DllImport("bls256.dll")] public static extern ulong blsPublicKeySerialize([Out]StringBuilder buf, ulong maxBufSize, ref PublicKey pub);
+ [DllImport("bls256.dll")] public static extern ulong blsSignatureSerialize([Out]StringBuilder buf, ulong maxBufSize, ref Signature sig);
+
+ [DllImport("bls256.dll")] public static extern int blsIdDeserialize(ref Id id, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ [DllImport("bls256.dll")] public static extern int blsSecretKeyDeserialize(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ [DllImport("bls256.dll")] public static extern int blsPublicKeyDeserialize(ref PublicKey pub, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ [DllImport("bls256.dll")] public static extern int blsSignatureDeserialize(ref Signature sig, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+
+ [DllImport("bls256.dll")] public static extern int blsIdIsEqual(ref Id lhs, ref Id rhs);
+ [DllImport("bls256.dll")] public static extern int blsSecretKeyIsEqual(ref SecretKey lhs, ref SecretKey rhs);
+ [DllImport("bls256.dll")] public static extern int blsPublicKeyIsEqual(ref PublicKey lhs, ref PublicKey rhs);
+ [DllImport("bls256.dll")] public static extern int blsSignatureIsEqual(ref Signature lhs, ref Signature rhs);
+
+ // add
+ [DllImport("bls256.dll")] public static extern void blsSecretKeyAdd(ref SecretKey sec, ref SecretKey rhs);
+ [DllImport("bls256.dll")] public static extern void blsPublicKeyAdd(ref PublicKey pub, ref PublicKey rhs);
+ [DllImport("bls256.dll")] public static extern void blsSignatureAdd(ref Signature sig, ref Signature rhs);
+
+ // hash buf and set
+ [DllImport("bls256.dll")] public static extern int blsHashToSecretKey(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ /*
+ set secretKey if system has /dev/urandom or CryptGenRandom
+ return 0 if success else -1
+ */
+ [DllImport("bls256.dll")] public static extern int blsSecretKeySetByCSPRNG(ref SecretKey sec);
+
+ [DllImport("bls256.dll")] public static extern void blsGetPublicKey(ref PublicKey pub, ref SecretKey sec);
+ [DllImport("bls256.dll")] public static extern void blsGetPop(ref Signature sig, ref SecretKey sec);
+
+ // return 0 if success
+ [DllImport("bls256.dll")] public static extern int blsSecretKeyShare(ref SecretKey sec, ref SecretKey msk, ulong k, ref Id id);
+ [DllImport("bls256.dll")] public static extern int blsPublicKeyShare(ref PublicKey pub, ref PublicKey mpk, ulong k, ref Id id);
+
+
+ [DllImport("bls256.dll")] public static extern int blsSecretKeyRecover(ref SecretKey sec, ref SecretKey secVec, ref Id idVec, ulong n);
+ [DllImport("bls256.dll")] public static extern int blsPublicKeyRecover(ref PublicKey pub, ref PublicKey pubVec, ref Id idVec, ulong n);
+ [DllImport("bls256.dll")] public static extern int blsSignatureRecover(ref Signature sig, ref Signature sigVec, ref Id idVec, ulong n);
+
+ [DllImport("bls256.dll")] public static extern void blsSign(ref Signature sig, ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string m, ulong size);
+
+ // return 1 if valid
+ [DllImport("bls256.dll")] public static extern int blsVerify(ref Signature sig, ref PublicKey pub, [In][MarshalAs(UnmanagedType.LPStr)] string m, ulong size);
+ [DllImport("bls256.dll")] public static extern int blsVerifyPop(ref Signature sig, ref PublicKey pub);
+
+ //////////////////////////////////////////////////////////////////////////
+ // the following apis will be removed
+
+ // mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r
+ [DllImport("bls256.dll")] public static extern int blsIdSetLittleEndian(ref Id id, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ /*
+ return written byte size if success else 0
+ */
+ [DllImport("bls256.dll")] public static extern ulong blsIdGetLittleEndian([Out]StringBuilder buf, ulong maxBufSize, ref Id id);
+
+ // return 0 if success
+ // mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r
+ [DllImport("bls256.dll")] public static extern int blsSecretKeySetLittleEndian(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ [DllImport("bls256.dll")] public static extern int blsSecretKeySetDecStr(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ [DllImport("bls256.dll")] public static extern int blsSecretKeySetHexStr(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ /*
+ return written byte size if success else 0
+ */
+ [DllImport("bls256.dll")] public static extern ulong blsSecretKeyGetLittleEndian([Out]StringBuilder buf, ulong maxBufSize, ref SecretKey sec);
+ /*
+ return strlen(buf) if success else 0
+ buf is '\0' terminated
+ */
+ [DllImport("bls256.dll")] public static extern ulong blsSecretKeyGetDecStr([Out]StringBuilder buf, ulong maxBufSize, ref SecretKey sec);
+ [DllImport("bls256.dll")] public static extern ulong blsSecretKeyGetHexStr([Out]StringBuilder buf, ulong maxBufSize, ref SecretKey sec);
+ [DllImport("bls256.dll")] public static extern int blsPublicKeySetHexStr(ref PublicKey pub, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ [DllImport("bls256.dll")] public static extern ulong blsPublicKeyGetHexStr([Out]StringBuilder buf, ulong maxBufSize, ref PublicKey pub);
+ [DllImport("bls256.dll")] public static extern int blsSignatureSetHexStr(ref Signature sig, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
+ [DllImport("bls256.dll")] public static extern ulong blsSignatureGetHexStr([Out]StringBuilder buf, ulong maxBufSize, ref Signature sig);
+
+ public static void Init()
+ {
+ const int CurveFp254BNb = 0;
+ if (!System.Environment.Is64BitProcess) {
+ throw new PlatformNotSupportedException("not 64-bit system");
+ }
+ int err = blsInit(CurveFp254BNb, MCLBN_COMPILED_TIME_VAR);
+ if (err != 0) {
+ throw new ArgumentException("blsInit");
+ }
+ }
+
+ public struct Id {
+ private ulong v0, v1, v2, v3;
+ public bool IsEqual(Id rhs)
+ {
+ return blsIdIsEqual(ref this, ref rhs) != 0;
+ }
+ public void SetDecStr(String s)
+ {
+ if (blsIdSetDecStr(ref this, s, (ulong)s.Length) != 0) {
+ throw new ArgumentException("blsIdSetDecSt:" + s);
+ }
+ }
+ public void SetHexStr(String s)
+ {
+ if (blsIdSetHexStr(ref this, s, (ulong)s.Length) != 0) {
+ throw new ArgumentException("blsIdSetHexStr:" + s);
+ }
+ }
+ public void SetInt(int x)
+ {
+ blsIdSetInt(ref this, x);
+ }
+ public string GetDecStr()
+ {
+ StringBuilder sb = new StringBuilder(1024);
+ ulong size = blsIdGetDecStr(sb, (ulong)sb.Capacity, ref this);
+ if (size == 0) {
+ throw new ArgumentException("blsIdGetDecStr");
+ }
+ return sb.ToString(0, (int)size);
+ }
+ public string GetHexStr()
+ {
+ StringBuilder sb = new StringBuilder(1024);
+ ulong size = blsIdGetHexStr(sb, (ulong)sb.Capacity, ref this);
+ if (size == 0) {
+ throw new ArgumentException("blsIdGetHexStr");
+ }
+ return sb.ToString(0, (int)size);
+ }
+ }
+ public struct SecretKey {
+ private ulong v0, v1, v2, v3;
+ public bool IsEqual(SecretKey rhs)
+ {
+ return blsSecretKeyIsEqual(ref this, ref rhs) != 0;
+ }
+ public void SetHexStr(String s)
+ {
+ if (blsSecretKeySetHexStr(ref this, s, (ulong)s.Length) != 0) {
+ throw new ArgumentException("blsSecretKeySetHexStr:" + s);
+ }
+ }
+ public string GetHexStr()
+ {
+ StringBuilder sb = new StringBuilder(1024);
+ ulong size = blsSecretKeyGetHexStr(sb, (ulong)sb.Capacity, ref this);
+ if (size == 0) {
+ throw new ArgumentException("mclBnFr_getStr");
+ }
+ return sb.ToString(0, (int)size);
+ }
+ public void Add(SecretKey rhs)
+ {
+ blsSecretKeyAdd(ref this, ref rhs);
+ }
+ public void SetByCSPRNG()
+ {
+ blsSecretKeySetByCSPRNG(ref this);
+ }
+ public void SetHashOf(string s)
+ {
+ if (blsHashToSecretKey(ref this, s, (ulong)s.Length) != 0) {
+ throw new ArgumentException("blsHashToSecretKey");
+ }
+ }
+ public PublicKey GetPublicKey()
+ {
+ PublicKey pub = new PublicKey();
+ blsGetPublicKey(ref pub, ref this);
+ return pub;
+ }
+ public Signature Signature(String m)
+ {
+ Signature Signature = new Signature();
+ blsSign(ref Signature, ref this, m, (ulong)m.Length);
+ return Signature;
+ }
+ }
+ // secretKey = sum_{i=0}^{msk.Length - 1} msk[i] * id^i
+ public static SecretKey ShareSecretKey(SecretKey[] msk, Id id)
+ {
+ SecretKey sec = new SecretKey();
+ if (blsSecretKeyShare(ref sec, ref msk[0], (ulong)msk.Length, ref id) != 0) {
+ throw new ArgumentException("GetSecretKeyForId:" + id.ToString());
+ }
+ return sec;
+ }
+ public static SecretKey RecoverSecretKey(SecretKey[] secs, Id[] ids)
+ {
+ SecretKey sec = new SecretKey();
+ if (blsSecretKeyRecover(ref sec, ref secs[0], ref ids[0], (ulong)secs.Length) != 0) {
+ throw new ArgumentException("Recover");
+ }
+ return sec;
+ }
+ public struct PublicKey {
+ private ulong v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11;
+ private ulong v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23;
+ public bool IsEqual(PublicKey rhs)
+ {
+ return blsPublicKeyIsEqual(ref this, ref rhs) != 0;
+ }
+ public void SetStr(String s)
+ {
+ if (blsPublicKeySetHexStr(ref this, s, (ulong)s.Length) != 0) {
+ throw new ArgumentException("blsPublicKeySetStr:" + s);
+ }
+ }
+ public string GetHexStr()
+ {
+ StringBuilder sb = new StringBuilder(1024);
+ ulong size = blsPublicKeyGetHexStr(sb, (ulong)sb.Capacity, ref this);
+ if (size == 0) {
+ throw new ArgumentException("blsPublicKeyGetStr");
+ }
+ return sb.ToString(0, (int)size);
+ }
+ public void Add(PublicKey rhs)
+ {
+ blsPublicKeyAdd(ref this, ref rhs);
+ }
+ public bool Verify(Signature Signature, string m)
+ {
+ return blsVerify(ref Signature, ref this, m, (ulong)m.Length) == 1;
+ }
+ }
+ // publicKey = sum_{i=0}^{mpk.Length - 1} mpk[i] * id^i
+ public static PublicKey SharePublicKey(PublicKey[] mpk, Id id)
+ {
+ PublicKey pub = new PublicKey();
+ if (blsPublicKeyShare(ref pub, ref mpk[0], (ulong)mpk.Length, ref id) != 0) {
+ throw new ArgumentException("GetPublicKeyForId:" + id.ToString());
+ }
+ return pub;
+ }
+ public static PublicKey RecoverPublicKey(PublicKey[] pubs, Id[] ids)
+ {
+ PublicKey pub = new PublicKey();
+ if (blsPublicKeyRecover(ref pub, ref pubs[0], ref ids[0], (ulong)pubs.Length) != 0) {
+ throw new ArgumentException("Recover");
+ }
+ return pub;
+ }
+ public struct Signature {
+ private ulong v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11;
+ public bool IsEqual(Signature rhs)
+ {
+ return blsSignatureIsEqual(ref this, ref rhs) != 0;
+ }
+ public void SetStr(String s)
+ {
+ if (blsSignatureSetHexStr(ref this, s, (ulong)s.Length) != 0) {
+ throw new ArgumentException("blsSignatureSetStr:" + s);
+ }
+ }
+ public string GetHexStr()
+ {
+ StringBuilder sb = new StringBuilder(1024);
+ ulong size = blsSignatureGetHexStr(sb, (ulong)sb.Capacity, ref this);
+ if (size == 0) {
+ throw new ArgumentException("blsSignatureGetStr");
+ }
+ return sb.ToString(0, (int)size);
+ }
+ public void Add(Signature rhs)
+ {
+ blsSignatureAdd(ref this, ref rhs);
+ }
+ }
+ public static Signature RecoverSign(Signature[] signs, Id[] ids)
+ {
+ Signature Signature = new Signature();
+ if (blsSignatureRecover(ref Signature, ref signs[0], ref ids[0], (ulong)signs.Length) != 0) {
+ throw new ArgumentException("Recover");
+ }
+ return Signature;
+ }
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.csproj b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.csproj
new file mode 100644
index 000000000..032a1d347
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.csproj
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{E9D06B1B-EA22-4EF4-BA4B-422F7625966C}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>bls256</RootNamespace>
+ <AssemblyName>bls256</AssemblyName>
+ <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>..\..\bin\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ <OutputPath>..\..\bin\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="bls256.cs" />
+ <Compile Include="bls256_test.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.sln b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.sln
new file mode 100644
index 000000000..eb29af97b
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBD}") = "bls256", "bls256.csproj", "{E9D06B1B-EA22-4EF4-BA4B-422F7625966C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E9D06B1B-EA22-4EF4-BA4B-422F7625966C}.Debug|x64.ActiveCfg = Debug|x64
+ {E9D06B1B-EA22-4EF4-BA4B-422F7625966C}.Debug|x64.Build.0 = Debug|x64
+ {E9D06B1B-EA22-4EF4-BA4B-422F7625966C}.Release|x64.ActiveCfg = Release|x64
+ {E9D06B1B-EA22-4EF4-BA4B-422F7625966C}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256_test.cs b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256_test.cs
new file mode 100644
index 000000000..989993e0f
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256_test.cs
@@ -0,0 +1,126 @@
+using System;
+
+namespace mcl {
+ using static BLS256;
+ class BLS256Test {
+ static int err = 0;
+ static void assert(string msg, bool b)
+ {
+ if (b) return;
+ Console.WriteLine("ERR {0}", msg);
+ err++;
+ }
+ static void TestId()
+ {
+ Console.WriteLine("TestId");
+ Id id = new Id();
+ id.SetDecStr("255");
+ assert("GetStr(10)", id.GetDecStr() == "255");
+ assert("GetStr(16)", id.GetHexStr() == "ff");
+ }
+ static void TestSecretKey()
+ {
+ Console.WriteLine("TestSecretKey");
+ SecretKey sec = new SecretKey();
+ sec.SetHexStr("ff");
+ assert("GetHexStr()", sec.GetHexStr() == "ff");
+ {
+ SecretKey sec2 = new SecretKey();
+ sec.SetHexStr("321");
+ sec2.SetHexStr("4000");
+ sec.Add(sec2);
+ assert("sec.Add", sec.GetHexStr() == "4321");
+ sec.SetByCSPRNG();
+ Console.WriteLine("sec.Init={0}", sec.GetHexStr());
+ }
+ }
+ static void TestPublicKey()
+ {
+ Console.WriteLine("TestPublicKey");
+ SecretKey sec = new SecretKey();
+ sec.SetByCSPRNG();
+ PublicKey pub = sec.GetPublicKey();
+ String s = pub.GetHexStr();
+ Console.WriteLine("pub={0}", s);
+ PublicKey pub2 = new PublicKey();
+ pub2.SetStr(s);
+ assert("pub.SetStr", pub.IsEqual(pub2));
+ }
+ static void TestSign()
+ {
+ Console.WriteLine("TestSign");
+ SecretKey sec = new SecretKey();
+ sec.SetByCSPRNG();
+ PublicKey pub = sec.GetPublicKey();
+ String m = "abc";
+ Signature sig = sec.Signature(m);
+ assert("verify", pub.Verify(sig, m));
+ assert("not verify", !pub.Verify(sig, m + "a"));
+ }
+ static void TestSharing()
+ {
+ Console.WriteLine("TestSharing");
+ int k = 5;
+ SecretKey[] msk = new SecretKey[k];
+ PublicKey[] mpk = new PublicKey[k];
+ // make master secretkey
+ for (int i = 0; i < k; i++) {
+ msk[i].SetByCSPRNG();
+ mpk[i] = msk[i].GetPublicKey();
+ }
+ int n = 30;
+ Id[] ids = new Id[n];
+ SecretKey[] secs = new SecretKey[n];
+ PublicKey[] pubs = new PublicKey[n];
+ for (int i = 0; i < n; i++) {
+ ids[i].SetInt(i * i + 123);
+ secs[i] = ShareSecretKey(msk, ids[i]);
+ pubs[i] = SharePublicKey(mpk, ids[i]);
+ assert("share publicKey", secs[i].GetPublicKey().IsEqual(pubs[i]));
+ }
+ string m = "doremi";
+ for (int i = 0; i < n; i++) {
+ Signature Signature = secs[i].Signature(m);
+ assert("Signature.Verify", pubs[i].Verify(Signature, m));
+ }
+ {
+ int[] idxTbl = { 0, 2, 5, 8, 10 };
+ assert("idxTbl.Length=k", idxTbl.Length == k);
+ Id[] subIds = new Id[k];
+ SecretKey[] subSecs = new SecretKey[k];
+ PublicKey[] subPubs = new PublicKey[k];
+ Signature[] subSigns = new Signature[k];
+ for (int i = 0; i < k; i++) {
+ int idx = idxTbl[i];
+ subIds[i] = ids[idx];
+ subSecs[i] = secs[idx];
+ subPubs[i] = pubs[idx];
+ subSigns[i] = secs[idx].Signature(m);
+ }
+ SecretKey sec = RecoverSecretKey(subSecs, subIds);
+ PublicKey pub = RecoverPublicKey(subPubs, subIds);
+ assert("check pub", pub.IsEqual(sec.GetPublicKey()));
+ Signature Signature = RecoverSign(subSigns, subIds);
+ assert("Signature.verify", pub.Verify(Signature, m));
+ }
+ }
+ static void Main(string[] args)
+ {
+ try {
+ Init();
+ TestId();
+ TestSecretKey();
+ TestPublicKey();
+ TestSign();
+ TestSharing();
+ if (err == 0) {
+ Console.WriteLine("all tests succeed");
+ } else {
+ Console.WriteLine("err={0}", err);
+ }
+ } catch (Exception e) {
+ Console.WriteLine("ERR={0}", e);
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/bls_test.cs b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls_test.cs
new file mode 100644
index 000000000..2eb451ba9
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls_test.cs
@@ -0,0 +1,176 @@
+using System;
+
+namespace mcl
+{
+ using static BLS;
+ class BLSTest
+ {
+ static int err = 0;
+ static void assert(string msg, bool b) {
+ if (b) return;
+ Console.WriteLine("ERR {0}", msg);
+ err++;
+ }
+ static void TestId() {
+ Console.WriteLine("TestId");
+ Id id1;
+ id1.SetDecStr("255");
+ assert("GetStr(10)", id1.GetDecStr() == "255");
+ assert("GetStr(16)", id1.GetHexStr() == "ff");
+ Id id2;
+ id2.SetInt(255);
+ assert("IsEqual", id1.IsEqual(id2));
+ }
+ static void TestSecretKey() {
+ Console.WriteLine("TestSecretKey");
+ SecretKey sec;
+ sec.SetHexStr("ff");
+ assert("GetHexStr()", sec.GetHexStr() == "ff");
+ {
+ SecretKey sec2;
+ sec.SetHexStr("321");
+ sec2.SetHexStr("4000");
+ sec.Add(sec2);
+ assert("sec.Add", sec.GetHexStr() == "4321");
+ sec.SetByCSPRNG();
+ Console.WriteLine("sec.Init={0}", sec.GetHexStr());
+ }
+ {
+ SecretKey sec2;
+ byte[] buf = sec.Serialize();
+ sec2.Deserialize(buf);
+ assert("serialize", sec2.IsEqual(sec));
+ }
+ }
+ static void TestPublicKey() {
+ Console.WriteLine("TestPublicKey");
+ SecretKey sec;
+ sec.SetByCSPRNG();
+ PublicKey pub = sec.GetPublicKey();
+ string s = pub.GetHexStr();
+ Console.WriteLine("pub={0}", s);
+ {
+ PublicKey pub2;
+ pub2.SetStr(s);
+ assert("pub.SetStr", pub.IsEqual(pub2));
+ }
+ {
+ PublicKey pub2;
+ byte[] buf = pub.Serialize();
+ pub2.Deserialize(buf);
+ assert("serialize", pub2.IsEqual(pub));
+ }
+ }
+ static void TestSign() {
+ Console.WriteLine("TestSign");
+ SecretKey sec;
+ sec.SetByCSPRNG();
+ PublicKey pub = sec.GetPublicKey();
+ string m = "abc";
+ Signature sig = sec.Sign(m);
+ Console.WriteLine("sig={0}", sig.GetHexStr());
+ assert("verify", pub.Verify(sig, m));
+ assert("not verify", !pub.Verify(sig, m + "a"));
+ {
+ Signature sig2;
+ byte[] buf = sig.Serialize();
+ sig2.Deserialize(buf);
+ assert("serialize", sig2.IsEqual(sig));
+ }
+ }
+ static void TestSharing() {
+ Console.WriteLine("TestSharing");
+ int k = 5;
+ SecretKey[] msk = new SecretKey[k];
+ PublicKey[] mpk = new PublicKey[k];
+ // make master secretkey
+ for (int i = 0; i < k; i++) {
+ msk[i].SetByCSPRNG();
+ mpk[i] = msk[i].GetPublicKey();
+ }
+ int n = 30;
+ Id[] ids = new Id[n];
+ SecretKey[] secs = new SecretKey[n];
+ PublicKey[] pubs = new PublicKey[n];
+ for (int i = 0; i < n; i++) {
+ ids[i].SetInt(i * i + 123);
+ secs[i] = ShareSecretKey(msk, ids[i]);
+ pubs[i] = SharePublicKey(mpk, ids[i]);
+ assert("share publicKey", secs[i].GetPublicKey().IsEqual(pubs[i]));
+ }
+ string m = "doremi";
+ for (int i = 0; i < n; i++) {
+ Signature Signature = secs[i].Sign(m);
+ assert("Signature.Verify", pubs[i].Verify(Signature, m));
+ }
+ {
+ int[] idxTbl = { 0, 2, 5, 8, 10 };
+ assert("idxTbl.Length=k", idxTbl.Length == k);
+ Id[] subIds = new Id[k];
+ SecretKey[] subSecs = new SecretKey[k];
+ PublicKey[] subPubs = new PublicKey[k];
+ Signature[] subSigns = new Signature[k];
+ for (int i = 0; i < k; i++) {
+ int idx = idxTbl[i];
+ subIds[i] = ids[idx];
+ subSecs[i] = secs[idx];
+ subPubs[i] = pubs[idx];
+ subSigns[i] = secs[idx].Sign(m);
+ }
+ SecretKey sec = RecoverSecretKey(subSecs, subIds);
+ PublicKey pub = RecoverPublicKey(subPubs, subIds);
+ assert("check pub", pub.IsEqual(sec.GetPublicKey()));
+ Signature Signature = RecoverSign(subSigns, subIds);
+ assert("Signature.verify", pub.Verify(Signature, m));
+ }
+ }
+ static void TestAggregate() {
+ Console.WriteLine("TestAggregate");
+ const int n = 10;
+ const string m = "abc";
+ SecretKey[] secVec = new SecretKey[n];
+ PublicKey[] pubVec = new PublicKey[n];
+ Signature[] popVec = new Signature[n];
+ Signature[] sigVec = new Signature[n];
+ for (int i = 0; i < n; i++) {
+ secVec[i].SetByCSPRNG();
+ pubVec[i] = secVec[i].GetPublicKey();
+ popVec[i] = secVec[i].GetPop();
+ sigVec[i] = secVec[i].Sign(m);
+ }
+ SecretKey secAgg;
+ PublicKey pubAgg;
+ Signature sigAgg;
+ for (int i = 0; i < n; i++) {
+ secAgg.Add(secVec[i]);
+ assert("verify pop", pubVec[i].VerifyPop(popVec[i]));
+ pubAgg.Add(pubVec[i]);
+ sigAgg.Add(sigVec[i]);
+ }
+ assert("aggregate sec", secAgg.Sign(m).IsEqual(sigAgg));
+ assert("aggregate", pubAgg.Verify(sigAgg, m));
+ }
+ static void Main(string[] args) {
+ try {
+ int[] curveTypeTbl = { BN254, BLS12_381 };
+ foreach (int curveType in curveTypeTbl) {
+ Console.WriteLine("curveType={0}", curveType);
+ Init(curveType);
+ TestId();
+ TestSecretKey();
+ TestPublicKey();
+ TestSign();
+ TestSharing();
+ TestAggregate();
+ if (err == 0) {
+ Console.WriteLine("all tests succeed");
+ } else {
+ Console.WriteLine("err={0}", err);
+ }
+ }
+ } catch (Exception e) {
+ Console.WriteLine("ERR={0}", e);
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/readme-ja.md b/vendor/github.com/dexon-foundation/bls/ffi/cs/readme-ja.md
new file mode 100644
index 000000000..199135725
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/readme-ja.md
@@ -0,0 +1,188 @@
+# BLSç½²åã®C#ãƒã‚¤ãƒ³ãƒ‡ã‚£ãƒ³ã‚°
+
+# å¿…è¦ç’°å¢ƒ
+
+* Visual Studio 2017(x64) or later
+* C# 7.2 or later
+* .NET Framework 4.5.2 or later
+
+# DLLã®ãƒ“ルド方法
+
+Visual Studio 2017ã®64bit用コマンドプロンプトを開ã„ã¦
+```
+md work
+cd work
+git clone https://github.com/herumi/cybozulib_ext
+git clone https://github.com/herumi/mcl
+git clone https://github.com/herumi/bls
+cd bls
+mklib dll
+```
+`bls/bin/*.dll`ãŒä½œæˆã•ã‚Œã‚‹ã€‚
+
+# サンプルã®ãƒ“ルド方法
+
+bls/ffi/cs/bls.slnã‚’é–‹ã„ã¦å®Ÿè¡Œã™ã‚‹ã€‚
+
+* æ³¨æ„ bls256.slnã¯å¤ã„ãŸã‚使ã‚ãªã„ã§ãã ã•ã„。
+
+# クラスã¨API
+
+## API
+
+* `Init(int curveType = BN254);`
+ * ライブラリを曲線curveTypeã§åˆæœŸåŒ–ã™ã‚‹ã€‚
+ * curveType = BN254 or BLS12_381
+* `SecretKey ShareSecretKey(in SecretKey[] msk, in Id id);`
+ * マスター秘密éµã®åˆ—mskã«å¯¾ã™ã‚‹idã®ç§˜å¯†éµã‚’生æˆ(共有)ã™ã‚‹ã€‚
+* `SecretKey RecoverSecretKey(in SecretKey[] secVec, in Id[] idVec);`
+ * 秘密éµsecVecã¨ID idVecã®ãƒšã‚¢ã‹ã‚‰ç§˜å¯†éµã‚’復元ã™ã‚‹ã€‚
+* `PublicKey SharePublicKey(in PublicKey[] mpk, in Id id);`
+ * マスター公開éµã®åˆ—mpkã«å¯¾ã™ã‚‹idã®å…¬é–‹éµã‚’生æˆ(共有)ã™ã‚‹ã€‚
+* `PublicKey RecoverPublicKey(in PublicKey[] pubVec, in Id[] idVec);`
+ * 公開éµpubVecã¨ID idVecã®ãƒšã‚¢ã‹ã‚‰å…¬é–‹éµã‚’復元ã™ã‚‹ã€‚
+* `Signature RecoverSign(in Signature[] sigVec, in Id[] idVec);`
+ * ç½²åsigVecã¨ID idVecã®ãƒšã‚¢ã‹ã‚‰ç½²åを復元ã™ã‚‹ã€‚
+
+## Id
+
+識別å­ã‚¯ãƒ©ã‚¹
+
+* `byte[] Serialize();`
+ * Idをシリアライズã™ã‚‹ã€‚
+* `void Deserialize(byte[] buf);`
+ * ãƒã‚¤ãƒˆåˆ—bufã‹ã‚‰Idをデシリアライズã™ã‚‹ã€‚
+* `bool IsEqual(in Id rhs);`
+ * åŒå€¤åˆ¤å®šã€‚
+* `void SetDecStr(string s);`
+ * 10進数文字列を設定ã™ã‚‹ã€‚
+* `void SetHexStr(string s);`
+ * 16進数文字列を設定ã™ã‚‹ã€‚
+* `void SetInt(int x);`
+ * æ•´æ•°xを設定ã™ã‚‹ã€‚
+* `string GetDecStr();`
+ * 10進数表記をå–å¾—ã™ã‚‹ã€‚
+* `string GetHexStr();`
+ * 16進数表記をå–å¾—ã™ã‚‹ã€‚
+
+## SecretKey
+
+* `byte[] Serialize();`
+ * Idをシリアライズã™ã‚‹ã€‚
+* `void Deserialize(byte[] buf);`
+ * ãƒã‚¤ãƒˆåˆ—bufã‹ã‚‰SecretKeyをデシリアライズã™ã‚‹ã€‚
+* `bool IsEqual(in SecretKey rhs);`
+ * åŒå€¤åˆ¤å®šã€‚
+* `void SetHexStr(string s);`
+ * 16進数文字列を設定ã™ã‚‹ã€‚
+* `string GetHexStr();`
+ * 16進数表記をå–å¾—ã™ã‚‹ã€‚
+* `void Add(in SecretKey rhs);`
+ * 秘密éµrhsを加算ã™ã‚‹ã€‚
+* `void SetByCSPRNG();`
+ * æš—å·å­¦çš„乱数ã§è¨­å®šã™ã‚‹ã€‚
+* `void SetHashOf(string s);`
+ * 文字列sã®ãƒãƒƒã‚·ãƒ¥å€¤ã‚’設定ã™ã‚‹ã€‚
+* `PublicKey GetPublicKey();`
+ * 対応ã™ã‚‹å…¬é–‹éµã‚’å–å¾—ã™ã‚‹ã€‚
+* `Signature Sign(string m);`
+ * 文字列mã®ç½²åを生æˆã™ã‚‹ã€‚
+* `Signature GetPop();`
+ * 自身ã®ç§˜å¯†éµã«ã‚ˆã‚‹ç½²å(Proof Of Posession)を生æˆã™ã‚‹ã€‚
+
+## PublicKey
+
+* `byte[] Serialize();`
+ * PublicKeyをシリアライズã™ã‚‹ã€‚
+* `void Deserialize(byte[] buf);`
+ * ãƒã‚¤ãƒˆåˆ—bufã‹ã‚‰PublicKeyをデシリアライズã™ã‚‹ã€‚
+* `bool IsEqual(in PublicKey rhs);`
+ * åŒå€¤åˆ¤å®šã€‚
+* `void Add(in PublicKey rhs);`
+ * 公開éµrhsを加算ã™ã‚‹ã€‚
+* `void SetHexStr(string s);`
+ * 16進数文字列を設定ã™ã‚‹ã€‚
+* `string GetHexStr();`
+ * 16進数表記をå–å¾—ã™ã‚‹ã€‚
+* `bool Verify(in Signature sig, string m);`
+ * 文字列mã«å¯¾ã™ã‚‹ç½²åsigã®æ­£å½“性を確èªã™ã‚‹ã€‚
+* `bool VerifyPop(in Signature pop);`
+ * PoPã®æ­£å½“性を確èªã™ã‚‹ã€‚
+
+## Signature
+
+* `byte[] Serialize();`
+ * Signatureをシリアライズã™ã‚‹ã€‚
+* `void Deserialize(byte[] buf);`
+ * ãƒã‚¤ãƒˆåˆ—bufã‹ã‚‰Signatureをデシリアライズã™ã‚‹ã€‚
+* `bool IsEqual(in Signature rhs);`
+ * åŒå€¤åˆ¤å®šã€‚
+* `void Add(in Signature rhs);`
+ * ç½²århsを加算ã™ã‚‹ã€‚
+* `void SetHexStr(string s);`
+ * 16進数文字列を設定ã™ã‚‹ã€‚
+* `string GetHexStr();`
+ * 16進数表記をå–å¾—ã™ã‚‹ã€‚
+
+## 使ã„æ–¹
+
+### 最å°ã‚µãƒ³ãƒ—ル
+
+```
+using static BLS;
+
+Init(BN254); // ライブラリåˆæœŸåŒ–
+SecretKey sec;
+sec.SetByCSPRNG(); // 秘密éµã®åˆæœŸåŒ–
+PublicKey pub = sec.GetPublicKey(); // 公開éµã®å–å¾—
+string m = "abc";
+Signature sig = sec.Sign(m); // ç½²åã®ä½œæˆ
+if (pub.Verify(sig, m))) {
+ // ç½²åã®ç¢ºèª
+}
+```
+
+### 集約署å
+```
+Init(BN254); // ライブラリåˆæœŸåŒ–
+const int n = 10;
+const string m = "abc";
+SecretKey[] secVec = new SecretKey[n];
+PublicKey[] pubVec = new PublicKey[n];
+Signature[] popVec = new Signature[n];
+Signature[] sigVec = new Signature[n];
+
+for (int i = 0; i < n; i++) {
+ secVec[i].SetByCSPRNG(); // 秘密éµã®åˆæœŸåŒ–
+ pubVec[i] = secVec[i].GetPublicKey(); // 公開éµã®å–å¾—
+ popVec[i] = secVec[i].GetPop(); // 所有(PoP)ã®è¨¼æ˜Ž
+ sigVec[i] = secVec[i].Sign(m); // ç½²å
+}
+
+SecretKey secAgg;
+PublicKey pubAgg;
+Signature sigAgg;
+for (int i = 0; i < n; i++) {
+ // PoPã®ç¢ºèª
+ if (pubVec[i].VerifyPop(popVec[i]))) {
+ // エラー
+ return;
+ }
+ pubAgg.Add(pubVec[i]); // 公開éµã®é›†ç´„
+ sigAgg.Add(sigVec[i]); // ç½²åã®é›†ç´„
+}
+if (pubAgg.Verify(sigAgg, m)) {
+ // ç½²åã®ç¢ºèª
+}
+```
+
+# ライセンス
+
+modified new BSD License
+http://opensource.org/licenses/BSD-3-Clause
+
+# 著者
+
+(C)2019 å…‰æˆæ»‹ç”Ÿ MITSUNARI Shigeo(herumi@nifty.com) All rights reserved.
+本コンテンツã®è‘—作権ã€ãŠã‚ˆã³æœ¬ã‚³ãƒ³ãƒ†ãƒ³ãƒ„中ã«å‡ºã¦ãる商標権ã€å›£ä½“åã€ãƒ­ã‚´ã€è£½å“ã€
+サービスãªã©ã¯ãã‚Œãžã‚Œã€å„権利ä¿æœ‰è€…ã«å¸°å±žã—ã¾ã™
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/readme.md b/vendor/github.com/dexon-foundation/bls/ffi/cs/readme.md
new file mode 100644
index 000000000..2b7191871
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/readme.md
@@ -0,0 +1,185 @@
+# C# binding of BLS threshold signature library
+
+# Installation Requirements
+
+* Visual Studio 2017 or later
+* C# 7.2 or later
+* .NET Framework 4.5.2 or later
+
+# How to build
+
+```
+md work
+cd work
+git clone https://github.com/herumi/cybozulib_ext
+git clone https://github.com/herumi/mcl
+git clone https://github.com/herumi/bls
+cd bls
+mklib dll
+```
+bls/bin/*.dll are created
+
+# How to build a sample
+
+Open bls/ffi/cs/bls.sln and exec it.
+
+* Remark. bls256 is obsolete. Please use bls.sln.
+
+# class and API
+
+## API
+
+* `Init(int curveType = BN254);`
+ * initialize this library with a curve `curveType`.
+ * curveType = BN254 or BLS12_381
+* `SecretKey ShareSecretKey(in SecretKey[] msk, in Id id);`
+ * generate the shared secret key from a sequence of master secret keys msk and Id.
+* `SecretKey RecoverSecretKey(in SecretKey[] secVec, in Id[] idVec);`
+ * recover the secret key from a sequence of secret keys secVec and idVec.
+* `PublicKey SharePublicKey(in PublicKey[] mpk, in Id id);`
+ * generate the shared public key from a sequence of master public keys mpk and Id.
+* `PublicKey RecoverPublicKey(in PublicKey[] pubVec, in Id[] idVec);`
+ * recover the public key from a sequence of public keys pubVec and idVec.
+* `Signature RecoverSign(in Signature[] sigVec, in Id[] idVec);`
+ * recover the signature from a sequence of signatures siVec and idVec.
+
+## Id
+
+Identifier class
+
+* `byte[] Serialize();`
+ * serialize Id
+* `void Deserialize(byte[] buf);`
+ * deserialize from byte[] buf
+* `bool IsEqual(in Id rhs);`
+ * equality
+* `void SetDecStr(string s);`
+ * set by a decimal string s
+* `void SetHexStr(string s);`
+ * set by a hexadecimal string s
+* `void SetInt(int x);`
+ * set an integer x
+* `string GetDecStr();`
+ * get a decimal string
+* `string GetHexStr();`
+ * get a hexadecimal string
+
+## SecretKey
+
+* `byte[] Serialize();`
+ * serialize SecretKey
+* `void Deserialize(byte[] buf);`
+ * deserialize from byte[] buf
+* `bool IsEqual(in SecretKey rhs);`
+ * equality
+* `string GetDecStr();`
+ * get a decimal string
+* `string GetHexStr();`
+ * get a hexadecimal string
+* `void Add(in SecretKey rhs);`
+ * add a secret key rhs
+* `void SetByCSPRNG();`
+ * set a secret key by cryptographically secure pseudo random number generator
+* `void SetHashOf(string s);`
+ * set a secret key by a hash of string s
+* `PublicKey GetPublicKey();`
+ * get the corresponding public key to a secret key
+* `Signature Sign(string m);`
+ * sign a string m
+* `Signature GetPop();`
+ * get a PoP (Proof Of Posession) for a secret key
+
+## PublicKey
+
+* `byte[] Serialize();`
+ * serialize PublicKey
+* `void Deserialize(byte[] buf);`
+ * deserialize from byte[] buf
+* `bool IsEqual(in PublicKey rhs);`
+ * equality
+* `void Add(in PublicKey rhs);`
+ * add a public key rhs
+* `string GetDecStr();`
+ * get a decimal string
+* `string GetHexStr();`
+ * get a hexadecimal string
+* `bool Verify(in Signature sig, string m);`
+ * verify the validness of the sig with m
+* `bool VerifyPop(in Signature pop);`
+ * verify the validness of PoP
+
+## Signature
+
+* `byte[] Serialize();`
+ * serialize Signature
+* `void Deserialize(byte[] buf);`
+ * deserialize from byte[] buf
+* `bool IsEqual(in Signature rhs);`
+ * equality
+* `void Add(in Signature rhs);`
+ * add a signature key rhs
+* `string GetDecStr();`
+ * get a decimal string
+* `string GetHexStr();`
+ * get a hexadecimal string
+
+## How to use
+
+### A minimum sample
+
+```
+using static BLS;
+
+Init(BN254); // init library
+SecretKey sec;
+sec.SetByCSPRNG(); // init secret key
+PublicKey pub = sec.GetPublicKey(); // get public key
+string m = "abc";
+Signature sig = sec.Sign(m); // create signature
+if (pub.Verify(sig, m))) {
+ // signature is verified
+}
+```
+
+### Aggregate signature
+```
+Init(BN254); // init library
+const int n = 10;
+const string m = "abc";
+SecretKey[] secVec = new SecretKey[n];
+PublicKey[] pubVec = new PublicKey[n];
+Signature[] popVec = new Signature[n];
+Signature[] sigVec = new Signature[n];
+
+for (int i = 0; i < n; i++) {
+ secVec[i].SetByCSPRNG(); // init secret key
+ pubVec[i] = secVec[i].GetPublicKey(); // get public key
+ popVec[i] = secVec[i].GetPop(); // get a proof of Possesion (PoP)
+ sigVec[i] = secVec[i].Sign(m); // create signature
+}
+
+SecretKey secAgg;
+PublicKey pubAgg;
+Signature sigAgg;
+for (int i = 0; i < n; i++) {
+ // verify PoP
+ if (pubVec[i].VerifyPop(popVec[i]))) {
+ // error
+ return;
+ }
+ pubAgg.Add(pubVec[i]); // aggregate public key
+ sigAgg.Add(sigVec[i]); // aggregate signature
+}
+if (pubAgg.Verify(sigAgg, m)) {
+ // aggregated signature is verified
+}
+```
+
+# License
+
+modified new BSD License
+http://opensource.org/licenses/BSD-3-Clause
+
+# Author
+
+(C)2019 MITSUNARI Shigeo(herumi@nifty.com) All rights reserved.
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/go/bls/bls.go b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/bls.go
index 5123a07e6..c83a4e658 100644
--- a/vendor/github.com/dexon-foundation/bls/ffi/go/bls/bls.go
+++ b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/bls.go
@@ -1,16 +1,25 @@
package bls
/*
-#cgo CFLAGS:-I../../../include -I../../../../mcl/include/
-#cgo LDFLAGS:${SRCDIR}/../../../lib/libbls384.a ${SRCDIR}/../../../../mcl/lib/libmcl.a -lgmpxx -lgmp -lstdc++
-#cgo CFLAGS:-DMCLBN_FP_UNIT_SIZE=6
-#cgo pkg-config: libcrypto
-#cgo static pkg-config: --static
+#cgo bn256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=4
+#cgo bn256 LDFLAGS:${SRCDIR}/../../../lib/libbls256.a
+#cgo bn384 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6
+#cgo bn384 LDFLAGS:${SRCDIR}/../../../lib/libbls384.a
+#cgo bn384_256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 -DMCLBN_FR_UNIT_SIZE=4
+#cgo bn384_256 LDFLAGS:${SRCDIR}/../../../lib/libbls384_256.a
+#cgo !bn256,!bn384,!bn384_256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6
+#cgo !bn256,!bn384,!bn384_256 LDFLAGS:${SRCDIR}/../../../lib/libbls384.a
+#cgo CFLAGS:-I${SRCDIR}/../../../include -I${SRCDIR}/../../../../mcl/include
+#cgo LDFLAGS:${SRCDIR}/../../../../mcl/lib/libmcl.a -lgmpxx -lgmp
+#cgo linux LDFLAGS:-static
+typedef unsigned int (*ReadRandFunc)(void *, void *, unsigned int);
+int wrapReadRandCgo(void *self, void *buf, unsigned int n);
#include <bls/bls.h>
*/
import "C"
import "fmt"
import "unsafe"
+import "io"
import "encoding/json"
// Init --
@@ -67,6 +76,9 @@ func (id *ID) SetDecString(s string) error {
// IsEqual --
func (id *ID) IsEqual(rhs *ID) bool {
+ if id == nil || rhs == nil {
+ return false
+ }
return id.v.IsEqual(&rhs.v)
}
@@ -146,6 +158,9 @@ func (sec *SecretKey) SetDecString(s string) error {
// IsEqual --
func (sec *SecretKey) IsEqual(rhs *SecretKey) bool {
+ if sec == nil || rhs == nil {
+ return false
+ }
return sec.v.IsEqual(&rhs.v)
}
@@ -264,6 +279,9 @@ func (pub *PublicKey) SetHexString(s string) error {
// IsEqual --
func (pub *PublicKey) IsEqual(rhs *PublicKey) bool {
+ if pub == nil || rhs == nil {
+ return false
+ }
return pub.v.IsEqual(&rhs.v)
}
@@ -350,6 +368,9 @@ func (sign *Sign) SetHexString(s string) error {
// IsEqual --
func (sign *Sign) IsEqual(rhs *Sign) bool {
+ if sign == nil || rhs == nil {
+ return false
+ }
return sign.v.IsEqual(&rhs.v)
}
@@ -389,6 +410,9 @@ func (sign *Sign) Verify(pub *PublicKey, m string) bool {
// VerifyPop --
func (sign *Sign) VerifyPop(pub *PublicKey) bool {
+ if pub.getPointer() == nil {
+ return false
+ }
return C.blsVerifyPop(sign.getPointer(), pub.getPointer()) == 1
}
@@ -420,3 +444,96 @@ func DHKeyExchange(sec *SecretKey, pub *PublicKey) (out PublicKey) {
C.blsDHKeyExchange(out.getPointer(), sec.getPointer(), pub.getPointer())
return out
}
+
+// HashAndMapToSignature --
+func HashAndMapToSignature(buf []byte) *Sign {
+ sig := new(Sign)
+ err := sig.v.HashAndMapTo(buf)
+ if err == nil {
+ return sig
+ } else {
+ return nil
+ }
+}
+
+// VerifyPairing --
+func VerifyPairing(X *Sign, Y *Sign, pub *PublicKey) bool {
+ if X.getPointer() == nil || Y.getPointer() == nil || pub.getPointer() == nil {
+ return false
+ }
+ return C.blsVerifyPairing(X.getPointer(), Y.getPointer(), pub.getPointer()) == 1
+}
+
+// SignHash --
+func (sec *SecretKey) SignHash(hash []byte) (sign *Sign) {
+ sign = new(Sign)
+ // #nosec
+ err := C.blsSignHash(sign.getPointer(), sec.getPointer(), unsafe.Pointer(&hash[0]), C.size_t(len(hash)))
+ if err == 0 {
+ return sign
+ } else {
+ return nil
+ }
+}
+
+// VerifyHash --
+func (sign *Sign) VerifyHash(pub *PublicKey, hash []byte) bool {
+ if pub.getPointer() == nil {
+ return false
+ }
+ // #nosec
+ return C.blsVerifyHash(sign.getPointer(), pub.getPointer(), unsafe.Pointer(&hash[0]), C.size_t(len(hash))) == 1
+}
+
+func Min(x, y int) int {
+ if x < y {
+ return x
+ }
+ return y
+}
+
+// VerifyAggregateHashes --
+func (sign *Sign) VerifyAggregateHashes(pubVec []PublicKey, hash [][]byte) bool {
+ hashByte := GetOpUnitSize() * 8
+ n := len(hash)
+ h := make([]byte, n*hashByte)
+ for i := 0; i < n; i++ {
+ hn := len(hash[i])
+ copy(h[i*hashByte:(i+1)*hashByte], hash[i][0:Min(hn, hashByte)])
+ }
+ if pubVec[0].getPointer() == nil {
+ return false
+ }
+ return C.blsVerifyAggregatedHashes(sign.getPointer(), pubVec[0].getPointer(), unsafe.Pointer(&h[0]), C.size_t(hashByte), C.size_t(n)) == 1
+}
+
+///
+
+var s_randReader io.Reader
+
+func createSlice(buf *C.char, n C.uint) []byte {
+ size := int(n)
+ return (*[1 << 30]byte)(unsafe.Pointer(buf))[:size:size]
+}
+
+// this function can't be put in callback.go
+//export wrapReadRandGo
+func wrapReadRandGo(buf *C.char, n C.uint) C.uint {
+ slice := createSlice(buf, n)
+ ret, err := s_randReader.Read(slice)
+ if ret == int(n) && err == nil {
+ return n
+ }
+ return 0
+}
+
+// SetRandFunc --
+func SetRandFunc(randReader io.Reader) {
+ s_randReader = randReader
+ if randReader != nil {
+ C.blsSetRandFunc(nil, C.ReadRandFunc(unsafe.Pointer(C.wrapReadRandCgo)))
+ } else {
+ // use default random generator
+ C.blsSetRandFunc(nil, C.ReadRandFunc(unsafe.Pointer(nil)))
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/go/bls/bls_test.go b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/bls_test.go
new file mode 100644
index 000000000..a13ee02f4
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/bls_test.go
@@ -0,0 +1,690 @@
+package bls
+
+import "testing"
+import "strconv"
+import "crypto/sha256"
+import "crypto/sha512"
+import "fmt"
+import "crypto/rand"
+
+var unitN = 0
+
+// Tests (for Benchmarks see below)
+
+func testPre(t *testing.T) {
+ t.Log("init")
+ {
+ var id ID
+ err := id.SetLittleEndian([]byte{6, 5, 4, 3, 2, 1})
+ if err != nil {
+ t.Error(err)
+ }
+ t.Log("id :", id.GetHexString())
+ var id2 ID
+ err = id2.SetHexString(id.GetHexString())
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !id.IsEqual(&id2) {
+ t.Errorf("not same id\n%s\n%s", id.GetHexString(), id2.GetHexString())
+ }
+ err = id2.SetDecString(id.GetDecString())
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !id.IsEqual(&id2) {
+ t.Errorf("not same id\n%s\n%s", id.GetDecString(), id2.GetDecString())
+ }
+ }
+ {
+ var sec SecretKey
+ err := sec.SetLittleEndian([]byte{1, 2, 3, 4, 5, 6})
+ if err != nil {
+ t.Error(err)
+ }
+ t.Log("sec=", sec.GetHexString())
+ }
+
+ t.Log("create secret key")
+ m := "this is a bls sample for go"
+ var sec SecretKey
+ sec.SetByCSPRNG()
+ t.Log("sec:", sec.GetHexString())
+ t.Log("create public key")
+ pub := sec.GetPublicKey()
+ t.Log("pub:", pub.GetHexString())
+ sign := sec.Sign(m)
+ t.Log("sign:", sign.GetHexString())
+ if !sign.Verify(pub, m) {
+ t.Error("Signature does not verify")
+ }
+
+ // How to make array of SecretKey
+ {
+ sec := make([]SecretKey, 3)
+ for i := 0; i < len(sec); i++ {
+ sec[i].SetByCSPRNG()
+ t.Log("sec=", sec[i].GetHexString())
+ }
+ }
+}
+
+func testStringConversion(t *testing.T) {
+ t.Log("testRecoverSecretKey")
+ var sec SecretKey
+ var s string
+ if unitN == 6 {
+ s = "16798108731015832284940804142231733909759579603404752749028378864165570215949"
+ } else {
+ s = "40804142231733909759579603404752749028378864165570215949"
+ }
+ err := sec.SetDecString(s)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if s != sec.GetDecString() {
+ t.Error("not equal")
+ }
+ s = sec.GetHexString()
+ var sec2 SecretKey
+ err = sec2.SetHexString(s)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !sec.IsEqual(&sec2) {
+ t.Error("not equal")
+ }
+}
+
+func testRecoverSecretKey(t *testing.T) {
+ t.Log("testRecoverSecretKey")
+ k := 3000
+ var sec SecretKey
+ sec.SetByCSPRNG()
+ t.Logf("sec=%s\n", sec.GetHexString())
+
+ // make master secret key
+ msk := sec.GetMasterSecretKey(k)
+
+ n := k
+ secVec := make([]SecretKey, n)
+ idVec := make([]ID, n)
+ for i := 0; i < n; i++ {
+ err := idVec[i].SetLittleEndian([]byte{byte(i & 255), byte(i >> 8), 2, 3, 4, 5})
+ if err != nil {
+ t.Error(err)
+ }
+ err = secVec[i].Set(msk, &idVec[i])
+ if err != nil {
+ t.Error(err)
+ }
+ // t.Logf("idVec[%d]=%s\n", i, idVec[i].GetHexString())
+ }
+ // recover sec2 from secVec and idVec
+ var sec2 SecretKey
+ err := sec2.Recover(secVec, idVec)
+ if err != nil {
+ t.Error(err)
+ }
+ if !sec.IsEqual(&sec2) {
+ t.Errorf("Mismatch in recovered secret key:\n %s\n %s.", sec.GetHexString(), sec2.GetHexString())
+ }
+}
+
+func testEachSign(t *testing.T, m string, msk []SecretKey, mpk []PublicKey) ([]ID, []SecretKey, []PublicKey, []Sign) {
+ idTbl := []byte{3, 5, 193, 22, 15}
+ n := len(idTbl)
+
+ secVec := make([]SecretKey, n)
+ pubVec := make([]PublicKey, n)
+ signVec := make([]Sign, n)
+ idVec := make([]ID, n)
+
+ for i := 0; i < n; i++ {
+ err := idVec[i].SetLittleEndian([]byte{idTbl[i], 0, 0, 0, 0, 0})
+ if err != nil {
+ t.Error(err)
+ }
+ t.Logf("idVec[%d]=%s\n", i, idVec[i].GetHexString())
+
+ err = secVec[i].Set(msk, &idVec[i])
+ if err != nil {
+ t.Error(err)
+ }
+
+ err = pubVec[i].Set(mpk, &idVec[i])
+ if err != nil {
+ t.Error(err)
+ }
+ t.Logf("pubVec[%d]=%s\n", i, pubVec[i].GetHexString())
+
+ if !pubVec[i].IsEqual(secVec[i].GetPublicKey()) {
+ t.Errorf("Pubkey derivation does not match\n%s\n%s", pubVec[i].GetHexString(), secVec[i].GetPublicKey().GetHexString())
+ }
+
+ signVec[i] = *secVec[i].Sign(m)
+ if !signVec[i].Verify(&pubVec[i], m) {
+ t.Error("Pubkey derivation does not match")
+ }
+ }
+ return idVec, secVec, pubVec, signVec
+}
+func testSign(t *testing.T) {
+ m := "testSign"
+ t.Log(m)
+
+ var sec0 SecretKey
+ sec0.SetByCSPRNG()
+ pub0 := sec0.GetPublicKey()
+ s0 := sec0.Sign(m)
+ if !s0.Verify(pub0, m) {
+ t.Error("Signature does not verify")
+ }
+
+ k := 3
+ msk := sec0.GetMasterSecretKey(k)
+ mpk := GetMasterPublicKey(msk)
+ idVec, secVec, pubVec, signVec := testEachSign(t, m, msk, mpk)
+
+ var sec1 SecretKey
+ err := sec1.Recover(secVec, idVec)
+ if err != nil {
+ t.Error(err)
+ }
+ if !sec0.IsEqual(&sec1) {
+ t.Error("Mismatch in recovered seckey.")
+ }
+ var pub1 PublicKey
+ err = pub1.Recover(pubVec, idVec)
+ if err != nil {
+ t.Error(err)
+ }
+ if !pub0.IsEqual(&pub1) {
+ t.Error("Mismatch in recovered pubkey.")
+ }
+ var s1 Sign
+ err = s1.Recover(signVec, idVec)
+ if err != nil {
+ t.Error(err)
+ }
+ if !s0.IsEqual(&s1) {
+ t.Error("Mismatch in recovered signature.")
+ }
+}
+
+func testAdd(t *testing.T) {
+ t.Log("testAdd")
+ var sec1 SecretKey
+ var sec2 SecretKey
+ sec1.SetByCSPRNG()
+ sec2.SetByCSPRNG()
+
+ pub1 := sec1.GetPublicKey()
+ pub2 := sec2.GetPublicKey()
+
+ m := "test test"
+ sign1 := sec1.Sign(m)
+ sign2 := sec2.Sign(m)
+
+ t.Log("sign1 :", sign1.GetHexString())
+ sign1.Add(sign2)
+ t.Log("sign1 add:", sign1.GetHexString())
+ pub1.Add(pub2)
+ if !sign1.Verify(pub1, m) {
+ t.Fail()
+ }
+}
+
+func testPop(t *testing.T) {
+ t.Log("testPop")
+ var sec SecretKey
+ sec.SetByCSPRNG()
+ pop := sec.GetPop()
+ if !pop.VerifyPop(sec.GetPublicKey()) {
+ t.Errorf("Valid Pop does not verify")
+ }
+ sec.SetByCSPRNG()
+ if pop.VerifyPop(sec.GetPublicKey()) {
+ t.Errorf("Invalid Pop verifies")
+ }
+}
+
+func testData(t *testing.T) {
+ t.Log("testData")
+ var sec1, sec2 SecretKey
+ sec1.SetByCSPRNG()
+ b := sec1.GetLittleEndian()
+ err := sec2.SetLittleEndian(b)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !sec1.IsEqual(&sec2) {
+ t.Error("SecretKey not same")
+ }
+ pub1 := sec1.GetPublicKey()
+ b = pub1.Serialize()
+ var pub2 PublicKey
+ err = pub2.Deserialize(b)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !pub1.IsEqual(&pub2) {
+ t.Error("PublicKey not same")
+ }
+ m := "doremi"
+ sign1 := sec1.Sign(m)
+ b = sign1.Serialize()
+ var sign2 Sign
+ err = sign2.Deserialize(b)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !sign1.IsEqual(&sign2) {
+ t.Error("Sign not same")
+ }
+}
+
+func testSerializeToHexStr(t *testing.T) {
+ t.Log("testSerializeToHexStr")
+ var sec1, sec2 SecretKey
+ sec1.SetByCSPRNG()
+ s := sec1.SerializeToHexStr()
+ err := sec2.DeserializeHexStr(s)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !sec1.IsEqual(&sec2) {
+ t.Error("SecretKey not same")
+ }
+ pub1 := sec1.GetPublicKey()
+ s = pub1.SerializeToHexStr()
+ var pub2 PublicKey
+ err = pub2.DeserializeHexStr(s)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !pub1.IsEqual(&pub2) {
+ t.Error("PublicKey not same")
+ }
+ m := "doremi"
+ sign1 := sec1.Sign(m)
+ s = sign1.SerializeToHexStr()
+ var sign2 Sign
+ err = sign2.DeserializeHexStr(s)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !sign1.IsEqual(&sign2) {
+ t.Error("Sign not same")
+ }
+}
+
+func testOrder(t *testing.T, c int) {
+ var curve string
+ var field string
+ if c == CurveFp254BNb {
+ curve = "16798108731015832284940804142231733909759579603404752749028378864165570215949"
+ field = "16798108731015832284940804142231733909889187121439069848933715426072753864723"
+ } else if c == CurveFp382_1 {
+ curve = "5540996953667913971058039301942914304734176495422447785042938606876043190415948413757785063597439175372845535461389"
+ field = "5540996953667913971058039301942914304734176495422447785045292539108217242186829586959562222833658991069414454984723"
+ } else if c == CurveFp382_2 {
+ curve = "5541245505022739011583672869577435255026888277144126952448297309161979278754528049907713682488818304329661351460877"
+ field = "5541245505022739011583672869577435255026888277144126952450651294188487038640194767986566260919128250811286032482323"
+ } else if c == BLS12_381 {
+ curve = "52435875175126190479447740508185965837690552500527637822603658699938581184513"
+ field = "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787"
+ } else {
+ t.Fatal("bad c", c)
+ }
+ s := GetCurveOrder()
+ if s != curve {
+ t.Errorf("bad curve order\n%s\n%s\n", s, curve)
+ }
+ s = GetFieldOrder()
+ if s != field {
+ t.Errorf("bad field order\n%s\n%s\n", s, field)
+ }
+}
+
+func testDHKeyExchange(t *testing.T) {
+ var sec1, sec2 SecretKey
+ sec1.SetByCSPRNG()
+ sec2.SetByCSPRNG()
+ pub1 := sec1.GetPublicKey()
+ pub2 := sec2.GetPublicKey()
+ out1 := DHKeyExchange(&sec1, pub2)
+ out2 := DHKeyExchange(&sec2, pub1)
+ if !out1.IsEqual(&out2) {
+ t.Errorf("DH key is not equal")
+ }
+}
+
+func testPairing(t *testing.T) {
+ var sec SecretKey
+ sec.SetByCSPRNG()
+ pub := sec.GetPublicKey()
+ m := "abc"
+ sig1 := sec.Sign(m)
+ sig2 := HashAndMapToSignature([]byte(m))
+ if !VerifyPairing(sig1, sig2, pub) {
+ t.Errorf("VerifyPairing")
+ }
+}
+
+func testAggregate(t *testing.T) {
+ var sec SecretKey
+ sec.SetByCSPRNG()
+ pub := sec.GetPublicKey()
+ msgTbl := []string{"abc", "def", "123"}
+ n := len(msgTbl)
+ sigVec := make([]*Sign, n)
+ for i := 0; i < n; i++ {
+ m := msgTbl[i]
+ sigVec[i] = sec.Sign(m)
+ }
+ aggSign := sigVec[0]
+ for i := 1; i < n; i++ {
+ aggSign.Add(sigVec[i])
+ }
+ hashPt := HashAndMapToSignature([]byte(msgTbl[0]))
+ for i := 1; i < n; i++ {
+ hashPt.Add(HashAndMapToSignature([]byte(msgTbl[i])))
+ }
+ if !VerifyPairing(aggSign, hashPt, pub) {
+ t.Errorf("aggregate2")
+ }
+}
+
+func Hash(buf []byte) []byte {
+ if GetOpUnitSize() == 4 {
+ d := sha256.Sum256([]byte(buf))
+ return d[:]
+ } else {
+ // use SHA512 if bitSize > 256
+ d := sha512.Sum512([]byte(buf))
+ return d[:]
+ }
+}
+
+func testHash(t *testing.T) {
+ var sec SecretKey
+ sec.SetByCSPRNG()
+ pub := sec.GetPublicKey()
+ m := "abc"
+ h := Hash([]byte(m))
+ sig1 := sec.Sign(m)
+ sig2 := sec.SignHash(h)
+ if !sig1.IsEqual(sig2) {
+ t.Errorf("SignHash")
+ }
+ if !sig1.Verify(pub, m) {
+ t.Errorf("sig1.Verify")
+ }
+ if !sig2.VerifyHash(pub, h) {
+ t.Errorf("sig2.VerifyHash")
+ }
+}
+
+func testAggregateHashes(t *testing.T) {
+ n := 1000
+ pubVec := make([]PublicKey, n)
+ sigVec := make([]*Sign, n)
+ h := make([][]byte, n)
+ for i := 0; i < n; i++ {
+ sec := new(SecretKey)
+ sec.SetByCSPRNG()
+ pubVec[i] = *sec.GetPublicKey()
+ m := fmt.Sprintf("abc-%d", i)
+ h[i] = Hash([]byte(m))
+ sigVec[i] = sec.SignHash(h[i])
+ }
+ // aggregate sig
+ sig := sigVec[0]
+ for i := 1; i < n; i++ {
+ sig.Add(sigVec[i])
+ }
+ if !sig.VerifyAggregateHashes(pubVec, h) {
+ t.Errorf("sig.VerifyAggregateHashes")
+ }
+}
+
+type SeqRead struct {
+}
+
+func (self *SeqRead) Read(buf []byte) (int, error) {
+ n := len(buf)
+ for i := 0; i < n; i++ {
+ buf[i] = byte(i)
+ }
+ return n, nil
+}
+
+func testReadRand(t *testing.T) {
+ s1 := new(SeqRead)
+ SetRandFunc(s1)
+ var sec SecretKey
+ sec.SetByCSPRNG()
+ buf := sec.GetLittleEndian()
+ fmt.Printf("(SeqRead) buf=%x\n", buf)
+ for i := 0; i < len(buf)-1; i++ {
+ // ommit buf[len(buf) - 1] because it may be masked
+ if buf[i] != byte(i) {
+ t.Fatal("buf")
+ }
+ }
+ SetRandFunc(rand.Reader)
+ sec.SetByCSPRNG()
+ buf = sec.GetLittleEndian()
+ fmt.Printf("(rand.Reader) buf=%x\n", buf)
+ SetRandFunc(nil)
+ sec.SetByCSPRNG()
+ buf = sec.GetLittleEndian()
+ fmt.Printf("(default) buf=%x\n", buf)
+}
+
+func test(t *testing.T, c int) {
+ err := Init(c)
+ if err != nil {
+ t.Fatal(err)
+ }
+ unitN = GetOpUnitSize()
+ t.Logf("unitN=%d\n", unitN)
+ testReadRand(t)
+ testPre(t)
+ testRecoverSecretKey(t)
+ testAdd(t)
+ testSign(t)
+ testPop(t)
+ testData(t)
+ testStringConversion(t)
+ testOrder(t, c)
+ testDHKeyExchange(t)
+ testSerializeToHexStr(t)
+ testPairing(t)
+ testAggregate(t)
+ testHash(t)
+ testAggregateHashes(t)
+}
+
+func TestMain(t *testing.T) {
+ t.Logf("GetMaxOpUnitSize() = %d\n", GetMaxOpUnitSize())
+ t.Log("CurveFp254BNb")
+ test(t, CurveFp254BNb)
+ if GetMaxOpUnitSize() == 6 {
+ if GetFrUnitSize() == 6 {
+ t.Log("CurveFp382_1")
+ test(t, CurveFp382_1)
+ }
+ t.Log("BLS12_381")
+ test(t, BLS12_381)
+ }
+}
+
+// Benchmarks
+
+var curve = CurveFp382_1
+
+//var curve = CurveFp254BNb
+
+func BenchmarkPubkeyFromSeckey(b *testing.B) {
+ b.StopTimer()
+ err := Init(curve)
+ if err != nil {
+ b.Fatal(err)
+ }
+ var sec SecretKey
+ for n := 0; n < b.N; n++ {
+ sec.SetByCSPRNG()
+ b.StartTimer()
+ sec.GetPublicKey()
+ b.StopTimer()
+ }
+}
+
+func BenchmarkSigning(b *testing.B) {
+ b.StopTimer()
+ err := Init(curve)
+ if err != nil {
+ b.Fatal(err)
+ }
+ var sec SecretKey
+ for n := 0; n < b.N; n++ {
+ sec.SetByCSPRNG()
+ b.StartTimer()
+ sec.Sign(strconv.Itoa(n))
+ b.StopTimer()
+ }
+}
+
+func BenchmarkValidation(b *testing.B) {
+ b.StopTimer()
+ err := Init(curve)
+ if err != nil {
+ b.Fatal(err)
+ }
+ var sec SecretKey
+ for n := 0; n < b.N; n++ {
+ sec.SetByCSPRNG()
+ pub := sec.GetPublicKey()
+ m := strconv.Itoa(n)
+ sig := sec.Sign(m)
+ b.StartTimer()
+ sig.Verify(pub, m)
+ b.StopTimer()
+ }
+}
+
+func benchmarkDeriveSeckeyShare(k int, b *testing.B) {
+ b.StopTimer()
+ err := Init(curve)
+ if err != nil {
+ b.Fatal(err)
+ }
+ var sec SecretKey
+ sec.SetByCSPRNG()
+ msk := sec.GetMasterSecretKey(k)
+ var id ID
+ for n := 0; n < b.N; n++ {
+ err = id.SetLittleEndian([]byte{1, 2, 3, 4, 5, byte(n)})
+ if err != nil {
+ b.Error(err)
+ }
+ b.StartTimer()
+ err := sec.Set(msk, &id)
+ b.StopTimer()
+ if err != nil {
+ b.Error(err)
+ }
+ }
+}
+
+//func BenchmarkDeriveSeckeyShare100(b *testing.B) { benchmarkDeriveSeckeyShare(100, b) }
+//func BenchmarkDeriveSeckeyShare200(b *testing.B) { benchmarkDeriveSeckeyShare(200, b) }
+func BenchmarkDeriveSeckeyShare500(b *testing.B) { benchmarkDeriveSeckeyShare(500, b) }
+
+//func BenchmarkDeriveSeckeyShare1000(b *testing.B) { benchmarkDeriveSeckeyShare(1000, b) }
+
+func benchmarkRecoverSeckey(k int, b *testing.B) {
+ b.StopTimer()
+ err := Init(curve)
+ if err != nil {
+ b.Fatal(err)
+ }
+ var sec SecretKey
+ sec.SetByCSPRNG()
+ msk := sec.GetMasterSecretKey(k)
+
+ // derive n shares
+ n := k
+ secVec := make([]SecretKey, n)
+ idVec := make([]ID, n)
+ for i := 0; i < n; i++ {
+ err := idVec[i].SetLittleEndian([]byte{1, 2, 3, 4, 5, byte(i)})
+ if err != nil {
+ b.Error(err)
+ }
+ err = secVec[i].Set(msk, &idVec[i])
+ if err != nil {
+ b.Error(err)
+ }
+ }
+
+ // recover from secVec and idVec
+ var sec2 SecretKey
+ b.StartTimer()
+ for n := 0; n < b.N; n++ {
+ err := sec2.Recover(secVec, idVec)
+ if err != nil {
+ b.Errorf("%s\n", err)
+ }
+ }
+}
+
+func BenchmarkRecoverSeckey100(b *testing.B) { benchmarkRecoverSeckey(100, b) }
+func BenchmarkRecoverSeckey200(b *testing.B) { benchmarkRecoverSeckey(200, b) }
+func BenchmarkRecoverSeckey500(b *testing.B) { benchmarkRecoverSeckey(500, b) }
+func BenchmarkRecoverSeckey1000(b *testing.B) { benchmarkRecoverSeckey(1000, b) }
+
+func benchmarkRecoverSignature(k int, b *testing.B) {
+ b.StopTimer()
+ err := Init(curve)
+ if err != nil {
+ b.Fatal(err)
+ }
+ var sec SecretKey
+ sec.SetByCSPRNG()
+ msk := sec.GetMasterSecretKey(k)
+
+ // derive n shares
+ n := k
+ idVec := make([]ID, n)
+ secVec := make([]SecretKey, n)
+ signVec := make([]Sign, n)
+ for i := 0; i < n; i++ {
+ err := idVec[i].SetLittleEndian([]byte{1, 2, 3, 4, 5, byte(i)})
+ if err != nil {
+ b.Error(err)
+ }
+ err = secVec[i].Set(msk, &idVec[i])
+ if err != nil {
+ b.Error(err)
+ }
+ signVec[i] = *secVec[i].Sign("test message")
+ }
+
+ // recover signature
+ var sig Sign
+ b.StartTimer()
+ for n := 0; n < b.N; n++ {
+ err := sig.Recover(signVec, idVec)
+ if err != nil {
+ b.Error(err)
+ }
+ }
+}
+
+func BenchmarkRecoverSignature100(b *testing.B) { benchmarkRecoverSignature(100, b) }
+func BenchmarkRecoverSignature200(b *testing.B) { benchmarkRecoverSignature(200, b) }
+func BenchmarkRecoverSignature500(b *testing.B) { benchmarkRecoverSignature(500, b) }
+func BenchmarkRecoverSignature1000(b *testing.B) { benchmarkRecoverSignature(1000, b) }
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/go/bls/callback.go b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/callback.go
new file mode 100644
index 000000000..ba73a5e15
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/callback.go
@@ -0,0 +1,12 @@
+package bls
+
+/*
+// exported from bls.go
+unsigned int wrapReadRandGo(void *buf, unsigned int n);
+int wrapReadRandCgo(void *self, void *buf, unsigned int n)
+{
+ (void)self;
+ return wrapReadRandGo(buf, n);
+}
+*/
+import "C"
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/go/bls/config.h b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/config.h
new file mode 100644
index 000000000..07e148137
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/config.h
@@ -0,0 +1,6 @@
+#pragma
+// use bn384 unless tags is specified
+#ifndef MCLBN_FP_UNIT_SIZE
+ #define MCLBN_FP_UNIT_SIZE 6
+#endif
+
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/go/bls/dummy.cpp b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/dummy.cpp
new file mode 100644
index 000000000..a5103a1c5
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/dummy.cpp
@@ -0,0 +1,3 @@
+// This is a dummy source file which forces cgo to use the C++ linker instead
+// of the default C linker. We can therefore eliminate non-portable linker
+// flags such as -lstdc++, which is likely to break on FreeBSD and OpenBSD.
diff --git a/vendor/github.com/dexon-foundation/bls/ffi/go/bls/mcl.go b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/mcl.go
index 9771201ec..ca8d7f02b 100644
--- a/vendor/github.com/dexon-foundation/bls/ffi/go/bls/mcl.go
+++ b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/mcl.go
@@ -1,7 +1,10 @@
package bls
/*
-#cgo CFLAGS:-DMCLBN_FP_UNIT_SIZE=6
+#cgo bn256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=4
+#cgo bn384 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6
+#cgo bn384_256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 -DMCLBN_FR_UNIT_SIZE=4
+#cgo !bn256,!bn384,!bn384_256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6
#include <mcl/bn.h>
*/
import "C"
@@ -23,6 +26,17 @@ const BLS12_381 = C.MCL_BLS12_381
// IoSerializeHexStr
const IoSerializeHexStr = C.MCLBN_IO_SERIALIZE_HEX_STR
+// GetFrUnitSize() --
+func GetFrUnitSize() int {
+ return int(C.MCLBN_FR_UNIT_SIZE)
+}
+
+// GetFpUnitSize() --
+// same as GetMaxOpUnitSize()
+func GetFpUnitSize() int {
+ return int(C.MCLBN_FP_UNIT_SIZE)
+}
+
// GetMaxOpUnitSize --
func GetMaxOpUnitSize() int {
return int(C.MCLBN_FP_UNIT_SIZE)
diff --git a/vendor/github.com/dexon-foundation/bls/images/bls-go-alpine/Dockerfile b/vendor/github.com/dexon-foundation/bls/images/bls-go-alpine/Dockerfile
new file mode 100644
index 000000000..edd49eb4b
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/images/bls-go-alpine/Dockerfile
@@ -0,0 +1,12 @@
+FROM golang:alpine
+MAINTAINER Jimmy Hu <jimmy.hu@dexon.org>
+
+# Install dependencies
+RUN apk add --update-cache build-base gmp-dev openssl-dev git
+
+# Build bls library
+RUN mkdir work ; cd work
+RUN git clone --depth 1 git://github.com/dexon-foundation/mcl.git
+RUN mkdir bls
+COPY . bls/
+RUN cd bls ; make clean && make test_go DOCKER=alpine -j && cp lib/* /usr/lib/
diff --git a/vendor/github.com/dexon-foundation/bls/include/bls/bls.h b/vendor/github.com/dexon-foundation/bls/include/bls/bls.h
index 6b7cbdd68..cb300bc49 100644
--- a/vendor/github.com/dexon-foundation/bls/include/bls/bls.h
+++ b/vendor/github.com/dexon-foundation/bls/include/bls/bls.h
@@ -8,6 +8,14 @@
*/
#include <mcl/bn.h>
+#ifdef BLS_SWAP_G
+ /*
+ error if BLS_SWAP_G is inconsistently used between library and exe
+ */
+ #undef MCLBN_COMPILED_TIME_VAR
+ #define MCLBN_COMPILED_TIME_VAR ((MCLBN_FR_UNIT_SIZE) * 10 + (MCLBN_FP_UNIT_SIZE) + 100)
+#endif
+
#ifdef _MSC_VER
#ifdef BLS_DONT_EXPORT
#define BLS_DLL_API
@@ -21,7 +29,9 @@
#ifndef BLS_NO_AUTOLINK
#if MCLBN_FP_UNIT_SIZE == 4
#pragma comment(lib, "bls256.lib")
- #elif MCLBN_FP_UNIT_SIZE == 6
+ #elif (MCLBN_FP_UNIT_SIZE == 6) && (MCLBN_FR_UNIT_SIZE == 4)
+ #pragma comment(lib, "bls384_256.lib")
+ #elif (MCLBN_FP_UNIT_SIZE == 6) && (MCLBN_FR_UNIT_SIZE == 6)
#pragma comment(lib, "bls384.lib")
#endif
#endif
@@ -46,11 +56,19 @@ typedef struct {
} blsSecretKey;
typedef struct {
+#ifdef BLS_SWAP_G
+ mclBnG1 v;
+#else
mclBnG2 v;
+#endif
} blsPublicKey;
typedef struct {
+#ifdef BLS_SWAP_G
+ mclBnG2 v;
+#else
mclBnG1 v;
+#endif
} blsSignature;
/*
@@ -68,9 +86,13 @@ BLS_DLL_API int blsInit(int curve, int compiledTimeVar);
BLS_DLL_API void blsIdSetInt(blsId *id, int x);
-// return 0 if success
-// mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r
+// sec = buf & (1 << bitLen(r)) - 1
+// if (sec >= r) sec &= (1 << (bitLen(r) - 1)) - 1
+// always return 0
BLS_DLL_API int blsSecretKeySetLittleEndian(blsSecretKey *sec, const void *buf, mclSize bufSize);
+// return 0 if success (bufSize <= 64) else -1
+// set (buf mod r) to sec
+BLS_DLL_API int blsSecretKeySetLittleEndianMod(blsSecretKey *sec, const void *buf, mclSize bufSize);
BLS_DLL_API void blsGetPublicKey(blsPublicKey *pub, const blsSecretKey *sec);
@@ -126,6 +148,15 @@ BLS_DLL_API int blsPublicKeyIsValidOrder(const blsPublicKey *pub);
#ifndef BLS_MINIMUM_API
/*
+ verify X == sY by checking e(X, sQ) = e(Y, Q)
+ @param X [in]
+ @param Y [in]
+ @param pub [in] pub = sQ
+ @return 1 if e(X, pub) = e(Y, Q) else 0
+*/
+BLS_DLL_API int blsVerifyPairing(const blsSignature *X, const blsSignature *Y, const blsPublicKey *pub);
+
+/*
sign the hash
use the low (bitSize of r) - 1 bit of h
return 0 if success else -1
@@ -162,8 +193,13 @@ BLS_DLL_API int blsGetG1ByteSize(void);
// return bytes for serialized Fr
BLS_DLL_API int blsGetFrByteSize(void);
+#ifdef BLS_SWAP_G
+// get a generator of G1
+BLS_DLL_API void blsGetGeneratorOfG1(blsPublicKey *pub);
+#else
// get a generator of G2
BLS_DLL_API void blsGetGeneratorOfG2(blsPublicKey *pub);
+#endif
// return 0 if success
BLS_DLL_API int blsIdSetDecStr(blsId *id, const char *buf, mclSize bufSize);
@@ -184,6 +220,15 @@ BLS_DLL_API int blsHashToSecretKey(blsSecretKey *sec, const void *buf, mclSize b
return 0 if success else -1
*/
BLS_DLL_API int blsSecretKeySetByCSPRNG(blsSecretKey *sec);
+/*
+ set user-defined random function for setByCSPRNG
+ @param self [in] user-defined pointer
+ @param readFunc [in] user-defined function,
+ which writes random bufSize bytes to buf and returns bufSize if success else returns 0
+ @note if self == 0 and readFunc == 0 then set default random function
+ @note not threadsafe
+*/
+BLS_DLL_API void blsSetRandFunc(void *self, unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize));
#endif
BLS_DLL_API void blsGetPop(blsSignature *sig, const blsSecretKey *sec);
diff --git a/vendor/github.com/dexon-foundation/bls/include/bls/bls.hpp b/vendor/github.com/dexon-foundation/bls/include/bls/bls.hpp
index b32b7e1fa..741334555 100644
--- a/vendor/github.com/dexon-foundation/bls/include/bls/bls.hpp
+++ b/vendor/github.com/dexon-foundation/bls/include/bls/bls.hpp
@@ -250,7 +250,7 @@ public:
*/
void recover(const SecretKeyVec& secVec, const IdVec& idVec)
{
- if (secVec.size() != idVec.size()) throw std::invalid_argument("SecretKey::recover");
+ if (secVec.size() != idVec.size()) throw std::invalid_argument("SecretKey:recover");
recover(secVec.data(), idVec.data(), idVec.size());
}
/*
@@ -300,7 +300,12 @@ public:
if (str != "0") {
// 1 <x.a> <x.b> <y.a> <y.b>
std::string t;
- for (int i = 0; i < 4; i++) {
+#ifdef BLS_SWAP_G
+ const int elemNum = 2;
+#else
+ const int elemNum = 4;
+#endif
+ for (int i = 0; i < elemNum; i++) {
is >> t;
str += ' ';
str += t;
@@ -312,14 +317,22 @@ public:
void getStr(std::string& str, int ioMode = 0) const
{
str.resize(1024);
+#ifdef BLS_SWAP_G
+ size_t n = mclBnG1_getStr(&str[0], str.size(), &self_.v, ioMode);
+#else
size_t n = mclBnG2_getStr(&str[0], str.size(), &self_.v, ioMode);
- if (n == 0) throw std::runtime_error("mclBnG2_getStr");
+#endif
+ if (n == 0) throw std::runtime_error("PublicKey:getStr");
str.resize(n);
}
void setStr(const std::string& str, int ioMode = 0)
{
+#ifdef BLS_SWAP_G
+ int ret = mclBnG1_setStr(&self_.v, str.c_str(), str.size(), ioMode);
+#else
int ret = mclBnG2_setStr(&self_.v, str.c_str(), str.size(), ioMode);
- if (ret != 0) throw std::runtime_error("mclBnG2_setStr");
+#endif
+ if (ret != 0) throw std::runtime_error("PublicKey:setStr");
}
/*
set public for id from mpk
@@ -333,7 +346,7 @@ public:
*/
void recover(const PublicKeyVec& pubVec, const IdVec& idVec)
{
- if (pubVec.size() != idVec.size()) throw std::invalid_argument("PublicKey::recover");
+ if (pubVec.size() != idVec.size()) throw std::invalid_argument("PublicKey:recover");
recover(pubVec.data(), idVec.data(), idVec.size());
}
/*
@@ -382,7 +395,12 @@ public:
if (str != "0") {
// 1 <x> <y>
std::string t;
- for (int i = 0; i < 2; i++) {
+#ifdef BLS_SWAP_G
+ const int elemNum = 4;
+#else
+ const int elemNum = 2;
+#endif
+ for (int i = 0; i < elemNum; i++) {
is >> t;
str += ' ';
str += t;
@@ -394,14 +412,22 @@ public:
void getStr(std::string& str, int ioMode = 0) const
{
str.resize(1024);
+#ifdef BLS_SWAP_G
+ size_t n = mclBnG2_getStr(&str[0], str.size(), &self_.v, ioMode);
+#else
size_t n = mclBnG1_getStr(&str[0], str.size(), &self_.v, ioMode);
- if (n == 0) throw std::runtime_error("mclBnG1_getStr");
+#endif
+ if (n == 0) throw std::runtime_error("Signature:tgetStr");
str.resize(n);
}
void setStr(const std::string& str, int ioMode = 0)
{
+#ifdef BLS_SWAP_G
+ int ret = mclBnG2_setStr(&self_.v, str.c_str(), str.size(), ioMode);
+#else
int ret = mclBnG1_setStr(&self_.v, str.c_str(), str.size(), ioMode);
- if (ret != 0) throw std::runtime_error("mclBnG1_setStr");
+#endif
+ if (ret != 0) throw std::runtime_error("Signature:setStr");
}
bool verify(const PublicKey& pub, const void *m, size_t size) const
{
@@ -437,7 +463,7 @@ public:
*/
void recover(const SignatureVec& sigVec, const IdVec& idVec)
{
- if (sigVec.size() != idVec.size()) throw std::invalid_argument("Signature::recover");
+ if (sigVec.size() != idVec.size()) throw std::invalid_argument("Signature:recover");
recover(sigVec.data(), idVec.data(), idVec.size());
}
/*
diff --git a/vendor/github.com/dexon-foundation/bls/mk.bat b/vendor/github.com/dexon-foundation/bls/mk.bat
index c5dfac91a..9bf8dd9e6 100644
--- a/vendor/github.com/dexon-foundation/bls/mk.bat
+++ b/vendor/github.com/dexon-foundation/bls/mk.bat
@@ -8,6 +8,7 @@ if "%1"=="-s" (
echo "mk (-s|-d) <source file>"
goto exit
)
+set CFLAGS=%CFLAGS% -I../mcl/include
set SRC=%2
set EXE=%SRC:.cpp=.exe%
set EXE=%EXE:.c=.exe%
diff --git a/vendor/github.com/dexon-foundation/bls/mklib.bat b/vendor/github.com/dexon-foundation/bls/mklib.bat
index fca9333fc..4a60d7196 100644
--- a/vendor/github.com/dexon-foundation/bls/mklib.bat
+++ b/vendor/github.com/dexon-foundation/bls/mklib.bat
@@ -10,13 +10,17 @@ call setvar.bat
if "%1"=="dll" (
cl /c %CFLAGS% /Foobj/bls_c256.obj src/bls_c256.cpp /DBLS_NO_AUTOLINK
cl /c %CFLAGS% /Foobj/bls_c384.obj src/bls_c384.cpp /DBLS_NO_AUTOLINK
+ cl /c %CFLAGS% /Foobj/bls_c384_256.obj src/bls_c384_256.cpp /DBLS_NO_AUTOLINK
cl /c %CFLAGS% /Foobj/fp.obj ../mcl/src/fp.cpp
link /nologo /DLL /OUT:bin\bls256.dll obj\bls_c256.obj obj\fp.obj %LDFLAGS% /implib:lib\bls256.lib
link /nologo /DLL /OUT:bin\bls384.dll obj\bls_c384.obj obj\fp.obj %LDFLAGS% /implib:lib\bls384.lib
+ link /nologo /DLL /OUT:bin\bls384_256.dll obj\bls_c384_256.obj obj\fp.obj %LDFLAGS% /implib:lib\bls384_256.lib
) else (
cl /c %CFLAGS% /Foobj/bls_c256.obj src/bls_c256.cpp
cl /c %CFLAGS% /Foobj/bls_c384.obj src/bls_c384.cpp
+ cl /c %CFLAGS% /Foobj/bls_c384_256.obj src/bls_c384_256.cpp
cl /c %CFLAGS% /Foobj/fp.obj ../mcl/src/fp.cpp /DMCLBN_DONT_EXPORT
lib /OUT:lib/bls256.lib /nodefaultlib obj/bls_c256.obj obj/fp.obj %LDFLAGS%
lib /OUT:lib/bls384.lib /nodefaultlib obj/bls_c384.obj obj/fp.obj %LDFLAGS%
+ lib /OUT:lib/bls384_256.lib /nodefaultlib obj/bls_c384_256.obj obj/fp.obj %LDFLAGS%
)
diff --git a/vendor/github.com/dexon-foundation/bls/readme.md b/vendor/github.com/dexon-foundation/bls/readme.md
index 08aac6ca1..b1efb3f36 100644
--- a/vendor/github.com/dexon-foundation/bls/readme.md
+++ b/vendor/github.com/dexon-foundation/bls/readme.md
@@ -15,7 +15,23 @@ git clone git://github.com/dexon-foundation/bls.git
git clone git://github.com/herumi/cybozulib_ext ; for only Windows
```
-# **REMARK** libbls.a for C++ interface(bls/bls.hpp) is removed
+# News
+* (Break backward compatibility) The suffix `_dy` of library name is removed and bls\*.a requires libmcl.so set LD_LIBRARY_PATH to the directory.
+* -tags option for Go bindings
+ * -tags bn256
+ * -tags bn384\_256
+ * -tags bn384 ; default mode
+* Support swap of G1 and G2
+ * `make BLS_SWAP_G=1` then G1 is assigned to PublicKey and G2 is assigned to Signature.
+ * golang binding does not support this feature yet.
+* Build option without GMP
+ * `make MCL_USE_GMP=0`
+* Build option without OpenSSL
+ * `make MCL_USE_OPENSSL=0`
+* Build option to specify `mcl` directory
+ * `make MCL_DIR=<mcl directory>`
+
+* (old) libbls.a for C++ interface(bls/bls.hpp) is removed
Link `lib/libbls256.a` or `lib/libbls384.a` to use `bls/bls.hpp` according to MCLBN_FP_UNIT_SIZE = 4 or 6.
# Build and test for Linux
@@ -45,8 +61,9 @@ bin\bls_c384_test.exe
```
# Library
-* libbls256.a/libbls256_dy.so ; for BN254 compiled with MCLBN_FP_UNIT_SIZE=4
-* libbls384.a/libbls384_dy.so ; for BN254/BN381_1/BLS12_381 compiled with MCLBN_FP_UNIT_SIZE=6
+* libbls256.a/libbls256.so ; for BN254 compiled with MCLBN_FP_UNIT_SIZE=4
+* libbls384.a/libbls384.so ; for BN254/BN381_1/BLS12_381 compiled with MCLBN_FP_UNIT_SIZE=6
+* libbls384_256.a/libbls384_256.so ; for BN254/BLS12_381 compiled with MCLBN_FP_UNIT_SIZE=6 and MCLBN_FR_UNIT_SIZE=4
See `mcl/include/curve_type.h` for curve parameter
diff --git a/vendor/github.com/dexon-foundation/bls/sample/bls_smpl.cpp b/vendor/github.com/dexon-foundation/bls/sample/bls_smpl.cpp
new file mode 100644
index 000000000..e812cd500
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/sample/bls_smpl.cpp
@@ -0,0 +1,168 @@
+#define MCLBN_FP_UNIT_SIZE 4
+#include <bls/bls.hpp>
+#include <cybozu/option.hpp>
+#include <cybozu/itoa.hpp>
+#include <fstream>
+
+const std::string pubFile = "sample/publickey";
+const std::string secFile = "sample/secretkey";
+const std::string signFile = "sample/sign";
+
+std::string makeName(const std::string& name, const bls::Id& id)
+{
+ const std::string suf = ".txt";
+ if (id.isZero()) return name + suf;
+ std::ostringstream os;
+ os << name << '.' << id << suf;
+ return os.str();
+}
+
+template<class T>
+void save(const std::string& file, const T& t, const bls::Id& id = 0)
+{
+ const std::string name = makeName(file, id);
+ std::ofstream ofs(name.c_str(), std::ios::binary);
+ if (!(ofs << t)) {
+ throw cybozu::Exception("can't save") << name;
+ }
+}
+
+template<class T>
+void load(T& t, const std::string& file, const bls::Id& id = 0)
+{
+ const std::string name = makeName(file, id);
+ std::ifstream ifs(name.c_str(), std::ios::binary);
+ if (!(ifs >> t)) {
+ throw cybozu::Exception("can't load") << name;
+ }
+}
+
+int init()
+{
+ printf("make %s and %s files\n", secFile.c_str(), pubFile.c_str());
+ bls::SecretKey sec;
+ sec.init();
+ save(secFile, sec);
+ bls::PublicKey pub;
+ sec.getPublicKey(pub);
+ save(pubFile, pub);
+ return 0;
+}
+
+int sign(const std::string& m, int id)
+{
+ printf("sign message `%s` by id=%d\n", m.c_str(), id);
+ bls::SecretKey sec;
+ load(sec, secFile, id);
+ bls::Signature s;
+ sec.sign(s, m);
+ save(signFile, s, id);
+ return 0;
+}
+
+int verify(const std::string& m, int id)
+{
+ printf("verify message `%s` by id=%d\n", m.c_str(), id);
+ bls::PublicKey pub;
+ load(pub, pubFile, id);
+ bls::Signature s;
+ load(s, signFile, id);
+ if (s.verify(pub, m)) {
+ puts("verify ok");
+ return 0;
+ } else {
+ puts("verify err");
+ return 1;
+ }
+}
+
+int share(size_t n, size_t k)
+{
+ printf("%d-out-of-%d threshold sharing\n", (int)k, (int)n);
+ bls::SecretKey sec;
+ load(sec, secFile);
+ bls::SecretKeyVec msk;
+ sec.getMasterSecretKey(msk, k);
+ bls::SecretKeyVec secVec(n);
+ bls::IdVec ids(n);
+ for (size_t i = 0; i < n; i++) {
+ int id = i + 1;
+ ids[i] = id;
+ secVec[i].set(msk, id);
+ }
+ for (size_t i = 0; i < n; i++) {
+ save(secFile, secVec[i], ids[i]);
+ bls::PublicKey pub;
+ secVec[i].getPublicKey(pub);
+ save(pubFile, pub, ids[i]);
+ }
+ return 0;
+}
+
+int recover(const bls::IdVec& ids)
+{
+ printf("recover from");
+ for (size_t i = 0; i < ids.size(); i++) {
+ std::cout << ' ' << ids[i];
+ }
+ printf("\n");
+ bls::SignatureVec sigVec(ids.size());
+ for (size_t i = 0; i < sigVec.size(); i++) {
+ load(sigVec[i], signFile, ids[i]);
+ }
+ bls::Signature s;
+ s.recover(sigVec, ids);
+ save(signFile, s);
+ return 0;
+}
+
+int main(int argc, char *argv[])
+ try
+{
+ bls::init(); // use BN254
+
+ std::string mode;
+ std::string m;
+ size_t n;
+ size_t k;
+ int id;
+ bls::IdVec ids;
+
+ cybozu::Option opt;
+ opt.appendParam(&mode, "init|sign|verify|share|recover");
+ opt.appendOpt(&n, 10, "n", ": k-out-of-n threshold");
+ opt.appendOpt(&k, 3, "k", ": k-out-of-n threshold");
+ opt.appendOpt(&m, "", "m", ": message to be signed");
+ opt.appendOpt(&id, 0, "id", ": id of secretKey");
+ opt.appendVec(&ids, "ids", ": select k id in [0, n). this option should be last");
+ opt.appendHelp("h");
+ if (!opt.parse(argc, argv)) {
+ goto ERR_EXIT;
+ }
+
+ if (mode == "init") {
+ return init();
+ } else if (mode == "sign") {
+ if (m.empty()) goto ERR_EXIT;
+ return sign(m, id);
+ } else if (mode == "verify") {
+ if (m.empty()) goto ERR_EXIT;
+ return verify(m, id);
+ } else if (mode == "share") {
+ return share(n, k);
+ } else if (mode == "recover") {
+ if (ids.empty()) {
+ fprintf(stderr, "use -ids option. ex. share -ids 1 3 5\n");
+ goto ERR_EXIT;
+ }
+ return recover(ids);
+ } else {
+ fprintf(stderr, "bad mode %s\n", mode.c_str());
+ }
+ERR_EXIT:
+ opt.usage();
+ return 1;
+} catch (std::exception& e) {
+ fprintf(stderr, "ERR %s\n", e.what());
+ return 1;
+}
diff --git a/vendor/github.com/dexon-foundation/bls/setvar.bat b/vendor/github.com/dexon-foundation/bls/setvar.bat
index b45af24b9..0ff286ab8 100755
--- a/vendor/github.com/dexon-foundation/bls/setvar.bat
+++ b/vendor/github.com/dexon-foundation/bls/setvar.bat
@@ -1,6 +1,6 @@
@echo off
call ..\mcl\setvar.bat
-set CFLAGS=%CFLAGS% /I ..\mcl\include /I .\
+set CFLAGS=%CFLAGS% /I ..\mcl\include /I ./
set LDFLAGS=%LDFLAGS% /LIBPATH:..\mcl\lib
echo CFLAGS=%CFLAGS%
-echo LDFLAGS=%LDFLAGS% \ No newline at end of file
+echo LDFLAGS=%LDFLAGS%
diff --git a/vendor/github.com/dexon-foundation/bls/src/bls_c384_256.cpp b/vendor/github.com/dexon-foundation/bls/src/bls_c384_256.cpp
new file mode 100644
index 000000000..3dcb3e7d7
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/src/bls_c384_256.cpp
@@ -0,0 +1,4 @@
+#define MCLBN_FP_UNIT_SIZE 6
+#define MCLBN_FR_UNIT_SIZE 4
+#include "bls_c_impl.hpp"
+
diff --git a/vendor/github.com/dexon-foundation/bls/src/bls_c_impl.hpp b/vendor/github.com/dexon-foundation/bls/src/bls_c_impl.hpp
index 16b79f913..b38c1ad06 100644
--- a/vendor/github.com/dexon-foundation/bls/src/bls_c_impl.hpp
+++ b/vendor/github.com/dexon-foundation/bls/src/bls_c_impl.hpp
@@ -3,30 +3,81 @@
#include <bls/bls.h>
-#include "../mcl/src/bn_c_impl.hpp"
+#if 1
+#include "mcl/impl/bn_c_impl.hpp"
+#else
+#if MCLBN_FP_UNIT_SIZE == 4 && MCLBN_FR_UNIT_SIZE == 4
+#include <mcl/bn256.hpp>
+#elif MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE == 6
+#include <mcl/bn384.hpp>
+#elif MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE == 4
+#include <mcl/bls12_381.hpp>
+#elif MCLBN_FP_UNIT_SIZE == 8 && MCLBN_FR_UNIT_SIZE == 8
+#include <mcl/bn512.hpp>
+#else
+ #error "not supported size"
+#endif
+#include <mcl/lagrange.hpp>
+using namespace mcl::bn;
+inline Fr *cast(mclBnFr *p) { return reinterpret_cast<Fr*>(p); }
+inline const Fr *cast(const mclBnFr *p) { return reinterpret_cast<const Fr*>(p); }
+
+inline G1 *cast(mclBnG1 *p) { return reinterpret_cast<G1*>(p); }
+inline const G1 *cast(const mclBnG1 *p) { return reinterpret_cast<const G1*>(p); }
+
+inline G2 *cast(mclBnG2 *p) { return reinterpret_cast<G2*>(p); }
+inline const G2 *cast(const mclBnG2 *p) { return reinterpret_cast<const G2*>(p); }
+
+inline Fp12 *cast(mclBnGT *p) { return reinterpret_cast<Fp12*>(p); }
+inline const Fp12 *cast(const mclBnGT *p) { return reinterpret_cast<const Fp12*>(p); }
+
+inline Fp6 *cast(uint64_t *p) { return reinterpret_cast<Fp6*>(p); }
+inline const Fp6 *cast(const uint64_t *p) { return reinterpret_cast<const Fp6*>(p); }
+#endif
+
+void Gmul(G1& z, const G1& x, const Fr& y) { G1::mul(z, x, y); }
+void Gmul(G2& z, const G2& x, const Fr& y) { G2::mul(z, x, y); }
+void GmulCT(G1& z, const G1& x, const Fr& y) { G1::mulCT(z, x, y); }
+void GmulCT(G2& z, const G2& x, const Fr& y) { G2::mulCT(z, x, y); }
/*
BLS signature
- e : G1 x G2 -> Fp12
+ e : G1 x G2 -> GT
Q in G2 ; fixed global parameter
H : {str} -> G1
s : secret key
sQ ; public key
s H(m) ; signature of m
verify ; e(sQ, H(m)) = e(Q, s H(m))
+
+ swap G1 and G2 if BLS_SWAP_G is defined
+ @note the current implementation does not support precomputed miller loop
*/
+#ifdef BLS_SWAP_G
+static G1 g_P;
+inline const G1& getBasePoint() { return g_P; }
+#else
static G2 g_Q;
const size_t maxQcoeffN = 128;
static mcl::FixedArray<Fp6, maxQcoeffN> g_Qcoeff; // precomputed Q
-inline const G2& getQ() { return g_Q; }
+inline const G2& getBasePoint() { return g_Q; }
inline const mcl::FixedArray<Fp6, maxQcoeffN>& getQcoeff() { return g_Qcoeff; }
+#endif
int blsInitNotThreadSafe(int curve, int compiledTimeVar)
{
- int ret = mclBn_init(curve, compiledTimeVar);
- if (ret < 0) return ret;
+ if (compiledTimeVar != MCLBN_COMPILED_TIME_VAR) {
+ return -(compiledTimeVar | (MCLBN_COMPILED_TIME_VAR * 100));
+ }
+ const mcl::CurveParam& cp = mcl::getCurveParam(curve);
bool b;
+ initPairing(&b, cp);
+ if (!b) return -1;
+
+#ifdef BLS_SWAP_G
+ mapToG1(&b, g_P, 1);
+#else
if (curve == MCL_BN254) {
const char *Qx_BN254 = "11ccb44e77ac2c5dc32a6009594dbe331ec85a61290d6bbac8cc7ebb2dceb128 f204a14bbdac4a05be9a25176de827f2e60085668becdd4fc5fa914c9ee0d9a";
@@ -41,7 +92,7 @@ int blsInitNotThreadSafe(int curve, int compiledTimeVar)
if (curve == MCL_BN254) {
#include "./qcoeff-bn254.hpp"
g_Qcoeff.resize(BN::param.precomputedQcoeffSize);
- assert(g_Qcoeff.size() == CYBOZU_NUM_OF_ARRAY(tbl));
+ assert(g_Qcoeff.size() == CYBOZU_NUM_OF_ARRAY(QcoeffTblBN254));
for (size_t i = 0; i < g_Qcoeff.size(); i++) {
Fp6& x6 = g_Qcoeff[i];
for (size_t j = 0; j < 6; j++) {
@@ -53,8 +104,9 @@ int blsInitNotThreadSafe(int curve, int compiledTimeVar)
}
}
} else {
- precomputeG2(&b, g_Qcoeff, getQ());
+ precomputeG2(&b, g_Qcoeff, getBasePoint());
}
+#endif
if (!b) return -101;
return 0;
}
@@ -103,26 +155,55 @@ static inline const mclBnG2 *cast(const G2* x) { return (const mclBnG2*)x; }
void blsIdSetInt(blsId *id, int x)
{
- mclBnFr_setInt(&id->v, x);
+ *cast(&id->v) = x;
}
int blsSecretKeySetLittleEndian(blsSecretKey *sec, const void *buf, mclSize bufSize)
{
- return mclBnFr_setLittleEndian(&sec->v, buf, bufSize);
+ cast(&sec->v)->setArrayMask((const char *)buf, bufSize);
+ return 0;
+}
+int blsSecretKeySetLittleEndianMod(blsSecretKey *sec, const void *buf, mclSize bufSize)
+{
+ bool b;
+ cast(&sec->v)->setArray(&b, (const char *)buf, bufSize, mcl::fp::Mod);
+ return b ? 0 : -1;
}
void blsGetPublicKey(blsPublicKey *pub, const blsSecretKey *sec)
{
- mclBnG2_mul(&pub->v, cast(&getQ()), &sec->v);
+ Gmul(*cast(&pub->v), getBasePoint(), *cast(&sec->v));
}
void blsSign(blsSignature *sig, const blsSecretKey *sec, const void *m, mclSize size)
{
+#ifdef BLS_SWAP_G
+ G2 Hm;
+ hashAndMapToG2(Hm, m, size);
+#else
G1 Hm;
hashAndMapToG1(Hm, m, size);
- mclBnG1_mulCT(&sig->v, cast(&Hm), &sec->v);
+#endif
+ GmulCT(*cast(&sig->v), Hm, *cast(&sec->v));
}
+#ifdef BLS_SWAP_G
+/*
+ e(P, sHm) == e(sP, Hm)
+ <=> finalExp(ML(P, sHm) * e(-sP, Hm)) == 1
+*/
+bool isEqualTwoPairings(const G2& sHm, const G1& sP, const G2& Hm)
+{
+ GT e1, e2;
+ millerLoop(e1, getBasePoint(), sHm);
+ G1 neg_sP;
+ G1::neg(neg_sP, sP);
+ millerLoop(e2, neg_sP, Hm);
+ e1 *= e2;
+ finalExp(e1, e1);
+ return e1.isOne();
+}
+#else
/*
e(P1, Q1) == e(P2, Q2)
<=> finalExp(ML(P1, Q1)) == finalExp(ML(P2, Q2))
@@ -132,14 +213,20 @@ void blsSign(blsSignature *sig, const blsSecretKey *sec, const void *m, mclSize
*/
bool isEqualTwoPairings(const G1& P1, const Fp6* Q1coeff, const G1& P2, const G2& Q2)
{
- Fp12 e;
+ GT e;
precomputedMillerLoop2mixed(e, P2, Q2, -P1, Q1coeff);
finalExp(e, e);
return e.isOne();
}
+#endif
int blsVerify(const blsSignature *sig, const blsPublicKey *pub, const void *m, mclSize size)
{
+#ifdef BLS_SWAP_G
+ G2 Hm;
+ hashAndMapToG2(Hm, m, size);
+ return isEqualTwoPairings(*cast(&sig->v), *cast(&pub->v), Hm);
+#else
G1 Hm;
hashAndMapToG1(Hm, m, size);
/*
@@ -147,187 +234,238 @@ int blsVerify(const blsSignature *sig, const blsPublicKey *pub, const void *m, m
e(sig, Q) = e(Hm, pub)
*/
return isEqualTwoPairings(*cast(&sig->v), getQcoeff().data(), Hm, *cast(&pub->v));
+#endif
}
mclSize blsIdSerialize(void *buf, mclSize maxBufSize, const blsId *id)
{
- return mclBnFr_serialize(buf, maxBufSize, &id->v);
+ return cast(&id->v)->serialize(buf, maxBufSize);
}
mclSize blsSecretKeySerialize(void *buf, mclSize maxBufSize, const blsSecretKey *sec)
{
- return mclBnFr_serialize(buf, maxBufSize, &sec->v);
+ return cast(&sec->v)->serialize(buf, maxBufSize);
}
mclSize blsPublicKeySerialize(void *buf, mclSize maxBufSize, const blsPublicKey *pub)
{
- return mclBnG2_serialize(buf, maxBufSize, &pub->v);
+ return cast(&pub->v)->serialize(buf, maxBufSize);
}
mclSize blsSignatureSerialize(void *buf, mclSize maxBufSize, const blsSignature *sig)
{
- return mclBnG1_serialize(buf, maxBufSize, &sig->v);
+ return cast(&sig->v)->serialize(buf, maxBufSize);
}
mclSize blsIdDeserialize(blsId *id, const void *buf, mclSize bufSize)
{
- return mclBnFr_deserialize(&id->v, buf, bufSize);
+ return cast(&id->v)->deserialize(buf, bufSize);
}
-mclSize blsSecretKeyDeserialize(blsSecretKey *sig, const void *buf, mclSize bufSize)
+mclSize blsSecretKeyDeserialize(blsSecretKey *sec, const void *buf, mclSize bufSize)
{
- return mclBnFr_deserialize(&sig->v, buf, bufSize);
+ return cast(&sec->v)->deserialize(buf, bufSize);
}
mclSize blsPublicKeyDeserialize(blsPublicKey *pub, const void *buf, mclSize bufSize)
{
- return mclBnG2_deserialize(&pub->v, buf, bufSize);
+ return cast(&pub->v)->deserialize(buf, bufSize);
}
mclSize blsSignatureDeserialize(blsSignature *sig, const void *buf, mclSize bufSize)
{
- return mclBnG1_deserialize(&sig->v, buf, bufSize);
+ return cast(&sig->v)->deserialize(buf, bufSize);
}
int blsIdIsEqual(const blsId *lhs, const blsId *rhs)
{
- return mclBnFr_isEqual(&lhs->v, &rhs->v);
+ return *cast(&lhs->v) == *cast(&rhs->v);
}
int blsSecretKeyIsEqual(const blsSecretKey *lhs, const blsSecretKey *rhs)
{
- return mclBnFr_isEqual(&lhs->v, &rhs->v);
+ return *cast(&lhs->v) == *cast(&rhs->v);
}
int blsPublicKeyIsEqual(const blsPublicKey *lhs, const blsPublicKey *rhs)
{
- return mclBnG2_isEqual(&lhs->v, &rhs->v);
+ return *cast(&lhs->v) == *cast(&rhs->v);
}
int blsSignatureIsEqual(const blsSignature *lhs, const blsSignature *rhs)
{
- return mclBnG1_isEqual(&lhs->v, &rhs->v);
+ return *cast(&lhs->v) == *cast(&rhs->v);
}
int blsSecretKeyShare(blsSecretKey *sec, const blsSecretKey* msk, mclSize k, const blsId *id)
{
- return mclBn_FrEvaluatePolynomial(&sec->v, &msk->v, k, &id->v);
+ bool b;
+ mcl::evaluatePolynomial(&b, *cast(&sec->v), cast(&msk->v), k, *cast(&id->v));
+ return b ? 0 : -1;
}
int blsPublicKeyShare(blsPublicKey *pub, const blsPublicKey *mpk, mclSize k, const blsId *id)
{
- return mclBn_G2EvaluatePolynomial(&pub->v, &mpk->v, k, &id->v);
+ bool b;
+ mcl::evaluatePolynomial(&b, *cast(&pub->v), cast(&mpk->v), k, *cast(&id->v));
+ return b ? 0 : -1;
}
int blsSecretKeyRecover(blsSecretKey *sec, const blsSecretKey *secVec, const blsId *idVec, mclSize n)
{
- return mclBn_FrLagrangeInterpolation(&sec->v, &idVec->v, &secVec->v, n);
+ bool b;
+ mcl::LagrangeInterpolation(&b, *cast(&sec->v), cast(&idVec->v), cast(&secVec->v), n);
+ return b ? 0 : -1;
}
int blsPublicKeyRecover(blsPublicKey *pub, const blsPublicKey *pubVec, const blsId *idVec, mclSize n)
{
- return mclBn_G2LagrangeInterpolation(&pub->v, &idVec->v, &pubVec->v, n);
+ bool b;
+ mcl::LagrangeInterpolation(&b, *cast(&pub->v), cast(&idVec->v), cast(&pubVec->v), n);
+ return b ? 0 : -1;
}
int blsSignatureRecover(blsSignature *sig, const blsSignature *sigVec, const blsId *idVec, mclSize n)
{
- return mclBn_G1LagrangeInterpolation(&sig->v, &idVec->v, &sigVec->v, n);
+ bool b;
+ mcl::LagrangeInterpolation(&b, *cast(&sig->v), cast(&idVec->v), cast(&sigVec->v), n);
+ return b ? 0 : -1;
}
void blsSecretKeyAdd(blsSecretKey *sec, const blsSecretKey *rhs)
{
- mclBnFr_add(&sec->v, &sec->v, &rhs->v);
+ *cast(&sec->v) += *cast(&rhs->v);
}
void blsPublicKeyAdd(blsPublicKey *pub, const blsPublicKey *rhs)
{
- mclBnG2_add(&pub->v, &pub->v, &rhs->v);
+ *cast(&pub->v) += *cast(&rhs->v);
}
void blsSignatureAdd(blsSignature *sig, const blsSignature *rhs)
{
- mclBnG1_add(&sig->v, &sig->v, &rhs->v);
+ *cast(&sig->v) += *cast(&rhs->v);
}
void blsSignatureVerifyOrder(int doVerify)
{
- mclBn_verifyOrderG1(doVerify);
+#ifdef BLS_SWAP_G
+ verifyOrderG2(doVerify != 0);
+#else
+ verifyOrderG1(doVerify != 0);
+#endif
}
void blsPublicKeyVerifyOrder(int doVerify)
{
- mclBn_verifyOrderG2(doVerify);
+#ifdef BLS_SWAP_G
+ verifyOrderG1(doVerify != 0);
+#else
+ verifyOrderG2(doVerify != 0);
+#endif
}
int blsSignatureIsValidOrder(const blsSignature *sig)
{
- return mclBnG1_isValidOrder(&sig->v);
+ return cast(&sig->v)->isValidOrder();
}
int blsPublicKeyIsValidOrder(const blsPublicKey *pub)
{
- return mclBnG2_isValidOrder(&pub->v);
+ return cast(&pub->v)->isValidOrder();
}
#ifndef BLS_MINIMUM_API
-inline bool toG1(G1& Hm, const void *h, mclSize size)
+template<class G>
+inline bool toG(G& Hm, const void *h, mclSize size)
{
Fp t;
t.setArrayMask((const char *)h, size);
bool b;
+#ifdef BLS_SWAP_G
+ BN::mapToG2(&b, Hm, Fp2(t, 0));
+#else
BN::mapToG1(&b, Hm, t);
+#endif
return b;
}
int blsVerifyAggregatedHashes(const blsSignature *aggSig, const blsPublicKey *pubVec, const void *hVec, size_t sizeofHash, mclSize n)
{
if (n == 0) return 0;
+ GT e1, e2;
+ const char *ph = (const char*)hVec;
+#ifdef BLS_SWAP_G
+ millerLoop(e1, getBasePoint(), -*cast(&aggSig->v));
+ G2 h;
+ if (!toG(h, &ph[0], sizeofHash)) return 0;
+ BN::millerLoop(e2, *cast(&pubVec[0].v), h);
+ e1 *= e2;
+ for (size_t i = 1; i < n; i++) {
+ if (!toG(h, &ph[i * sizeofHash], sizeofHash)) return 0;
+ millerLoop(e2, *cast(&pubVec[i].v), h);
+ e1 *= e2;
+ }
+#else
/*
e(aggSig, Q) = prod_i e(hVec[i], pubVec[i])
<=> finalExp(ML(-aggSig, Q) * prod_i ML(hVec[i], pubVec[i])) == 1
*/
- GT e1, e2;
BN::precomputedMillerLoop(e1, -*cast(&aggSig->v), g_Qcoeff.data());
- const char *ph = (const char*)hVec;
G1 h;
- if (!toG1(h, &ph[0], sizeofHash)) return 0;
+ if (!toG(h, &ph[0], sizeofHash)) return 0;
BN::millerLoop(e2, h, *cast(&pubVec[0].v));
e1 *= e2;
for (size_t i = 1; i < n; i++) {
- if (!toG1(h, &ph[i * sizeofHash], sizeofHash)) return 0;
+ if (!toG(h, &ph[i * sizeofHash], sizeofHash)) return 0;
BN::millerLoop(e2, h, *cast(&pubVec[i].v));
e1 *= e2;
}
+#endif
BN::finalExp(e1, e1);
return e1.isOne();
}
int blsSignHash(blsSignature *sig, const blsSecretKey *sec, const void *h, mclSize size)
{
+#ifdef BLS_SWAP_G
+ G2 Hm;
+#else
G1 Hm;
- if (!toG1(Hm, h, size)) return -1;
- mclBnG1_mulCT(&sig->v, cast(&Hm), &sec->v);
+#endif
+ if (!toG(Hm, h, size)) return -1;
+ GmulCT(*cast(&sig->v), Hm, *cast(&sec->v));
return 0;
}
+int blsVerifyPairing(const blsSignature *X, const blsSignature *Y, const blsPublicKey *pub)
+{
+#ifdef BLS_SWAP_G
+ return isEqualTwoPairings(*cast(&X->v), *cast(&pub->v), *cast(&Y->v));
+#else
+ return isEqualTwoPairings(*cast(&X->v), getQcoeff().data(), *cast(&Y->v), *cast(&pub->v));
+#endif
+}
+
int blsVerifyHash(const blsSignature *sig, const blsPublicKey *pub, const void *h, mclSize size)
{
- G1 Hm;
- if (!toG1(Hm, h, size)) return 0;
- return isEqualTwoPairings(*cast(&sig->v), getQcoeff().data(), Hm, *cast(&pub->v));
+ blsSignature Hm;
+ if (!toG(*cast(&Hm.v), h, size)) return 0;
+ return blsVerifyPairing(sig, &Hm, pub);
}
void blsSecretKeySub(blsSecretKey *sec, const blsSecretKey *rhs)
{
- mclBnFr_sub(&sec->v, &sec->v, &rhs->v);
+ *cast(&sec->v) -= *cast(&rhs->v);
}
void blsPublicKeySub(blsPublicKey *pub, const blsPublicKey *rhs)
{
- mclBnG2_sub(&pub->v, &pub->v, &rhs->v);
+ *cast(&pub->v) -= *cast(&rhs->v);
}
void blsSignatureSub(blsSignature *sig, const blsSignature *rhs)
{
- mclBnG1_sub(&sig->v, &sig->v, &rhs->v);
+ *cast(&sig->v) -= *cast(&rhs->v);
}
+
mclSize blsGetOpUnitSize() // FpUint64Size
{
return Fp::getUnitSize() * sizeof(mcl::fp::Unit) / sizeof(uint64_t);
@@ -345,52 +483,67 @@ int blsGetFieldOrder(char *buf, mclSize maxBufSize)
int blsGetG1ByteSize()
{
- return mclBn_getG1ByteSize();
+ return (int)Fp::getByteSize();
}
int blsGetFrByteSize()
{
- return mclBn_getFrByteSize();
+ return (int)Fr::getByteSize();
}
+#ifdef BLS_SWAP_G
+void blsGetGeneratorOfG1(blsPublicKey *pub)
+{
+ *cast(&pub->v) = getBasePoint();
+}
+#else
void blsGetGeneratorOfG2(blsPublicKey *pub)
{
- *(G2*)pub = getQ();
+ *cast(&pub->v) = getBasePoint();
}
+#endif
int blsIdSetDecStr(blsId *id, const char *buf, mclSize bufSize)
{
- return mclBnFr_setStr(&id->v, buf, bufSize, 10);
+ return cast(&id->v)->deserialize(buf, bufSize, 10) > 0 ? 0 : -1;
}
int blsIdSetHexStr(blsId *id, const char *buf, mclSize bufSize)
{
- return mclBnFr_setStr(&id->v, buf, bufSize, 16);
+ return cast(&id->v)->deserialize(buf, bufSize, 16) > 0 ? 0 : -1;
}
int blsIdSetLittleEndian(blsId *id, const void *buf, mclSize bufSize)
{
- return mclBnFr_setLittleEndian(&id->v, buf, bufSize);
+ cast(&id->v)->setArrayMask((const char *)buf, bufSize);
+ return 0;
}
mclSize blsIdGetDecStr(char *buf, mclSize maxBufSize, const blsId *id)
{
- return mclBnFr_getStr(buf, maxBufSize, &id->v, 10);
+ return cast(&id->v)->getStr(buf, maxBufSize, 10);
}
mclSize blsIdGetHexStr(char *buf, mclSize maxBufSize, const blsId *id)
{
- return mclBnFr_getStr(buf, maxBufSize, &id->v, 16);
+ return cast(&id->v)->getStr(buf, maxBufSize, 16);
}
int blsHashToSecretKey(blsSecretKey *sec, const void *buf, mclSize bufSize)
{
- return mclBnFr_setHashOf(&sec->v, buf, bufSize);
+ cast(&sec->v)->setHashOf(buf, bufSize);
+ return 0;
}
#ifndef MCL_DONT_USE_CSPRNG
int blsSecretKeySetByCSPRNG(blsSecretKey *sec)
{
- return mclBnFr_setByCSPRNG(&sec->v);
+ bool b;
+ cast(&sec->v)->setByCSPRNG(&b);
+ return b ? 0 : -1;
+}
+void blsSetRandFunc(void *self, unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize))
+{
+ mcl::fp::RandGen::setRandFunc(self, readFunc);
}
#endif
@@ -399,7 +552,7 @@ void blsGetPop(blsSignature *sig, const blsSecretKey *sec)
blsPublicKey pub;
blsGetPublicKey(&pub, sec);
char buf[1024];
- mclSize n = mclBnG2_serialize(buf, sizeof(buf), &pub.v);
+ mclSize n = cast(&pub.v)->serialize(buf, sizeof(buf));
assert(n);
blsSign(sig, sec, buf, n);
}
@@ -407,54 +560,54 @@ void blsGetPop(blsSignature *sig, const blsSecretKey *sec)
int blsVerifyPop(const blsSignature *sig, const blsPublicKey *pub)
{
char buf[1024];
- mclSize n = mclBnG2_serialize(buf, sizeof(buf), &pub->v);
+ mclSize n = cast(&pub->v)->serialize(buf, sizeof(buf));
if (n == 0) return 0;
return blsVerify(sig, pub, buf, n);
}
mclSize blsIdGetLittleEndian(void *buf, mclSize maxBufSize, const blsId *id)
{
- return mclBnFr_serialize(buf, maxBufSize, &id->v);
+ return cast(&id->v)->serialize(buf, maxBufSize);
}
int blsSecretKeySetDecStr(blsSecretKey *sec, const char *buf, mclSize bufSize)
{
- return mclBnFr_setStr(&sec->v, buf, bufSize, 10);
+ return cast(&sec->v)->deserialize(buf, bufSize, 10) > 0 ? 0 : -1;
}
int blsSecretKeySetHexStr(blsSecretKey *sec, const char *buf, mclSize bufSize)
{
- return mclBnFr_setStr(&sec->v, buf, bufSize, 16);
+ return cast(&sec->v)->deserialize(buf, bufSize, 16) > 0 ? 0 : -1;
}
mclSize blsSecretKeyGetLittleEndian(void *buf, mclSize maxBufSize, const blsSecretKey *sec)
{
- return mclBnFr_serialize(buf, maxBufSize, &sec->v);
+ return cast(&sec->v)->serialize(buf, maxBufSize);
}
mclSize blsSecretKeyGetDecStr(char *buf, mclSize maxBufSize, const blsSecretKey *sec)
{
- return mclBnFr_getStr(buf, maxBufSize, &sec->v, 10);
+ return cast(&sec->v)->getStr(buf, maxBufSize, 10);
}
mclSize blsSecretKeyGetHexStr(char *buf, mclSize maxBufSize, const blsSecretKey *sec)
{
- return mclBnFr_getStr(buf, maxBufSize, &sec->v, 16);
+ return cast(&sec->v)->getStr(buf, maxBufSize, 16);
}
int blsPublicKeySetHexStr(blsPublicKey *pub, const char *buf, mclSize bufSize)
{
- return mclBnG2_setStr(&pub->v, buf, bufSize, 16);
+ return cast(&pub->v)->deserialize(buf, bufSize, 16) > 0 ? 0 : -1;
}
mclSize blsPublicKeyGetHexStr(char *buf, mclSize maxBufSize, const blsPublicKey *pub)
{
- return mclBnG2_getStr(buf, maxBufSize, &pub->v, 16);
+ return cast(&pub->v)->getStr(buf, maxBufSize, 16);
}
int blsSignatureSetHexStr(blsSignature *sig, const char *buf, mclSize bufSize)
{
- return mclBnG1_setStr(&sig->v, buf, bufSize, 16);
+ return cast(&sig->v)->deserialize(buf, bufSize, 16) > 0 ? 0 : -1;
}
mclSize blsSignatureGetHexStr(char *buf, mclSize maxBufSize, const blsSignature *sig)
{
- return mclBnG1_getStr(buf, maxBufSize, &sig->v, 16);
+ return cast(&sig->v)->getStr(buf, maxBufSize, 16);
}
void blsDHKeyExchange(blsPublicKey *out, const blsSecretKey *sec, const blsPublicKey *pub)
{
- mclBnG2_mulCT(&out->v, &pub->v, &sec->v);
+ GmulCT(*cast(&out->v), *cast(&pub->v), *cast(&sec->v));
}
#endif
diff --git a/vendor/github.com/dexon-foundation/bls/test/bls256_test.cpp b/vendor/github.com/dexon-foundation/bls/test/bls256_test.cpp
new file mode 100644
index 000000000..e53a87057
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/test/bls256_test.cpp
@@ -0,0 +1,3 @@
+#define MCLBN_FP_UNIT_SIZE 4
+#include "bls_test.hpp"
+
diff --git a/vendor/github.com/dexon-foundation/bls/test/bls384_256_test.cpp b/vendor/github.com/dexon-foundation/bls/test/bls384_256_test.cpp
new file mode 100644
index 000000000..ea8126567
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/test/bls384_256_test.cpp
@@ -0,0 +1,4 @@
+#define MCLBN_FP_UNIT_SIZE 6
+#define MCLBN_FR_UNIT_SIZE 4
+#include "bls_test.hpp"
+
diff --git a/vendor/github.com/dexon-foundation/bls/test/bls384_test.cpp b/vendor/github.com/dexon-foundation/bls/test/bls384_test.cpp
new file mode 100644
index 000000000..2212f8e6b
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/test/bls384_test.cpp
@@ -0,0 +1,3 @@
+#define MCLBN_FP_UNIT_SIZE 6
+#include "bls_test.hpp"
+
diff --git a/vendor/github.com/dexon-foundation/bls/test/bls_c256_test.cpp b/vendor/github.com/dexon-foundation/bls/test/bls_c256_test.cpp
new file mode 100644
index 000000000..8613720b4
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/test/bls_c256_test.cpp
@@ -0,0 +1,2 @@
+#define MCLBN_FP_UNIT_SIZE 4
+#include "bls_c_test.hpp"
diff --git a/vendor/github.com/dexon-foundation/bls/test/bls_c384_256_test.cpp b/vendor/github.com/dexon-foundation/bls/test/bls_c384_256_test.cpp
new file mode 100644
index 000000000..6f153f9d8
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/test/bls_c384_256_test.cpp
@@ -0,0 +1,3 @@
+#define MCLBN_FP_UNIT_SIZE 6
+#define MCLBN_FR_UNIT_SIZE 4
+#include "bls_c_test.hpp"
diff --git a/vendor/github.com/dexon-foundation/bls/test/bls_c384_test.cpp b/vendor/github.com/dexon-foundation/bls/test/bls_c384_test.cpp
new file mode 100644
index 000000000..b6886dd04
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/test/bls_c384_test.cpp
@@ -0,0 +1,2 @@
+#define MCLBN_FP_UNIT_SIZE 6
+#include "bls_c_test.hpp"
diff --git a/vendor/github.com/dexon-foundation/bls/test/bls_c_test.hpp b/vendor/github.com/dexon-foundation/bls/test/bls_c_test.hpp
new file mode 100644
index 000000000..e9b6e6302
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/test/bls_c_test.hpp
@@ -0,0 +1,437 @@
+#include <cybozu/test.hpp>
+#include <cybozu/inttype.hpp>
+#include <bls/bls.h>
+#include <string.h>
+#include <cybozu/benchmark.hpp>
+#include <mcl/gmp_util.hpp>
+
+size_t pubSize(size_t FrSize)
+{
+#ifdef BLS_SWAP_G
+ return FrSize;
+#else
+ return FrSize * 2;
+#endif
+}
+size_t sigSize(size_t FrSize)
+{
+#ifdef BLS_SWAP_G
+ return FrSize * 2;
+#else
+ return FrSize;
+#endif
+}
+
+void bls_use_stackTest()
+{
+ blsSecretKey sec;
+ blsPublicKey pub;
+ blsSignature sig;
+ const char *msg = "this is a pen";
+ const size_t msgSize = strlen(msg);
+
+ blsSecretKeySetByCSPRNG(&sec);
+
+ blsGetPublicKey(&pub, &sec);
+
+ blsSign(&sig, &sec, msg, msgSize);
+
+ CYBOZU_TEST_ASSERT(blsVerify(&sig, &pub, msg, msgSize));
+}
+
+void blsDataTest()
+{
+ const char *msg = "test test";
+ const size_t msgSize = strlen(msg);
+ const size_t FrSize = blsGetFrByteSize();
+ const size_t FpSize = blsGetG1ByteSize();
+ blsSecretKey sec1, sec2;
+ blsSecretKeySetByCSPRNG(&sec1);
+ char buf[1024];
+ size_t n;
+ size_t ret;
+ n = blsSecretKeyGetHexStr(buf, sizeof(buf), &sec1);
+ CYBOZU_TEST_ASSERT(0 < n && n <= FrSize * 2);
+ ret = blsSecretKeySetHexStr(&sec2, buf, n);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ CYBOZU_TEST_ASSERT(blsSecretKeyIsEqual(&sec1, &sec2));
+
+ memset(&sec2, 0, sizeof(sec2));
+ n = blsSecretKeySerialize(buf, sizeof(buf), &sec1);
+ CYBOZU_TEST_EQUAL(n, FrSize);
+ ret = blsSecretKeyDeserialize(&sec2, buf, n);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(blsSecretKeyIsEqual(&sec1, &sec2));
+
+ blsPublicKey pub1, pub2;
+ blsGetPublicKey(&pub1, &sec1);
+ n = blsPublicKeySerialize(buf, sizeof(buf), &pub1);
+ CYBOZU_TEST_EQUAL(n, pubSize(FpSize));
+ ret = blsPublicKeyDeserialize(&pub2, buf, n);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(blsPublicKeyIsEqual(&pub1, &pub2));
+ blsSignature sig1, sig2;
+ blsSign(&sig1, &sec1, msg, msgSize);
+ n = blsSignatureSerialize(buf, sizeof(buf), &sig1);
+ CYBOZU_TEST_EQUAL(n, sigSize(FpSize));
+ ret = blsSignatureDeserialize(&sig2, buf, n);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(blsSignatureIsEqual(&sig1, &sig2));
+}
+
+void blsOrderTest(const char *curveOrder/*Fr*/, const char *fieldOrder/*Fp*/)
+{
+ char buf[1024];
+ size_t len;
+ len = blsGetCurveOrder(buf, sizeof(buf));
+ CYBOZU_TEST_ASSERT(len > 0);
+ CYBOZU_TEST_EQUAL(buf, curveOrder);
+ len = blsGetFieldOrder(buf, sizeof(buf));
+ CYBOZU_TEST_ASSERT(len > 0);
+ CYBOZU_TEST_EQUAL(buf, fieldOrder);
+}
+
+#if !defined(DISABLE_THREAD_TEST) || defined(__clang__)
+#if defined(CYBOZU_CPP_VERSION) && CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
+#include <thread>
+#include <vector>
+struct Thread {
+ std::unique_ptr<std::thread> t;
+ Thread() : t() {}
+ ~Thread()
+ {
+ if (t) {
+ t->join();
+ }
+ }
+ template<class F>
+ void run(F func, int p1, int p2)
+ {
+ t.reset(new std::thread(func, p1, p2));
+ }
+};
+
+CYBOZU_TEST_AUTO(multipleInit)
+{
+ const size_t n = 100;
+ {
+ std::vector<Thread> vt(n);
+ for (size_t i = 0; i < n; i++) {
+ vt[i].run(blsInit, MCL_BN254, MCLBN_COMPILED_TIME_VAR);
+ }
+ }
+ CYBOZU_TEST_EQUAL(blsGetOpUnitSize(), 4u);
+#if MCLBN_FP_UNIT_SIZE == 6
+ {
+ std::vector<Thread> vt(n);
+ for (size_t i = 0; i < n; i++) {
+ vt[i].run(blsInit, MCL_BLS12_381, MCLBN_COMPILED_TIME_VAR);
+ }
+ }
+ CYBOZU_TEST_EQUAL(blsGetOpUnitSize(), 6u);
+#endif
+}
+#endif
+#endif
+
+void blsSerializeTest()
+{
+ const size_t FrSize = blsGetFrByteSize();
+ const size_t FpSize = blsGetG1ByteSize();
+ printf("FrSize=%d, FpSize=%d\n", (int)FrSize, (int)FpSize);
+ blsId id1, id2;
+ blsSecretKey sec1, sec2;
+ blsPublicKey pub1, pub2;
+ blsSignature sig1, sig2;
+ char buf[1024];
+ size_t n;
+ size_t expectSize;
+ size_t ret;
+ const char dummyChar = '1';
+
+ // Id
+ expectSize = FrSize;
+ blsIdSetInt(&id1, -1);
+ n = blsIdSerialize(buf, sizeof(buf), &id1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ ret = blsIdDeserialize(&id2, buf, n);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(blsIdIsEqual(&id1, &id2));
+
+ ret = blsIdDeserialize(&id2, buf, n - 1);
+ CYBOZU_TEST_EQUAL(ret, 0);
+
+ memset(&id2, 0, sizeof(id2));
+ buf[n] = dummyChar;
+ ret = blsIdDeserialize(&id2, buf, n + 1);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(blsIdIsEqual(&id1, &id2));
+
+ n = blsIdSerialize(buf, expectSize, &id1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ // SecretKey
+ expectSize = FrSize;
+ blsSecretKeySetDecStr(&sec1, "-1", 2);
+ n = blsSecretKeySerialize(buf, sizeof(buf), &sec1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ ret = blsSecretKeyDeserialize(&sec2, buf, n);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(blsSecretKeyIsEqual(&sec1, &sec2));
+
+ ret = blsSecretKeyDeserialize(&sec2, buf, n - 1);
+ CYBOZU_TEST_EQUAL(ret, 0);
+
+ memset(&sec2, 0, sizeof(sec2));
+ buf[n] = dummyChar;
+ ret = blsSecretKeyDeserialize(&sec2, buf, n + 1);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(blsSecretKeyIsEqual(&sec1, &sec2));
+
+ n = blsSecretKeySerialize(buf, expectSize, &sec1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ // PublicKey
+ expectSize = pubSize(FpSize);
+ blsGetPublicKey(&pub1, &sec1);
+ n = blsPublicKeySerialize(buf, sizeof(buf), &pub1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+ CYBOZU_TEST_ASSERT(blsPublicKeyIsValidOrder(&pub1));
+
+ ret = blsPublicKeyDeserialize(&pub2, buf, n);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(blsPublicKeyIsEqual(&pub1, &pub2));
+
+ ret = blsPublicKeyDeserialize(&pub2, buf, n - 1);
+ CYBOZU_TEST_EQUAL(ret, 0);
+
+ memset(&pub2, 0, sizeof(pub2));
+ buf[n] = dummyChar;
+ ret = blsPublicKeyDeserialize(&pub2, buf, n + 1);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(blsPublicKeyIsEqual(&pub1, &pub2));
+
+ n = blsPublicKeySerialize(buf, expectSize, &pub1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ // Signature
+#ifdef BLS_SWAP_G
+ expectSize = FpSize * 2;
+#else
+ expectSize = FpSize;
+#endif
+ blsSign(&sig1, &sec1, "abc", 3);
+ n = blsSignatureSerialize(buf, sizeof(buf), &sig1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+ CYBOZU_TEST_ASSERT(blsSignatureIsValidOrder(&sig1));
+
+ ret = blsSignatureDeserialize(&sig2, buf, n);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(blsSignatureIsEqual(&sig1, &sig2));
+
+ ret = blsSignatureDeserialize(&sig2, buf, n - 1);
+ CYBOZU_TEST_EQUAL(ret, 0);
+
+ memset(&sig2, 0, sizeof(sig2));
+ buf[n] = dummyChar;
+ ret = blsSignatureDeserialize(&sig2, buf, n + 1);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(blsSignatureIsEqual(&sig1, &sig2));
+
+ n = blsSignatureSerialize(buf, expectSize, &sig1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+}
+
+void blsVerifyOrderTest()
+{
+ puts("blsVerifyOrderTest");
+#ifdef BLS_SWAP_G
+ const uint8_t Qs[] =
+#else
+ const uint8_t Ps[] =
+#endif
+ {
+0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ };
+#ifdef BLS_SWAP_G
+ const uint8_t Ps[] =
+#else
+ const uint8_t Qs[] =
+#endif
+ {
+0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ };
+ size_t n;
+ blsPublicKey pub;
+ n = blsPublicKeyDeserialize(&pub, Ps, sizeof(Ps));
+ CYBOZU_TEST_EQUAL(n, 0);
+ blsPublicKeyVerifyOrder(0);
+ n = blsPublicKeyDeserialize(&pub, Ps, sizeof(Ps));
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_ASSERT(!blsPublicKeyIsValidOrder(&pub));
+ blsPublicKeyVerifyOrder(1);
+
+ blsSignature sig;
+ n = blsSignatureDeserialize(&sig, Qs, sizeof(Qs));
+ CYBOZU_TEST_EQUAL(n, 0);
+ blsSignatureVerifyOrder(0);
+ n = blsSignatureDeserialize(&sig, Qs, sizeof(Qs));
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_ASSERT(!blsSignatureIsValidOrder(&sig));
+ blsSignatureVerifyOrder(1);
+}
+
+void blsAddSubTest()
+{
+ blsSecretKey sec[3];
+ blsPublicKey pub[3];
+ blsSignature sig[3];
+ const char *msg = "this is a pen";
+ const size_t msgSize = strlen(msg);
+
+ const char *secHexStr[8] = { "12", "34" };
+ for (int i = 0; i < 2; i++) {
+ blsSecretKeySetHexStr(&sec[i], secHexStr[i], strlen(secHexStr[i]));
+ blsGetPublicKey(&pub[i], &sec[i]);
+ blsSign(&sig[i], &sec[i], msg, msgSize);
+ }
+ sec[2] = sec[0];
+ blsSecretKeyAdd(&sec[2], &sec[1]);
+ char buf[1024];
+ size_t n = blsSecretKeyGetHexStr(buf, sizeof(buf), &sec[2]);
+ CYBOZU_TEST_EQUAL(n, 2);
+ CYBOZU_TEST_EQUAL(buf, "46"); // "12" + "34"
+
+ pub[2] = pub[0];
+ blsPublicKeyAdd(&pub[2], &pub[1]);
+ sig[2] = sig[0];
+ blsSignatureAdd(&sig[2], &sig[1]); // sig[2] = sig[0] + sig[1]
+ blsSignature sig2;
+ blsSign(&sig2, &sec[2], msg, msgSize); // sig2 = signature by sec[2]
+ CYBOZU_TEST_ASSERT(blsSignatureIsEqual(&sig2, &sig[2]));
+ CYBOZU_TEST_ASSERT(blsVerify(&sig[2], &pub[2], msg, msgSize)); // verify by pub[2]
+
+ blsSecretKeySub(&sec[2], &sec[1]);
+ CYBOZU_TEST_ASSERT(blsSecretKeyIsEqual(&sec[2], &sec[0]));
+ blsPublicKeySub(&pub[2], &pub[1]);
+ CYBOZU_TEST_ASSERT(blsPublicKeyIsEqual(&pub[2], &pub[0]));
+ blsSignatureSub(&sig[2], &sig[1]);
+ CYBOZU_TEST_ASSERT(blsSignatureIsEqual(&sig[2], &sig[0]));
+}
+
+void blsTrivialShareTest()
+{
+ blsSecretKey sec1, sec2;
+ blsPublicKey pub1, pub2;
+ blsId id;
+ blsIdSetInt(&id, 123);
+
+ blsSecretKeySetByCSPRNG(&sec1);
+ blsGetPublicKey(&pub1, &sec1);
+ int ret;
+
+ memset(&sec2, 0, sizeof(sec2));
+ ret = blsSecretKeyShare(&sec2, &sec1, 1, &id);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ CYBOZU_TEST_ASSERT(blsSecretKeyIsEqual(&sec1, &sec2));
+ memset(&sec2, 0, sizeof(sec2));
+ ret = blsSecretKeyRecover(&sec2, &sec1, &id, 1);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ CYBOZU_TEST_ASSERT(blsSecretKeyIsEqual(&sec1, &sec2));
+
+ memset(&pub2, 0, sizeof(pub2));
+ ret = blsPublicKeyShare(&pub2, &pub1, 1, &id);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ CYBOZU_TEST_ASSERT(blsPublicKeyIsEqual(&pub1, &pub2));
+ memset(&pub2, 0, sizeof(pub2));
+ ret = blsPublicKeyRecover(&pub2, &pub1, &id, 1);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ CYBOZU_TEST_ASSERT(blsPublicKeyIsEqual(&pub1, &pub2));
+}
+
+void modTest(const char *rStr)
+{
+ unsigned char buf[1024] = {};
+ int ret;
+ blsSecretKey sec;
+ const size_t maxByte = 64; // 512-bit
+ memset(buf, 0xff, maxByte);
+ ret = blsSecretKeySetLittleEndianMod(&sec, buf, maxByte);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ const mpz_class x = (mpz_class(1) << (maxByte * 8)) - 1; // 512-bit 0xff....ff
+ const mpz_class r(rStr);
+ size_t n = blsSecretKeySerialize(buf, sizeof(buf), &sec);
+ CYBOZU_TEST_ASSERT(n > 0);
+ // serialized data to mpz_class
+ mpz_class y = 0;
+ for (size_t i = 0; i < n; i++) {
+ y <<= 8;
+ y += buf[n - 1 - i];
+ }
+ CYBOZU_TEST_EQUAL(y, x % r);
+}
+
+void blsBench()
+{
+ blsSecretKey sec;
+ blsPublicKey pub;
+ blsSignature sig;
+ const char *msg = "this is a pen";
+ const size_t msgSize = strlen(msg);
+
+ blsSecretKeySetByCSPRNG(&sec);
+
+ blsGetPublicKey(&pub, &sec);
+
+ CYBOZU_BENCH_C("sign", 10000, blsSign, &sig, &sec, msg, msgSize);
+ CYBOZU_BENCH_C("verify", 1000, blsVerify, &sig, &pub, msg, msgSize);
+}
+
+CYBOZU_TEST_AUTO(all)
+{
+ const struct {
+ int curveType;
+ const char *r;
+ const char *p;
+ } tbl[] = {
+ {
+ MCL_BN254,
+ "16798108731015832284940804142231733909759579603404752749028378864165570215949",
+ "16798108731015832284940804142231733909889187121439069848933715426072753864723",
+ },
+#if MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE == 6
+ {
+ MCL_BN381_1,
+ "5540996953667913971058039301942914304734176495422447785042938606876043190415948413757785063597439175372845535461389",
+ "5540996953667913971058039301942914304734176495422447785045292539108217242186829586959562222833658991069414454984723",
+ },
+#endif
+#if MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE >= 4
+ {
+ MCL_BLS12_381,
+ "52435875175126190479447740508185965837690552500527637822603658699938581184513",
+ "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787",
+ },
+#endif
+ };
+ for (size_t i = 0; i < sizeof(tbl) / sizeof(tbl[0]); i++) {
+ printf("i=%d\n", (int)i);
+ int ret = blsInit(tbl[i].curveType, MCLBN_COMPILED_TIME_VAR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ if (ret) {
+ printf("ERR %d\n", ret);
+ exit(1);
+ }
+ bls_use_stackTest();
+ blsDataTest();
+ blsOrderTest(tbl[i].r, tbl[i].p);
+ blsSerializeTest();
+ if (tbl[i].curveType == MCL_BLS12_381) blsVerifyOrderTest();
+ blsAddSubTest();
+ blsTrivialShareTest();
+ modTest(tbl[i].r);
+ blsBench();
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/bls/test/bls_test.hpp b/vendor/github.com/dexon-foundation/bls/test/bls_test.hpp
new file mode 100644
index 000000000..346fafe15
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/test/bls_test.hpp
@@ -0,0 +1,545 @@
+#include <bls/bls.hpp>
+#include <cybozu/test.hpp>
+#include <cybozu/inttype.hpp>
+#include <iostream>
+#include <sstream>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/sha2.hpp>
+
+template<class T>
+void streamTest(const T& t)
+{
+ std::ostringstream oss;
+ oss << t;
+ std::istringstream iss(oss.str());
+ T t2;
+ iss >> t2;
+ CYBOZU_TEST_EQUAL(t, t2);
+}
+
+template<class T>
+void testSetForBN254()
+{
+ /*
+ mask value to be less than r if the value >= (1 << (192 + 62))
+ */
+ const uint64_t fff = uint64_t(-1);
+ const uint64_t one = uint64_t(1);
+ const struct {
+ uint64_t in;
+ uint64_t expected;
+ } tbl[] = {
+ { fff, (one << 61) - 1 }, // masked with (1 << 61) - 1
+ { one << 62, 0 }, // masked
+ { (one << 62) | (one << 61), (one << 61) }, // masked
+ { (one << 61) - 1, (one << 61) - 1 }, // same
+ };
+ T t1, t2;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ uint64_t v1[] = { fff, fff, fff, tbl[i].in };
+ uint64_t v2[] = { fff, fff, fff, tbl[i].expected };
+ t1.set(v1);
+ t2.set(v2);
+ CYBOZU_TEST_EQUAL(t1, t2);
+ }
+}
+
+void testForBN254()
+{
+ CYBOZU_TEST_EQUAL(bls::getOpUnitSize(), 4);
+ bls::Id id;
+ CYBOZU_TEST_ASSERT(id.isZero());
+ id = 5;
+ CYBOZU_TEST_EQUAL(id, 5);
+ {
+ const uint64_t id1[] = { 1, 2, 3, 4 };
+ id.set(id1);
+ std::ostringstream os;
+ os << id;
+ CYBOZU_TEST_EQUAL(os.str(), "0x4000000000000000300000000000000020000000000000001");
+ }
+ testSetForBN254<bls::Id>();
+ testSetForBN254<bls::SecretKey>();
+}
+
+void hashTest(int type)
+{
+ bls::SecretKey sec;
+ sec.init();
+ bls::PublicKey pub;
+ sec.getPublicKey(pub);
+ const std::string h = "\x01\x02\x03";
+ bls::Signature sig;
+ sec.signHash(sig, h);
+ CYBOZU_TEST_ASSERT(sig.verifyHash(pub, h));
+ CYBOZU_TEST_ASSERT(!sig.verifyHash(pub, "\x01\x02\04"));
+ if (type == MCL_BN254) {
+ CYBOZU_TEST_EXCEPTION(sec.signHash(sig, "", 0), std::exception);
+ CYBOZU_TEST_EXCEPTION(sec.signHash(sig, "\x00", 1), std::exception);
+ CYBOZU_TEST_EXCEPTION(sec.signHash(sig, "\x00\x00", 2), std::exception);
+#ifndef BLS_SWAP_G
+ const uint64_t c1[] = { 0x0c00000000000004ull, 0xcf0f000000000006ull, 0x26cd890000000003ull, 0x2523648240000001ull };
+ const uint64_t mc1[] = { 0x9b0000000000000full, 0x921200000000000dull, 0x9366c48000000004ull };
+ CYBOZU_TEST_EXCEPTION(sec.signHash(sig, c1, 32), std::exception);
+ CYBOZU_TEST_EXCEPTION(sec.signHash(sig, mc1, 24), std::exception);
+#endif
+ }
+}
+
+void blsTest()
+{
+ bls::SecretKey sec;
+ sec.init();
+ streamTest(sec);
+ bls::PublicKey pub;
+ sec.getPublicKey(pub);
+ streamTest(pub);
+ for (int i = 0; i < 5; i++) {
+ std::string m = "hello";
+ m += char('0' + i);
+ bls::Signature sig;
+ sec.sign(sig, m);
+ CYBOZU_TEST_ASSERT(sig.verify(pub, m));
+ CYBOZU_TEST_ASSERT(!sig.verify(pub, m + "a"));
+ streamTest(sig);
+ CYBOZU_BENCH_C("sign", 10000, sec.sign, sig, m);
+ CYBOZU_BENCH_C("verify", 1000, sig.verify, pub, m);
+ }
+}
+
+void k_of_nTest()
+{
+ const std::string m = "abc";
+ const int n = 5;
+ const int k = 3;
+ bls::SecretKey sec0;
+ sec0.init();
+ bls::Signature sig0;
+ sec0.sign(sig0, m);
+ bls::PublicKey pub0;
+ sec0.getPublicKey(pub0);
+ CYBOZU_TEST_ASSERT(sig0.verify(pub0, m));
+
+ bls::SecretKeyVec msk;
+ sec0.getMasterSecretKey(msk, k);
+
+ bls::SecretKeyVec allPrvVec(n);
+ bls::IdVec allIdVec(n);
+ for (int i = 0; i < n; i++) {
+ int id = i + 1;
+ allPrvVec[i].set(msk, id);
+ allIdVec[i] = id;
+
+ bls::SecretKey p;
+ p.set(msk.data(), k, id);
+ CYBOZU_TEST_EQUAL(allPrvVec[i], p);
+ }
+
+ bls::SignatureVec allSigVec(n);
+ for (int i = 0; i < n; i++) {
+ CYBOZU_TEST_ASSERT(allPrvVec[i] != sec0);
+ allPrvVec[i].sign(allSigVec[i], m);
+ bls::PublicKey pub;
+ allPrvVec[i].getPublicKey(pub);
+ CYBOZU_TEST_ASSERT(pub != pub0);
+ CYBOZU_TEST_ASSERT(allSigVec[i].verify(pub, m));
+ }
+
+ /*
+ 3-out-of-n
+ can recover
+ */
+ bls::SecretKeyVec secVec(3);
+ bls::IdVec idVec(3);
+ for (int a = 0; a < n; a++) {
+ secVec[0] = allPrvVec[a];
+ idVec[0] = allIdVec[a];
+ for (int b = a + 1; b < n; b++) {
+ secVec[1] = allPrvVec[b];
+ idVec[1] = allIdVec[b];
+ for (int c = b + 1; c < n; c++) {
+ secVec[2] = allPrvVec[c];
+ idVec[2] = allIdVec[c];
+ bls::SecretKey sec;
+ sec.recover(secVec, idVec);
+ CYBOZU_TEST_EQUAL(sec, sec0);
+ bls::SecretKey sec2;
+ sec2.recover(secVec.data(), idVec.data(), secVec.size());
+ CYBOZU_TEST_EQUAL(sec, sec2);
+ }
+ }
+ }
+ {
+ secVec[0] = allPrvVec[0];
+ secVec[1] = allPrvVec[1];
+ secVec[2] = allPrvVec[0]; // same of secVec[0]
+ idVec[0] = allIdVec[0];
+ idVec[1] = allIdVec[1];
+ idVec[2] = allIdVec[0];
+ bls::SecretKey sec;
+ CYBOZU_TEST_EXCEPTION_MESSAGE(sec.recover(secVec, idVec), std::exception, "same id");
+ }
+ {
+ /*
+ n-out-of-n
+ can recover
+ */
+ bls::SecretKey sec;
+ sec.recover(allPrvVec, allIdVec);
+ CYBOZU_TEST_EQUAL(sec, sec0);
+ }
+ /*
+ 2-out-of-n
+ can't recover
+ */
+ secVec.resize(2);
+ idVec.resize(2);
+ for (int a = 0; a < n; a++) {
+ secVec[0] = allPrvVec[a];
+ idVec[0] = allIdVec[a];
+ for (int b = a + 1; b < n; b++) {
+ secVec[1] = allPrvVec[b];
+ idVec[1] = allIdVec[b];
+ bls::SecretKey sec;
+ sec.recover(secVec, idVec);
+ CYBOZU_TEST_ASSERT(sec != sec0);
+ }
+ }
+ /*
+ 3-out-of-n
+ can recover
+ */
+ bls::SignatureVec sigVec(3);
+ idVec.resize(3);
+ for (int a = 0; a < n; a++) {
+ sigVec[0] = allSigVec[a];
+ idVec[0] = allIdVec[a];
+ for (int b = a + 1; b < n; b++) {
+ sigVec[1] = allSigVec[b];
+ idVec[1] = allIdVec[b];
+ for (int c = b + 1; c < n; c++) {
+ sigVec[2] = allSigVec[c];
+ idVec[2] = allIdVec[c];
+ bls::Signature sig;
+ sig.recover(sigVec, idVec);
+ CYBOZU_TEST_EQUAL(sig, sig0);
+ }
+ }
+ }
+ {
+ sigVec[0] = allSigVec[1]; idVec[0] = allIdVec[1];
+ sigVec[1] = allSigVec[4]; idVec[1] = allIdVec[4];
+ sigVec[2] = allSigVec[3]; idVec[2] = allIdVec[3];
+ bls::Signature sig;
+ CYBOZU_BENCH_C("sig.recover", 100, sig.recover, sigVec, idVec);
+ }
+ {
+ /*
+ n-out-of-n
+ can recover
+ */
+ bls::Signature sig;
+ sig.recover(allSigVec, allIdVec);
+ CYBOZU_TEST_EQUAL(sig, sig0);
+ }
+ /*
+ 2-out-of-n
+ can't recover
+ */
+ sigVec.resize(2);
+ idVec.resize(2);
+ for (int a = 0; a < n; a++) {
+ sigVec[0] = allSigVec[a];
+ idVec[0] = allIdVec[a];
+ for (int b = a + 1; b < n; b++) {
+ sigVec[1] = allSigVec[b];
+ idVec[1] = allIdVec[b];
+ bls::Signature sig;
+ sig.recover(sigVec, idVec);
+ CYBOZU_TEST_ASSERT(sig != sig0);
+ }
+ }
+ // return same value if n = 1
+ sigVec.resize(1);
+ idVec.resize(1);
+ sigVec[0] = allSigVec[0];
+ idVec[0] = allIdVec[0];
+ {
+ bls::Signature sig;
+ sig.recover(sigVec, idVec);
+ CYBOZU_TEST_EQUAL(sig, sigVec[0]);
+ }
+ // share and recover publicKey
+ {
+ bls::PublicKeyVec pubVec(k);
+ idVec.resize(k);
+ // select [0, k) publicKey
+ for (int i = 0; i < k; i++) {
+ allPrvVec[i].getPublicKey(pubVec[i]);
+ idVec[i] = allIdVec[i];
+ }
+ bls::PublicKey pub;
+ pub.recover(pubVec, idVec);
+ CYBOZU_TEST_EQUAL(pub, pub0);
+ bls::PublicKey pub2;
+ pub2.recover(pubVec.data(), idVec.data(), pubVec.size());
+ CYBOZU_TEST_EQUAL(pub, pub2);
+ }
+}
+
+void popTest()
+{
+ const size_t k = 3;
+ const size_t n = 6;
+ const std::string m = "pop test";
+ bls::SecretKey sec0;
+ sec0.init();
+ bls::PublicKey pub0;
+ sec0.getPublicKey(pub0);
+ bls::Signature sig0;
+ sec0.sign(sig0, m);
+ CYBOZU_TEST_ASSERT(sig0.verify(pub0, m));
+
+ bls::SecretKeyVec msk;
+ sec0.getMasterSecretKey(msk, k);
+
+ bls::PublicKeyVec mpk;
+ bls::getMasterPublicKey(mpk, msk);
+ bls::SignatureVec popVec;
+ bls::getPopVec(popVec, msk);
+
+ for (size_t i = 0; i < popVec.size(); i++) {
+ CYBOZU_TEST_ASSERT(popVec[i].verify(mpk[i]));
+ }
+
+ const int idTbl[n] = {
+ 3, 5, 193, 22, 15
+ };
+ bls::SecretKeyVec secVec(n);
+ bls::PublicKeyVec pubVec(n);
+ bls::SignatureVec sVec(n);
+ for (size_t i = 0; i < n; i++) {
+ int id = idTbl[i];
+ secVec[i].set(msk, id);
+ secVec[i].getPublicKey(pubVec[i]);
+ bls::PublicKey pub;
+ pub.set(mpk, id);
+ CYBOZU_TEST_EQUAL(pubVec[i], pub);
+
+ bls::Signature pop;
+ secVec[i].getPop(pop);
+ CYBOZU_TEST_ASSERT(pop.verify(pubVec[i]));
+
+ secVec[i].sign(sVec[i], m);
+ CYBOZU_TEST_ASSERT(sVec[i].verify(pubVec[i], m));
+ }
+ secVec.resize(k);
+ sVec.resize(k);
+ bls::IdVec idVec(k);
+ for (size_t i = 0; i < k; i++) {
+ idVec[i] = idTbl[i];
+ }
+ bls::SecretKey sec;
+ sec.recover(secVec, idVec);
+ CYBOZU_TEST_EQUAL(sec, sec0);
+ bls::Signature sig;
+ sig.recover(sVec, idVec);
+ CYBOZU_TEST_EQUAL(sig, sig0);
+ bls::Signature sig2;
+ sig2.recover(sVec.data(), idVec.data(), sVec.size());
+ CYBOZU_TEST_EQUAL(sig, sig2);
+}
+
+void addTest()
+{
+ bls::SecretKey sec1, sec2;
+ sec1.init();
+ sec2.init();
+ CYBOZU_TEST_ASSERT(sec1 != sec2);
+
+ bls::PublicKey pub1, pub2;
+ sec1.getPublicKey(pub1);
+ sec2.getPublicKey(pub2);
+
+ const std::string m = "doremi";
+ bls::Signature sig1, sig2;
+ sec1.sign(sig1, m);
+ sec2.sign(sig2, m);
+ CYBOZU_TEST_ASSERT((sig1 + sig2).verify(pub1 + pub2, m));
+}
+
+void aggregateTest()
+{
+ const size_t n = 10;
+ bls::SecretKey secs[n];
+ bls::PublicKey pubs[n], pub;
+ bls::Signature sigs[n], sig;
+ const std::string m = "abc";
+ for (size_t i = 0; i < n; i++) {
+ secs[i].init();
+ secs[i].getPublicKey(pubs[i]);
+ secs[i].sign(sigs[i], m);
+ }
+ pub = pubs[0];
+ sig = sigs[0];
+ for (size_t i = 1; i < n; i++) {
+ pub.add(pubs[i]);
+ sig.add(sigs[i]);
+ }
+ CYBOZU_TEST_ASSERT(sig.verify(pub, m));
+}
+
+void dataTest()
+{
+ const size_t FrSize = bls::getFrByteSize();
+ const size_t FpSize = bls::getG1ByteSize();
+ bls::SecretKey sec;
+ sec.init();
+ std::string str;
+ sec.getStr(str, bls::IoFixedByteSeq);
+ {
+ CYBOZU_TEST_EQUAL(str.size(), FrSize);
+ bls::SecretKey sec2;
+ sec2.setStr(str, bls::IoFixedByteSeq);
+ CYBOZU_TEST_EQUAL(sec, sec2);
+ }
+ bls::PublicKey pub;
+ sec.getPublicKey(pub);
+ pub.getStr(str, bls::IoFixedByteSeq);
+ {
+#ifdef BLS_SWAP_G
+ CYBOZU_TEST_EQUAL(str.size(), FpSize);
+#else
+ CYBOZU_TEST_EQUAL(str.size(), FpSize * 2);
+#endif
+ bls::PublicKey pub2;
+ pub2.setStr(str, bls::IoFixedByteSeq);
+ CYBOZU_TEST_EQUAL(pub, pub2);
+ }
+ std::string m = "abc";
+ bls::Signature sign;
+ sec.sign(sign, m);
+ sign.getStr(str, bls::IoFixedByteSeq);
+ {
+#ifdef BLS_SWAP_G
+ CYBOZU_TEST_EQUAL(str.size(), FpSize * 2);
+#else
+ CYBOZU_TEST_EQUAL(str.size(), FpSize);
+#endif
+ bls::Signature sign2;
+ sign2.setStr(str, bls::IoFixedByteSeq);
+ CYBOZU_TEST_EQUAL(sign, sign2);
+ }
+ bls::Id id;
+ const uint64_t v[] = { 1, 2, 3, 4, 5, 6, };
+ id.set(v);
+ id.getStr(str, bls::IoFixedByteSeq);
+ {
+ CYBOZU_TEST_EQUAL(str.size(), FrSize);
+ bls::Id id2;
+ id2.setStr(str, bls::IoFixedByteSeq);
+ CYBOZU_TEST_EQUAL(id, id2);
+ }
+}
+
+void verifyAggregateTest()
+{
+ const size_t n = 10;
+ bls::SecretKey secs[n];
+ bls::PublicKey pubs[n];
+ bls::Signature sigs[n], sig;
+ const size_t sizeofHash = 32;
+ struct Hash { char data[sizeofHash]; };
+ std::vector<Hash> h(n);
+ for (size_t i = 0; i < n; i++) {
+ char msg[128];
+ CYBOZU_SNPRINTF(msg, sizeof(msg), "abc-%d", (int)i);
+ const size_t msgSize = strlen(msg);
+ cybozu::Sha256().digest(h[i].data, sizeofHash, msg, msgSize);
+ secs[i].init();
+ secs[i].getPublicKey(pubs[i]);
+ secs[i].signHash(sigs[i], h[i].data, sizeofHash);
+ }
+ sig = sigs[0];
+ for (size_t i = 1; i < n; i++) {
+ sig.add(sigs[i]);
+ }
+ CYBOZU_TEST_ASSERT(sig.verifyAggregatedHashes(pubs, h.data(), sizeofHash, n));
+ bls::Signature invalidSig = sigs[0] + sigs[1];
+ CYBOZU_TEST_ASSERT(!invalidSig.verifyAggregatedHashes(pubs, h.data(), sizeofHash, n));
+ h[0].data[0]++;
+ CYBOZU_TEST_ASSERT(!sig.verifyAggregatedHashes(pubs, h.data(), sizeofHash, n));
+}
+
+unsigned int writeSeq(void *self, void *buf, unsigned int bufSize)
+{
+ int& seq = *(int*)self;
+ char *p = (char *)buf;
+ for (unsigned int i = 0; i < bufSize; i++) {
+ p[i] = char(seq++);
+ }
+ return bufSize;
+}
+
+void setRandFuncTest()
+{
+ blsSecretKey sec;
+ const int seqInit1 = 5;
+ int seq = seqInit1;
+ blsSetRandFunc(&seq, writeSeq);
+ blsSecretKeySetByCSPRNG(&sec);
+ unsigned char buf[128];
+ size_t n = blsSecretKeySerialize(buf, sizeof(buf), &sec);
+ CYBOZU_TEST_ASSERT(n > 0);
+ for (size_t i = 0; i < n - 1; i++) {
+ // ommit buf[n - 1] because it may be masked
+ CYBOZU_TEST_EQUAL(buf[i], seqInit1 + i);
+ }
+ // use default CSPRNG
+ blsSetRandFunc(0, 0);
+ blsSecretKeySetByCSPRNG(&sec);
+ n = blsSecretKeySerialize(buf, sizeof(buf), &sec);
+ CYBOZU_TEST_ASSERT(n > 0);
+ printf("sec=");
+ for (size_t i = 0; i < n; i++) {
+ printf("%02x", buf[i]);
+ }
+ printf("\n");
+}
+
+void testAll()
+{
+ blsTest();
+ k_of_nTest();
+ popTest();
+ addTest();
+ dataTest();
+ aggregateTest();
+ verifyAggregateTest();
+ setRandFuncTest();
+}
+CYBOZU_TEST_AUTO(all)
+{
+ const struct {
+ int type;
+ const char *name;
+ } tbl[] = {
+ { MCL_BN254, "BN254" },
+#if MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE == 6
+ { MCL_BN381_1, "BN381_1" },
+#endif
+#if MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE == 4
+ { MCL_BLS12_381, "BLS12_381" },
+#endif
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ printf("curve=%s\n", tbl[i].name);
+ int type = tbl[i].type;
+ bls::init(type);
+ if (type == MCL_BN254) {
+ testForBN254();
+ }
+ testAll();
+ hashTest(type);
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/bls/test/proj/bls_test/bls_test.vcxproj b/vendor/github.com/dexon-foundation/bls/test/proj/bls_test/bls_test.vcxproj
new file mode 100644
index 000000000..1755135fb
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/bls/test/proj/bls_test/bls_test.vcxproj
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{51266DE6-B57B-4AE3-B85C-282F170E1728}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>fp_test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)debug.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)release.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)test\\bls_test.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto/dkg/constant.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto/dkg/constant.go
index 3e7ef4574..37d873d6f 100644
--- a/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto/dkg/constant.go
+++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto/dkg/constant.go
@@ -22,5 +22,5 @@ import (
)
const (
- curve = bls.CurveFp382_2
+ curve = bls.BLS12_381
)
diff --git a/vendor/github.com/dexon-foundation/mcl/.gitignore b/vendor/github.com/dexon-foundation/mcl/.gitignore
new file mode 100644
index 000000000..f5edb3706
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/.gitignore
@@ -0,0 +1,13 @@
+CVS
+java/*_wrap.cxx
+lib/*.so
+lib/*.a
+*.class
+GPATH
+GRTAGS
+GTAGS
+*.o
+*.d
+*.exe
+*.swp
+.cvsignore
diff --git a/vendor/github.com/dexon-foundation/mcl/.travis.yml b/vendor/github.com/dexon-foundation/mcl/.travis.yml
new file mode 100644
index 000000000..73a97e6aa
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/.travis.yml
@@ -0,0 +1,17 @@
+sudo: true
+dist: trusty
+language: cpp
+compiler:
+ - gcc
+ - clang
+addons:
+ apt:
+ packages:
+ - libgmp-dev
+script:
+ - make test_ci DEBUG=1 -j3
+ - make clean
+ - make test_ci CFLAGS_USER=-DMCL_DONT_USE_XBYAK -j3
+ - make clean
+ - make test_go
+
diff --git a/vendor/github.com/dexon-foundation/mcl/CMakeLists.txt b/vendor/github.com/dexon-foundation/mcl/CMakeLists.txt
index 8ac418098..aaa0a8cf2 100644
--- a/vendor/github.com/dexon-foundation/mcl/CMakeLists.txt
+++ b/vendor/github.com/dexon-foundation/mcl/CMakeLists.txt
@@ -36,6 +36,10 @@ else()
add_definitions(-DMCL_USE_LLVM=1)
set(SRCS ${SRCS} src/asm/aarch64.s)
set(CPU arch64)
+ elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm")
+ add_definitions(-DMCL_USE_LLVM=1)
+ set(SRCS ${SRCS} src/asm/arm.s)
+ set(CPU arm)
elseif(APPLE)
add_definitions(-DMCL_USE_LLVM=1)
set(SRCS ${SRCS} src/asm/x86-64mac.s src/asm/x86-64mac.bmi2.s)
@@ -85,18 +89,20 @@ include_directories(
)
add_library(mcl STATIC ${SRCS})
-if(NOT MSVC)
add_library(mcl_dy SHARED ${SRCS})
-endif()
+target_link_libraries(mcl_dy ${LIBS})
+set_target_properties(mcl_dy PROPERTIES OUTPUT_NAME mcl)
+#set_target_properties(mcl_dy PROPERTIES OUTPUT_NAME mcl VERSION 1.0.0 SOVERSION 1)
+# For semantics of ABI compatibility including when you must bump SOVERSION, see:
+# https://community.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B#The_Do.27s_and_Don.27ts
-file(GLOB MCL_HEADERS include/mcl/*.hpp include/mcl/*.h)
+file(GLOB MCL_HEADERS include/mcl/*.hpp include/mcl/bn.h include/mcl/curve_type.h)
file(GLOB CYBOZULIB_HEADERS include/cybozu/*.hpp)
install(TARGETS mcl DESTINATION lib)
-if(NOT MSVC)
install(TARGETS mcl_dy DESTINATION lib)
-endif()
install(FILES ${MCL_HEADERS} DESTINATION include/mcl)
+install(FILES include/mcl/impl/bn_c_impl.hpp DESTINATION include/mcl/impl)
install(FILES ${CYBOZULIB_HEADERS} DESTINATION include/cybozu)
set(TEST_BASE fp_test ec_test fp_util_test window_method_test elgamal_test fp_tower_test gmp_test bn_test glv_test)
diff --git a/vendor/github.com/dexon-foundation/mcl/Makefile b/vendor/github.com/dexon-foundation/mcl/Makefile
index fae248aba..7df1dd300 100644
--- a/vendor/github.com/dexon-foundation/mcl/Makefile
+++ b/vendor/github.com/dexon-foundation/mcl/Makefile
@@ -8,6 +8,7 @@ TEST_SRC+=bn_c256_test.cpp bn_c384_test.cpp bn_c384_256_test.cpp bn_c512_test.cp
TEST_SRC+=aggregate_sig_test.cpp array_test.cpp
TEST_SRC+=bls12_test.cpp
TEST_SRC+=ecdsa_c_test.cpp
+TEST_SRC+=modp_test.cpp
ifeq ($(CPU),x86-64)
MCL_USE_XBYAK?=1
TEST_SRC+=mont_fp_test.cpp sq_test.cpp
@@ -26,15 +27,14 @@ endif
ifeq ($(MCL_USE_XBYAK),0)
CFLAGS+=-DMCL_DONT_USE_XBYAK
endif
-SHARE_BASENAME_SUF?=_dy
##################################################################
MCL_LIB=$(LIB_DIR)/libmcl.a
-MCL_SNAME=mcl$(SHARE_BASENAME_SUF)
-BN256_SNAME=mclbn256$(SHARE_BASENAME_SUF)
-BN384_SNAME=mclbn384$(SHARE_BASENAME_SUF)
-BN384_256_SNAME=mclbn384_256$(SHARE_BASENAME_SUF)
-BN512_SNAME=mclbn512$(SHARE_BASENAME_SUF)
-SHE256_SNAME=mclshe256$(SHARE_BASENAME_SUF)
+MCL_SNAME=mcl
+BN256_SNAME=mclbn256
+BN384_SNAME=mclbn384
+BN384_256_SNAME=mclbn384_256
+BN512_SNAME=mclbn512
+SHE256_SNAME=mclshe256
MCL_SLIB=$(LIB_DIR)/lib$(MCL_SNAME).$(LIB_SUF)
BN256_LIB=$(LIB_DIR)/libmclbn256.a
BN256_SLIB=$(LIB_DIR)/lib$(BN256_SNAME).$(LIB_SUF)
@@ -45,9 +45,10 @@ BN384_256_SLIB=$(LIB_DIR)/lib$(BN384_256_SNAME).$(LIB_SUF)
BN512_LIB=$(LIB_DIR)/libmclbn512.a
BN512_SLIB=$(LIB_DIR)/lib$(BN512_SNAME).$(LIB_SUF)
SHE256_LIB=$(LIB_DIR)/libmclshe256.a
+SHE256_SLIB=$(LIB_DIR)/lib$(SHE256_SNAME).$(LIB_SUF)
SHE384_LIB=$(LIB_DIR)/libmclshe384.a
ECDSA_LIB=$(LIB_DIR)/libmclecdsa.a
-all: $(MCL_LIB) $(MCL_SLIB) $(BN256_LIB) $(BN256_SLIB) $(BN384_LIB) $(BN384_SLIB) $(BN384_256_LIB) $(BN384_256_SLIB) $(BN512_LIB) $(BN512_SLIB) $(SHE256_LIB) $(SHE384_lib) $(ECDSA_LIB)
+all: $(MCL_LIB) $(MCL_SLIB) $(BN256_LIB) $(BN256_SLIB) $(BN384_LIB) $(BN384_SLIB) $(BN384_256_LIB) $(BN384_256_SLIB) $(BN512_LIB) $(BN512_SLIB) $(SHE256_LIB) $(SHE256_SLIB) $(SHE384_lib) $(ECDSA_LIB)
#LLVM_VER=-3.8
LLVM_LLC=llc$(LLVM_VER)
@@ -121,6 +122,7 @@ ifneq ($(findstring $(OS),mac/mingw64),)
BN384_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib
BN384_256_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib
BN512_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib
+ SHE256_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib
endif
ifeq ($(OS),mingw64)
MCL_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(MCL_SNAME).a
@@ -128,6 +130,7 @@ ifeq ($(OS),mingw64)
BN384_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(BN384_SNAME).a
BN384_256_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(BN384_256_SNAME).a
BN512_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(BN512_SNAME).a
+ SHE256_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(SHE256_SNAME).a
endif
$(MCL_LIB): $(LIB_OBJ)
@@ -142,6 +145,9 @@ $(BN256_LIB): $(BN256_OBJ)
$(SHE256_LIB): $(SHE256_OBJ)
$(AR) $@ $(SHE256_OBJ)
+$(SHE256_SLIB): $(SHE256_OBJ) $(MCL_LIB)
+ $(PRE)$(CXX) -o $@ $(SHE256_OBJ) $(MCL_LIB) -shared $(LDFLAGS) $(SHE256_SLIB_LDFLAGS)
+
$(SHE384_LIB): $(SHE384_OBJ)
$(AR) $@ $(SHE384_OBJ)
@@ -199,7 +205,7 @@ else
endif
$(GEN_EXE): src/gen.cpp src/llvm_gen.hpp
- $(CXX) -o $@ $< $(CFLAGS) -O0
+ $(CXX) -o $@ $< $(CFLAGS)
asm: $(LLVM_SRC)
$(LLVM_OPT) -O3 -o - $(LLVM_SRC) | $(LLVM_LLC) -O3 $(LLVM_FLAGS) -x86-asm-syntax=intel
@@ -207,21 +213,27 @@ asm: $(LLVM_SRC)
$(LOW_ASM_OBJ): $(LOW_ASM_SRC)
$(ASM) $<
-ifeq ($(OS),mac)
- MAC_GO_LDFLAGS="-ldflags=-s"
-endif
-# set PATH for mingw, set LD_RUN_PATH is for other env
+# set PATH for mingw, set LD_LIBRARY_PATH is for other env
+COMMON_LIB_PATH="../../../lib"
+PATH_VAL=$$PATH:$(COMMON_LIB_PATH) LD_LIBRARY_PATH=$(COMMON_LIB_PATH) DYLD_LIBRARY_PATH=$(COMMON_LIB_PATH) CGO_CFLAGS="-I$(shell pwd)/include" CGO_LDFLAGS="-L../../../lib"
test_go256: $(MCL_SLIB) $(BN256_SLIB)
-# cd ffi/go/mcl && env PATH="$$PATH:../../../lib" LD_RUN_PATH="../../../lib" CGO_LDFLAGS="-L../../../lib -l$(BN256_SNAME) -l$(MCL_SNAME) -lgmpxx -lgmp -lcrypto -lstdc++" go test $(MAC_GO_LDFLAGS) -tags bn256 .
- cd ffi/go/mcl && env PATH="$$PATH:../../../lib" LD_RUN_PATH="../../../lib" go test $(MAC_GO_LDFLAGS) -tags bn256 .
+ cd ffi/go/mcl && env PATH=$(PATH_VAL) go test -tags bn256 .
test_go384: $(MCL_SLIB) $(BN384_SLIB)
-# cd ffi/go/mcl && env LD_RUN_PATH="../../../lib" CGO_CFLAGS="-I../../../include" CGO_LDFLAGS="-L../../../lib -l$(BN384_SNAME) -l$(MCL_SNAME) -lgmpxx -lgmp -lcrypto -lstdc++" go test $(MAC_GO_LDFLAGS) .
- cd ffi/go/mcl && env PATH="$$PATH:../../../lib" LD_RUN_PATH="../../../lib" go test $(MAC_GO_LDFLAGS) -tags bn384 .
+ cd ffi/go/mcl && env PATH=$(PATH_VAL) go test -tags bn384 .
+
+test_go384_256: $(MCL_SLIB) $(BN384_256_SLIB)
+ cd ffi/go/mcl && env PATH=$(PATH_VAL) go test -tags bn384_256 .
test_go:
$(MAKE) test_go256
$(MAKE) test_go384
+ $(MAKE) test_go384_256
+
+test_python_she: $(SHE256_SLIB)
+ cd ffi/python && env LD_LIBRARY_PATH="../../lib" DYLD_LIBRARY_PATH="../../lib" PATH=$$PATH:"../../lib" python3 she.py
+test_python:
+ $(MAKE) test_python_she
test_java:
$(MAKE) -C ffi/java test
@@ -265,10 +277,18 @@ $(EXE_DIR)/she_c384_test.exe: $(OBJ_DIR)/she_c384_test.o $(SHE384_LIB) $(MCL_LIB
$(EXE_DIR)/ecdsa_c_test.exe: $(OBJ_DIR)/ecdsa_c_test.o $(ECDSA_LIB) $(MCL_LIB) src/ecdsa_c.cpp include/mcl/ecdsa.hpp include/mcl/ecdsa.h
$(PRE)$(CXX) $< -o $@ $(ECDSA_LIB) $(MCL_LIB) $(LDFLAGS)
+$(OBJ_DIR)/modp_test.o: test/modp_test.cpp
+ $(PRE)$(CXX) -c $< -o $@ -MMD -MP -MF $(@:.o=.d) -DMCL_USE_VINT -DMCL_MAX_BIT_SIZE=384 -DMCL_VINT_64BIT_PORTABLE -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_FIXED_BUFFER -I./include -O2 $(CFLAGS_WARN)
+
+$(EXE_DIR)/modp_test.exe: $(OBJ_DIR)/modp_test.o
+ $(PRE)$(CXX) $< -o $@
+
SAMPLE_EXE=$(addprefix $(EXE_DIR)/,$(addsuffix .exe,$(basename $(SAMPLE_SRC))))
sample: $(SAMPLE_EXE) $(MCL_LIB)
TEST_EXE=$(addprefix $(EXE_DIR)/,$(TEST_SRC:.cpp=.exe))
+test_ci: $(TEST_EXE)
+ @sh -ec 'for i in $(TEST_EXE); do echo $$i; env LSAN_OPTIONS=verbosity=1:log_threads=1 $$i; done'
test: $(TEST_EXE)
@echo test $(TEST_EXE)
@sh -ec 'for i in $(TEST_EXE); do $$i|grep "ctest:name"; done' > result.txt
@@ -279,8 +299,8 @@ EMCC_OPT+=-O3 -DNDEBUG -DMCLSHE_WIN_SIZE=8
EMCC_OPT+=-s WASM=1 -s NO_EXIT_RUNTIME=1 -s MODULARIZE=1 #-s ASSERTIONS=1
EMCC_OPT+=-DCYBOZU_MINIMUM_EXCEPTION
EMCC_OPT+=-s ABORTING_MALLOC=0
-SHE_C_DEP=src/fp.cpp src/she_c_impl.hpp include/mcl/she.hpp include/mcl/she.h Makefile
-MCL_C_DEP=src/fp.cpp src/bn_c_impl.hpp include/mcl/bn.hpp include/mcl/bn.h Makefile
+SHE_C_DEP=src/fp.cpp src/she_c_impl.hpp include/mcl/she.hpp include/mcl/fp.hpp include/mcl/op.hpp include/mcl/she.h Makefile
+MCL_C_DEP=src/fp.cpp include/mcl/impl/bn_c_impl.hpp include/mcl/bn.hpp include/mcl/fp.hpp include/mcl/op.hpp include/mcl/bn.h Makefile
ifeq ($(MCL_USE_LLVM),2)
EMCC_OPT+=src/base64m.ll -DMCL_USE_LLVM
SHE_C_DEP+=src/base64m.ll
@@ -328,21 +348,23 @@ make_tbl:
update_xbyak:
cp -a ../xbyak/xbyak/xbyak.h ../xbyak/xbyak/xbyak_util.h ../xbyak/xbyak/xbyak_mnemonic.h src/xbyak/
+update_cybozulib:
+ cp -a $(addprefix ../cybozulib/,$(wildcard include/cybozu/*.hpp)) include/cybozu/
clean:
- $(RM) $(LIB_DIR)/*.a $(EXE_DIR)/*.$(LIB_SUF) $(OBJ_DIR)/*.o $(OBJ_DIR)/*.d $(EXE_DIR)/*.exe $(GEN_EXE) $(ASM_OBJ) $(LIB_OBJ) $(BN256_OBJ) $(BN384_OBJ) $(BN512_OBJ) $(LLVM_SRC) $(FUNC_LIST) src/*.ll lib/*.a
+ $(RM) $(LIB_DIR)/*.a $(LIB_DIR)/*.$(LIB_SUF) $(OBJ_DIR)/*.o $(OBJ_DIR)/*.obj $(OBJ_DIR)/*.d $(EXE_DIR)/*.exe $(GEN_EXE) $(ASM_OBJ) $(LIB_OBJ) $(BN256_OBJ) $(BN384_OBJ) $(BN512_OBJ) $(LLVM_SRC) $(FUNC_LIST) src/*.ll lib/*.a
ALL_SRC=$(SRC_SRC) $(TEST_SRC) $(SAMPLE_SRC)
DEPEND_FILE=$(addprefix $(OBJ_DIR)/, $(addsuffix .d,$(basename $(ALL_SRC))))
-include $(DEPEND_FILE)
PREFIX?=/usr/local
-install: lib/libmcl.a lib/libmcl$(SHARE_BASENAME_SUF).$(LIB_SUF)
+install: lib/libmcl.a lib/libmcl.$(LIB_SUF)
$(MKDIR) $(PREFIX)/include/mcl
cp -a include/mcl/ $(PREFIX)/include/
cp -a include/cybozu/ $(PREFIX)/include/
$(MKDIR) $(PREFIX)/lib
- cp -a lib/libmcl.a lib/libmcl$(SHARE_BASENAME_SUF).$(LIB_SUF) $(PREFIX)/lib/
+ cp -a lib/libmcl.a lib/libmcl.$(LIB_SUF) $(PREFIX)/lib/
.PHONY: test mcl-wasm she-wasm bin/emu
diff --git a/vendor/github.com/dexon-foundation/mcl/common.mk b/vendor/github.com/dexon-foundation/mcl/common.mk
index a05f5c9cb..5c749e1a6 100644
--- a/vendor/github.com/dexon-foundation/mcl/common.mk
+++ b/vendor/github.com/dexon-foundation/mcl/common.mk
@@ -78,7 +78,7 @@ else
endif
ifeq ($(MARCH),)
ifeq ($(INTEL),1)
- CFLAGS_OPT+=-march=native
+# CFLAGS_OPT+=-march=native
endif
else
CFLAGS_OPT+=$(MARCH)
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/cs/App.config b/vendor/github.com/dexon-foundation/mcl/ffi/cs/App.config
new file mode 100644
index 000000000..88fa4027b
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/cs/App.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+ <startup>
+ <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
+ </startup>
+</configuration> \ No newline at end of file
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/cs/Properties/AssemblyInfo.cs b/vendor/github.com/dexon-foundation/mcl/ffi/cs/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..c87e1d44b
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/cs/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// アセンブリã«é–¢ã™ã‚‹ä¸€èˆ¬æƒ…å ±ã¯ä»¥ä¸‹ã®å±žæ€§ã‚»ãƒƒãƒˆã‚’ã¨ãŠã—ã¦åˆ¶å¾¡ã•ã‚Œã¾ã™ã€‚
+// アセンブリã«é–¢é€£ä»˜ã‘られã¦ã„る情報を変更ã™ã‚‹ã«ã¯ã€
+// ã“れらã®å±žæ€§å€¤ã‚’変更ã—ã¦ãã ã•ã„。
+[assembly: AssemblyTitle("bn256")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("bn256")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// ComVisible ã‚’ false ã«è¨­å®šã™ã‚‹ã¨ã€ãã®åž‹ã¯ã“ã®ã‚¢ã‚»ãƒ³ãƒ–リ内㧠COM コンãƒãƒ¼ãƒãƒ³ãƒˆã‹ã‚‰
+// å‚ç…§ä¸å¯èƒ½ã«ãªã‚Šã¾ã™ã€‚COM ã‹ã‚‰ã“ã®ã‚¢ã‚»ãƒ³ãƒ–リ内ã®åž‹ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹å ´åˆã¯ã€
+// ãã®åž‹ã® ComVisible 属性を true ã«è¨­å®šã—ã¦ãã ã•ã„。
+[assembly: ComVisible(false)]
+
+// ã“ã®ãƒ—ロジェクト㌠COM ã«å…¬é–‹ã•ã‚Œã‚‹å ´åˆã€æ¬¡ã® GUID ㌠typelib ã® ID ã«ãªã‚Šã¾ã™
+[assembly: Guid("e9d06b1b-ea22-4ef4-ba4b-422f7625966b")]
+
+// アセンブリã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã¯æ¬¡ã® 4 ã¤ã®å€¤ã§æ§‹æˆã•ã‚Œã¦ã„ã¾ã™:
+//
+// メジャー ãƒãƒ¼ã‚¸ãƒ§ãƒ³
+// マイナー ãƒãƒ¼ã‚¸ãƒ§ãƒ³
+// ビルド番å·
+// Revision
+//
+// ã™ã¹ã¦ã®å€¤ã‚’指定ã™ã‚‹ã‹ã€ä¸‹ã®ã‚ˆã†ã« '*' を使ã£ã¦ãƒ“ルドãŠã‚ˆã³ãƒªãƒ“ジョン番å·ã‚’
+// 既定値ã«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.cs b/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.cs
new file mode 100644
index 000000000..0e1ed032c
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.cs
@@ -0,0 +1,475 @@
+using System;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace mcl {
+ public class BN256 {
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBn_init(int curve, int maxUnitSize);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnFr_clear(ref Fr x);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnFr_setInt(ref Fr y, int x);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnFr_setStr(ref Fr x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize, int ioMode);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnFr_isValid(ref Fr x);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnFr_isEqual(ref Fr x, ref Fr y);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnFr_isZero(ref Fr x);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnFr_isOne(ref Fr x);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnFr_setByCSPRNG(ref Fr x);
+
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnFr_setHashOf(ref Fr x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnFr_getStr([Out]StringBuilder buf, long maxBufSize, ref Fr x, int ioMode);
+
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnFr_neg(ref Fr y, ref Fr x);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnFr_inv(ref Fr y, ref Fr x);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnFr_add(ref Fr z, ref Fr x, ref Fr y);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnFr_sub(ref Fr z, ref Fr x, ref Fr y);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnFr_mul(ref Fr z, ref Fr x, ref Fr y);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnFr_div(ref Fr z, ref Fr x, ref Fr y);
+
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnG1_clear(ref G1 x);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnG1_setStr(ref G1 x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize, int ioMode);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnG1_isValid(ref G1 x);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnG1_isEqual(ref G1 x, ref G1 y);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnG1_isZero(ref G1 x);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnG1_hashAndMapTo(ref G1 x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize);
+ [DllImport("mclBn256.dll")]
+ public static extern long mclBnG1_getStr([Out]StringBuilder buf, long maxBufSize, ref G1 x, int ioMode);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnG1_neg(ref G1 y, ref G1 x);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnG1_dbl(ref G1 y, ref G1 x);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnG1_add(ref G1 z, ref G1 x, ref G1 y);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnG1_sub(ref G1 z, ref G1 x, ref G1 y);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnG1_mul(ref G1 z, ref G1 x, ref Fr y);
+
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnG2_clear(ref G2 x);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnG2_setStr(ref G2 x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize, int ioMode);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnG2_isValid(ref G2 x);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnG2_isEqual(ref G2 x, ref G2 y);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnG2_isZero(ref G2 x);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnG2_hashAndMapTo(ref G2 x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize);
+ [DllImport("mclBn256.dll")]
+ public static extern long mclBnG2_getStr([Out]StringBuilder buf, long maxBufSize, ref G2 x, int ioMode);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnG2_neg(ref G2 y, ref G2 x);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnG2_dbl(ref G2 y, ref G2 x);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnG2_add(ref G2 z, ref G2 x, ref G2 y);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnG2_sub(ref G2 z, ref G2 x, ref G2 y);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnG2_mul(ref G2 z, ref G2 x, ref Fr y);
+
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnGT_clear(ref GT x);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnGT_setStr(ref GT x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize, int ioMode);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnGT_isEqual(ref GT x, ref GT y);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnGT_isZero(ref GT x);
+ [DllImport("mclBn256.dll")]
+ public static extern int mclBnGT_isOne(ref GT x);
+ [DllImport("mclBn256.dll")]
+ public static extern long mclBnGT_getStr([Out]StringBuilder buf, long maxBufSize, ref GT x, int ioMode);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnGT_neg(ref GT y, ref GT x);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnGT_inv(ref GT y, ref GT x);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnGT_add(ref GT z, ref GT x, ref GT y);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnGT_sub(ref GT z, ref GT x, ref GT y);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnGT_mul(ref GT z, ref GT x, ref GT y);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnGT_div(ref GT z, ref GT x, ref GT y);
+
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBnGT_pow(ref GT z, ref GT x, ref Fr y);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBn_pairing(ref GT z, ref G1 x, ref G2 y);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBn_finalExp(ref GT y, ref GT x);
+ [DllImport("mclBn256.dll")]
+ public static extern void mclBn_millerLoop(ref GT z, ref G1 x, ref G2 y);
+
+ public static void init()
+ {
+ const int curveFp254BNb = 0;
+ const int maxUnitSize = 4;
+ if (mclBn_init(curveFp254BNb, maxUnitSize) != 0) {
+ throw new InvalidOperationException("mclBn_init");
+ }
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Fr {
+ private ulong v0, v1, v2, v3;
+ public void Clear()
+ {
+ mclBnFr_clear(ref this);
+ }
+ public void SetInt(int x)
+ {
+ mclBnFr_setInt(ref this, x);
+ }
+ public void SetStr(string s, int ioMode)
+ {
+ if (mclBnFr_setStr(ref this, s, s.Length, ioMode) != 0) {
+ throw new ArgumentException("mclBnFr_setStr" + s);
+ }
+ }
+ public bool IsValid()
+ {
+ return mclBnFr_isValid(ref this) == 1;
+ }
+ public bool Equals(Fr rhs)
+ {
+ return mclBnFr_isEqual(ref this, ref rhs) == 1;
+ }
+ public bool IsZero()
+ {
+ return mclBnFr_isZero(ref this) == 1;
+ }
+ public bool IsOne()
+ {
+ return mclBnFr_isOne(ref this) == 1;
+ }
+ public void SetByCSPRNG()
+ {
+ mclBnFr_setByCSPRNG(ref this);
+ }
+ public void SetHashOf(String s)
+ {
+ if (mclBnFr_setHashOf(ref this, s, s.Length) != 0) {
+ throw new InvalidOperationException("mclBnFr_setHashOf:" + s);
+ }
+ }
+ public string GetStr(int ioMode)
+ {
+ StringBuilder sb = new StringBuilder(1024);
+ long size = mclBnFr_getStr(sb, sb.Capacity, ref this, ioMode);
+ if (size == 0) {
+ throw new InvalidOperationException("mclBnFr_getStr:");
+ }
+ return sb.ToString();
+ }
+ public void Neg(Fr x)
+ {
+ mclBnFr_neg(ref this, ref x);
+ }
+ public void Inv(Fr x)
+ {
+ mclBnFr_inv(ref this, ref x);
+ }
+ public void Add(Fr x, Fr y)
+ {
+ mclBnFr_add(ref this, ref x, ref y);
+ }
+ public void Sub(Fr x, Fr y)
+ {
+ mclBnFr_sub(ref this, ref x, ref y);
+ }
+ public void Mul(Fr x, Fr y)
+ {
+ mclBnFr_mul(ref this, ref x, ref y);
+ }
+ public void Div(Fr x, Fr y)
+ {
+ mclBnFr_div(ref this, ref x, ref y);
+ }
+ public static Fr operator -(Fr x)
+ {
+ Fr y = new Fr();
+ y.Neg(x);
+ return y;
+ }
+ public static Fr operator +(Fr x, Fr y)
+ {
+ Fr z = new Fr();
+ z.Add(x, y);
+ return z;
+ }
+ public static Fr operator -(Fr x, Fr y)
+ {
+ Fr z = new Fr();
+ z.Sub(x, y);
+ return z;
+ }
+ public static Fr operator *(Fr x, Fr y)
+ {
+ Fr z = new Fr();
+ z.Mul(x, y);
+ return z;
+ }
+ public static Fr operator /(Fr x, Fr y)
+ {
+ Fr z = new Fr();
+ z.Div(x, y);
+ return z;
+ }
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ public struct G1 {
+ private ulong v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11;
+ public void Clear()
+ {
+ mclBnG1_clear(ref this);
+ }
+ public void setStr(String s, int ioMode)
+ {
+ if (mclBnG1_setStr(ref this, s, s.Length, ioMode) != 0) {
+ throw new ArgumentException("mclBnG1_setStr:" + s);
+ }
+ }
+ public bool IsValid()
+ {
+ return mclBnG1_isValid(ref this) == 1;
+ }
+ public bool Equals(G1 rhs)
+ {
+ return mclBnG1_isEqual(ref this, ref rhs) == 1;
+ }
+ public bool IsZero()
+ {
+ return mclBnG1_isZero(ref this) == 1;
+ }
+ public void HashAndMapTo(String s)
+ {
+ if (mclBnG1_hashAndMapTo(ref this, s, s.Length) != 0) {
+ throw new ArgumentException("mclBnG1_hashAndMapTo:" + s);
+ }
+ }
+ public string GetStr(int ioMode)
+ {
+ StringBuilder sb = new StringBuilder(1024);
+ long size = mclBnG1_getStr(sb, sb.Capacity, ref this, ioMode);
+ if (size == 0) {
+ throw new InvalidOperationException("mclBnG1_getStr:");
+ }
+ return sb.ToString();
+ }
+ public void Neg(G1 x)
+ {
+ mclBnG1_neg(ref this, ref x);
+ }
+ public void Dbl(G1 x)
+ {
+ mclBnG1_dbl(ref this, ref x);
+ }
+ public void Add(G1 x, G1 y)
+ {
+ mclBnG1_add(ref this, ref x, ref y);
+ }
+ public void Sub(G1 x, G1 y)
+ {
+ mclBnG1_sub(ref this, ref x, ref y);
+ }
+ public void Mul(G1 x, Fr y)
+ {
+ mclBnG1_mul(ref this, ref x, ref y);
+ }
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ public struct G2 {
+ private ulong v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11;
+ private ulong v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23;
+ public void Clear()
+ {
+ mclBnG2_clear(ref this);
+ }
+ public void setStr(String s, int ioMode)
+ {
+ if (mclBnG2_setStr(ref this, s, s.Length, ioMode) != 0) {
+ throw new ArgumentException("mclBnG2_setStr:" + s);
+ }
+ }
+ public bool IsValid()
+ {
+ return mclBnG2_isValid(ref this) == 1;
+ }
+ public bool Equals(G2 rhs)
+ {
+ return mclBnG2_isEqual(ref this, ref rhs) == 1;
+ }
+ public bool IsZero()
+ {
+ return mclBnG2_isZero(ref this) == 1;
+ }
+ public void HashAndMapTo(String s)
+ {
+ if (mclBnG2_hashAndMapTo(ref this, s, s.Length) != 0) {
+ throw new ArgumentException("mclBnG2_hashAndMapTo:" + s);
+ }
+ }
+ public string GetStr(int ioMode)
+ {
+ StringBuilder sb = new StringBuilder(1024);
+ long size = mclBnG2_getStr(sb, sb.Capacity, ref this, ioMode);
+ if (size == 0) {
+ throw new InvalidOperationException("mclBnG2_getStr:");
+ }
+ return sb.ToString();
+ }
+ public void Neg(G2 x)
+ {
+ mclBnG2_neg(ref this, ref x);
+ }
+ public void Dbl(G2 x)
+ {
+ mclBnG2_dbl(ref this, ref x);
+ }
+ public void Add(G2 x, G2 y)
+ {
+ mclBnG2_add(ref this, ref x, ref y);
+ }
+ public void Sub(G2 x, G2 y)
+ {
+ mclBnG2_sub(ref this, ref x, ref y);
+ }
+ public void Mul(G2 x, Fr y)
+ {
+ mclBnG2_mul(ref this, ref x, ref y);
+ }
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ public struct GT {
+ private ulong v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11;
+ private ulong v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23;
+ private ulong v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35;
+ private ulong v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47;
+ public void Clear()
+ {
+ mclBnGT_clear(ref this);
+ }
+ public void setStr(String s, int ioMode)
+ {
+ if (mclBnGT_setStr(ref this, s, s.Length, ioMode) != 0) {
+ throw new ArgumentException("mclBnGT_setStr:" + s);
+ }
+ }
+ public bool Equals(GT rhs)
+ {
+ return mclBnGT_isEqual(ref this, ref rhs) == 1;
+ }
+ public bool IsZero()
+ {
+ return mclBnGT_isZero(ref this) == 1;
+ }
+ public bool IsOne()
+ {
+ return mclBnGT_isOne(ref this) == 1;
+ }
+ public string GetStr(int ioMode)
+ {
+ StringBuilder sb = new StringBuilder(1024);
+ long size = mclBnGT_getStr(sb, sb.Capacity, ref this, ioMode);
+ if (size == 0) {
+ throw new InvalidOperationException("mclBnGT_getStr:");
+ }
+ return sb.ToString();
+ }
+ public void Neg(GT x)
+ {
+ mclBnGT_neg(ref this, ref x);
+ }
+ public void Inv(GT x)
+ {
+ mclBnGT_inv(ref this, ref x);
+ }
+ public void Add(GT x, GT y)
+ {
+ mclBnGT_add(ref this, ref x, ref y);
+ }
+ public void Sub(GT x, GT y)
+ {
+ mclBnGT_sub(ref this, ref x, ref y);
+ }
+ public void Mul(GT x, GT y)
+ {
+ mclBnGT_mul(ref this, ref x, ref y);
+ }
+ public void Div(GT x, GT y)
+ {
+ mclBnGT_div(ref this, ref x, ref y);
+ }
+ public static GT operator -(GT x)
+ {
+ GT y = new GT();
+ y.Neg(x);
+ return y;
+ }
+ public static GT operator +(GT x, GT y)
+ {
+ GT z = new GT();
+ z.Add(x, y);
+ return z;
+ }
+ public static GT operator -(GT x, GT y)
+ {
+ GT z = new GT();
+ z.Sub(x, y);
+ return z;
+ }
+ public static GT operator *(GT x, GT y)
+ {
+ GT z = new GT();
+ z.Mul(x, y);
+ return z;
+ }
+ public static GT operator /(GT x, GT y)
+ {
+ GT z = new GT();
+ z.Div(x, y);
+ return z;
+ }
+ public void Pow(GT x, Fr y)
+ {
+ mclBnGT_pow(ref this, ref x, ref y);
+ }
+ public void Pairing(G1 x, G2 y)
+ {
+ mclBn_pairing(ref this, ref x, ref y);
+ }
+ public void FinalExp(GT x)
+ {
+ mclBn_finalExp(ref this, ref x);
+ }
+ public void MillerLoop(G1 x, G2 y)
+ {
+ mclBn_millerLoop(ref this, ref x, ref y);
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.csproj b/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.csproj
new file mode 100644
index 000000000..21a049f01
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.csproj
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{E9D06B1B-EA22-4EF4-BA4B-422F7625966B}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>bn256</RootNamespace>
+ <AssemblyName>bn256</AssemblyName>
+ <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>..\..\bin\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ <OutputPath>..\..\bin\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="bn256.cs" />
+ <Compile Include="bn256_test.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.sln b/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.sln
new file mode 100644
index 000000000..6e6aa67ee
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bn256", "bn256.csproj", "{E9D06B1B-EA22-4EF4-BA4B-422F7625966B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E9D06B1B-EA22-4EF4-BA4B-422F7625966B}.Debug|x64.ActiveCfg = Debug|x64
+ {E9D06B1B-EA22-4EF4-BA4B-422F7625966B}.Debug|x64.Build.0 = Debug|x64
+ {E9D06B1B-EA22-4EF4-BA4B-422F7625966B}.Release|x64.ActiveCfg = Release|x64
+ {E9D06B1B-EA22-4EF4-BA4B-422F7625966B}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256_test.cs b/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256_test.cs
new file mode 100644
index 000000000..cad8c03d3
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256_test.cs
@@ -0,0 +1,149 @@
+using System;
+
+namespace mcl {
+ using static BN256;
+ class BN256Test {
+ static int err = 0;
+ static void assert(string msg, bool b)
+ {
+ if (b) return;
+ Console.WriteLine("ERR {0}", msg);
+ err++;
+ }
+ static void Main(string[] args)
+ {
+ try {
+ assert("64bit system", System.Environment.Is64BitProcess);
+ init();
+ TestFr();
+ TestG1();
+ TestG2();
+ TestPairing();
+ if (err == 0) {
+ Console.WriteLine("all tests succeed");
+ } else {
+ Console.WriteLine("err={0}", err);
+ }
+ } catch (Exception e) {
+ Console.WriteLine("ERR={0}", e);
+ }
+ }
+ static void TestFr()
+ {
+ Console.WriteLine("TestFr");
+ Fr x = new Fr();
+ x.Clear();
+ assert("0", x.GetStr(10) == "0");
+ assert("0.IzZero", x.IsZero());
+ assert("!0.IzOne", !x.IsOne());
+ x.SetInt(1);
+ assert("1", x.GetStr(10) == "1");
+ assert("!1.IzZero", !x.IsZero());
+ assert("1.IzOne", x.IsOne());
+ x.SetInt(3);
+ assert("3", x.GetStr(10) == "3");
+ assert("!3.IzZero", !x.IsZero());
+ assert("!3.IzOne", !x.IsOne());
+ x.SetInt(-5);
+ x = -x;
+ assert("5", x.GetStr(10) == "5");
+ x.SetInt(4);
+ x = x * x;
+ assert("16", x.GetStr(10) == "16");
+ assert("10", x.GetStr(16) == "10");
+ Fr y;
+ y = x;
+ assert("x == y", x.Equals(y));
+ x.SetInt(123);
+ assert("123", x.GetStr(10) == "123");
+ assert("7b", x.GetStr(16) == "7b");
+ assert("y != x", !x.Equals(y));
+ try {
+ x.SetStr("1234567891234x", 10);
+ Console.WriteLine("x = {0}", x);
+ } catch (Exception e) {
+ Console.WriteLine("exception test OK\n'{0}'", e);
+ }
+ x.SetStr("1234567891234", 10);
+ assert("1234567891234", x.GetStr(10) == "1234567891234");
+ }
+ static void TestG1()
+ {
+ Console.WriteLine("TestG1");
+ G1 P = new G1();
+ P.Clear();
+ assert("P.IsValid", P.IsValid());
+ assert("P.IsZero", P.IsZero());
+ P.HashAndMapTo("abc");
+ assert("P.IsValid", P.IsValid());
+ assert("!P.IsZero", !P.IsZero());
+ G1 Q = new G1();
+ Q = P;
+ assert("P == Q", Q.Equals(P));
+ Q.Neg(P);
+ Q.Add(Q, P);
+ assert("P = Q", Q.IsZero());
+ Q.Dbl(P);
+ G1 R = new G1();
+ R.Add(P, P);
+ assert("Q == R", Q.Equals(R));
+ Fr x = new Fr();
+ x.SetInt(3);
+ R.Add(R, P);
+ Q.Mul(P, x);
+ assert("Q == R", Q.Equals(R));
+ }
+ static void TestG2()
+ {
+ Console.WriteLine("TestG2");
+ G2 P = new G2();
+ P.Clear();
+ assert("P is valid", P.IsValid());
+ assert("P is zero", P.IsZero());
+ P.HashAndMapTo("abc");
+ assert("P is valid", P.IsValid());
+ assert("P is not zero", !P.IsZero());
+ G2 Q = new G2();
+ Q = P;
+ assert("P == Q", Q.Equals(P));
+ Q.Neg(P);
+ Q.Add(Q, P);
+ assert("Q is zero", Q.IsZero());
+ Q.Dbl(P);
+ G2 R = new G2();
+ R.Add(P, P);
+ assert("Q == R", Q.Equals(R));
+ Fr x = new Fr();
+ x.SetInt(3);
+ R.Add(R, P);
+ Q.Mul(P, x);
+ assert("Q == R", Q.Equals(R));
+ }
+ static void TestPairing()
+ {
+ Console.WriteLine("TestG2");
+ G1 P = new G1();
+ P.HashAndMapTo("123");
+ G2 Q = new G2();
+ Q.HashAndMapTo("1");
+ Fr a = new Fr();
+ Fr b = new Fr();
+ a.SetStr("12345678912345673453", 10);
+ b.SetStr("230498230982394243424", 10);
+ G1 aP = new G1();
+ G2 bQ = new G2();
+ aP.Mul(P, a);
+ bQ.Mul(Q, b);
+ GT e1 = new GT();
+ GT e2 = new GT();
+ GT e3 = new GT();
+ e1.Pairing(P, Q);
+ e2.Pairing(aP, Q);
+ e3.Pow(e1, a);
+ assert("e2.Equals(e3)", e2.Equals(e3));
+ e2.Pairing(P, bQ);
+ e3.Pow(e1, b);
+ assert("e2.Equals(e3)", e2.Equals(e3));
+ }
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/go/mcl/mcl.go b/vendor/github.com/dexon-foundation/mcl/ffi/go/mcl/mcl.go
new file mode 100644
index 000000000..a0c8bb4d3
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/go/mcl/mcl.go
@@ -0,0 +1,659 @@
+package mcl
+
+/*
+#cgo bn256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=4
+#cgo bn384 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6
+#cgo bn384_256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 -DMCLBN_FR_UNIT_SIZE=4
+#cgo bn256 LDFLAGS:-lmclbn256 -lmcl
+#cgo bn384 LDFLAGS:-lmclbn384 -lmcl
+#cgo bn384_256 LDFLAGS:-lmclbn384_256 -lmcl
+#include <mcl/bn.h>
+*/
+import "C"
+import "fmt"
+import "unsafe"
+
+// CurveFp254BNb -- 254 bit curve
+const CurveFp254BNb = C.mclBn_CurveFp254BNb
+
+// CurveFp382_1 -- 382 bit curve 1
+const CurveFp382_1 = C.mclBn_CurveFp382_1
+
+// CurveFp382_2 -- 382 bit curve 2
+const CurveFp382_2 = C.mclBn_CurveFp382_2
+
+// BLS12_381
+const BLS12_381 = C.MCL_BLS12_381
+
+// IoSerializeHexStr
+const IoSerializeHexStr = C.MCLBN_IO_SERIALIZE_HEX_STR
+
+// Init --
+// call this function before calling all the other operations
+// this function is not thread safe
+func Init(curve int) error {
+ err := C.mclBn_init(C.int(curve), C.MCLBN_COMPILED_TIME_VAR)
+ if err != 0 {
+ return fmt.Errorf("ERR mclBn_init curve=%d", curve)
+ }
+ return nil
+}
+
+// GetFrUnitSize() --
+func GetFrUnitSize() int {
+ return int(C.MCLBN_FR_UNIT_SIZE)
+}
+
+// GetFpUnitSize() --
+// same as GetMaxOpUnitSize()
+func GetFpUnitSize() int {
+ return int(C.MCLBN_FP_UNIT_SIZE)
+}
+
+// GetMaxOpUnitSize --
+func GetMaxOpUnitSize() int {
+ return int(C.MCLBN_FP_UNIT_SIZE)
+}
+
+// GetOpUnitSize --
+// the length of Fr is GetOpUnitSize() * 8 bytes
+func GetOpUnitSize() int {
+ return int(C.mclBn_getOpUnitSize())
+}
+
+// GetCurveOrder --
+// return the order of G1
+func GetCurveOrder() string {
+ buf := make([]byte, 1024)
+ // #nosec
+ n := C.mclBn_getCurveOrder((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)))
+ if n == 0 {
+ panic("implementation err. size of buf is small")
+ }
+ return string(buf[:n])
+}
+
+// GetFieldOrder --
+// return the characteristic of the field where a curve is defined
+func GetFieldOrder() string {
+ buf := make([]byte, 1024)
+ // #nosec
+ n := C.mclBn_getFieldOrder((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)))
+ if n == 0 {
+ panic("implementation err. size of buf is small")
+ }
+ return string(buf[:n])
+}
+
+// Fr --
+type Fr struct {
+ v C.mclBnFr
+}
+
+// getPointer --
+func (x *Fr) getPointer() (p *C.mclBnFr) {
+ // #nosec
+ return (*C.mclBnFr)(unsafe.Pointer(x))
+}
+
+// Clear --
+func (x *Fr) Clear() {
+ // #nosec
+ C.mclBnFr_clear(x.getPointer())
+}
+
+// SetInt64 --
+func (x *Fr) SetInt64(v int64) {
+ // #nosec
+ C.mclBnFr_setInt(x.getPointer(), C.int64_t(v))
+}
+
+// SetString --
+func (x *Fr) SetString(s string, base int) error {
+ buf := []byte(s)
+ // #nosec
+ err := C.mclBnFr_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base))
+ if err != 0 {
+ return fmt.Errorf("err mclBnFr_setStr %x", err)
+ }
+ return nil
+}
+
+// Deserialize --
+func (x *Fr) Deserialize(buf []byte) error {
+ // #nosec
+ err := C.mclBnFr_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
+ if err == 0 {
+ return fmt.Errorf("err mclBnFr_deserialize %x", buf)
+ }
+ return nil
+}
+
+// SetLittleEndian --
+func (x *Fr) SetLittleEndian(buf []byte) error {
+ // #nosec
+ err := C.mclBnFr_setLittleEndian(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
+ if err != 0 {
+ return fmt.Errorf("err mclBnFr_setLittleEndian %x", err)
+ }
+ return nil
+}
+
+// IsEqual --
+func (x *Fr) IsEqual(rhs *Fr) bool {
+ return C.mclBnFr_isEqual(x.getPointer(), rhs.getPointer()) == 1
+}
+
+// IsZero --
+func (x *Fr) IsZero() bool {
+ return C.mclBnFr_isZero(x.getPointer()) == 1
+}
+
+// IsOne --
+func (x *Fr) IsOne() bool {
+ return C.mclBnFr_isOne(x.getPointer()) == 1
+}
+
+// SetByCSPRNG --
+func (x *Fr) SetByCSPRNG() {
+ err := C.mclBnFr_setByCSPRNG(x.getPointer())
+ if err != 0 {
+ panic("err mclBnFr_setByCSPRNG")
+ }
+}
+
+// SetHashOf --
+func (x *Fr) SetHashOf(buf []byte) bool {
+ // #nosec
+ return C.mclBnFr_setHashOf(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) == 0
+}
+
+// GetString --
+func (x *Fr) GetString(base int) string {
+ buf := make([]byte, 2048)
+ // #nosec
+ n := C.mclBnFr_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base))
+ if n == 0 {
+ panic("err mclBnFr_getStr")
+ }
+ return string(buf[:n])
+}
+
+// Serialize --
+func (x *Fr) Serialize() []byte {
+ buf := make([]byte, 2048)
+ // #nosec
+ n := C.mclBnFr_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer())
+ if n == 0 {
+ panic("err mclBnFr_serialize")
+ }
+ return buf[:n]
+}
+
+// FrNeg --
+func FrNeg(out *Fr, x *Fr) {
+ C.mclBnFr_neg(out.getPointer(), x.getPointer())
+}
+
+// FrInv --
+func FrInv(out *Fr, x *Fr) {
+ C.mclBnFr_inv(out.getPointer(), x.getPointer())
+}
+
+// FrAdd --
+func FrAdd(out *Fr, x *Fr, y *Fr) {
+ C.mclBnFr_add(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// FrSub --
+func FrSub(out *Fr, x *Fr, y *Fr) {
+ C.mclBnFr_sub(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// FrMul --
+func FrMul(out *Fr, x *Fr, y *Fr) {
+ C.mclBnFr_mul(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// FrDiv --
+func FrDiv(out *Fr, x *Fr, y *Fr) {
+ C.mclBnFr_div(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// G1 --
+type G1 struct {
+ v C.mclBnG1
+}
+
+// getPointer --
+func (x *G1) getPointer() (p *C.mclBnG1) {
+ // #nosec
+ return (*C.mclBnG1)(unsafe.Pointer(x))
+}
+
+// Clear --
+func (x *G1) Clear() {
+ // #nosec
+ C.mclBnG1_clear(x.getPointer())
+}
+
+// SetString --
+func (x *G1) SetString(s string, base int) error {
+ buf := []byte(s)
+ // #nosec
+ err := C.mclBnG1_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base))
+ if err != 0 {
+ return fmt.Errorf("err mclBnG1_setStr %x", err)
+ }
+ return nil
+}
+
+// Deserialize --
+func (x *G1) Deserialize(buf []byte) error {
+ // #nosec
+ err := C.mclBnG1_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
+ if err == 0 {
+ return fmt.Errorf("err mclBnG1_deserialize %x", buf)
+ }
+ return nil
+}
+
+// IsEqual --
+func (x *G1) IsEqual(rhs *G1) bool {
+ return C.mclBnG1_isEqual(x.getPointer(), rhs.getPointer()) == 1
+}
+
+// IsZero --
+func (x *G1) IsZero() bool {
+ return C.mclBnG1_isZero(x.getPointer()) == 1
+}
+
+// HashAndMapTo --
+func (x *G1) HashAndMapTo(buf []byte) error {
+ // #nosec
+ err := C.mclBnG1_hashAndMapTo(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
+ if err != 0 {
+ return fmt.Errorf("err mclBnG1_hashAndMapTo %x", err)
+ }
+ return nil
+}
+
+// GetString --
+func (x *G1) GetString(base int) string {
+ buf := make([]byte, 2048)
+ // #nosec
+ n := C.mclBnG1_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base))
+ if n == 0 {
+ panic("err mclBnG1_getStr")
+ }
+ return string(buf[:n])
+}
+
+// Serialize --
+func (x *G1) Serialize() []byte {
+ buf := make([]byte, 2048)
+ // #nosec
+ n := C.mclBnG1_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer())
+ if n == 0 {
+ panic("err mclBnG1_serialize")
+ }
+ return buf[:n]
+}
+
+// G1Neg --
+func G1Neg(out *G1, x *G1) {
+ C.mclBnG1_neg(out.getPointer(), x.getPointer())
+}
+
+// G1Dbl --
+func G1Dbl(out *G1, x *G1) {
+ C.mclBnG1_dbl(out.getPointer(), x.getPointer())
+}
+
+// G1Add --
+func G1Add(out *G1, x *G1, y *G1) {
+ C.mclBnG1_add(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// G1Sub --
+func G1Sub(out *G1, x *G1, y *G1) {
+ C.mclBnG1_sub(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// G1Mul --
+func G1Mul(out *G1, x *G1, y *Fr) {
+ C.mclBnG1_mul(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// G1MulCT -- constant time (depending on bit lengh of y)
+func G1MulCT(out *G1, x *G1, y *Fr) {
+ C.mclBnG1_mulCT(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// G2 --
+type G2 struct {
+ v C.mclBnG2
+}
+
+// getPointer --
+func (x *G2) getPointer() (p *C.mclBnG2) {
+ // #nosec
+ return (*C.mclBnG2)(unsafe.Pointer(x))
+}
+
+// Clear --
+func (x *G2) Clear() {
+ // #nosec
+ C.mclBnG2_clear(x.getPointer())
+}
+
+// SetString --
+func (x *G2) SetString(s string, base int) error {
+ buf := []byte(s)
+ // #nosec
+ err := C.mclBnG2_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base))
+ if err != 0 {
+ return fmt.Errorf("err mclBnG2_setStr %x", err)
+ }
+ return nil
+}
+
+// Deserialize --
+func (x *G2) Deserialize(buf []byte) error {
+ // #nosec
+ err := C.mclBnG2_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
+ if err == 0 {
+ return fmt.Errorf("err mclBnG2_deserialize %x", buf)
+ }
+ return nil
+}
+
+// IsEqual --
+func (x *G2) IsEqual(rhs *G2) bool {
+ return C.mclBnG2_isEqual(x.getPointer(), rhs.getPointer()) == 1
+}
+
+// IsZero --
+func (x *G2) IsZero() bool {
+ return C.mclBnG2_isZero(x.getPointer()) == 1
+}
+
+// HashAndMapTo --
+func (x *G2) HashAndMapTo(buf []byte) error {
+ // #nosec
+ err := C.mclBnG2_hashAndMapTo(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
+ if err != 0 {
+ return fmt.Errorf("err mclBnG2_hashAndMapTo %x", err)
+ }
+ return nil
+}
+
+// GetString --
+func (x *G2) GetString(base int) string {
+ buf := make([]byte, 2048)
+ // #nosec
+ n := C.mclBnG2_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base))
+ if n == 0 {
+ panic("err mclBnG2_getStr")
+ }
+ return string(buf[:n])
+}
+
+// Serialize --
+func (x *G2) Serialize() []byte {
+ buf := make([]byte, 2048)
+ // #nosec
+ n := C.mclBnG2_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer())
+ if n == 0 {
+ panic("err mclBnG2_serialize")
+ }
+ return buf[:n]
+}
+
+// G2Neg --
+func G2Neg(out *G2, x *G2) {
+ C.mclBnG2_neg(out.getPointer(), x.getPointer())
+}
+
+// G2Dbl --
+func G2Dbl(out *G2, x *G2) {
+ C.mclBnG2_dbl(out.getPointer(), x.getPointer())
+}
+
+// G2Add --
+func G2Add(out *G2, x *G2, y *G2) {
+ C.mclBnG2_add(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// G2Sub --
+func G2Sub(out *G2, x *G2, y *G2) {
+ C.mclBnG2_sub(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// G2Mul --
+func G2Mul(out *G2, x *G2, y *Fr) {
+ C.mclBnG2_mul(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// GT --
+type GT struct {
+ v C.mclBnGT
+}
+
+// getPointer --
+func (x *GT) getPointer() (p *C.mclBnGT) {
+ // #nosec
+ return (*C.mclBnGT)(unsafe.Pointer(x))
+}
+
+// Clear --
+func (x *GT) Clear() {
+ // #nosec
+ C.mclBnGT_clear(x.getPointer())
+}
+
+// SetInt64 --
+func (x *GT) SetInt64(v int64) {
+ // #nosec
+ C.mclBnGT_setInt(x.getPointer(), C.int64_t(v))
+}
+
+// SetString --
+func (x *GT) SetString(s string, base int) error {
+ buf := []byte(s)
+ // #nosec
+ err := C.mclBnGT_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base))
+ if err != 0 {
+ return fmt.Errorf("err mclBnGT_setStr %x", err)
+ }
+ return nil
+}
+
+// Deserialize --
+func (x *GT) Deserialize(buf []byte) error {
+ // #nosec
+ err := C.mclBnGT_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
+ if err == 0 {
+ return fmt.Errorf("err mclBnGT_deserialize %x", buf)
+ }
+ return nil
+}
+
+// IsEqual --
+func (x *GT) IsEqual(rhs *GT) bool {
+ return C.mclBnGT_isEqual(x.getPointer(), rhs.getPointer()) == 1
+}
+
+// IsZero --
+func (x *GT) IsZero() bool {
+ return C.mclBnGT_isZero(x.getPointer()) == 1
+}
+
+// IsOne --
+func (x *GT) IsOne() bool {
+ return C.mclBnGT_isOne(x.getPointer()) == 1
+}
+
+// GetString --
+func (x *GT) GetString(base int) string {
+ buf := make([]byte, 2048)
+ // #nosec
+ n := C.mclBnGT_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base))
+ if n == 0 {
+ panic("err mclBnGT_getStr")
+ }
+ return string(buf[:n])
+}
+
+// Serialize --
+func (x *GT) Serialize() []byte {
+ buf := make([]byte, 2048)
+ // #nosec
+ n := C.mclBnGT_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer())
+ if n == 0 {
+ panic("err mclBnGT_serialize")
+ }
+ return buf[:n]
+}
+
+// GTNeg --
+func GTNeg(out *GT, x *GT) {
+ C.mclBnGT_neg(out.getPointer(), x.getPointer())
+}
+
+// GTInv --
+func GTInv(out *GT, x *GT) {
+ C.mclBnGT_inv(out.getPointer(), x.getPointer())
+}
+
+// GTAdd --
+func GTAdd(out *GT, x *GT, y *GT) {
+ C.mclBnGT_add(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// GTSub --
+func GTSub(out *GT, x *GT, y *GT) {
+ C.mclBnGT_sub(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// GTMul --
+func GTMul(out *GT, x *GT, y *GT) {
+ C.mclBnGT_mul(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// GTDiv --
+func GTDiv(out *GT, x *GT, y *GT) {
+ C.mclBnGT_div(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// GTPow --
+func GTPow(out *GT, x *GT, y *Fr) {
+ C.mclBnGT_pow(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// Pairing --
+func Pairing(out *GT, x *G1, y *G2) {
+ C.mclBn_pairing(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// FinalExp --
+func FinalExp(out *GT, x *GT) {
+ C.mclBn_finalExp(out.getPointer(), x.getPointer())
+}
+
+// MillerLoop --
+func MillerLoop(out *GT, x *G1, y *G2) {
+ C.mclBn_millerLoop(out.getPointer(), x.getPointer(), y.getPointer())
+}
+
+// GetUint64NumToPrecompute --
+func GetUint64NumToPrecompute() int {
+ return int(C.mclBn_getUint64NumToPrecompute())
+}
+
+// PrecomputeG2 --
+func PrecomputeG2(Qbuf []uint64, Q *G2) {
+ // #nosec
+ C.mclBn_precomputeG2((*C.uint64_t)(unsafe.Pointer(&Qbuf[0])), Q.getPointer())
+}
+
+// PrecomputedMillerLoop --
+func PrecomputedMillerLoop(out *GT, P *G1, Qbuf []uint64) {
+ // #nosec
+ C.mclBn_precomputedMillerLoop(out.getPointer(), P.getPointer(), (*C.uint64_t)(unsafe.Pointer(&Qbuf[0])))
+}
+
+// PrecomputedMillerLoop2 --
+func PrecomputedMillerLoop2(out *GT, P1 *G1, Q1buf []uint64, P2 *G1, Q2buf []uint64) {
+ // #nosec
+ C.mclBn_precomputedMillerLoop2(out.getPointer(), P1.getPointer(), (*C.uint64_t)(unsafe.Pointer(&Q1buf[0])), P1.getPointer(), (*C.uint64_t)(unsafe.Pointer(&Q1buf[0])))
+}
+
+// FrEvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ...
+func FrEvaluatePolynomial(y *Fr, c []Fr, x *Fr) error {
+ // #nosec
+ err := C.mclBn_FrEvaluatePolynomial(y.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&c[0])), (C.size_t)(len(c)), x.getPointer())
+ if err != 0 {
+ return fmt.Errorf("err mclBn_FrEvaluatePolynomial")
+ }
+ return nil
+}
+
+// G1EvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ...
+func G1EvaluatePolynomial(y *G1, c []G1, x *Fr) error {
+ // #nosec
+ err := C.mclBn_G1EvaluatePolynomial(y.getPointer(), (*C.mclBnG1)(unsafe.Pointer(&c[0])), (C.size_t)(len(c)), x.getPointer())
+ if err != 0 {
+ return fmt.Errorf("err mclBn_G1EvaluatePolynomial")
+ }
+ return nil
+}
+
+// G2EvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ...
+func G2EvaluatePolynomial(y *G2, c []G2, x *Fr) error {
+ // #nosec
+ err := C.mclBn_G2EvaluatePolynomial(y.getPointer(), (*C.mclBnG2)(unsafe.Pointer(&c[0])), (C.size_t)(len(c)), x.getPointer())
+ if err != 0 {
+ return fmt.Errorf("err mclBn_G2EvaluatePolynomial")
+ }
+ return nil
+}
+
+// FrLagrangeInterpolation --
+func FrLagrangeInterpolation(out *Fr, xVec []Fr, yVec []Fr) error {
+ if len(xVec) != len(yVec) {
+ return fmt.Errorf("err FrLagrangeInterpolation:bad size")
+ }
+ // #nosec
+ err := C.mclBn_FrLagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnFr)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec)))
+ if err != 0 {
+ return fmt.Errorf("err FrLagrangeInterpolation")
+ }
+ return nil
+}
+
+// G1LagrangeInterpolation --
+func G1LagrangeInterpolation(out *G1, xVec []Fr, yVec []G1) error {
+ if len(xVec) != len(yVec) {
+ return fmt.Errorf("err G1LagrangeInterpolation:bad size")
+ }
+ // #nosec
+ err := C.mclBn_G1LagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnG1)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec)))
+ if err != 0 {
+ return fmt.Errorf("err G1LagrangeInterpolation")
+ }
+ return nil
+}
+
+// G2LagrangeInterpolation --
+func G2LagrangeInterpolation(out *G2, xVec []Fr, yVec []G2) error {
+ if len(xVec) != len(yVec) {
+ return fmt.Errorf("err G2LagrangeInterpolation:bad size")
+ }
+ // #nosec
+ err := C.mclBn_G2LagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnG2)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec)))
+ if err != 0 {
+ return fmt.Errorf("err G2LagrangeInterpolation")
+ }
+ return nil
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/go/mcl/mcl_test.go b/vendor/github.com/dexon-foundation/mcl/ffi/go/mcl/mcl_test.go
new file mode 100644
index 000000000..16bb6910f
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/go/mcl/mcl_test.go
@@ -0,0 +1,157 @@
+package mcl
+
+import "testing"
+import "fmt"
+
+func testBadPointOfG2(t *testing.T) {
+ var Q G2
+ // this value is not in G2 so should return an error
+ err := Q.SetString("1 18d3d8c085a5a5e7553c3a4eb628e88b8465bf4de2612e35a0a4eb018fb0c82e9698896031e62fd7633ffd824a859474 1dc6edfcf33e29575d4791faed8e7203832217423bf7f7fbf1f6b36625b12e7132c15fbc15562ce93362a322fb83dd0d 65836963b1f7b6959030ddfa15ab38ce056097e91dedffd996c1808624fa7e2644a77be606290aa555cda8481cfb3cb 1b77b708d3d4f65aeedf54b58393463a42f0dc5856baadb5ce608036baeca398c5d9e6b169473a8838098fd72fd28b50", 16)
+ if err == nil {
+ t.Error(err)
+ }
+}
+
+func testGT(t *testing.T) {
+ var x GT
+ x.Clear()
+ if !x.IsZero() {
+ t.Errorf("not zero")
+ }
+ x.SetInt64(1)
+ if !x.IsOne() {
+ t.Errorf("not one")
+ }
+}
+
+func testHash(t *testing.T) {
+ var x Fr
+ if !x.SetHashOf([]byte("abc")) {
+ t.Error("SetHashOf")
+ }
+ fmt.Printf("x=%s\n", x.GetString(16))
+}
+
+func testNegAdd(t *testing.T) {
+ var x Fr
+ var P1, P2, P3 G1
+ var Q1, Q2, Q3 G2
+ err := P1.HashAndMapTo([]byte("this"))
+ if err != nil {
+ t.Error(err)
+ }
+ err = Q1.HashAndMapTo([]byte("this"))
+ if err != nil {
+ t.Error(err)
+ }
+ fmt.Printf("P1=%s\n", P1.GetString(16))
+ fmt.Printf("Q1=%s\n", Q1.GetString(16))
+ G1Neg(&P2, &P1)
+ G2Neg(&Q2, &Q1)
+ fmt.Printf("P2=%s\n", P2.GetString(16))
+ fmt.Printf("Q2=%s\n", Q2.GetString(16))
+
+ x.SetInt64(-1)
+ G1Mul(&P3, &P1, &x)
+ G2Mul(&Q3, &Q1, &x)
+ if !P2.IsEqual(&P3) {
+ t.Errorf("P2 != P3 %s\n", P3.GetString(16))
+ }
+ if !Q2.IsEqual(&Q3) {
+ t.Errorf("Q2 != Q3 %s\n", Q3.GetString(16))
+ }
+
+ G1Add(&P2, &P2, &P1)
+ G2Add(&Q2, &Q2, &Q1)
+ if !P2.IsZero() {
+ t.Errorf("P2 is not zero %s\n", P2.GetString(16))
+ }
+ if !Q2.IsZero() {
+ t.Errorf("Q2 is not zero %s\n", Q2.GetString(16))
+ }
+}
+
+func testPairing(t *testing.T) {
+ var a, b, ab Fr
+ err := a.SetString("123", 10)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ err = b.SetString("456", 10)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ FrMul(&ab, &a, &b)
+ var P, aP G1
+ var Q, bQ G2
+ err = P.HashAndMapTo([]byte("this"))
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ fmt.Printf("P=%s\n", P.GetString(16))
+ G1Mul(&aP, &P, &a)
+ fmt.Printf("aP=%s\n", aP.GetString(16))
+ err = Q.HashAndMapTo([]byte("that"))
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ fmt.Printf("Q=%s\n", Q.GetString(16))
+ G2Mul(&bQ, &Q, &b)
+ fmt.Printf("bQ=%s\n", bQ.GetString(16))
+ var e1, e2 GT
+ Pairing(&e1, &P, &Q)
+ fmt.Printf("e1=%s\n", e1.GetString(16))
+ Pairing(&e2, &aP, &bQ)
+ fmt.Printf("e2=%s\n", e1.GetString(16))
+ GTPow(&e1, &e1, &ab)
+ fmt.Printf("e1=%s\n", e1.GetString(16))
+ if !e1.IsEqual(&e2) {
+ t.Errorf("not equal pairing\n%s\n%s", e1.GetString(16), e2.GetString(16))
+ }
+ {
+ s := P.GetString(IoSerializeHexStr)
+ var P1 G1
+ P1.SetString(s, IoSerializeHexStr)
+ if !P1.IsEqual(&P) {
+ t.Error("not equal to P")
+ return
+ }
+ s = Q.GetString(IoSerializeHexStr)
+ var Q1 G2
+ Q1.SetString(s, IoSerializeHexStr)
+ if !Q1.IsEqual(&Q) {
+ t.Error("not equal to Q")
+ return
+ }
+ }
+}
+
+func testMcl(t *testing.T, c int) {
+ err := Init(c)
+ if err != nil {
+ t.Fatal(err)
+ }
+ testHash(t)
+ testNegAdd(t)
+ testPairing(t)
+ testGT(t)
+ testBadPointOfG2(t)
+}
+
+func TestMclMain(t *testing.T) {
+ t.Logf("GetMaxOpUnitSize() = %d\n", GetMaxOpUnitSize())
+ t.Log("CurveFp254BNb")
+ testMcl(t, CurveFp254BNb)
+ if GetMaxOpUnitSize() == 6 {
+ if GetFrUnitSize() == 6 {
+ t.Log("CurveFp382_1")
+ testMcl(t, CurveFp382_1)
+ }
+ t.Log("BLS12_381")
+ testMcl(t, BLS12_381)
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/Bn256Test.java b/vendor/github.com/dexon-foundation/mcl/ffi/java/Bn256Test.java
new file mode 100644
index 000000000..b1f9f6f34
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/Bn256Test.java
@@ -0,0 +1,104 @@
+import java.io.*;
+import com.herumi.mcl.*;
+
+/*
+ Bn256Test
+*/
+public class Bn256Test {
+ static {
+ String lib = "mcl_bn256";
+ String libName = System.mapLibraryName(lib);
+ System.out.println("libName : " + libName);
+ System.loadLibrary(lib);
+ }
+ public static void assertEquals(String msg, String x, String y) {
+ if (x.equals(y)) {
+ System.out.println("OK : " + msg);
+ } else {
+ System.out.println("NG : " + msg + ", x = " + x + ", y = " + y);
+ }
+ }
+ public static void assertBool(String msg, boolean b) {
+ if (b) {
+ System.out.println("OK : " + msg);
+ } else {
+ System.out.println("NG : " + msg);
+ }
+ }
+ public static void main(String argv[]) {
+ try {
+ Bn256.SystemInit();
+ Fr x = new Fr(5);
+ Fr y = new Fr(-2);
+ Fr z = new Fr(5);
+ assertBool("x != y", !x.equals(y));
+ assertBool("x == z", x.equals(z));
+ assertEquals("x == 5", x.toString(), "5");
+ Bn256.add(x, x, y);
+ assertEquals("x == 3", x.toString(), "3");
+ Bn256.mul(x, x, x);
+ assertEquals("x == 9", x.toString(), "9");
+ G1 P = new G1();
+ System.out.println("P=" + P);
+ P.set("-1", "1");
+ System.out.println("P=" + P);
+ Bn256.neg(P, P);
+ System.out.println("P=" + P);
+
+ String xa = "12723517038133731887338407189719511622662176727675373276651903807414909099441";
+ String xb = "4168783608814932154536427934509895782246573715297911553964171371032945126671";
+ String ya = "13891744915211034074451795021214165905772212241412891944830863846330766296736";
+ String yb = "7937318970632701341203597196594272556916396164729705624521405069090520231616";
+
+ G2 Q = new G2(xa, xb, ya, yb);
+
+ P.hashAndMapToG1("This is a pen");
+ {
+ String s = P.toString();
+ G1 P1 = new G1();
+ P1.setStr(s);
+ assertBool("P == P1", P1.equals(P));
+ }
+
+ GT e = new GT();
+ Bn256.pairing(e, P, Q);
+ GT e1 = new GT();
+ GT e2 = new GT();
+ Fr c = new Fr("1234567890123234928348230428394234");
+ G2 cQ = new G2(Q);
+ Bn256.mul(cQ, Q, c); // cQ = Q * c
+ Bn256.pairing(e1, P, cQ);
+ Bn256.pow(e2, e, c); // e2 = e^c
+ assertBool("e1 == e2", e1.equals(e2));
+
+ G1 cP = new G1(P);
+ Bn256.mul(cP, P, c); // cP = P * c
+ Bn256.pairing(e1, cP, Q);
+ assertBool("e1 == e2", e1.equals(e2));
+
+ BLSsignature(Q);
+ } catch (RuntimeException e) {
+ System.out.println("unknown exception :" + e);
+ }
+ }
+ public static void BLSsignature(G2 Q)
+ {
+ Fr s = new Fr();
+ s.setRand(); // secret key
+ System.out.println("secret key " + s);
+ G2 pub = new G2();
+ Bn256.mul(pub, Q, s); // public key = sQ
+
+ String m = "signature test";
+ G1 H = new G1();
+ H.hashAndMapToG1(m); // H = Hash(m)
+ G1 sign = new G1();
+ Bn256.mul(sign, H, s); // signature of m = s H
+
+ GT e1 = new GT();
+ GT e2 = new GT();
+ Bn256.pairing(e1, H, pub); // e1 = e(H, s Q)
+ Bn256.pairing(e2, sign, Q); // e2 = e(s H, Q);
+ assertBool("verify signature", e1.equals(e2));
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/ElgamalTest.java b/vendor/github.com/dexon-foundation/mcl/ffi/java/ElgamalTest.java
new file mode 100644
index 000000000..0cf49e144
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/ElgamalTest.java
@@ -0,0 +1,144 @@
+import java.io.*;
+import com.herumi.mcl.*;
+
+/*
+ ElgamalTest [ecParam]
+ ecParam = secp192k1, NIST_P224, ...
+ hashParam = hash224, hash384, ...
+*/
+public class ElgamalTest {
+ static {
+ String lib = "mcl_elgamal";
+ String libName = System.mapLibraryName(lib);
+ System.out.println("libName : " + libName);
+ System.loadLibrary(lib);
+ }
+ public static void assertEquals(String msg, int x, int y) {
+ if (x == y) {
+ System.out.println("OK : " + msg);
+ } else {
+ System.out.println("NG : " + msg + ", x = " + x + ", y = " + y);
+ }
+ }
+ public static void assertBool(String msg, boolean b) {
+ if (b) {
+ System.out.println("OK : " + msg);
+ } else {
+ System.out.println("NG : " + msg);
+ }
+ }
+ public static void main(String argv[]) {
+ try {
+ String ecStr = "secp192k1";
+ String hashStr = "sha224";
+ for (int i = 0; i < argv.length; i++) {
+ if (argv[i].equals("-e") && i < argv.length - 1) {
+ ecStr = argv[i + 1];
+ i++;
+ } else
+ if (argv[i].equals("-h") && i < argv.length - 1) {
+ hashStr = argv[i + 1];
+ i++;
+ }
+ }
+ String param = ecStr + " " + hashStr;
+ System.out.println("param=" + param);
+ Elgamal.SystemInit(param);
+
+ String prvStr = "";
+ String pubStr = "";
+ {
+ PrivateKey prv = new PrivateKey();
+ prv.init();
+ prvStr = prv.toStr();
+ PublicKey pub = prv.getPublicKey();
+ pubStr = pub.toStr();
+ }
+ int m = 1234;
+ CipherText c = new CipherText();
+ PublicKey pub = new PublicKey();
+
+ pub.fromStr(pubStr);
+
+ pub.enc(c, m);
+
+ PrivateKey prv = new PrivateKey();
+ prv.fromStr(prvStr);
+ prv.setCache(0, 60000);
+
+ int dec = prv.dec(c);
+ // verify dec(enc(m)) == m
+ assertEquals("dec(enc(m)) == m", m, dec);
+
+ // verify toStr, fromStr
+ {
+ String cStr = c.toStr();
+ CipherText c2 = new CipherText();
+ c2.fromStr(cStr);
+ int dec2 = prv.dec(c2);
+ assertEquals("fromStr(toStr(CipherText) == CipherText", dec, dec2);
+ }
+
+ // verify dec(enc(str)) == str
+ pub.enc(c, "1234");
+ dec = prv.dec(c);
+ assertEquals("dec(enc(str)) == str", m, dec);
+
+ // verify dec(mul(enc(m), 3)) == m * 3
+ c.mul(3);
+ m *= 3;
+ dec = prv.dec(c);
+ assertEquals("mul(int)", m, dec);
+
+ // verify dec(mul(enc(m), "10")) == m * 10
+ c.mul("10");
+ m *= 10;
+ dec = prv.dec(c);
+ assertEquals("mul(str)", m, dec);
+
+ // convert str
+ {
+ String s = c.toStr();
+ CipherText c2 = new CipherText();
+ c2.fromStr(s);
+ dec = prv.dec(c);
+ assertEquals("fromStr", m, dec);
+ }
+ // rerandomize
+ pub.rerandomize(c);
+ dec = prv.dec(c);
+ assertEquals("rerandomize", m, dec);
+ int m2 = 12345;
+ // verify dec(add(enc(m), m2)) == m + m2
+ pub.add(c, m2);
+ m += m2;
+ dec = prv.dec(c);
+ assertEquals("pub.add(int)", m, dec);
+
+ pub.add(c, "993");
+ m += 993;
+ dec = prv.dec(c);
+ assertEquals("pub.add(str)", m, dec);
+
+ // string test
+ String m3 = "-2000000";
+ String m4 = "2001234";
+ CipherText c2 = new CipherText();
+ SWIGTYPE_p_bool b = Elgamal.new_p_bool();
+ pub.enc(c, m3);
+ dec = prv.dec(c, b);
+ assertBool("expect dec fail", !Elgamal.p_bool_value(b));
+ pub.enc(c2, m4);
+ dec = prv.dec(c2, b);
+ assertBool("expect dec fail", !Elgamal.p_bool_value(b));
+ c.add(c2); // m3 + m4
+
+ dec = prv.dec(c, b);
+ assertEquals("int add", 1234, dec);
+ assertBool("expect dec success", Elgamal.p_bool_value(b));
+ Elgamal.delete_p_bool(b);
+ } catch (RuntimeException e) {
+ System.out.println("unknown exception :" + e);
+ }
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/Makefile b/vendor/github.com/dexon-foundation/mcl/ffi/java/Makefile
new file mode 100644
index 000000000..d69c043fb
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/Makefile
@@ -0,0 +1,64 @@
+TOP_DIR=../..
+include $(TOP_DIR)/common.mk
+ifeq ($(UNAME_S),Darwin)
+ JAVA_INC=-I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/
+else
+ JAVA_INC=-I/usr/lib/jvm/default-java/include
+#JAVA_INC=-I/usr/lib/jvm/java-7-openjdk-amd64/include
+ CFLAGS+=-z noexecstack
+ LDFLAGS+=-lrt
+endif
+CFLAGS+=$(JAVA_INC) $(JAVA_INC)/linux -I $(TOP_DIR)/include -I $(TOP_DIR)/../xbyak -I $(TOP_DIR)/../cybozulib/include -Wno-strict-aliasing
+MCL_LIB=$(TOP_DIR)/lib/libmcl.a
+
+PACKAGE_NAME=com.herumi.mcl
+PACKAGE_DIR=$(subst .,/,$(PACKAGE_NAME))
+
+ELGAMAL_LIB=$(TOP_DIR)/bin/libmcl_elgamal.$(LIB_SUF)
+BN256_LIB=$(TOP_DIR)/bin/libmcl_bn256.$(LIB_SUF)
+JAVA_EXE=cd $(TOP_DIR)/bin && LD_LIBRARY_PATH=./:$(LD_LIBRARY_PATH) java -classpath ../ffi/java
+all: $(ELGAMAL_LIB)
+
+elgamal_wrap.cxx: elgamal.i elgamal_impl.hpp
+ $(MKDIR) $(PACKAGE_DIR)
+ swig -java -package $(PACKAGE_NAME) -outdir $(PACKAGE_DIR) -c++ -Wall elgamal.i
+
+bn256_wrap.cxx: bn256.i bn256_impl.hpp
+ $(MKDIR) $(PACKAGE_DIR)
+ swig -java -package $(PACKAGE_NAME) -outdir $(PACKAGE_DIR) -c++ -Wall bn256.i
+
+$(MCL_LIB):
+ make -C $(TOP_DIR)
+
+$(ELGAMAL_LIB): elgamal_wrap.cxx $(MCL_LIB)
+ $(PRE)$(CXX) $< -o $@ $(CFLAGS) $(LDFLAGS) $(MCL_LIB) -shared
+
+$(BN256_LIB): bn256_wrap.cxx $(MCL_LIB)
+ $(PRE)$(CXX) $< -o $@ $(CFLAGS) $(LDFLAGS) $(MCL_LIB) -shared
+
+%.class: %.java
+ javac $<
+
+ElgamalTest.class: ElgamalTest.java $(ELGAMAL_LIB)
+Bn256Test.class: Bn256Test.java $(BN256_LIB)
+
+jar:
+ jar cvf mcl.jar com
+
+test_elgamal: ElgamalTest.class $(ELGAMAL_LIB)
+ $(JAVA_EXE) ElgamalTest
+ $(JAVA_EXE) ElgamalTest -e NIST_P192
+ $(JAVA_EXE) ElgamalTest -e NIST_P256 -h sha256
+ $(JAVA_EXE) ElgamalTest -e NIST_P384 -h sha384
+ $(JAVA_EXE) ElgamalTest -e NIST_P521 -h sha512
+
+test_bn256: Bn256Test.class $(BN256_LIB)
+ $(JAVA_EXE) Bn256Test
+
+test:
+ $(MAKE) test_elgamal
+ $(MAKE) test_bn256
+
+clean:
+ rm -rf *.class $(ELGAMAL_LIB) $(PACKAGE_DIR)/*.class *_wrap.cxx
+
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256.i b/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256.i
new file mode 100644
index 000000000..94a8edb7a
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256.i
@@ -0,0 +1,31 @@
+%module Bn256
+
+%include "std_string.i"
+%include "std_except.i"
+
+
+%{
+#include <cybozu/random_generator.hpp>
+#include <cybozu/crypto.hpp>
+#include <mcl/bn256.hpp>
+struct Param {
+ cybozu::RandomGenerator rg;
+ static inline Param& getParam()
+ {
+ static Param p;
+ return p;
+ }
+};
+
+static void HashAndMapToG1(mcl::bn256::G1& P, const std::string& m)
+{
+ std::string digest = cybozu::crypto::Hash::digest(cybozu::crypto::Hash::N_SHA256, m);
+ mcl::bn256::Fp t;
+ t.setArrayMask(digest.c_str(), digest.size());
+ mcl::bn256::BN::param.mapTo.calcG1(P, t);
+}
+
+#include "bn256_impl.hpp"
+%}
+
+%include "bn256_impl.hpp"
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256_impl.hpp b/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256_impl.hpp
new file mode 100644
index 000000000..c4caaf3ca
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256_impl.hpp
@@ -0,0 +1,249 @@
+#include <mcl/bn256.hpp>
+#include <stdint.h>
+#include <sstream>
+
+void SystemInit() throw(std::exception)
+{
+ mcl::bn256::initPairing();
+}
+
+class G1;
+class G2;
+class GT;
+/*
+ Fr = Z / rZ
+*/
+class Fr {
+ mcl::bn256::Fr self_;
+ friend class G1;
+ friend class G2;
+ friend class GT;
+ friend void neg(Fr& y, const Fr& x);
+ friend void add(Fr& z, const Fr& x, const Fr& y);
+ friend void sub(Fr& z, const Fr& x, const Fr& y);
+ friend void mul(Fr& z, const Fr& x, const Fr& y);
+ friend void mul(G1& z, const G1& x, const Fr& y);
+ friend void mul(G2& z, const G2& x, const Fr& y);
+ friend void div(Fr& z, const Fr& x, const Fr& y);
+ friend void pow(GT& z, const GT& x, const Fr& y);
+public:
+ Fr() {}
+ Fr(const Fr& rhs) : self_(rhs.self_) {}
+ Fr(int x) : self_(x) {}
+ Fr(const std::string& str) throw(std::exception)
+ : self_(str) {}
+ bool equals(const Fr& rhs) const { return self_ == rhs.self_; }
+ void setStr(const std::string& str) throw(std::exception)
+ {
+ self_.setStr(str);
+ }
+ void setInt(int x)
+ {
+ self_ = x;
+ }
+ void clear()
+ {
+ self_.clear();
+ }
+ void setRand()
+ {
+ self_.setRand(Param::getParam().rg);
+ }
+ std::string toString() const throw(std::exception)
+ {
+ return self_.getStr();
+ }
+};
+
+void neg(Fr& y, const Fr& x)
+{
+ mcl::bn256::Fr::neg(y.self_, x.self_);
+}
+
+void add(Fr& z, const Fr& x, const Fr& y)
+{
+ mcl::bn256::Fr::add(z.self_, x.self_, y.self_);
+}
+
+void sub(Fr& z, const Fr& x, const Fr& y)
+{
+ mcl::bn256::Fr::sub(z.self_, x.self_, y.self_);
+}
+
+void mul(Fr& z, const Fr& x, const Fr& y)
+{
+ mcl::bn256::Fr::mul(z.self_, x.self_, y.self_);
+}
+
+void div(Fr& z, const Fr& x, const Fr& y)
+{
+ mcl::bn256::Fr::div(z.self_, x.self_, y.self_);
+}
+
+/*
+ #G1 = r
+*/
+class G1 {
+ mcl::bn256::G1 self_;
+ friend void neg(G1& y, const G1& x);
+ friend void dbl(G1& y, const G1& x);
+ friend void add(G1& z, const G1& x, const G1& y);
+ friend void sub(G1& z, const G1& x, const G1& y);
+ friend void mul(G1& z, const G1& x, const Fr& y);
+ friend void pairing(GT& e, const G1& P, const G2& Q);
+public:
+ G1() {}
+ G1(const G1& rhs) : self_(rhs.self_) {}
+ G1(const std::string& x, const std::string& y) throw(std::exception)
+ : self_(mcl::bn256::Fp(x), mcl::bn256::Fp(y))
+ {
+ }
+ bool equals(const G1& rhs) const { return self_ == rhs.self_; }
+ void set(const std::string& x, const std::string& y)
+ {
+ self_.set(mcl::bn256::Fp(x), mcl::bn256::Fp(y));
+ }
+ void hashAndMapToG1(const std::string& m) throw(std::exception)
+ {
+ HashAndMapToG1(self_, m);
+ }
+ void clear()
+ {
+ self_.clear();
+ }
+ /*
+ compressed format
+ */
+ void setStr(const std::string& str) throw(std::exception)
+ {
+ self_.setStr(str);
+ }
+ std::string toString() const throw(std::exception)
+ {
+ return self_.getStr();
+ }
+};
+
+void neg(G1& y, const G1& x)
+{
+ mcl::bn256::G1::neg(y.self_, x.self_);
+}
+void dbl(G1& y, const G1& x)
+{
+ mcl::bn256::G1::dbl(y.self_, x.self_);
+}
+void add(G1& z, const G1& x, const G1& y)
+{
+ mcl::bn256::G1::add(z.self_, x.self_, y.self_);
+}
+void sub(G1& z, const G1& x, const G1& y)
+{
+ mcl::bn256::G1::sub(z.self_, x.self_, y.self_);
+}
+void mul(G1& z, const G1& x, const Fr& y)
+{
+ mcl::bn256::G1::mul(z.self_, x.self_, y.self_);
+}
+
+/*
+ #G2 = r
+*/
+class G2 {
+ mcl::bn256::G2 self_;
+ friend void neg(G2& y, const G2& x);
+ friend void dbl(G2& y, const G2& x);
+ friend void add(G2& z, const G2& x, const G2& y);
+ friend void sub(G2& z, const G2& x, const G2& y);
+ friend void mul(G2& z, const G2& x, const Fr& y);
+ friend void pairing(GT& e, const G1& P, const G2& Q);
+public:
+ G2() {}
+ G2(const G2& rhs) : self_(rhs.self_) {}
+ G2(const std::string& xa, const std::string& xb, const std::string& ya, const std::string& yb) throw(std::exception)
+ : self_(mcl::bn256::Fp2(xa, xb), mcl::bn256::Fp2(ya, yb))
+ {
+ }
+ bool equals(const G2& rhs) const { return self_ == rhs.self_; }
+ void set(const std::string& xa, const std::string& xb, const std::string& ya, const std::string& yb)
+ {
+ self_.set(mcl::bn256::Fp2(xa, xb), mcl::bn256::Fp2(ya, yb));
+ }
+ void clear()
+ {
+ self_.clear();
+ }
+ /*
+ compressed format
+ */
+ void setStr(const std::string& str) throw(std::exception)
+ {
+ self_.setStr(str);
+ }
+ std::string toString() const throw(std::exception)
+ {
+ return self_.getStr();
+ }
+};
+
+void neg(G2& y, const G2& x)
+{
+ mcl::bn256::G2::neg(y.self_, x.self_);
+}
+void dbl(G2& y, const G2& x)
+{
+ mcl::bn256::G2::dbl(y.self_, x.self_);
+}
+void add(G2& z, const G2& x, const G2& y)
+{
+ mcl::bn256::G2::add(z.self_, x.self_, y.self_);
+}
+void sub(G2& z, const G2& x, const G2& y)
+{
+ mcl::bn256::G2::sub(z.self_, x.self_, y.self_);
+}
+void mul(G2& z, const G2& x, const Fr& y)
+{
+ mcl::bn256::G2::mul(z.self_, x.self_, y.self_);
+}
+
+/*
+ #GT = r
+*/
+class GT {
+ mcl::bn256::Fp12 self_;
+ friend void mul(GT& z, const GT& x, const GT& y);
+ friend void pow(GT& z, const GT& x, const Fr& y);
+ friend void pairing(GT& e, const G1& P, const G2& Q);
+public:
+ GT() {}
+ GT(const GT& rhs) : self_(rhs.self_) {}
+ bool equals(const GT& rhs) const { return self_ == rhs.self_; }
+ void clear()
+ {
+ self_.clear();
+ }
+ void setStr(const std::string& str) throw(std::exception)
+ {
+ std::istringstream iss(str);
+ iss >> self_;
+ }
+ std::string toString() const throw(std::exception)
+ {
+ std::ostringstream oss;
+ oss << self_;
+ return oss.str();
+ }
+};
+
+void mul(GT& z, const GT& x, const GT& y)
+{
+ mcl::bn256::Fp12::mul(z.self_, x.self_, y.self_);
+}
+void pow(GT& z, const GT& x, const Fr& y)
+{
+ mcl::bn256::Fp12::pow(z.self_, x.self_, y.self_);
+}
+void pairing(GT& e, const G1& P, const G2& Q)
+{
+ mcl::bn256::pairing(e.self_, P.self_, Q.self_);
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256_wrap.cxx b/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256_wrap.cxx
new file mode 100644
index 000000000..0c8257af5
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256_wrap.cxx
@@ -0,0 +1,1542 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 3.0.12
+ *
+ * This file is not intended to be easily readable and contains a number of
+ * coding conventions designed to improve portability and efficiency. Do not make
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+
+#ifndef SWIGJAVA
+#define SWIGJAVA
+#endif
+
+
+
+#ifdef __cplusplus
+/* SwigValueWrapper is described in swig.swg */
+template<typename T> class SwigValueWrapper {
+ struct SwigMovePointer {
+ T *ptr;
+ SwigMovePointer(T *p) : ptr(p) { }
+ ~SwigMovePointer() { delete ptr; }
+ SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; }
+ } pointer;
+ SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs);
+ SwigValueWrapper(const SwigValueWrapper<T>& rhs);
+public:
+ SwigValueWrapper() : pointer(0) { }
+ SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; }
+ operator T&() const { return *pointer.ptr; }
+ T *operator&() { return pointer.ptr; }
+};
+
+template <typename T> T SwigValueInit() {
+ return T();
+}
+#endif
+
+/* -----------------------------------------------------------------------------
+ * This section contains generic SWIG labels for method/variable
+ * declarations/attributes, and other compiler dependent labels.
+ * ----------------------------------------------------------------------------- */
+
+/* template workaround for compilers that cannot correctly implement the C++ standard */
+#ifndef SWIGTEMPLATEDISAMBIGUATOR
+# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560)
+# define SWIGTEMPLATEDISAMBIGUATOR template
+# elif defined(__HP_aCC)
+/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */
+/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */
+# define SWIGTEMPLATEDISAMBIGUATOR template
+# else
+# define SWIGTEMPLATEDISAMBIGUATOR
+# endif
+#endif
+
+/* inline attribute */
+#ifndef SWIGINLINE
+# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__))
+# define SWIGINLINE inline
+# else
+# define SWIGINLINE
+# endif
+#endif
+
+/* attribute recognised by some compilers to avoid 'unused' warnings */
+#ifndef SWIGUNUSED
+# if defined(__GNUC__)
+# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+# define SWIGUNUSED __attribute__ ((__unused__))
+# else
+# define SWIGUNUSED
+# endif
+# elif defined(__ICC)
+# define SWIGUNUSED __attribute__ ((__unused__))
+# else
+# define SWIGUNUSED
+# endif
+#endif
+
+#ifndef SWIG_MSC_UNSUPPRESS_4505
+# if defined(_MSC_VER)
+# pragma warning(disable : 4505) /* unreferenced local function has been removed */
+# endif
+#endif
+
+#ifndef SWIGUNUSEDPARM
+# ifdef __cplusplus
+# define SWIGUNUSEDPARM(p)
+# else
+# define SWIGUNUSEDPARM(p) p SWIGUNUSED
+# endif
+#endif
+
+/* internal SWIG method */
+#ifndef SWIGINTERN
+# define SWIGINTERN static SWIGUNUSED
+#endif
+
+/* internal inline SWIG method */
+#ifndef SWIGINTERNINLINE
+# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE
+#endif
+
+/* exporting methods */
+#if defined(__GNUC__)
+# if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+# ifndef GCC_HASCLASSVISIBILITY
+# define GCC_HASCLASSVISIBILITY
+# endif
+# endif
+#endif
+
+#ifndef SWIGEXPORT
+# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# if defined(STATIC_LINKED)
+# define SWIGEXPORT
+# else
+# define SWIGEXPORT __declspec(dllexport)
+# endif
+# else
+# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)
+# define SWIGEXPORT __attribute__ ((visibility("default")))
+# else
+# define SWIGEXPORT
+# endif
+# endif
+#endif
+
+/* calling conventions for Windows */
+#ifndef SWIGSTDCALL
+# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# define SWIGSTDCALL __stdcall
+# else
+# define SWIGSTDCALL
+# endif
+#endif
+
+/* Deal with Microsoft's attempt at deprecating C standard runtime functions */
+#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+# define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */
+#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE)
+# define _SCL_SECURE_NO_DEPRECATE
+#endif
+
+/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */
+#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES)
+# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
+#endif
+
+/* Intel's compiler complains if a variable which was never initialised is
+ * cast to void, which is a common idiom which we use to indicate that we
+ * are aware a variable isn't used. So we just silence that warning.
+ * See: https://github.com/swig/swig/issues/192 for more discussion.
+ */
+#ifdef __INTEL_COMPILER
+# pragma warning disable 592
+#endif
+
+
+/* Fix for jlong on some versions of gcc on Windows */
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+ typedef long long __int64;
+#endif
+
+/* Fix for jlong on 64-bit x86 Solaris */
+#if defined(__x86_64)
+# ifdef _LP64
+# undef _LP64
+# endif
+#endif
+
+#include <jni.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Support for throwing Java exceptions */
+typedef enum {
+ SWIG_JavaOutOfMemoryError = 1,
+ SWIG_JavaIOException,
+ SWIG_JavaRuntimeException,
+ SWIG_JavaIndexOutOfBoundsException,
+ SWIG_JavaArithmeticException,
+ SWIG_JavaIllegalArgumentException,
+ SWIG_JavaNullPointerException,
+ SWIG_JavaDirectorPureVirtual,
+ SWIG_JavaUnknownError
+} SWIG_JavaExceptionCodes;
+
+typedef struct {
+ SWIG_JavaExceptionCodes code;
+ const char *java_exception;
+} SWIG_JavaExceptions_t;
+
+
+static void SWIGUNUSED SWIG_JavaThrowException(JNIEnv *jenv, SWIG_JavaExceptionCodes code, const char *msg) {
+ jclass excep;
+ static const SWIG_JavaExceptions_t java_exceptions[] = {
+ { SWIG_JavaOutOfMemoryError, "java/lang/OutOfMemoryError" },
+ { SWIG_JavaIOException, "java/io/IOException" },
+ { SWIG_JavaRuntimeException, "java/lang/RuntimeException" },
+ { SWIG_JavaIndexOutOfBoundsException, "java/lang/IndexOutOfBoundsException" },
+ { SWIG_JavaArithmeticException, "java/lang/ArithmeticException" },
+ { SWIG_JavaIllegalArgumentException, "java/lang/IllegalArgumentException" },
+ { SWIG_JavaNullPointerException, "java/lang/NullPointerException" },
+ { SWIG_JavaDirectorPureVirtual, "java/lang/RuntimeException" },
+ { SWIG_JavaUnknownError, "java/lang/UnknownError" },
+ { (SWIG_JavaExceptionCodes)0, "java/lang/UnknownError" }
+ };
+ const SWIG_JavaExceptions_t *except_ptr = java_exceptions;
+
+ while (except_ptr->code != code && except_ptr->code)
+ except_ptr++;
+
+ jenv->ExceptionClear();
+ excep = jenv->FindClass(except_ptr->java_exception);
+ if (excep)
+ jenv->ThrowNew(excep, msg);
+}
+
+
+/* Contract support */
+
+#define SWIG_contract_assert(nullreturn, expr, msg) if (!(expr)) {SWIG_JavaThrowException(jenv, SWIG_JavaIllegalArgumentException, msg); return nullreturn; } else
+
+
+#include <string>
+
+
+#include <typeinfo>
+#include <stdexcept>
+
+
+#include <cybozu/random_generator.hpp>
+#include <cybozu/crypto.hpp>
+#include <mcl/bn256.hpp>
+struct Param {
+ cybozu::RandomGenerator rg;
+ static inline Param& getParam()
+ {
+ static Param p;
+ return p;
+ }
+};
+
+static void HashAndMapToG1(mcl::bn256::G1& P, const std::string& m)
+{
+ std::string digest = cybozu::crypto::Hash::digest(cybozu::crypto::Hash::N_SHA256, m);
+ mcl::bn256::Fp t;
+ t.setArrayMask(digest.c_str(), digest.size());
+ mcl::bn256::BN::param.mapTo.calcG1(P, t);
+}
+
+#include "bn256_impl.hpp"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_SystemInit(JNIEnv *jenv, jclass jcls) {
+ (void)jenv;
+ (void)jcls;
+ try {
+ SystemInit();
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_neg_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) {
+ Fr *arg1 = 0 ;
+ Fr *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ arg1 = *(Fr **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr & reference is null");
+ return ;
+ }
+ arg2 = *(Fr **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null");
+ return ;
+ }
+ neg(*arg1,(Fr const &)*arg2);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_add_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) {
+ Fr *arg1 = 0 ;
+ Fr *arg2 = 0 ;
+ Fr *arg3 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ (void)jarg3_;
+ arg1 = *(Fr **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr & reference is null");
+ return ;
+ }
+ arg2 = *(Fr **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null");
+ return ;
+ }
+ arg3 = *(Fr **)&jarg3;
+ if (!arg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null");
+ return ;
+ }
+ add(*arg1,(Fr const &)*arg2,(Fr const &)*arg3);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_sub_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) {
+ Fr *arg1 = 0 ;
+ Fr *arg2 = 0 ;
+ Fr *arg3 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ (void)jarg3_;
+ arg1 = *(Fr **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr & reference is null");
+ return ;
+ }
+ arg2 = *(Fr **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null");
+ return ;
+ }
+ arg3 = *(Fr **)&jarg3;
+ if (!arg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null");
+ return ;
+ }
+ sub(*arg1,(Fr const &)*arg2,(Fr const &)*arg3);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_mul_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) {
+ Fr *arg1 = 0 ;
+ Fr *arg2 = 0 ;
+ Fr *arg3 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ (void)jarg3_;
+ arg1 = *(Fr **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr & reference is null");
+ return ;
+ }
+ arg2 = *(Fr **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null");
+ return ;
+ }
+ arg3 = *(Fr **)&jarg3;
+ if (!arg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null");
+ return ;
+ }
+ mul(*arg1,(Fr const &)*arg2,(Fr const &)*arg3);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_mul_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) {
+ G1 *arg1 = 0 ;
+ G1 *arg2 = 0 ;
+ Fr *arg3 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ (void)jarg3_;
+ arg1 = *(G1 **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 & reference is null");
+ return ;
+ }
+ arg2 = *(G1 **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null");
+ return ;
+ }
+ arg3 = *(Fr **)&jarg3;
+ if (!arg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null");
+ return ;
+ }
+ mul(*arg1,(G1 const &)*arg2,(Fr const &)*arg3);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_mul_1_1SWIG_12(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) {
+ G2 *arg1 = 0 ;
+ G2 *arg2 = 0 ;
+ Fr *arg3 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ (void)jarg3_;
+ arg1 = *(G2 **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 & reference is null");
+ return ;
+ }
+ arg2 = *(G2 **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null");
+ return ;
+ }
+ arg3 = *(Fr **)&jarg3;
+ if (!arg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null");
+ return ;
+ }
+ mul(*arg1,(G2 const &)*arg2,(Fr const &)*arg3);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_div(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) {
+ Fr *arg1 = 0 ;
+ Fr *arg2 = 0 ;
+ Fr *arg3 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ (void)jarg3_;
+ arg1 = *(Fr **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr & reference is null");
+ return ;
+ }
+ arg2 = *(Fr **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null");
+ return ;
+ }
+ arg3 = *(Fr **)&jarg3;
+ if (!arg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null");
+ return ;
+ }
+ div(*arg1,(Fr const &)*arg2,(Fr const &)*arg3);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_pow(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) {
+ GT *arg1 = 0 ;
+ GT *arg2 = 0 ;
+ Fr *arg3 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ (void)jarg3_;
+ arg1 = *(GT **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "GT & reference is null");
+ return ;
+ }
+ arg2 = *(GT **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "GT const & reference is null");
+ return ;
+ }
+ arg3 = *(Fr **)&jarg3;
+ if (!arg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null");
+ return ;
+ }
+ pow(*arg1,(GT const &)*arg2,(Fr const &)*arg3);
+}
+
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1Fr_1_1SWIG_10(JNIEnv *jenv, jclass jcls) {
+ jlong jresult = 0 ;
+ Fr *result = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ result = (Fr *)new Fr();
+ *(Fr **)&jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1Fr_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ jlong jresult = 0 ;
+ Fr *arg1 = 0 ;
+ Fr *result = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(Fr **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null");
+ return 0;
+ }
+ result = (Fr *)new Fr((Fr const &)*arg1);
+ *(Fr **)&jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1Fr_1_1SWIG_12(JNIEnv *jenv, jclass jcls, jint jarg1) {
+ jlong jresult = 0 ;
+ int arg1 ;
+ Fr *result = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ arg1 = (int)jarg1;
+ result = (Fr *)new Fr(arg1);
+ *(Fr **)&jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1Fr_1_1SWIG_13(JNIEnv *jenv, jclass jcls, jstring jarg1) {
+ jlong jresult = 0 ;
+ std::string *arg1 = 0 ;
+ Fr *result = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ if(!jarg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return 0;
+ }
+ const char *arg1_pstr = (const char *)jenv->GetStringUTFChars(jarg1, 0);
+ if (!arg1_pstr) return 0;
+ std::string arg1_str(arg1_pstr);
+ arg1 = &arg1_str;
+ jenv->ReleaseStringUTFChars(jarg1, arg1_pstr);
+ try {
+ result = (Fr *)new Fr((std::string const &)*arg1);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return 0;
+ }
+
+ *(Fr **)&jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT jboolean JNICALL Java_com_herumi_mcl_Bn256JNI_Fr_1equals(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) {
+ jboolean jresult = 0 ;
+ Fr *arg1 = (Fr *) 0 ;
+ Fr *arg2 = 0 ;
+ bool result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ arg1 = *(Fr **)&jarg1;
+ arg2 = *(Fr **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null");
+ return 0;
+ }
+ result = (bool)((Fr const *)arg1)->equals((Fr const &)*arg2);
+ jresult = (jboolean)result;
+ return jresult;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_Fr_1setStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
+ Fr *arg1 = (Fr *) 0 ;
+ std::string *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(Fr **)&jarg1;
+ if(!jarg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2_pstr) return ;
+ std::string arg2_str(arg2_pstr);
+ arg2 = &arg2_str;
+ jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
+ try {
+ (arg1)->setStr((std::string const &)*arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_Fr_1setInt(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2) {
+ Fr *arg1 = (Fr *) 0 ;
+ int arg2 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(Fr **)&jarg1;
+ arg2 = (int)jarg2;
+ (arg1)->setInt(arg2);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_Fr_1clear(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ Fr *arg1 = (Fr *) 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(Fr **)&jarg1;
+ (arg1)->clear();
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_Fr_1setRand(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ Fr *arg1 = (Fr *) 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(Fr **)&jarg1;
+ (arg1)->setRand();
+}
+
+
+SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_Bn256JNI_Fr_1toString(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ jstring jresult = 0 ;
+ Fr *arg1 = (Fr *) 0 ;
+ std::string result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(Fr **)&jarg1;
+ try {
+ result = ((Fr const *)arg1)->toString();
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return 0;
+ }
+
+ jresult = jenv->NewStringUTF((&result)->c_str());
+ return jresult;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_delete_1Fr(JNIEnv *jenv, jclass jcls, jlong jarg1) {
+ Fr *arg1 = (Fr *) 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ arg1 = *(Fr **)&jarg1;
+ delete arg1;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_neg_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) {
+ G1 *arg1 = 0 ;
+ G1 *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ arg1 = *(G1 **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 & reference is null");
+ return ;
+ }
+ arg2 = *(G1 **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null");
+ return ;
+ }
+ neg(*arg1,(G1 const &)*arg2);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_dbl_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) {
+ G1 *arg1 = 0 ;
+ G1 *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ arg1 = *(G1 **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 & reference is null");
+ return ;
+ }
+ arg2 = *(G1 **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null");
+ return ;
+ }
+ dbl(*arg1,(G1 const &)*arg2);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_add_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) {
+ G1 *arg1 = 0 ;
+ G1 *arg2 = 0 ;
+ G1 *arg3 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ (void)jarg3_;
+ arg1 = *(G1 **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 & reference is null");
+ return ;
+ }
+ arg2 = *(G1 **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null");
+ return ;
+ }
+ arg3 = *(G1 **)&jarg3;
+ if (!arg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null");
+ return ;
+ }
+ add(*arg1,(G1 const &)*arg2,(G1 const &)*arg3);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_sub_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) {
+ G1 *arg1 = 0 ;
+ G1 *arg2 = 0 ;
+ G1 *arg3 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ (void)jarg3_;
+ arg1 = *(G1 **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 & reference is null");
+ return ;
+ }
+ arg2 = *(G1 **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null");
+ return ;
+ }
+ arg3 = *(G1 **)&jarg3;
+ if (!arg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null");
+ return ;
+ }
+ sub(*arg1,(G1 const &)*arg2,(G1 const &)*arg3);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_pairing(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) {
+ GT *arg1 = 0 ;
+ G1 *arg2 = 0 ;
+ G2 *arg3 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ (void)jarg3_;
+ arg1 = *(GT **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "GT & reference is null");
+ return ;
+ }
+ arg2 = *(G1 **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null");
+ return ;
+ }
+ arg3 = *(G2 **)&jarg3;
+ if (!arg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null");
+ return ;
+ }
+ pairing(*arg1,(G1 const &)*arg2,(G2 const &)*arg3);
+}
+
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1G1_1_1SWIG_10(JNIEnv *jenv, jclass jcls) {
+ jlong jresult = 0 ;
+ G1 *result = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ result = (G1 *)new G1();
+ *(G1 **)&jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1G1_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ jlong jresult = 0 ;
+ G1 *arg1 = 0 ;
+ G1 *result = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(G1 **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null");
+ return 0;
+ }
+ result = (G1 *)new G1((G1 const &)*arg1);
+ *(G1 **)&jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1G1_1_1SWIG_12(JNIEnv *jenv, jclass jcls, jstring jarg1, jstring jarg2) {
+ jlong jresult = 0 ;
+ std::string *arg1 = 0 ;
+ std::string *arg2 = 0 ;
+ G1 *result = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ if(!jarg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return 0;
+ }
+ const char *arg1_pstr = (const char *)jenv->GetStringUTFChars(jarg1, 0);
+ if (!arg1_pstr) return 0;
+ std::string arg1_str(arg1_pstr);
+ arg1 = &arg1_str;
+ jenv->ReleaseStringUTFChars(jarg1, arg1_pstr);
+ if(!jarg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return 0;
+ }
+ const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2_pstr) return 0;
+ std::string arg2_str(arg2_pstr);
+ arg2 = &arg2_str;
+ jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
+ try {
+ result = (G1 *)new G1((std::string const &)*arg1,(std::string const &)*arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return 0;
+ }
+
+ *(G1 **)&jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT jboolean JNICALL Java_com_herumi_mcl_Bn256JNI_G1_1equals(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) {
+ jboolean jresult = 0 ;
+ G1 *arg1 = (G1 *) 0 ;
+ G1 *arg2 = 0 ;
+ bool result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ arg1 = *(G1 **)&jarg1;
+ arg2 = *(G1 **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null");
+ return 0;
+ }
+ result = (bool)((G1 const *)arg1)->equals((G1 const &)*arg2);
+ jresult = (jboolean)result;
+ return jresult;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_G1_1set(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2, jstring jarg3) {
+ G1 *arg1 = (G1 *) 0 ;
+ std::string *arg2 = 0 ;
+ std::string *arg3 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(G1 **)&jarg1;
+ if(!jarg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2_pstr) return ;
+ std::string arg2_str(arg2_pstr);
+ arg2 = &arg2_str;
+ jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
+ if(!jarg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg3_pstr = (const char *)jenv->GetStringUTFChars(jarg3, 0);
+ if (!arg3_pstr) return ;
+ std::string arg3_str(arg3_pstr);
+ arg3 = &arg3_str;
+ jenv->ReleaseStringUTFChars(jarg3, arg3_pstr);
+ (arg1)->set((std::string const &)*arg2,(std::string const &)*arg3);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_G1_1hashAndMapToG1(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
+ G1 *arg1 = (G1 *) 0 ;
+ std::string *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(G1 **)&jarg1;
+ if(!jarg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2_pstr) return ;
+ std::string arg2_str(arg2_pstr);
+ arg2 = &arg2_str;
+ jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
+ try {
+ (arg1)->hashAndMapToG1((std::string const &)*arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_G1_1clear(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ G1 *arg1 = (G1 *) 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(G1 **)&jarg1;
+ (arg1)->clear();
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_G1_1setStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
+ G1 *arg1 = (G1 *) 0 ;
+ std::string *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(G1 **)&jarg1;
+ if(!jarg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2_pstr) return ;
+ std::string arg2_str(arg2_pstr);
+ arg2 = &arg2_str;
+ jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
+ try {
+ (arg1)->setStr((std::string const &)*arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_Bn256JNI_G1_1toString(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ jstring jresult = 0 ;
+ G1 *arg1 = (G1 *) 0 ;
+ std::string result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(G1 **)&jarg1;
+ try {
+ result = ((G1 const *)arg1)->toString();
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return 0;
+ }
+
+ jresult = jenv->NewStringUTF((&result)->c_str());
+ return jresult;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_delete_1G1(JNIEnv *jenv, jclass jcls, jlong jarg1) {
+ G1 *arg1 = (G1 *) 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ arg1 = *(G1 **)&jarg1;
+ delete arg1;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_neg_1_1SWIG_12(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) {
+ G2 *arg1 = 0 ;
+ G2 *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ arg1 = *(G2 **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 & reference is null");
+ return ;
+ }
+ arg2 = *(G2 **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null");
+ return ;
+ }
+ neg(*arg1,(G2 const &)*arg2);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_dbl_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) {
+ G2 *arg1 = 0 ;
+ G2 *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ arg1 = *(G2 **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 & reference is null");
+ return ;
+ }
+ arg2 = *(G2 **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null");
+ return ;
+ }
+ dbl(*arg1,(G2 const &)*arg2);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_add_1_1SWIG_12(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) {
+ G2 *arg1 = 0 ;
+ G2 *arg2 = 0 ;
+ G2 *arg3 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ (void)jarg3_;
+ arg1 = *(G2 **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 & reference is null");
+ return ;
+ }
+ arg2 = *(G2 **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null");
+ return ;
+ }
+ arg3 = *(G2 **)&jarg3;
+ if (!arg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null");
+ return ;
+ }
+ add(*arg1,(G2 const &)*arg2,(G2 const &)*arg3);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_sub_1_1SWIG_12(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) {
+ G2 *arg1 = 0 ;
+ G2 *arg2 = 0 ;
+ G2 *arg3 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ (void)jarg3_;
+ arg1 = *(G2 **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 & reference is null");
+ return ;
+ }
+ arg2 = *(G2 **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null");
+ return ;
+ }
+ arg3 = *(G2 **)&jarg3;
+ if (!arg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null");
+ return ;
+ }
+ sub(*arg1,(G2 const &)*arg2,(G2 const &)*arg3);
+}
+
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1G2_1_1SWIG_10(JNIEnv *jenv, jclass jcls) {
+ jlong jresult = 0 ;
+ G2 *result = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ result = (G2 *)new G2();
+ *(G2 **)&jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1G2_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ jlong jresult = 0 ;
+ G2 *arg1 = 0 ;
+ G2 *result = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(G2 **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null");
+ return 0;
+ }
+ result = (G2 *)new G2((G2 const &)*arg1);
+ *(G2 **)&jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1G2_1_1SWIG_12(JNIEnv *jenv, jclass jcls, jstring jarg1, jstring jarg2, jstring jarg3, jstring jarg4) {
+ jlong jresult = 0 ;
+ std::string *arg1 = 0 ;
+ std::string *arg2 = 0 ;
+ std::string *arg3 = 0 ;
+ std::string *arg4 = 0 ;
+ G2 *result = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ if(!jarg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return 0;
+ }
+ const char *arg1_pstr = (const char *)jenv->GetStringUTFChars(jarg1, 0);
+ if (!arg1_pstr) return 0;
+ std::string arg1_str(arg1_pstr);
+ arg1 = &arg1_str;
+ jenv->ReleaseStringUTFChars(jarg1, arg1_pstr);
+ if(!jarg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return 0;
+ }
+ const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2_pstr) return 0;
+ std::string arg2_str(arg2_pstr);
+ arg2 = &arg2_str;
+ jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
+ if(!jarg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return 0;
+ }
+ const char *arg3_pstr = (const char *)jenv->GetStringUTFChars(jarg3, 0);
+ if (!arg3_pstr) return 0;
+ std::string arg3_str(arg3_pstr);
+ arg3 = &arg3_str;
+ jenv->ReleaseStringUTFChars(jarg3, arg3_pstr);
+ if(!jarg4) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return 0;
+ }
+ const char *arg4_pstr = (const char *)jenv->GetStringUTFChars(jarg4, 0);
+ if (!arg4_pstr) return 0;
+ std::string arg4_str(arg4_pstr);
+ arg4 = &arg4_str;
+ jenv->ReleaseStringUTFChars(jarg4, arg4_pstr);
+ try {
+ result = (G2 *)new G2((std::string const &)*arg1,(std::string const &)*arg2,(std::string const &)*arg3,(std::string const &)*arg4);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return 0;
+ }
+
+ *(G2 **)&jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT jboolean JNICALL Java_com_herumi_mcl_Bn256JNI_G2_1equals(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) {
+ jboolean jresult = 0 ;
+ G2 *arg1 = (G2 *) 0 ;
+ G2 *arg2 = 0 ;
+ bool result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ arg1 = *(G2 **)&jarg1;
+ arg2 = *(G2 **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null");
+ return 0;
+ }
+ result = (bool)((G2 const *)arg1)->equals((G2 const &)*arg2);
+ jresult = (jboolean)result;
+ return jresult;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_G2_1set(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2, jstring jarg3, jstring jarg4, jstring jarg5) {
+ G2 *arg1 = (G2 *) 0 ;
+ std::string *arg2 = 0 ;
+ std::string *arg3 = 0 ;
+ std::string *arg4 = 0 ;
+ std::string *arg5 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(G2 **)&jarg1;
+ if(!jarg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2_pstr) return ;
+ std::string arg2_str(arg2_pstr);
+ arg2 = &arg2_str;
+ jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
+ if(!jarg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg3_pstr = (const char *)jenv->GetStringUTFChars(jarg3, 0);
+ if (!arg3_pstr) return ;
+ std::string arg3_str(arg3_pstr);
+ arg3 = &arg3_str;
+ jenv->ReleaseStringUTFChars(jarg3, arg3_pstr);
+ if(!jarg4) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg4_pstr = (const char *)jenv->GetStringUTFChars(jarg4, 0);
+ if (!arg4_pstr) return ;
+ std::string arg4_str(arg4_pstr);
+ arg4 = &arg4_str;
+ jenv->ReleaseStringUTFChars(jarg4, arg4_pstr);
+ if(!jarg5) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg5_pstr = (const char *)jenv->GetStringUTFChars(jarg5, 0);
+ if (!arg5_pstr) return ;
+ std::string arg5_str(arg5_pstr);
+ arg5 = &arg5_str;
+ jenv->ReleaseStringUTFChars(jarg5, arg5_pstr);
+ (arg1)->set((std::string const &)*arg2,(std::string const &)*arg3,(std::string const &)*arg4,(std::string const &)*arg5);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_G2_1clear(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ G2 *arg1 = (G2 *) 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(G2 **)&jarg1;
+ (arg1)->clear();
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_G2_1setStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
+ G2 *arg1 = (G2 *) 0 ;
+ std::string *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(G2 **)&jarg1;
+ if(!jarg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2_pstr) return ;
+ std::string arg2_str(arg2_pstr);
+ arg2 = &arg2_str;
+ jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
+ try {
+ (arg1)->setStr((std::string const &)*arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_Bn256JNI_G2_1toString(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ jstring jresult = 0 ;
+ G2 *arg1 = (G2 *) 0 ;
+ std::string result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(G2 **)&jarg1;
+ try {
+ result = ((G2 const *)arg1)->toString();
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return 0;
+ }
+
+ jresult = jenv->NewStringUTF((&result)->c_str());
+ return jresult;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_delete_1G2(JNIEnv *jenv, jclass jcls, jlong jarg1) {
+ G2 *arg1 = (G2 *) 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ arg1 = *(G2 **)&jarg1;
+ delete arg1;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_mul_1_1SWIG_13(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) {
+ GT *arg1 = 0 ;
+ GT *arg2 = 0 ;
+ GT *arg3 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ (void)jarg3_;
+ arg1 = *(GT **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "GT & reference is null");
+ return ;
+ }
+ arg2 = *(GT **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "GT const & reference is null");
+ return ;
+ }
+ arg3 = *(GT **)&jarg3;
+ if (!arg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "GT const & reference is null");
+ return ;
+ }
+ mul(*arg1,(GT const &)*arg2,(GT const &)*arg3);
+}
+
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1GT_1_1SWIG_10(JNIEnv *jenv, jclass jcls) {
+ jlong jresult = 0 ;
+ GT *result = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ result = (GT *)new GT();
+ *(GT **)&jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1GT_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ jlong jresult = 0 ;
+ GT *arg1 = 0 ;
+ GT *result = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(GT **)&jarg1;
+ if (!arg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "GT const & reference is null");
+ return 0;
+ }
+ result = (GT *)new GT((GT const &)*arg1);
+ *(GT **)&jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT jboolean JNICALL Java_com_herumi_mcl_Bn256JNI_GT_1equals(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) {
+ jboolean jresult = 0 ;
+ GT *arg1 = (GT *) 0 ;
+ GT *arg2 = 0 ;
+ bool result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ arg1 = *(GT **)&jarg1;
+ arg2 = *(GT **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "GT const & reference is null");
+ return 0;
+ }
+ result = (bool)((GT const *)arg1)->equals((GT const &)*arg2);
+ jresult = (jboolean)result;
+ return jresult;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_GT_1clear(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ GT *arg1 = (GT *) 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(GT **)&jarg1;
+ (arg1)->clear();
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_GT_1setStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
+ GT *arg1 = (GT *) 0 ;
+ std::string *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(GT **)&jarg1;
+ if(!jarg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2_pstr) return ;
+ std::string arg2_str(arg2_pstr);
+ arg2 = &arg2_str;
+ jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
+ try {
+ (arg1)->setStr((std::string const &)*arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_Bn256JNI_GT_1toString(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ jstring jresult = 0 ;
+ GT *arg1 = (GT *) 0 ;
+ std::string result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(GT **)&jarg1;
+ try {
+ result = ((GT const *)arg1)->toString();
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return 0;
+ }
+
+ jresult = jenv->NewStringUTF((&result)->c_str());
+ return jresult;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_delete_1GT(JNIEnv *jenv, jclass jcls, jlong jarg1) {
+ GT *arg1 = (GT *) 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ arg1 = *(GT **)&jarg1;
+ delete arg1;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal.i b/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal.i
new file mode 100644
index 000000000..410723174
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal.i
@@ -0,0 +1,28 @@
+%module Elgamal
+
+%include "std_string.i"
+%include "std_except.i"
+
+
+%{
+#include <cybozu/random_generator.hpp>
+#include <cybozu/crypto.hpp>
+#include <mcl/fp.hpp>
+#include <mcl/ecparam.hpp>
+struct Param {
+const mcl::EcParam *ecParam;
+cybozu::RandomGenerator rg;
+cybozu::crypto::Hash::Name hashName;
+static inline Param& getParam()
+{
+ static Param p;
+ return p;
+}
+};
+
+#include "elgamal_impl.hpp"
+%}
+%include cpointer.i
+%pointer_functions(bool, p_bool);
+
+%include "elgamal_impl.hpp"
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal_impl.hpp b/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal_impl.hpp
new file mode 100644
index 000000000..dbf2ba64e
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal_impl.hpp
@@ -0,0 +1,147 @@
+#pragma once
+//#define MCL_MAX_BIT_SIZE 521
+#include <iostream>
+#include <fstream>
+#include <cybozu/random_generator.hpp>
+#include <cybozu/crypto.hpp>
+#include <mcl/fp.hpp>
+#include <mcl/ecparam.hpp>
+#include <mcl/elgamal.hpp>
+
+typedef mcl::FpT<mcl::FpTag, 521> Fp;
+typedef mcl::FpT<mcl::ZnTag, 521> Zn;
+typedef mcl::EcT<Fp> Ec;
+typedef mcl::ElgamalT<Ec, Zn> Elgamal;
+
+/*
+ init system
+ @param param [in] string such as "ecParamName hashName"
+ @note NOT thread safe because setting global parameters of elliptic curve
+ ex1) "secp192k1 sha256" // 192bit security + sha256
+ ex2) "secp160k1 sha1" // 160bit security + sha1
+ hashName : sha1 sha224 sha256 sha384 sha512
+*/
+void SystemInit(const std::string& param) throw(std::exception)
+{
+ std::istringstream iss(param);
+ std::string ecParamStr;
+ std::string hashNameStr;
+ if (iss >> ecParamStr >> hashNameStr) {
+ Param& p = Param::getParam();
+ p.ecParam = mcl::getEcParam(ecParamStr);
+ Zn::init(p.ecParam->n);
+ Fp::init(p.ecParam->p);
+ Ec::init(p.ecParam->a, p.ecParam->b);
+ p.hashName = cybozu::crypto::Hash::getName(hashNameStr);
+ return;
+ }
+ throw cybozu::Exception("SystemInit:bad param") << param;
+}
+
+class CipherText {
+ Elgamal::CipherText self_;
+ friend class PublicKey;
+ friend class PrivateKey;
+public:
+ std::string toStr() const throw(std::exception) { return self_.toStr(); }
+ std::string toString() const throw(std::exception) { return toStr(); }
+ void fromStr(const std::string& str) throw(std::exception) { self_.fromStr(str); }
+
+ void add(const CipherText& c) throw(std::exception) { self_.add(c.self_); }
+ void mul(int m) throw(std::exception)
+ {
+ self_.mul(m);
+ }
+ void mul(const std::string& str) throw(std::exception)
+ {
+ Zn zn(str);
+ self_.mul(zn);
+ }
+};
+
+class PublicKey {
+ Elgamal::PublicKey self_;
+ friend class PrivateKey;
+public:
+ std::string toStr() const throw(std::exception) { return self_.toStr(); }
+ std::string toString() const throw(std::exception) { return toStr(); }
+ void fromStr(const std::string& str) throw(std::exception) { self_.fromStr(str); }
+
+ void save(const std::string& fileName) const throw(std::exception)
+ {
+ std::ofstream ofs(fileName.c_str(), std::ios::binary);
+ if (!(ofs << self_)) throw cybozu::Exception("PublicKey:save") << fileName;
+ }
+ void load(const std::string& fileName) throw(std::exception)
+ {
+ std::ifstream ifs(fileName.c_str(), std::ios::binary);
+ if (!(ifs >> self_)) throw cybozu::Exception("PublicKey:load") << fileName;
+ }
+ void enc(CipherText& c, int m) const throw(std::exception)
+ {
+ self_.enc(c.self_, m, Param::getParam().rg);
+ }
+ void enc(CipherText& c, const std::string& str) const throw(std::exception)
+ {
+ Zn zn(str);
+ self_.enc(c.self_, zn, Param::getParam().rg);
+ }
+ void rerandomize(CipherText& c) const throw(std::exception)
+ {
+ self_.rerandomize(c.self_, Param::getParam().rg);
+ }
+ void add(CipherText& c, int m) const throw(std::exception)
+ {
+ self_.add(c.self_, m);
+ }
+ void add(CipherText& c, const std::string& str) const throw(std::exception)
+ {
+ Zn zn(str);
+ self_.add(c.self_, zn);
+ }
+};
+
+class PrivateKey {
+ Elgamal::PrivateKey self_;
+public:
+ std::string toStr() const throw(std::exception) { return self_.toStr(); }
+ std::string toString() const throw(std::exception) { return toStr(); }
+ void fromStr(const std::string& str) throw(std::exception) { self_.fromStr(str); }
+
+ void save(const std::string& fileName) const throw(std::exception)
+ {
+ std::ofstream ofs(fileName.c_str(), std::ios::binary);
+ if (!(ofs << self_)) throw cybozu::Exception("PrivateKey:save") << fileName;
+ }
+ void load(const std::string& fileName) throw(std::exception)
+ {
+ std::ifstream ifs(fileName.c_str(), std::ios::binary);
+ if (!(ifs >> self_)) throw cybozu::Exception("PrivateKey:load") << fileName;
+ }
+ void init() throw(std::exception)
+ {
+ Param& p = Param::getParam();
+ const Fp x0(p.ecParam->gx);
+ const Fp y0(p.ecParam->gy);
+ Ec P(x0, y0);
+ self_.init(P, Zn::getBitSize(), p.rg);
+ }
+ PublicKey getPublicKey() const throw(std::exception)
+ {
+ PublicKey ret;
+ ret.self_ = self_.getPublicKey();
+ return ret;
+ }
+ int dec(const CipherText& c, bool *b = 0) const throw(std::exception)
+ {
+ return self_.dec(c.self_, b);
+ }
+ void setCache(int rangeMin, int rangeMax) throw(std::exception)
+ {
+ self_.setCache(rangeMin, rangeMax);
+ }
+ void clearCache() throw(std::exception)
+ {
+ self_.clearCache();
+ }
+};
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal_wrap.cxx b/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal_wrap.cxx
new file mode 100644
index 000000000..38d05f489
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal_wrap.cxx
@@ -0,0 +1,1129 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 3.0.12
+ *
+ * This file is not intended to be easily readable and contains a number of
+ * coding conventions designed to improve portability and efficiency. Do not make
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+
+#ifndef SWIGJAVA
+#define SWIGJAVA
+#endif
+
+
+
+#ifdef __cplusplus
+/* SwigValueWrapper is described in swig.swg */
+template<typename T> class SwigValueWrapper {
+ struct SwigMovePointer {
+ T *ptr;
+ SwigMovePointer(T *p) : ptr(p) { }
+ ~SwigMovePointer() { delete ptr; }
+ SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; }
+ } pointer;
+ SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs);
+ SwigValueWrapper(const SwigValueWrapper<T>& rhs);
+public:
+ SwigValueWrapper() : pointer(0) { }
+ SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; }
+ operator T&() const { return *pointer.ptr; }
+ T *operator&() { return pointer.ptr; }
+};
+
+template <typename T> T SwigValueInit() {
+ return T();
+}
+#endif
+
+/* -----------------------------------------------------------------------------
+ * This section contains generic SWIG labels for method/variable
+ * declarations/attributes, and other compiler dependent labels.
+ * ----------------------------------------------------------------------------- */
+
+/* template workaround for compilers that cannot correctly implement the C++ standard */
+#ifndef SWIGTEMPLATEDISAMBIGUATOR
+# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560)
+# define SWIGTEMPLATEDISAMBIGUATOR template
+# elif defined(__HP_aCC)
+/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */
+/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */
+# define SWIGTEMPLATEDISAMBIGUATOR template
+# else
+# define SWIGTEMPLATEDISAMBIGUATOR
+# endif
+#endif
+
+/* inline attribute */
+#ifndef SWIGINLINE
+# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__))
+# define SWIGINLINE inline
+# else
+# define SWIGINLINE
+# endif
+#endif
+
+/* attribute recognised by some compilers to avoid 'unused' warnings */
+#ifndef SWIGUNUSED
+# if defined(__GNUC__)
+# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+# define SWIGUNUSED __attribute__ ((__unused__))
+# else
+# define SWIGUNUSED
+# endif
+# elif defined(__ICC)
+# define SWIGUNUSED __attribute__ ((__unused__))
+# else
+# define SWIGUNUSED
+# endif
+#endif
+
+#ifndef SWIG_MSC_UNSUPPRESS_4505
+# if defined(_MSC_VER)
+# pragma warning(disable : 4505) /* unreferenced local function has been removed */
+# endif
+#endif
+
+#ifndef SWIGUNUSEDPARM
+# ifdef __cplusplus
+# define SWIGUNUSEDPARM(p)
+# else
+# define SWIGUNUSEDPARM(p) p SWIGUNUSED
+# endif
+#endif
+
+/* internal SWIG method */
+#ifndef SWIGINTERN
+# define SWIGINTERN static SWIGUNUSED
+#endif
+
+/* internal inline SWIG method */
+#ifndef SWIGINTERNINLINE
+# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE
+#endif
+
+/* exporting methods */
+#if defined(__GNUC__)
+# if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+# ifndef GCC_HASCLASSVISIBILITY
+# define GCC_HASCLASSVISIBILITY
+# endif
+# endif
+#endif
+
+#ifndef SWIGEXPORT
+# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# if defined(STATIC_LINKED)
+# define SWIGEXPORT
+# else
+# define SWIGEXPORT __declspec(dllexport)
+# endif
+# else
+# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)
+# define SWIGEXPORT __attribute__ ((visibility("default")))
+# else
+# define SWIGEXPORT
+# endif
+# endif
+#endif
+
+/* calling conventions for Windows */
+#ifndef SWIGSTDCALL
+# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# define SWIGSTDCALL __stdcall
+# else
+# define SWIGSTDCALL
+# endif
+#endif
+
+/* Deal with Microsoft's attempt at deprecating C standard runtime functions */
+#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+# define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */
+#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE)
+# define _SCL_SECURE_NO_DEPRECATE
+#endif
+
+/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */
+#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES)
+# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
+#endif
+
+/* Intel's compiler complains if a variable which was never initialised is
+ * cast to void, which is a common idiom which we use to indicate that we
+ * are aware a variable isn't used. So we just silence that warning.
+ * See: https://github.com/swig/swig/issues/192 for more discussion.
+ */
+#ifdef __INTEL_COMPILER
+# pragma warning disable 592
+#endif
+
+
+/* Fix for jlong on some versions of gcc on Windows */
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+ typedef long long __int64;
+#endif
+
+/* Fix for jlong on 64-bit x86 Solaris */
+#if defined(__x86_64)
+# ifdef _LP64
+# undef _LP64
+# endif
+#endif
+
+#include <jni.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Support for throwing Java exceptions */
+typedef enum {
+ SWIG_JavaOutOfMemoryError = 1,
+ SWIG_JavaIOException,
+ SWIG_JavaRuntimeException,
+ SWIG_JavaIndexOutOfBoundsException,
+ SWIG_JavaArithmeticException,
+ SWIG_JavaIllegalArgumentException,
+ SWIG_JavaNullPointerException,
+ SWIG_JavaDirectorPureVirtual,
+ SWIG_JavaUnknownError
+} SWIG_JavaExceptionCodes;
+
+typedef struct {
+ SWIG_JavaExceptionCodes code;
+ const char *java_exception;
+} SWIG_JavaExceptions_t;
+
+
+static void SWIGUNUSED SWIG_JavaThrowException(JNIEnv *jenv, SWIG_JavaExceptionCodes code, const char *msg) {
+ jclass excep;
+ static const SWIG_JavaExceptions_t java_exceptions[] = {
+ { SWIG_JavaOutOfMemoryError, "java/lang/OutOfMemoryError" },
+ { SWIG_JavaIOException, "java/io/IOException" },
+ { SWIG_JavaRuntimeException, "java/lang/RuntimeException" },
+ { SWIG_JavaIndexOutOfBoundsException, "java/lang/IndexOutOfBoundsException" },
+ { SWIG_JavaArithmeticException, "java/lang/ArithmeticException" },
+ { SWIG_JavaIllegalArgumentException, "java/lang/IllegalArgumentException" },
+ { SWIG_JavaNullPointerException, "java/lang/NullPointerException" },
+ { SWIG_JavaDirectorPureVirtual, "java/lang/RuntimeException" },
+ { SWIG_JavaUnknownError, "java/lang/UnknownError" },
+ { (SWIG_JavaExceptionCodes)0, "java/lang/UnknownError" }
+ };
+ const SWIG_JavaExceptions_t *except_ptr = java_exceptions;
+
+ while (except_ptr->code != code && except_ptr->code)
+ except_ptr++;
+
+ jenv->ExceptionClear();
+ excep = jenv->FindClass(except_ptr->java_exception);
+ if (excep)
+ jenv->ThrowNew(excep, msg);
+}
+
+
+/* Contract support */
+
+#define SWIG_contract_assert(nullreturn, expr, msg) if (!(expr)) {SWIG_JavaThrowException(jenv, SWIG_JavaIllegalArgumentException, msg); return nullreturn; } else
+
+
+#include <string>
+
+
+#include <typeinfo>
+#include <stdexcept>
+
+
+#include <cybozu/random_generator.hpp>
+#include <cybozu/crypto.hpp>
+#include <mcl/fp.hpp>
+#include <mcl/ecparam.hpp>
+struct Param {
+const mcl::EcParam *ecParam;
+cybozu::RandomGenerator rg;
+cybozu::crypto::Hash::Name hashName;
+static inline Param& getParam()
+{
+ static Param p;
+ return p;
+}
+};
+
+#include "elgamal_impl.hpp"
+
+
+static bool *new_p_bool() {
+ return new bool();
+}
+
+static bool *copy_p_bool(bool value) {
+ return new bool(value);
+}
+
+static void delete_p_bool(bool *obj) {
+ if (obj) delete obj;
+}
+
+static void p_bool_assign(bool *obj, bool value) {
+ *obj = value;
+}
+
+static bool p_bool_value(bool *obj) {
+ return *obj;
+}
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_ElgamalJNI_new_1p_1bool(JNIEnv *jenv, jclass jcls) {
+ jlong jresult = 0 ;
+ bool *result = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ result = (bool *)new_p_bool();
+ *(bool **)&jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_ElgamalJNI_copy_1p_1bool(JNIEnv *jenv, jclass jcls, jboolean jarg1) {
+ jlong jresult = 0 ;
+ bool arg1 ;
+ bool *result = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ arg1 = jarg1 ? true : false;
+ result = (bool *)copy_p_bool(arg1);
+ *(bool **)&jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_delete_1p_1bool(JNIEnv *jenv, jclass jcls, jlong jarg1) {
+ bool *arg1 = (bool *) 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ arg1 = *(bool **)&jarg1;
+ delete_p_bool(arg1);
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_p_1bool_1assign(JNIEnv *jenv, jclass jcls, jlong jarg1, jboolean jarg2) {
+ bool *arg1 = (bool *) 0 ;
+ bool arg2 ;
+
+ (void)jenv;
+ (void)jcls;
+ arg1 = *(bool **)&jarg1;
+ arg2 = jarg2 ? true : false;
+ p_bool_assign(arg1,arg2);
+}
+
+
+SWIGEXPORT jboolean JNICALL Java_com_herumi_mcl_ElgamalJNI_p_1bool_1value(JNIEnv *jenv, jclass jcls, jlong jarg1) {
+ jboolean jresult = 0 ;
+ bool *arg1 = (bool *) 0 ;
+ bool result;
+
+ (void)jenv;
+ (void)jcls;
+ arg1 = *(bool **)&jarg1;
+ result = (bool)p_bool_value(arg1);
+ jresult = (jboolean)result;
+ return jresult;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_SystemInit(JNIEnv *jenv, jclass jcls, jstring jarg1) {
+ std::string *arg1 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ if(!jarg1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg1_pstr = (const char *)jenv->GetStringUTFChars(jarg1, 0);
+ if (!arg1_pstr) return ;
+ std::string arg1_str(arg1_pstr);
+ arg1 = &arg1_str;
+ jenv->ReleaseStringUTFChars(jarg1, arg1_pstr);
+ try {
+ SystemInit((std::string const &)*arg1);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1toStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ jstring jresult = 0 ;
+ CipherText *arg1 = (CipherText *) 0 ;
+ std::string result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(CipherText **)&jarg1;
+ try {
+ result = ((CipherText const *)arg1)->toStr();
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return 0;
+ }
+
+ jresult = jenv->NewStringUTF((&result)->c_str());
+ return jresult;
+}
+
+
+SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1toString(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ jstring jresult = 0 ;
+ CipherText *arg1 = (CipherText *) 0 ;
+ std::string result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(CipherText **)&jarg1;
+ try {
+ result = ((CipherText const *)arg1)->toString();
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return 0;
+ }
+
+ jresult = jenv->NewStringUTF((&result)->c_str());
+ return jresult;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1fromStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
+ CipherText *arg1 = (CipherText *) 0 ;
+ std::string *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(CipherText **)&jarg1;
+ if(!jarg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2_pstr) return ;
+ std::string arg2_str(arg2_pstr);
+ arg2 = &arg2_str;
+ jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
+ try {
+ (arg1)->fromStr((std::string const &)*arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1add(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) {
+ CipherText *arg1 = (CipherText *) 0 ;
+ CipherText *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ arg1 = *(CipherText **)&jarg1;
+ arg2 = *(CipherText **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "CipherText const & reference is null");
+ return ;
+ }
+ try {
+ (arg1)->add((CipherText const &)*arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1mul_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2) {
+ CipherText *arg1 = (CipherText *) 0 ;
+ int arg2 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(CipherText **)&jarg1;
+ arg2 = (int)jarg2;
+ try {
+ (arg1)->mul(arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1mul_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
+ CipherText *arg1 = (CipherText *) 0 ;
+ std::string *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(CipherText **)&jarg1;
+ if(!jarg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2_pstr) return ;
+ std::string arg2_str(arg2_pstr);
+ arg2 = &arg2_str;
+ jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
+ try {
+ (arg1)->mul((std::string const &)*arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_ElgamalJNI_new_1CipherText(JNIEnv *jenv, jclass jcls) {
+ jlong jresult = 0 ;
+ CipherText *result = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ result = (CipherText *)new CipherText();
+ *(CipherText **)&jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_delete_1CipherText(JNIEnv *jenv, jclass jcls, jlong jarg1) {
+ CipherText *arg1 = (CipherText *) 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ arg1 = *(CipherText **)&jarg1;
+ delete arg1;
+}
+
+
+SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1toStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ jstring jresult = 0 ;
+ PublicKey *arg1 = (PublicKey *) 0 ;
+ std::string result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(PublicKey **)&jarg1;
+ try {
+ result = ((PublicKey const *)arg1)->toStr();
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return 0;
+ }
+
+ jresult = jenv->NewStringUTF((&result)->c_str());
+ return jresult;
+}
+
+
+SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1toString(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ jstring jresult = 0 ;
+ PublicKey *arg1 = (PublicKey *) 0 ;
+ std::string result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(PublicKey **)&jarg1;
+ try {
+ result = ((PublicKey const *)arg1)->toString();
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return 0;
+ }
+
+ jresult = jenv->NewStringUTF((&result)->c_str());
+ return jresult;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1fromStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
+ PublicKey *arg1 = (PublicKey *) 0 ;
+ std::string *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(PublicKey **)&jarg1;
+ if(!jarg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2_pstr) return ;
+ std::string arg2_str(arg2_pstr);
+ arg2 = &arg2_str;
+ jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
+ try {
+ (arg1)->fromStr((std::string const &)*arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1save(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
+ PublicKey *arg1 = (PublicKey *) 0 ;
+ std::string *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(PublicKey **)&jarg1;
+ if(!jarg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2_pstr) return ;
+ std::string arg2_str(arg2_pstr);
+ arg2 = &arg2_str;
+ jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
+ try {
+ ((PublicKey const *)arg1)->save((std::string const &)*arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1load(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
+ PublicKey *arg1 = (PublicKey *) 0 ;
+ std::string *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(PublicKey **)&jarg1;
+ if(!jarg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2_pstr) return ;
+ std::string arg2_str(arg2_pstr);
+ arg2 = &arg2_str;
+ jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
+ try {
+ (arg1)->load((std::string const &)*arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1enc_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jint jarg3) {
+ PublicKey *arg1 = (PublicKey *) 0 ;
+ CipherText *arg2 = 0 ;
+ int arg3 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ arg1 = *(PublicKey **)&jarg1;
+ arg2 = *(CipherText **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "CipherText & reference is null");
+ return ;
+ }
+ arg3 = (int)jarg3;
+ try {
+ ((PublicKey const *)arg1)->enc(*arg2,arg3);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1enc_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jstring jarg3) {
+ PublicKey *arg1 = (PublicKey *) 0 ;
+ CipherText *arg2 = 0 ;
+ std::string *arg3 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ arg1 = *(PublicKey **)&jarg1;
+ arg2 = *(CipherText **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "CipherText & reference is null");
+ return ;
+ }
+ if(!jarg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg3_pstr = (const char *)jenv->GetStringUTFChars(jarg3, 0);
+ if (!arg3_pstr) return ;
+ std::string arg3_str(arg3_pstr);
+ arg3 = &arg3_str;
+ jenv->ReleaseStringUTFChars(jarg3, arg3_pstr);
+ try {
+ ((PublicKey const *)arg1)->enc(*arg2,(std::string const &)*arg3);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1rerandomize(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) {
+ PublicKey *arg1 = (PublicKey *) 0 ;
+ CipherText *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ arg1 = *(PublicKey **)&jarg1;
+ arg2 = *(CipherText **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "CipherText & reference is null");
+ return ;
+ }
+ try {
+ ((PublicKey const *)arg1)->rerandomize(*arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1add_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jint jarg3) {
+ PublicKey *arg1 = (PublicKey *) 0 ;
+ CipherText *arg2 = 0 ;
+ int arg3 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ arg1 = *(PublicKey **)&jarg1;
+ arg2 = *(CipherText **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "CipherText & reference is null");
+ return ;
+ }
+ arg3 = (int)jarg3;
+ try {
+ ((PublicKey const *)arg1)->add(*arg2,arg3);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1add_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jstring jarg3) {
+ PublicKey *arg1 = (PublicKey *) 0 ;
+ CipherText *arg2 = 0 ;
+ std::string *arg3 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ arg1 = *(PublicKey **)&jarg1;
+ arg2 = *(CipherText **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "CipherText & reference is null");
+ return ;
+ }
+ if(!jarg3) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg3_pstr = (const char *)jenv->GetStringUTFChars(jarg3, 0);
+ if (!arg3_pstr) return ;
+ std::string arg3_str(arg3_pstr);
+ arg3 = &arg3_str;
+ jenv->ReleaseStringUTFChars(jarg3, arg3_pstr);
+ try {
+ ((PublicKey const *)arg1)->add(*arg2,(std::string const &)*arg3);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_ElgamalJNI_new_1PublicKey(JNIEnv *jenv, jclass jcls) {
+ jlong jresult = 0 ;
+ PublicKey *result = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ result = (PublicKey *)new PublicKey();
+ *(PublicKey **)&jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_delete_1PublicKey(JNIEnv *jenv, jclass jcls, jlong jarg1) {
+ PublicKey *arg1 = (PublicKey *) 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ arg1 = *(PublicKey **)&jarg1;
+ delete arg1;
+}
+
+
+SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1toStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ jstring jresult = 0 ;
+ PrivateKey *arg1 = (PrivateKey *) 0 ;
+ std::string result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(PrivateKey **)&jarg1;
+ try {
+ result = ((PrivateKey const *)arg1)->toStr();
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return 0;
+ }
+
+ jresult = jenv->NewStringUTF((&result)->c_str());
+ return jresult;
+}
+
+
+SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1toString(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ jstring jresult = 0 ;
+ PrivateKey *arg1 = (PrivateKey *) 0 ;
+ std::string result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(PrivateKey **)&jarg1;
+ try {
+ result = ((PrivateKey const *)arg1)->toString();
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return 0;
+ }
+
+ jresult = jenv->NewStringUTF((&result)->c_str());
+ return jresult;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1fromStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
+ PrivateKey *arg1 = (PrivateKey *) 0 ;
+ std::string *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(PrivateKey **)&jarg1;
+ if(!jarg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2_pstr) return ;
+ std::string arg2_str(arg2_pstr);
+ arg2 = &arg2_str;
+ jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
+ try {
+ (arg1)->fromStr((std::string const &)*arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1save(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
+ PrivateKey *arg1 = (PrivateKey *) 0 ;
+ std::string *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(PrivateKey **)&jarg1;
+ if(!jarg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2_pstr) return ;
+ std::string arg2_str(arg2_pstr);
+ arg2 = &arg2_str;
+ jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
+ try {
+ ((PrivateKey const *)arg1)->save((std::string const &)*arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1load(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
+ PrivateKey *arg1 = (PrivateKey *) 0 ;
+ std::string *arg2 = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(PrivateKey **)&jarg1;
+ if(!jarg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return ;
+ }
+ const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2_pstr) return ;
+ std::string arg2_str(arg2_pstr);
+ arg2 = &arg2_str;
+ jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
+ try {
+ (arg1)->load((std::string const &)*arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1init(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ PrivateKey *arg1 = (PrivateKey *) 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(PrivateKey **)&jarg1;
+ try {
+ (arg1)->init();
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1getPublicKey(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ jlong jresult = 0 ;
+ PrivateKey *arg1 = (PrivateKey *) 0 ;
+ PublicKey result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(PrivateKey **)&jarg1;
+ try {
+ result = ((PrivateKey const *)arg1)->getPublicKey();
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return 0;
+ }
+
+ *(PublicKey **)&jresult = new PublicKey((const PublicKey &)result);
+ return jresult;
+}
+
+
+SWIGEXPORT jint JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1dec_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3) {
+ jint jresult = 0 ;
+ PrivateKey *arg1 = (PrivateKey *) 0 ;
+ CipherText *arg2 = 0 ;
+ bool *arg3 = (bool *) 0 ;
+ int result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ arg1 = *(PrivateKey **)&jarg1;
+ arg2 = *(CipherText **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "CipherText const & reference is null");
+ return 0;
+ }
+ arg3 = *(bool **)&jarg3;
+ try {
+ result = (int)((PrivateKey const *)arg1)->dec((CipherText const &)*arg2,arg3);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return 0;
+ }
+
+ jresult = (jint)result;
+ return jresult;
+}
+
+
+SWIGEXPORT jint JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1dec_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) {
+ jint jresult = 0 ;
+ PrivateKey *arg1 = (PrivateKey *) 0 ;
+ CipherText *arg2 = 0 ;
+ int result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ (void)jarg2_;
+ arg1 = *(PrivateKey **)&jarg1;
+ arg2 = *(CipherText **)&jarg2;
+ if (!arg2) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "CipherText const & reference is null");
+ return 0;
+ }
+ try {
+ result = (int)((PrivateKey const *)arg1)->dec((CipherText const &)*arg2);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return 0;
+ }
+
+ jresult = (jint)result;
+ return jresult;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1setCache(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2, jint jarg3) {
+ PrivateKey *arg1 = (PrivateKey *) 0 ;
+ int arg2 ;
+ int arg3 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(PrivateKey **)&jarg1;
+ arg2 = (int)jarg2;
+ arg3 = (int)jarg3;
+ try {
+ (arg1)->setCache(arg2,arg3);
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1clearCache(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
+ PrivateKey *arg1 = (PrivateKey *) 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(PrivateKey **)&jarg1;
+ try {
+ (arg1)->clearCache();
+ }
+ catch(std::exception &_e) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
+ return ;
+ }
+
+}
+
+
+SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_ElgamalJNI_new_1PrivateKey(JNIEnv *jenv, jclass jcls) {
+ jlong jresult = 0 ;
+ PrivateKey *result = 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ result = (PrivateKey *)new PrivateKey();
+ *(PrivateKey **)&jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_delete_1PrivateKey(JNIEnv *jenv, jclass jcls, jlong jarg1) {
+ PrivateKey *arg1 = (PrivateKey *) 0 ;
+
+ (void)jenv;
+ (void)jcls;
+ arg1 = *(PrivateKey **)&jarg1;
+ delete arg1;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/java.md b/vendor/github.com/dexon-foundation/mcl/ffi/java/java.md
new file mode 100644
index 000000000..3fe861351
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/java.md
@@ -0,0 +1,95 @@
+# JNI for mcl (experimental)
+This library provides functionality to compute the optimal ate pairing
+over Barreto-Naehrig (BN) curves.
+
+# Initialization
+Load the library `mcl_bn256`.
+```
+import com.herumi.mcl.*;
+
+System.loadLibrary("mcl_bn256");
+```
+
+# Classes
+* `G1` ; The cyclic group instantiated as E(Fp)[r] where where r = p + 1 - t.
+* `G2` ; The cyclic group instantiated as the inverse image of E'(Fp^2)[r].
+* `GT` ; The cyclic group in the image of the optimal ate pairing.
+ * `e : G1 x G2 -> GT`
+* `Fr` ; The finite field with characteristic r.
+
+# Methods and Functions
+## Fr
+* `Fr::setInt(int x)` ; set by x
+* `Fr::setStr(String str)` ; set by str such as "123", "0xfff", etc.
+* `Fr::setRand()` ; randomly set
+* `Bn256.neg(Fr y, Fr x)` ; `y = -x`
+* `Bn256.add(Fr z, Fr x, Fr y)` ; `z = x + y`
+* `Bn256.sub(Fr z, Fr x, Fr y)` ; `z = x - y`
+* `Bn256.mul(Fr z, Fr x, Fr y)` ; `z = x * y`
+* `Bn256.div(Fr z, Fr x, Fr y)` ; `z = x / y`
+
+## G1
+
+* `G1::set(String x, String y)` ; set by (x, y)
+* `G1::hashAndMapToG1(String m)` ; take SHA-256 of m and map it to an element of G1
+* `G1::setStr(String str)` ; set by the result of `toString()` method
+* `Bn256.neg(G1 y, G1 x)` ; `y = -x`
+* `Bn256.dbl(G1 y, G1 x)` ; `y = 2x`
+* `Bn256.add(G1 z, G1 x, G1 y)` ; `z = x + y`
+* `Bn256.sub(G1 z, G1 x, G1 y)` ; `z = x - y`
+* `Bn256.mul(G1 z, G1 x, Fr y)` ; `z = x * y`
+
+## G2
+
+* `G2::set(String xa, String xb, String ya, String yb)` ; set by ((xa, xb), (ya, yb))
+* `G2::setStr(String str)` ; set by the result of `toString()` method
+* `Bn256.neg(G2 y, G2 x)` ; `y = -x`
+* `Bn256.dbl(G2 y, G2 x)` ; `y = 2x`
+* `Bn256.add(G2 z, G2 x, G2 y)` ; `z = x + y`
+* `Bn256.sub(G2 z, G2 x, G2 y)` ; `z = x - y`
+* `Bn256.mul(G2 z, G2 x, Fr y)` ; `z = x * y`
+
+## GT
+
+* `GT::setStr(String str)` ; set by the result of `toString()` method
+* `Bn256.mul(GT z, GT x, GT y)` ; `z = x * y`
+* `Bn256.pow(GT z, GT x, Fr y)` ; `z = x ^ y`
+
+## pairing
+* `Bn256.pairing(GT e, G1 P, G2 Q)` ; e = e(P, Q)
+
+# BLS signature sample
+```
+String xa = "12723517038133731887338407189719511622662176727675373276651903807414909099441";
+String xb = "4168783608814932154536427934509895782246573715297911553964171371032945126671";
+String ya = "13891744915211034074451795021214165905772212241412891944830863846330766296736";
+String yb = "7937318970632701341203597196594272556916396164729705624521405069090520231616";
+
+G2 Q = new G2(xa, xb, ya, yb); // fixed point of G2
+
+Fr s = new Fr();
+s.setRand(); // secret key
+G2 pub = new G2();
+Bn256.mul(pub, Q, s); // public key = sQ
+
+String m = "signature test";
+G1 H = new G1();
+H.hashAndMapToG1(m); // H = Hash(m)
+G1 sign = new G1();
+Bn256.mul(sign, H, s); // signature of m = s H
+
+GT e1 = new GT();
+GT e2 = new GT();
+Bn256.pairing(e1, H, pub); // e1 = e(H, s Q)
+Bn256.pairing(e2, sign, Q); // e2 = e(s H, Q);
+assertBool("verify signature", e1.equals(e2));
+```
+
+# Make test
+```
+cd java
+make test_bn256
+```
+
+# Sample code
+[Bn256Test.java](https://github.com/herumi/mcl/blob/master/java/Bn256Test.java)
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/make_wrap.bat b/vendor/github.com/dexon-foundation/mcl/ffi/java/make_wrap.bat
new file mode 100644
index 000000000..b7008bc02
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/make_wrap.bat
@@ -0,0 +1,23 @@
+@echo off
+call set-java-path.bat
+set JAVA_INCLUDE=%JAVA_DIR%\include
+set SWIG=..\..\..\..\p\swig\swig.exe
+set PACKAGE_NAME=com.herumi.mcl
+set PACKAGE_DIR=%PACKAGE_NAME:.=\%
+if /i "%1"=="" (
+ set NAME=elgamal
+) else (
+ set NAME=%1
+)
+
+echo [[run swig]]
+mkdir %PACKAGE_DIR%
+set TOP_DIR=../..
+%SWIG% -java -package %PACKAGE_NAME% -outdir %PACKAGE_DIR% -c++ -Wall %NAME%.i
+echo [[make dll]]
+cl /MT /DNOMINMAX /LD /Ox /DNDEBUG /EHsc %NAME%_wrap.cxx %TOP_DIR%/src/fp.cpp -DMCL_NO_AUTOLINK -I%JAVA_INCLUDE% -I%JAVA_INCLUDE%\win32 -I%TOP_DIR%/include -I%TOP_DIR%/../cybozulib/include -I%TOP_DIR%/../cybozulib_ext/include -I%TOP_DIR%/../xbyak /link /LIBPATH:%TOP_DIR%/../cybozulib_ext/lib /OUT:%TOP_DIR%/bin/mcl_%NAME%.dll
+
+call run-%NAME%.bat
+
+echo [[make jar]]
+%JAVA_DIR%\bin\jar cvf mcl.jar com
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/run-bn256.bat b/vendor/github.com/dexon-foundation/mcl/ffi/java/run-bn256.bat
new file mode 100644
index 000000000..903876ec6
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/run-bn256.bat
@@ -0,0 +1,9 @@
+@echo off
+echo [[compile Bn256Test.java]]
+%JAVA_DIR%\bin\javac Bn256Test.java
+
+echo [[run Bn256Test]]
+set TOP_DIR=..\..
+pushd %TOP_DIR%\bin
+%JAVA_DIR%\bin\java -classpath ../ffi/java Bn256Test %1 %2 %3 %4 %5 %6
+popd
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/run-elgamal.bat b/vendor/github.com/dexon-foundation/mcl/ffi/java/run-elgamal.bat
new file mode 100644
index 000000000..8b889a64c
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/run-elgamal.bat
@@ -0,0 +1,9 @@
+@echo off
+echo [[compile ElgamalTest.java]]
+%JAVA_DIR%\bin\javac ElgamalTest.java
+
+echo [[run ElgamalTest]]
+set TOP_DIR=..\..
+pushd %TOP_DIR%\bin
+%JAVA_DIR%\bin\java -classpath ../ffi/java ElgamalTest %1 %2 %3 %4 %5 %6
+popd
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/set-java-path.bat b/vendor/github.com/dexon-foundation/mcl/ffi/java/set-java-path.bat
new file mode 100644
index 000000000..c66f81830
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/set-java-path.bat
@@ -0,0 +1,8 @@
+@echo off
+if "%JAVA_HOME%"=="" (
+ set JAVA_DIR=c:/p/Java/jdk
+) else (
+ set JAVA_DIR=%JAVA_HOME%
+)
+echo JAVA_DIR=%JAVA_DIR%
+rem set PATH=%PATH%;%JAVA_DIR%\bin
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/js/export-functions.py b/vendor/github.com/dexon-foundation/mcl/ffi/js/export-functions.py
new file mode 100644
index 000000000..2a929564b
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/js/export-functions.py
@@ -0,0 +1,73 @@
+import sys, re, argparse
+
+#RE_PROTOTYPE = re.compile(r'MCLBN_DLL_API\s\w\s\w\([^)]*\);')
+RE_PROTOTYPE = re.compile(r'\w*\s(\w*)\s(\w*)\(([^)]*)\);')
+def export_functions(args, fileNames, reToAddUnderscore):
+ modName = args.js
+ json = args.json
+ if not reToAddUnderscore:
+ reToAddUnderscore = r'(mclBn_init|setStr|getStr|[sS]erialize|setLittleEndian|setHashOf|hashAndMapTo|DecStr|HexStr|HashTo|blsSign|blsVerify|GetCurveOrder|GetFieldOrder|KeyShare|KeyRecover|blsSignatureRecover|blsInit)'
+ reSpecialFunctionName = re.compile(reToAddUnderscore)
+ if json:
+ print '['
+ elif modName:
+ print 'function define_exported_' + modName + '(mod) {'
+ comma = ''
+ for fileName in fileNames:
+ with open(fileName, 'rb') as f:
+ for line in f.readlines():
+ p = RE_PROTOTYPE.search(line)
+ if p:
+ ret = p.group(1)
+ name = p.group(2)
+ arg = p.group(3)
+ if json or modName:
+ retType = 'null' if ret == 'void' else 'number'
+ if arg == '' or arg == 'void':
+ paramNum = 0
+ else:
+ paramNum = len(arg.split(','))
+ if reSpecialFunctionName.search(name):
+ exportName = '_' + name # to wrap function
+ else:
+ exportName = name
+ if json:
+ print comma + '{'
+ if comma == '':
+ comma = ','
+ print ' "name":"{0}",'.format(name)
+ print ' "exportName":"{0}",'.format(exportName)
+ print ' "ret":"{0}",'.format(retType)
+ print ' "args":[',
+ if paramNum > 0:
+ print '"number"' + (', "number"' * (paramNum - 1)),
+ print ']'
+ print '}'
+ else:
+ paramType = '[' + ("'number', " * paramNum) + ']'
+ print "{0} = mod.cwrap('{1}', '{2}', {3})".format(exportName, name, retType, paramType)
+ else:
+ print comma + "'_" + name + "'",
+ if comma == '':
+ comma = ','
+ if json:
+ print ']'
+ elif modName:
+ print '}'
+
+def main():
+ p = argparse.ArgumentParser('export_functions')
+ p.add_argument('header', type=str, nargs='+', help='headers')
+ p.add_argument('-js', type=str, nargs='?', help='module name')
+ p.add_argument('-re', type=str, nargs='?', help='regular expression file to add underscore to function name')
+ p.add_argument('-json', action='store_true', help='output json')
+ args = p.parse_args()
+
+ reToAddUnderscore = ''
+ if args.re:
+ reToAddUnderscore = open(args.re).read().strip()
+ export_functions(args, args.header, reToAddUnderscore)
+
+if __name__ == '__main__':
+ main()
+
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/js/pre-mcl.js b/vendor/github.com/dexon-foundation/mcl/ffi/js/pre-mcl.js
new file mode 100644
index 000000000..ebc93e581
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/js/pre-mcl.js
@@ -0,0 +1,5 @@
+if (typeof __dirname === 'string') {
+ var Module = {}
+ Module.wasmBinaryFile = __dirname + '/mcl_c.wasm'
+}
+
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/python/pairing.py b/vendor/github.com/dexon-foundation/mcl/ffi/python/pairing.py
new file mode 100644
index 000000000..88b729176
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/python/pairing.py
@@ -0,0 +1,80 @@
+from ctypes import *
+from ctypes.wintypes import LPWSTR, LPCSTR, LPVOID
+
+g_lib = None
+
+def BN256_init():
+ global g_lib
+ g_lib = cdll.LoadLibrary("../../bin/bn256.dll")
+ ret = g_lib.BN256_init()
+ if ret:
+ print "ERR BN256_init"
+
+class Fr(Structure):
+ _fields_ = [("v", c_ulonglong * 4)]
+ def setInt(self, v):
+ g_lib.BN256_Fr_setInt(self.v, v)
+ def setStr(self, s):
+ ret = g_lib.BN256_Fr_setStr(self.v, c_char_p(s))
+ if ret:
+ print("ERR Fr:setStr")
+ def __str__(self):
+ svLen = 1024
+ sv = create_string_buffer('\0' * svLen)
+ ret = g_lib.BN256_Fr_getStr(sv, svLen, self.v)
+ if ret:
+ print("ERR Fr:getStr")
+ return sv.value
+ def isZero(self, rhs):
+ return g_lib.BN256_Fr_isZero(self.v) != 0
+ def isOne(self, rhs):
+ return g_lib.BN256_Fr_isOne(self.v) != 0
+ def __eq__(self, rhs):
+ return g_lib.BN256_Fr_isEqual(self.v, rhs.v) != 0
+ def __ne__(self, rhs):
+ return not(P == Q)
+ def __add__(self, rhs):
+ ret = Fr()
+ g_lib.BN256_Fr_add(ret.v, self.v, rhs.v)
+ return ret
+ def __sub__(self, rhs):
+ ret = Fr()
+ g_lib.BN256_Fr_sub(ret.v, self.v, rhs.v)
+ return ret
+ def __mul__(self, rhs):
+ ret = Fr()
+ g_lib.BN256_Fr_mul(ret.v, self.v, rhs.v)
+ return ret
+ def __div__(self, rhs):
+ ret = Fr()
+ g_lib.BN256_Fr_div(ret.v, self.v, rhs.v)
+ return ret
+ def __neg__(self):
+ ret = Fr()
+ g_lib.BN256_Fr_neg(ret.v, self.v)
+ return ret
+
+def Fr_add(z, x, y):
+ g_lib.BN256_Fr_add(z.v, x.v, y.v)
+
+def Fr_sub(z, x, y):
+ g_lib.BN256_Fr_sub(z.v, x.v, y.v)
+
+def Fr_mul(z, x, y):
+ g_lib.BN256_Fr_mul(z.v, x.v, y.v)
+
+def Fr_div(z, x, y):
+ g_lib.BN256_Fr_div(z.v, x.v, y.v)
+
+BN256_init()
+
+P = Fr()
+Q = Fr()
+print P == Q
+print P != Q
+P.setInt(5)
+Q.setStr("34982034824")
+print Q
+R = Fr()
+Fr_add(R, P, Q)
+print R
diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/python/she.py b/vendor/github.com/dexon-foundation/mcl/ffi/python/she.py
new file mode 100644
index 000000000..ab8975274
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/ffi/python/she.py
@@ -0,0 +1,298 @@
+import os
+import platform
+from ctypes import *
+
+MCL_BN254 = 0
+MCLBN_FR_UNIT_SIZE = 4
+MCLBN_FP_UNIT_SIZE = 4
+
+FR_SIZE = MCLBN_FR_UNIT_SIZE
+G1_SIZE = MCLBN_FP_UNIT_SIZE * 3
+G2_SIZE = MCLBN_FP_UNIT_SIZE * 6
+GT_SIZE = MCLBN_FP_UNIT_SIZE * 12
+
+SEC_SIZE = FR_SIZE * 2
+PUB_SIZE = G1_SIZE + G2_SIZE
+G1_CIPHER_SIZE = G1_SIZE * 2
+G2_CIPHER_SIZE = G2_SIZE * 2
+GT_CIPHER_SIZE = GT_SIZE * 4
+
+MCLBN_COMPILED_TIME_VAR = (MCLBN_FR_UNIT_SIZE * 10) + MCLBN_FP_UNIT_SIZE
+
+Buffer = c_ubyte * 1536
+lib = None
+
+def init(curveType=MCL_BN254):
+ global lib
+ name = platform.system()
+ if name == 'Linux':
+ libName = 'libmclshe256.so'
+ elif name == 'Darwin':
+ libName = 'libmclshe256.dylib'
+ elif name == 'Windows':
+ libName = 'mclshe256.dll'
+ else:
+ raise RuntimeError("not support yet", name)
+ lib = cdll.LoadLibrary(libName)
+ ret = lib.sheInit(MCL_BN254, MCLBN_COMPILED_TIME_VAR)
+ if ret != 0:
+ raise RuntimeError("sheInit", ret)
+ # custom setup for a function which returns pointer
+ lib.shePrecomputedPublicKeyCreate.restype = c_void_p
+
+def setRangeForDLP(hashSize):
+ ret = lib.sheSetRangeForDLP(hashSize)
+ if ret != 0:
+ raise RuntimeError("setRangeForDLP", ret)
+
+def setTryNum(tryNum):
+ ret = lib.sheSetTryNum(tryNum)
+ if ret != 0:
+ raise RuntimeError("setTryNum", ret)
+
+def hexStr(v):
+ s = ""
+ for x in v:
+ s += format(x, '02x')
+ return s
+
+class CipherTextG1(Structure):
+ _fields_ = [("v", c_ulonglong * G1_CIPHER_SIZE)]
+ def serialize(self):
+ buf = Buffer()
+ ret = lib.sheCipherTextG1Serialize(byref(buf), len(buf), byref(self.v))
+ if ret == 0:
+ raise RuntimeError("serialize")
+ return buf[0:ret]
+ def serializeToHexStr(self):
+ return hexStr(self.serialize())
+
+class CipherTextG2(Structure):
+ _fields_ = [("v", c_ulonglong * G2_CIPHER_SIZE)]
+ def serialize(self):
+ buf = Buffer()
+ ret = lib.sheCipherTextG2Serialize(byref(buf), len(buf), byref(self.v))
+ if ret == 0:
+ raise RuntimeError("serialize")
+ return buf[0:ret]
+ def serializeToHexStr(self):
+ return hexStr(self.serialize())
+
+class CipherTextGT(Structure):
+ _fields_ = [("v", c_ulonglong * GT_CIPHER_SIZE)]
+ def serialize(self):
+ buf = Buffer()
+ ret = lib.sheCipherTextGTSerialize(byref(buf), len(buf), byref(self.v))
+ if ret == 0:
+ raise RuntimeError("serialize")
+ return buf[0:ret]
+ def serializeToHexStr(self):
+ return hexStr(self.serialize())
+
+class PrecomputedPublicKey(Structure):
+ def __init__(self):
+ self.p = 0
+ def create(self):
+ if not self.p:
+ self.p = c_void_p(lib.shePrecomputedPublicKeyCreate())
+ if self.p == 0:
+ raise RuntimeError("PrecomputedPublicKey::create")
+ def destroy(self):
+ lib.shePrecomputedPublicKeyDestroy(self.p)
+ def encG1(self, m):
+ c = CipherTextG1()
+ ret = lib.shePrecomputedPublicKeyEncG1(byref(c.v), self.p, m)
+ if ret != 0:
+ raise RuntimeError("encG1", m)
+ return c
+ def encG2(self, m):
+ c = CipherTextG2()
+ ret = lib.shePrecomputedPublicKeyEncG2(byref(c.v), self.p, m)
+ if ret != 0:
+ raise RuntimeError("encG2", m)
+ return c
+ def encGT(self, m):
+ c = CipherTextGT()
+ ret = lib.shePrecomputedPublicKeyEncGT(byref(c.v), self.p, m)
+ if ret != 0:
+ raise RuntimeError("encGT", m)
+ return c
+
+class PublicKey(Structure):
+ _fields_ = [("v", c_ulonglong * PUB_SIZE)]
+ def serialize(self):
+ buf = Buffer()
+ ret = lib.shePublicKeySerialize(byref(buf), len(buf), byref(self.v))
+ if ret == 0:
+ raise RuntimeError("serialize")
+ return buf[0:ret]
+ def serializeToHexStr(self):
+ return hexStr(self.serialize())
+ def encG1(self, m):
+ c = CipherTextG1()
+ ret = lib.sheEncG1(byref(c.v), byref(self.v), m)
+ if ret != 0:
+ raise RuntimeError("encG1", m)
+ return c
+ def encG2(self, m):
+ c = CipherTextG2()
+ ret = lib.sheEncG2(byref(c.v), byref(self.v), m)
+ if ret != 0:
+ raise RuntimeError("encG2", m)
+ return c
+ def encGT(self, m):
+ c = CipherTextGT()
+ ret = lib.sheEncGT(byref(c.v), byref(self.v), m)
+ if ret != 0:
+ raise RuntimeError("encGT", m)
+ return c
+ def createPrecomputedPublicKey(self):
+ ppub = PrecomputedPublicKey()
+ ppub.create()
+ ret = lib.shePrecomputedPublicKeyInit(ppub.p, byref(self.v))
+ if ret != 0:
+ raise RuntimeError("createPrecomputedPublicKey")
+ return ppub
+
+class SecretKey(Structure):
+ _fields_ = [("v", c_ulonglong * SEC_SIZE)]
+ def setByCSPRNG(self):
+ ret = lib.sheSecretKeySetByCSPRNG(byref(self.v))
+ if ret != 0:
+ raise RuntimeError("setByCSPRNG", ret)
+ def serialize(self):
+ buf = Buffer()
+ ret = lib.sheSecretKeySerialize(byref(buf), len(buf), byref(self.v))
+ if ret == 0:
+ raise RuntimeError("serialize")
+ return buf[0:ret]
+ def serializeToHexStr(self):
+ return hexStr(self.serialize())
+ def getPulicKey(self):
+ pub = PublicKey()
+ lib.sheGetPublicKey(byref(pub.v), byref(self.v))
+ return pub
+ def dec(self, c):
+ m = c_longlong()
+ if isinstance(c, CipherTextG1):
+ ret = lib.sheDecG1(byref(m), byref(self.v), byref(c.v))
+ elif isinstance(c, CipherTextG2):
+ ret = lib.sheDecG2(byref(m), byref(self.v), byref(c.v))
+ elif isinstance(c, CipherTextGT):
+ ret = lib.sheDecGT(byref(m), byref(self.v), byref(c.v))
+ if ret != 0:
+ raise RuntimeError("dec")
+ return m.value
+
+def neg(c):
+ ret = -1
+ if isinstance(c, CipherTextG1):
+ out = CipherTextG1()
+ ret = lib.sheNegG1(byref(out.v), byref(c.v))
+ elif isinstance(c, CipherTextG2):
+ out = CipherTextG2()
+ ret = lib.sheNegG2(byref(out.v), byref(c.v))
+ elif isinstance(c, CipherTextGT):
+ out = CipherTextGT()
+ ret = lib.sheNegGT(byref(out.v), byref(c.v))
+ if ret != 0:
+ raise RuntimeError("neg")
+ return out
+
+def add(cx, cy):
+ ret = -1
+ if isinstance(cx, CipherTextG1) and isinstance(cy, CipherTextG1):
+ out = CipherTextG1()
+ ret = lib.sheAddG1(byref(out.v), byref(cx.v), byref(cy.v))
+ elif isinstance(cx, CipherTextG2) and isinstance(cy, CipherTextG2):
+ out = CipherTextG2()
+ ret = lib.sheAddG2(byref(out.v), byref(cx.v), byref(cy.v))
+ elif isinstance(cx, CipherTextGT) and isinstance(cy, CipherTextGT):
+ out = CipherTextGT()
+ ret = lib.sheAddGT(byref(out.v), byref(cx.v), byref(cy.v))
+ if ret != 0:
+ raise RuntimeError("add")
+ return out
+
+def sub(cx, cy):
+ ret = -1
+ if isinstance(cx, CipherTextG1) and isinstance(cy, CipherTextG1):
+ out = CipherTextG1()
+ ret = lib.sheSubG1(byref(out.v), byref(cx.v), byref(cy.v))
+ elif isinstance(cx, CipherTextG2) and isinstance(cy, CipherTextG2):
+ out = CipherTextG2()
+ ret = lib.sheSubG2(byref(out.v), byref(cx.v), byref(cy.v))
+ elif isinstance(cx, CipherTextGT) and isinstance(cy, CipherTextGT):
+ out = CipherTextGT()
+ ret = lib.sheSubGT(byref(out.v), byref(cx.v), byref(cy.v))
+ if ret != 0:
+ raise RuntimeError("sub")
+ return out
+
+def mul(cx, cy):
+ ret = -1
+ if isinstance(cx, CipherTextG1) and isinstance(cy, CipherTextG2):
+ out = CipherTextGT()
+ ret = lib.sheMul(byref(out.v), byref(cx.v), byref(cy.v))
+ elif isinstance(cx, CipherTextG1) and isinstance(cy, int):
+ out = CipherTextG1()
+ ret = lib.sheMulG1(byref(out.v), byref(cx.v), cy)
+ elif isinstance(cx, CipherTextG2) and isinstance(cy, int):
+ out = CipherTextG2()
+ ret = lib.sheMulG2(byref(out.v), byref(cx.v), cy)
+ elif isinstance(cx, CipherTextGT) and isinstance(cy, int):
+ out = CipherTextGT()
+ ret = lib.sheMulGT(byref(out.v), byref(cx.v), cy)
+ if ret != 0:
+ raise RuntimeError("mul")
+ return out
+
+if __name__ == '__main__':
+ init()
+ sec = SecretKey()
+ sec.setByCSPRNG()
+ print("sec=", sec.serializeToHexStr())
+ pub = sec.getPulicKey()
+ print("pub=", pub.serializeToHexStr())
+
+ m11 = 1
+ m12 = 5
+ m21 = 3
+ m22 = -4
+ c11 = pub.encG1(m11)
+ c12 = pub.encG1(m12)
+ # dec(enc) for G1
+ if sec.dec(c11) != m11: print("err1")
+
+ # add/sub for G1
+ if sec.dec(add(c11, c12)) != m11 + m12: print("err2")
+ if sec.dec(sub(c11, c12)) != m11 - m12: print("err3")
+
+ # add/sub for G2
+ c21 = pub.encG2(m21)
+ c22 = pub.encG2(m22)
+ if sec.dec(c21) != m21: print("err4")
+ if sec.dec(add(c21, c22)) != m21 + m22: print("err5")
+ if sec.dec(sub(c21, c22)) != m21 - m22: print("err6")
+
+ mt = -56
+ ct = pub.encGT(mt)
+ if sec.dec(ct) != mt: print("err7")
+
+ # mul G1 and G2
+ if sec.dec(mul(c11, c21)) != m11 * m21: print("err8")
+
+ # use precomputedPublicKey for performance
+ ppub = pub.createPrecomputedPublicKey()
+ c1 = ppub.encG1(m11)
+ if sec.dec(c1) != m11: print("err9")
+
+ import sys
+ if sys.version_info.major >= 3:
+ import timeit
+ N = 100000
+ print(str(timeit.timeit("pub.encG1(12)", number=N, globals=globals()) / float(N) * 1e3) + "msec")
+ print(str(timeit.timeit("ppub.encG1(12)", number=N, globals=globals()) / float(N) * 1e3) + "msec")
+
+ ppub.destroy() # necessary to avoid memory leak
+
diff --git a/vendor/github.com/dexon-foundation/mcl/include/cybozu/random_generator.hpp b/vendor/github.com/dexon-foundation/mcl/include/cybozu/random_generator.hpp
index 23096989d..ff4a78da5 100644
--- a/vendor/github.com/dexon-foundation/mcl/include/cybozu/random_generator.hpp
+++ b/vendor/github.com/dexon-foundation/mcl/include/cybozu/random_generator.hpp
@@ -54,11 +54,9 @@ public:
}
throw cybozu::Exception("randomgenerator");
}
- void read_inner(void *buf, size_t byteSize)
+ bool read_inner(void *buf, size_t byteSize)
{
- if (CryptGenRandom(prov_, static_cast<DWORD>(byteSize), static_cast<BYTE*>(buf)) == 0) {
- throw cybozu::Exception("randomgenerator:read") << byteSize;
- }
+ return CryptGenRandom(prov_, static_cast<DWORD>(byteSize), static_cast<BYTE*>(buf)) != 0;
}
~RandomGenerator()
{
@@ -71,12 +69,15 @@ public:
@note bufNum is not byte size
*/
template<class T>
- void read(T *buf, size_t bufNum)
+ void read(bool *pb, T *buf, size_t bufNum)
{
cybozu::AutoLockCs al(cs_);
const size_t byteSize = sizeof(T) * bufNum;
if (byteSize > bufSize) {
- read_inner(buf, byteSize);
+ if (!read_inner(buf, byteSize)) {
+ *pb = false;
+ return;
+ }
} else {
if (pos_ + byteSize > bufSize) {
read_inner(buf_, bufSize);
@@ -85,6 +86,14 @@ public:
memcpy(buf, buf_ + pos_, byteSize);
pos_ += byteSize;
}
+ *pb = true;
+ }
+ template<class T>
+ void read(T *buf, size_t bufNum)
+ {
+ bool b;
+ read(&b, buf, bufNum);
+ if (!b) throw cybozu::Exception("RandomGenerator:read") << bufNum;
}
private:
HCRYPTPROV prov_;
@@ -107,12 +116,17 @@ private:
@note bufNum is not byte size
*/
template<class T>
- void read(T *buf, size_t bufNum)
+ void read(bool *pb, T *buf, size_t bufNum)
{
const size_t byteSize = sizeof(T) * bufNum;
- if (::fread(buf, 1, (int)byteSize, fp_) != byteSize) {
- throw cybozu::Exception("randomgenerator:read") << byteSize;
- }
+ *pb = ::fread(buf, 1, (int)byteSize, fp_) == byteSize;
+ }
+ template<class T>
+ void read(T *buf, size_t bufNum)
+ {
+ bool b;
+ read(&b, buf, bufNum);
+ if (!b) throw cybozu::Exception("RandomGenerator:read") << bufNum;
}
#endif
private:
diff --git a/vendor/github.com/dexon-foundation/mcl/include/cybozu/sha2.hpp b/vendor/github.com/dexon-foundation/mcl/include/cybozu/sha2.hpp
index 97193849b..1830936f0 100644
--- a/vendor/github.com/dexon-foundation/mcl/include/cybozu/sha2.hpp
+++ b/vendor/github.com/dexon-foundation/mcl/include/cybozu/sha2.hpp
@@ -6,36 +6,124 @@
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
*/
-#include <cybozu/endian.hpp>
+#if !defined(CYBOZU_DONT_USE_OPENSSL) && !defined(MCL_DONT_USE_OPENSSL)
+ #define CYBOZU_USE_OPENSSL_SHA
+#endif
+
#ifndef CYBOZU_DONT_USE_STRING
-#include <cybozu/itoa.hpp>
#include <string>
#endif
-#include <memory.h>
-#include <assert.h>
-namespace cybozu {
+#ifdef CYBOZU_USE_OPENSSL_SHA
+#ifdef __APPLE__
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+#include <openssl/sha.h>
+#ifdef _MSC_VER
+ #include <cybozu/link_libeay32.hpp>
+#endif
-namespace sha2_local {
+#ifdef __APPLE__
+ #pragma GCC diagnostic pop
+#endif
-template<class T>
-T min_(T x, T y) { return x < y ? x : y;; }
+namespace cybozu {
+class Sha256 {
+ SHA256_CTX ctx_;
+public:
+ Sha256()
+ {
+ clear();
+ }
+ void clear()
+ {
+ SHA256_Init(&ctx_);
+ }
+ void update(const void *buf, size_t bufSize)
+ {
+ SHA256_Update(&ctx_, buf, bufSize);
+ }
+ size_t digest(void *md, size_t mdSize, const void *buf, size_t bufSize)
+ {
+ if (mdSize < SHA256_DIGEST_LENGTH) return 0;
+ update(buf, bufSize);
+ SHA256_Final(reinterpret_cast<uint8_t*>(md), &ctx_);
+ return SHA256_DIGEST_LENGTH;
+ }
#ifndef CYBOZU_DONT_USE_STRING
-inline void uint32toHexStr(char *buf, const uint32_t *x, size_t n)
-{
- for (size_t i = 0; i < n; i++) {
- cybozu::itohex(buf + i * 8, 8, x[i], false);
+ void update(const std::string& buf)
+ {
+ update(buf.c_str(), buf.size());
}
-}
+ std::string digest(const std::string& buf)
+ {
+ return digest(buf.c_str(), buf.size());
+ }
+ std::string digest(const void *buf, size_t bufSize)
+ {
+ std::string md(SHA256_DIGEST_LENGTH, 0);
+ digest(&md[0], md.size(), buf, bufSize);
+ return md;
+ }
+#endif
+};
-inline void uint64toHexStr(char *buf, const uint64_t *x, size_t n)
-{
- for (size_t i = 0; i < n; i++) {
- cybozu::itohex(buf + i * 16, 16, x[i], false);
+class Sha512 {
+ SHA512_CTX ctx_;
+public:
+ Sha512()
+ {
+ clear();
+ }
+ void clear()
+ {
+ SHA512_Init(&ctx_);
+ }
+ void update(const void *buf, size_t bufSize)
+ {
+ SHA512_Update(&ctx_, buf, bufSize);
+ }
+ size_t digest(void *md, size_t mdSize, const void *buf, size_t bufSize)
+ {
+ if (mdSize < SHA512_DIGEST_LENGTH) return 0;
+ update(buf, bufSize);
+ SHA512_Final(reinterpret_cast<uint8_t*>(md), &ctx_);
+ return SHA512_DIGEST_LENGTH;
+ }
+#ifndef CYBOZU_DONT_USE_STRING
+ void update(const std::string& buf)
+ {
+ update(buf.c_str(), buf.size());
+ }
+ std::string digest(const std::string& buf)
+ {
+ return digest(buf.c_str(), buf.size());
+ }
+ std::string digest(const void *buf, size_t bufSize)
+ {
+ std::string md(SHA512_DIGEST_LENGTH, 0);
+ digest(&md[0], md.size(), buf, bufSize);
+ return md;
}
-}
#endif
+};
+
+} // cybozu
+
+#else
+
+#include <cybozu/endian.hpp>
+#include <memory.h>
+#include <assert.h>
+
+namespace cybozu {
+
+namespace sha2_local {
+
+template<class T>
+T min_(T x, T y) { return x < y ? x : y;; }
inline uint32_t rot32(uint32_t x, int s)
{
@@ -55,12 +143,64 @@ inline uint64_t rot64(uint64_t x, int s)
#endif
}
+template<class T>
+struct Common {
+ void term(const char *buf, size_t bufSize)
+ {
+ assert(bufSize < T::blockSize_);
+ T& self = static_cast<T&>(*this);
+ const uint64_t totalSize = self.totalSize_ + bufSize;
+
+ uint8_t last[T::blockSize_];
+ memcpy(last, buf, bufSize);
+ last[bufSize] = uint8_t(0x80); /* top bit = 1 */
+ memset(&last[bufSize + 1], 0, T::blockSize_ - bufSize - 1);
+ if (bufSize >= T::blockSize_ - T::msgLenByte_) {
+ self.round(reinterpret_cast<const char*>(last));
+ memset(last, 0, sizeof(last)); // clear stack
+ }
+ cybozu::Set64bitAsBE(&last[T::blockSize_ - 8], totalSize * 8);
+ self.round(reinterpret_cast<const char*>(last));
+ }
+ void inner_update(const char *buf, size_t bufSize)
+ {
+ T& self = static_cast<T&>(*this);
+ if (bufSize == 0) return;
+ if (self.roundBufSize_ > 0) {
+ size_t size = sha2_local::min_(T::blockSize_ - self.roundBufSize_, bufSize);
+ memcpy(self.roundBuf_ + self.roundBufSize_, buf, size);
+ self.roundBufSize_ += size;
+ buf += size;
+ bufSize -= size;
+ }
+ if (self.roundBufSize_ == T::blockSize_) {
+ self.round(self.roundBuf_);
+ self.roundBufSize_ = 0;
+ }
+ while (bufSize >= T::blockSize_) {
+ assert(self.roundBufSize_ == 0);
+ self.round(buf);
+ buf += T::blockSize_;
+ bufSize -= T::blockSize_;
+ }
+ if (bufSize > 0) {
+ assert(bufSize < T::blockSize_);
+ assert(self.roundBufSize_ == 0);
+ memcpy(self.roundBuf_, buf, bufSize);
+ self.roundBufSize_ = bufSize;
+ }
+ assert(self.roundBufSize_ < T::blockSize_);
+ }
+};
+
} // cybozu::sha2_local
-class Sha256 {
+class Sha256 : public sha2_local::Common<Sha256> {
+ friend struct sha2_local::Common<Sha256>;
private:
static const size_t blockSize_ = 64;
static const size_t hSize_ = 8;
+ static const size_t msgLenByte_ = 8;
uint64_t totalSize_;
size_t roundBufSize_;
char roundBuf_[blockSize_];
@@ -117,38 +257,13 @@ private:
h_[5] += f;
h_[6] += g;
h_[7] += h;
- totalSize_ += 64;
- }
- /*
- final phase
- */
- void term(const char *buf, size_t bufSize)
- {
- assert(bufSize < blockSize_);
- const uint64_t totalSize = totalSize_ + bufSize;
-
- uint8_t last[blockSize_];
- memcpy(last, buf, bufSize);
- memset(&last[bufSize], 0, blockSize_ - bufSize);
- last[bufSize] = uint8_t(0x80); /* top bit = 1 */
- if (bufSize >= blockSize_ - 8) {
- round(reinterpret_cast<const char*>(last));
- memset(last, 0, sizeof(last)); // clear stack
- }
- cybozu::Set32bitAsBE(&last[56], uint32_t(totalSize >> 29));
- cybozu::Set32bitAsBE(&last[60], uint32_t(totalSize * 8));
- round(reinterpret_cast<const char*>(last));
+ totalSize_ += blockSize_;
}
public:
Sha256()
{
clear();
}
- Sha256(const void *buf, size_t bufSize)
- {
- clear();
- digest(buf, bufSize);
- }
void clear()
{
static const uint32_t kTbl[] = {
@@ -173,43 +288,16 @@ public:
h_[6] = 0x1f83d9ab;
h_[7] = 0x5be0cd19;
}
- void update(const void *buf_, size_t bufSize)
+ void update(const void *buf, size_t bufSize)
{
- const char *buf = reinterpret_cast<const char*>(buf_);
- if (bufSize == 0) return;
- if (roundBufSize_ > 0) {
- size_t size = sha2_local::min_(blockSize_ - roundBufSize_, bufSize);
- memcpy(roundBuf_ + roundBufSize_, buf, size);
- roundBufSize_ += size;
- buf += size;
- bufSize -= size;
- }
- if (roundBufSize_ == blockSize_) {
- round(roundBuf_);
- roundBufSize_ = 0;
- }
- while (bufSize >= blockSize_) {
- assert(roundBufSize_ == 0);
- round(buf);
- buf += blockSize_;
- bufSize -= blockSize_;
- }
- if (bufSize > 0) {
- assert(bufSize < blockSize_);
- assert(roundBufSize_ == 0);
- memcpy(roundBuf_, buf, bufSize);
- roundBufSize_ = bufSize;
- }
- assert(roundBufSize_ < blockSize_);
+ inner_update(reinterpret_cast<const char*>(buf), bufSize);
}
- void digest(const void *buf, size_t bufSize)
+ size_t digest(void *md, size_t mdSize, const void *buf, size_t bufSize)
{
+ if (mdSize < outByteSize_) return 0;
update(buf, bufSize);
term(roundBuf_, roundBufSize_);
- }
- size_t get(void *out) const
- {
- char *p = reinterpret_cast<char*>(out);
+ char *p = reinterpret_cast<char*>(md);
for (size_t i = 0; i < hSize_; i++) {
cybozu::Set32bitAsBE(&p[i * sizeof(h_[0])], h_[i]);
}
@@ -220,29 +308,25 @@ public:
{
update(buf.c_str(), buf.size());
}
- void digest(const std::string& str = "")
+ std::string digest(const std::string& buf)
{
- digest(str.c_str(), str.size());
+ return digest(buf.c_str(), buf.size());
}
- std::string get() const
+ std::string digest(const void *buf, size_t bufSize)
{
- char out[outByteSize_];
- get(out);
- return std::string(out, sizeof(out));
- }
- std::string toHexStr() const
- {
- char buf[outByteSize_ * 2];
- sha2_local::uint32toHexStr(buf, h_, hSize_);
- return std::string(buf, sizeof(buf));
+ std::string md(outByteSize_, 0);
+ digest(&md[0], md.size(), buf, bufSize);
+ return md;
}
#endif
};
-class Sha512 {
+class Sha512 : public sha2_local::Common<Sha512> {
+ friend struct sha2_local::Common<Sha512>;
private:
static const size_t blockSize_ = 128;
static const size_t hSize_ = 8;
+ static const size_t msgLenByte_ = 16;
uint64_t totalSize_;
size_t roundBufSize_;
char roundBuf_[blockSize_];
@@ -308,35 +392,11 @@ private:
}
totalSize_ += blockSize_;
}
- /*
- final phase
- */
- void term(const char *buf, size_t bufSize)
- {
- assert(bufSize < blockSize_);
- const uint64_t totalSize = totalSize_ + bufSize;
-
- uint8_t last[blockSize_];
- memcpy(last, buf, bufSize);
- memset(&last[bufSize], 0, blockSize_ - bufSize);
- last[bufSize] = uint8_t(0x80); /* top bit = 1 */
- if (bufSize >= blockSize_ - 16) {
- round(reinterpret_cast<const char*>(last));
- memset(last, 0, sizeof(last)); // clear stack
- }
- cybozu::Set64bitAsBE(&last[blockSize_ - 8], totalSize * 8);
- round(reinterpret_cast<const char*>(last));
- }
public:
Sha512()
{
clear();
}
- Sha512(const void *buf, size_t bufSize)
- {
- clear();
- digest(buf, bufSize);
- }
void clear()
{
static const uint64_t kTbl[] = {
@@ -369,70 +429,39 @@ public:
h_[6] = 0x1f83d9abfb41bd6bull;
h_[7] = 0x5be0cd19137e2179ull;
}
- void update(const void *buf_, size_t bufSize)
+ void update(const void *buf, size_t bufSize)
{
- const char *buf = reinterpret_cast<const char*>(buf_);
- if (bufSize == 0) return;
- if (roundBufSize_ > 0) {
- size_t size = sha2_local::min_(blockSize_ - roundBufSize_, bufSize);
- memcpy(roundBuf_ + roundBufSize_, buf, size);
- roundBufSize_ += size;
- buf += size;
- bufSize -= size;
- }
- if (roundBufSize_ == blockSize_) {
- round(roundBuf_);
- roundBufSize_ = 0;
- }
- while (bufSize >= blockSize_) {
- assert(roundBufSize_ == 0);
- round(buf);
- buf += blockSize_;
- bufSize -= blockSize_;
- }
- if (bufSize > 0) {
- assert(bufSize < blockSize_);
- assert(roundBufSize_ == 0);
- memcpy(roundBuf_, buf, bufSize);
- roundBufSize_ = bufSize;
- }
- assert(roundBufSize_ < blockSize_);
+ inner_update(reinterpret_cast<const char*>(buf), bufSize);
}
- void digest(const void *buf, size_t bufSize)
+ size_t digest(void *md, size_t mdSize, const void *buf, size_t bufSize)
{
+ if (mdSize < outByteSize_) return 0;
update(buf, bufSize);
term(roundBuf_, roundBufSize_);
- }
- size_t get(void *out) const
- {
- char *p = reinterpret_cast<char*>(out);
+ char *p = reinterpret_cast<char*>(md);
for (size_t i = 0; i < hSize_; i++) {
cybozu::Set64bitAsBE(&p[i * sizeof(h_[0])], h_[i]);
}
return outByteSize_;
}
#ifndef CYBOZU_DONT_USE_STRING
- void digest(const std::string& str = "")
- {
- digest(str.c_str(), str.size());
- }
void update(const std::string& buf)
{
update(buf.c_str(), buf.size());
}
- std::string get() const
+ std::string digest(const std::string& buf)
{
- char out[outByteSize_];
- get(out);
- return std::string(out, sizeof(out));
+ return digest(buf.c_str(), buf.size());
}
- std::string toHexStr() const
+ std::string digest(const void *buf, size_t bufSize)
{
- char buf[outByteSize_ * 2];
- sha2_local::uint64toHexStr(buf, h_, hSize_);
- return std::string(buf, sizeof(buf));
+ std::string md(outByteSize_, 0);
+ digest(&md[0], md.size(), buf, bufSize);
+ return md;
}
#endif
};
} // cybozu
+
+#endif
diff --git a/vendor/github.com/dexon-foundation/mcl/include/cybozu/xorshift.hpp b/vendor/github.com/dexon-foundation/mcl/include/cybozu/xorshift.hpp
index 69edaa939..08c6a04f9 100644
--- a/vendor/github.com/dexon-foundation/mcl/include/cybozu/xorshift.hpp
+++ b/vendor/github.com/dexon-foundation/mcl/include/cybozu/xorshift.hpp
@@ -7,9 +7,47 @@
@author MITSUNARI Shigeo
*/
#include <cybozu/inttype.hpp>
+#include <assert.h>
namespace cybozu {
+namespace xorshift_local {
+
+/*
+ U is uint32_t or uint64_t
+*/
+template<class U, class Gen>
+void read_local(void *p, size_t n, Gen& gen, U (Gen::*f)())
+{
+ uint8_t *dst = static_cast<uint8_t*>(p);
+ const size_t uSize = sizeof(U);
+ assert(uSize == 4 || uSize == 8);
+ union ua {
+ U u;
+ uint8_t a[uSize];
+ };
+
+ while (n >= uSize) {
+ ua ua;
+ ua.u = (gen.*f)();
+ for (size_t i = 0; i < uSize; i++) {
+ dst[i] = ua.a[i];
+ }
+ dst += uSize;
+ n -= uSize;
+ }
+ assert(n < uSize);
+ if (n > 0) {
+ ua ua;
+ ua.u = (gen.*f)();
+ for (size_t i = 0; i < n; i++) {
+ dst[i] = ua.a[i];
+ }
+ }
+}
+
+} // xorshift_local
+
class XorShift {
uint32_t x_, y_, z_, w_;
public:
@@ -38,25 +76,18 @@ public:
return (uint64_t(a) << 32) | b;
}
template<class T>
- void read(T *x, size_t n)
- {
- const size_t size = sizeof(T) * n;
- uint8_t *p8 = static_cast<uint8_t*>(x);
- for (size_t i = 0; i < size; i++) {
- p8[i] = static_cast<uint8_t>(get32());
- }
- }
- void read(uint32_t *x, size_t n)
+ void read(bool *pb, T *p, size_t n)
{
- for (size_t i = 0; i < n; i++) {
- x[i] = get32();
- }
+ xorshift_local::read_local(p, n * sizeof(T), *this, &XorShift::get32);
+ *pb = true;
}
- void read(uint64_t *x, size_t n)
+ template<class T>
+ size_t read(T *p, size_t n)
{
- for (size_t i = 0; i < n; i++) {
- x[i] = get64();
- }
+ bool b;
+ read(&b, p, n);
+ (void)b;
+ return n;
}
};
@@ -90,25 +121,18 @@ public:
return s_[1] + s0;
}
template<class T>
- void read(T *x, size_t n)
+ void read(bool *pb, T *p, size_t n)
{
- const size_t size = sizeof(T) * n;
- uint8_t *p8 = static_cast<uint8_t*>(x);
- for (size_t i = 0; i < size; i++) {
- p8[i] = static_cast<uint8_t>(get32());
- }
+ xorshift_local::read_local(p, n * sizeof(T), *this, &XorShift128Plus::get64);
+ *pb = true;
}
- void read(uint32_t *x, size_t n)
- {
- for (size_t i = 0; i < n; i++) {
- x[i] = get32();
- }
- }
- void read(uint64_t *x, size_t n)
+ template<class T>
+ size_t read(T *p, size_t n)
{
- for (size_t i = 0; i < n; i++) {
- x[i] = get64();
- }
+ bool b;
+ read(&b, p, n);
+ (void)b;
+ return n;
}
};
@@ -147,25 +171,18 @@ public:
return result;
}
template<class T>
- void read(T *x, size_t n)
+ void read(bool *pb, T *p, size_t n)
{
- const size_t size = sizeof(T) * n;
- uint8_t *p8 = static_cast<uint8_t*>(x);
- for (size_t i = 0; i < size; i++) {
- p8[i] = static_cast<uint8_t>(get32());
- }
- }
- void read(uint32_t *x, size_t n)
- {
- for (size_t i = 0; i < n; i++) {
- x[i] = get32();
- }
+ xorshift_local::read_local(p, n * sizeof(T), *this, &Xoroshiro128Plus::get64);
+ *pb = true;
}
- void read(uint64_t *x, size_t n)
+ template<class T>
+ size_t read(T *p, size_t n)
{
- for (size_t i = 0; i < n; i++) {
- x[i] = get64();
- }
+ bool b;
+ read(&b, p, n);
+ (void)b;
+ return n;
}
};
diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/array.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/array.hpp
index 84c5f3765..a6d2a8fa3 100644
--- a/vendor/github.com/dexon-foundation/mcl/include/mcl/array.hpp
+++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/array.hpp
@@ -8,6 +8,9 @@
*/
#include <stdlib.h>
#include <stddef.h>
+#ifndef CYBOZU_DONT_USE_EXCEPTION
+#include <new>
+#endif
namespace mcl {
@@ -15,8 +18,6 @@ template<class T>
class Array {
T *p_;
size_t n_;
- Array(const Array&);
- void operator=(const Array&);
template<class U>
void swap_(U& x, U& y) const
{
@@ -31,6 +32,26 @@ public:
{
free(p_);
}
+#ifndef CYBOZU_DONT_USE_EXCEPTION
+ Array(const Array& rhs)
+ : p_(0)
+ , n_(0)
+ {
+ if (rhs.n_ == 0) return;
+ p_ = (T*)malloc(sizeof(T) * rhs.n_);
+ if (p_ == 0) throw std::bad_alloc();
+ n_ = rhs.n_;
+ for (size_t i = 0; i < n_; i++) {
+ p_[i] = rhs.p_[i];
+ }
+ }
+ Array& operator=(const Array& rhs)
+ {
+ Array tmp(rhs);
+ tmp.swap(*this);
+ return *this;
+ }
+#endif
bool resize(size_t n)
{
if (n <= n_) {
diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/bn.h b/vendor/github.com/dexon-foundation/mcl/include/mcl/bn.h
index 9c78f92f1..0a31d5501 100644
--- a/vendor/github.com/dexon-foundation/mcl/include/mcl/bn.h
+++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/bn.h
@@ -68,6 +68,8 @@ typedef struct mclBnFr mclBnFr;
typedef struct mclBnG1 mclBnG1;
typedef struct mclBnG2 mclBnG2;
typedef struct mclBnGT mclBnGT;
+typedef struct mclBnFp mclBnFp;
+typedef struct mclBnFp2 mclBnFp2;
#else
@@ -87,6 +89,14 @@ typedef struct {
uint64_t d[MCLBN_FP_UNIT_SIZE * 12];
} mclBnGT;
+typedef struct {
+ uint64_t d[MCLBN_FP_UNIT_SIZE];
+} mclBnFp;
+
+typedef struct {
+ mclBnFp d[2];
+} mclBnFp2;
+
#endif
#include <mcl/curve_type.h>
@@ -102,6 +112,8 @@ enum {
mclBls12_CurveFp381 = 5
};
+// return 0xABC which means A.BC
+MCLBN_DLL_API int mclBn_getVersion();
/*
init library
@param curve [in] type of bn curve
@@ -146,6 +158,10 @@ MCLBN_DLL_API int mclBn_getG1ByteSize(void);
return bytes for serialized Fr
*/
MCLBN_DLL_API int mclBn_getFrByteSize(void);
+/*
+ return bytes for serialized Fp
+*/
+MCLBN_DLL_API int mclBn_getFpByteSize(void);
/*
return decimal string of the order of the curve(=the characteristic of Fr)
@@ -168,6 +184,8 @@ MCLBN_DLL_API mclSize mclBnFr_deserialize(mclBnFr *x, const void *buf, mclSize b
MCLBN_DLL_API mclSize mclBnG1_deserialize(mclBnG1 *x, const void *buf, mclSize bufSize);
MCLBN_DLL_API mclSize mclBnG2_deserialize(mclBnG2 *x, const void *buf, mclSize bufSize);
MCLBN_DLL_API mclSize mclBnGT_deserialize(mclBnGT *x, const void *buf, mclSize bufSize);
+MCLBN_DLL_API mclSize mclBnFp_deserialize(mclBnFp *x, const void *buf, mclSize bufSize);
+MCLBN_DLL_API mclSize mclBnFp2_deserialize(mclBnFp2 *x, const void *buf, mclSize bufSize);
/*
serialize
@@ -177,6 +195,8 @@ MCLBN_DLL_API mclSize mclBnFr_serialize(void *buf, mclSize maxBufSize, const mcl
MCLBN_DLL_API mclSize mclBnG1_serialize(void *buf, mclSize maxBufSize, const mclBnG1 *x);
MCLBN_DLL_API mclSize mclBnG2_serialize(void *buf, mclSize maxBufSize, const mclBnG2 *x);
MCLBN_DLL_API mclSize mclBnGT_serialize(void *buf, mclSize maxBufSize, const mclBnGT *x);
+MCLBN_DLL_API mclSize mclBnFp_serialize(void *buf, mclSize maxBufSize, const mclBnFp *x);
+MCLBN_DLL_API mclSize mclBnFp2_serialize(void *buf, mclSize maxBufSize, const mclBnFp2 *x);
/*
set string
@@ -190,6 +210,7 @@ MCLBN_DLL_API int mclBnFr_setStr(mclBnFr *x, const char *buf, mclSize bufSize, i
MCLBN_DLL_API int mclBnG1_setStr(mclBnG1 *x, const char *buf, mclSize bufSize, int ioMode);
MCLBN_DLL_API int mclBnG2_setStr(mclBnG2 *x, const char *buf, mclSize bufSize, int ioMode);
MCLBN_DLL_API int mclBnGT_setStr(mclBnGT *x, const char *buf, mclSize bufSize, int ioMode);
+MCLBN_DLL_API int mclBnFp_setStr(mclBnFp *x, const char *buf, mclSize bufSize, int ioMode);
/*
buf is terminated by '\0'
@@ -199,16 +220,29 @@ MCLBN_DLL_API mclSize mclBnFr_getStr(char *buf, mclSize maxBufSize, const mclBnF
MCLBN_DLL_API mclSize mclBnG1_getStr(char *buf, mclSize maxBufSize, const mclBnG1 *x, int ioMode);
MCLBN_DLL_API mclSize mclBnG2_getStr(char *buf, mclSize maxBufSize, const mclBnG2 *x, int ioMode);
MCLBN_DLL_API mclSize mclBnGT_getStr(char *buf, mclSize maxBufSize, const mclBnGT *x, int ioMode);
+MCLBN_DLL_API mclSize mclBnFp_getStr(char *buf, mclSize maxBufSize, const mclBnFp *x, int ioMode);
// set zero
MCLBN_DLL_API void mclBnFr_clear(mclBnFr *x);
+MCLBN_DLL_API void mclBnFp_clear(mclBnFp *x);
+MCLBN_DLL_API void mclBnFp2_clear(mclBnFp2 *x);
// set x to y
MCLBN_DLL_API void mclBnFr_setInt(mclBnFr *y, mclInt x);
MCLBN_DLL_API void mclBnFr_setInt32(mclBnFr *y, int x);
-// mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r
+// x = buf & (1 << bitLen(r)) - 1
+// if (x >= r) x &= (1 << (bitLen(r) - 1)) - 1
+// always return 0
MCLBN_DLL_API int mclBnFr_setLittleEndian(mclBnFr *x, const void *buf, mclSize bufSize);
+MCLBN_DLL_API int mclBnFp_setLittleEndian(mclBnFp *x, const void *buf, mclSize bufSize);
+
+// set (buf mod r) to x
+// return 0 if bufSize <= (byte size of Fr * 2) else -1
+MCLBN_DLL_API int mclBnFr_setLittleEndianMod(mclBnFr *x, const void *buf, mclSize bufSize);
+// set (buf mod p) to x
+// return 0 if bufSize <= (byte size of Fp * 2) else -1
+MCLBN_DLL_API int mclBnFp_setLittleEndianMod(mclBnFp *x, const void *buf, mclSize bufSize);
// return 1 if true and 0 otherwise
MCLBN_DLL_API int mclBnFr_isValid(const mclBnFr *x);
@@ -216,15 +250,33 @@ MCLBN_DLL_API int mclBnFr_isEqual(const mclBnFr *x, const mclBnFr *y);
MCLBN_DLL_API int mclBnFr_isZero(const mclBnFr *x);
MCLBN_DLL_API int mclBnFr_isOne(const mclBnFr *x);
+MCLBN_DLL_API int mclBnFp_isEqual(const mclBnFp *x, const mclBnFp *y);
+MCLBN_DLL_API int mclBnFp2_isEqual(const mclBnFp2 *x, const mclBnFp2 *y);
+
#ifndef MCL_DONT_USE_CSRPNG
// return 0 if success
MCLBN_DLL_API int mclBnFr_setByCSPRNG(mclBnFr *x);
+
+/*
+ set user-defined random function for setByCSPRNG
+ @param self [in] user-defined pointer
+ @param readFunc [in] user-defined function,
+ which writes random bufSize bytes to buf and returns bufSize if success else returns 0
+ @note if self == 0 and readFunc == 0 then set default random function
+ @note not threadsafe
+*/
+MCLBN_DLL_API void mclBn_setRandFunc(void *self, unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize));
#endif
// hash(s) and set x
// return 0 if success
MCLBN_DLL_API int mclBnFr_setHashOf(mclBnFr *x, const void *buf, mclSize bufSize);
+MCLBN_DLL_API int mclBnFp_setHashOf(mclBnFp *x, const void *buf, mclSize bufSize);
+// map x to y
+// return 0 if success else -1
+MCLBN_DLL_API int mclBnFp_mapToG1(mclBnG1 *y, const mclBnFp *x);
+MCLBN_DLL_API int mclBnFp2_mapToG2(mclBnG2 *y, const mclBnFp2 *x);
MCLBN_DLL_API void mclBnFr_neg(mclBnFr *y, const mclBnFr *x);
MCLBN_DLL_API void mclBnFr_inv(mclBnFr *y, const mclBnFr *x);
@@ -340,6 +392,7 @@ MCLBN_DLL_API void mclBn_precomputedMillerLoop2mixed(mclBnGT *f, const mclBnG1 *
Lagrange interpolation
recover out = y(0) by { (xVec[i], yVec[i]) }
return 0 if success else -1
+ @note *out = yVec[0] if k = 1
@note k >= 2, xVec[i] != 0, xVec[i] != xVec[j] for i != j
*/
MCLBN_DLL_API int mclBn_FrLagrangeInterpolation(mclBnFr *out, const mclBnFr *xVec, const mclBnFr *yVec, mclSize k);
@@ -363,6 +416,13 @@ MCLBN_DLL_API int mclBn_G2EvaluatePolynomial(mclBnG2 *out, const mclBnG2 *cVec,
MCLBN_DLL_API void mclBn_verifyOrderG1(int doVerify);
MCLBN_DLL_API void mclBn_verifyOrderG2(int doVerify);
+/*
+ EXPERIMENTAL
+ only for curve = MCL_SECP* or MCL_NIST*
+ return standard base point of the current elliptic curve
+*/
+MCLBN_DLL_API int mclBnG1_getBasePoint(mclBnG1 *x);
+
#ifdef __cplusplus
}
#endif
diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/bn.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/bn.hpp
index 8e9a9c652..5ebe5d956 100644
--- a/vendor/github.com/dexon-foundation/mcl/include/mcl/bn.hpp
+++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/bn.hpp
@@ -315,11 +315,18 @@ public:
};
struct MapTo {
+ enum {
+ BNtype,
+ BLS12type,
+ STD_ECtype
+ };
Fp c1_; // sqrt(-3)
Fp c2_; // (-1 + sqrt(-3)) / 2
mpz_class z_;
mpz_class cofactor_;
- bool isBN_;
+ int type_;
+ bool useNaiveMapTo_;
+
int legendre(bool *pb, const Fp& x) const
{
mpz_class xx;
@@ -488,27 +495,44 @@ struct MapTo {
(void)b;
c2_ = (c1_ - 1) / 2;
}
- void init(const mpz_class& cofactor, const mpz_class &z, bool isBN, int curveType = -1)
+ /*
+ if type == STD_ECtype, then cofactor, z are not used.
+ */
+ void init(const mpz_class& cofactor, const mpz_class &z, int curveType)
{
- isBN_ = isBN;
- if (isBN_) {
- initBN(cofactor, z, curveType);
+ if (0 <= curveType && curveType < MCL_EC_BEGIN) {
+ type_ = curveType == MCL_BLS12_381 ? BLS12type : BNtype;
+ } else {
+ type_ = STD_ECtype;
+ }
+ if (type_ == STD_ECtype) {
+ useNaiveMapTo_ = true;
} else {
+ useNaiveMapTo_ = false;
+ }
+#ifdef MCL_USE_OLD_MAPTO_FOR_BLS12
+ if (type == BLS12type) useNaiveMapTo_ = true;
+#endif
+ if (type_ == BNtype) {
+ initBN(cofactor, z, curveType);
+ } else if (type_ == BLS12type) {
initBLS12(z);
}
}
bool calcG1(G1& P, const Fp& t) const
{
- if (isBN_) {
- if (!calcBN<G1, Fp>(P, t)) return false;
- // no subgroup
- } else {
-#ifdef MCL_USE_OLD_MAPTO_FOR_BLS12
+ if (useNaiveMapTo_) {
naiveMapTo<G1, Fp>(P, t);
-#else
+ } else {
if (!calcBN<G1, Fp>(P, t)) return false;
-#endif
+ }
+ switch (type_) {
+ case BNtype:
+ // no subgroup
+ break;
+ case BLS12type:
mulByCofactorBLS12(P, P);
+ break;
}
assert(P.isValid());
return true;
@@ -518,16 +542,18 @@ struct MapTo {
*/
bool calcG2(G2& P, const Fp2& t) const
{
- if (isBN_) {
- if (!calcBN<G2, Fp2>(P, t)) return false;
- mulByCofactorBN(P, P);
+ if (useNaiveMapTo_) {
+ naiveMapTo<G2, Fp2>(P, t);
} else {
-#ifdef MCL_USE_OLD_MAPTO_FOR_BLS12
- naiveMapTo<G1, Fp>(P, t);
-#else
if (!calcBN<G2, Fp2>(P, t)) return false;
-#endif
+ }
+ switch(type_) {
+ case BNtype:
+ mulByCofactorBN(P, P);
+ break;
+ case BLS12type:
mulByCofactorBLS12(P, P);
+ break;
}
assert(P.isValid());
return true;
@@ -1018,6 +1044,9 @@ struct Param {
bool useNAF;
local::SignVec zReplTbl;
+ // for initG1only
+ G1 basePoint;
+
void init(bool *pb, const mcl::CurveParam& cp, fp::Mode mode)
{
this->cp = cp;
@@ -1043,12 +1072,12 @@ struct Param {
assert((p % 6) == 1);
r = local::evalPoly(z, rCoff);
}
- Fp::init(pb, p, mode);
- if (!*pb) return;
Fr::init(pb, r, mode);
if (!*pb) return;
- Fp2::init(cp.xi_a);
- Fp2 xi(cp.xi_a, 1);
+ Fp::init(pb, cp.xi_a, p, mode);
+ if (!*pb) return;
+ Fp2::init();
+ const Fp2 xi(cp.xi_a, 1);
g2 = Fp2::get_gTbl()[0];
g3 = Fp2::get_gTbl()[3];
if (cp.isMtype) {
@@ -1099,14 +1128,31 @@ struct Param {
}
*/
if (isBLS12) {
- mapTo.init(0, z, false);
+ mapTo.init(0, z, cp.curveType);
} else {
- mapTo.init(2 * p - r, z, true, cp.curveType);
+ mapTo.init(2 * p - r, z, cp.curveType);
}
glv1.init(r, z, isBLS12, cp.curveType);
glv2.init(r, z, isBLS12);
+ basePoint.clear();
*pb = true;
}
+ void initG1only(bool *pb, const mcl::EcParam& para)
+ {
+ Fp::init(pb, para.p);
+ if (!*pb) return;
+ Fr::init(pb, para.n);
+ if (!*pb) return;
+ G1::init(pb, para.a, para.b);
+ if (!*pb) return;
+ G1::setOrder(Fr::getOp().mp);
+ mapTo.init(0, 0, para.curveType);
+ Fp x0, y0;
+ x0.setStr(pb, para.gx);
+ if (!*pb) return;
+ y0.setStr(pb, para.gy);
+ basePoint.set(pb, x0, y0);
+ }
#ifndef CYBOZU_DONT_USE_EXCEPTION
void init(const mcl::CurveParam& cp, fp::Mode mode)
{
@@ -1564,17 +1610,22 @@ inline void mulSparse(Fp12& z, const Fp6& x)
}
inline void convertFp6toFp12(Fp12& y, const Fp6& x)
{
- y.clear();
if (BN::param.cp.isMtype) {
// (a, b, c) -> (a, c, 0, 0, b, 0)
y.a.a = x.a;
y.b.b = x.b;
y.a.b = x.c;
+ y.a.c.clear();
+ y.b.a.clear();
+ y.b.c.clear();
} else {
// (a, b, c) -> (b, 0, 0, c, a, 0)
y.b.b = x.a;
y.a.a = x.b;
y.b.a = x.c;
+ y.a.b.clear();
+ y.a.c.clear();
+ y.b.c.clear();
}
}
inline void mulSparse2(Fp12& z, const Fp6& x, const Fp6& y)
@@ -2190,5 +2241,21 @@ inline void initPairing(const mcl::CurveParam& cp = mcl::BN254, fp::Mode mode =
}
#endif
+inline void initG1only(bool *pb, const mcl::EcParam& para)
+{
+ local::StaticVar<>::param.initG1only(pb, para);
+ if (!*pb) return;
+ G1::setMulArrayGLV(0);
+ G2::setMulArrayGLV(0);
+ Fp12::setPowArrayGLV(0);
+ G1::setCompressedExpression();
+ G2::setCompressedExpression();
+}
+
+inline const G1& getG1basePoint()
+{
+ return local::StaticVar<>::param.basePoint;
+}
+
} } // mcl::bn
diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/curve_type.h b/vendor/github.com/dexon-foundation/mcl/include/mcl/curve_type.h
index 5957d1ae8..9e4a941a0 100644
--- a/vendor/github.com/dexon-foundation/mcl/include/mcl/curve_type.h
+++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/curve_type.h
@@ -14,5 +14,22 @@ enum {
MCL_BN462 = 3,
MCL_BN_SNARK1 = 4,
MCL_BLS12_381 = 5,
- MCL_BN160 = 6
+ MCL_BN160 = 6,
+
+ /*
+ for only G1
+ the size of curve must be less or equal to MCLBN_FP_UNIT_SIZE
+ */
+ MCL_EC_BEGIN = 100,
+ MCL_SECP192K1 = MCL_EC_BEGIN,
+ MCL_SECP224K1 = 101,
+ MCL_SECP256K1 = 102,
+ MCL_SECP384R1 = 103,
+ MCL_SECP521R1 = 104,
+ MCL_NIST_P192 = 105,
+ MCL_NIST_P224 = 106,
+ MCL_NIST_P256 = 107,
+ MCL_EC_END = MCL_NIST_P256 + 1,
+ MCL_NIST_P384 = MCL_SECP384R1,
+ MCL_NIST_P521 = MCL_SECP521R1
};
diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/ec.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/ec.hpp
index 8ebf7e757..b8eb10be3 100644
--- a/vendor/github.com/dexon-foundation/mcl/include/mcl/ec.hpp
+++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/ec.hpp
@@ -23,11 +23,11 @@ namespace mcl {
namespace ec {
enum Mode {
- Jacobi,
- Proj
+ Jacobi = 0,
+ Proj = 1
};
-} // mcl::ecl
+} // mcl::ec
/*
elliptic curve
@@ -423,27 +423,41 @@ public:
dblNoVerifyInf(R, P);
}
#ifndef MCL_EC_USE_AFFINE
- static inline void addJacobi(EcT& R, const EcT& P, const EcT& Q)
+ static inline void addJacobi(EcT& R, const EcT& P, const EcT& Q, bool isPzOne, bool isQzOne)
{
- const bool isQzOne = Q.z.isOne();
Fp r, U1, S1, H, H3;
- Fp::sqr(r, P.z);
+ if (isPzOne) {
+ // r = 1;
+ } else {
+ Fp::sqr(r, P.z);
+ }
if (isQzOne) {
U1 = P.x;
- Fp::mul(H, Q.x, r);
+ if (isPzOne) {
+ H = Q.x;
+ } else {
+ Fp::mul(H, Q.x, r);
+ }
H -= U1;
- r *= P.z;
S1 = P.y;
} else {
Fp::sqr(S1, Q.z);
Fp::mul(U1, P.x, S1);
- Fp::mul(H, Q.x, r);
+ if (isPzOne) {
+ H = Q.x;
+ } else {
+ Fp::mul(H, Q.x, r);
+ }
H -= U1;
- r *= P.z;
S1 *= Q.z;
S1 *= P.y;
}
- r *= Q.y;
+ if (isPzOne) {
+ r = Q.y;
+ } else {
+ r *= P.z;
+ r *= Q.y;
+ }
r -= S1;
if (H.isZero()) {
if (r.isZero()) {
@@ -453,11 +467,13 @@ public:
}
return;
}
- if (isQzOne) {
- Fp::mul(R.z, P.z, H);
+ if (isPzOne) {
+ R.z = H;
} else {
- Fp::mul(R.z, P.z, Q.z);
- R.z *= H;
+ Fp::mul(R.z, P.z, H);
+ }
+ if (!isQzOne) {
+ R.z *= Q.z;
}
Fp::sqr(H3, H); // H^2
Fp::sqr(R.y, r); // r^2
@@ -471,9 +487,8 @@ public:
H3 *= S1;
Fp::sub(R.y, U1, H3);
}
- static inline void addProj(EcT& R, const EcT& P, const EcT& Q)
+ static inline void addProj(EcT& R, const EcT& P, const EcT& Q, bool isPzOne, bool isQzOne)
{
- const bool isQzOne = Q.z.isOne();
Fp r, PyQz, v, A, vv;
if (isQzOne) {
r = P.x;
@@ -482,8 +497,13 @@ public:
Fp::mul(r, P.x, Q.z);
Fp::mul(PyQz, P.y, Q.z);
}
- Fp::mul(A, Q.y, P.z);
- Fp::mul(v, Q.x, P.z);
+ if (isPzOne) {
+ A = Q.y;
+ v = Q.x;
+ } else {
+ Fp::mul(A, Q.y, P.z);
+ Fp::mul(v, Q.x, P.z);
+ }
v -= r;
if (v.isZero()) {
if (A == PyQz) {
@@ -501,10 +521,19 @@ public:
if (isQzOne) {
R.z = P.z;
} else {
- Fp::mul(R.z, P.z, Q.z);
+ if (isPzOne) {
+ R.z = Q.z;
+ } else {
+ Fp::mul(R.z, P.z, Q.z);
+ }
+ }
+ // R.z = 1 if isPzOne && isQzOne
+ if (isPzOne && isQzOne) {
+ R.z = vv;
+ } else {
+ A *= R.z;
+ R.z *= vv;
}
- A *= R.z;
- R.z *= vv;
A -= vv;
vv *= PyQz;
A -= r;
@@ -515,17 +544,14 @@ public:
R.y -= vv;
}
#endif
- static inline void add(EcT& R, const EcT& P0, const EcT& Q0)
- {
- if (P0.isZero()) { R = Q0; return; }
- if (Q0.isZero()) { R = P0; return; }
- if (&P0 == &Q0) {
- dblNoVerifyInf(R, P0);
+ static inline void add(EcT& R, const EcT& P, const EcT& Q) {
+ if (P.isZero()) { R = Q; return; }
+ if (Q.isZero()) { R = P; return; }
+ if (&P == &Q) {
+ dblNoVerifyInf(R, P);
return;
}
#ifdef MCL_EC_USE_AFFINE
- const EcT& P(P0);
- const EcT& Q(Q0);
Fp t;
Fp::neg(t, Q.y);
if (P.y == t) { R.clear(); return; }
@@ -547,19 +573,14 @@ public:
Fp::sub(R.y, s, P.y);
R.x = x3;
#else
- const EcT *pP = &P0;
- const EcT *pQ = &Q0;
- if (pP->z.isOne()) {
- fp::swap_(pP, pQ);
- }
- const EcT& P(*pP);
- const EcT& Q(*pQ);
+ bool isPzOne = P.z.isOne();
+ bool isQzOne = Q.z.isOne();
switch (mode_) {
case ec::Jacobi:
- addJacobi(R, P, Q);
+ addJacobi(R, P, Q, isPzOne, isQzOne);
break;
case ec::Proj:
- addProj(R, P, Q);
+ addProj(R, P, Q, isPzOne, isQzOne);
break;
}
#endif
@@ -889,6 +910,10 @@ public:
bool operator<=(const EcT& rhs) const { return !operator>(rhs); }
static inline void mulArray(EcT& z, const EcT& x, const fp::Unit *y, size_t yn, bool isNegative, bool constTime = false)
{
+ if (!constTime && x.isZero()) {
+ z.clear();
+ return;
+ }
if (mulArrayGLV && (constTime || yn > 1)) {
mulArrayGLV(z, x, y, yn, isNegative, constTime);
return;
@@ -983,6 +1008,7 @@ struct EcParam {
const char *gy;
const char *n;
size_t bitSize; // bit length of p
+ int curveType;
};
} // mcl
diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/ecparam.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/ecparam.hpp
index 19b76bf55..087bf8b6c 100644
--- a/vendor/github.com/dexon-foundation/mcl/include/mcl/ecparam.hpp
+++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/ecparam.hpp
@@ -7,6 +7,7 @@
http://opensource.org/licenses/BSD-3-Clause
*/
#include <mcl/ec.hpp>
+#include <mcl/curve_type.h>
namespace mcl { namespace ecparam {
@@ -18,7 +19,8 @@ const struct mcl::EcParam secp160k1 = {
"0x3b4c382ce37aa192a4019e763036f4f5dd4d7ebb",
"0x938cf935318fdced6bc28286531733c3f03c4fee",
"0x100000000000000000001b8fa16dfab9aca16b6b3",
- 160
+ 160,
+ -1
};
// p=2^160 + 7
const struct mcl::EcParam p160_1 = {
@@ -29,7 +31,8 @@ const struct mcl::EcParam p160_1 = {
"1",
"1236612389951462151661156731535316138439983579284",
"1461501637330902918203683518218126812711137002561",
- 161
+ 161,
+ -1
};
const struct mcl::EcParam secp192k1 = {
"secp192k1",
@@ -39,7 +42,8 @@ const struct mcl::EcParam secp192k1 = {
"0xdb4ff10ec057e9ae26b07d0280b7f4341da5d1b1eae06c7d",
"0x9b2f2f6d9c5628a7844163d015be86344082aa88d95e2f9d",
"0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d",
- 192
+ 192,
+ MCL_SECP192K1
};
const struct mcl::EcParam secp224k1 = {
"secp224k1",
@@ -49,7 +53,8 @@ const struct mcl::EcParam secp224k1 = {
"0xa1455b334df099df30fc28a169a467e9e47075a90f7e650eb6b7a45c",
"0x7e089fed7fba344282cafbd6f7e319f7c0b0bd59e2ca4bdb556d61a5",
"0x10000000000000000000000000001dce8d2ec6184caf0a971769fb1f7",
- 224
+ 224,
+ MCL_SECP224K1
};
const struct mcl::EcParam secp256k1 = {
"secp256k1",
@@ -59,7 +64,8 @@ const struct mcl::EcParam secp256k1 = {
"0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
"0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
"0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
- 256
+ 256,
+ MCL_SECP256K1
};
const struct mcl::EcParam secp384r1 = {
"secp384r1",
@@ -69,7 +75,8 @@ const struct mcl::EcParam secp384r1 = {
"0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7",
"0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f",
"0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973",
- 384
+ 384,
+ MCL_SECP384R1
};
const struct mcl::EcParam secp521r1 = {
"secp521r1",
@@ -79,7 +86,8 @@ const struct mcl::EcParam secp521r1 = {
"0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
"0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
"0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
- 521
+ 521,
+ MCL_SECP521R1
};
const struct mcl::EcParam NIST_P192 = {
"NIST_P192",
@@ -89,7 +97,8 @@ const struct mcl::EcParam NIST_P192 = {
"0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
"0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811",
"0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
- 192
+ 192,
+ MCL_NIST_P192
};
const struct mcl::EcParam NIST_P224 = {
"NIST_P224",
@@ -99,7 +108,8 @@ const struct mcl::EcParam NIST_P224 = {
"0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
"0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
"0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d",
- 224
+ 224,
+ MCL_NIST_P224
};
const struct mcl::EcParam NIST_P256 = {
"NIST_P256",
@@ -109,7 +119,8 @@ const struct mcl::EcParam NIST_P256 = {
"0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
"0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
"0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
- 256
+ 256,
+ MCL_NIST_P256
};
// same secp384r1
const struct mcl::EcParam NIST_P384 = {
@@ -120,7 +131,8 @@ const struct mcl::EcParam NIST_P384 = {
"0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7",
"0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f",
"0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973",
- 384
+ 384,
+ MCL_NIST_P384
};
// same secp521r1
const struct mcl::EcParam NIST_P521 = {
@@ -131,7 +143,8 @@ const struct mcl::EcParam NIST_P521 = {
"0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
"0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
"0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
- 521
+ 521,
+ MCL_NIST_P521
};
} // mcl::ecparam
@@ -161,4 +174,18 @@ static inline const mcl::EcParam* getEcParam(const std::string& name)
}
#endif
+inline const mcl::EcParam* getEcParam(int curve)
+{
+ switch (curve) {
+ case MCL_SECP192K1: return &ecparam::secp192k1;
+ case MCL_SECP224K1: return &ecparam::secp224k1;
+ case MCL_SECP256K1: return &ecparam::secp256k1;
+ case MCL_SECP384R1: return &ecparam::secp384r1;
+ case MCL_NIST_P192: return &ecparam::NIST_P192;
+ case MCL_NIST_P224: return &ecparam::NIST_P224;
+ case MCL_NIST_P256: return &ecparam::NIST_P256;
+ default: return 0;
+ }
+}
+
} // mcl
diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/elgamal.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/elgamal.hpp
index 8bc3104b7..431148508 100644
--- a/vendor/github.com/dexon-foundation/mcl/include/mcl/elgamal.hpp
+++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/elgamal.hpp
@@ -244,8 +244,7 @@ struct ElgamalT {
input : m = 0 or 1
output : c (c1, c2), zkp
*/
- template<class Hash>
- void encWithZkp(CipherText& c, Zkp& zkp, int m, Hash& hash, fp::RandGen rg = fp::RandGen()) const
+ void encWithZkp(CipherText& c, Zkp& zkp, int m, fp::RandGen rg = fp::RandGen()) const
{
if (m != 0 && m != 1) {
throw cybozu::Exception("elgamal:PublicKey:encWithZkp") << m;
@@ -272,10 +271,8 @@ struct ElgamalT {
mulH(R12, r1);
std::ostringstream os;
os << R01 << R02 << R11 << R12 << c.c1 << c.c2 << f << g << h;
- hash.update(os.str());
- const std::string digest = hash.digest();
Zn cc;
- cc.setArrayMask(digest.c_str(), digest.size());
+ cc.setHashOf(os.str());
zkp.c1 = cc - zkp.c0;
zkp.s1 = r1 + zkp.c1 * u;
} else {
@@ -296,10 +293,8 @@ struct ElgamalT {
Ec::sub(R12, t1, t2);
std::ostringstream os;
os << R01 << R02 << R11 << R12 << c.c1 << c.c2 << f << g << h;
- hash.update(os.str());
- const std::string digest = hash.digest();
Zn cc;
- cc.setArrayMask(digest.c_str(), digest.size());
+ cc.setHashOf(os.str());
zkp.c0 = cc - zkp.c1;
zkp.s0 = r0 + zkp.c0 * u;
}
@@ -307,8 +302,7 @@ struct ElgamalT {
/*
verify cipher text with ZKP
*/
- template<class Hash>
- bool verify(const CipherText& c, const Zkp& zkp, Hash& hash) const
+ bool verify(const CipherText& c, const Zkp& zkp) const
{
Ec R01, R02, R11, R12;
Ec t1, t2;
@@ -327,10 +321,8 @@ struct ElgamalT {
Ec::sub(R12, t1, t2);
std::ostringstream os;
os << R01 << R02 << R11 << R12 << c.c1 << c.c2 << f << g << h;
- hash.update(os.str());
- const std::string digest = hash.digest();
Zn cc;
- cc.setArrayMask(digest.c_str(), digest.size());
+ cc.setHashOf(os.str());
return cc == zkp.c0 + zkp.c1;
}
/*
diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/fp.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/fp.hpp
index 48500127e..2e69729dd 100644
--- a/vendor/github.com/dexon-foundation/mcl/include/mcl/fp.hpp
+++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/fp.hpp
@@ -70,8 +70,6 @@ inline void dumpUnit(Unit x)
bool isEnableJIT(); // 1st call is not threadsafe
-void getRandVal(Unit *out, RandGen& rg, const Unit *in, size_t bitSize);
-
uint32_t sha256(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize);
uint32_t sha512(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize);
@@ -112,10 +110,14 @@ public:
}
printf("\n");
}
- static inline void init(bool *pb, const mpz_class& _p, fp::Mode mode = fp::FP_AUTO)
+ /*
+ xi_a is used for Fp2::mul_xi(), where xi = xi_a + i and i^2 = -1
+ if xi_a = 0 then asm functions for Fp2 are not generated.
+ */
+ static inline void init(bool *pb, int xi_a, const mpz_class& p, fp::Mode mode = fp::FP_AUTO)
{
assert(maxBitSize <= MCL_MAX_BIT_SIZE);
- *pb = op_.init(_p, maxBitSize, mode);
+ *pb = op_.init(p, maxBitSize, xi_a, mode);
if (!*pb) return;
{ // set oneRep
FpT& one = *reinterpret_cast<FpT*>(op_.oneRep);
@@ -130,19 +132,23 @@ public:
}
inv(inv2_, 2);
#ifdef MCL_XBYAK_DIRECT_CALL
- add = (void (*)(FpT& z, const FpT& x, const FpT& y))op_.fp_addA_;
+ add = fp::func_ptr_cast<void (*)(FpT& z, const FpT& x, const FpT& y)>(op_.fp_addA_);
if (add == 0) add = addC;
- sub = (void (*)(FpT& z, const FpT& x, const FpT& y))op_.fp_subA_;
+ sub = fp::func_ptr_cast<void (*)(FpT& z, const FpT& x, const FpT& y)>(op_.fp_subA_);
if (sub == 0) sub = subC;
- neg = (void (*)(FpT& y, const FpT& x))op_.fp_negA_;
+ neg = fp::func_ptr_cast<void (*)(FpT& y, const FpT& x)>(op_.fp_negA_);
if (neg == 0) neg = negC;
- mul = (void (*)(FpT& z, const FpT& x, const FpT& y))op_.fp_mulA_;
+ mul = fp::func_ptr_cast<void (*)(FpT& z, const FpT& x, const FpT& y)>(op_.fp_mulA_);
if (mul == 0) mul = mulC;
- sqr = (void (*)(FpT& y, const FpT& x))op_.fp_sqrA_;
+ sqr = fp::func_ptr_cast<void (*)(FpT& y, const FpT& x)>(op_.fp_sqrA_);
if (sqr == 0) sqr = sqrC;
#endif
*pb = true;
}
+ static inline void init(bool *pb, const mpz_class& p, fp::Mode mode = fp::FP_AUTO)
+ {
+ init(pb, 0, p, mode);
+ }
static inline void init(bool *pb, const char *mstr, fp::Mode mode = fp::FP_AUTO)
{
mpz_class p;
@@ -296,10 +302,13 @@ public:
}
cybozu::write(pb, os, buf + sizeof(buf) - len, len);
}
+ /*
+ mode = Mod : set x mod p if sizeof(S) * n <= 64 else error
+ */
template<class S>
- void setArray(bool *pb, const S *x, size_t n)
+ void setArray(bool *pb, const S *x, size_t n, mcl::fp::MaskMode mode = fp::NoMask)
{
- *pb = fp::copyAndMask(v_, x, sizeof(S) * n, op_, fp::NoMask);
+ *pb = fp::copyAndMask(v_, x, sizeof(S) * n, op_, mode);
toMont();
}
/*
@@ -331,12 +340,21 @@ public:
b.p = &v_[0];
}
}
- void setByCSPRNG(fp::RandGen rg = fp::RandGen())
+ void setByCSPRNG(bool *pb, fp::RandGen rg = fp::RandGen())
{
if (rg.isZero()) rg = fp::RandGen::get();
- fp::getRandVal(v_, rg, op_.p, op_.bitSize);
- toMont();
+ rg.read(pb, v_, op_.N * sizeof(Unit)); // byte size
+ if (!pb) return;
+ setArrayMask(v_, op_.N);
+ }
+#ifndef CYBOZU_DONT_USE_EXCEPTION
+ void setByCSPRNG(fp::RandGen rg = fp::RandGen())
+ {
+ bool b;
+ setByCSPRNG(&b, rg);
+ if (!b) throw cybozu::Exception("setByCSPRNG");
}
+#endif
void setRand(fp::RandGen rg = fp::RandGen()) // old api
{
setByCSPRNG(rg);
@@ -522,17 +540,25 @@ public:
}
#endif
#ifndef CYBOZU_DONT_USE_EXCEPTION
- static inline void init(const mpz_class& _p, fp::Mode mode = fp::FP_AUTO)
+ static inline void init(int xi_a, const mpz_class& p, fp::Mode mode = fp::FP_AUTO)
{
bool b;
- init(&b, _p, mode);
+ init(&b, xi_a, p, mode);
if (!b) throw cybozu::Exception("Fp:init");
}
+ static inline void init(int xi_a, const std::string& mstr, fp::Mode mode = fp::FP_AUTO)
+ {
+ mpz_class p;
+ gmp::setStr(p, mstr);
+ init(xi_a, p, mode);
+ }
+ static inline void init(const mpz_class& p, fp::Mode mode = fp::FP_AUTO)
+ {
+ init(0, p, mode);
+ }
static inline void init(const std::string& mstr, fp::Mode mode = fp::FP_AUTO)
{
- bool b;
- init(&b, mstr.c_str(), mode);
- if (!b) throw cybozu::Exception("Fp:init");
+ init(0, mstr, mode);
}
template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const
@@ -562,7 +588,7 @@ public:
{
bool b;
setMpz(&b, x);
- if (!b) throw cybozu::Exception("Fp:setMpz:neg");
+ if (!b) throw cybozu::Exception("Fp:setMpz");
}
uint64_t getUint64() const
{
diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/fp_tower.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/fp_tower.hpp
index 63738a3f5..95722e2d5 100644
--- a/vendor/github.com/dexon-foundation/mcl/include/mcl/fp_tower.hpp
+++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/fp_tower.hpp
@@ -121,20 +121,22 @@ public:
static void (*add)(FpDblT& z, const FpDblT& x, const FpDblT& y);
static void (*sub)(FpDblT& z, const FpDblT& x, const FpDblT& y);
static void (*mod)(Fp& z, const FpDblT& xy);
+ static void (*addPre)(FpDblT& z, const FpDblT& x, const FpDblT& y);
+ static void (*subPre)(FpDblT& z, const FpDblT& x, const FpDblT& y);
static void addC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_add(z.v_, x.v_, y.v_, Fp::op_.p); }
static void subC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_sub(z.v_, x.v_, y.v_, Fp::op_.p); }
static void modC(Fp& z, const FpDblT& xy) { Fp::op_.fpDbl_mod(z.v_, xy.v_, Fp::op_.p); }
+ static void addPreC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_addPre(z.v_, x.v_, y.v_); }
+ static void subPreC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_subPre(z.v_, x.v_, y.v_); }
#else
static void add(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_add(z.v_, x.v_, y.v_, Fp::op_.p); }
static void sub(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_sub(z.v_, x.v_, y.v_, Fp::op_.p); }
static void mod(Fp& z, const FpDblT& xy) { Fp::op_.fpDbl_mod(z.v_, xy.v_, Fp::op_.p); }
+ static void addPre(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_addPre(z.v_, x.v_, y.v_); }
+ static void subPre(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_subPre(z.v_, x.v_, y.v_); }
#endif
- static void addPreC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_addPre(z.v_, x.v_, y.v_); }
- static void subPreC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_subPre(z.v_, x.v_, y.v_); }
static void mulPreC(FpDblT& xy, const Fp& x, const Fp& y) { Fp::op_.fpDbl_mulPre(xy.v_, x.v_, y.v_); }
static void sqrPreC(FpDblT& xx, const Fp& x) { Fp::op_.fpDbl_sqrPre(xx.v_, x.v_); }
- static void (*addPre)(FpDblT& z, const FpDblT& x, const FpDblT& y);
- static void (*subPre)(FpDblT& z, const FpDblT& x, const FpDblT& y);
/*
mul(z, x, y) = mulPre(xy, x, y) + mod(z, xy)
*/
@@ -149,30 +151,24 @@ public:
{
const mcl::fp::Op& op = Fp::getOp();
#ifdef MCL_XBYAK_DIRECT_CALL
- add = (void (*)(FpDblT&, const FpDblT&, const FpDblT&))op.fpDbl_addA_;
+ add = fp::func_ptr_cast<void (*)(FpDblT&, const FpDblT&, const FpDblT&)>(op.fpDbl_addA_);
if (add == 0) add = addC;
- sub = (void (*)(FpDblT&, const FpDblT&, const FpDblT&))op.fpDbl_subA_;
+ sub = fp::func_ptr_cast<void (*)(FpDblT&, const FpDblT&, const FpDblT&)>(op.fpDbl_subA_);
if (sub == 0) sub = subC;
- mod = (void (*)(Fp&, const FpDblT&))op.fpDbl_modA_;
+ mod = fp::func_ptr_cast<void (*)(Fp&, const FpDblT&)>(op.fpDbl_modA_);
if (mod == 0) mod = modC;
+ addPre = fp::func_ptr_cast<void (*)(FpDblT&, const FpDblT&, const FpDblT&)>(op.fpDbl_addPre);
+ if (addPre == 0) addPre = addPreC;
+ subPre = fp::func_ptr_cast<void (*)(FpDblT&, const FpDblT&, const FpDblT&)>(op.fpDbl_subPre);
+ if (subPre == 0) subPre = subPreC;
#endif
- if (op.fpDbl_addPreA_) {
- addPre = (void (*)(FpDblT&, const FpDblT&, const FpDblT&))op.fpDbl_addPreA_;
- } else {
- addPre = addPreC;
- }
- if (op.fpDbl_subPreA_) {
- subPre = (void (*)(FpDblT&, const FpDblT&, const FpDblT&))op.fpDbl_subPreA_;
- } else {
- subPre = subPreC;
- }
if (op.fpDbl_mulPreA_) {
- mulPre = (void (*)(FpDblT&, const Fp&, const Fp&))op.fpDbl_mulPreA_;
+ mulPre = fp::func_ptr_cast<void (*)(FpDblT&, const Fp&, const Fp&)>(op.fpDbl_mulPreA_);
} else {
mulPre = mulPreC;
}
if (op.fpDbl_sqrPreA_) {
- sqrPre = (void (*)(FpDblT&, const Fp&))op.fpDbl_sqrPreA_;
+ sqrPre = fp::func_ptr_cast<void (*)(FpDblT&, const Fp&)>(op.fpDbl_sqrPreA_);
} else {
sqrPre = sqrPreC;
}
@@ -185,9 +181,9 @@ public:
template<class Fp> void (*FpDblT<Fp>::add)(FpDblT&, const FpDblT&, const FpDblT&);
template<class Fp> void (*FpDblT<Fp>::sub)(FpDblT&, const FpDblT&, const FpDblT&);
template<class Fp> void (*FpDblT<Fp>::mod)(Fp&, const FpDblT&);
-#endif
template<class Fp> void (*FpDblT<Fp>::addPre)(FpDblT&, const FpDblT&, const FpDblT&);
template<class Fp> void (*FpDblT<Fp>::subPre)(FpDblT&, const FpDblT&, const FpDblT&);
+#endif
template<class Fp> void (*FpDblT<Fp>::mulPre)(FpDblT&, const Fp&, const Fp&);
template<class Fp> void (*FpDblT<Fp>::sqrPre)(FpDblT&, const Fp&);
@@ -206,7 +202,6 @@ class Fp2T : public fp::Serializable<Fp2T<_Fp>,
typedef fp::Unit Unit;
typedef FpDblT<Fp> FpDbl;
typedef Fp2DblT<Fp> Fp2Dbl;
- static uint32_t xi_a_;
static const size_t gN = 5;
/*
g = xi^((p - 1) / 6)
@@ -245,11 +240,19 @@ public:
a = a_;
b = b_;
}
+#ifdef MCL_XBYAK_DIRECT_CALL
static void (*add)(Fp2T& z, const Fp2T& x, const Fp2T& y);
static void (*sub)(Fp2T& z, const Fp2T& x, const Fp2T& y);
static void (*neg)(Fp2T& y, const Fp2T& x);
static void (*mul)(Fp2T& z, const Fp2T& x, const Fp2T& y);
static void (*sqr)(Fp2T& y, const Fp2T& x);
+#else
+ static void add(Fp2T& z, const Fp2T& x, const Fp2T& y) { addC(z, x, y); }
+ static void sub(Fp2T& z, const Fp2T& x, const Fp2T& y) { subC(z, x, y); }
+ static void neg(Fp2T& y, const Fp2T& x) { negC(y, x); }
+ static void mul(Fp2T& z, const Fp2T& x, const Fp2T& y) { mulC(z, x, y); }
+ static void sqr(Fp2T& y, const Fp2T& x) { sqrC(y, x); }
+#endif
static void (*mul_xi)(Fp2T& y, const Fp2T& x);
static void addPre(Fp2T& z, const Fp2T& x, const Fp2T& y) { Fp::addPre(z.a, x.a, y.a); Fp::addPre(z.b, x.b, y.b); }
static void inv(Fp2T& y, const Fp2T& x) { Fp::op_.fp2_inv(y.a.v_, x.a.v_); }
@@ -377,51 +380,38 @@ public:
}
}
- static uint32_t get_xi_a() { return xi_a_; }
- static void init(uint32_t xi_a)
+ static uint32_t get_xi_a() { return Fp::getOp().xi_a; }
+ static void init()
{
// assert(Fp::maxSize <= 256);
- xi_a_ = xi_a;
mcl::fp::Op& op = Fp::op_;
- add = (void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y))op.fp2_addA_;
- if (add == 0) add = fp2_addC;
- sub = (void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y))op.fp2_subA_;
- if (sub == 0) sub = fp2_subC;
- neg = (void (*)(Fp2T& y, const Fp2T& x))op.fp2_negA_;
- if (neg == 0) neg = fp2_negC;
- mul = (void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y))op.fp2_mulA_;
- if (mul == 0) {
- if (op.isFastMod) {
- mul = fp2_mulC;
- } else if (!op.isFullBit) {
- if (0 && sizeof(Fp) * 8 == op.N * fp::UnitBitSize && op.fp2_mulNF) {
- mul = fp2_mulNFW;
- } else {
- mul = fp2_mulC;
- }
- } else {
- mul = fp2_mulC;
- }
- }
- sqr = (void (*)(Fp2T& y, const Fp2T& x))op.fp2_sqrA_;
- if (sqr == 0) sqr = fp2_sqrC;
+ assert(op.xi_a);
+ mul_xi = 0;
+#ifdef MCL_XBYAK_DIRECT_CALL
+ add = fp::func_ptr_cast<void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y)>(op.fp2_addA_);
+ if (add == 0) add = addC;
+ sub = fp::func_ptr_cast<void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y)>(op.fp2_subA_);
+ if (sub == 0) sub = subC;
+ neg = fp::func_ptr_cast<void (*)(Fp2T& y, const Fp2T& x)>(op.fp2_negA_);
+ if (neg == 0) neg = negC;
+ mul = fp::func_ptr_cast<void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y)>(op.fp2_mulA_);
+ if (mul == 0) mul = mulC;
+ sqr = fp::func_ptr_cast<void (*)(Fp2T& y, const Fp2T& x)>(op.fp2_sqrA_);
+ if (sqr == 0) sqr = sqrC;
+ mul_xi = fp::func_ptr_cast<void (*)(Fp2T&, const Fp2T&)>(op.fp2_mul_xiA_);
+#endif
op.fp2_inv = fp2_invW;
- if (xi_a == 1) {
- /*
- current fp_generator.hpp generates mul_xi for xi_a = 1
- */
- if (op.fp2_mul_xiA_) {
- mul_xi = (void (*)(Fp2T&, const Fp2T&))op.fp2_mul_xiA_;
+ if (mul_xi == 0) {
+ if (op.xi_a == 1) {
+ mul_xi = fp2_mul_xi_1_1iC;
} else {
- mul_xi = fp2_mul_xi_1_1i;
+ mul_xi = fp2_mul_xiC;
}
- } else {
- mul_xi = fp2_mul_xiC;
}
FpDblT<Fp>::init();
Fp2DblT<Fp>::init();
// call init before Fp2::pow because FpDbl is used in Fp2T
- const Fp2T xi(xi_a, 1);
+ const Fp2T xi(op.xi_a, 1);
const mpz_class& p = Fp::getOp().mp;
Fp2T::pow(g[0], xi, (p - 1) / 6); // g = xi^((p-1)/6)
for (size_t i = 1; i < gN; i++) {
@@ -490,17 +480,17 @@ private:
default Fp2T operator
Fp2T = Fp[i]/(i^2 + 1)
*/
- static void fp2_addC(Fp2T& z, const Fp2T& x, const Fp2T& y)
+ static void addC(Fp2T& z, const Fp2T& x, const Fp2T& y)
{
Fp::add(z.a, x.a, y.a);
Fp::add(z.b, x.b, y.b);
}
- static void fp2_subC(Fp2T& z, const Fp2T& x, const Fp2T& y)
+ static void subC(Fp2T& z, const Fp2T& x, const Fp2T& y)
{
Fp::sub(z.a, x.a, y.a);
Fp::sub(z.b, x.b, y.b);
}
- static void fp2_negC(Fp2T& y, const Fp2T& x)
+ static void negC(Fp2T& y, const Fp2T& x)
{
Fp::neg(y.a, x.a);
Fp::neg(y.b, x.b);
@@ -531,13 +521,13 @@ private:
Fp::sub(pz[1], t1, ac);
pz[1] -= bd;
}
-#endif
static void fp2_mulNFW(Fp2T& z, const Fp2T& x, const Fp2T& y)
{
const fp::Op& op = Fp::op_;
op.fp2_mulNF((Unit*)&z, (const Unit*)&x, (const Unit*)&y, op.p);
}
- static void fp2_mulC(Fp2T& z, const Fp2T& x, const Fp2T& y)
+#endif
+ static void mulC(Fp2T& z, const Fp2T& x, const Fp2T& y)
{
Fp2Dbl d;
Fp2Dbl::mulPre(d, x, y);
@@ -548,7 +538,7 @@ private:
x = a + bi, i^2 = -1
y = x^2 = (a + bi)^2 = (a + b)(a - b) + 2abi
*/
- static void fp2_sqrC(Fp2T& y, const Fp2T& x)
+ static void sqrC(Fp2T& y, const Fp2T& x)
{
const Fp& a = x.a;
const Fp& b = x.b;
@@ -583,9 +573,9 @@ private:
const Fp& a = x.a;
const Fp& b = x.b;
Fp t;
- Fp::mulUnit(t, a, xi_a_);
+ Fp::mulUnit(t, a, Fp::getOp().xi_a);
t -= b;
- Fp::mulUnit(y.b, b, xi_a_);
+ Fp::mulUnit(y.b, b, Fp::getOp().xi_a);
y.b += a;
y.a = t;
}
@@ -593,7 +583,7 @@ private:
xi = 1 + i ; xi_a = 1
y = (a + bi)xi = (a - b) + (a + b)i
*/
- static void fp2_mul_xi_1_1i(Fp2T& y, const Fp2T& x)
+ static void fp2_mul_xi_1_1iC(Fp2T& y, const Fp2T& x)
{
const Fp& a = x.a;
const Fp& b = x.b;
@@ -623,11 +613,13 @@ private:
}
};
+#ifdef MCL_XBYAK_DIRECT_CALL
template<class Fp_> void (*Fp2T<Fp_>::add)(Fp2T& z, const Fp2T& x, const Fp2T& y);
template<class Fp_> void (*Fp2T<Fp_>::sub)(Fp2T& z, const Fp2T& x, const Fp2T& y);
template<class Fp_> void (*Fp2T<Fp_>::neg)(Fp2T& y, const Fp2T& x);
template<class Fp_> void (*Fp2T<Fp_>::mul)(Fp2T& z, const Fp2T& x, const Fp2T& y);
template<class Fp_> void (*Fp2T<Fp_>::sqr)(Fp2T& y, const Fp2T& x);
+#endif
template<class Fp_> void (*Fp2T<Fp_>::mul_xi)(Fp2T& y, const Fp2T& x);
template<class Fp>
@@ -697,7 +689,7 @@ struct Fp2DblT {
{
const mcl::fp::Op& op = Fp::getOp();
if (op.fp2Dbl_mulPreA_) {
- mulPre = (void (*)(Fp2DblT&, const Fp2&, const Fp2&))op.fp2Dbl_mulPreA_;
+ mulPre = fp::func_ptr_cast<void (*)(Fp2DblT&, const Fp2&, const Fp2&)>(op.fp2Dbl_mulPreA_);
} else {
if (op.isFullBit) {
mulPre = fp2Dbl_mulPreW<true>;
@@ -706,7 +698,7 @@ struct Fp2DblT {
}
}
if (op.fp2Dbl_sqrPreA_) {
- sqrPre = (void (*)(Fp2DblT&, const Fp2&))op.fp2Dbl_sqrPreA_;
+ sqrPre = fp::func_ptr_cast<void (*)(Fp2DblT&, const Fp2&)>(op.fp2Dbl_sqrPreA_);
} else {
if (op.isFullBit) {
sqrPre = fp2Dbl_sqrPreW<true>;
@@ -769,11 +761,12 @@ struct Fp2DblT {
template<class Fp> void (*Fp2DblT<Fp>::mulPre)(Fp2DblT&, const Fp2T<Fp>&, const Fp2T<Fp>&);
template<class Fp> void (*Fp2DblT<Fp>::sqrPre)(Fp2DblT&, const Fp2T<Fp>&);
-template<class Fp> uint32_t Fp2T<Fp>::xi_a_;
template<class Fp> Fp2T<Fp> Fp2T<Fp>::g[Fp2T<Fp>::gN];
template<class Fp> Fp2T<Fp> Fp2T<Fp>::g2[Fp2T<Fp>::gN];
template<class Fp> Fp2T<Fp> Fp2T<Fp>::g3[Fp2T<Fp>::gN];
+template<class Fp>
+struct Fp6DblT;
/*
Fp6T = Fp2[v] / (v^3 - xi)
x = a + b v + c v^2
@@ -784,6 +777,7 @@ struct Fp6T : public fp::Serializable<Fp6T<_Fp>,
typedef _Fp Fp;
typedef Fp2T<Fp> Fp2;
typedef Fp2DblT<Fp> Fp2Dbl;
+ typedef Fp6DblT<Fp> Fp6Dbl;
typedef Fp BaseFp;
Fp2 a, b, c;
Fp6T() { }
@@ -914,91 +908,7 @@ struct Fp6T : public fp::Serializable<Fp6T<_Fp>,
y.b += t1; // c^2 xi + 2ab
y.c -= t1; // b^2 + 2ac
}
- /*
- x = a + bv + cv^2, y = d + ev + fv^2, v^3 = xi
- xy = (ad + (bf + ce)xi) + ((ae + bd) + cf xi)v + ((af + cd) + be)v^2
- bf + ce = (b + c)(e + f) - be - cf
- ae + bd = (a + b)(e + d) - ad - be
- af + cd = (a + c)(d + f) - ad - cf
- */
- static void mul(Fp6T& z, const Fp6T& x, const Fp6T& y)
- {
-//clk.begin();
- const Fp2& a = x.a;
- const Fp2& b = x.b;
- const Fp2& c = x.c;
- const Fp2& d = y.a;
- const Fp2& e = y.b;
- const Fp2& f = y.c;
-#if 1
- Fp2Dbl AD, BE, CF;
- Fp2Dbl::mulPre(AD, a, d);
- Fp2Dbl::mulPre(BE, b, e);
- Fp2Dbl::mulPre(CF, c, f);
-
- Fp2 t1, t2, t3, t4;
- Fp2::add(t1, b, c);
- Fp2::add(t2, e, f);
- Fp2Dbl T1;
- Fp2Dbl::mulPre(T1, t1, t2);
- Fp2Dbl::sub(T1, T1, BE);
- Fp2Dbl::sub(T1, T1, CF);
- Fp2Dbl::mul_xi(T1, T1);
-
- Fp2::add(t2, a, b);
- Fp2::add(t3, e, d);
- Fp2Dbl T2;
- Fp2Dbl::mulPre(T2, t2, t3);
- Fp2Dbl::sub(T2, T2, AD);
- Fp2Dbl::sub(T2, T2, BE);
-
- Fp2::add(t3, a, c);
- Fp2::add(t4, d, f);
- Fp2Dbl T3;
- Fp2Dbl::mulPre(T3, t3, t4);
- Fp2Dbl::sub(T3, T3, AD);
- Fp2Dbl::sub(T3, T3, CF);
-
- Fp2Dbl::add(AD, AD, T1);
- Fp2Dbl::mod(z.a, AD);
- Fp2Dbl::mul_xi(CF, CF);
- Fp2Dbl::add(CF, CF, T2);
- Fp2Dbl::mod(z.b, CF);
- Fp2Dbl::add(T3, T3, BE);
- Fp2Dbl::mod(z.c, T3);
-#else
- Fp2 ad, be, cf;
- Fp2::mul(ad, a, d);
- Fp2::mul(be, b, e);
- Fp2::mul(cf, c, f);
-
- Fp2 t1, t2, t3, t4;
- Fp2::add(t1, b, c);
- Fp2::add(t2, e, f);
- t1 *= t2;
- t1 -= be;
- t1 -= cf;
- Fp2::mul_xi(t1, t1);
-
- Fp2::add(t2, a, b);
- Fp2::add(t3, e, d);
- t2 *= t3;
- t2 -= ad;
- t2 -= be;
-
- Fp2::add(t3, a, c);
- Fp2::add(t4, d, f);
- t3 *= t4;
- t3 -= ad;
- t3 -= cf;
-
- Fp2::add(z.a, ad, t1);
- Fp2::mul_xi(z.b, cf);
- z.b += t2;
- Fp2::add(z.c, t3, be);
-#endif
-//clk.end();
- }
+ static inline void mul(Fp6T& z, const Fp6T& x, const Fp6T& y);
/*
x = a + bv + cv^2, v^3 = xi
y = 1/x = p/q where
@@ -1040,6 +950,94 @@ struct Fp6T : public fp::Serializable<Fp6T<_Fp>,
}
};
+template<class Fp>
+struct Fp6DblT {
+ typedef Fp2T<Fp> Fp2;
+ typedef Fp6T<Fp> Fp6;
+ typedef Fp2DblT<Fp> Fp2Dbl;
+ typedef Fp6DblT<Fp> Fp6Dbl;
+ typedef fp::Unit Unit;
+ Fp2Dbl a, b, c;
+ static void add(Fp6Dbl& z, const Fp6Dbl& x, const Fp6Dbl& y)
+ {
+ Fp2Dbl::add(z.a, x.a, y.a);
+ Fp2Dbl::add(z.b, x.b, y.b);
+ Fp2Dbl::add(z.c, x.c, y.c);
+ }
+ static void sub(Fp6Dbl& z, const Fp6Dbl& x, const Fp6Dbl& y)
+ {
+ Fp2Dbl::sub(z.a, x.a, y.a);
+ Fp2Dbl::sub(z.b, x.b, y.b);
+ Fp2Dbl::sub(z.c, x.c, y.c);
+ }
+ /*
+ x = a + bv + cv^2, y = d + ev + fv^2, v^3 = xi
+ xy = (ad + (bf + ce)xi) + ((ae + bd) + cf xi)v + ((af + cd) + be)v^2
+ bf + ce = (b + c)(e + f) - be - cf
+ ae + bd = (a + b)(e + d) - ad - be
+ af + cd = (a + c)(d + f) - ad - cf
+ */
+ static void mulPre(Fp6DblT& z, const Fp6& x, const Fp6& y)
+ {
+//clk.begin();
+ const Fp2& a = x.a;
+ const Fp2& b = x.b;
+ const Fp2& c = x.c;
+ const Fp2& d = y.a;
+ const Fp2& e = y.b;
+ const Fp2& f = y.c;
+ Fp2Dbl& za = z.a;
+ Fp2Dbl& zb = z.b;
+ Fp2Dbl& zc = z.c;
+ Fp2Dbl BE;
+ Fp2Dbl::mulPre(za, a, d);
+ Fp2Dbl::mulPre(BE, b, e);
+ Fp2Dbl::mulPre(zb, c, f);
+
+ Fp2 t1, t2, t3, t4;
+ Fp2::add(t1, b, c);
+ Fp2::add(t2, e, f);
+ Fp2Dbl T1;
+ Fp2Dbl::mulPre(T1, t1, t2);
+ Fp2Dbl::sub(T1, T1, BE);
+ Fp2Dbl::sub(T1, T1, zb);
+ Fp2Dbl::mul_xi(T1, T1);
+
+ Fp2::add(t2, a, b);
+ Fp2::add(t3, e, d);
+ Fp2Dbl T2;
+ Fp2Dbl::mulPre(T2, t2, t3);
+ Fp2Dbl::sub(T2, T2, za);
+ Fp2Dbl::sub(T2, T2, BE);
+
+ Fp2::add(t3, a, c);
+ Fp2::add(t4, d, f);
+ Fp2Dbl::mulPre(zc, t3, t4);
+ Fp2Dbl::sub(zc, zc, za);
+ Fp2Dbl::sub(zc, zc, zb);
+
+ Fp2Dbl::add(za, za, T1);
+ Fp2Dbl::mul_xi(zb, zb);
+ Fp2Dbl::add(zb, zb, T2);
+ Fp2Dbl::add(zc, zc, BE);
+//clk.end();
+ }
+ static void mod(Fp6& y, const Fp6Dbl& x)
+ {
+ Fp2Dbl::mod(y.a, x.a);
+ Fp2Dbl::mod(y.b, x.b);
+ Fp2Dbl::mod(y.c, x.c);
+ }
+};
+
+template<class Fp>
+inline void Fp6T<Fp>::mul(Fp6T<Fp>& z, const Fp6T<Fp>& x, const Fp6T<Fp>& y)
+{
+ Fp6DblT<Fp> Z;
+ Fp6DblT<Fp>::mulPre(Z, x, y);
+ Fp6DblT<Fp>::mod(z, Z);
+}
+
/*
Fp12T = Fp6[w] / (w^2 - v)
x = a + b w
@@ -1049,6 +1047,8 @@ struct Fp12T : public fp::Serializable<Fp12T<Fp>,
fp::Operator<Fp12T<Fp> > > {
typedef Fp2T<Fp> Fp2;
typedef Fp6T<Fp> Fp6;
+ typedef Fp2DblT<Fp> Fp2Dbl;
+ typedef Fp6DblT<Fp> Fp6Dbl;
typedef Fp BaseFp;
Fp6 a, b;
Fp12T() {}
@@ -1115,6 +1115,14 @@ struct Fp12T : public fp::Serializable<Fp12T<Fp>,
Fp2::add(z.b, x.a, y.b);
Fp2::add(z.a, t, y.a);
}
+ static void mulVadd(Fp6Dbl& z, const Fp6Dbl& x, const Fp6Dbl& y)
+ {
+ Fp2Dbl t;
+ Fp2Dbl::mul_xi(t, x.c);
+ Fp2Dbl::add(z.c, x.b, y.c);
+ Fp2Dbl::add(z.b, x.a, y.b);
+ Fp2Dbl::add(z.a, t, y.a);
+ }
/*
x = a + bw, y = c + dw, w^2 = v
z = xy = (a + bw)(c + dw) = (ac + bdv) + (ad + bc)w
@@ -1124,19 +1132,33 @@ struct Fp12T : public fp::Serializable<Fp12T<Fp>,
*/
static void mul(Fp12T& z, const Fp12T& x, const Fp12T& y)
{
+ // 4.7Kclk -> 4.55Kclk
const Fp6& a = x.a;
const Fp6& b = x.b;
const Fp6& c = y.a;
const Fp6& d = y.b;
- Fp6 t1, t2, ac, bd;
+ Fp6 t1, t2;
Fp6::add(t1, a, b);
Fp6::add(t2, c, d);
+#if 1
+ Fp6Dbl T, AC, BD;
+ Fp6Dbl::mulPre(AC, a, c);
+ Fp6Dbl::mulPre(BD, b, d);
+ mulVadd(T, BD, AC);
+ Fp6Dbl::mod(z.a, T);
+ Fp6Dbl::mulPre(T, t1, t2); // (a + b)(c + d)
+ Fp6Dbl::sub(T, T, AC);
+ Fp6Dbl::sub(T, T, BD);
+ Fp6Dbl::mod(z.b, T);
+#else
+ Fp6 ac, bd;
t1 *= t2; // (a + b)(c + d)
Fp6::mul(ac, a, c);
Fp6::mul(bd, b, d);
mulVadd(z.a, bd, ac);
t1 -= ac;
Fp6::sub(z.b, t1, bd);
+#endif
}
/*
x = a + bw, w^2 = v
diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/gmp_util.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/gmp_util.hpp
index 2dd71eb50..bcbd91a1e 100644
--- a/vendor/github.com/dexon-foundation/mcl/include/mcl/gmp_util.hpp
+++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/gmp_util.hpp
@@ -450,7 +450,8 @@ inline void getRand(bool *pb, mpz_class& z, size_t bitSize, fp::RandGen rg = fp:
*pb = false;
return;
}
- rg.read(buf, n * sizeof(buf[0]));
+ rg.read(pb, buf, n * sizeof(buf[0]));
+ if (!*pb) return;
uint32_t v = buf[n - 1];
if (rem == 0) {
v |= 1U << 31;
@@ -858,4 +859,96 @@ public:
#endif
};
+/*
+ Barrett Reduction
+ for non GMP version
+ mod of GMP is faster than Modp
+*/
+struct Modp {
+ static const size_t unitBitSize = sizeof(mcl::fp::Unit) * 8;
+ mpz_class p_;
+ mpz_class u_;
+ mpz_class a_;
+ size_t pBitSize_;
+ size_t N_;
+ bool initU_; // Is u_ initialized?
+ Modp()
+ : pBitSize_(0)
+ , N_(0)
+ , initU_(false)
+ {
+ }
+ // x &= 1 << (unitBitSize * unitSize)
+ void shrinkSize(mpz_class &x, size_t unitSize) const
+ {
+ size_t u = gmp::getUnitSize(x);
+ if (u < unitSize) return;
+ bool b;
+ gmp::setArray(&b, x, gmp::getUnit(x), unitSize);
+ (void)b;
+ assert(b);
+ }
+ // p_ is set by p and compute (u_, a_) if possible
+ void init(const mpz_class& p)
+ {
+ p_ = p;
+ pBitSize_ = gmp::getBitSize(p);
+ N_ = (pBitSize_ + unitBitSize - 1) / unitBitSize;
+ initU_ = false;
+#if 0
+ u_ = (mpz_class(1) << (unitBitSize * 2 * N_)) / p_;
+#else
+ /*
+ 1 << (unitBitSize * 2 * N_) may be overflow,
+ so use (1 << (unitBitSize * 2 * N_)) - 1 because u_ is same.
+ */
+ uint8_t buf[48 * 2];
+ const size_t byteSize = unitBitSize / 8 * 2 * N_;
+ if (byteSize > sizeof(buf)) return;
+ memset(buf, 0xff, byteSize);
+ bool b;
+ gmp::setArray(&b, u_, buf, byteSize);
+ if (!b) return;
+#endif
+ u_ /= p_;
+ a_ = mpz_class(1) << (unitBitSize * (N_ + 1));
+ initU_ = true;
+ }
+ void modp(mpz_class& r, const mpz_class& t) const
+ {
+ assert(p_ > 0);
+ const size_t tBitSize = gmp::getBitSize(t);
+ // use gmp::mod if init() fails or t is too large
+ if (tBitSize > unitBitSize * 2 * N_ || !initU_) {
+ gmp::mod(r, t, p_);
+ return;
+ }
+ if (tBitSize < pBitSize_) {
+ r = t;
+ return;
+ }
+ // mod is faster than modp if t is small
+ if (tBitSize <= unitBitSize * N_) {
+ gmp::mod(r, t, p_);
+ return;
+ }
+ mpz_class q;
+ q = t;
+ q >>= unitBitSize * (N_ - 1);
+ q *= u_;
+ q >>= unitBitSize * (N_ + 1);
+ q *= p_;
+ shrinkSize(q, N_ + 1);
+ r = t;
+ shrinkSize(r, N_ + 1);
+ r -= q;
+ if (r < 0) {
+ r += a_;
+ }
+ if (r >= p_) {
+ r -= p_;
+ }
+ }
+};
+
} // mcl
diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/impl/bn_c_impl.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/impl/bn_c_impl.hpp
new file mode 100644
index 000000000..bec2466dd
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/impl/bn_c_impl.hpp
@@ -0,0 +1,643 @@
+/*
+ This is an internal header
+ Do not include this
+*/
+#define MCLBN_DLL_EXPORT
+#include <mcl/bn.h>
+
+#if MCLBN_FP_UNIT_SIZE == 4 && MCLBN_FR_UNIT_SIZE == 4
+#include <mcl/bn256.hpp>
+#elif MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE == 6
+#include <mcl/bn384.hpp>
+#elif MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE == 4
+#include <mcl/bls12_381.hpp>
+#elif MCLBN_FP_UNIT_SIZE == 8 && MCLBN_FR_UNIT_SIZE == 8
+#include <mcl/bn512.hpp>
+#else
+ #error "not supported size"
+#endif
+#include <mcl/lagrange.hpp>
+#include <mcl/ecparam.hpp>
+using namespace mcl::bn;
+
+static Fr *cast(mclBnFr *p) { return reinterpret_cast<Fr*>(p); }
+static const Fr *cast(const mclBnFr *p) { return reinterpret_cast<const Fr*>(p); }
+
+static G1 *cast(mclBnG1 *p) { return reinterpret_cast<G1*>(p); }
+static const G1 *cast(const mclBnG1 *p) { return reinterpret_cast<const G1*>(p); }
+
+static G2 *cast(mclBnG2 *p) { return reinterpret_cast<G2*>(p); }
+static const G2 *cast(const mclBnG2 *p) { return reinterpret_cast<const G2*>(p); }
+
+static Fp12 *cast(mclBnGT *p) { return reinterpret_cast<Fp12*>(p); }
+static const Fp12 *cast(const mclBnGT *p) { return reinterpret_cast<const Fp12*>(p); }
+
+static Fp6 *cast(uint64_t *p) { return reinterpret_cast<Fp6*>(p); }
+static const Fp6 *cast(const uint64_t *p) { return reinterpret_cast<const Fp6*>(p); }
+
+static Fp2 *cast(mclBnFp2 *p) { return reinterpret_cast<Fp2*>(p); }
+static const Fp2 *cast(const mclBnFp2 *p) { return reinterpret_cast<const Fp2*>(p); }
+
+static Fp *cast(mclBnFp *p) { return reinterpret_cast<Fp*>(p); }
+static const Fp *cast(const mclBnFp *p) { return reinterpret_cast<const Fp*>(p); }
+
+template<class T>
+int setStr(T *x, const char *buf, mclSize bufSize, int ioMode)
+{
+ size_t n = cast(x)->deserialize(buf, bufSize, ioMode);
+ return n > 0 ? 0 : -1;
+}
+
+#ifdef __EMSCRIPTEN__
+// use these functions forcibly
+extern "C" MCLBN_DLL_API void *mclBnMalloc(size_t n)
+{
+ return malloc(n);
+}
+extern "C" MCLBN_DLL_API void mclBnFree(void *p)
+{
+ free(p);
+}
+#endif
+
+int mclBn_getVersion()
+{
+ return mcl::version;
+}
+
+int mclBn_init(int curve, int compiledTimeVar)
+{
+ if (compiledTimeVar != MCLBN_COMPILED_TIME_VAR) {
+ return -(compiledTimeVar | (MCLBN_COMPILED_TIME_VAR * 100));
+ }
+ if (MCL_EC_BEGIN <= curve && curve < MCL_EC_END) {
+ const mcl::EcParam *para = mcl::getEcParam(curve);
+ if (para == 0) return -2;
+ bool b;
+ initG1only(&b, *para);
+ return b ? 0 : -1;
+ }
+ const mcl::CurveParam& cp = mcl::getCurveParam(curve);
+ bool b;
+ initPairing(&b, cp);
+ return b ? 0 : -1;
+}
+
+int mclBn_getOpUnitSize()
+{
+ return (int)Fp::getUnitSize() * sizeof(mcl::fp::Unit) / sizeof(uint64_t);
+}
+
+int mclBn_getG1ByteSize()
+{
+ return mclBn_getFpByteSize();
+}
+
+int mclBn_getFrByteSize()
+{
+ return (int)Fr::getByteSize();
+}
+
+int mclBn_getFpByteSize()
+{
+ return (int)Fp::getByteSize();
+}
+
+mclSize mclBn_getCurveOrder(char *buf, mclSize maxBufSize)
+{
+ return Fr::getModulo(buf, maxBufSize);
+}
+
+mclSize mclBn_getFieldOrder(char *buf, mclSize maxBufSize)
+{
+ return Fp::getModulo(buf, maxBufSize);
+}
+
+////////////////////////////////////////////////
+// set zero
+void mclBnFr_clear(mclBnFr *x)
+{
+ cast(x)->clear();
+}
+
+// set x to y
+void mclBnFr_setInt(mclBnFr *y, mclInt x)
+{
+ *cast(y) = x;
+}
+void mclBnFr_setInt32(mclBnFr *y, int x)
+{
+ *cast(y) = x;
+}
+
+int mclBnFr_setStr(mclBnFr *x, const char *buf, mclSize bufSize, int ioMode)
+{
+ return setStr(x, buf, bufSize, ioMode);
+}
+int mclBnFr_setLittleEndian(mclBnFr *x, const void *buf, mclSize bufSize)
+{
+ cast(x)->setArrayMask((const char *)buf, bufSize);
+ return 0;
+}
+int mclBnFr_setLittleEndianMod(mclBnFr *x, const void *buf, mclSize bufSize)
+{
+ bool b;
+ cast(x)->setArray(&b, (const char *)buf, bufSize, mcl::fp::Mod);
+ return b ? 0 : -1;
+}
+mclSize mclBnFr_deserialize(mclBnFr *x, const void *buf, mclSize bufSize)
+{
+ return (mclSize)cast(x)->deserialize(buf, bufSize);
+}
+// return 1 if true
+int mclBnFr_isValid(const mclBnFr *x)
+{
+ return cast(x)->isValid();
+}
+int mclBnFr_isEqual(const mclBnFr *x, const mclBnFr *y)
+{
+ return *cast(x) == *cast(y);
+}
+int mclBnFr_isZero(const mclBnFr *x)
+{
+ return cast(x)->isZero();
+}
+int mclBnFr_isOne(const mclBnFr *x)
+{
+ return cast(x)->isOne();
+}
+
+#ifndef MCL_DONT_USE_CSRPNG
+int mclBnFr_setByCSPRNG(mclBnFr *x)
+{
+ bool b;
+ cast(x)->setByCSPRNG(&b);
+ return b ? 0 : -1;
+}
+void mclBn_setRandFunc(void *self, unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize))
+{
+ mcl::fp::RandGen::setRandFunc(self, readFunc);
+}
+#endif
+
+// hash(buf) and set x
+int mclBnFr_setHashOf(mclBnFr *x, const void *buf, mclSize bufSize)
+{
+ cast(x)->setHashOf(buf, bufSize);
+ return 0;
+}
+
+mclSize mclBnFr_getStr(char *buf, mclSize maxBufSize, const mclBnFr *x, int ioMode)
+{
+ return cast(x)->getStr(buf, maxBufSize, ioMode);
+}
+mclSize mclBnFr_serialize(void *buf, mclSize maxBufSize, const mclBnFr *x)
+{
+ return (mclSize)cast(x)->serialize(buf, maxBufSize);
+}
+
+void mclBnFr_neg(mclBnFr *y, const mclBnFr *x)
+{
+ Fr::neg(*cast(y), *cast(x));
+}
+void mclBnFr_inv(mclBnFr *y, const mclBnFr *x)
+{
+ Fr::inv(*cast(y), *cast(x));
+}
+void mclBnFr_sqr(mclBnFr *y, const mclBnFr *x)
+{
+ Fr::sqr(*cast(y), *cast(x));
+}
+void mclBnFr_add(mclBnFr *z, const mclBnFr *x, const mclBnFr *y)
+{
+ Fr::add(*cast(z),*cast(x), *cast(y));
+}
+void mclBnFr_sub(mclBnFr *z, const mclBnFr *x, const mclBnFr *y)
+{
+ Fr::sub(*cast(z),*cast(x), *cast(y));
+}
+void mclBnFr_mul(mclBnFr *z, const mclBnFr *x, const mclBnFr *y)
+{
+ Fr::mul(*cast(z),*cast(x), *cast(y));
+}
+void mclBnFr_div(mclBnFr *z, const mclBnFr *x, const mclBnFr *y)
+{
+ Fr::div(*cast(z),*cast(x), *cast(y));
+}
+
+////////////////////////////////////////////////
+// set zero
+void mclBnG1_clear(mclBnG1 *x)
+{
+ cast(x)->clear();
+}
+
+int mclBnG1_setStr(mclBnG1 *x, const char *buf, mclSize bufSize, int ioMode)
+{
+ return setStr(x, buf, bufSize, ioMode);
+}
+mclSize mclBnG1_deserialize(mclBnG1 *x, const void *buf, mclSize bufSize)
+{
+ return (mclSize)cast(x)->deserialize(buf, bufSize);
+}
+
+// return 1 if true
+int mclBnG1_isValid(const mclBnG1 *x)
+{
+ return cast(x)->isValid();
+}
+int mclBnG1_isEqual(const mclBnG1 *x, const mclBnG1 *y)
+{
+ return *cast(x) == *cast(y);
+}
+int mclBnG1_isZero(const mclBnG1 *x)
+{
+ return cast(x)->isZero();
+}
+int mclBnG1_isValidOrder(const mclBnG1 *x)
+{
+ return cast(x)->isValidOrder();
+}
+
+int mclBnG1_hashAndMapTo(mclBnG1 *x, const void *buf, mclSize bufSize)
+{
+ hashAndMapToG1(*cast(x), buf, bufSize);
+ return 0;
+}
+
+mclSize mclBnG1_getStr(char *buf, mclSize maxBufSize, const mclBnG1 *x, int ioMode)
+{
+ return cast(x)->getStr(buf, maxBufSize, ioMode);
+}
+
+mclSize mclBnG1_serialize(void *buf, mclSize maxBufSize, const mclBnG1 *x)
+{
+ return (mclSize)cast(x)->serialize(buf, maxBufSize);
+}
+
+void mclBnG1_neg(mclBnG1 *y, const mclBnG1 *x)
+{
+ G1::neg(*cast(y), *cast(x));
+}
+void mclBnG1_dbl(mclBnG1 *y, const mclBnG1 *x)
+{
+ G1::dbl(*cast(y), *cast(x));
+}
+void mclBnG1_normalize(mclBnG1 *y, const mclBnG1 *x)
+{
+ G1::normalize(*cast(y), *cast(x));
+}
+void mclBnG1_add(mclBnG1 *z, const mclBnG1 *x, const mclBnG1 *y)
+{
+ G1::add(*cast(z),*cast(x), *cast(y));
+}
+void mclBnG1_sub(mclBnG1 *z, const mclBnG1 *x, const mclBnG1 *y)
+{
+ G1::sub(*cast(z),*cast(x), *cast(y));
+}
+void mclBnG1_mul(mclBnG1 *z, const mclBnG1 *x, const mclBnFr *y)
+{
+ G1::mul(*cast(z),*cast(x), *cast(y));
+}
+void mclBnG1_mulCT(mclBnG1 *z, const mclBnG1 *x, const mclBnFr *y)
+{
+ G1::mulCT(*cast(z),*cast(x), *cast(y));
+}
+
+////////////////////////////////////////////////
+// set zero
+void mclBnG2_clear(mclBnG2 *x)
+{
+ cast(x)->clear();
+}
+
+int mclBnG2_setStr(mclBnG2 *x, const char *buf, mclSize bufSize, int ioMode)
+{
+ return setStr(x, buf, bufSize, ioMode);
+}
+mclSize mclBnG2_deserialize(mclBnG2 *x, const void *buf, mclSize bufSize)
+{
+ return (mclSize)cast(x)->deserialize(buf, bufSize);
+}
+
+// return 1 if true
+int mclBnG2_isValid(const mclBnG2 *x)
+{
+ return cast(x)->isValid();
+}
+int mclBnG2_isEqual(const mclBnG2 *x, const mclBnG2 *y)
+{
+ return *cast(x) == *cast(y);
+}
+int mclBnG2_isZero(const mclBnG2 *x)
+{
+ return cast(x)->isZero();
+}
+int mclBnG2_isValidOrder(const mclBnG2 *x)
+{
+ return cast(x)->isValidOrder();
+}
+
+int mclBnG2_hashAndMapTo(mclBnG2 *x, const void *buf, mclSize bufSize)
+{
+ hashAndMapToG2(*cast(x), buf, bufSize);
+ return 0;
+}
+
+mclSize mclBnG2_getStr(char *buf, mclSize maxBufSize, const mclBnG2 *x, int ioMode)
+{
+ return cast(x)->getStr(buf, maxBufSize, ioMode);
+}
+
+mclSize mclBnG2_serialize(void *buf, mclSize maxBufSize, const mclBnG2 *x)
+{
+ return (mclSize)cast(x)->serialize(buf, maxBufSize);
+}
+
+void mclBnG2_neg(mclBnG2 *y, const mclBnG2 *x)
+{
+ G2::neg(*cast(y), *cast(x));
+}
+void mclBnG2_dbl(mclBnG2 *y, const mclBnG2 *x)
+{
+ G2::dbl(*cast(y), *cast(x));
+}
+void mclBnG2_normalize(mclBnG2 *y, const mclBnG2 *x)
+{
+ G2::normalize(*cast(y), *cast(x));
+}
+void mclBnG2_add(mclBnG2 *z, const mclBnG2 *x, const mclBnG2 *y)
+{
+ G2::add(*cast(z),*cast(x), *cast(y));
+}
+void mclBnG2_sub(mclBnG2 *z, const mclBnG2 *x, const mclBnG2 *y)
+{
+ G2::sub(*cast(z),*cast(x), *cast(y));
+}
+void mclBnG2_mul(mclBnG2 *z, const mclBnG2 *x, const mclBnFr *y)
+{
+ G2::mul(*cast(z),*cast(x), *cast(y));
+}
+void mclBnG2_mulCT(mclBnG2 *z, const mclBnG2 *x, const mclBnFr *y)
+{
+ G2::mulCT(*cast(z),*cast(x), *cast(y));
+}
+
+////////////////////////////////////////////////
+// set zero
+void mclBnGT_clear(mclBnGT *x)
+{
+ cast(x)->clear();
+}
+void mclBnGT_setInt(mclBnGT *y, mclInt x)
+{
+ cast(y)->clear();
+ *(cast(y)->getFp0()) = x;
+}
+void mclBnGT_setInt32(mclBnGT *y, int x)
+{
+ cast(y)->clear();
+ *(cast(y)->getFp0()) = x;
+}
+
+int mclBnGT_setStr(mclBnGT *x, const char *buf, mclSize bufSize, int ioMode)
+{
+ return setStr(x, buf, bufSize, ioMode);
+}
+mclSize mclBnGT_deserialize(mclBnGT *x, const void *buf, mclSize bufSize)
+{
+ return (mclSize)cast(x)->deserialize(buf, bufSize);
+}
+
+// return 1 if true
+int mclBnGT_isEqual(const mclBnGT *x, const mclBnGT *y)
+{
+ return *cast(x) == *cast(y);
+}
+int mclBnGT_isZero(const mclBnGT *x)
+{
+ return cast(x)->isZero();
+}
+int mclBnGT_isOne(const mclBnGT *x)
+{
+ return cast(x)->isOne();
+}
+
+mclSize mclBnGT_getStr(char *buf, mclSize maxBufSize, const mclBnGT *x, int ioMode)
+{
+ return cast(x)->getStr(buf, maxBufSize, ioMode);
+}
+
+mclSize mclBnGT_serialize(void *buf, mclSize maxBufSize, const mclBnGT *x)
+{
+ return (mclSize)cast(x)->serialize(buf, maxBufSize);
+}
+
+void mclBnGT_neg(mclBnGT *y, const mclBnGT *x)
+{
+ Fp12::neg(*cast(y), *cast(x));
+}
+void mclBnGT_inv(mclBnGT *y, const mclBnGT *x)
+{
+ Fp12::inv(*cast(y), *cast(x));
+}
+void mclBnGT_sqr(mclBnGT *y, const mclBnGT *x)
+{
+ Fp12::sqr(*cast(y), *cast(x));
+}
+void mclBnGT_add(mclBnGT *z, const mclBnGT *x, const mclBnGT *y)
+{
+ Fp12::add(*cast(z),*cast(x), *cast(y));
+}
+void mclBnGT_sub(mclBnGT *z, const mclBnGT *x, const mclBnGT *y)
+{
+ Fp12::sub(*cast(z),*cast(x), *cast(y));
+}
+void mclBnGT_mul(mclBnGT *z, const mclBnGT *x, const mclBnGT *y)
+{
+ Fp12::mul(*cast(z),*cast(x), *cast(y));
+}
+void mclBnGT_div(mclBnGT *z, const mclBnGT *x, const mclBnGT *y)
+{
+ Fp12::div(*cast(z),*cast(x), *cast(y));
+}
+
+void mclBnGT_pow(mclBnGT *z, const mclBnGT *x, const mclBnFr *y)
+{
+ Fp12::pow(*cast(z), *cast(x), *cast(y));
+}
+void mclBnGT_powGeneric(mclBnGT *z, const mclBnGT *x, const mclBnFr *y)
+{
+ Fp12::powGeneric(*cast(z), *cast(x), *cast(y));
+}
+
+void mclBn_pairing(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y)
+{
+ pairing(*cast(z), *cast(x), *cast(y));
+}
+void mclBn_finalExp(mclBnGT *y, const mclBnGT *x)
+{
+ finalExp(*cast(y), *cast(x));
+}
+void mclBn_millerLoop(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y)
+{
+ millerLoop(*cast(z), *cast(x), *cast(y));
+}
+int mclBn_getUint64NumToPrecompute(void)
+{
+ return int(BN::param.precomputedQcoeffSize * sizeof(Fp6) / sizeof(uint64_t));
+}
+
+void mclBn_precomputeG2(uint64_t *Qbuf, const mclBnG2 *Q)
+{
+ precomputeG2(cast(Qbuf), *cast(Q));
+}
+
+void mclBn_precomputedMillerLoop(mclBnGT *f, const mclBnG1 *P, const uint64_t *Qbuf)
+{
+ precomputedMillerLoop(*cast(f), *cast(P), cast(Qbuf));
+}
+
+void mclBn_precomputedMillerLoop2(mclBnGT *f, const mclBnG1 *P1, const uint64_t *Q1buf, const mclBnG1 *P2, const uint64_t *Q2buf)
+{
+ precomputedMillerLoop2(*cast(f), *cast(P1), cast(Q1buf), *cast(P2), cast(Q2buf));
+}
+
+void mclBn_precomputedMillerLoop2mixed(mclBnGT *f, const mclBnG1 *P1, const mclBnG2 *Q1, const mclBnG1 *P2, const uint64_t *Q2buf)
+{
+ precomputedMillerLoop2mixed(*cast(f), *cast(P1), *cast(Q1), *cast(P2), cast(Q2buf));
+}
+
+int mclBn_FrLagrangeInterpolation(mclBnFr *out, const mclBnFr *xVec, const mclBnFr *yVec, mclSize k)
+{
+ bool b;
+ mcl::LagrangeInterpolation(&b, *cast(out), cast(xVec), cast(yVec), k);
+ return b ? 0 : -1;
+}
+int mclBn_G1LagrangeInterpolation(mclBnG1 *out, const mclBnFr *xVec, const mclBnG1 *yVec, mclSize k)
+{
+ bool b;
+ mcl::LagrangeInterpolation(&b, *cast(out), cast(xVec), cast(yVec), k);
+ return b ? 0 : -1;
+}
+int mclBn_G2LagrangeInterpolation(mclBnG2 *out, const mclBnFr *xVec, const mclBnG2 *yVec, mclSize k)
+{
+ bool b;
+ mcl::LagrangeInterpolation(&b, *cast(out), cast(xVec), cast(yVec), k);
+ return b ? 0 : -1;
+}
+int mclBn_FrEvaluatePolynomial(mclBnFr *out, const mclBnFr *cVec, mclSize cSize, const mclBnFr *x)
+{
+ bool b;
+ mcl::evaluatePolynomial(&b, *cast(out), cast(cVec), cSize, *cast(x));
+ return b ? 0 : -1;
+}
+int mclBn_G1EvaluatePolynomial(mclBnG1 *out, const mclBnG1 *cVec, mclSize cSize, const mclBnFr *x)
+{
+ bool b;
+ mcl::evaluatePolynomial(&b, *cast(out), cast(cVec), cSize, *cast(x));
+ return b ? 0 : -1;
+}
+int mclBn_G2EvaluatePolynomial(mclBnG2 *out, const mclBnG2 *cVec, mclSize cSize, const mclBnFr *x)
+{
+ bool b;
+ mcl::evaluatePolynomial(&b, *cast(out), cast(cVec), cSize, *cast(x));
+ return b ? 0 : -1;
+}
+
+void mclBn_verifyOrderG1(int doVerify)
+{
+ verifyOrderG1(doVerify != 0);
+}
+
+void mclBn_verifyOrderG2(int doVerify)
+{
+ verifyOrderG2(doVerify != 0);
+}
+
+mclSize mclBnFp_getStr(char *buf, mclSize maxBufSize, const mclBnFp *x, int ioMode)
+{
+ return cast(x)->getStr(buf, maxBufSize, ioMode);
+}
+int mclBnFp_setStr(mclBnFp *x, const char *buf, mclSize bufSize, int ioMode)
+{
+ return setStr(x, buf, bufSize, ioMode);
+}
+mclSize mclBnFp_deserialize(mclBnFp *x, const void *buf, mclSize bufSize)
+{
+ return (mclSize)cast(x)->deserialize(buf, bufSize);
+}
+
+mclSize mclBnFp_serialize(void *buf, mclSize maxBufSize, const mclBnFp *x)
+{
+ return (mclSize)cast(x)->serialize(buf, maxBufSize);
+}
+
+void mclBnFp_clear(mclBnFp *x)
+{
+ cast(x)->clear();
+}
+
+int mclBnFp_setLittleEndian(mclBnFp *x, const void *buf, mclSize bufSize)
+{
+ cast(x)->setArrayMask((const char *)buf, bufSize);
+ return 0;
+}
+
+int mclBnFp_setLittleEndianMod(mclBnFp *x, const void *buf, mclSize bufSize)
+{
+ bool b;
+ cast(x)->setArray(&b, (const char *)buf, bufSize, mcl::fp::Mod);
+ return b ? 0 : -1;
+}
+int mclBnFp_isEqual(const mclBnFp *x, const mclBnFp *y)
+{
+ return *cast(x) == *cast(y);
+}
+
+int mclBnFp_setHashOf(mclBnFp *x, const void *buf, mclSize bufSize)
+{
+ cast(x)->setHashOf(buf, bufSize);
+ return 0;
+}
+
+int mclBnFp_mapToG1(mclBnG1 *y, const mclBnFp *x)
+{
+ bool b;
+ mapToG1(&b, *cast(y), *cast(x));
+ return b ? 0 : -1;
+}
+
+mclSize mclBnFp2_deserialize(mclBnFp2 *x, const void *buf, mclSize bufSize)
+{
+ return (mclSize)cast(x)->deserialize(buf, bufSize);
+}
+
+mclSize mclBnFp2_serialize(void *buf, mclSize maxBufSize, const mclBnFp2 *x)
+{
+ return (mclSize)cast(x)->serialize(buf, maxBufSize);
+}
+
+void mclBnFp2_clear(mclBnFp2 *x)
+{
+ cast(x)->clear();
+}
+
+int mclBnFp2_isEqual(const mclBnFp2 *x, const mclBnFp2 *y)
+{
+ return *cast(x) == *cast(y);
+}
+
+int mclBnFp2_mapToG2(mclBnG2 *y, const mclBnFp2 *x)
+{
+ bool b;
+ mapToG2(&b, *cast(y), *cast(x));
+ return b ? 0 : -1;
+}
+
+int mclBnG1_getBasePoint(mclBnG1 *x)
+{
+ *cast(x) = mcl::bn::getG1basePoint();
+ return 0;
+}
+
diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/lagrange.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/lagrange.hpp
index 7c0218896..18e0597ec 100644
--- a/vendor/github.com/dexon-foundation/mcl/include/mcl/lagrange.hpp
+++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/lagrange.hpp
@@ -15,14 +15,19 @@ namespace mcl {
template<class G, class F>
void LagrangeInterpolation(bool *pb, G& out, const F *S, const G *vec, size_t k)
{
+ if (k == 0) {
+ *pb = false;
+ return;
+ }
+ if (k == 1) {
+ out = vec[0];
+ *pb = true;
+ return;
+ }
/*
delta_{i,S}(0) = prod_{j != i} S[j] / (S[j] - S[i]) = a / b
where a = prod S[j], b = S[i] * prod_{j != i} (S[j] - S[i])
*/
- if (k < 2) {
- *pb = false;
- return;
- }
F a = S[0];
for (size_t i = 1; i < k; i++) {
a *= S[i];
@@ -58,15 +63,20 @@ void LagrangeInterpolation(bool *pb, G& out, const F *S, const G *vec, size_t k)
/*
out = f(x) = c[0] + c[1] * x + c[2] * x^2 + ... + c[cSize - 1] * x^(cSize - 1)
- @retval 0 if succeed else -1
+ @retval 0 if succeed else -1 (if cSize == 0)
*/
template<class G, class T>
void evaluatePolynomial(bool *pb, G& out, const G *c, size_t cSize, const T& x)
{
- if (cSize < 2) {
+ if (cSize == 0) {
*pb = false;
return;
}
+ if (cSize == 1) {
+ out = c[0];
+ *pb = true;
+ return;
+ }
G y = c[cSize - 1];
for (int i = (int)cSize - 2; i >= 0; i--) {
G::mul(y, y, x);
diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/op.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/op.hpp
index d108d1a55..36d37035e 100644
--- a/vendor/github.com/dexon-foundation/mcl/include/mcl/op.hpp
+++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/op.hpp
@@ -26,6 +26,8 @@
namespace mcl {
+static const int version = 0x092; /* 0xABC = A.BC */
+
/*
specifies available string format mode for X::setIoMode()
// for Fp, Fp2, Fp6, Fp12
@@ -59,7 +61,7 @@ namespace mcl {
IoArray
array of Unit(fixed size = Fp::getByteSize())
IoArrayRaw
- array of Unit(fixed size = Fp::getByteSize()) without Montgomery convresion
+ array of Unit(fixed size = Fp::getByteSize()) without Montgomery conversion
// for Ec::setIoMode()
IoEcAffine(default)
@@ -127,6 +129,15 @@ typedef int (*int2u)(Unit*, const Unit*);
typedef Unit (*u1uII)(Unit*, Unit, Unit);
typedef Unit (*u3u)(Unit*, const Unit*, const Unit*);
+/*
+ disable -Wcast-function-type
+ the number of arguments of some JIT functions is smaller than that of T
+*/
+template<class T, class S>
+T func_ptr_cast(S func)
+{
+ return reinterpret_cast<T>(reinterpret_cast<void*>(func));
+}
struct Block {
const Unit *p; // pointer to original FpT.v_
size_t n;
@@ -152,7 +163,8 @@ enum PrimeMode {
enum MaskMode {
NoMask = 0, // throw if greater or equal
SmallMask = 1, // 1-bit smaller mask if greater or equal
- MaskAndMod = 2 // mask and substract if greater or equal
+ MaskAndMod = 2, // mask and substract if greater or equal
+ Mod = 3 // mod p
};
struct Op {
@@ -165,6 +177,7 @@ struct Op {
mpz_class mp;
uint32_t pmod4;
mcl::SquareRoot sq;
+ mcl::Modp modp;
Unit half[maxUnitSize]; // (p + 1) / 2
Unit oneRep[maxUnitSize]; // 1(=inv R if Montgomery)
/*
@@ -193,8 +206,6 @@ struct Op {
void2u fp2_sqrA_;
void3u fpDbl_addA_;
void3u fpDbl_subA_;
- void3u fpDbl_addPreA_;
- void3u fpDbl_subPreA_;
void3u fpDbl_mulPreA_;
void2u fpDbl_sqrPreA_;
void2u fpDbl_modA_;
@@ -282,8 +293,6 @@ struct Op {
fp2_sqrA_ = 0;
fpDbl_addA_ = 0;
fpDbl_subA_ = 0;
- fpDbl_addPreA_ = 0;
- fpDbl_subPreA_ = 0;
fpDbl_mulPreA_ = 0;
fpDbl_sqrPreA_ = 0;
fpDbl_modA_ = 0;
@@ -345,8 +354,7 @@ struct Op {
*/
fp_mul(y, x, R2, p);
}
- bool init(const mpz_class& p, size_t maxBitSize, Mode mode, size_t mclMaxBitSize = MCL_MAX_BIT_SIZE);
- void initFp2(int xi_a);
+ bool init(const mpz_class& p, size_t maxBitSize, int xi_a, Mode mode, size_t mclMaxBitSize = MCL_MAX_BIT_SIZE);
#ifdef MCL_USE_XBYAK
static FpGenerator* createFpGenerator();
static void destroyFpGenerator(FpGenerator *fg);
diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/randgen.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/randgen.hpp
index 4bfb30b03..30502fc10 100644
--- a/vendor/github.com/dexon-foundation/mcl/include/mcl/randgen.hpp
+++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/randgen.hpp
@@ -15,10 +15,16 @@
namespace mcl {
struct RandomGeneratorJS {
- void read(void *buf, size_t bufSize)
+ void read(bool *pb, void *buf, uint32_t byteSize)
{
+ // cf. https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
+ if (byteSize > 65536) {
+ *pb = false;
+ return;
+ }
// use crypto.getRandomValues
- EM_ASM({Module.cryptoGetRandomValues($0, $1)}, buf, bufSize);
+ EM_ASM({Module.cryptoGetRandomValues($0, $1)}, buf, byteSize);
+ *pb = true;
}
};
} // mcl
@@ -38,28 +44,33 @@ namespace mcl { namespace fp {
namespace local {
template<class RG>
-void readWrapper(void *self, void *buf, uint32_t bufSize)
+uint32_t readWrapper(void *self, void *buf, uint32_t byteSize)
{
- reinterpret_cast<RG*>(self)->read((uint8_t*)buf, bufSize);
+ bool b;
+ reinterpret_cast<RG*>(self)->read(&b, (uint8_t*)buf, byteSize);
+ if (b) return byteSize;
+ return 0;
}
#if 0 // #if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
template<>
-inline void readWrapper<std::random_device>(void *self, void *buf, uint32_t bufSize)
+inline uint32_t readWrapper<std::random_device>(void *self, void *buf, uint32_t byteSize)
{
+ const uint32_t keep = byteSize;
std::random_device& rg = *reinterpret_cast<std::random_device*>(self);
uint8_t *p = reinterpret_cast<uint8_t*>(buf);
uint32_t v;
- while (bufSize >= 4) {
+ while (byteSize >= 4) {
v = rg();
memcpy(p, &v, 4);
p += 4;
- bufSize -= 4;
+ byteSize -= 4;
}
- if (bufSize > 0) {
+ if (byteSize > 0) {
v = rg();
- memcpy(p, &v, bufSize);
+ memcpy(p, &v, byteSize);
}
+ return keep;
}
#endif
} // local
@@ -67,7 +78,7 @@ inline void readWrapper<std::random_device>(void *self, void *buf, uint32_t bufS
wrapper of cryptographically secure pseudo random number generator
*/
class RandGen {
- typedef void (*readFuncType)(void *self, void *buf, uint32_t bufSize);
+ typedef uint32_t (*readFuncType)(void *self, void *buf, uint32_t byteSize);
void *self_;
readFuncType readFunc_;
public:
@@ -87,16 +98,17 @@ public:
, readFunc_(local::readWrapper<RG>)
{
}
- void read(void *out, size_t byteSize)
+ void read(bool *pb, void *out, size_t byteSize)
{
- readFunc_(self_, out, static_cast<uint32_t>(byteSize));
+ uint32_t size = readFunc_(self_, out, static_cast<uint32_t>(byteSize));
+ *pb = size == byteSize;
}
#ifdef MCL_DONT_USE_CSPRNG
bool isZero() const { return false; } /* return false to avoid copying default rg */
#else
bool isZero() const { return self_ == 0 && readFunc_ == 0; }
#endif
- static RandGen& get()
+ static RandGen& getDefaultRandGen()
{
#ifdef MCL_DONT_USE_CSPRNG
static RandGen wrg;
@@ -109,14 +121,32 @@ public:
#endif
return wrg;
}
+ static RandGen& get()
+ {
+ static RandGen wrg(getDefaultRandGen());
+ return wrg;
+ }
/*
rg must be thread safe
- rg.read(void *buf, size_t bufSize);
+ rg.read(void *buf, size_t byteSize);
*/
static void setRandGen(const RandGen& rg)
{
get() = rg;
}
+ /*
+ set rand function
+ if self and readFunc are NULL then set default rand function
+ */
+ static void setRandFunc(void *self, readFuncType readFunc)
+ {
+ if (self == 0 && readFunc == 0) {
+ setRandGen(getDefaultRandGen());
+ } else {
+ RandGen rg(self, readFunc);
+ setRandGen(rg);
+ }
+ }
};
} } // mcl::fp
diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/vint.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/vint.hpp
index 32a51bb64..b087688c3 100644
--- a/vendor/github.com/dexon-foundation/mcl/include/mcl/vint.hpp
+++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/vint.hpp
@@ -568,6 +568,7 @@ void divNM(T *q, size_t qn, T *r, const T *x, size_t xn, const T *y, size_t yn)
yn = getRealSize(y, yn);
if (x == y) {
assert(xn == yn);
+ x_is_y:
clearN(r, rn);
if (q) {
q[0] = 1;
@@ -579,6 +580,7 @@ void divNM(T *q, size_t qn, T *r, const T *x, size_t xn, const T *y, size_t yn)
/*
if y > x then q = 0 and r = x
*/
+ q_is_zero:
copyN(r, x, xn);
clearN(r + xn, rn - xn);
if (q) clearN(q, qn);
@@ -598,11 +600,61 @@ void divNM(T *q, size_t qn, T *r, const T *x, size_t xn, const T *y, size_t yn)
clearN(r + 1, rn - 1);
return;
}
+ const size_t yTopBit = cybozu::bsr(y[yn - 1]);
assert(yn >= 2);
+ if (xn == yn) {
+ const size_t xTopBit = cybozu::bsr(x[xn - 1]);
+ if (xTopBit < yTopBit) goto q_is_zero;
+ if (yTopBit == xTopBit) {
+ int ret = compareNM(x, xn, y, yn);
+ if (ret == 0) goto x_is_y;
+ if (ret < 0) goto q_is_zero;
+ if (r) {
+ subN(r, x, y, yn);
+ }
+ if (q) {
+ q[0] = 1;
+ clearN(q + 1, qn - 1);
+ }
+ return;
+ }
+ assert(xTopBit > yTopBit);
+ // fast reduction for larger than fullbit-3 size p
+ if (yTopBit >= sizeof(T) * 8 - 4) {
+ T *xx = (T*)CYBOZU_ALLOCA(sizeof(T) * xn);
+ T qv = 0;
+ if (yTopBit == sizeof(T) * 8 - 2) {
+ copyN(xx, x, xn);
+ } else {
+ qv = x[xn - 1] >> (yTopBit + 1);
+ mulu1(xx, y, yn, qv);
+ subN(xx, x, xx, xn);
+ xn = getRealSize(xx, xn);
+ }
+ for (;;) {
+ T ret = subN(xx, xx, y, yn);
+ if (ret) {
+ addN(xx, xx, y, yn);
+ break;
+ }
+ qv++;
+ xn = getRealSize(xx, xn);
+ }
+ if (r) {
+ copyN(r, xx, xn);
+ clearN(r + xn, rn - xn);
+ }
+ if (q) {
+ q[0] = qv;
+ clearN(q + 1, qn - 1);
+ }
+ return;
+ }
+ }
/*
bitwise left shift x and y to adjust MSB of y[yn - 1] = 1
*/
- const size_t shift = sizeof(T) * 8 - 1 - cybozu::bsr(y[yn - 1]);
+ const size_t shift = sizeof(T) * 8 - 1 - yTopBit;
T *xx = (T*)CYBOZU_ALLOCA(sizeof(T) * (xn + 1));
const T *yy;
if (shift) {
@@ -1124,8 +1176,15 @@ public:
size_t unitSize = (sizeof(S) * size + sizeof(Unit) - 1) / sizeof(Unit);
buf_.alloc(pb, unitSize);
if (!*pb) return;
- buf_[unitSize - 1] = 0;
- memcpy(&buf_[0], x, sizeof(S) * size);
+ char *dst = (char *)&buf_[0];
+ const char *src = (const char *)x;
+ size_t i = 0;
+ for (; i < sizeof(S) * size; i++) {
+ dst[i] = src[i];
+ }
+ for (; i < sizeof(Unit) * unitSize; i++) {
+ dst[i] = 0;
+ }
trim(unitSize);
}
/*
@@ -1138,7 +1197,8 @@ public:
size_t n = max.size();
buf_.alloc(pb, n);
if (!*pb) return;
- rg.read(&buf_[0], n * sizeof(buf_[0]));
+ rg.read(pb, &buf_[0], n * sizeof(buf_[0]));
+ if (!*pb) return;
trim(n);
*this %= max;
}
@@ -1231,7 +1291,8 @@ public:
*/
void setStr(bool *pb, const char *str, int base = 0)
{
- const size_t maxN = MCL_MAX_BIT_SIZE / (sizeof(MCL_SIZEOF_UNIT) * 8);
+ // allow twice size of MCL_MAX_BIT_SIZE because of multiplication
+ const size_t maxN = (MCL_MAX_BIT_SIZE * 2 + unitBitSize - 1) / unitBitSize;
buf_.alloc(pb, maxN);
if (!*pb) return;
*pb = false;
diff --git a/vendor/github.com/dexon-foundation/mcl/misc/bench.txt b/vendor/github.com/dexon-foundation/mcl/misc/bench.txt
new file mode 100644
index 000000000..3e18e6b44
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/misc/bench.txt
@@ -0,0 +1,21 @@
+Core i7-7700 @ 3.6GHz
+ BN254 BLS12_381
+G1::mul 185.863Kclk 360.723Kclk
+G1::add 812.01 clk 1.540Kclk
+G1::dbl 837.24 clk 1.977Kclk
+G2::mul 340.125Kclk 642.457Kclk
+G2::add 2.233Kclk 4.368Kclk
+G2::dbl 2.134Kclk 4.088Kclk
+GT::pow 615.052Kclk 1.055Mclk
+G1::setStr chk 1.546Kclk 534.376Kclk
+G1::setStr 1.592Kclk 4.000Kclk
+G2::setStr chk 609.195Kclk 1.402Mclk
+G2::setStr 5.444Kclk 8.282Kclk
+hashAndMapToG1 26.997Kclk 336.207Kclk
+hashAndMapToG2 212.800Kclk 775.072Kclk
+pairing 909.076Kclk 2.367Mclk
+millerLoop 549.957Kclk 983.935Kclk
+finalExp 375.203Kclk 1.404Mclk
+precomputeG2 126.000Kclk 236.912Kclk
+precomputedML 427.272Kclk 729.234Kclk
+
diff --git a/vendor/github.com/dexon-foundation/mcl/misc/karatsuba.cpp b/vendor/github.com/dexon-foundation/mcl/misc/karatsuba.cpp
new file mode 100644
index 000000000..7c150c6e3
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/misc/karatsuba.cpp
@@ -0,0 +1,75 @@
+/*
+ sudo cpufreq-set -c 0 -g performance
+ mycl karatsuba.cpp -DMCL_USE_LLVM=1 ../lib/libmcl.a && ./a.out
+*/
+#include <stdio.h>
+#include <mcl/fp.hpp>
+#include <cybozu/xorshift.hpp>
+#include "../src/proto.hpp"
+#include "../src/low_func.hpp"
+#ifdef MCL_USE_LLVM
+#include "../src/low_func_llvm.hpp"
+#endif
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+
+typedef mcl::FpT<> Fp;
+
+using namespace mcl::fp;
+
+void dump(const Unit *x, size_t N)
+{
+ for (size_t i = 0; i < N; i++) {
+ printf("%016llx ", (long long)x[N - 1 - i]);
+ }
+ printf("\n");
+}
+
+void gggKara(uint64_t *z, const uint64_t *x, const uint64_t *)
+{
+ SqrPre<8, Gtag>::f(z, x);
+}
+void gggLLVM(uint64_t *z, const uint64_t *x, const uint64_t *y)
+{
+ MulPre<8, Ltag>::f(z, x, y);
+}
+
+template<size_t N>
+void benchKaratsuba()
+{
+ cybozu::XorShift rg;
+ printf("N=%d\n", (int)N);
+ Unit z[N * 2];
+ rg.read(z, N);
+ CYBOZU_BENCH("g:mulPre ", (MulPreCore<N, Gtag>::f), z, z, z);
+// CYBOZU_BENCH("g:mulKara", (MulPre<N, Gtag>::karatsuba), z, z, z);
+ CYBOZU_BENCH("g:sqrPre ", (SqrPreCore<N, Gtag>::f), z, z);
+// CYBOZU_BENCH("g:sqrKara", (SqrPre<N, Gtag>::karatsuba), z, z);
+
+#ifdef MCL_USE_LLVM
+ CYBOZU_BENCH("l:mulPre ", (MulPreCore<N, Ltag>::f), z, z, z);
+ CYBOZU_BENCH("l:sqrPre ", (SqrPreCore<N, Ltag>::f), z, z);
+ CYBOZU_BENCH("l:mulKara", (MulPre<N, Ltag>::karatsuba), z, z, z);
+ CYBOZU_BENCH("l:sqrKara", (SqrPre<N, Ltag>::karatsuba), z, z);
+#endif
+}
+
+CYBOZU_TEST_AUTO(karatsuba)
+{
+ benchKaratsuba<4>();
+ benchKaratsuba<6>();
+ benchKaratsuba<8>();
+#if MCL_MAX_BIT_SIZE >= 640
+ benchKaratsuba<10>();
+#endif
+#if MCL_MAX_BIT_SIZE >= 768
+ benchKaratsuba<12>();
+#endif
+#if MCL_MAX_BIT_SIZE >= 896
+ benchKaratsuba<14>();
+#endif
+#if MCL_MAX_BIT_SIZE >= 1024
+ benchKaratsuba<16>();
+#endif
+}
+
diff --git a/vendor/github.com/dexon-foundation/mcl/misc/mul.cpp b/vendor/github.com/dexon-foundation/mcl/misc/mul.cpp
new file mode 100644
index 000000000..146ac33a9
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/misc/mul.cpp
@@ -0,0 +1,58 @@
+/*
+ sudo cpufreq-set -c 0 -g performance
+ mycl mul.cpp -DMCL_USE_LLVM=1 ../lib/libmcl.a && ./a.out
+*/
+#include <stdio.h>
+#include <mcl/fp.hpp>
+#include <cybozu/xorshift.hpp>
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+
+typedef mcl::FpT<> Fp;
+
+using namespace mcl::fp;
+
+void dump(const Unit *x, size_t N)
+{
+ for (size_t i = 0; i < N; i++) {
+ printf("%016llx ", (long long)x[N - 1 - i]);
+ }
+ printf("\n");
+}
+
+CYBOZU_TEST_AUTO(mulPre)
+{
+ cybozu::XorShift rg;
+ const char *pTbl[] = {
+ "0x2523648240000001ba344d80000000086121000000000013a700000000000013",
+ "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff",
+ "6701817056313037086248947066310538444882082605308124576230408038843357549886356779857393369967010764802541005796711440355753503701056323603", // 462 bit
+ "4562440617622195218641171605700291324893228507248559930579192517899275167208677386505912811317371399778642309573594407310688704721375437998252661319722214188251994674360264950082874192246603471", // 640 bit
+ "1552518092300708935148979488462502555256886017116696611139052038026050952686376886330878408828646477950487730697131073206171580044114814391444287275041181139204454976020849905550265285631598444825262999193716468750892846853816057031", // 768 bit
+ };
+ const size_t N = 16;
+ const Mode modeTbl[] = {
+ FP_GMP_MONT,
+#ifdef MCL_USE_LLVM
+ FP_LLVM_MONT,
+#endif
+ };
+ for (size_t j = 0; j < CYBOZU_NUM_OF_ARRAY(modeTbl); j++) {
+ Mode mode = modeTbl[j];
+ printf("%s\n", ModeToStr(mode));
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(pTbl); i++) {
+ const char *p = pTbl[i];
+ Fp::init(p, mode);
+ printf("bitSize=%d\n", (int)Fp::getBitSize());
+ const Op& op = Fp::getOp();
+ Unit x[N], y[N * 2];
+ rg.read(x, N);
+ rg.read(y, N * 2);
+ CYBOZU_BENCH("mul ", op.fp_mul, y, y, x, op.p);
+ CYBOZU_BENCH("sqr ", op.fp_sqr, y, y, op.p);
+ CYBOZU_BENCH("mulPre", op.fpDbl_mulPre, y, y, y);
+ CYBOZU_BENCH("sqrPre", op.fpDbl_sqrPre, y, y);
+ CYBOZU_BENCH("mod ", op.fpDbl_mod, y, y, op.p);
+ }
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/misc/precompute.cpp b/vendor/github.com/dexon-foundation/mcl/misc/precompute.cpp
new file mode 100644
index 000000000..63cdd663b
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/misc/precompute.cpp
@@ -0,0 +1,30 @@
+#include <mcl/bn256.hpp>
+#include <iostream>
+
+using namespace mcl::bn;
+
+int main()
+{
+ initPairing(mcl::BN254);
+ G2 Q;
+ mapToG2(Q, 1);
+ std::vector<Fp6> Qcoeff;
+ precomputeG2(Qcoeff, Q);
+ puts("#if MCL_SIZEOF_UNIT == 8");
+ puts("static const uint64_t QcoeffTblBN254[][6][4] = {");
+ for (size_t i = 0; i < Qcoeff.size(); i++) {
+ const Fp6& x6 = Qcoeff[i];
+ puts("\t{");
+ for (size_t j = 0; j < 6; j++) {
+ printf("\t\t{");
+ const Fp& x = x6.getFp0()[j];
+ for (size_t k = 0; k < 4; k++) {
+ printf("0x%016llxull,", (unsigned long long)x.getUnit()[k]);
+ }
+ puts("},");
+ }
+ puts("\t},");
+ }
+ puts("};");
+ puts("#endif");
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/misc/she/bench.sh b/vendor/github.com/dexon-foundation/mcl/misc/she/bench.sh
new file mode 100644
index 000000000..ced87b4db
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/misc/she/bench.sh
@@ -0,0 +1,6 @@
+for i in 4 6 8
+do echo $i
+touch test/she_test.cpp
+make bin/she_test.exe CFLAGS_USER=-DMCLBN_FP_UNIT_SIZE=$i
+bin/she_test.exe > misc/she/bench$i.txt
+done
diff --git a/vendor/github.com/dexon-foundation/mcl/misc/she/bench4.txt b/vendor/github.com/dexon-foundation/mcl/misc/she/bench4.txt
new file mode 100644
index 000000000..99b2593c4
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/misc/she/bench4.txt
@@ -0,0 +1,99 @@
+ctest:module=log
+CurveFp254BNb
+ctest:module=HashTable
+ctest:module=GTHashTable
+ctest:module=enc_dec
+ctest:module=add_sub_mul
+ctest:module=add_mul_add_sub
+ctest:module=innerProduct
+ctest:module=io
+ctest:module=bench
+enc 673.772Kclk
+add 8.021Kclk
+mul 4.042Mclk
+dec 2.194Mclk
+add after mul 20.693Kclk
+ctest:module=saveHash
+ctest:module=hashBench
+Kclk
+m=000fffff decG1 1.83e+02
+m=001fffff decG1 1.83e+02
+m=003fffff decG1 1.83e+02
+m=007fffff decG1 1.90e+02
+m=00ffffff decG1 2.04e+02
+m=01ffffff decG1 2.66e+02
+m=03ffffff decG1 4.17e+02
+m=07ffffff decG1 7.15e+02
+m=0fffffff decG1 1.29e+03
+m=1fffffff decG1 2.43e+03
+m=3fffffff decG1 4.70e+03
+m=7fffffff decG1 9.28e+03
+
+m=000fffff decG2 4.09e+02
+m=001fffff decG2 4.11e+02
+m=003fffff decG2 4.09e+02
+m=007fffff decG2 4.23e+02
+m=00ffffff decG2 4.48e+02
+m=01ffffff decG2 5.21e+02
+m=03ffffff decG2 7.25e+02
+m=07ffffff decG2 1.11e+03
+m=0fffffff decG2 1.87e+03
+m=1fffffff decG2 3.36e+03
+m=3fffffff decG2 6.38e+03
+m=7fffffff decG2 1.24e+04
+
+m=000fffff decGT 2.20e+03
+m=001fffff decGT 2.21e+03
+m=003fffff decGT 2.20e+03
+m=007fffff decGT 2.21e+03
+m=00ffffff decGT 2.23e+03
+m=01ffffff decGT 2.28e+03
+m=03ffffff decGT 2.37e+03
+m=07ffffff decGT 2.56e+03
+m=0fffffff decGT 2.94e+03
+m=1fffffff decGT 3.78e+03
+m=3fffffff decGT 5.41e+03
+m=7fffffff decGT 8.69e+03
+large m
+G1::add 7.36e-01
+G1::mul 1.92e+02
+G2::add 3.51e+00
+G2::mul 4.03e+02
+GT::mul 5.47e+00
+GT::pow 7.27e+02
+G1window 1.92e+01
+G2window 6.15e+01
+GTwindow 1.35e+02
+miller 6.69e+02
+finalExp 4.23e+02
+precomML 5.16e+02
+small m = 2097151
+G1::mul 4.52e+01
+G2::mul 1.01e+02
+GT::pow 1.33e+02
+G1window 1.55e+00
+G2window 5.02e+00
+GTwindow 1.55e+01
+encG1 2.10e+02
+encG2 4.82e+02
+encGT 2.47e+03
+encG1pre 5.31e+01
+encG2pre 1.47e+02
+encGTpre 6.01e+02
+decG1 1.84e+02
+decG2 3.96e+02
+degGT 2.20e+03
+mul 4.07e+03
+addG1 1.56e+00
+addG2 4.72e+00
+addGT 2.12e+01
+reRandG1 2.10e+02
+reRandG2 4.71e+02
+reRandGT 2.49e+03
+reRandG1pre 5.16e+01
+reRandG2pre 1.44e+02
+reRandGTpre 6.10e+02
+mulG1 9.03e+01
+mulG2 2.03e+02
+mulGT 5.34e+02
+ctest:name=she_test, module=11, total=2879, ok=2879, ng=0, exception=0
diff --git a/vendor/github.com/dexon-foundation/mcl/misc/she/bench6.txt b/vendor/github.com/dexon-foundation/mcl/misc/she/bench6.txt
new file mode 100644
index 000000000..863f7129a
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/misc/she/bench6.txt
@@ -0,0 +1,99 @@
+ctest:module=log
+CurveFp382_1
+ctest:module=HashTable
+ctest:module=GTHashTable
+ctest:module=enc_dec
+ctest:module=add_sub_mul
+ctest:module=add_mul_add_sub
+ctest:module=innerProduct
+ctest:module=io
+ctest:module=bench
+enc 2.077Mclk
+add 17.694Kclk
+mul 13.408Mclk
+dec 5.854Mclk
+add after mul 41.570Kclk
+ctest:module=saveHash
+ctest:module=hashBench
+Kclk
+m=000fffff decG1 5.34e+02
+m=001fffff decG1 5.36e+02
+m=003fffff decG1 5.34e+02
+m=007fffff decG1 5.48e+02
+m=00ffffff decG1 5.87e+02
+m=01ffffff decG1 7.11e+02
+m=03ffffff decG1 9.53e+02
+m=07ffffff decG1 1.41e+03
+m=0fffffff decG1 2.30e+03
+m=1fffffff decG1 4.11e+03
+m=3fffffff decG1 7.71e+03
+m=7fffffff decG1 1.50e+04
+
+m=000fffff decG2 1.27e+03
+m=001fffff decG2 1.27e+03
+m=003fffff decG2 1.27e+03
+m=007fffff decG2 1.30e+03
+m=00ffffff decG2 1.35e+03
+m=01ffffff decG2 1.53e+03
+m=03ffffff decG2 1.88e+03
+m=07ffffff decG2 2.55e+03
+m=0fffffff decG2 3.87e+03
+m=1fffffff decG2 6.53e+03
+m=3fffffff decG2 1.18e+04
+m=7fffffff decG2 2.25e+04
+
+m=000fffff decGT 6.01e+03
+m=001fffff decGT 6.03e+03
+m=003fffff decGT 6.01e+03
+m=007fffff decGT 6.04e+03
+m=00ffffff decGT 6.08e+03
+m=01ffffff decGT 6.17e+03
+m=03ffffff decGT 6.39e+03
+m=07ffffff decGT 6.71e+03
+m=0fffffff decGT 7.44e+03
+m=1fffffff decGT 8.95e+03
+m=3fffffff decGT 1.20e+04
+m=7fffffff decGT 1.80e+04
+large m
+G1::add 1.48e+00
+G1::mul 5.44e+02
+G2::add 6.91e+00
+G2::mul 1.28e+03
+GT::mul 1.04e+01
+GT::pow 2.04e+03
+G1window 5.57e+01
+G2window 2.04e+02
+GTwindow 4.03e+02
+miller 2.09e+03
+finalExp 1.50e+03
+precomML 1.63e+03
+small m = 2097151
+G1::mul 8.29e+01
+G2::mul 2.05e+02
+GT::pow 2.66e+02
+G1window 3.18e+00
+G2window 1.14e+01
+GTwindow 3.19e+01
+encG1 6.01e+02
+encG2 1.49e+03
+encGT 7.66e+03
+encG1pre 1.41e+02
+encG2pre 4.71e+02
+encGTpre 1.76e+03
+decG1 5.37e+02
+decG2 1.27e+03
+degGT 6.02e+03
+mul 1.34e+04
+addG1 3.07e+00
+addG2 1.02e+01
+addGT 4.18e+01
+reRandG1 5.99e+02
+reRandG2 1.49e+03
+reRandGT 7.69e+03
+reRandG1pre 1.40e+02
+reRandG2pre 4.68e+02
+reRandGTpre 1.75e+03
+mulG1 1.65e+02
+mulG2 4.14e+02
+mulGT 1.06e+03
+ctest:name=she_test, module=11, total=2879, ok=2879, ng=0, exception=0
diff --git a/vendor/github.com/dexon-foundation/mcl/misc/she/bench8.txt b/vendor/github.com/dexon-foundation/mcl/misc/she/bench8.txt
new file mode 100644
index 000000000..f8fe8fd75
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/misc/she/bench8.txt
@@ -0,0 +1,99 @@
+ctest:module=log
+CurveFp462
+ctest:module=HashTable
+ctest:module=GTHashTable
+ctest:module=enc_dec
+ctest:module=add_sub_mul
+ctest:module=add_mul_add_sub
+ctest:module=innerProduct
+ctest:module=io
+ctest:module=bench
+enc 5.095Mclk
+add 36.280Kclk
+mul 30.163Mclk
+dec 12.974Mclk
+add after mul 76.646Kclk
+ctest:module=saveHash
+ctest:module=hashBench
+Kclk
+m=000fffff decG1 1.44e+03
+m=001fffff decG1 1.45e+03
+m=003fffff decG1 1.45e+03
+m=007fffff decG1 1.47e+03
+m=00ffffff decG1 1.54e+03
+m=01ffffff decG1 1.70e+03
+m=03ffffff decG1 2.03e+03
+m=07ffffff decG1 2.64e+03
+m=0fffffff decG1 3.88e+03
+m=1fffffff decG1 6.32e+03
+m=3fffffff decG1 1.12e+04
+m=7fffffff decG1 2.11e+04
+
+m=000fffff decG2 2.99e+03
+m=001fffff decG2 3.01e+03
+m=003fffff decG2 2.99e+03
+m=007fffff decG2 3.05e+03
+m=00ffffff decG2 3.15e+03
+m=01ffffff decG2 3.41e+03
+m=03ffffff decG2 3.93e+03
+m=07ffffff decG2 4.95e+03
+m=0fffffff decG2 6.97e+03
+m=1fffffff decG2 1.10e+04
+m=3fffffff decG2 1.91e+04
+m=7fffffff decG2 3.54e+04
+
+m=000fffff decGT 1.31e+04
+m=001fffff decGT 1.31e+04
+m=003fffff decGT 1.31e+04
+m=007fffff decGT 1.31e+04
+m=00ffffff decGT 1.32e+04
+m=01ffffff decGT 1.33e+04
+m=03ffffff decGT 1.36e+04
+m=07ffffff decGT 1.43e+04
+m=0fffffff decGT 1.56e+04
+m=1fffffff decGT 1.82e+04
+m=3fffffff decGT 2.34e+04
+m=7fffffff decGT 3.39e+04
+large m
+G1::add 3.40e+00
+G1::mul 1.41e+03
+G2::add 1.38e+01
+G2::mul 2.93e+03
+GT::mul 1.94e+01
+GT::pow 4.30e+03
+G1window 1.59e+02
+G2window 4.89e+02
+GTwindow 8.96e+02
+miller 4.99e+03
+finalExp 3.26e+03
+precomML 3.71e+03
+small m = 2097151
+G1::mul 1.53e+02
+G2::mul 3.85e+02
+GT::pow 4.88e+02
+G1window 6.96e+00
+G2window 2.17e+01
+GTwindow 5.83e+01
+encG1 1.62e+03
+encG2 3.48e+03
+encGT 1.79e+04
+encG1pre 3.67e+02
+encG2pre 1.09e+03
+encGTpre 3.88e+03
+decG1 1.45e+03
+decG2 3.02e+03
+degGT 1.31e+04
+mul 3.02e+04
+addG1 7.08e+00
+addG2 2.03e+01
+addGT 7.68e+01
+reRandG1 1.63e+03
+reRandG2 3.48e+03
+reRandGT 1.79e+04
+reRandG1pre 3.65e+02
+reRandG2pre 1.08e+03
+reRandGTpre 3.79e+03
+mulG1 3.08e+02
+mulG2 7.65e+02
+mulGT 1.95e+03
+ctest:name=she_test, module=11, total=2879, ok=2879, ng=0, exception=0
diff --git a/vendor/github.com/dexon-foundation/mcl/misc/she/nizkp.pdf b/vendor/github.com/dexon-foundation/mcl/misc/she/nizkp.pdf
new file mode 100644
index 000000000..7e61b5a64
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/misc/she/nizkp.pdf
Binary files differ
diff --git a/vendor/github.com/dexon-foundation/mcl/misc/she/she-api-ja.md b/vendor/github.com/dexon-foundation/mcl/misc/she/she-api-ja.md
new file mode 100644
index 000000000..850f11ff3
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/misc/she/she-api-ja.md
@@ -0,0 +1,314 @@
+# L2準åŒåž‹æš—å·ãƒ©ã‚¤ãƒ–ラリshe
+
+# 概è¦
+she(somewhat homomorphic encryption)ã¯ãƒšã‚¢ãƒªãƒ³ã‚°ãƒ™ãƒ¼ã‚¹ã®L2準åŒåž‹æš—å·ã¨å‘¼ã°ã‚Œã‚‹å…¬é–‹éµæš—å·ãƒ©ã‚¤ãƒ–ラリã§ã‚る。
+L2準åŒåž‹æš—å·ã¨ã¯æš—å·æ–‡åŒå£«ã®åŠ ç®—を複数回ã€ä¹—算を一度ã ã‘ã§ãる性質を表ã™ã€‚
+
+特ã«2個ã®æ•´æ•°å€¤ãƒ™ã‚¯ãƒˆãƒ«x = (x_i), y = (y_i)ã®å„è¦ç´ ãŒæš—å·åŒ–ã•ã‚ŒãŸçŠ¶æ…‹ã§ã€ãã®2個ã®ãƒ™ã‚¯ãƒˆãƒ«ã®å†…ç©ã‚’æš—å·åŒ–ã—ãŸã¾ã¾è¨ˆç®—ã§ãる。
+
+ΣEnc(x_i) Enc(y_i) = Enc(Σx_i y_i).
+
+# 特長
+* ペアリングベースã®æœ€æ–°ã‚¢ãƒ«ã‚´ãƒªã‚ºãƒ ã‚’実装
+ * [Efficient Two-level Homomorphic Encryption in Prime-order Bilinear Groups and A Fast Implementation in WebAssembly : ASIA CCS2018](http://asiaccs2018.org/?page_id=632)
+* C++版ã¯Windows(x64), Linux(x64, ARM64), OSX(x64)ã«å¯¾å¿œ
+* JavaScript(WebAssembly 以é™JSã¨è¨˜ã™)版ã¯Chrome, Firefox, Edge, Safari(Android, iPhoneå«ã‚€), Node.jsã«å¯¾å¿œ
+
+# クラスã¨ä¸»ãªæ©Ÿèƒ½
+
+## 主ãªã‚¯ãƒ©ã‚¹
+* 秘密éµã‚¯ãƒ©ã‚¹ SecretKey
+* 公開éµã‚¯ãƒ©ã‚¹ PublicKey
+* æš—å·æ–‡ã‚¯ãƒ©ã‚¹ CipherTextG1, CipherTextG2, CipherTextGT
+* ゼロ知識証明クラス ZkpBin, ZkpEq, ZkpBinEq
+
+## æš—å·åŒ–ã¨å¾©å·æ–¹æ³•
+* 秘密éµã‹ã‚‰å…¬é–‹éµã‚’作æˆã™ã‚‹
+* 公開éµã‚’用ã„ã¦æ•´æ•°ã‹ã‚‰æš—å·æ–‡ã‚’作る
+* 秘密éµã‚’用ã„ã¦æš—å·æ–‡ã‚’復å·ã™ã‚‹
+
+## æš—å·æ–‡åŒå£«ã®è¨ˆç®—
+* åŒã˜æš—å·æ–‡ã‚¯ãƒ©ã‚¹åŒå£«ã¯åŠ ç®—・減算ã§ãã‚‹
+* CipherTextG1ã¨CipherTextG2ã‚’ä¹—ç®—ã™ã‚‹ã¨CipherTextGTã«ãªã‚‹
+
+## 復å·ã®é‡è¦ãªæ³¨æ„点
+* ã“ã®sheã¯å¾©å·æ™‚ã«å°ã•ãªé›¢æ•£å¯¾æ•°å•é¡Œ(DLP)を解ãå¿…è¦ãŒã‚ã‚‹
+* DLPã®ãƒ†ãƒ¼ãƒ–ルサイズをsã€æš—å·æ–‡ã‚’Enc(m)ã¨ã™ã‚‹ã¨å¾©å·æ™‚é–“ã¯m/sã«æ¯”例ã™ã‚‹
+* テーブルサイズã®è¨­å®šã¯`setRangeForDLP(s)`を使ã†
+ * `m/s`ã®æœ€å¤§å€¤ã¯`setTryNum(tryNum)`ã§è¡Œã†
+
+## ゼロ知識証明クラス
+* mã‚’æš—å·ã™ã‚‹ã¨ãã«åŒæ™‚ã«ã‚¼ãƒ­çŸ¥è­˜è¨¼æ˜Žã‚’生æˆã™ã‚‹
+* æš—å·æ–‡ã¨ç”Ÿæˆã•ã‚ŒãŸã‚¼ãƒ­çŸ¥è­˜è¨¼æ˜Žã¨å…¬é–‹éµã§mã«é–¢ã™ã‚‹åˆ¶ç´„æ¡ä»¶ã‚’検証ã§ãã‚‹
+
+# JS版
+
+## Node.jsã§ã®èª­ã¿è¾¼ã¿
+
+```
+>npm install she-wasm
+>node
+>const she = require('she-wasm')
+```
+
+## ブラウザã§ã®èª­ã¿è¾¼ã¿
+[she-wasm](https://github.com/herumi/she-wasm/)ã®she.js, she\_c.js, she\_c.wasmファイルをåŒã˜ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ç½®ã„ã¦she.jsを読ã¿è¾¼ã‚€
+```
+// HTML
+<script src="she.js"></script>
+```
+
+## JS版サンプル
+
+```
+// システムã®åˆæœŸåŒ–
+she.init().then(() => {
+ const sec = new she.SecretKey()
+ // 秘密éµã®åˆæœŸåŒ–
+ sec.setByCSPRNG()
+
+ // 秘密éµsecã‹ã‚‰å…¬é–‹éµpubを作æˆ
+ const pub = sec.getPublicKey()
+
+ const m1 = 1
+ const m2 = 2
+ const m3 = 3
+ const m4 = -1
+
+ // 平文m1ã¨m2ã‚’CipherTextG1ã¨ã—ã¦æš—å·åŒ–
+ const c11 = pub.encG1(m1)
+ const c12 = pub.encG1(m2)
+
+ // 平文m3ã¨m4ã‚’CipherTextG2ã¨ã—ã¦æš—å·åŒ–
+ const c21 = pub.encG2(m3)
+ const c22 = pub.encG2(m4)
+
+ // c11ã¨c12, c21ã¨c22ã‚’ãã‚Œãžã‚ŒåŠ ç®—
+ const c1 = she.add(c11, c12)
+ const c2 = she.add(c21, c22)
+
+ // c1ã¨c2ã‚’ä¹—ç®—ã™ã‚‹ã¨CipherTextGTåž‹ã«ãªã‚‹
+ const ct = she.mul(c1, c2)
+
+ // æš—å·æ–‡ctを復å·ã™ã‚‹
+ console.log(`(${m1} + ${m2}) * (${m3} + ${m4}) = ${sec.dec(ct)}`)
+})
+```
+
+# C++版サンプル
+ライブラリã®ãƒ“ルドã¯[mcl](https://github.com/herumi/mcl/#installation-requirements)ã‚’å‚ç…§
+```
+#include <mcl/she.hpp>
+int main()
+ try
+{
+ using namespace mcl::she;
+ // システã®ãƒ åˆæœŸåŒ–
+ init();
+
+ SecretKey sec;
+
+ // 秘密éµã®åˆæœŸåŒ–
+ sec.setByCSPRNG();
+
+ // 秘密éµsecã‹ã‚‰å…¬é–‹éµpubを作æˆ
+ PublicKey pub;
+ sec.getPublicKey(pub);
+
+ int m1 = 1;
+ int m2 = 2;
+ int m3 = 3;
+ int m4 = -1;
+
+ // 平文m1ã¨m2ã‚’CipherTextG1ã¨ã—ã¦æš—å·åŒ–
+ CipherTextG1 c11, c12;
+ pub.enc(c11, m1);
+ pub.enc(c12, m2);
+
+ // 平文m3ã¨m4ã‚’CipherTextG2ã¨ã—ã¦æš—å·åŒ–
+ CipherTextG2 c21, c22;
+ pub.enc(c21, m3);
+ pub.enc(c22, m4);
+
+ // c11ã¨c12, c21ã¨c22ã‚’ãã‚Œãžã‚ŒåŠ ç®—
+ CipherTextG1 c1;
+ CipherTextG2 c2;
+ CipherTextG1::add(c1, c11, c12);
+ CipherTextG2::add(c2, c21, c22);
+
+ // c1ã¨c2ã‚’ä¹—ç®—ã™ã‚‹ã¨CipherTextGTåž‹ã«ãªã‚‹
+ CipherTextGT ct;
+ CipherTextGT::mul(ct, c1, c2);
+
+ // æš—å·æ–‡ctを復å·ã™ã‚‹
+ printf("(%d + %d) * (%d + %d) = %d\n", m1, m2, m3, m4, (int)sec.dec(ct));
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+ return 1;
+}
+
+```
+
+# クラス共通メソッド
+
+## シリアライズ(C++)
+
+* `setStr(const std::string& str, int ioMode = 0)`
+ * ioModeã«å¾“ã£ã¦strã§è¨­å®šã™ã‚‹
+
+* `getStr(std::string& str, int ioMode = 0) const`
+* `std::string getStr(int ioMode = 0) const`
+ * ioModeã«å¾“ã£ã¦strã‚’å–å¾—ã™ã‚‹
+* `size_t serialize(void *buf, size_t maxBufSize) const`
+ * maxBufSize確ä¿ã•ã‚ŒãŸbufã«ã‚·ãƒªã‚¢ãƒ©ã‚¤ã‚ºã™ã‚‹
+ * bufã«æ›¸ãè¾¼ã¾ã‚ŒãŸbyteé•·ãŒè¿”ã‚‹
+ * エラーã®å ´åˆã¯0ãŒè¿”ã‚‹
+* `size_t deserialize(const void *buf, size_t bufSize)`
+ * bufã‹ã‚‰æœ€å¤§bufSizeã¾ã§å€¤ã‚’読ã¿è¾¼ã¿ãƒ‡ãƒªã‚·ã‚¢ãƒ©ã‚¤ã‚ºã™ã‚‹
+ * 読ã¿è¾¼ã¾ã‚ŒãŸbyteé•·ãŒè¿”ã‚‹
+ * エラーã®å ´åˆã¯0ãŒè¿”ã‚‹
+
+## シリアライズ(JS)
+
+* `deserialize(s)`
+ * Uint8Arrayåž‹sã§ãƒ‡ã‚·ãƒªã‚¢ãƒ©ã‚¤ã‚º
+* `serialize()`
+ * シリアライズã—ã¦Uint8Arrayã®å€¤ã‚’è¿”ã™
+* `deserializeHexStr(s)`
+ * 16進数文字列sã§ãƒ‡ã‚·ãƒªã‚¢ãƒ©ã‚¤ã‚º
+* `serializeToHexStr()`
+ * 16進数文字列sã§ã‚·ãƒªã‚¢ãƒ©ã‚¤ã‚º
+
+## ioMode
+
+* 2 ; 2進数
+* 10 ; 10進数
+* 16 ; 16進数
+* IoPrefix ; 2ã¾ãŸã¯16ã¨orã®å€¤ã‚’設定ã™ã‚‹ã¨0bã¾ãŸã¯0xãŒã¤ã
+* IoEcAffine ; (G1, G2ã®ã¿)アフィン座標
+* IoEcProj ; (G1, G2ã®ã¿)射影座標
+* IoSerialize ; serialize()/deserialize()ã¨åŒã˜
+
+## 注æ„
+* C++ã®åå‰ç©ºé–“ã¯`mcl::she`
+* 以下CTã¯CipherTextG1, CipherTextG2, CipherTextGTã®ã„ãšã‚Œã‹ã‚’表ã™
+* JS版ã®å¹³æ–‡ã¯32ビット整数ã®ç¯„囲ã«åˆ¶é™ã•ã‚Œã‚‹
+
+## SecretKeyクラス
+
+* `void setByCSPRNG()`(C++)
+* `void setByCSPRNG()`(JS)
+ * 疑似乱数ã§ç§˜å¯†éµã‚’åˆæœŸåŒ–ã™ã‚‹
+
+* `int64_t dec(const CT& c) const`(C++)
+* `int dec(CT c)`(JS)
+ * æš—å·æ–‡cを復å·ã™ã‚‹
+* `int64_t decViaGT(const CipherTextG1& c) const`(C++)
+* `int64_t decViaGT(const CipherTextG2& c) const`(C++)
+* `int decViaGT(CT c)`(JS)
+ * æš—å·æ–‡ã‚’GT経由ã§å¾©å·ã™ã‚‹
+* `bool isZero(const CT& c) const`(C++)
+* `bool isZero(CT c)`(JS)
+ * cã®å¾©å·çµæžœãŒ0ãªã‚‰ã°true
+ * decã—ã¦ã‹ã‚‰0ã¨æ¯”較ã™ã‚‹ã‚ˆã‚Šã‚‚高速
+
+## PublicKey, PrecomputedPublicKeyクラス
+PrecomputedPublicKeyã¯PublicKeyã®é«˜é€Ÿç‰ˆ
+
+* `void PrecomputedPublicKey::init(const PublicKey& pub)`(C++)
+* `void PrecomputedPublicKey::init(pub)`(JS)
+ * 公開éµpubã§PrecomputedPublicKeyã‚’åˆæœŸåŒ–ã™ã‚‹
+
+
+* `PrecomputedPublicKey::destroy()`(JS)
+ * JavaScriptã§ã¯PrecomputedPublicKeyãŒä¸è¦ã«ãªã£ãŸã‚‰ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ã‚’呼ã¶å¿…è¦ãŒã‚ã‚‹
+ * ãã†ã—ãªã„ã¨ãƒ¡ãƒ¢ãƒªãƒªãƒ¼ã‚¯ã™ã‚‹
+
+以下ã¯PK = PublicKey or PrecomputedPublicKey
+
+* `void PK::enc(CT& c, int64_t m) const`(C++)
+* `CipherTextG1 PK::encG1(m)`(JS)
+* `CipherTextG2 PK::encG2(m)`(JS)
+* `CipherTextGT PK::encGT(m)`(JS)
+ * mã‚’æš—å·åŒ–ã—ã¦cã«ã‚»ãƒƒãƒˆã™ã‚‹(ã¾ãŸã¯ãã®å€¤ã‚’è¿”ã™)
+
+* `void PK::reRand(CT& c) const`(C++)
+* `CT PK::reRand(CT c)`(JS)
+ * cã‚’å†ãƒ©ãƒ³ãƒ€ãƒ åŒ–ã™ã‚‹
+ * å†ãƒ©ãƒ³ãƒ€ãƒ åŒ–ã•ã‚ŒãŸæš—å·æ–‡ã¨å…ƒã®æš—å·æ–‡ã¯åŒã˜å¹³æ–‡ã‚’æš—å·åŒ–ã—ãŸã‚‚ã®ã‹ã©ã†ã‹åˆ¤å®šã§ããªã„
+
+* `void convert(CipherTextGT& cm, const CT& ca) const`
+* `CipherTextGT convert(CT ca)`
+ * æš—å·æ–‡ca(CipherTextG1ã‹CipherTextG2)ã‚’CipherTextGTã«å¤‰æ›ã™ã‚‹
+
+## CipherTextクラス
+
+* `void CT::add(CT& z, const CT& x const CT& y)`(C++)
+* `CT she.add(CT x, CT y)`(JS)
+ * æš—å·æ–‡xã¨æš—å·æ–‡yを足ã—ã¦zã«ã‚»ãƒƒãƒˆã™ã‚‹(ã¾ãŸã¯ãã®å€¤ã‚’è¿”ã™)
+* `void CT::sub(CT& z, const CT& x const CT& y)`(C++)
+* `CT she.sub(CT x, CT y)`(JS)
+ * æš—å·æ–‡xã‹ã‚‰æš—å·æ–‡yを引ã„ã¦zã«ã‚»ãƒƒãƒˆã™ã‚‹(ã¾ãŸã¯ãã®å€¤ã‚’è¿”ã™)
+* `void CT::neg(CT& y, const CT& x)`(C++)
+* `void she.neg(CT x)`(JS)
+ * æš—å·æ–‡xã®ç¬¦å·å転をyã«ã‚»ãƒƒãƒˆã™ã‚‹(ã¾ãŸã¯ãã®å€¤ã‚’è¿”ã™)
+* `void CT::mul(CT& z, const CT& x, int y)`(C++)
+* `CT she.mulInt(CT x, int y)`(JS)
+ * æš—å·æ–‡xã‚’æ•´æ•°å€yã—ã¦zã«ã‚»ãƒƒãƒˆã™ã‚‹(ã¾ãŸã¯ãã®å€¤ã‚’è¿”ã™)
+
+* `void CipherTextGT::mul(CipherTextGT& z, const CipherTextG1& x, const CipherTextG2& y)`(C++)
+* `CipherTextGT she.mul(CipherTextG1 x, CipherTextG2 y)`(JS)
+ * æš—å·æ–‡xã¨æš—å·æ–‡yを掛ã‘ã¦zã«ã‚»ãƒƒãƒˆã™ã‚‹(ã¾ãŸã¯ãã®å€¤ã‚’è¿”ã™)
+
+* `void CipherTextGT::mulML(CipherTextGT& z, const CipherTextG1& x, const CipherTextG2& y)`(C++)
+ * æš—å·æ–‡xã¨æš—å·æ–‡yを掛ã‘ã¦(Millerループã ã‘ã—ã¦)zã«ã‚»ãƒƒãƒˆã™ã‚‹(ã¾ãŸã¯ãã®å€¤ã‚’è¿”ã™)
+* `CipherTextGT::finalExp(CipherText& , const CipherTextG1& x, const CipherTextG2& y)`(C++)
+ * mul(a, b) = finalExp(mulML(a, b))
+ * add(mul(a, b), mul(c, d)) = finalExp(add(mulML(a, b), mulML(c, d)))
+ * ã™ãªã‚ã¡ç©å’Œæ¼”ç®—ã¯mulMLã—ãŸã‚‚ã®ã‚’足ã—ã¦ã‹ã‚‰æœ€å¾Œã«ä¸€åº¦finalExpã™ã‚‹ã®ãŒã‚ˆã„
+
+## ゼロ知識証明クラス
+
+### 概è¦
+* ZkpBin æš—å·æ–‡encGi(m)(i = 1, 2, T)ã«ã¤ã„ã¦m = 0ã¾ãŸã¯1ã§ã‚ã‚‹ã“ã¨ã‚’復å·ã›ãšã«æ¤œè¨¼ã§ãã‚‹
+* ZkpEq æš—å·æ–‡encG1(m1), encG2(m2)ã«ã¤ã„ã¦m1 = m2ã§ã‚ã‚‹ã“ã¨ã‚’検証ã§ãã‚‹
+* ZkpBinEq æš—å·æ–‡encG1(m1), encG2(m2)ã«ã¤ã„ã¦m1 = m2 = 0ã¾ãŸã¯1ã§ã‚ã‚‹ã“ã¨ã‚’検証ã§ãã‚‹
+
+### API
+PK = PublicKey or PrecomputedPublicKey
+
+* `void PK::encWithZkpBin(CipherTextG1& c, Zkp& zkp, int m) const`(C++)
+* `void PK::encWithZkpBin(CipherTextG2& c, Zkp& zkp, int m) const`(C++)
+* `[CipherTextG1, ZkpBin] PK::encWithZkpBinG1(m)`(JS)
+* `[CipherTextG2, ZkpBin] PK::encWithZkpBinG2(m)`(JS)
+ * m(=0 or 1)ã‚’æš—å·åŒ–ã—ã¦æš—å·æ–‡cã¨ã‚¼ãƒ­çŸ¥è­˜è¨¼æ˜Žzkpをセットã™ã‚‹(ã¾ãŸã¯[c, zkp]ã‚’è¿”ã™)
+ * mãŒ0ã§ã‚‚1ã§ã‚‚ãªã‘ã‚Œã°ä¾‹å¤–
+* `void PK::encWithZkpEq(CipherTextG1& c1, CipherTextG2& c2, ZkpEq& zkp, const INT& m) const`(C++)
+* `[CipherTextG1, CipherTextG2, ZkpEq] PK::encWithZkpEq(m)`(JS)
+ * mã‚’æš—å·åŒ–ã—ã¦æš—å·æ–‡c1, c2ã¨ã‚¼ãƒ­çŸ¥è­˜è¨¼æ˜Žzkpをセットã™ã‚‹(ã¾ãŸã¯[c1, c2, zkp]ã‚’è¿”ã™)
+* `void PK::encWithZkpBinEq(CipherTextG1& c1, CipherTextG2& c2, ZkpBinEq& zkp, int m) const`(C++)
+* `[CipherTextG1, CipherTextG2, ZkpEqBin] PK::encWithZkpBinEq(m)`(JS)
+ * m(=0 or 1)ã‚’æš—å·åŒ–ã—ã¦æš—å·æ–‡c1, c2ã¨ã‚¼ãƒ­çŸ¥è­˜è¨¼æ˜Žzkpをセットã™ã‚‹(ã¾ãŸã¯[c1, c2, zkp]ã‚’è¿”ã™)
+ * mãŒ0ã§ã‚‚1ã§ã‚‚ãªã‘ã‚Œã°ä¾‹å¤–
+
+## グローãƒãƒ«é–¢æ•°
+
+* `void init(const CurveParam& cp, size_t hashSize = 1024, size_t tryNum = 2048)`(C++)
+* `void init(curveType = she.BN254, hashSize = 1024, tryNum = 2048)`(JS)
+ * hashSizeã®å¤§ãã•ã®å¾©å·ç”¨ãƒ†ãƒ¼ãƒ–ルã¨tryNumã‚’å…ƒã«åˆæœŸåŒ–ã™ã‚‹
+ * 復å·å¯èƒ½ãªå¹³æ–‡mã®ç¯„囲ã¯|m| <= hashSize * tryNum
+* `she.loadTableForGTDLP(Uint8Array a)`(JS)
+ * 復å·ç”¨ãƒ†ãƒ¼ãƒ–ルを読ã¿è¾¼ã‚€
+ * ç¾åœ¨ã¯`https://herumi.github.io/she-dlp-table/she-dlp-0-20-gt.bin`ã®ã¿ãŒã‚ã‚‹
+* `void useDecG1ViaGT(bool use)`(C++/JS)
+* `void useDecG2ViaGT(bool use)`(C++/JS)
+ * CipherTextG1, CipherTextG2ã®å¾©å·ã‚’CipherTextGT経由ã§è¡Œã†
+ * 大ããªå€¤ã‚’復å·ã™ã‚‹ã¨ãã¯DLP用ã®å·¨å¤§ãªãƒ†ãƒ¼ãƒ–ルをãã‚Œãžã‚Œã«æŒã¤ã‚ˆã‚Šã‚‚GTã«é›†ç´„ã—ãŸæ–¹ãŒåŠ¹çŽ‡ãŒã‚ˆã„
+
+# ライセンス
+
+ã“ã®ãƒ©ã‚¤ãƒ–ラリã¯[修正BSDライセンス](https://github.com/herumi/mcl/blob/master/COPYRIGHT)ã§æä¾›ã•ã‚Œã¾ã™
+
+# 開発者
+
+å…‰æˆæ»‹ç”Ÿ MITSUNARI Shigeo(herumi@nifty.com)
diff --git a/vendor/github.com/dexon-foundation/mcl/misc/she/she-api.md b/vendor/github.com/dexon-foundation/mcl/misc/she/she-api.md
new file mode 100644
index 000000000..af54311e9
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/misc/she/she-api.md
@@ -0,0 +1,322 @@
+# she ; Two-level homomorphic encryption library for browser/Node.js by WebAssembly
+
+# Abstruct
+she is a somewhat(two-level) homomorphic encryption library,
+which is based on pairings.
+This library supports polynomially many homomorphic additions and
+one multiplication over encrypted data.
+
+Especially, the inner products of two encrypted integer vectors such as Enc(x) = (Enc(x_i)), Enc(y) = (Enc(y_i))
+can be computed.
+
+Sum_i Enc(x_i) Enc(y_i) = Enc(Sum_i x_i y_i).
+
+# Features
+* supports the latest pairing based algorithm
+ * [Efficient Two-level Homomorphic Encryption in Prime-order Bilinear Groups and A Fast Implementation in WebAssembly : ASIA CCS2018](http://asiaccs2018.org/?page_id=632)
+* supports Windows(x64), Linux(x64, ARM64), OSX(x64)
+* supports JavaScript(WebAssembly), Chrome, Firefox, Safari(contains Android, iPhone), Node.js
+
+# Classes
+
+## Main classes
+* secret key class ; SecretKey
+* public key class ; PublicKey
+* ciphertext class ; CipherTextG1, CipherTextG2, CipherTextGT
+* zero-knowledge proof class ; ZkpBin, ZkpEq, ZkpBinEq
+
+## Encryption and decryption
+* create the corresponding public key from a secret key
+* encrypt an integer(plaintext) with a public key
+* decrypt a ciphertext with a secret key
+
+## Homomorphic operations
+* homomorphic addtion/substraction over ciphertexts of the same ciphertext class
+* homomprphic multiplication over ciphertext of CipherTextG1 and CipherTextG2
+ * The class of the result is CipherTextGT.
+
+## Important notation of decryption
+* This library requires to solve a small DLP to decrypt a ciphertext.
+* The decryption timing is O(m/s), where s is the size of table to solve DLP, and m is the size fo a plaintext.
+* call `setRangeForDLP(s)` to set the table size.
+ * The maximun `m/s` is set by `setTryNum(tryNum)`.
+
+## Zero-knowledge proof class
+* A zero-knowledge proof is simultaneously created when encrypting a plaintext `m`.
+* The restriction according to `m` can be verified with a created zero-knowledge proof and a public key.
+
+# Setup for JavaScript(JS)
+
+## for Node.js
+
+```
+>npm install she-wasm
+>node
+>const she = require('she-wasm')
+```
+
+## for a browser
+
+Copy `she.js`, `she\_c.js`, `she\_c.wasm` to your directory from [she-wasm](https://github.com/herumi/she-wasm/),
+and read `she.js`.
+```
+// HTML
+<script src="she.js"></script>
+```
+
+## A sample for JS
+
+```
+// initialize a library
+she.init().then(() => {
+ const sec = new she.SecretKey()
+ // initialize a secret key by CSPRNG(cryptographically secure pseudo random number generator)
+ sec.setByCSPRNG()
+
+ // create a public key from a secret key
+ const pub = sec.getPublicKey()
+
+ const m1 = 1
+ const m2 = 2
+ const m3 = 3
+ const m4 = -1
+
+ // encrypt m1 and m2 as CipherTextG1 class
+ const c11 = pub.encG1(m1)
+ const c12 = pub.encG1(m2)
+
+ // encrypt m3 and m4 as CipherTextG2 class
+ const c21 = pub.encG2(m3)
+ const c22 = pub.encG2(m4)
+
+ // add c11 and c12, c21 and c22 respectively
+ const c1 = she.add(c11, c12)
+ const c2 = she.add(c21, c22)
+
+ // get ct as a CipherTextGT class by multiplying c1 with c2
+ const ct = she.mul(c1, c2)
+
+ // decrypt ct
+ console.log(`(${m1} + ${m2}) * (${m3} + ${m4}) = ${sec.dec(ct)}`)
+})
+```
+
+# A sample for C++
+How to build the library, see [mcl](https://github.com/herumi/mcl/#installation-requirements).
+```
+#include <mcl/she.hpp>
+int main()
+ try
+{
+ using namespace mcl::she;
+ // initialize a library
+ init();
+
+ SecretKey sec;
+
+ // initialize a secret key by CSPRNG
+ sec.setByCSPRNG();
+
+ // create a public key from a secret key
+ PublicKey pub;
+ sec.getPublicKey(pub);
+
+ int m1 = 1;
+ int m2 = 2;
+ int m3 = 3;
+ int m4 = -1;
+
+ // encrypt m1 and m2 as CipherTextG1 class
+ CipherTextG1 c11, c12;
+ pub.enc(c11, m1);
+ pub.enc(c12, m2);
+
+ // encrypt m3 and m4 as CipherTextG2 class
+ CipherTextG2 c21, c22;
+ pub.enc(c21, m3);
+ pub.enc(c22, m4);
+
+ // add c11 and c12, c21 and c22 respectively
+ CipherTextG1 c1;
+ CipherTextG2 c2;
+ CipherTextG1::add(c1, c11, c12);
+ CipherTextG2::add(c2, c21, c22);
+
+ // get ct as a CipherTextGT class by multiplying c1 with c2
+ CipherTextGT ct;
+ CipherTextGT::mul(ct, c1, c2);
+
+ // decrypt ct
+ printf("(%d + %d) * (%d + %d) = %d\n", m1, m2, m3, m4, (int)sec.dec(ct));
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+ return 1;
+}
+
+```
+# Class method
+
+## Serialization(C++)
+
+* `setStr(const std::string& str, int ioMode = 0)`
+ * set a value by `str` according to `ioMode`
+
+* `getStr(std::string& str, int ioMode = 0) const`
+* `std::string getStr(int ioMode = 0) const`
+ * get a string `str` according to `ioMode`
+* `size_t serialize(void *buf, size_t maxBufSize) const`
+ * serialize a value to buf which has maxBufSize byte size
+ * return the byte size to be written in `buf`
+ * return zero if error
+* `size_t deserialize(const void *buf, size_t bufSize)`
+ * deserialize a value from buf which has bufSize byte size
+ * return the byte size to be read from `buf`
+ * return zero if error
+
+## Serialization(JS)
+
+* `deserialize(s)`
+ * deserialize from `s` as Uint8Array type
+* `serialize()`
+ * serialize a value and return Uint8Array value
+* `deserializeHexStr(s)`
+ * deserialize as a hexadecimal string
+* `serializeToHexStr()`
+ * serialize as a hexadecimal string
+
+## ioMode
+
+* 2 ; binary number
+* 10 ; decimal number
+* 16 ; hexadecimal number
+* IoPrefix ; append a prefix 0b(resp. 2) or 0x(resp. 16)
+* IoEcAffine ; affine coordinate (for only G1, G2)
+* IoEcProj ; projective coordinate (for only G1, G2)
+* IoSerialize ; same as serialize()/deserialize()
+
+## Notation
+* the namespace of C++ is `mcl::she`
+* CT means one of CipherTextG1, CipherTextG2, CipherTextGT
+* The range of plaintext is rectricted as a 32-bit integer for JS
+
+## SecretKey class
+
+* `void setByCSPRNG()`(C++)
+* `void setByCSPRNG()`(JS)
+ * set a secret key by CSPRNG(cryptographically secure pseudo random number generator)
+
+* `int64_t dec(const CT& c) const`(C++)
+* `int dec(CT c)`(JS)
+ * decrypt `c`
+* `int64_t decViaGT(const CipherTextG1& c) const`(C++)
+* `int64_t decViaGT(const CipherTextG2& c) const`(C++)
+* `int decViaGT(CT c)`(JS)
+ * decrypt `c` through CipherTextGT
+* `bool isZero(const CT& c) const`(C++)
+* `bool isZero(CT c)`(JS)
+ * return true if decryption of `c` is zero
+ * it is faster than the timing of comparision with zero after decrypting `c`
+
+## PublicKey, PrecomputedPublicKey class
+`PrecomputedPublicKey` is a faster version of `PublicKey`
+
+* `void PrecomputedPublicKey::init(const PublicKey& pub)`(C++)
+* `void PrecomputedPublicKey::init(pub)`(JS)
+ * initialize `PrecomputedPublicKey` by a public key `pub`
+
+* `PrecomputedPublicKey::destroy()`(JS)
+ * It is necessary to call this method if this instance becomes unnecessary
+ * otherwise a memory leak will be caused
+
+PK means PublicKey or PrecomputedPublicKey
+
+* `void PK::enc(CT& c, int64_t m) const`(C++)
+* `CipherTextG1 PK::encG1(m)`(JS)
+* `CipherTextG2 PK::encG2(m)`(JS)
+* `CipherTextGT PK::encGT(m)`(JS)
+ * encrypt `m` and set `c`(or return the value)
+
+* `void PK::reRand(CT& c) const`(C++)
+* `CT PK::reRand(CT c)`(JS)
+ * rerandomize `c`
+ * For `c = Enc(m)`, the rerandomized ciphertext is hard to detect if it is generated by the rerandomization
+ or an encrypted `m` freshly again.
+
+* `void convert(CipherTextGT& cm, const CT& ca) const`
+* `CipherTextGT convert(CT ca)`
+ * convert `ca`(CipherTextG1 or CipherTextG2) to `CipherTextGT` class
+
+## CipherText class
+
+* `void CT::add(CT& z, const CT& x const CT& y)`(C++)
+* `CT she.add(CT x, CT y)`(JS)
+ * add `x` and `y` and set the value to `z`(or return the value)
+* `void CT::sub(CT& z, const CT& x const CT& y)`(C++)
+* `CT she.sub(CT x, CT y)`(JS)
+ * subtract `x` and `y` and set the value to `z`(or return the value)
+* `void CT::neg(CT& y, const CT& x)`(C++)
+* `void she.neg(CT x)`(JS)
+ * negate `x` and set the value to `y`(or return the value)
+* `void CT::mul(CT& z, const CT& x, int y)`(C++)
+* `CT she.mulInt(CT x, int y)`(JS)
+ * multiple `x` and `y` and set the value `y`(or return the value)
+
+* `void CipherTextGT::mul(CipherTextGT& z, const CipherTextG1& x, const CipherTextG2& y)`(C++)
+* `CipherTextGT she.mul(CipherTextG1 x, CipherTextG2 y)`(JS)
+ * multiple `x` and `y` and set the value `y`(or return the value)
+
+* `void CipherTextGT::mulML(CipherTextGT& z, const CipherTextG1& x, const CipherTextG2& y)`(C++)
+ * multiple(only Miller Loop) `x` and `y` and set the value `y`(or return the value)
+
+* `CipherTextGT::finalExp(CipherText& , const CipherTextG1& x, const CipherTextG2& y)`(C++)
+ * mul(a, b) = finalExp(mulML(a, b))
+ * add(mul(a, b), mul(c, d)) = finalExp(add(mulML(a, b), mulML(c, d)))
+ * i.e., innor product can be computed as once calling `finalExp` after computing `mulML` for each elements of two vectors and adding all
+
+## Zero knowledge proof class
+
+### Abstract
+* ZkpBin ; verify whether `m = 0` or `1` for ciphertexts `encGi(m)(i = 1, 2, T)`
+* ZkpEq ; verify whether `m1 = m2` for ciphertexts `encG1(m1)` and `encG2(m2)`
+* ZkpBinEq ; verify whether `m1 = m2 = 0` or `1` for ciphertexts `encG1(m1)` and `encG2(m2)`
+
+### API
+PK = PublicKey or PrecomputedPublicKey
+
+* `void PK::encWithZkpBin(CipherTextG1& c, Zkp& zkp, int m) const`(C++)
+* `void PK::encWithZkpBin(CipherTextG2& c, Zkp& zkp, int m) const`(C++)
+* `[CipherTextG1, ZkpBin] PK::encWithZkpBinG1(m)`(JS)
+* `[CipherTextG2, ZkpBin] PK::encWithZkpBinG2(m)`(JS)
+ * encrypt `m`(=0 or 1) and set the ciphertext `c` and zero-knowledge proof `zkp`(or returns [c, zkp])
+ * throw exception if m != 0 and m != 1
+* `void PK::encWithZkpEq(CipherTextG1& c1, CipherTextG2& c2, ZkpEq& zkp, const INT& m) const`(C++)
+* `[CipherTextG1, CipherTextG2, ZkpEq] PK::encWithZkpEq(m)`(JS)
+ * encrypt `m` and set the ciphertext `c1`, `c2` and zero-knowledge proof `zk`(or returns [c1, c2, zkp])
+* `void PK::encWithZkpBinEq(CipherTextG1& c1, CipherTextG2& c2, ZkpBinEq& zkp, int m) const`(C++)
+* `[CipherTextG1, CipherTextG2, ZkpEqBin] PK::encWithZkpBinEq(m)`(JS)
+ * encrypt `m`(=0 or 1) and set ciphertexts `c1`, `c2` and zero-knowledge proof `zkp`(or returns [c1, c2, zkp])
+ * throw exception if m != 0 and m != 1
+
+## Global functions
+
+* `void init(const CurveParam& cp, size_t hashSize = 1024, size_t tryNum = 2048)`(C++)
+* `void init(curveType = she.BN254, hashSize = 1024, tryNum = 2048)`(JS)
+ * initialize a table to solve a DLP with `hashSize` size and set maximum trying count `tryNum`.
+ * the range `m` to be solvable is |m| <= hashSize * tryNum
+* `getHashTableGT().load(InputStream& is)`(C++)
+* `she.loadTableForGTDLP(Uint8Array a)`(JS)
+ * load a DLP table for CipherTextGT
+ * reset the value of `hashSize` used in `init()`
+ * `https://herumi.github.io/she-dlp-table/she-dlp-0-20-gt.bin` is a precomputed table
+* `void useDecG1ViaGT(bool use)`(C++/JS)
+* `void useDecG2ViaGT(bool use)`(C++/JS)
+ * decrypt a ciphertext of CipherTextG1 and CipherTextG2 through CipherTextGT
+ * it is better when decrypt a big value
+
+# License
+
+[modified new BSD License](https://github.com/herumi/mcl/blob/master/COPYRIGHT)
+
+# Author
+
+å…‰æˆæ»‹ç”Ÿ MITSUNARI Shigeo(herumi@nifty.com)
diff --git a/vendor/github.com/dexon-foundation/mcl/misc/she/she.pdf b/vendor/github.com/dexon-foundation/mcl/misc/she/she.pdf
new file mode 100644
index 000000000..355a308b3
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/misc/she/she.pdf
Binary files differ
diff --git a/vendor/github.com/dexon-foundation/mcl/mklib.bat b/vendor/github.com/dexon-foundation/mcl/mklib.bat
index b601f15d2..389b69009 100644
--- a/vendor/github.com/dexon-foundation/mcl/mklib.bat
+++ b/vendor/github.com/dexon-foundation/mcl/mklib.bat
@@ -23,6 +23,11 @@ if "%1"=="dll" (
cl /c %CFLAGS% src\bn_c384.cpp /Foobj\bn_c384.obj /DMCLBN_NO_AUTOLINK
echo link /nologo /DLL /OUT:bin\mclbn384.dll obj\bn_c384.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn384.lib
link /nologo /DLL /OUT:bin\mclbn384.dll obj\bn_c384.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn384.lib
+
+ echo cl /c %CFLAGS% src\she_c256.cpp /Foobj\she_c256.obj /DMCLBN_NO_AUTOLINK
+ cl /c %CFLAGS% src\she_c256.cpp /Foobj\she_c256.obj /DMCLBN_NO_AUTOLINK
+ echo link /nologo /DLL /OUT:bin\mclshe256.dll obj\she_c256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclshe_c256.lib
+ link /nologo /DLL /OUT:bin\mclshe256.dll obj\she_c256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclshe_c256.lib
) else (
echo cl /c %CFLAGS% src\bn_c256.cpp /Foobj\bn_c256.obj
cl /c %CFLAGS% src\bn_c256.cpp /Foobj\bn_c256.obj
diff --git a/vendor/github.com/dexon-foundation/mcl/readme.md b/vendor/github.com/dexon-foundation/mcl/readme.md
index 1a9f3acc0..39b3d4d42 100644
--- a/vendor/github.com/dexon-foundation/mcl/readme.md
+++ b/vendor/github.com/dexon-foundation/mcl/readme.md
@@ -10,6 +10,8 @@ mcl is a library for pairing-based cryptography.
The current version supports the optimal Ate pairing over BN curves and BLS12-381 curves.
# News
+* (Break backward compatibility) libmcl_dy.a is renamed to libmcl.a
+ * The option SHARE_BASENAME_SUF is removed
* 2nd argument of `mclBn_init` is changed from `maxUnitSize` to `compiledTimeVar`, which must be `MCLBN_COMPILED_TIME_VAR`.
* break backward compatibility of mapToGi for BLS12. A map-to-function for BN is used.
If `MCL_USE_OLD_MAPTO_FOR_BLS12` is defined, then the old function is used, but this will be removed in the future.
@@ -35,33 +37,31 @@ p(z) = 36z^4 + 36z^3 + 24z^2 + 6z + 1.
# Benchmark
-A benchmark of a BN curve BN254(2016/12/25).
+## The latest benchmark(2018/11/7)
-* x64, x86 ; Inte Core i7-6700 3.4GHz(Skylake) upto 4GHz on Ubuntu 16.04.
- * `sudo cpufreq-set -g performance`
-* arm ; 900MHz quad-core ARM Cortex-A7 on Raspberry Pi2, Linux 4.4.11-v7+
-* arm64 ; 1.2GHz ARM Cortex-A53 [HiKey](http://www.96boards.org/product/hikey/)
+### Intel Core i7-6700 3.4GHz(Skylake), Ubuntu 18.04.1 LTS
-software | x64| x86| arm|arm64(msec)
----------------------------------------------------------|------|-----|----|-----
-[ate-pairing](https://github.com/herumi/ate-pairing) | 0.21 | - | - | -
-mcl | 0.31 | 1.6 |22.6| 3.9
-[TEPLA](http://www.cipher.risk.tsukuba.ac.jp/tepla/) | 1.76 | 3.7 | 37 | 17.9
-[RELIC](https://github.com/relic-toolkit/relic) PRIME=254| 0.30 | 3.5 | 36 | -
-[MIRACL](https://github.com/miracl/MIRACL) ake12bnx | 4.2 | - | 78 | -
-[NEONabe](http://sandia.cs.cinvestav.mx/Site/NEONabe) | - | - | 16 | -
+curveType | binary|clang-6.0.0|gcc-7.3.0|
+----------|--------------------|-----------|---------|
+BN254 | bin/bn\_test.exe| 882Kclk| 933Kclk|
+BLS12-381 | bin/bls12\_test.exe| 2290Kclk| 2630Kclk|
-* compile option for RELIC
-```
-cmake -DARITH=x64-asm-254 -DFP_PRIME=254 -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP"
-```
-## Higher-bit BN curve benchmark by mcl
+### Intel Core i7-7700 3.6GHz(Kaby Lake), Ubuntu 18.04.1 LTS on Windows 10 Vmware
+
+curveType | binary|clang-6.0.0|gcc-7.3.0|
+----------|--------------------|-----------|---------|
+BN254 | bin/bn\_test.exe| 900Kclk| 954Kclk|
+BLS12-381 | bin/bls12\_test.exe| 2340Kclk| 2680Kclk|
+
+* now investigating the reason why gcc is slower than clang.
+
+## Higher-bit BN curve benchmark
For JavaScript(WebAssembly), see [ID based encryption demo](https://herumi.github.io/mcl-wasm/ibe-demo.html).
paramter | x64| Firefox on x64|Safari on iPhone7|
-----------|-----|---------------|-----------------|
-BN254 | 0.29| 2.48| 4.78|
+BN254 | 0.25| 2.48| 4.78|
BN381\_1 | 0.95| 7.91| 11.74|
BN462 | 2.16| 14.73| 22.77|
@@ -74,6 +74,27 @@ BN462 | 2.16| 14.73| 22.77|
The other benchmark results are [bench.txt](bench.txt).
+## An old benchmark of a BN curve BN254(2016/12/25).
+
+* x64, x86 ; Inte Core i7-6700 3.4GHz(Skylake) upto 4GHz on Ubuntu 16.04.
+ * `sudo cpufreq-set -g performance`
+* arm ; 900MHz quad-core ARM Cortex-A7 on Raspberry Pi2, Linux 4.4.11-v7+
+* arm64 ; 1.2GHz ARM Cortex-A53 [HiKey](http://www.96boards.org/product/hikey/)
+
+software | x64| x86| arm|arm64(msec)
+---------------------------------------------------------|------|-----|----|-----
+[ate-pairing](https://github.com/herumi/ate-pairing) | 0.21 | - | - | -
+mcl | 0.31 | 1.6 |22.6| 3.9
+[TEPLA](http://www.cipher.risk.tsukuba.ac.jp/tepla/) | 1.76 | 3.7 | 37 | 17.9
+[RELIC](https://github.com/relic-toolkit/relic) PRIME=254| 0.30 | 3.5 | 36 | -
+[MIRACL](https://github.com/miracl/MIRACL) ake12bnx | 4.2 | - | 78 | -
+[NEONabe](http://sandia.cs.cinvestav.mx/Site/NEONabe) | - | - | 16 | -
+
+* compile option for RELIC
+```
+cmake -DARITH=x64-asm-254 -DFP_PRIME=254 -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP"
+```
+
# Installation Requirements
* [GMP](https://gmplib.org/) and OpenSSL
@@ -90,6 +111,18 @@ git clone git://github.com/herumi/cybozulib_ext ; for only Windows
```
* Cybozulib\_ext is a prerequisite for running OpenSSL and GMP on VC (Visual C++).
+# (Option) Without GMP
+```
+make MCL_USE_GMP=0
+```
+Define `MCL_USE_VINT` before including `bn.hpp`
+
+# (Option) Without Openssl
+```
+make MCL_USE_OPENSSL=0
+```
+Define `MCL_DONT_USE_OPENSSL` before including `bn.hpp`
+
# Build and test on x86-64 Linux, macOS, ARM and ARM64 Linux
To make lib/libmcl.a and test it:
```
@@ -198,7 +231,7 @@ finalExp 546.259Kclk
## C++ library
* libmcl.a ; static C++ library of mcl
-* libmcl\_dy.so ; shared C++ library of mcl
+* libmcl.so ; shared C++ library of mcl
* the default parameter of curveType is BN254
header |support curveType |sizeof Fr|sizeof Fp|
@@ -212,16 +245,22 @@ bn384.hpp |BN381_1, BLS12_381, BN254| 48 | 48 |
* Define `MCLBN_FR_UNIT_SIZE` and `MCLBN_FP_UNIT_SIZE` and include bn.h
* set `MCLBN_FR_UNIT_SIZE = MCLBN_FP_UNIT_SIZE` unless `MCLBN_FR_UNIT_SIZE` is defined
+
library |MCLBN_FR_UNIT_SIZE|MCLBN_FP_UNIT_SIZE|
------------------|------------------|------------------|
+sizeof | Fr | Fp |
libmclbn256.a | 4 | 4 |
libmclbn384_256.a | 4 | 6 |
libmclbn384.a | 6 | 6 |
+
* libmclbn*.a ; static C library
-* libmclbn*\_dy.so ; shared C library
+* libmclbn*.so ; shared C library
-If you want to remove `_dy` of so files, then `makeSHARE_BASENAME\_SUF=`.
+### 2nd argument of `mclBn_init`
+Specify `MCLBN_COMPILED_TIME_VAR` to 2nd argument of `mclBn_init`, which
+is defined as `MCLBN_FR_UNIT_SIZE * 10 + MCLBN_FP_UNIT_SIZE`.
+This parameter is used to make sure that the values are the same when the library is built and used.
# How to initialize pairing library
Call `mcl::bn256::initPairing` before calling any operations.
@@ -293,10 +332,14 @@ Use `Fp12::mulGeneric` for x in Fp12 - GT.
## Map To points
-* mapToG1(G1& P, const Fp& x);
+Use these functions to make a point of G1 and G2.
+
+* mapToG1(G1& P, const Fp& x); // assume x != 0
* mapToG2(G2& P, const Fp2& x);
+* hashAndMapToG1(G1& P, const void *buf, size_t bufSize); // set P by the hash value of [buf, bufSize)
+* hashAndMapToG2(G2& P, const void *buf, size_t bufSize);
-These functions maps x into Gi according to [_Faster hashing to G2_].
+These functions maps x into Gi according to [\[_Faster hashing to G2_\]].
## String format of G1 and G2
G1 and G2 have three elements of Fp (x, y, z) for Jacobi coordinate.
@@ -309,6 +352,44 @@ getStr() method gets
* `2 <x>` ; compressed format for even y
* `3 <x>` ; compressed format for odd y
+## Generator of G1 and G2
+
+If you want to use the same generators of BLS12-381 with [zkcrypto](https://github.com/zkcrypto/pairing/tree/master/src/bls12_381#g2) then,
+
+```
+// G1 P
+P.setStr('1 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569')
+
+// G2 Q
+Q.setStr('1 352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160 3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582')
+```
+
+## Serialization format of G1 and G2
+
+pseudo-code to serialize of p
+```
+if bit-length(p) % 8 != 0:
+ size = Fp::getByteSize()
+ if p is zero:
+ return [0] * size
+ else:
+ s = x.serialize()
+ # x in Fp2 is odd <=> x.a is odd
+ if y is odd:
+ s[byte-length(s) - 1] |= 0x80
+ return s
+else:
+ size = Fp::getByteSize() + 1
+ if p is zero:
+ return [0] * size
+ else:
+ s = x.serialize()
+ if y is odd:
+ return 2:s
+ else:
+ return 3:s
+```
+
## Verify an element in G2
`G2::isValid()` checks that the element is in the curve of G2 and the order of it is r for subgroup attack.
`G2::set()`, `G2::setStr` and `operator<<` also check the order.
@@ -360,6 +441,17 @@ This library contains some part of the followings software licensed by BSD-3-Cla
* [_Skew Frobenius Map and Efficient Scalar Multiplication for Pairing–Based Cryptography_](https://www.researchgate.net/publication/221282560_Skew_Frobenius_Map_and_Efficient_Scalar_Multiplication_for_Pairing-Based_Cryptography),
Y. Sakemi, Y. Nogami, K. Okeya, Y. Morikawa, CANS 2008.
+# History
+
+* 2019/Mar/22 v0.92 shortcut for Ec::mul(Px, P, x) if P = 0
+* 2019/Mar/21 python binding of she256 for Linux/Mac/Windows
+* 2019/Mar/14 v0.91 modp supports mcl-wasm
+* 2019/Mar/12 v0.90 fix Vint::setArray(x) for x == this
+* 2019/Mar/07 add mclBnFr_setLittleEndianMod, mclBnFp_setLittleEndianMod
+* 2019/Feb/20 LagrangeInterpolation sets out = yVec[0] if k = 1
+* 2019/Jan/31 add mclBnFp_mapToG1, mclBnFp2_mapToG2
+* 2019/Jan/31 fix crash on x64-CPU without AVX (thanks to mortdeus)
+
# Author
å…‰æˆæ»‹ç”Ÿ MITSUNARI Shigeo(herumi@nifty.com)
diff --git a/vendor/github.com/dexon-foundation/mcl/sample/bench.cpp b/vendor/github.com/dexon-foundation/mcl/sample/bench.cpp
new file mode 100644
index 000000000..0f865b189
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/sample/bench.cpp
@@ -0,0 +1,233 @@
+#include <cybozu/benchmark.hpp>
+#include <cybozu/option.hpp>
+#include <cybozu/xorshift.hpp>
+#include <mcl/fp.hpp>
+#include <mcl/conversion.hpp>
+#include <mcl/ecparam.hpp>
+
+typedef mcl::FpT<> Fp;
+typedef mcl::FpT<mcl::ZnTag> Zn;
+typedef mcl::EcT<Fp> Ec;
+
+void benchFpSub(const char *pStr, const char *xStr, const char *yStr, mcl::fp::Mode mode)
+{
+ const char *s = mcl::fp::ModeToStr(mode);
+ Fp::init(pStr, mode);
+ Fp x(xStr);
+ Fp y(yStr);
+
+ double addT, subT, mulT, sqrT, invT;
+ CYBOZU_BENCH_T(addT, Fp::add, x, x, x);
+ CYBOZU_BENCH_T(subT, Fp::sub, x, x, y);
+ CYBOZU_BENCH_T(mulT, Fp::mul, x, x, x);
+ CYBOZU_BENCH_T(sqrT, Fp::sqr, x, x);
+ CYBOZU_BENCH_T(invT, x += y;Fp::inv, x, x); // avoid same jmp
+ printf("%10s bit % 3d add %8.2f sub %8.2f mul %8.2f sqr %8.2f inv %8.2f\n", s, (int)Fp::getBitSize(), addT, subT, mulT, sqrT, invT);
+}
+
+void benchFp(size_t bitSize, int mode)
+{
+ const struct {
+ size_t bitSize;
+ const char *p;
+ const char *x;
+ const char *y;
+ } tbl[] = {
+ {
+ 192,
+ "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d",
+ "0x148094810948190412345678901234567900342423332197",
+ "0x7fffffffffffffffffffffe26f2fc170f69466a74defd8d",
+ },
+ {
+ 256,
+ "0x2523648240000001ba344d80000000086121000000000013a700000000000013",
+ "0x1480948109481904123456789234234242423424201234567900342423332197",
+ "0x151342342342341517fffffffffffffffffffffe26f2fc170f69466a74defd8d",
+ },
+ {
+ 384,
+ "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff",
+ "0x19481084109481094820948209482094820984290482212345678901234567900342308472047204720422423332197",
+ "0x209348209481094820984209842094820948204204243123456789012345679003423084720472047204224233321972",
+
+ },
+ {
+ 521,
+ "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x2908209582095820941098410948109482094820984209840294829049240294242498540975555312345678901234567900342308472047204720422423332197",
+ "0x3948384209834029834092384204920349820948205872380573205782385729385729385723985837ffffffffffffffffffffffe26f2fc170f69466a74defd8d",
+
+ },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ if (bitSize != 0 && tbl[i].bitSize != bitSize) continue;
+ if (mode & 1) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_GMP);
+ if (mode & 2) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_GMP_MONT);
+#ifdef MCL_USE_LLVM
+ if (mode & 4) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_LLVM);
+ if (mode & 8) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_LLVM_MONT);
+#endif
+#ifdef MCL_USE_XBYAK
+ if (mode & 16) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_XBYAK);
+#endif
+ }
+}
+
+void benchEcSub(const mcl::EcParam& para, mcl::fp::Mode mode, mcl::ec::Mode ecMode)
+{
+ Fp::init(para.p, mode);
+ Zn::init(para.n);
+ Ec::init(para.a, para.b, ecMode);
+ Fp x(para.gx);
+ Fp y(para.gy);
+ Ec P(x, y);
+ Ec P2; Ec::add(P2, P, P);
+ Ec Q = P + P + P;
+ double addT, add2T, subT, dblT, mulT, mulCTT, mulRandT, mulCTRandT, normT;
+ CYBOZU_BENCH_T(addT, P = P2; Ec::add, Q, P, Q);
+ P.normalize();
+ CYBOZU_BENCH_T(add2T, Ec::add, Q, P, Q);
+ CYBOZU_BENCH_T(subT, Ec::sub, Q, P, Q);
+ CYBOZU_BENCH_T(dblT, Ec::dbl, P, P);
+ Zn z("3");
+ CYBOZU_BENCH_T(mulT, Ec::mul, Q, P, z);
+ CYBOZU_BENCH_T(mulCTT, Ec::mulCT, Q, P, z);
+ cybozu::XorShift rg;
+ z.setRand(rg);
+ CYBOZU_BENCH_T(mulRandT, Ec::mul, Q, P, z);
+ CYBOZU_BENCH_T(mulCTRandT, Ec::mulCT, Q, P, z);
+ CYBOZU_BENCH_T(normT, Q = P; Q.normalize);
+ printf("%10s %10s add %8.2f add2 %8.2f sub %8.2f dbl %8.2f mul(3) %8.2f mulCT(3) %8.2f mul(rand) %8.2f mulCT(rand) %8.2f norm %8.2f\n", para.name, mcl::fp::ModeToStr(mode), addT, add2T, subT, dblT, mulT, mulCTT, mulRandT, mulCTRandT, normT);
+
+}
+void benchEc(size_t bitSize, int mode, mcl::ec::Mode ecMode)
+{
+ const struct mcl::EcParam tbl[] = {
+ mcl::ecparam::p160_1,
+ mcl::ecparam::secp160k1,
+ mcl::ecparam::secp192k1,
+ mcl::ecparam::NIST_P192,
+ mcl::ecparam::secp224k1,
+ mcl::ecparam::secp256k1,
+ mcl::ecparam::NIST_P224,
+ mcl::ecparam::NIST_P256,
+// mcl::ecparam::secp384r1,
+ mcl::ecparam::NIST_P384,
+// mcl::ecparam::secp521r1,
+ mcl::ecparam::NIST_P521,
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ if (bitSize != 0 && tbl[i].bitSize != bitSize) continue;
+ benchEcSub(tbl[i], mcl::fp::FP_AUTO, ecMode);
+ if (mode & 1) benchEcSub(tbl[i], mcl::fp::FP_GMP, ecMode);
+ if (mode & 2) benchEcSub(tbl[i], mcl::fp::FP_GMP_MONT, ecMode);
+#ifdef MCL_USE_LLVM
+ if (mode & 4) benchEcSub(tbl[i], mcl::fp::FP_LLVM, ecMode);
+ if (mode & 8) benchEcSub(tbl[i], mcl::fp::FP_LLVM_MONT, ecMode);
+#endif
+#ifdef MCL_USE_XBYAK
+ if (mode & 16) benchEcSub(tbl[i], mcl::fp::FP_XBYAK, ecMode);
+#endif
+ }
+}
+
+void benchToStr16()
+{
+ puts("benchToStr16");
+ const char *tbl[] = {
+ "0x0",
+ "0x5",
+ "0x123",
+ "0x123456789012345679adbc",
+ "0xffffffff26f2fc170f69466a74defd8d",
+ "0x100000000000000000000000000000033",
+ "0x11ee12312312940000000000000000000000000002342343"
+ };
+ Fp::init("0xffffffffffffffffffffffffffffffffffffffffffffff13");
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ char buf[128];
+ std::string str;
+ Fp x(tbl[i]);
+ CYBOZU_BENCH("fp::arrayToHex", mcl::fp::arrayToHex, buf, sizeof(buf), x.getUnit(), x.getUnitSize(), true);
+ mpz_class y(tbl[i]);
+ CYBOZU_BENCH("gmp:getStr ", mcl::gmp::getStr, str, y, 16);
+ }
+}
+
+void benchFromStr16()
+{
+ puts("benchFromStr16");
+ const char *tbl[] = {
+ "0",
+ "5",
+ "123",
+ "123456789012345679adbc",
+ "ffffffff26f2fc170f69466a74defd8d",
+ "100000000000000000000000000000033",
+ "11ee12312312940000000000000000000000000002342343"
+ };
+ Fp::init("0xffffffffffffffffffffffffffffffffffffffffffffff13");
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ std::string str = tbl[i];
+ Fp x;
+ const size_t N = 64;
+ mcl::fp::Unit buf[N];
+ CYBOZU_BENCH("fp:hexToArray", mcl::fp::hexToArray, buf, N, str.c_str(), str.size());
+
+ mpz_class y;
+ CYBOZU_BENCH("gmp:setStr ", mcl::gmp::setStr, y, str, 16);
+ }
+}
+
+int main(int argc, char *argv[])
+ try
+{
+ size_t bitSize;
+ int mode;
+ bool ecOnly;
+ bool fpOnly;
+ bool misc;
+ mcl::ec::Mode ecMode;
+ std::string ecModeStr;
+ cybozu::Option opt;
+ opt.appendOpt(&bitSize, 0, "s", ": bitSize");
+ opt.appendOpt(&mode, 0, "m", ": mode(0:all, sum of 1:gmp, 2:gmp+mont, 4:llvm, 8:llvm+mont, 16:xbyak");
+ opt.appendBoolOpt(&ecOnly, "ec", ": ec only");
+ opt.appendBoolOpt(&fpOnly, "fp", ": fp only");
+ opt.appendBoolOpt(&misc, "misc", ": other benchmark");
+ opt.appendOpt(&ecModeStr, "jacobi", "ecmode", ": jacobi or proj");
+ opt.appendHelp("h", ": show this message");
+ if (!opt.parse(argc, argv)) {
+ opt.usage();
+ return 1;
+ }
+ if (ecModeStr == "jacobi") {
+ ecMode = mcl::ec::Jacobi;
+ } else if (ecModeStr == "proj") {
+ ecMode = mcl::ec::Proj;
+ } else {
+ printf("bad ecstr %s\n", ecModeStr.c_str());
+ opt.usage();
+ return 1;
+ }
+ if (mode < 0 || mode > 31) {
+ printf("bad mode %d\n", mode);
+ opt.usage();
+ return 1;
+ }
+ if (mode == 0) mode = 31;
+ if (misc) {
+ benchToStr16();
+ benchFromStr16();
+ } else {
+ if (!ecOnly) benchFp(bitSize, mode);
+ if (!fpOnly) {
+ printf("ecMode=%s\n", ecModeStr.c_str());
+ benchEc(bitSize, mode, ecMode);
+ }
+ }
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+}
+
diff --git a/vendor/github.com/dexon-foundation/mcl/sample/bls_sig.cpp b/vendor/github.com/dexon-foundation/mcl/sample/bls_sig.cpp
new file mode 100644
index 000000000..d75f7d427
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/sample/bls_sig.cpp
@@ -0,0 +1,70 @@
+/**
+ @file
+ @brief a sample of BLS signature
+ see https://github.com/herumi/bls
+ @author MITSUNARI Shigeo(@herumi)
+ @license modified new BSD license
+ http://opensource.org/licenses/BSD-3-Clause
+
+*/
+#include <mcl/bn256.hpp>
+#include <iostream>
+
+using namespace mcl::bn256;
+
+void Hash(G1& P, const std::string& m)
+{
+ Fp t;
+ t.setHashOf(m);
+ mapToG1(P, t);
+}
+
+void KeyGen(Fr& s, G2& pub, const G2& Q)
+{
+ s.setRand();
+ G2::mul(pub, Q, s); // pub = sQ
+}
+
+void Sign(G1& sign, const Fr& s, const std::string& m)
+{
+ G1 Hm;
+ Hash(Hm, m);
+ G1::mul(sign, Hm, s); // sign = s H(m)
+}
+
+bool Verify(const G1& sign, const G2& Q, const G2& pub, const std::string& m)
+{
+ Fp12 e1, e2;
+ G1 Hm;
+ Hash(Hm, m);
+ pairing(e1, sign, Q); // e1 = e(sign, Q)
+ pairing(e2, Hm, pub); // e2 = e(Hm, sQ)
+ return e1 == e2;
+}
+
+int main(int argc, char *argv[])
+{
+ std::string m = argc == 1 ? "hello mcl" : argv[1];
+
+ // setup parameter
+ initPairing();
+ G2 Q;
+ mapToG2(Q, 1);
+
+ // generate secret key and public key
+ Fr s;
+ G2 pub;
+ KeyGen(s, pub, Q);
+ std::cout << "secret key " << s << std::endl;
+ std::cout << "public key " << pub << std::endl;
+
+ // sign
+ G1 sign;
+ Sign(sign, s, m);
+ std::cout << "msg " << m << std::endl;
+ std::cout << "sign " << sign << std::endl;
+
+ // verify
+ bool ok = Verify(sign, Q, pub, m);
+ std::cout << "verify " << (ok ? "ok" : "ng") << std::endl;
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/sample/ecdh.cpp b/vendor/github.com/dexon-foundation/mcl/sample/ecdh.cpp
new file mode 100644
index 000000000..d5c4a31b2
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/sample/ecdh.cpp
@@ -0,0 +1,64 @@
+/*
+ sample of Elliptic Curve Diffie-Hellman key sharing
+*/
+#include <iostream>
+#include <fstream>
+#include <cybozu/random_generator.hpp>
+#include <mcl/fp.hpp>
+#include <mcl/ecparam.hpp>
+
+typedef mcl::FpT<> Fp;
+typedef mcl::FpT<mcl::ZnTag> Zn;
+typedef mcl::EcT<Fp> Ec;
+
+int main()
+{
+ cybozu::RandomGenerator rg;
+ /*
+ system setup with a parameter secp192k1 recommended by SECG
+ Ec is an elliptic curve over Fp
+ the cyclic group of <P> is isomorphic to Zn
+ */
+ const mcl::EcParam& para = mcl::ecparam::secp192k1;
+ Zn::init(para.n);
+ Fp::init(para.p);
+ Ec::init(para.a, para.b);
+ const Ec P(Fp(para.gx), Fp(para.gy));
+
+ /*
+ Alice setups a private key a and public key aP
+ */
+ Zn a;
+ Ec aP;
+
+ a.setRand(rg);
+ Ec::mul(aP, P, a); // aP = a * P;
+
+ std::cout << "aP=" << aP << std::endl;
+
+ /*
+ Bob setups a private key b and public key bP
+ */
+ Zn b;
+ Ec bP;
+
+ b.setRand(rg);
+ Ec::mul(bP, P, b); // bP = b * P;
+
+ std::cout << "bP=" << bP << std::endl;
+
+ Ec abP, baP;
+
+ // Alice uses bP(B's public key) and a(A's priavte key)
+ Ec::mul(abP, bP, a); // abP = a * (bP)
+
+ // Bob uses aP(A's public key) and b(B's private key)
+ Ec::mul(baP, aP, b); // baP = b * (aP)
+
+ if (abP == baP) {
+ std::cout << "key sharing succeed:" << abP << std::endl;
+ } else {
+ std::cout << "ERR(not here)" << std::endl;
+ }
+}
+
diff --git a/vendor/github.com/dexon-foundation/mcl/sample/large.cpp b/vendor/github.com/dexon-foundation/mcl/sample/large.cpp
new file mode 100644
index 000000000..60b2ac900
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/sample/large.cpp
@@ -0,0 +1,125 @@
+/*
+ large prime sample for 64-bit arch
+ make MCL_USE_LLVM=1 MCL_MAX_BIT_SIZE=768
+*/
+#include <mcl/fp.hpp>
+#include <cybozu/benchmark.hpp>
+#include <iostream>
+#include "../src/low_func.hpp"
+
+typedef mcl::FpT<> Fp;
+
+using namespace mcl::fp;
+const size_t N = 12;
+
+void testMul()
+{
+ Unit ux[N], uy[N], a[N * 2], b[N * 2];
+ for (size_t i = 0; i < N; i++) {
+ ux[i] = -i * i + 5;
+ uy[i] = -i * i + 9;
+ }
+ MulPreCore<N, Gtag>::f(a, ux, uy);
+ MulPreCore<N, Ltag>::f(b, ux, uy);
+ for (size_t i = 0; i < N * 2; i++) {
+ if (a[i] != b[i]) {
+ printf("ERR %016llx %016llx\n", (long long)a[i], (long long)b[i]);
+ }
+ }
+ puts("end testMul");
+ CYBOZU_BENCH("gmp ", (MulPreCore<N, Gtag>::f), ux, ux, uy);
+ CYBOZU_BENCH("kara", (MulPre<N, Gtag>::karatsuba), ux, ux, uy);
+}
+
+void mulGmp(mpz_class& z, const mpz_class& x, const mpz_class& y, const mpz_class& p)
+{
+ z = (x * y) % p;
+}
+void compareGmp(const std::string& pStr)
+{
+ Fp::init(pStr);
+ std::string xStr = "2104871209348712947120947102843728";
+ std::string s1, s2;
+ {
+ Fp x(xStr);
+ CYBOZU_BENCH_C("mul by mcl", 1000, Fp::mul, x, x, x);
+ std::ostringstream os;
+ os << x;
+ s1 = os.str();
+ }
+ {
+ const mpz_class p(pStr);
+ mpz_class x(xStr);
+ CYBOZU_BENCH_C("mul by GMP", 1000, mulGmp, x, x, x, p);
+ std::ostringstream os;
+ os << x;
+ s2 = os.str();
+ }
+ if (s1 != s2) {
+ puts("ERR");
+ }
+}
+
+void test(const std::string& pStr, mcl::fp::Mode mode)
+{
+ printf("test %s\n", mcl::fp::ModeToStr(mode));
+ Fp::init(pStr, mode);
+ const mcl::fp::Op& op = Fp::getOp();
+ printf("bitSize=%d\n", (int)Fp::getBitSize());
+ mpz_class p(pStr);
+ Fp x = 123456;
+ Fp y;
+ Fp::pow(y, x, p);
+ std::cout << y << std::endl;
+ if (x != y) {
+ std::cout << "err:pow:" << y << std::endl;
+ return;
+ }
+ const size_t N = 24;
+ mcl::fp::Unit ux[N], uy[N];
+ for (size_t i = 0; i < N; i++) {
+ ux[i] = -i * i + 5;
+ uy[i] = -i * i + 9;
+ }
+ CYBOZU_BENCH("mulPre", op.fpDbl_mulPre, ux, ux, uy);
+ CYBOZU_BENCH("sqrPre", op.fpDbl_sqrPre, ux, ux);
+ CYBOZU_BENCH("add", op.fpDbl_add, ux, ux, ux, op.p);
+ CYBOZU_BENCH("sub", op.fpDbl_sub, ux, ux, ux, op.p);
+ if (op.fpDbl_addPre) {
+ CYBOZU_BENCH("addPre", op.fpDbl_addPre, ux, ux, ux);
+ CYBOZU_BENCH("subPre", op.fpDbl_subPre, ux, ux, ux);
+ }
+ CYBOZU_BENCH("mont", op.fpDbl_mod, ux, ux, op.p);
+ CYBOZU_BENCH("mul", Fp::mul, x, x, x);
+ compareGmp(pStr);
+}
+
+void testAll(const std::string& pStr)
+{
+ test(pStr, mcl::fp::FP_GMP);
+ test(pStr, mcl::fp::FP_GMP_MONT);
+#ifdef MCL_USE_LLVM
+ test(pStr, mcl::fp::FP_LLVM);
+ test(pStr, mcl::fp::FP_LLVM_MONT);
+#endif
+ compareGmp(pStr);
+}
+int main()
+ try
+{
+ const char *pTbl[] = {
+ "40347654345107946713373737062547060536401653012956617387979052445947619094013143666088208645002153616185987062074179207",
+ "13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006083527",
+ "776259046150354467574489744231251277628443008558348305569526019013025476343188443165439204414323238975243865348565536603085790022057407195722143637520590569602227488010424952775132642815799222412631499596858234375446423426908029627",
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(pTbl); i++) {
+ testAll(pTbl[i]);
+ }
+ testMul();
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ puts("make clean");
+ puts("make -DMCL_MAX_BIT_SIZE=768");
+ return 1;
+}
+
diff --git a/vendor/github.com/dexon-foundation/mcl/sample/pairing.cpp b/vendor/github.com/dexon-foundation/mcl/sample/pairing.cpp
new file mode 100644
index 000000000..230583b6e
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/sample/pairing.cpp
@@ -0,0 +1,56 @@
+#include <mcl/bn256.hpp>
+
+using namespace mcl::bn256;
+
+void minimum_sample(const G1& P, const G2& Q)
+{
+ const mpz_class a = 123;
+ const mpz_class b = 456;
+ Fp12 e1, e2;
+ pairing(e1, P, Q);
+ G2 aQ;
+ G1 bP;
+ G2::mul(aQ, Q, a);
+ G1::mul(bP, P, b);
+ pairing(e2, bP, aQ);
+ Fp12::pow(e1, e1, a * b);
+ printf("%s\n", e1 == e2 ? "ok" : "ng");
+}
+
+void miller_and_finel_exp(const G1& P, const G2& Q)
+{
+ Fp12 e1, e2;
+ pairing(e1, P, Q);
+
+ millerLoop(e2, P, Q);
+ finalExp(e2, e2);
+ printf("%s\n", e1 == e2 ? "ok" : "ng");
+}
+
+void precomputed(const G1& P, const G2& Q)
+{
+ Fp12 e1, e2;
+ pairing(e1, P, Q);
+ std::vector<Fp6> Qcoeff;
+ precomputeG2(Qcoeff, Q);
+ precomputedMillerLoop(e2, P, Qcoeff);
+ finalExp(e2, e2);
+ printf("%s\n", e1 == e2 ? "ok" : "ng");
+}
+
+int main()
+{
+ const char *aa = "12723517038133731887338407189719511622662176727675373276651903807414909099441";
+ const char *ab = "4168783608814932154536427934509895782246573715297911553964171371032945126671";
+ const char *ba = "13891744915211034074451795021214165905772212241412891944830863846330766296736";
+ const char *bb = "7937318970632701341203597196594272556916396164729705624521405069090520231616";
+
+ initPairing();
+ G2 Q(Fp2(aa, ab), Fp2(ba, bb));
+ G1 P(-1, 1);
+
+ minimum_sample(P, Q);
+ miller_and_finel_exp(P, Q);
+ precomputed(P, Q);
+}
+
diff --git a/vendor/github.com/dexon-foundation/mcl/sample/pairing_c.c b/vendor/github.com/dexon-foundation/mcl/sample/pairing_c.c
new file mode 100644
index 000000000..5c2cd222a
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/sample/pairing_c.c
@@ -0,0 +1,52 @@
+#include <stdio.h>
+#include <string.h>
+#define MCLBN_FP_UNIT_SIZE 4
+#include <mcl/bn.h>
+
+int g_err = 0;
+#define ASSERT(x) { if (!(x)) { printf("err %s:%d\n", __FILE__, __LINE__); g_err++; } }
+
+int main()
+{
+ char buf[1024];
+ const char *aStr = "123";
+ const char *bStr = "456";
+ mclBn_init(MCL_BN254, MCLBN_FP_UNIT_SIZE);
+ mclBnFr a, b, ab;
+ mclBnG1 P, aP;
+ mclBnG2 Q, bQ;
+ mclBnGT e, e1, e2;
+ mclBnFr_setStr(&a, aStr, strlen(aStr), 10);
+ mclBnFr_setStr(&b, bStr, strlen(bStr), 10);
+ mclBnFr_mul(&ab, &a, &b);
+ mclBnFr_getStr(buf, sizeof(buf), &ab, 10);
+ printf("%s x %s = %s\n", aStr, bStr, buf);
+
+ ASSERT(!mclBnG1_hashAndMapTo(&P, "this", 4));
+ ASSERT(!mclBnG2_hashAndMapTo(&Q, "that", 4));
+ mclBnG1_getStr(buf, sizeof(buf), &P, 16);
+ printf("P = %s\n", buf);
+ mclBnG2_getStr(buf, sizeof(buf), &Q, 16);
+ printf("Q = %s\n", buf);
+
+ mclBnG1_mul(&aP, &P, &a);
+ mclBnG2_mul(&bQ, &Q, &b);
+
+ mclBn_pairing(&e, &P, &Q);
+ mclBnGT_getStr(buf, sizeof(buf), &e, 16);
+ printf("e = %s\n", buf);
+ mclBnGT_pow(&e1, &e, &a);
+ mclBn_pairing(&e2, &aP, &Q);
+ ASSERT(mclBnGT_isEqual(&e1, &e2));
+
+ mclBnGT_pow(&e1, &e, &b);
+ mclBn_pairing(&e2, &P, &bQ);
+ ASSERT(mclBnGT_isEqual(&e1, &e2));
+ if (g_err) {
+ printf("err %d\n", g_err);
+ return 1;
+ } else {
+ printf("no err\n");
+ return 0;
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/sample/random.cpp b/vendor/github.com/dexon-foundation/mcl/sample/random.cpp
new file mode 100644
index 000000000..a2a3619ad
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/sample/random.cpp
@@ -0,0 +1,29 @@
+#include <mcl/fp.hpp>
+#include <mcl/gmp_util.hpp>
+#include <mcl/ecparam.hpp>
+#include <cybozu/random_generator.hpp>
+#include <map>
+#include <mcl/fp.hpp>
+typedef mcl::FpT<> Fp;
+
+typedef std::map<std::string, int> Map;
+
+int main(int argc, char *argv[])
+{
+ cybozu::RandomGenerator rg;
+ const char *p = mcl::ecparam::secp192k1.p;
+ if (argc == 2) {
+ p = argv[1];
+ }
+ Fp::init(p);
+ Fp x;
+ printf("p=%s\n", p);
+ Map m;
+ for (int i = 0; i < 10000; i++) {
+ x.setRand(rg);
+ m[x.getStr(16)]++;
+ }
+ for (Map::const_iterator i = m.begin(), ie = m.end(); i != ie; ++i) {
+ printf("%s %d\n", i->first.c_str(), i->second);
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/sample/rawbench.cpp b/vendor/github.com/dexon-foundation/mcl/sample/rawbench.cpp
new file mode 100644
index 000000000..4d7506ef5
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/sample/rawbench.cpp
@@ -0,0 +1,180 @@
+#define PUT(x) std::cout << #x "=" << (x) << std::endl
+#include <cybozu/benchmark.hpp>
+#include <cybozu/option.hpp>
+#include <cybozu/xorshift.hpp>
+#include <mcl/fp.hpp>
+#include <mcl/fp_tower.hpp>
+
+typedef mcl::FpT<mcl::FpTag> Fp;
+typedef mcl::Fp2T<Fp> Fp2;
+typedef mcl::FpDblT<Fp> FpDbl;
+typedef mcl::Fp6T<Fp> Fp6;
+typedef mcl::Fp12T<Fp> Fp12;
+
+typedef mcl::fp::Unit Unit;
+
+void mul9(const mcl::fp::Op& op, Unit *y, const Unit *x, const Unit *p)
+{
+ const size_t maxN = sizeof(Fp) / sizeof(Unit);
+ Unit tmp[maxN];
+ op.fp_add(tmp, x, x, p); // 2x
+ op.fp_add(tmp, tmp, tmp, p); // 4x
+ op.fp_add(tmp, tmp, tmp, p); // 8x
+ op.fp_add(y, tmp, x, p); // 9x
+}
+
+void benchRaw(const char *p, mcl::fp::Mode mode)
+{
+ Fp::init(1, p, mode);
+ Fp2::init();
+ const size_t maxN = sizeof(Fp) / sizeof(Unit);
+ const mcl::fp::Op& op = Fp::getOp();
+ cybozu::XorShift rg;
+ Fp fx, fy;
+ fx.setRand(rg);
+ fy.setRand(rg);
+ Unit ux[maxN * 2] = {};
+ Unit uy[maxN * 2] = {};
+ Unit uz[maxN * 2] = {};
+ memcpy(ux, fx.getUnit(), sizeof(Unit) * op.N);
+ memcpy(ux + op.N, fx.getUnit(), sizeof(Unit) * op.N);
+ memcpy(uy, fy.getUnit(), sizeof(Unit) * op.N);
+ memcpy(ux + op.N, fx.getUnit(), sizeof(Unit) * op.N);
+ double fp_addT, fp_subT;
+ double fp_addPreT, fp_subPreT;
+ double fp_sqrT, fp_mulT;
+ double fp_mulUnitT;
+ double mul9T;
+ double fp_mulUnitPreT;
+ double fpN1_modT;
+ double fpDbl_addT, fpDbl_subT;
+ double fpDbl_sqrPreT, fpDbl_mulPreT, fpDbl_modT;
+ double fp2_sqrT, fp2_mulT;
+ CYBOZU_BENCH_T(fp_addT, op.fp_add, uz, ux, uy, op.p);
+ CYBOZU_BENCH_T(fp_subT, op.fp_sub, uz, uy, ux, op.p);
+ CYBOZU_BENCH_T(fp_addPreT, op.fp_addPre, uz, ux, uy);
+ CYBOZU_BENCH_T(fp_subPreT, op.fp_subPre, uz, uy, ux);
+ CYBOZU_BENCH_T(fp_sqrT, op.fp_sqr, uz, ux, op.p);
+ CYBOZU_BENCH_T(fp_mulT, op.fp_mul, uz, ux, uy, op.p);
+ CYBOZU_BENCH_T(fp_mulUnitT, op.fp_mulUnit, uz, ux, 9, op.p);
+ CYBOZU_BENCH_T(mul9T, mul9, op, uz, ux, op.p);
+ CYBOZU_BENCH_T(fp_mulUnitPreT, op.fp_mulUnitPre, ux, ux, 9);
+ CYBOZU_BENCH_T(fpN1_modT, op.fpN1_mod, ux, uy, op.p);
+ CYBOZU_BENCH_T(fpDbl_addT, op.fpDbl_add, uz, ux, uy, op.p);
+ CYBOZU_BENCH_T(fpDbl_subT, op.fpDbl_sub, uz, uy, ux, op.p);
+ CYBOZU_BENCH_T(fpDbl_sqrPreT, op.fpDbl_sqrPre, uz, ux);
+ CYBOZU_BENCH_T(fpDbl_mulPreT, op.fpDbl_mulPre, uz, ux, uy);
+ CYBOZU_BENCH_T(fpDbl_modT, op.fpDbl_mod, uz, ux, op.p);
+ Fp2 f2x, f2y;
+ f2x.a = fx;
+ f2x.b = fy;
+ f2y = f2x;
+ CYBOZU_BENCH_T(fp2_sqrT, Fp2::sqr, f2x, f2x);
+ CYBOZU_BENCH_T(fp2_mulT, Fp2::mul, f2x, f2x, f2y);
+ printf("%s\n", mcl::fp::ModeToStr(mode));
+ const char *tStrTbl[] = {
+ "fp_add", "fp_sub",
+ "addPre", "subPre",
+ "fp_sqr", "fp_mul",
+ "mulUnit",
+ "mul9",
+ "mulUnitP",
+ "fpN1_mod",
+ "D_add", "D_sub",
+ "D_sqrPre", "D_mulPre", "D_mod",
+ "fp2_sqr", "fp2_mul",
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tStrTbl); i++) {
+ printf(" %8s", tStrTbl[i]);
+ }
+ printf("\n");
+ const double tTbl[] = {
+ fp_addT, fp_subT,
+ fp_addPreT, fp_subPreT,
+ fp_sqrT, fp_mulT,
+ fp_mulUnitT,
+ mul9T,
+ fp_mulUnitPreT,
+ fpN1_modT,
+ fpDbl_addT, fpDbl_subT,
+ fpDbl_sqrPreT, fpDbl_mulPreT, fpDbl_modT,
+ fp2_sqrT, fp2_mulT,
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tTbl); i++) {
+ printf(" %8.2f", tTbl[i]);
+ }
+ printf("\n");
+}
+
+int main(int argc, char *argv[])
+ try
+{
+ cybozu::Option opt;
+ size_t bitSize;
+ opt.appendOpt(&bitSize, 0, "s", ": bitSize");
+ opt.appendHelp("h", ": show this message");
+ if (!opt.parse(argc, argv)) {
+ opt.usage();
+ return 1;
+ }
+ const char *tbl[] = {
+ // N = 2
+ "0x0000000000000001000000000000000d",
+ "0x7fffffffffffffffffffffffffffffff",
+ "0x8000000000000000000000000000001d",
+ "0xffffffffffffffffffffffffffffff61",
+
+ // N = 3
+ "0x000000000000000100000000000000000000000000000033", // min prime
+ "0x70000000000000000000000000000000000000000000001f",
+ "0x800000000000000000000000000000000000000000000005",
+ "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d",
+ "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
+ "0xffffffffffffffffffffffffffffffffffffffffffffff13", // max prime
+
+ // N = 4
+ "0x0000000000000001000000000000000000000000000000000000000000000085", // min prime
+ "0x2523648240000001ba344d80000000086121000000000013a700000000000013", // BN254
+ "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47", // Snark
+ "0x7523648240000001ba344d80000000086121000000000013a700000000000017",
+ "0x800000000000000000000000000000000000000000000000000000000000005f",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43", // max prime
+ // N = 5
+ "0x80000000000000000000000000000000000000000000000000000000000000000000000000000009",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3b",
+ // N = 6
+ "0x800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000171",
+ "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec3",
+ // N = 7
+ "0x8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff35",
+ // N = 8
+ "0x8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f",
+ "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc7",
+#if MCL_MAX_BIT_SIZE == 1024
+ "0xc70b1ddda9b96e3965e5855942aa5852d8f8e052c760ac32cdfec16a2ed3d56981e1a475e20a70144ed2f5061ba64900f69451492803f815d446ee133d0668f7a7f3276d6301c95ce231f0e4b0d0f3882f10014fca04454cff55d2e2d4cfc1aad33b8d38397e2fc8b623177e63d0b783269c40a85b8f105654783b8ed2e737df",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff97",
+#endif
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const char *p = tbl[i];
+ if (bitSize > 0 && (strlen(p) - 2) * 4 != bitSize) {
+ continue;
+ }
+ printf("prime=%s\n", p);
+ benchRaw(tbl[i], mcl::fp::FP_GMP);
+ benchRaw(tbl[i], mcl::fp::FP_GMP_MONT);
+#ifdef MCL_USE_LLVM
+ benchRaw(tbl[i], mcl::fp::FP_LLVM);
+ benchRaw(tbl[i], mcl::fp::FP_LLVM_MONT);
+#endif
+#ifdef MCL_USE_XBYAK
+ if (bitSize <= 384) {
+ benchRaw(tbl[i], mcl::fp::FP_XBYAK);
+ }
+#endif
+ }
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+ return 1;
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/sample/she_make_dlp_table.cpp b/vendor/github.com/dexon-foundation/mcl/sample/she_make_dlp_table.cpp
new file mode 100644
index 000000000..41f18e225
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/sample/she_make_dlp_table.cpp
@@ -0,0 +1,69 @@
+/*
+ make she DLP table
+*/
+#include <mcl/she.hpp>
+#include <cybozu/option.hpp>
+#include <fstream>
+
+using namespace mcl::she;
+
+struct Param {
+ int curveType;
+ int hashBitSize;
+ int group;
+ std::string path;
+};
+
+template<class HashTable, class G>
+void makeTable(const Param& param, const char *groupStr, HashTable& hashTbl, const G& P)
+{
+ char baseName[32];
+ CYBOZU_SNPRINTF(baseName, sizeof(baseName), "she-dlp-%d-%d-%s.bin", param.curveType, param.hashBitSize, groupStr);
+ const std::string fileName = param.path + baseName;
+ printf("file=%s\n", fileName.c_str());
+ std::ofstream ofs(fileName.c_str(), std::ios::binary);
+
+ const size_t hashSize = 1u << param.hashBitSize;
+ hashTbl.init(P, hashSize);
+ hashTbl.save(ofs);
+}
+
+void run(const Param& param)
+{
+ SHE::init(mcl::getCurveParam(param.curveType));
+
+ switch (param.group) {
+ case 1:
+ makeTable(param, "g1", getHashTableG1(), SHE::P_);
+ break;
+ case 2:
+ makeTable(param, "g2", getHashTableG2(), SHE::Q_);
+ break;
+ case 3:
+ makeTable(param, "gt", getHashTableGT(), SHE::ePQ_);
+ break;
+ default:
+ throw cybozu::Exception("bad group") << param.group;
+ }
+}
+
+int main(int argc, char *argv[])
+ try
+{
+ cybozu::Option opt;
+ Param param;
+ opt.appendOpt(&param.curveType, 0, "ct", ": curveType(0:BN254, 1:BN381_1, 5:BLS12_381)");
+ opt.appendOpt(&param.hashBitSize, 20, "hb", ": hash bit size");
+ opt.appendOpt(&param.group, 3, "g", ": group(1:G1, 2:G2, 3:GT");
+ opt.appendOpt(&param.path, "./", "path", ": path to table");
+ opt.appendHelp("h");
+ if (opt.parse(argc, argv)) {
+ run(param);
+ } else {
+ opt.usage();
+ return 1;
+ }
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return 1;
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/sample/she_smpl.cpp b/vendor/github.com/dexon-foundation/mcl/sample/she_smpl.cpp
new file mode 100644
index 000000000..e01b9c130
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/sample/she_smpl.cpp
@@ -0,0 +1,125 @@
+/*
+ sample of somewhat homomorphic encryption(SHE)
+*/
+#define PUT(x) std::cout << #x << "=" << (x) << std::endl;
+#include <cybozu/benchmark.hpp>
+#include <mcl/she.hpp>
+
+using namespace mcl::she;
+
+void miniSample()
+{
+ // init library
+ SHE::init();
+
+ SecretKey sec;
+
+ // init secret key by random_device
+ sec.setByCSPRNG();
+
+ // set range to decode GT DLP
+ SHE::setRangeForDLP(1000);
+
+ PublicKey pub;
+ // get public key
+ sec.getPublicKey(pub);
+
+ const int N = 5;
+ int a[] = { 1, 5, -3, 4, 6 };
+ int b[] = { 4, 2, 1, 9, -2 };
+ // compute correct value
+ int sum = 0;
+ for (size_t i = 0; i < N; i++) {
+ sum += a[i] * b[i];
+ }
+
+ std::vector<CipherText> ca(N), cb(N);
+
+ // encrypt each a[] and b[]
+ for (size_t i = 0; i < N; i++) {
+ pub.enc(ca[i], a[i]);
+ pub.enc(cb[i], b[i]);
+ }
+ CipherText c;
+ c.clearAsMultiplied(); // clear as multiplied before using c.add()
+ // inner product of encrypted vector
+ for (size_t i = 0; i < N; i++) {
+ CipherText t;
+ CipherText::mul(t, ca[i], cb[i]); // t = ca[i] * cb[i]
+ c.add(t); // c += t
+ }
+ // decode it
+ int m = (int)sec.dec(c);
+ // verify the value
+ if (m == sum) {
+ puts("ok");
+ } else {
+ printf("err correct %d err %d\n", sum, m);
+ }
+}
+
+void usePrimitiveCipherText()
+{
+ // init library
+ SHE::init();
+
+ SecretKey sec;
+
+ // init secret key by random_device
+ sec.setByCSPRNG();
+
+ // set range to decode GT DLP
+ SHE::setRangeForGTDLP(100);
+
+ PublicKey pub;
+ // get public key
+ sec.getPublicKey(pub);
+
+ int a1 = 1, a2 = 2;
+ int b1 = 5, b2 = -4;
+ CipherTextG1 c1, c2; // size of CipherTextG1 = N * 2 ; N = 256-bit for CurveFp254BNb
+ CipherTextG2 d1, d2; // size of CipherTextG2 = N * 4
+ pub.enc(c1, a1);
+ pub.enc(c2, a2);
+ pub.enc(d1, b1);
+ pub.enc(d2, b2);
+ c1.add(c2); // CipherTextG1 is additive HE
+ d1.add(d2); // CipherTextG2 is additive HE
+ CipherTextGT cm; // size of CipherTextGT = N * 12 * 4
+ CipherTextGT::mul(cm, c1, d1); // cm = c1 * d1
+ cm.add(cm); // 2cm
+ int m = (int)sec.dec(cm);
+ int ok = (a1 + a2) * (b1 + b2) * 2;
+ if (m == ok) {
+ puts("ok");
+ } else {
+ printf("err m=%d ok=%d\n", m, ok);
+ }
+ std::string s;
+ s = c1.getStr(mcl::IoSerialize); // serialize
+ printf("c1 data size %d byte\n", (int)s.size());
+
+ c2.setStr(s, mcl::IoSerialize);
+ printf("deserialize %s\n", c1 == c2 ? "ok" : "ng");
+
+ s = d1.getStr(mcl::IoSerialize); // serialize
+ printf("d1 data size %d byte\n", (int)s.size());
+ d2.setStr(s, mcl::IoSerialize);
+ printf("deserialize %s\n", d1 == d2 ? "ok" : "ng");
+
+ s = cm.getStr(mcl::IoSerialize); // serialize
+ printf("cm data size %d byte\n", (int)s.size());
+ CipherTextGT cm2;
+ cm2.setStr(s, mcl::IoSerialize);
+ printf("deserialize %s\n", cm == cm2 ? "ok" : "ng");
+}
+
+int main()
+ try
+{
+ miniSample();
+ usePrimitiveCipherText();
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return 1;
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/sample/tri-dh.cpp b/vendor/github.com/dexon-foundation/mcl/sample/tri-dh.cpp
new file mode 100644
index 000000000..8b720edbf
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/sample/tri-dh.cpp
@@ -0,0 +1,97 @@
+/*
+ tripartie Diffie-Hellman
+*/
+#include <iostream>
+#include <fstream>
+#include <cybozu/random_generator.hpp>
+#include <mcl/bn256.hpp>
+#include <cybozu/option.hpp>
+
+static cybozu::RandomGenerator rg;
+
+const std::string skSuf = ".sk.txt";
+const std::string pkSuf = ".pk.txt";
+
+using namespace mcl::bn256;
+
+void keygen(const std::string& user)
+{
+ if (user.empty()) {
+ throw cybozu::Exception("keygen:user is empty");
+ }
+ const char *aa = "12723517038133731887338407189719511622662176727675373276651903807414909099441";
+ const char *ab = "4168783608814932154536427934509895782246573715297911553964171371032945126671";
+ const char *ba = "13891744915211034074451795021214165905772212241412891944830863846330766296736";
+ const char *bb = "7937318970632701341203597196594272556916396164729705624521405069090520231616";
+
+
+ initPairing();
+ G2 Q(Fp2(aa, ab), Fp2(ba, bb));
+ G1 P(-1, 1);
+
+ Fr s;
+ s.setRand(rg);
+ G1::mul(P, P, s);
+ G2::mul(Q, Q, s);
+ {
+ std::string name = user + skSuf;
+ std::ofstream ofs(name.c_str(), std::ios::binary);
+ ofs << s << std::endl;
+ }
+ {
+ std::string name = user + pkSuf;
+ std::ofstream ofs(name.c_str(), std::ios::binary);
+ ofs << P << std::endl;
+ ofs << Q << std::endl;
+ }
+}
+
+void load(G1& P, G2& Q, const std::string& fileName)
+{
+ std::ifstream ifs(fileName.c_str(), std::ios::binary);
+ ifs >> P >> Q;
+}
+
+void share(const std::string& skFile, const std::string& pk1File, const std::string& pk2File)
+{
+ initPairing();
+ Fr s;
+ G1 P1, P2;
+ G2 Q1, Q2;
+ {
+ std::ifstream ifs(skFile.c_str(), std::ios::binary);
+ ifs >> s;
+ }
+ load(P1, Q1, pk1File);
+ load(P2, Q2, pk2File);
+ Fp12 e;
+ pairing(e, P1, Q2);
+ {
+ // verify(not necessary)
+ Fp12 e2;
+ pairing(e2, P2, Q1);
+ if (e != e2) {
+ throw cybozu::Exception("share:bad public key file") << e << e2;
+ }
+ }
+ Fp12::pow(e, e, s);
+ std::cout << "share key:\n" << e << std::endl;
+}
+
+int main(int argc, char *argv[])
+ try
+{
+ if (argc == 3 && strcmp(argv[1], "keygen") == 0) {
+ keygen(argv[2]);
+ } else if (argc == 5 && strcmp(argv[1], "share") == 0) {
+ share(argv[2], argv[3], argv[4]);
+ } else {
+ fprintf(stderr, "tri-dh.exe keygen <user name>\n");
+ fprintf(stderr, "tri-dh.exe share <secret key file> <public key1 file> <public key2 file>\n");
+ return 1;
+ }
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+ return 1;
+}
+
diff --git a/vendor/github.com/dexon-foundation/mcl/sample/vote.cpp b/vendor/github.com/dexon-foundation/mcl/sample/vote.cpp
new file mode 100644
index 000000000..88137187c
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/sample/vote.cpp
@@ -0,0 +1,206 @@
+/*
+ vote sample tool
+ Copyright (c) 2014, National Institute of Advanced Industrial
+ Science and Technology All rights reserved.
+ This source file is subject to BSD 3-Clause license.
+
+ modifyed for mcl by herumi
+*/
+#include <iostream>
+#include <fstream>
+#include <cybozu/random_generator.hpp>
+#include <cybozu/option.hpp>
+#include <cybozu/itoa.hpp>
+#include <mcl/fp.hpp>
+#include <mcl/ec.hpp>
+#include <mcl/elgamal.hpp>
+#include <mcl/ecparam.hpp>
+
+typedef mcl::FpT<> Fp;
+typedef mcl::FpT<mcl::ZnTag> Zn; // use ZnTag because Zn is different class with Fp
+typedef mcl::EcT<Fp> Ec;
+typedef mcl::ElgamalT<Ec, Zn> Elgamal;
+
+cybozu::RandomGenerator rg;
+
+const std::string pubFile = "vote_pub.txt";
+const std::string prvFile = "vote_prv.txt";
+const std::string resultFile = "vote_ret.txt";
+
+std::string GetSheetName(size_t n)
+{
+ return std::string("vote_") + cybozu::itoa(n) + ".txt";
+}
+
+struct Param {
+ std::string mode;
+ std::string voteList;
+ Param(int argc, const char *const argv[])
+ {
+ cybozu::Option opt;
+ opt.appendOpt(&voteList, "11001100", "l", ": list of voters for vote mode(eg. 11001100)");
+ opt.appendHelp("h", ": put this message");
+ opt.appendParam(&mode, "mode", ": init/vote/count/open");
+ if (!opt.parse(argc, argv)) {
+ opt.usage();
+ exit(1);
+ }
+ printf("mode=%s\n", mode.c_str());
+ if (mode == "vote") {
+ printf("voters=%s\n", voteList.c_str());
+ size_t pos = voteList.find_first_not_of("01");
+ if (pos != std::string::npos) {
+ printf("bad char %c\n", voteList[pos]);
+ exit(1);
+ }
+ }
+ }
+};
+
+void SysInit()
+{
+ const mcl::EcParam& para = mcl::ecparam::secp192k1;
+ Zn::init(para.n);
+ Fp::init(para.p);
+ Ec::init(para.a, para.b);
+}
+
+template<class T>
+bool Load(T& t, const std::string& name, bool doThrow = true)
+{
+ std::ifstream ifs(name.c_str(), std::ios::binary);
+ if (!ifs) {
+ if (doThrow) throw cybozu::Exception("Load:can't read") << name;
+ return false;
+ }
+ if (ifs >> t) return true;
+ if (doThrow) throw cybozu::Exception("Load:bad data") << name;
+ return false;
+}
+
+template<class T>
+void Save(const std::string& name, const T& t)
+{
+ std::ofstream ofs(name.c_str(), std::ios::binary);
+ ofs << t;
+}
+
+void Init()
+{
+ const mcl::EcParam& para = mcl::ecparam::secp192k1;
+ const Fp x0(para.gx);
+ const Fp y0(para.gy);
+ const Ec P(x0, y0);
+ const size_t bitSize = para.bitSize;
+
+ Elgamal::PrivateKey prv;
+ prv.init(P, bitSize, rg);
+ const Elgamal::PublicKey& pub = prv.getPublicKey();
+ printf("make privateKey=%s, publicKey=%s\n", prvFile.c_str(), pubFile.c_str());
+ Save(prvFile, prv);
+ Save(pubFile, pub);
+}
+
+struct CipherWithZkp {
+ Elgamal::CipherText c;
+ Elgamal::Zkp zkp;
+ bool verify(const Elgamal::PublicKey& pub) const
+ {
+ return pub.verify(c, zkp);
+ }
+};
+
+inline std::ostream& operator<<(std::ostream& os, const CipherWithZkp& self)
+{
+ return os << self.c << std::endl << self.zkp;
+}
+inline std::istream& operator>>(std::istream& is, CipherWithZkp& self)
+{
+ return is >> self.c >> self.zkp;
+}
+
+void Vote(const std::string& voteList)
+{
+ Elgamal::PublicKey pub;
+ Load(pub, pubFile);
+ puts("shuffle");
+ std::vector<size_t> idxTbl(voteList.size());
+ for (size_t i = 0; i < idxTbl.size(); i++) {
+ idxTbl[i] = i;
+ }
+ cybozu::shuffle(idxTbl, rg);
+ puts("each voter votes");
+ for (size_t i = 0; i < voteList.size(); i++) {
+ CipherWithZkp c;
+ pub.encWithZkp(c.c, c.zkp, voteList[i] - '0', rg);
+ const std::string sheetName = GetSheetName(idxTbl[i]);
+ printf("make %s\n", sheetName.c_str());
+ Save(sheetName, c);
+ }
+}
+
+void Count()
+{
+ Elgamal::PublicKey pub;
+ Load(pub, pubFile);
+ Elgamal::CipherText result;
+ puts("aggregate votes");
+ for (size_t i = 0; ; i++) {
+ const std::string sheetName = GetSheetName(i);
+ CipherWithZkp c;
+ if (!Load(c, sheetName, false)) break;
+ if (!c.verify(pub)) throw cybozu::Exception("bad cipher text") << i;
+ printf("add %s\n", sheetName.c_str());
+ result.add(c.c);
+ }
+ printf("create result file : %s\n", resultFile.c_str());
+ Save(resultFile, result);
+}
+
+void Open()
+{
+ Elgamal::PrivateKey prv;
+ Load(prv, prvFile);
+ Elgamal::CipherText c;
+ Load(c, resultFile);
+ Zn n;
+ prv.dec(n, c);
+ std::cout << "result of vote count " << n << std::endl;
+#if 0
+ puts("open real value");
+ for (size_t i = 0; ; i++) {
+ Elgamal::CipherText c;
+ const std::string sheetName = GetSheetName(i);
+ if (!Load(c, sheetName, false)) break;
+ Zn n;
+ prv.dec(n, c);
+ std::cout << sheetName << " " << n << std::endl;
+ }
+#endif
+}
+
+int main(int argc, char *argv[])
+ try
+{
+ const Param p(argc, argv);
+ SysInit();
+ if (p.mode == "init") {
+ Init();
+ } else
+ if (p.mode == "vote") {
+ Vote(p.voteList);
+ } else
+ if (p.mode == "count") {
+ Count();
+ } else
+ if (p.mode == "open") {
+ Open();
+ } else
+ {
+ printf("bad mode=%s\n", p.mode.c_str());
+ return 1;
+ }
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+}
+
diff --git a/vendor/github.com/dexon-foundation/mcl/src/bn_c256.cpp b/vendor/github.com/dexon-foundation/mcl/src/bn_c256.cpp
index 5c3007410..2f975a287 100644
--- a/vendor/github.com/dexon-foundation/mcl/src/bn_c256.cpp
+++ b/vendor/github.com/dexon-foundation/mcl/src/bn_c256.cpp
@@ -2,5 +2,5 @@
implementation of mclBn_* apis
*/
#define MCLBN_FP_UNIT_SIZE 4
-#include "bn_c_impl.hpp"
+#include "mcl/impl/bn_c_impl.hpp"
diff --git a/vendor/github.com/dexon-foundation/mcl/src/bn_c384.cpp b/vendor/github.com/dexon-foundation/mcl/src/bn_c384.cpp
index 067e728f1..934a078ae 100644
--- a/vendor/github.com/dexon-foundation/mcl/src/bn_c384.cpp
+++ b/vendor/github.com/dexon-foundation/mcl/src/bn_c384.cpp
@@ -3,5 +3,5 @@
*/
#define MCLBN_FP_UNIT_SIZE 6
#define MCLBN_FR_UNIT_SIZE 6
-#include "bn_c_impl.hpp"
+#include "mcl/impl/bn_c_impl.hpp"
diff --git a/vendor/github.com/dexon-foundation/mcl/src/bn_c384_256.cpp b/vendor/github.com/dexon-foundation/mcl/src/bn_c384_256.cpp
index 5630e831d..ecd968efd 100644
--- a/vendor/github.com/dexon-foundation/mcl/src/bn_c384_256.cpp
+++ b/vendor/github.com/dexon-foundation/mcl/src/bn_c384_256.cpp
@@ -3,5 +3,5 @@
*/
#define MCLBN_FP_UNIT_SIZE 6
#define MCLBN_FR_UNIT_SIZE 4
-#include "bn_c_impl.hpp"
+#include "mcl/impl/bn_c_impl.hpp"
diff --git a/vendor/github.com/dexon-foundation/mcl/src/bn_c512.cpp b/vendor/github.com/dexon-foundation/mcl/src/bn_c512.cpp
index 90be2d9bc..7c1029522 100644
--- a/vendor/github.com/dexon-foundation/mcl/src/bn_c512.cpp
+++ b/vendor/github.com/dexon-foundation/mcl/src/bn_c512.cpp
@@ -2,5 +2,5 @@
implementation of mclBn_* apis
*/
#define MCLBN_FP_UNIT_SIZE 8
-#include "bn_c_impl.hpp"
+#include "mcl/impl/bn_c_impl.hpp"
diff --git a/vendor/github.com/dexon-foundation/mcl/src/fp.cpp b/vendor/github.com/dexon-foundation/mcl/src/fp.cpp
index bea1dff72..df72d6d07 100644
--- a/vendor/github.com/dexon-foundation/mcl/src/fp.cpp
+++ b/vendor/github.com/dexon-foundation/mcl/src/fp.cpp
@@ -1,10 +1,6 @@
#include <mcl/op.hpp>
#include <mcl/util.hpp>
-#ifdef MCL_DONT_USE_OPENSSL
#include <cybozu/sha2.hpp>
-#else
-#include <cybozu/crypto.hpp>
-#endif
#include <cybozu/endian.hpp>
#include <mcl/conversion.hpp>
#ifdef MCL_USE_XBYAK
@@ -120,44 +116,16 @@ bool isEnableJIT()
#endif
}
-void getRandVal(Unit *out, RandGen& rg, const Unit *in, size_t bitSize)
-{
- if (rg.isZero()) rg = RandGen::get();
- const size_t n = (bitSize + UnitBitSize - 1) / UnitBitSize;
- const size_t rem = bitSize & (UnitBitSize - 1);
- assert(n > 0);
- for (;;) {
- rg.read(out, n * sizeof(Unit));
- if (rem > 0) out[n - 1] &= (Unit(1) << rem) - 1;
- if (isLessArray(out, in, n)) return;
- }
-}
-
uint32_t sha256(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize)
{
- const uint32_t hashSize = 256 / 8;
- if (maxOutSize < hashSize) return 0;
-#ifdef MCL_DONT_USE_OPENSSL
- cybozu::Sha256(msg, msgSize).get(out);
-#else
- cybozu::crypto::Hash::digest(out, cybozu::crypto::Hash::N_SHA256, msg, msgSize);
-#endif
- return hashSize;
+ return (uint32_t)cybozu::Sha256().digest(out, maxOutSize, msg, msgSize);
}
uint32_t sha512(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize)
{
- const uint32_t hashSize = 512 / 8;
- if (maxOutSize < hashSize) return 0;
-#ifdef MCL_DONT_USE_OPENSSL
- cybozu::Sha512(msg, msgSize).get(out);
-#else
- cybozu::crypto::Hash::digest(out, cybozu::crypto::Hash::N_SHA512, msg, msgSize);
-#endif
- return hashSize;
+ return (uint32_t)cybozu::Sha512().digest(out, maxOutSize, msg, msgSize);
}
-
#ifndef MCL_USE_VINT
static inline void set_mpz_t(mpz_t& z, const Unit* p, int n)
{
@@ -350,9 +318,9 @@ static bool initForMont(Op& op, const Unit *p, Mode mode)
if (mode != FP_XBYAK) return true;
#ifdef MCL_USE_XBYAK
if (op.fg == 0) op.fg = Op::createFpGenerator();
- op.fg->init(op);
+ bool useXbyak = op.fg->init(op);
- if (op.isMont && N <= 4) {
+ if (useXbyak && op.isMont && N <= 4) {
op.fp_invOp = &invOpForMontC;
initInvTbl(op);
}
@@ -360,7 +328,7 @@ static bool initForMont(Op& op, const Unit *p, Mode mode)
return true;
}
-bool Op::init(const mpz_class& _p, size_t maxBitSize, Mode mode, size_t mclMaxBitSize)
+bool Op::init(const mpz_class& _p, size_t maxBitSize, int _xi_a, Mode mode, size_t mclMaxBitSize)
{
if (mclMaxBitSize != MCL_MAX_BIT_SIZE) return false;
#ifdef MCL_USE_VINT
@@ -382,6 +350,7 @@ bool Op::init(const mpz_class& _p, size_t maxBitSize, Mode mode, size_t mclMaxBi
mp = _p;
bitSize = gmp::getBitSize(mp);
pmod4 = gmp::getUnit(mp, 0) % 4;
+ this->xi_a = _xi_a;
/*
priority : MCL_USE_XBYAK > MCL_USE_LLVM > none
Xbyak > llvm_mont > llvm > gmp_mont > gmp
@@ -497,18 +466,18 @@ bool Op::init(const mpz_class& _p, size_t maxBitSize, Mode mode, size_t mclMaxBi
fpDbl_mod = &mcl::vint::mcl_fpDbl_mod_SECP256K1;
}
#endif
- if (!fp::initForMont(*this, p, mode)) return false;
- {
- bool b;
- sq.set(&b, mp);
- if (!b) return false;
- }
if (N * UnitBitSize <= 256) {
hash = sha256;
} else {
hash = sha512;
}
- return true;
+ {
+ bool b;
+ sq.set(&b, mp);
+ if (!b) return false;
+ }
+ modp.init(mp);
+ return fp::initForMont(*this, p, mode);
}
void copyUnitToByteAsLE(uint8_t *dst, const Unit *src, size_t byteSize)
@@ -560,6 +529,27 @@ int detectIoMode(int ioMode, const std::ios_base& ios)
bool copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, MaskMode maskMode)
{
const size_t fpByteSize = sizeof(Unit) * op.N;
+ if (maskMode == Mod) {
+ if (xByteSize > fpByteSize * 2) return false;
+ mpz_class mx;
+ bool b;
+ gmp::setArray(&b, mx, (const char*)x, xByteSize);
+ if (!b) return false;
+#ifdef MCL_USE_VINT
+ op.modp.modp(mx, mx);
+#else
+ mx %= op.mp;
+#endif
+ const Unit *pmx = gmp::getUnit(mx);
+ size_t i = 0;
+ for (const size_t n = gmp::getUnitSize(mx); i < n; i++) {
+ y[i] = pmx[i];
+ }
+ for (; i < op.N; i++) {
+ y[i] = 0;
+ }
+ return true;
+ }
if (xByteSize > fpByteSize) {
if (maskMode == NoMask) return false;
xByteSize = fpByteSize;
@@ -652,10 +642,5 @@ int64_t getInt64(bool *pb, fp::Block& b, const fp::Op& op)
#pragma warning(pop)
#endif
-void Op::initFp2(int _xi_a)
-{
- this->xi_a = _xi_a;
-}
-
} } // mcl::fp
diff --git a/vendor/github.com/dexon-foundation/mcl/src/fp_generator.hpp b/vendor/github.com/dexon-foundation/mcl/src/fp_generator.hpp
index 581a0de87..b496bc4d4 100644
--- a/vendor/github.com/dexon-foundation/mcl/src/fp_generator.hpp
+++ b/vendor/github.com/dexon-foundation/mcl/src/fp_generator.hpp
@@ -8,6 +8,7 @@
*/
#if CYBOZU_HOST == CYBOZU_HOST_INTEL
#define XBYAK_NO_OP_NAMES
+#define XBYAK_DISABLE_AVX512
#include "xbyak/xbyak_util.h"
#if MCL_SIZEOF_UNIT == 8
@@ -126,6 +127,71 @@ if (rm.isReg()) { \
namespace fp {
+struct Profiler {
+ FILE *fp_;
+ const char *suf_;
+ const uint8_t *prev_;
+ Profiler()
+ : fp_(0)
+ , suf_(0)
+ , prev_(0)
+ {
+ }
+ void init(const char *suf, const uint8_t *prev)
+ {
+#ifdef __linux__
+ close();
+ const char *s = getenv("MCL_PERF");
+ if (s == 0 || strcmp(s, "1") != 0) return;
+ fprintf(stderr, "use perf suf=%s\n", suf);
+ suf_ = suf;
+ const int pid = getpid();
+ char name[128];
+ snprintf(name, sizeof(name), "/tmp/perf-%d.map", pid);
+ fp_ = fopen(name, "wb");
+ if (fp_ == 0) throw cybozu::Exception("PerMap") << name;
+ prev_ = prev;
+#else
+ (void)suf;
+ (void)prev;
+#endif
+ }
+ ~Profiler()
+ {
+ close();
+ }
+ void close()
+ {
+#ifdef __linux__
+ if (fp_ == 0) return;
+ fclose(fp_);
+ fp_ = 0;
+ prev_ = 0;
+#endif
+ }
+ void set(const uint8_t *p, size_t n, const char *name) const
+ {
+#ifdef __linux__
+ if (fp_ == 0) return;
+ fprintf(fp_, "%llx %zx %s%s\n", (long long)p, n, name, suf_);
+#else
+ (void)p;
+ (void)n;
+ (void)name;
+#endif
+ }
+ void set(const char *name, const uint8_t *cur)
+ {
+#ifdef __linux__
+ set(prev_, cur - prev_, name);
+ prev_ = cur;
+#else
+ (void)name;
+ (void)cur;
+#endif
+ }
+};
+
struct FpGenerator : Xbyak::CodeGenerator {
typedef Xbyak::RegExp RegExp;
typedef Xbyak::Reg64 Reg64;
@@ -192,28 +258,17 @@ struct FpGenerator : Xbyak::CodeGenerator {
const Reg64& gt8;
const Reg64& gt9;
const mcl::fp::Op *op_;
- Label *pL_; // valid only in init_inner
+ Label pL_; // pointer to p
+ // the following labels assume sf(this, 3, 10 | UseRDX)
+ Label mulPreL;
+ Label fpDbl_modL;
+ Label fp_mulL;
const uint64_t *p_;
uint64_t rp_;
int pn_;
int FpByte_;
bool isFullBit_;
- // add/sub without carry. return true if overflow
- typedef bool (*bool3op)(uint64_t*, const uint64_t*, const uint64_t*);
-
- // add/sub with mod
-// typedef void (*void3op)(uint64_t*, const uint64_t*, const uint64_t*);
-
- // mul without carry. return top of z
- typedef uint64_t (*uint3opI)(uint64_t*, const uint64_t*, uint64_t);
-
- // neg
- typedef void (*void2op)(uint64_t*, const uint64_t*);
-
- // preInv
- typedef int (*int2op)(uint64_t*, const uint64_t*);
- void4u mul_;
-// uint3opI mulUnit_;
+ Profiler prof_;
/*
@param op [in] ; use op.p, op.N, op.isFullBit
@@ -248,34 +303,25 @@ struct FpGenerator : Xbyak::CodeGenerator {
, rp_(0)
, pn_(0)
, FpByte_(0)
- , mul_(0)
-// , mulUnit_(0)
{
useMulx_ = cpu_.has(Xbyak::util::Cpu::tBMI2);
useAdx_ = cpu_.has(Xbyak::util::Cpu::tADX);
}
- void init(Op& op)
+ bool init(Op& op)
{
+ if (!cpu_.has(Xbyak::util::Cpu::tAVX)) return false;
reset(); // reset jit code for reuse
setProtectModeRW(); // read/write memory
init_inner(op);
+// printf("code size=%d\n", (int)getSize());
setProtectModeRE(); // set read/exec memory
+ return true;
}
private:
void init_inner(Op& op)
{
- // the following labels assume sf(this, 3, 10 | UseRDX)
- Label mulPreL;
- Label fpDbl_modL;
- Label fp_mulL;
- Label pL; // label to p_
op_ = &op;
- pL_ = &pL;
- /*
- first 4096-byte is data area
- remain is code area
- */
- L(pL);
+ L(pL_);
p_ = reinterpret_cast<const uint64_t*>(getCurr());
for (size_t i = 0; i < op.N; i++) {
dq(op.p[i]);
@@ -285,167 +331,101 @@ private:
FpByte_ = int(op.maxN * sizeof(uint64_t));
isFullBit_ = op.isFullBit;
// printf("p=%p, pn_=%d, isFullBit_=%d\n", p_, pn_, isFullBit_);
- // code from here
- setSize(4096);
- assert((getCurr<size_t>() & 4095) == 0);
- op.fp_addPre = getCurr<u3u>();
- gen_addSubPre(true, pn_);
- align(16);
- op.fp_subPre = getCurr<u3u>();
- gen_addSubPre(false, pn_);
- align(16);
- op.fp_sub = getCurr<void4u>();
- op.fp_subA_ = getCurr<void3u>();
- gen_fp_sub();
- align(16);
- op.fp_add = getCurr<void4u>();
- op.fp_addA_ = getCurr<void3u>();
- gen_fp_add();
+ static char suf[] = "_0";
+ prof_.init(suf, getCurr());
+ suf[1]++;
- align(16);
- op.fp_shr1 = getCurr<void2u>();
- gen_shr1();
+ op.fp_addPre = gen_addSubPre(true, pn_);
+ prof_.set("Fp_addPre", getCurr());
- align(16);
- op.fp_negA_ = getCurr<void2u>();
- gen_fp_neg();
+ op.fp_subPre = gen_addSubPre(false, pn_);
+ prof_.set("Fp_subPre", getCurr());
- // setup fp_tower
- op.fp2_mulNF = 0;
- if (pn_ <= 4 || (pn_ == 6 && !isFullBit_)) {
- align(16);
- op.fpDbl_addA_ = getCurr<void3u>();
- gen_fpDbl_add();
- align(16);
- op.fpDbl_subA_ = getCurr<void3u>();
- gen_fpDbl_sub();
- }
- if (op.isFullBit) {
- op.fpDbl_addPre = 0;
- op.fpDbl_subPre = 0;
- } else {
- align(16);
- op.fpDbl_addPreA_ = getCurr<void3u>();
- gen_addSubPre(true, pn_ * 2);
- align(16);
- op.fpDbl_subPreA_ = getCurr<void3u>();
- gen_addSubPre(false, pn_ * 2);
- }
- if ((useMulx_ && op.N == 2) || op.N == 3 || op.N == 4 || (useAdx_ && op.N == 6)) {
- align(16);
- op.fpDbl_mulPreA_ = getCurr<void3u>();
- if (op.N == 4) {
- /*
- fpDbl_mulPre is available as C function
- this function calls mulPreL directly.
- */
- StackFrame sf(this, 3, 10 | UseRDX, 0, false);
- mulPre4(gp0, gp1, gp2, sf.t);
- sf.close(); // make epilog
- L(mulPreL); // called only from asm code
- mulPre4(gp0, gp1, gp2, sf.t);
- ret();
- } else if (op.N == 6 && useAdx_) {
-#if 1
- StackFrame sf(this, 3, 7 | UseRDX, 0, false);
- mulPre6(gp0, gp1, gp2, sf.t);
- sf.close(); // make epilog
- L(mulPreL); // called only from asm code
- mulPre6(gp0, gp1, gp2, sf.t);
- ret();
-#else
- {
- StackFrame sf(this, 3, 7 | UseRDX);
- mulPre6(gp0, gp1, gp2, sf.t);
- }
- {
- StackFrame sf(this, 3, 10 | UseRDX, 0, false);
- L(mulPreL); // called only from asm code
- mulPre6(gp0, gp1, gp2, sf.t);
- ret();
- }
-#endif
- } else {
- gen_fpDbl_mulPre();
- }
- }
- if (op.N == 2 || op.N == 3 || op.N == 4 || (op.N == 6 && !isFullBit_ && useAdx_)) {
- align(16);
- op.fpDbl_modA_ = getCurr<void2u>();
- if (op.N == 4) {
- StackFrame sf(this, 3, 10 | UseRDX, 0, false);
- call(fpDbl_modL);
- sf.close();
- L(fpDbl_modL);
- gen_fpDbl_mod4(gp0, gp1, sf.t, gp2);
- ret();
- } else if (op.N == 6 && !isFullBit_ && useAdx_) {
- StackFrame sf(this, 3, 10 | UseRDX, 0, false);
- call(fpDbl_modL);
- sf.close();
- L(fpDbl_modL);
- Pack t = sf.t;
- t.append(gp2);
- gen_fpDbl_mod6(gp0, gp1, t);
- ret();
- } else {
- gen_fpDbl_mod(op);
- }
- }
- if (op.N > 4) return;
- if ((useMulx_ && op.N == 2) || op.N == 3 || op.N == 4) {
- align(16);
- op.fpDbl_sqrPreA_ = getCurr<void2u>();
- gen_fpDbl_sqrPre(op);
+ op.fp_addA_ = gen_fp_add();
+ prof_.set("Fp_add", getCurr());
+
+ op.fp_subA_ = gen_fp_sub();
+ prof_.set("Fp_sub", getCurr());
+
+ op.fp_shr1 = gen_shr1();
+ prof_.set("Fp_shr1", getCurr());
+
+ op.fp_negA_ = gen_fp_neg();
+ prof_.set("Fp_neg", getCurr());
+
+ op.fpDbl_addA_ = gen_fpDbl_add();
+ prof_.set("FpDbl_add", getCurr());
+
+ op.fpDbl_subA_ = gen_fpDbl_sub();
+ prof_.set("FpDbl_sub", getCurr());
+
+ op.fpDbl_addPre = gen_addSubPre(true, pn_ * 2);
+ prof_.set("FpDbl_addPre", getCurr());
+
+ op.fpDbl_subPre = gen_addSubPre(false, pn_ * 2);
+ prof_.set("FpDbl_subPre", getCurr());
+
+ op.fpDbl_mulPreA_ = gen_fpDbl_mulPre();
+ prof_.set("FpDbl_mulPre", getCurr());
+
+ op.fpDbl_sqrPreA_ = gen_fpDbl_sqrPre();
+ prof_.set("FpDbl_sqrPre", getCurr());
+
+ op.fpDbl_modA_ = gen_fpDbl_mod(op);
+ prof_.set("FpDbl_mod", getCurr());
+
+ op.fp_mulA_ = gen_mul();
+ prof_.set("Fp_mul", getCurr());
+ if (op.fp_mulA_) {
+ op.fp_mul = fp::func_ptr_cast<void4u>(op.fp_mulA_); // used in toMont/fromMont
}
- align(16);
- op.fp_mul = getCurr<void4u>(); // used in toMont/fromMont
- op.fp_mulA_ = getCurr<void3u>();
- gen_mul(fp_mulL);
-// if (op.N > 4) return;
- align(16);
- op.fp_sqrA_ = getCurr<void2u>();
- gen_sqr();
+ op.fp_sqrA_ = gen_sqr();
+ prof_.set("Fp_sqr", getCurr());
+
if (op.primeMode != PM_NIST_P192 && op.N <= 4) { // support general op.N but not fast for op.N > 4
align(16);
op.fp_preInv = getCurr<int2u>();
gen_preInv();
+ prof_.set("preInv", getCurr());
}
- if (op.N == 4 && !isFullBit_) {
- align(16);
- op.fp2_addA_ = getCurr<void3u>();
- gen_fp2_add4();
- align(16);
- op.fp2_subA_ = getCurr<void3u>();
- gen_fp2_sub4();
- align(16);
- op.fp2_negA_ = getCurr<void2u>();
- gen_fp2_neg4();
- align(16);
- op.fp2Dbl_mulPreA_ = getCurr<void3u>();
- gen_fp2Dbl_mulPre(mulPreL);
- align(16);
- op.fp2Dbl_sqrPreA_ = getCurr<void2u>();
- gen_fp2Dbl_sqrPre(mulPreL);
- align(16);
- op.fp2_mulA_ = getCurr<void3u>();
- gen_fp2_mul4(fpDbl_modL);
- align(16);
- op.fp2_sqrA_ = getCurr<void2u>();
- gen_fp2_sqr4(fp_mulL);
- align(16);
- op.fp2_mul_xiA_ = getCurr<void2u>();
- gen_fp2_mul_xi4();
- }
+ if (op.xi_a == 0) return; // Fp2 is not used
+ op.fp2_addA_ = gen_fp2_add();
+ prof_.set("Fp2_add", getCurr());
+
+ op.fp2_subA_ = gen_fp2_sub();
+ prof_.set("Fp2_sub", getCurr());
+
+ op.fp2_negA_ = gen_fp2_neg();
+ prof_.set("Fp2_neg", getCurr());
+
+ op.fp2_mulNF = 0;
+ op.fp2Dbl_mulPreA_ = gen_fp2Dbl_mulPre();
+ prof_.set("Fp2Dbl_mulPre", getCurr());
+
+ op.fp2Dbl_sqrPreA_ = gen_fp2Dbl_sqrPre();
+ prof_.set("Fp2Dbl_sqrPre", getCurr());
+
+ op.fp2_mulA_ = gen_fp2_mul();
+ prof_.set("Fp2_mul", getCurr());
+
+ op.fp2_sqrA_ = gen_fp2_sqr();
+ prof_.set("Fp2_sqr", getCurr());
+
+ op.fp2_mul_xiA_ = gen_fp2_mul_xi();
+ prof_.set("Fp2_mul_xi", getCurr());
}
- void gen_addSubPre(bool isAdd, int n)
+ u3u gen_addSubPre(bool isAdd, int n)
{
+// if (isFullBit_) return 0;
+ align(16);
+ u3u func = getCurr<u3u>();
StackFrame sf(this, 3);
if (isAdd) {
gen_raw_add(sf.p[0], sf.p[1], sf.p[2], rax, n);
} else {
gen_raw_sub(sf.p[0], sf.p[1], sf.p[2], rax, n);
}
+ return func;
}
/*
pz[] = px[] + py[]
@@ -498,7 +478,7 @@ private:
}
jmp(exit);
L(nonZero);
- mov(rax, (size_t)p_);
+ mov(rax, pL_);
for (size_t i = 0; i < t.size(); i++) {
mov(rdx, ptr [rax + i * 8]);
if (i == 0) {
@@ -626,7 +606,7 @@ private:
mov(*fullReg, 0);
adc(*fullReg, 0);
}
- mov(rax, (size_t)p_);
+ mov(rax, pL_);
sub_rm(p1, rax);
if (fullReg) {
sbb(*fullReg, 0);
@@ -646,7 +626,7 @@ private:
const Pack& p1 = t.sub(pn_, pn_);
load_rm(p0, px);
sub_rm(p0, py, withCarry);
- mov(rax, (size_t)p_);
+ mov(rax, pL_);
load_rm(p1, rax);
sbb(rax, rax); // rax = (x > y) ? 0 : -1
for (size_t i = 0; i < p1.size(); i++) {
@@ -676,29 +656,29 @@ private:
gen_raw_fp_sub(pz, px, py, sf.t, false);
}
/*
- add(pz + offset, px + offset, py + offset);
+ add(pz, px, py);
size of t1, t2 == 6
destroy t0, t1
*/
- void gen_raw_fp_add6(const Reg64& pz, const Reg64& px, const Reg64& py, int offset, const Pack& t1, const Pack& t2, bool withCarry)
+ void gen_raw_fp_add6(const RegExp& pz, const RegExp& px, const RegExp& py, const Pack& t1, const Pack& t2, bool withCarry)
{
- load_rm(t1, px + offset);
- add_rm(t1, py + offset, withCarry);
+ load_rm(t1, px);
+ add_rm(t1, py, withCarry);
Label exit;
if (isFullBit_) {
jnc("@f");
- mov(t2[0], *pL_); // t2 is not used
+ mov(t2[0], pL_); // t2 is not used
sub_rm(t1, t2[0]);
jmp(exit);
L("@@");
}
mov_rr(t2, t1);
- sub_rm(t2, rip + *pL_);
+ sub_rm(t2, rip + pL_);
for (int i = 0; i < 6; i++) {
cmovnc(t1[i], t2[i]);
}
L(exit);
- store_mr(pz + offset, t1);
+ store_mr(pz, t1);
}
void gen_fp_add6()
{
@@ -713,17 +693,19 @@ private:
Pack t2 = sf.t.sub(6);
t2.append(rax);
t2.append(px); // destory after used
- gen_raw_fp_add6(pz, px, py, 0, t1, t2, false);
+ gen_raw_fp_add6(pz, px, py, t1, t2, false);
}
- void gen_fp_add()
+ void3u gen_fp_add()
{
+ align(16);
+ void3u func = getCurr<void3u>();
if (pn_ <= 4) {
gen_fp_add_le4();
- return;
+ return func;
}
if (pn_ == 6) {
gen_fp_add6();
- return;
+ return func;
}
StackFrame sf(this, 3, 0, pn_ * 8);
const Reg64& pz = sf.p[0];
@@ -733,7 +715,7 @@ private:
inLocalLabel();
gen_raw_add(pz, px, py, rax, pn_);
- mov(px, (size_t)p_); // destroy px
+ mov(px, pL_); // destroy px
if (isFullBit_) {
jc(".over", jmpMode);
}
@@ -759,9 +741,12 @@ private:
L(".exit");
#endif
outLocalLabel();
+ return func;
}
- void gen_fpDbl_add()
+ void3u gen_fpDbl_add()
{
+ align(16);
+ void3u func = getCurr<void3u>();
if (pn_ <= 4) {
int tn = pn_ * 2 + (isFullBit_ ? 1 : 0);
StackFrame sf(this, 3, tn);
@@ -770,6 +755,7 @@ private:
const Reg64& py = sf.p[2];
gen_raw_add(pz, px, py, rax, pn_);
gen_raw_fp_add(pz + 8 * pn_, px + 8 * pn_, py + 8 * pn_, sf.t, true);
+ return func;
} else if (pn_ == 6 && !isFullBit_) {
StackFrame sf(this, 3, 10);
const Reg64& pz = sf.p[0];
@@ -780,14 +766,15 @@ private:
Pack t2 = sf.t.sub(6);
t2.append(rax);
t2.append(py);
- gen_raw_fp_add6(pz, px, py, pn_ * 8, t1, t2, true);
- } else {
- assert(0);
- exit(1);
+ gen_raw_fp_add6(pz + pn_ * 8, px + pn_ * 8, py + pn_ * 8, t1, t2, true);
+ return func;
}
+ return 0;
}
- void gen_fpDbl_sub()
+ void3u gen_fpDbl_sub()
{
+ align(16);
+ void3u func = getCurr<void3u>();
if (pn_ <= 4) {
int tn = pn_ * 2;
StackFrame sf(this, 3, tn);
@@ -796,6 +783,7 @@ private:
const Reg64& py = sf.p[2];
gen_raw_sub(pz, px, py, rax, pn_);
gen_raw_fp_sub(pz + 8 * pn_, px + 8 * pn_, py + 8 * pn_, sf.t, true);
+ return func;
} else if (pn_ == 6) {
StackFrame sf(this, 3, 4);
const Reg64& pz = sf.p[0];
@@ -806,12 +794,11 @@ private:
t.append(rax);
t.append(px);
gen_raw_fp_sub6(pz, px, py, pn_ * 8, t, true);
- } else {
- assert(0);
- exit(1);
+ return func;
}
+ return 0;
}
- void gen_raw_fp_sub6(const Reg64& pz, const Reg64& px, const Reg64& py, int offset, const Pack& t, bool withCarry)
+ void gen_raw_fp_sub6(const RegExp& pz, const RegExp& px, const RegExp& py, int offset, const Pack& t, bool withCarry)
{
load_rm(t, px + offset);
sub_rm(t, py + offset, withCarry);
@@ -819,7 +806,7 @@ private:
jmp is faster than and-mask without jmp
*/
jnc("@f");
- add_rm(t, rip + *pL_);
+ add_rm(t, rip + pL_);
L("@@");
store_mr(pz + offset, t);
}
@@ -834,15 +821,17 @@ private:
t.append(px); // |t| = 6
gen_raw_fp_sub6(pz, px, py, 0, t, false);
}
- void gen_fp_sub()
+ void3u gen_fp_sub()
{
+ align(16);
+ void3u func = getCurr<void3u>();
if (pn_ <= 4) {
gen_fp_sub_le4();
- return;
+ return func;
}
if (pn_ == 6) {
gen_fp_sub6();
- return;
+ return func;
}
StackFrame sf(this, 3);
const Reg64& pz = sf.p[0];
@@ -852,17 +841,23 @@ private:
Label exit;
gen_raw_sub(pz, px, py, rax, pn_);
jnc(exit, jmpMode);
- mov(px, (size_t)p_);
+ mov(px, pL_);
gen_raw_add(pz, pz, px, rax, pn_);
L(exit);
+ return func;
}
- void gen_fp_neg()
+ void2u gen_fp_neg()
{
+ align(16);
+ void2u func = getCurr<void2u>();
StackFrame sf(this, 2, UseRDX | pn_);
gen_raw_neg(sf.p[0], sf.p[1], sf.t);
+ return func;
}
- void gen_shr1()
+ void2u gen_shr1()
{
+ align(16);
+ void2u func = getCurr<void2u>();
const int c = 1;
StackFrame sf(this, 2, 1);
const Reg64 *t0 = &rax;
@@ -878,25 +873,54 @@ private:
}
shr(*t0, c);
mov(ptr [pz + (pn_ - 1) * 8], *t0);
+ return func;
}
- void gen_mul(Label& fp_mulL)
+ void3u gen_mul()
{
+ align(16);
+ void3u func = getCurr<void3u>();
if (op_->primeMode == PM_NIST_P192) {
StackFrame sf(this, 3, 10 | UseRDX, 8 * 6);
mulPre3(rsp, sf.p[1], sf.p[2], sf.t);
fpDbl_mod_NIST_P192(sf.p[0], rsp, sf.t);
+ return func;
}
if (pn_ == 3) {
- gen_montMul3(p_, rp_);
- } else if (pn_ == 4) {
- gen_montMul4(fp_mulL, p_, rp_);
-// } else if (pn_ == 6 && useAdx_) {
-// gen_montMul6(fp_mulL, p_, rp_);
- } else if (pn_ <= 9) {
+ gen_montMul3();
+ return func;
+ }
+ if (pn_ == 4) {
+ gen_montMul4();
+ return func;
+ }
+ if (pn_ == 6 && !isFullBit_ && useMulx_ && useAdx_) {
+#if 1
+ // a little faster
+ gen_montMul6();
+#else
+ if (mulPreL.getAddress() == 0 || fpDbl_modL.getAddress() == 0) return 0;
+ StackFrame sf(this, 3, 10 | UseRDX, 12 * 8);
+ /*
+ use xm3
+ rsp
+ [0, ..12 * 8) ; mul(x, y)
+ */
+ vmovq(xm3, gp0);
+ mov(gp0, rsp);
+ call(mulPreL); // gp0, x, y
+ vmovq(gp0, xm3);
+ mov(gp1, rsp);
+ call(fpDbl_modL);
+#endif
+ return func;
+ }
+#if 0
+ if (pn_ <= 9) {
gen_montMulN(p_, rp_, pn_);
- } else {
- throw cybozu::Exception("mcl:FpGenerator:gen_mul:not implemented for") << pn_;
+ return func;
}
+#endif
+ return 0;
}
/*
@input (z, xy)
@@ -926,7 +950,7 @@ private:
mov(a, rp_);
mul(t6);
- mov(t0, (uint64_t)p_);
+ mov(t0, pL_);
mov(t7, a); // q
// [d:t7:t1] = p * q
@@ -995,7 +1019,7 @@ private:
mov(a, rp_);
mul(t10);
- mov(t0, (uint64_t)p_);
+ mov(t0, pL_);
mov(t7, a); // q
// [d:t7:t2:t1] = p * q
@@ -1070,12 +1094,12 @@ private:
const Reg64& a = rax;
const Reg64& d = rdx;
- movq(xm0, z);
+ vmovq(xm0, z);
mov(z, ptr [xy + 8 * 0]);
mov(a, rp_);
mul(z);
- mov(t0, (uint64_t)p_);
+ mov(t0, pL_);
mov(t7, a); // q
// [d:t7:t3:t2:t1] = p * q
@@ -1097,7 +1121,7 @@ private:
if (isFullBit_) {
mov(t5, 0);
adc(t5, 0);
- movq(xm2, t5);
+ vmovq(xm2, t5);
}
// free z, t0, t1, t5, t6, xy
@@ -1106,18 +1130,18 @@ private:
mul(t2);
mov(z, a); // q
- movq(xm1, t10);
+ vmovq(xm1, t10);
// [d:z:t5:t6:xy] = p * q
mul4x1(t0, z, t1, t5, t6, xy, t10);
- movq(t10, xm1);
+ vmovq(t10, xm1);
add_rr(Pack(t8, t4, t7, t3, t2), Pack(d, z, t5, t6, xy));
adc(t9, 0);
adc(t10, 0); // [t10:t9:t8:t4:t7:t3]
if (isFullBit_) {
- movq(t5, xm2);
+ vmovq(t5, xm2);
adc(t5, 0);
- movq(xm2, t5);
+ vmovq(xm2, t5);
}
// free z, t0, t1, t2, t5, t6, xy
@@ -1132,7 +1156,7 @@ private:
add_rr(Pack(t9, t8, t4, t7, t3), Pack(d, z, t5, xy, t6));
adc(t10, 0); // c' = [t10:t9:t8:t4:t7]
if (isFullBit_) {
- movq(t3, xm2);
+ vmovq(t3, xm2);
adc(t3, 0);
}
@@ -1161,60 +1185,112 @@ private:
cmovc(t9, t2);
cmovc(t10, t6);
- movq(z, xm0);
+ vmovq(z, xm0);
store_mr(z, Pack(t10, t9, t8, t4));
}
- void gen_fpDbl_mod(const mcl::fp::Op& op)
+ void2u gen_fpDbl_mod(const fp::Op& op)
{
+ align(16);
+ void2u func = getCurr<void2u>();
if (op.primeMode == PM_NIST_P192) {
StackFrame sf(this, 2, 6 | UseRDX);
fpDbl_mod_NIST_P192(sf.p[0], sf.p[1], sf.t);
- return;
+ return func;
}
#if 0
if (op.primeMode == PM_NIST_P521) {
StackFrame sf(this, 2, 8 | UseRDX);
fpDbl_mod_NIST_P521(sf.p[0], sf.p[1], sf.t);
- return;
+ return func;
}
#endif
- switch (pn_) {
- case 2:
+ if (pn_ == 2) {
gen_fpDbl_mod2();
- break;
- case 3:
+ return func;
+ }
+ if (pn_ == 3) {
gen_fpDbl_mod3();
- break;
-#if 0
- case 4:
- {
- StackFrame sf(this, 3, 10 | UseRDX);
- gen_fpDbl_mod4(gp0, gp1, sf.t, gp2);
- }
- break;
-#endif
- default:
- throw cybozu::Exception("gen_fpDbl_mod:not support") << pn_;
+ return func;
+ }
+ if (pn_ == 4) {
+ StackFrame sf(this, 3, 10 | UseRDX, 0, false);
+ call(fpDbl_modL);
+ sf.close();
+ L(fpDbl_modL);
+ gen_fpDbl_mod4(gp0, gp1, sf.t, gp2);
+ ret();
+ return func;
+ }
+ if (pn_ == 6 && !isFullBit_ && useMulx_ && useAdx_) {
+ StackFrame sf(this, 3, 10 | UseRDX, 0, false);
+ call(fpDbl_modL);
+ sf.close();
+ L(fpDbl_modL);
+ Pack t = sf.t;
+ t.append(gp2);
+ gen_fpDbl_mod6(gp0, gp1, t);
+ ret();
+ return func;
}
+ return 0;
}
- void gen_sqr()
+ void2u gen_sqr()
{
+ align(16);
+ void2u func = getCurr<void2u>();
if (op_->primeMode == PM_NIST_P192) {
- StackFrame sf(this, 2, 10 | UseRDX | UseRCX, 8 * 6);
- sqrPre3(rsp, sf.p[1], sf.t);
+ StackFrame sf(this, 3, 10 | UseRDX, 6 * 8);
+ Pack t = sf.t;
+ t.append(sf.p[2]);
+ sqrPre3(rsp, sf.p[1], t);
fpDbl_mod_NIST_P192(sf.p[0], rsp, sf.t);
+ return func;
}
if (pn_ == 3) {
- gen_montSqr3(p_, rp_);
- return;
+ gen_montSqr3();
+ return func;
}
- // sqr(y, x) = mul(y, x, x)
+ if (pn_ == 4 && useMulx_) {
+#if 1
+ // sqr(y, x) = mul(y, x, x)
#ifdef XBYAK64_WIN
- mov(r8, rdx);
+ mov(r8, rdx);
#else
- mov(rdx, rsi);
+ mov(rdx, rsi);
+#endif
+ jmp((const void*)op_->fp_mulA_);
+#else // (sqrPre + mod) is slower than mul
+ StackFrame sf(this, 3, 10 | UseRDX, 8 * 8);
+ Pack t = sf.t;
+ t.append(sf.p[2]);
+ sqrPre4(rsp, sf.p[1], t);
+ mov(gp0, sf.p[0]);
+ mov(gp1, rsp);
+ call(fpDbl_modL);
#endif
- jmp((const void*)op_->fp_mulA_);
+ return func;
+ }
+ if (pn_ == 6 && !isFullBit_ && useMulx_ && useAdx_) {
+ if (fpDbl_modL.getAddress() == 0) return 0;
+ StackFrame sf(this, 3, 10 | UseRDX, (12 + 6) * 8);
+ /*
+ use xm3
+ rsp
+ [6 * 8, (12 + 6) * 8) ; sqrPre(x, x)
+ [0..6 * 8) ; stack for sqrPre6
+ */
+ vmovq(xm3, gp0);
+ Pack t = sf.t;
+ t.append(sf.p[2]);
+ // sqrPre6 uses 6 * 8 bytes stack
+ sqrPre6(rsp + 6 * 8, sf.p[1], t);
+ mov(gp0, ptr[rsp + (12 + 6) * 8]);
+ vmovq(gp0, xm3);
+ lea(gp1, ptr[rsp + 6 * 8]);
+ call(fpDbl_modL);
+ return func;
+ }
+ return 0;
}
/*
input (pz[], px[], py[])
@@ -1259,7 +1335,7 @@ private:
z[0..3] <- montgomery(x[0..3], y[0..3])
destroy gt0, ..., gt9, xm0, xm1, p2
*/
- void gen_montMul4(Label& fp_mulL, const uint64_t *p, uint64_t pp)
+ void gen_montMul4()
{
StackFrame sf(this, 3, 10 | UseRDX, 0, false);
call(fp_mulL);
@@ -1280,23 +1356,23 @@ private:
const Reg64& t9 = sf.t[9];
L(fp_mulL);
- movq(xm0, p0); // save p0
- mov(p0, (uint64_t)p);
- movq(xm1, p2);
+ vmovq(xm0, p0); // save p0
+ mov(p0, pL_);
+ vmovq(xm1, p2);
mov(p2, ptr [p2]);
- montgomery4_1(pp, t0, t7, t3, t2, t1, p1, p2, p0, t4, t5, t6, t8, t9, true, xm2);
+ montgomery4_1(rp_, t0, t7, t3, t2, t1, p1, p2, p0, t4, t5, t6, t8, t9, true, xm2);
- movq(p2, xm1);
+ vmovq(p2, xm1);
mov(p2, ptr [p2 + 8]);
- montgomery4_1(pp, t1, t0, t7, t3, t2, p1, p2, p0, t4, t5, t6, t8, t9, false, xm2);
+ montgomery4_1(rp_, t1, t0, t7, t3, t2, p1, p2, p0, t4, t5, t6, t8, t9, false, xm2);
- movq(p2, xm1);
+ vmovq(p2, xm1);
mov(p2, ptr [p2 + 16]);
- montgomery4_1(pp, t2, t1, t0, t7, t3, p1, p2, p0, t4, t5, t6, t8, t9, false, xm2);
+ montgomery4_1(rp_, t2, t1, t0, t7, t3, p1, p2, p0, t4, t5, t6, t8, t9, false, xm2);
- movq(p2, xm1);
+ vmovq(p2, xm1);
mov(p2, ptr [p2 + 24]);
- montgomery4_1(pp, t3, t2, t1, t0, t7, p1, p2, p0, t4, t5, t6, t8, t9, false, xm2);
+ montgomery4_1(rp_, t3, t2, t1, t0, t7, p1, p2, p0, t4, t5, t6, t8, t9, false, xm2);
// [t7:t3:t2:t1:t0]
mov(t4, t0);
@@ -1310,16 +1386,131 @@ private:
cmovc(t2, t6);
cmovc(t3, rdx);
- movq(p0, xm0); // load p0
+ vmovq(p0, xm0); // load p0
store_mr(p0, Pack(t3, t2, t1, t0));
ret();
}
/*
+ c[n+2] = c[n+1] + px[n] * rdx
+ use rax
+ */
+ void mulAdd(const Pack& c, int n, const RegExp& px)
+ {
+ const Reg64& a = rax;
+ xor_(a, a);
+ for (int i = 0; i < n; i++) {
+ mulx(c[n + 1], a, ptr [px + i * 8]);
+ adox(c[i], a);
+ adcx(c[i + 1], c[n + 1]);
+ }
+ mov(a, 0);
+ mov(c[n + 1], a);
+ adox(c[n], a);
+ adcx(c[n + 1], a);
+ adox(c[n + 1], a);
+ }
+ /*
+ input
+ c[6..0]
+ rdx = yi
+ use rax, rdx
+ output
+ c[7..1]
+
+ if first:
+ c = x[5..0] * rdx
+ else:
+ c += x[5..0] * rdx
+ q = uint64_t(c0 * rp)
+ c += p * q
+ c >>= 64
+ */
+ void montgomery6_1(const Pack& c, const RegExp& px, const Reg64& t0, const Reg64& t1, bool isFirst)
+ {
+ const int n = 6;
+ const Reg64& a = rax;
+ const Reg64& d = rdx;
+ if (isFirst) {
+ const Reg64 *pt0 = &a;
+ const Reg64 *pt1 = &t0;
+ // c[6..0] = px[5..0] * rdx
+ mulx(*pt0, c[0], ptr [px + 0 * 8]);
+ for (int i = 1; i < n; i++) {
+ mulx(*pt1, c[i], ptr[px + i * 8]);
+ if (i == 1) {
+ add(c[i], *pt0);
+ } else {
+ adc(c[i], *pt0);
+ }
+ std::swap(pt0, pt1);
+ }
+ mov(c[n], 0);
+ adc(c[n], *pt0);
+ } else {
+ // c[7..0] = c[6..0] + px[5..0] * rdx
+ mulAdd(c, 6, px);
+ }
+ mov(a, rp_);
+ mul(c[0]); // q = a
+ mov(d, a);
+ mov(t1, pL_);
+ // c += p * q
+ mulAdd(c, 6, t1);
+ }
+ /*
+ input (z, x, y) = (p0, p1, p2)
+ z[0..5] <- montgomery(x[0..5], y[0..5])
+ destroy t0, ..., t9, rax, rdx
+ */
+ void gen_montMul6()
+ {
+ assert(!isFullBit_ && useMulx_ && useAdx_);
+ StackFrame sf(this, 3, 10 | UseRDX, 0, false);
+ call(fp_mulL);
+ sf.close();
+ const Reg64& pz = sf.p[0];
+ const Reg64& px = sf.p[1];
+ const Reg64& py = sf.p[2];
+
+ const Reg64& t0 = sf.t[0];
+ const Reg64& t1 = sf.t[1];
+ const Reg64& t2 = sf.t[2];
+ const Reg64& t3 = sf.t[3];
+ const Reg64& t4 = sf.t[4];
+ const Reg64& t5 = sf.t[5];
+ const Reg64& t6 = sf.t[6];
+ const Reg64& t7 = sf.t[7];
+ const Reg64& t8 = sf.t[8];
+ const Reg64& t9 = sf.t[9];
+ L(fp_mulL);
+ mov(rdx, ptr [py + 0 * 8]);
+ montgomery6_1(Pack(t7, t6, t5, t4, t3, t2, t1, t0), px, t8, t9, true);
+ mov(rdx, ptr [py + 1 * 8]);
+ montgomery6_1(Pack(t0, t7, t6, t5, t4, t3, t2, t1), px, t8, t9, false);
+ mov(rdx, ptr [py + 2 * 8]);
+ montgomery6_1(Pack(t1, t0, t7, t6, t5, t4, t3, t2), px, t8, t9, false);
+ mov(rdx, ptr [py + 3 * 8]);
+ montgomery6_1(Pack(t2, t1, t0, t7, t6, t5, t4, t3), px, t8, t9, false);
+ mov(rdx, ptr [py + 4 * 8]);
+ montgomery6_1(Pack(t3, t2, t1, t0, t7, t6, t5, t4), px, t8, t9, false);
+ mov(rdx, ptr [py + 5 * 8]);
+ montgomery6_1(Pack(t4, t3, t2, t1, t0, t7, t6, t5), px, t8, t9, false);
+ // [t4:t3:t2:t1:t0:t7:t6]
+ const Pack z = Pack(t3, t2, t1, t0, t7, t6);
+ const Pack keep = Pack(rdx, rax, px, py, t8, t9);
+ mov_rr(keep, z);
+ mov(t5, pL_);
+ sub_rm(z, t5);
+ cmovc_rr(z, keep);
+ store_mr(pz, z);
+ ret();
+ }
+ /*
input (z, x, y) = (p0, p1, p2)
z[0..2] <- montgomery(x[0..2], y[0..2])
destroy gt0, ..., gt9, xm0, xm1, p2
*/
- void gen_montMul3(const uint64_t *p, uint64_t pp)
+ void gen_montMul3()
{
StackFrame sf(this, 3, 10 | UseRDX);
const Reg64& p0 = sf.p[0];
@@ -1337,16 +1528,16 @@ private:
const Reg64& t8 = sf.t[8];
const Reg64& t9 = sf.t[9];
- movq(xm0, p0); // save p0
- mov(t7, (uint64_t)p);
+ vmovq(xm0, p0); // save p0
+ mov(t7, pL_);
mov(t9, ptr [p2]);
// c3, c2, c1, c0, px, y, p,
- montgomery3_1(pp, t0, t3, t2, t1, p1, t9, t7, t4, t5, t6, t8, p0, true);
+ montgomery3_1(rp_, t0, t3, t2, t1, p1, t9, t7, t4, t5, t6, t8, p0, true);
mov(t9, ptr [p2 + 8]);
- montgomery3_1(pp, t1, t0, t3, t2, p1, t9, t7, t4, t5, t6, t8, p0, false);
+ montgomery3_1(rp_, t1, t0, t3, t2, p1, t9, t7, t4, t5, t6, t8, p0, false);
mov(t9, ptr [p2 + 16]);
- montgomery3_1(pp, t2, t1, t0, t3, p1, t9, t7, t4, t5, t6, t8, p0, false);
+ montgomery3_1(rp_, t2, t1, t0, t3, p1, t9, t7, t4, t5, t6, t8, p0, false);
// [(t3):t2:t1:t0]
mov(t4, t0);
@@ -1357,7 +1548,7 @@ private:
cmovc(t0, t4);
cmovc(t1, t5);
cmovc(t2, t6);
- movq(p0, xm0);
+ vmovq(p0, xm0);
store_mr(p0, Pack(t2, t1, t0));
}
/*
@@ -1365,7 +1556,7 @@ private:
z[0..2] <- montgomery(px[0..2], px[0..2])
destroy gt0, ..., gt9, xm0, xm1, p2
*/
- void gen_montSqr3(const uint64_t *p, uint64_t pp)
+ void gen_montSqr3()
{
StackFrame sf(this, 3, 10 | UseRDX, 16 * 3);
const Reg64& pz = sf.p[0];
@@ -1383,24 +1574,24 @@ private:
const Reg64& t8 = sf.t[8];
const Reg64& t9 = sf.t[9];
- movq(xm0, pz); // save pz
- mov(t7, (uint64_t)p);
+ vmovq(xm0, pz); // save pz
+ mov(t7, pL_);
mov(t9, ptr [px]);
mul3x1_sqr1(px, t9, t3, t2, t1, t0);
mov(t0, rdx);
- montgomery3_sub(pp, t0, t9, t2, t1, px, t3, t7, t4, t5, t6, t8, pz, true);
+ montgomery3_sub(rp_, t0, t9, t2, t1, px, t3, t7, t4, t5, t6, t8, pz, true);
mov(t3, ptr [px + 8]);
mul3x1_sqr2(px, t3, t6, t5, t4);
add_rr(Pack(t1, t0, t9, t2), Pack(rdx, rax, t5, t4));
if (isFullBit_) setc(pz.cvt8());
- montgomery3_sub(pp, t1, t3, t9, t2, px, t0, t7, t4, t5, t6, t8, pz, false);
+ montgomery3_sub(rp_, t1, t3, t9, t2, px, t0, t7, t4, t5, t6, t8, pz, false);
mov(t0, ptr [px + 16]);
mul3x1_sqr3(t0, t5, t4);
add_rr(Pack(t2, t1, t3, t9), Pack(rdx, rax, t5, t4));
if (isFullBit_) setc(pz.cvt8());
- montgomery3_sub(pp, t2, t0, t3, t9, px, t1, t7, t4, t5, t6, t8, pz, false);
+ montgomery3_sub(rp_, t2, t0, t3, t9, px, t1, t7, t4, t5, t6, t8, pz, false);
// [t9:t2:t0:t3]
mov(t4, t3);
@@ -1411,18 +1602,17 @@ private:
cmovc(t3, t4);
cmovc(t0, t5);
cmovc(t2, t6);
- movq(pz, xm0);
+ vmovq(pz, xm0);
store_mr(pz, Pack(t2, t0, t3));
}
/*
py[5..0] <- px[2..0]^2
- @note use rax, rdx, rcx!
+ @note use rax, rdx
*/
void sqrPre3(const RegExp& py, const RegExp& px, const Pack& t)
{
const Reg64& a = rax;
const Reg64& d = rdx;
- const Reg64& c = rcx;
const Reg64& t0 = t[0];
const Reg64& t1 = t[1];
const Reg64& t2 = t[2];
@@ -1433,6 +1623,7 @@ private:
const Reg64& t7 = t[7];
const Reg64& t8 = t[8];
const Reg64& t9 = t[9];
+ const Reg64& t10 = t[10];
if (useMulx_) {
mov(d, ptr [px + 8 * 0]);
@@ -1453,7 +1644,7 @@ private:
mov(d, t7);
mulx(t8, t7, d);
- mulx(c, t9, t9);
+ mulx(t10, t9, t9);
} else {
mov(t9, ptr [px + 8 * 0]);
mov(a, t9);
@@ -1484,11 +1675,11 @@ private:
mov(a, ptr [px + 8 * 2]);
mul(t9);
mov(t9, a);
- mov(c, d);
+ mov(t10, d);
}
add(t2, t7);
adc(t8, t9);
- mov(t7, c);
+ mov(t7, t10);
adc(t7, 0); // [t7:t8:t2:t1]
add(t0, t1);
@@ -1500,7 +1691,7 @@ private:
mov(a, ptr [px + 8 * 2]);
mul(a);
add(t4, t9);
- adc(a, c);
+ adc(a, t10);
adc(d, 0); // [d:a:t4:t3]
add(t2, t3);
@@ -1537,13 +1728,13 @@ private:
const Reg64& a = rax;
const Reg64& d = rdx;
mov(d, ptr [px]);
- mulx(hi, a, ptr [py + 8 * 0]);
- adox(pd[0], a);
- mov(ptr [pz], pd[0]);
- for (size_t i = 1; i < pd.size(); i++) {
- adcx(pd[i], hi);
- mulx(hi, a, ptr [py + 8 * i]);
+ xor_(a, a);
+ for (size_t i = 0; i < pd.size(); i++) {
+ mulx(hi, a, ptr [py + i * 8]);
adox(pd[i], a);
+ if (i == 0) mov(ptr[pz], pd[0]);
+ if (i == pd.size() - 1) break;
+ adcx(pd[i + 1], hi);
}
mov(d, 0);
adcx(hi, d);
@@ -1611,6 +1802,7 @@ private:
if (useMulx_) {
mulPack(pz, px, py, Pack(t2, t1, t0));
+#if 0 // a little slow
if (useAdx_) {
// [t2:t1:t0]
mulPackAdd(pz + 8 * 1, px + 8 * 1, py, t3, Pack(t2, t1, t0));
@@ -1620,6 +1812,7 @@ private:
store_mr(pz + 8 * 3, Pack(t4, t3, t2));
return;
}
+#endif
} else {
mov(t5, ptr [px]);
mov(a, ptr [py + 8 * 0]);
@@ -1749,6 +1942,7 @@ private:
}
/*
py[7..0] = px[3..0] ^ 2
+ use xmm0
*/
void sqrPre4(const RegExp& py, const RegExp& px, const Pack& t)
{
@@ -1762,30 +1956,76 @@ private:
const Reg64& t7 = t[7];
const Reg64& t8 = t[8];
const Reg64& t9 = t[9];
+ const Reg64& t10 = t[10];
+ const Reg64& a = rax;
+ const Reg64& d = rdx;
- // (AN + B)^2 = A^2N^2 + 2AB + B^2
-
- mul2x2(px + 8 * 0, px + 8 * 2, t4, t3, t2, t1, t0);
- // [t3:t2:t1:t0] = AB
- xor_(t4, t4);
- add_rr(Pack(t4, t3, t2, t1, t0), Pack(t4, t3, t2, t1, t0));
- // [t4:t3:t2:t1:t0] = 2AB
- store_mr(py + 8 * 2, Pack(t4, t3, t2, t1, t0));
-
- mov(t8, ptr [px + 8 * 0]);
- mov(t9, ptr [px + 8 * 1]);
- sqr2(t1, t0, t7, t6, t9, t8, rax, rcx);
- // B^2 = [t1:t0:t7:t6]
- store_mr(py + 8 * 0, Pack(t7, t6));
- // [t1:t0]
-
- mov(t8, ptr [px + 8 * 2]);
- mov(t9, ptr [px + 8 * 3]);
- sqr2(t5, t4, t3, t2, t9, t8, rax, rcx);
- // [t5:t4:t3:t2]
- add_rm(Pack(t4, t3, t2, t1, t0), py + 8 * 2);
- adc(t5, 0);
- store_mr(py + 8 * 2, Pack(t5, t4, t3, t2, t1, t0));
+ /*
+ (aN + b)^2 = a^2 N^2 + 2ab N + b^2
+ */
+ load_rm(Pack(t9, t8), px);
+ sqr2(t3, t2, t1, t0, t9, t8, t7, t6);
+ // [t3:t2:t1:t0] = b^2
+ store_mr(py, Pack(t1, t0));
+ vmovq(xm0, t2);
+ mul2x2(px, px + 2 * 8, t6, t5, t4, t1, t0);
+ // [t5:t4:t1:t0] = ab
+ xor_(t6, t6);
+ add_rr(Pack(t6, t5, t4, t1, t0), Pack(t6, t5, t4, t1, t0));
+ // [t6:t5:t4:t1:t0] = 2ab
+ load_rm(Pack(t8, t7), px + 2 * 8);
+ // free t10, t9, rax, rdx
+ /*
+ [d:t8:t10:t9] = [t8:t7]^2
+ */
+ mov(d, t7);
+ mulx(t10, t9, t7); // [t10:t9] = t7^2
+ mulx(t7, t2, t8); // [t7:t2] = t7 t8
+ xor_(a, a);
+ add_rr(Pack(a, t7, t2), Pack(a, t7, t2));
+ // [a:t7:t2] = 2 t7 t8
+ mov(d, t8);
+ mulx(d, t8, t8); // [d:t8] = t8^2
+ add_rr(Pack(d, t8, t10), Pack(a, t7, t2));
+ // [d:t8:t10:t9] = [t8:t7]^2
+ vmovq(t2, xm0);
+ add_rr(Pack(t8, t10, t9, t3, t2), Pack(t6, t5, t4, t1, t0));
+ adc(d, 0);
+ store_mr(py + 2 * 8, Pack(d, t8, t10, t9, t3, t2));
+ }
+ /*
+ py[11..0] = px[5..0] ^ 2
+ use rax, rdx, stack[6 * 8]
+ */
+ void sqrPre6(const RegExp& py, const RegExp& px, const Pack& t)
+ {
+ const Reg64& t0 = t[0];
+ const Reg64& t1 = t[1];
+ const Reg64& t2 = t[2];
+ /*
+ (aN + b)^2 = a^2 N^2 + 2ab N + b^2
+ */
+ sqrPre3(py, px, t); // [py] <- b^2
+ sqrPre3(py + 6 * 8, px + 3 * 8, t); // [py + 6 * 8] <- a^2
+ mulPre3(rsp, px, px + 3 * 8, t); // ab
+ Pack ab = t.sub(0, 6);
+ load_rm(ab, rsp);
+ xor_(rax, rax);
+ for (int i = 0; i < 6; i++) {
+ if (i == 0) {
+ add(ab[i], ab[i]);
+ } else {
+ adc(ab[i], ab[i]);
+ }
+ }
+ adc(rax, rax);
+ add_rm(ab, py + 3 * 8);
+ store_mr(py + 3 * 8, ab);
+ load_rm(Pack(t2, t1, t0), py + 9 * 8);
+ adc(t0, rax);
+ adc(t1, 0);
+ adc(t2, 0);
+ store_mr(py + 9 * 8, Pack(t2, t1, t0));
}
/*
pz[7..0] <- px[3..0] * py[3..0]
@@ -1805,6 +2045,16 @@ private:
const Reg64& t8 = t[8];
const Reg64& t9 = t[9];
+#if 0 // a little slower
+ if (useMulx_ && useAdx_) {
+ mulPack(pz, px, py, Pack(t3, t2, t1, t0));
+ mulPackAdd(pz + 8 * 1, px + 8 * 1, py, t4, Pack(t3, t2, t1, t0));
+ mulPackAdd(pz + 8 * 2, px + 8 * 2, py, t0, Pack(t4, t3, t2, t1));
+ mulPackAdd(pz + 8 * 3, px + 8 * 3, py, t1, Pack(t0, t4, t3, t2));
+ store_mr(pz + 8 * 4, Pack(t1, t0, t4, t3));
+ return;
+ }
+#endif
#if 0
// a little slower
if (!useMulx_) {
@@ -1818,28 +2068,17 @@ private:
mul2x2(px + 8 * 0, py + 8 * 0, t9, t8, t7, t6, t5);
store_mr(pz, Pack(t6, t5));
// [t8:t7]
- movq(xm0, t7);
- movq(xm1, t8);
+ vmovq(xm0, t7);
+ vmovq(xm1, t8);
mul2x2(px + 8 * 2, py + 8 * 2, t8, t7, t9, t6, t5);
- movq(a, xm0);
- movq(d, xm1);
+ vmovq(a, xm0);
+ vmovq(d, xm1);
add_rr(Pack(t4, t3, t2, t1, t0), Pack(t9, t6, t5, d, a));
adc(t7, 0);
store_mr(pz + 8 * 2, Pack(t7, t4, t3, t2, t1, t0));
#else
if (useMulx_) {
mulPack(pz, px, py, Pack(t3, t2, t1, t0));
- if (0 && useAdx_) { // a little slower?
- // [t3:t2:t1:t0]
- mulPackAdd(pz + 8 * 1, px + 8 * 1, py, t4, Pack(t3, t2, t1, t0));
- // [t4:t3:t2:t1]
- mulPackAdd(pz + 8 * 2, px + 8 * 2, py, t5, Pack(t4, t3, t2, t1));
- // [t5:t4:t3:t2]
- mulPackAdd(pz + 8 * 3, px + 8 * 3, py, t0, Pack(t5, t4, t3, t2));
- // [t0:t5:t4:t3]
- store_mr(pz + 8 * 4, Pack(t0, t5, t4, t3));
- return;
- }
} else {
mov(t5, ptr [px]);
mov(a, ptr [py + 8 * 0]);
@@ -1894,12 +2133,111 @@ private:
mov(ptr [pz + 8 * 7], d);
#endif
}
- void mulPre6(const RegExp& pz, const RegExp& px, const RegExp& py, const Pack& t)
+ // [gp0] <- [gp1] * [gp2]
+ void mulPre6(const Pack& t)
{
+ const Reg64& pz = gp0;
+ const Reg64& px = gp1;
+ const Reg64& py = gp2;
const Reg64& t0 = t[0];
const Reg64& t1 = t[1];
const Reg64& t2 = t[2];
const Reg64& t3 = t[3];
+#if 0 // slower than basic multiplication(56clk -> 67clk)
+// const Reg64& t7 = t[7];
+// const Reg64& t8 = t[8];
+// const Reg64& t9 = t[9];
+ const Reg64& a = rax;
+ const Reg64& d = rdx;
+ const int stackSize = (3 + 3 + 6 + 1 + 1 + 1) * 8; // a+b, c+d, (a+b)(c+d), x, y, z
+ const int abPos = 0;
+ const int cdPos = abPos + 3 * 8;
+ const int abcdPos = cdPos + 3 * 8;
+ const int zPos = abcdPos + 6 * 8;
+ const int yPos = zPos + 8;
+ const int xPos = yPos + 8;
+
+ sub(rsp, stackSize);
+ mov(ptr[rsp + zPos], pz);
+ mov(ptr[rsp + xPos], px);
+ mov(ptr[rsp + yPos], py);
+ /*
+ x = aN + b, y = cN + d
+ xy = abN^2 + ((a+b)(c+d) - ac - bd)N + bd
+ */
+ xor_(a, a);
+ load_rm(Pack(t2, t1, t0), px); // b
+ add_rm(Pack(t2, t1, t0), px + 3 * 8); // a + b
+ adc(a, 0);
+ store_mr(pz, Pack(t2, t1, t0));
+ vmovq(xm0, a); // carry1
+
+ xor_(a, a);
+ load_rm(Pack(t2, t1, t0), py); // d
+ add_rm(Pack(t2, t1, t0), py + 3 * 8); // c + d
+ adc(a, 0);
+ store_mr(pz + 3 * 8, Pack(t2, t1, t0));
+ vmovq(xm1, a); // carry2
+
+ mulPre3(rsp + abcdPos, pz, pz + 3 * 8, t); // (a+b)(c+d)
+
+ vmovq(a, xm0);
+ vmovq(d, xm1);
+ mov(t3, a);
+ and_(t3, d); // t3 = carry1 & carry2
+ Label doNothing;
+ je(doNothing);
+ load_rm(Pack(t2, t1, t0), rsp + abcdPos + 3 * 8);
+ test(a, a);
+ je("@f");
+ // add (c+d)
+ add_rm(Pack(t2, t1, t0), pz + 3 * 8);
+ adc(t3, 0);
+ L("@@");
+ test(d, d);
+ je("@f");
+ // add(a+b)
+ add_rm(Pack(t2, t1, t0), pz);
+ adc(t3, 0);
+ L("@@");
+ store_mr(rsp + abcdPos + 3 * 8, Pack(t2, t1, t0));
+ L(doNothing);
+ vmovq(xm0, t3); // save new carry
+
+
+ mov(gp0, ptr [rsp + zPos]);
+ mov(gp1, ptr [rsp + xPos]);
+ mov(gp2, ptr [rsp + yPos]);
+ mulPre3(gp0, gp1, gp2, t); // [rsp] <- bd
+
+ mov(gp0, ptr [rsp + zPos]);
+ mov(gp1, ptr [rsp + xPos]);
+ mov(gp2, ptr [rsp + yPos]);
+ mulPre3(gp0 + 6 * 8, gp1 + 3 * 8, gp2 + 3 * 8, t); // [rsp + 6 * 8] <- ac
+
+ mov(pz, ptr[rsp + zPos]);
+ vmovq(d, xm0);
+ for (int i = 0; i < 6; i++) {
+ mov(a, ptr[pz + (3 + i) * 8]);
+ if (i == 0) {
+ add(a, ptr[rsp + abcdPos + i * 8]);
+ } else {
+ adc(a, ptr[rsp + abcdPos + i * 8]);
+ }
+ mov(ptr[pz + (3 + i) * 8], a);
+ }
+ mov(a, ptr[pz + 9 * 8]);
+ adc(a, d);
+ mov(ptr[pz + 9 * 8], a);
+ jnc("@f");
+ for (int i = 10; i < 12; i++) {
+ mov(a, ptr[pz + i * 8]);
+ adc(a, 0);
+ mov(ptr[pz + i * 8], a);
+ }
+ L("@@");
+ add(rsp, stackSize);
+#else
const Reg64& t4 = t[4];
const Reg64& t5 = t[5];
const Reg64& t6 = t[6];
@@ -1911,6 +2249,7 @@ private:
mulPackAdd(pz + 8 * 4, px + 8 * 4, py, t2, Pack(t1, t0, t6, t5, t4, t3)); // [t2:t1:t0:t6:t5:t4]
mulPackAdd(pz + 8 * 5, px + 8 * 5, py, t3, Pack(t2, t1, t0, t6, t5, t4)); // [t3:t2:t1:t0:t6:t5]
store_mr(pz + 8 * 6, Pack(t3, t2, t1, t0, t6, t5));
+#endif
}
/*
@input (z, xy)
@@ -1934,11 +2273,11 @@ private:
const Reg64& a = rax;
const Reg64& d = rdx;
- movq(xm0, z);
+ vmovq(xm0, z);
mov(z, ptr [xy + 0 * 8]);
mov(a, rp_);
mul(z);
- lea(t0, ptr [rip + *pL_]);
+ lea(t0, ptr [rip + pL_]);
load_rm(Pack(t7, t6, t5, t4, t3, t2, t1), xy);
mov(d, a); // q
mulPackAddShr(Pack(t7, t6, t5, t4, t3, t2, t1), t0, t10);
@@ -1951,32 +2290,32 @@ private:
// z = [t1:t0:t10:t9:t8:t7:t6:t5:t4:t3:t2]
mov(a, rp_);
mul(t2);
- movq(xm1, t0); // save
- lea(t0, ptr [rip + *pL_]);
+ vmovq(xm1, t0); // save
+ lea(t0, ptr [rip + pL_]);
mov(d, a);
- movq(xm2, t10);
+ vmovq(xm2, t10);
mulPackAddShr(Pack(t8, t7, t6, t5, t4, t3, t2), t0, t10);
- movq(t10, xm2);
+ vmovq(t10, xm2);
adc(t9, rax);
adc(t10, rax);
- movq(t0, xm1); // load
+ vmovq(t0, xm1); // load
adc(t0, rax);
adc(t1, rax);
// z = [t1:t0:t10:t9:t8:t7:t6:t5:t4:t3]
mov(a, rp_);
mul(t3);
- lea(t2, ptr [rip + *pL_]);
+ lea(t2, ptr [rip + pL_]);
mov(d, a);
- movq(xm2, t10);
+ vmovq(xm2, t10);
mulPackAddShr(Pack(t9, t8, t7, t6, t5, t4, t3), t2, t10);
- movq(t10, xm2);
+ vmovq(t10, xm2);
adc(t10, rax);
adc(t0, rax);
adc(t1, rax);
// z = [t1:t0:t10:t9:t8:t7:t6:t5:t4]
mov(a, rp_);
mul(t4);
- lea(t2, ptr [rip + *pL_]);
+ lea(t2, ptr [rip + pL_]);
mov(d, a);
mulPackAddShr(Pack(t10, t9, t8, t7, t6, t5, t4), t2, t3);
adc(t0, rax);
@@ -1984,14 +2323,14 @@ private:
// z = [t1:t0:t10:t9:t8:t7:t6:t5]
mov(a, rp_);
mul(t5);
- lea(t2, ptr [rip + *pL_]);
+ lea(t2, ptr [rip + pL_]);
mov(d, a);
mulPackAddShr(Pack(t0, t10, t9, t8, t7, t6, t5), t2, t3);
adc(t1, a);
// z = [t1:t0:t10:t9:t8:t7:t6]
mov(a, rp_);
mul(t6);
- lea(t2, ptr [rip + *pL_]);
+ lea(t2, ptr [rip + pL_]);
mov(d, a);
mulPackAddShr(Pack(t1, t0, t10, t9, t8, t7, t6), t2, t3, true);
// z = [t1:t0:t10:t9:t8:t7]
@@ -2000,47 +2339,87 @@ private:
mov_rr(keep, zp);
sub_rm(zp, t2); // z -= p
cmovc_rr(zp, keep);
- movq(z, xm0);
+ vmovq(z, xm0);
store_mr(z, zp);
}
- void gen_fpDbl_sqrPre(mcl::fp::Op& op)
+ void2u gen_fpDbl_sqrPre()
{
- if (useMulx_ && pn_ == 2) {
+ align(16);
+ void2u func = getCurr<void2u>();
+ if (pn_ == 2 && useMulx_) {
StackFrame sf(this, 2, 7 | UseRDX);
sqrPre2(sf.p[0], sf.p[1], sf.t);
- return;
+ return func;
}
if (pn_ == 3) {
- StackFrame sf(this, 2, 10 | UseRDX | UseRCX);
- sqrPre3(sf.p[0], sf.p[1], sf.t);
- return;
+ StackFrame sf(this, 3, 10 | UseRDX);
+ Pack t = sf.t;
+ t.append(sf.p[2]);
+ sqrPre3(sf.p[0], sf.p[1], t);
+ return func;
}
- if (useMulx_ && pn_ == 4) {
- StackFrame sf(this, 2, 10 | UseRDX | UseRCX);
- sqrPre4(sf.p[0], sf.p[1], sf.t);
- return;
+ if (pn_ == 4 && useMulx_) {
+ StackFrame sf(this, 3, 10 | UseRDX);
+ Pack t = sf.t;
+ t.append(sf.p[2]);
+ sqrPre4(sf.p[0], sf.p[1], t);
+ return func;
+ }
+ if (pn_ == 6 && useMulx_ && useAdx_) {
+ StackFrame sf(this, 3, 10 | UseRDX, 6 * 8);
+ Pack t = sf.t;
+ t.append(sf.p[2]);
+ sqrPre6(sf.p[0], sf.p[1], t);
+ return func;
}
+ return 0;
+#if 0
#ifdef XBYAK64_WIN
mov(r8, rdx);
#else
mov(rdx, rsi);
#endif
jmp((void*)op.fpDbl_mulPreA_);
+ return func;
+#endif
}
- void gen_fpDbl_mulPre()
+ void3u gen_fpDbl_mulPre()
{
- if (useMulx_ && pn_ == 2) {
+ align(16);
+ void3u func = getCurr<void3u>();
+ if (pn_ == 2 && useMulx_) {
StackFrame sf(this, 3, 5 | UseRDX);
mulPre2(sf.p[0], sf.p[1], sf.p[2], sf.t);
- return;
+ return func;
}
if (pn_ == 3) {
StackFrame sf(this, 3, 10 | UseRDX);
mulPre3(sf.p[0], sf.p[1], sf.p[2], sf.t);
- return;
+ return func;
}
- assert(0);
- exit(1);
+ if (pn_ == 4) {
+ /*
+ fpDbl_mulPre is available as C function
+ this function calls mulPreL directly.
+ */
+ StackFrame sf(this, 3, 10 | UseRDX, 0, false);
+ mulPre4(gp0, gp1, gp2, sf.t);
+ sf.close(); // make epilog
+ L(mulPreL); // called only from asm code
+ mulPre4(gp0, gp1, gp2, sf.t);
+ ret();
+ return func;
+ }
+ if (pn_ == 6 && useAdx_) {
+ StackFrame sf(this, 3, 10 | UseRDX, 0, false);
+ call(mulPreL);
+ sf.close(); // make epilog
+ L(mulPreL); // called only from asm code
+ mulPre6(sf.t);
+ ret();
+ return func;
+ }
+ return 0;
}
static inline void debug_put_inner(const uint64_t *ptr, int n)
{
@@ -2250,10 +2629,10 @@ private:
{
if (n >= 10) exit(1);
static uint64_t buf[10];
- movq(xm0, rax);
+ vmovq(xm0, rax);
mov(rax, (size_t)buf);
store_mp(rax, mp, t);
- movq(rax, xm0);
+ vmovq(rax, xm0);
push(rax);
mov(rax, (size_t)buf);
debug_put(rax, n);
@@ -2270,11 +2649,8 @@ private:
*/
void gen_preInv()
{
- assert(pn_ >= 1);
+ assert(1 <= pn_ && pn_ <= 4);
const int freeRegNum = 13;
- if (pn_ > 9) {
- throw cybozu::Exception("mcl:FpGenerator:gen_preInv:large pn_") << pn_;
- }
StackFrame sf(this, 2, 10 | UseRDX | UseRCX, (std::max<int>(0, pn_ * 5 - freeRegNum) + 1 + (isFullBit_ ? 1 : 0)) * 8);
const Reg64& pr = sf.p[0];
const Reg64& px = sf.p[1];
@@ -2307,7 +2683,7 @@ private:
mov(rax, px);
// px is free frome here
load_mp(vv, rax, t); // v = x
- mov(rax, (size_t)p_);
+ mov(rax, pL_);
load_mp(uu, rax, t); // u = p_
// k = 0
xor_(rax, rax);
@@ -2324,46 +2700,6 @@ private:
} else {
mov(qword [ss.getMem(0)], 1);
}
-#if 0
- L(".lp");
- or_mp(vv, t);
- jz(".exit", T_NEAR);
-
- g_test(uu[0], 1);
- jz(".u_even", T_NEAR);
- g_test(vv[0], 1);
- jz(".v_even", T_NEAR);
- for (int i = pn_ - 1; i >= 0; i--) {
- g_cmp(vv[i], uu[i], t);
- jc(".v_lt_u", T_NEAR);
- if (i > 0) jnz(".v_ge_u", T_NEAR);
- }
-
- L(".v_ge_u");
- sub_mp(vv, uu, t);
- add_mp(ss, rr, t);
- L(".v_even");
- shr_mp(vv, 1, t);
- twice_mp(rr, t);
- if (isFullBit_) {
- sbb(t, t);
- mov(ptr [rTop], t);
- }
- inc(rax);
- jmp(".lp", T_NEAR);
- L(".v_lt_u");
- sub_mp(uu, vv, t);
- add_mp(rr, ss, t);
- if (isFullBit_) {
- sbb(t, t);
- mov(ptr [rTop], t);
- }
- L(".u_even");
- shr_mp(uu, 1, t);
- twice_mp(ss, t);
- inc(rax);
- jmp(".lp", T_NEAR);
-#else
for (int cn = pn_; cn > 0; cn--) {
const std::string _lp = mkLabel(".lp", cn);
const std::string _u_v_odd = mkLabel(".u_v_odd", cn);
@@ -2420,13 +2756,12 @@ private:
uu.removeLast();
}
}
-#endif
L(".exit");
assert(ss.isReg(0));
const Reg64& t2 = ss.getReg(0);
const Reg64& t3 = rdx;
- mov(t2, (size_t)p_);
+ mov(t2, pL_);
if (isFullBit_) {
mov(t, ptr [rTop]);
test(t, t);
@@ -3057,7 +3392,7 @@ private:
mul4x1(px, y, t3, t2, t1, t0, t4);
// [rdx:y:t2:t1:t0] = px[3..0] * y
if (isFullBit_) {
- movq(xt, px);
+ vmovq(xt, px);
xor_(px, px);
}
add_rr(Pack(c4, y, c2, c1, c0), Pack(rdx, c3, t2, t1, t0));
@@ -3081,13 +3416,19 @@ private:
adc(c0, 0);
} else {
adc(c0, px);
- movq(px, xt);
+ vmovq(px, xt);
}
}
}
- void gen_fp2Dbl_mulPre(Label& mulPreL)
+ void3u gen_fp2Dbl_mulPre()
{
- assert(!isFullBit_);
+ if (isFullBit_) return 0;
+// if (pn_ != 4 && !(pn_ == 6 && useMulx_ && useAdx_)) return 0;
+ // almost same for pn_ == 6
+ if (pn_ != 4) return 0;
+ align(16);
+ void3u func = getCurr<void3u>();
+
const RegExp z = rsp + 0 * 8;
const RegExp x = rsp + 1 * 8;
const RegExp y = rsp + 2 * 8;
@@ -3100,9 +3441,9 @@ private:
mov(ptr [x], gp1);
mov(ptr [y], gp2);
// s = a + b
- gen_raw_add(s, gp1, gp1 + FpByte_, rax, 4);
+ gen_raw_add(s, gp1, gp1 + FpByte_, rax, pn_);
// t = c + d
- gen_raw_add(t, gp2, gp2 + FpByte_, rax, 4);
+ gen_raw_add(t, gp2, gp2 + FpByte_, rax, pn_);
// d1 = (a + b)(c + d)
mov(gp0, ptr [z]);
add(gp0, FpByte_ * 2); // d1
@@ -3127,20 +3468,33 @@ private:
add(gp0, FpByte_ * 2); // d1
mov(gp1, gp0);
mov(gp2, ptr [z]);
- gen_raw_sub(gp0, gp1, gp2, rax, 8);
+ gen_raw_sub(gp0, gp1, gp2, rax, pn_ * 2);
lea(gp2, ptr [d2]);
- gen_raw_sub(gp0, gp1, gp2, rax, 8);
+ gen_raw_sub(gp0, gp1, gp2, rax, pn_ * 2);
mov(gp0, ptr [z]);
mov(gp1, gp0);
lea(gp2, ptr [d2]);
- gen_raw_sub(gp0, gp1, gp2, rax, 4);
- gen_raw_fp_sub(gp0 + 8 * 4, gp1 + 8 * 4, gp2 + 8 * 4, Pack(gt0, gt1, gt2, gt3, gt4, gt5, gt6, gt7), true);
+ gen_raw_sub(gp0, gp1, gp2, rax, pn_);
+ if (pn_ == 4) {
+ gen_raw_fp_sub(gp0 + pn_ * 8, gp1 + pn_ * 8, gp2 + pn_ * 8, Pack(gt0, gt1, gt2, gt3, gt4, gt5, gt6, gt7), true);
+ } else {
+ assert(pn_ == 6);
+ gen_raw_fp_sub6(gp0, gp1, gp2, pn_ * 8, sf.t.sub(0, 6), true);
+ }
+ return func;
}
- void gen_fp2Dbl_sqrPre(Label& mulPreL)
+ void2u gen_fp2Dbl_sqrPre()
{
- assert(!isFullBit_);
+ if (isFullBit_) return 0;
+// if (pn_ != 4 && !(pn_ == 6 && useMulx_ && useAdx_)) return 0;
+ // almost same for pn_ == 6
+ if (pn_ != 4) return 0;
+ align(16);
+ void2u func = getCurr<void2u>();
+ // almost same for pn_ == 6
+ if (pn_ != 4) return 0;
const RegExp y = rsp + 0 * 8;
const RegExp x = rsp + 1 * 8;
const Ext1 t1(FpByte_, rsp, 2 * 8);
@@ -3149,10 +3503,15 @@ private:
StackFrame sf(this, 3 /* not 2 */, 10 | UseRDX, t2.next);
mov(ptr [y], gp0);
mov(ptr [x], gp1);
- const Pack a = sf.t.sub(0, 4);
- const Pack b = sf.t.sub(4, 4);
+ Pack t = sf.t;
+ if (pn_ == 6) {
+ t.append(rax);
+ t.append(rdx);
+ }
+ const Pack a = t.sub(0, pn_);
+ const Pack b = t.sub(pn_, pn_);
load_rm(b, gp1 + FpByte_);
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < pn_; i++) {
mov(rax, b[i]);
if (i == 0) {
add(rax, rax);
@@ -3170,11 +3529,17 @@ private:
mov(gp2, ptr [x]);
call(mulPreL);
mov(gp0, ptr [x]);
- gen_raw_fp_sub(t1, gp0, gp0 + FpByte_, sf.t, false);
+ if (pn_ == 4) {
+ gen_raw_fp_sub(t1, gp0, gp0 + FpByte_, sf.t, false);
+ } else {
+ assert(pn_ == 6);
+ gen_raw_fp_sub6(t1, gp0, gp0, FpByte_, a, false);
+ }
mov(gp0, ptr [y]);
lea(gp1, ptr [t1]);
lea(gp2, ptr [t2]);
call(mulPreL);
+ return func;
}
void gen_fp2_add4()
{
@@ -3183,6 +3548,61 @@ private:
gen_raw_fp_add(sf.p[0], sf.p[1], sf.p[2], sf.t, false);
gen_raw_fp_add(sf.p[0] + FpByte_, sf.p[1] + FpByte_, sf.p[2] + FpByte_, sf.t, false);
}
+ void gen_fp2_add6()
+ {
+ assert(!isFullBit_);
+ StackFrame sf(this, 3, 10);
+ const Reg64& pz = sf.p[0];
+ const Reg64& px = sf.p[1];
+ const Reg64& py = sf.p[2];
+ Pack t1 = sf.t.sub(0, 6);
+ Pack t2 = sf.t.sub(6);
+ t2.append(rax);
+ t2.append(px); // destory after used
+ vmovq(xm0, px);
+ gen_raw_fp_add6(pz, px, py, t1, t2, false);
+ vmovq(px, xm0);
+ gen_raw_fp_add6(pz + FpByte_, px + FpByte_, py + FpByte_, t1, t2, false);
+ }
+ void gen_fp2_sub6()
+ {
+ StackFrame sf(this, 3, 5);
+ const Reg64& pz = sf.p[0];
+ const Reg64& px = sf.p[1];
+ const Reg64& py = sf.p[2];
+ Pack t = sf.t;
+ t.append(rax);
+ gen_raw_fp_sub6(pz, px, py, 0, t, false);
+ gen_raw_fp_sub6(pz, px, py, FpByte_, t, false);
+ }
+ void3u gen_fp2_add()
+ {
+ align(16);
+ void3u func = getCurr<void3u>();
+ if (pn_ == 4 && !isFullBit_) {
+ gen_fp2_add4();
+ return func;
+ }
+ if (pn_ == 6 && !isFullBit_) {
+ gen_fp2_add6();
+ return func;
+ }
+ return 0;
+ }
+ void3u gen_fp2_sub()
+ {
+ align(16);
+ void3u func = getCurr<void3u>();
+ if (pn_ == 4 && !isFullBit_) {
+ gen_fp2_sub4();
+ return func;
+ }
+ if (pn_ == 6 && !isFullBit_) {
+ gen_fp2_sub6();
+ return func;
+ }
+ return 0;
+ }
void gen_fp2_sub4()
{
assert(!isFullBit_);
@@ -3198,14 +3618,17 @@ private:
void gen_fp2_mul_xi4()
{
assert(!isFullBit_);
-#if 0
- StackFrame sf(this, 2, 10 | UseRDX | UseRCX);
+ StackFrame sf(this, 2, 11 | UseRDX);
+ const Reg64& py = sf.p[0];
+ const Reg64& px = sf.p[1];
Pack a = sf.t.sub(0, 4);
Pack b = sf.t.sub(4, 4);
- Pack t(rdx, rcx, sf.t[8], sf.t[9]);
- load_rm(a, sf.p[1]);
- load_rm(b, sf.p[1] + FpByte_);
- for (int i = 0; i < 4; i++) {
+ Pack t = sf.t.sub(8);
+ t.append(rdx);
+ assert(t.size() == 4);
+ load_rm(a, px);
+ load_rm(b, px + FpByte_);
+ for (int i = 0; i < pn_; i++) {
mov(t[i], a[i]);
if (i == 0) {
add(t[i], b[i]);
@@ -3214,41 +3637,78 @@ private:
}
}
sub_rr(a, b);
- mov(rax, (size_t)p_);
+ mov(rax, pL_);
load_rm(b, rax);
sbb(rax, rax);
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < pn_; i++) {
and_(b[i], rax);
}
add_rr(a, b);
- store_mr(sf.p[0], a);
- mov(rax, (size_t)p_);
+ store_mr(py, a);
+ mov(rax, pL_);
mov_rr(a, t);
sub_rm(t, rax);
- for (int i = 0; i < 4; i++) {
- cmovc(t[i], a[i]);
+ cmovc_rr(t, a);
+ store_mr(py + FpByte_, t);
+ }
+ void gen_fp2_mul_xi6()
+ {
+ assert(!isFullBit_);
+ StackFrame sf(this, 2, 12);
+ const Reg64& py = sf.p[0];
+ const Reg64& px = sf.p[1];
+ Pack a = sf.t.sub(0, 6);
+ Pack b = sf.t.sub(6);
+ load_rm(a, px);
+ mov_rr(b, a);
+ add_rm(b, px + FpByte_);
+ sub_rm(a, px + FpByte_);
+ mov(rax, pL_);
+ jnc("@f");
+ add_rm(a, rax);
+ L("@@");
+ store_mr(py, a);
+ mov_rr(a, b);
+ sub_rm(b, rax);
+ cmovc_rr(b, a);
+ store_mr(py + FpByte_, b);
+ }
+ void2u gen_fp2_mul_xi()
+ {
+ if (isFullBit_) return 0;
+ if (op_->xi_a != 1) return 0;
+ align(16);
+ void2u func = getCurr<void2u>();
+ if (pn_ == 4) {
+ gen_fp2_mul_xi4();
+ return func;
}
- store_mr(sf.p[0] + FpByte_, t);
-#else
- StackFrame sf(this, 2, 8, 8 * 4);
- gen_raw_fp_add(rsp, sf.p[1], sf.p[1] + FpByte_, sf.t, false);
- gen_raw_fp_sub(sf.p[0], sf.p[1], sf.p[1] + FpByte_, sf.t, false);
- for (int i = 0; i < 4; i++) {
- mov(rax, ptr [rsp + i * 8]);
- mov(ptr[sf.p[0] + FpByte_ + i * 8], rax);
+ if (pn_ == 6) {
+ gen_fp2_mul_xi6();
+ return func;
}
-#endif
+ return 0;
}
- void gen_fp2_neg4()
+ void2u gen_fp2_neg()
{
- assert(!isFullBit_);
- StackFrame sf(this, 2, UseRDX | pn_);
- gen_raw_neg(sf.p[0], sf.p[1], sf.t);
- gen_raw_neg(sf.p[0] + FpByte_, sf.p[1] + FpByte_, sf.t);
+ align(16);
+ void2u func = getCurr<void2u>();
+ if (pn_ <= 6) {
+ StackFrame sf(this, 2, UseRDX | pn_);
+ gen_raw_neg(sf.p[0], sf.p[1], sf.t);
+ gen_raw_neg(sf.p[0] + FpByte_, sf.p[1] + FpByte_, sf.t);
+ return func;
+ }
+ return 0;
}
- void gen_fp2_mul4(Label& fpDbl_modL)
+ void3u gen_fp2_mul()
{
- assert(!isFullBit_);
+ if (isFullBit_) return 0;
+ if (pn_ != 4 && !(pn_ == 6 && useMulx_ && useAdx_)) return 0;
+ align(16);
+ void3u func = getCurr<void3u>();
+ bool embedded = pn_ == 4;
+
const RegExp z = rsp + 0 * 8;
const RegExp x = rsp + 1 * 8;
const RegExp y = rsp + 2 * 8;
@@ -3263,27 +3723,50 @@ private:
mov(ptr[x], gp1);
mov(ptr[y], gp2);
// s = a + b
- gen_raw_add(s, gp1, gp1 + FpByte_, rax, 4);
+ gen_raw_add(s, gp1, gp1 + FpByte_, rax, pn_);
// t = c + d
- gen_raw_add(t, gp2, gp2 + FpByte_, rax, 4);
+ gen_raw_add(t, gp2, gp2 + FpByte_, rax, pn_);
// d1 = (a + b)(c + d)
- mulPre4(d1, s, t, sf.t);
+ if (embedded) {
+ mulPre4(d1, s, t, sf.t);
+ } else {
+ lea(gp0, ptr [d1]);
+ lea(gp1, ptr [s]);
+ lea(gp2, ptr [t]);
+ call(mulPreL);
+ }
// d0 = a c
mov(gp1, ptr [x]);
mov(gp2, ptr [y]);
- mulPre4(d0, gp1, gp2, sf.t);
+ if (embedded) {
+ mulPre4(d0, gp1, gp2, sf.t);
+ } else {
+ lea(gp0, ptr [d0]);
+ call(mulPreL);
+ }
// d2 = b d
mov(gp1, ptr [x]);
add(gp1, FpByte_);
mov(gp2, ptr [y]);
add(gp2, FpByte_);
- mulPre4(d2, gp1, gp2, sf.t);
+ if (embedded) {
+ mulPre4(d2, gp1, gp2, sf.t);
+ } else {
+ lea(gp0, ptr [d2]);
+ call(mulPreL);
+ }
- gen_raw_sub(d1, d1, d0, rax, 8);
- gen_raw_sub(d1, d1, d2, rax, 8);
+ gen_raw_sub(d1, d1, d0, rax, pn_ * 2);
+ gen_raw_sub(d1, d1, d2, rax, pn_ * 2);
- gen_raw_sub(d0, d0, d2, rax, 4);
- gen_raw_fp_sub((RegExp)d0 + 8 * 4, (RegExp)d0 + 8 * 4, (RegExp)d2 + 8 * 4, Pack(gt0, gt1, gt2, gt3, gt4, gt5, gt6, gt7), true);
+ gen_raw_sub(d0, d0, d2, rax, pn_);
+ if (pn_ == 4) {
+ gen_raw_fp_sub((RegExp)d0 + pn_ * 8, (RegExp)d0 + pn_ * 8, (RegExp)d2 + pn_ * 8, Pack(gt0, gt1, gt2, gt3, gt4, gt5, gt6, gt7), true);
+ } else {
+ lea(gp0, ptr[d0]);
+ lea(gp2, ptr[d2]);
+ gen_raw_fp_sub6(gp0, gp0, gp2, pn_ * 8, sf.t.sub(0, 6), true);
+ }
mov(gp0, ptr [z]);
lea(gp1, ptr[d0]);
@@ -3293,10 +3776,15 @@ private:
add(gp0, FpByte_);
lea(gp1, ptr[d1]);
call(fpDbl_modL);
+ return func;
}
- void gen_fp2_sqr4(Label& fp_mulL)
+ void2u gen_fp2_sqr()
{
- assert(!isFullBit_);
+ if (isFullBit_) return 0;
+ if (pn_ != 4 && !(pn_ == 6 && useMulx_ && useAdx_)) return 0;
+ align(16);
+ void2u func = getCurr<void2u>();
+
const RegExp y = rsp + 0 * 8;
const RegExp x = rsp + 1 * 8;
const Ext1 t1(FpByte_, rsp, 2 * 8);
@@ -3309,7 +3797,7 @@ private:
// t1 = b + b
lea(gp0, ptr [t1]);
if (nocarry) {
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < pn_; i++) {
mov(rax, ptr [gp1 + FpByte_ + i * 8]);
if (i == 0) {
add(rax, rax);
@@ -3319,7 +3807,15 @@ private:
mov(ptr [gp0 + i * 8], rax);
}
} else {
- gen_raw_fp_add(gp0, gp1 + FpByte_, gp1 + FpByte_, sf.t, false);
+ if (pn_ == 4) {
+ gen_raw_fp_add(gp0, gp1 + FpByte_, gp1 + FpByte_, sf.t, false);
+ } else {
+ assert(pn_ == 6);
+ Pack t = sf.t.sub(6, 4);
+ t.append(rax);
+ t.append(rdx);
+ gen_raw_fp_add6(gp0, gp1 + FpByte_, gp1 + FpByte_, sf.t.sub(0, 6), t, false);
+ }
}
// t1 = 2ab
mov(gp1, gp0);
@@ -3327,13 +3823,16 @@ private:
call(fp_mulL);
if (nocarry) {
- Pack a = sf.t.sub(0, 4);
- Pack b = sf.t.sub(4, 4);
+ Pack t = sf.t;
+ t.append(rdx);
+ t.append(gp1);
+ Pack a = t.sub(0, pn_);
+ Pack b = t.sub(pn_, pn_);
mov(gp0, ptr [x]);
load_rm(a, gp0);
load_rm(b, gp0 + FpByte_);
// t2 = a + b
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < pn_; i++) {
mov(rax, a[i]);
if (i == 0) {
add(rax, b[i]);
@@ -3343,14 +3842,24 @@ private:
mov(ptr [(RegExp)t2 + i * 8], rax);
}
// t3 = a + p - b
- mov(gp1, (size_t)p_);
- add_rm(a, gp1);
+ mov(rax, pL_);
+ add_rm(a, rax);
sub_rr(a, b);
store_mr(t3, a);
} else {
mov(gp0, ptr [x]);
- gen_raw_fp_add(t2, gp0, gp0 + FpByte_, sf.t, false);
- gen_raw_fp_sub(t3, gp0, gp0 + FpByte_, sf.t, false);
+ if (pn_ == 4) {
+ gen_raw_fp_add(t2, gp0, gp0 + FpByte_, sf.t, false);
+ gen_raw_fp_sub(t3, gp0, gp0 + FpByte_, sf.t, false);
+ } else {
+ assert(pn_ == 6);
+ Pack p1 = sf.t.sub(0, 6);
+ Pack p2 = sf.t.sub(6, 4);
+ p2.append(rax);
+ p2.append(rdx);
+ gen_raw_fp_add6(t2, gp0, gp0 + FpByte_, p1, p2, false);
+ gen_raw_fp_sub6(t3, gp0, gp0 + FpByte_, 0, p1, false);
+ }
}
mov(gp0, ptr [y]);
@@ -3358,10 +3867,11 @@ private:
lea(gp2, ptr [t3]);
call(fp_mulL);
mov(gp0, ptr [y]);
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < pn_; i++) {
mov(rax, ptr [(RegExp)t1 + i * 8]);
mov(ptr [gp0 + FpByte_ + i * 8], rax);
}
+ return func;
}
};
diff --git a/vendor/github.com/dexon-foundation/mcl/src/she_c_impl.hpp b/vendor/github.com/dexon-foundation/mcl/src/she_c_impl.hpp
index 723765a3c..073bc2b34 100644
--- a/vendor/github.com/dexon-foundation/mcl/src/she_c_impl.hpp
+++ b/vendor/github.com/dexon-foundation/mcl/src/she_c_impl.hpp
@@ -5,7 +5,7 @@
#include <iosfwd>
#include <stdint.h>
#include <memory.h>
-#include "../src/bn_c_impl.hpp"
+#include "mcl/impl/bn_c_impl.hpp"
#define MCLSHE_DLL_EXPORT
#include <mcl/she.h>
diff --git a/vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak.h b/vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak.h
index 47494ef09..bcfeb34bf 100644
--- a/vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak.h
+++ b/vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak.h
@@ -40,6 +40,8 @@
// This covers -std=(gnu|c)++(0x|11|1y), -stdlib=libc++, and modern Microsoft.
#if ((defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(_LIBCPP_VERSION) ||\
((__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)))
+ #include <unordered_set>
+ #define XBYAK_STD_UNORDERED_SET std::unordered_set
#include <unordered_map>
#define XBYAK_STD_UNORDERED_MAP std::unordered_map
#define XBYAK_STD_UNORDERED_MULTIMAP std::unordered_multimap
@@ -49,16 +51,22 @@
libstdcxx 20070719 (from GCC 4.2.1, the last GPL 2 version).
*/
#elif XBYAK_GNUC_PREREQ(4, 5) || (XBYAK_GNUC_PREREQ(4, 2) && __GLIBCXX__ >= 20070719) || defined(__INTEL_COMPILER) || defined(__llvm__)
+ #include <tr1/unordered_set>
+ #define XBYAK_STD_UNORDERED_SET std::tr1::unordered_set
#include <tr1/unordered_map>
#define XBYAK_STD_UNORDERED_MAP std::tr1::unordered_map
#define XBYAK_STD_UNORDERED_MULTIMAP std::tr1::unordered_multimap
#elif defined(_MSC_VER) && (_MSC_VER >= 1500) && (_MSC_VER < 1600)
+ #include <unordered_set>
+ #define XBYAK_STD_UNORDERED_SET std::tr1::unordered_set
#include <unordered_map>
#define XBYAK_STD_UNORDERED_MAP std::tr1::unordered_map
#define XBYAK_STD_UNORDERED_MULTIMAP std::tr1::unordered_multimap
#else
+ #include <set>
+ #define XBYAK_STD_UNORDERED_SET std::set
#include <map>
#define XBYAK_STD_UNORDERED_MAP std::map
#define XBYAK_STD_UNORDERED_MULTIMAP std::multimap
@@ -105,7 +113,7 @@ namespace Xbyak {
enum {
DEFAULT_MAX_CODE_SIZE = 4096,
- VERSION = 0x5730 /* 0xABCD = A.BC(D) */
+ VERSION = 0x5751 /* 0xABCD = A.BC(D) */
};
#ifndef MIE_INTEGER_TYPE_DEFINED
@@ -925,10 +933,10 @@ public:
void dq(uint64 code) { db(code, 8); }
const uint8 *getCode() const { return top_; }
template<class F>
- const F getCode() const { return CastTo<F>(top_); }
+ const F getCode() const { return reinterpret_cast<F>(top_); }
const uint8 *getCurr() const { return &top_[size_]; }
template<class F>
- const F getCurr() const { return CastTo<F>(&top_[size_]); }
+ const F getCurr() const { return reinterpret_cast<F>(&top_[size_]); }
size_t getSize() const { return size_; }
void setSize(size_t size)
{
@@ -1134,6 +1142,7 @@ public:
Label(const Label& rhs);
Label& operator=(const Label& rhs);
~Label();
+ void clear() { mgr = 0; id = 0; }
int getId() const { return id; }
const uint8 *getAddress() const;
@@ -1172,6 +1181,7 @@ class LabelManager {
};
typedef XBYAK_STD_UNORDERED_MAP<int, ClabelVal> ClabelDefList;
typedef XBYAK_STD_UNORDERED_MULTIMAP<int, const JmpLabel> ClabelUndefList;
+ typedef XBYAK_STD_UNORDERED_SET<Label*> LabelPtrList;
CodeArray *base_;
// global : stateList_.front(), local : stateList_.back()
@@ -1179,6 +1189,7 @@ class LabelManager {
mutable int labelId_;
ClabelDefList clabelDefList_;
ClabelUndefList clabelUndefList_;
+ LabelPtrList labelPtrList_;
int getId(const Label& label) const
{
@@ -1227,9 +1238,14 @@ class LabelManager {
return true;
}
friend class Label;
- void incRefCount(int id) { clabelDefList_[id].refCount++; }
- void decRefCount(int id)
+ void incRefCount(int id, Label *label)
{
+ clabelDefList_[id].refCount++;
+ labelPtrList_.insert(label);
+ }
+ void decRefCount(int id, Label *label)
+ {
+ labelPtrList_.erase(label);
ClabelDefList::iterator i = clabelDefList_.find(id);
if (i == clabelDefList_.end()) return;
if (i->second.refCount == 1) {
@@ -1248,11 +1264,23 @@ class LabelManager {
#endif
return !list.empty();
}
+ // detach all labels linked to LabelManager
+ void resetLabelPtrList()
+ {
+ for (LabelPtrList::iterator i = labelPtrList_.begin(), ie = labelPtrList_.end(); i != ie; ++i) {
+ (*i)->clear();
+ }
+ labelPtrList_.clear();
+ }
public:
LabelManager()
{
reset();
}
+ ~LabelManager()
+ {
+ resetLabelPtrList();
+ }
void reset()
{
base_ = 0;
@@ -1262,6 +1290,7 @@ public:
stateList_.push_back(SlabelState());
clabelDefList_.clear();
clabelUndefList_.clear();
+ resetLabelPtrList();
}
void enterLocal()
{
@@ -1294,10 +1323,11 @@ public:
SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front();
define_inner(st.defList, st.undefList, label, base_->getSize());
}
- void defineClabel(const Label& label)
+ void defineClabel(Label& label)
{
define_inner(clabelDefList_, clabelUndefList_, getId(label), base_->getSize());
label.mgr = this;
+ labelPtrList_.insert(&label);
}
void assign(Label& dst, const Label& src)
{
@@ -1305,6 +1335,7 @@ public:
if (i == clabelDefList_.end()) throw Error(ERR_LABEL_ISNOT_SET_BY_L);
define_inner(clabelDefList_, clabelUndefList_, dst.id, i->second.offset);
dst.mgr = this;
+ labelPtrList_.insert(&dst);
}
bool getOffset(size_t *offset, std::string& label) const
{
@@ -1352,19 +1383,19 @@ inline Label::Label(const Label& rhs)
{
id = rhs.id;
mgr = rhs.mgr;
- if (mgr) mgr->incRefCount(id);
+ if (mgr) mgr->incRefCount(id, this);
}
inline Label& Label::operator=(const Label& rhs)
{
if (id) throw Error(ERR_LABEL_IS_ALREADY_SET_BY_L);
id = rhs.id;
mgr = rhs.mgr;
- if (mgr) mgr->incRefCount(id);
+ if (mgr) mgr->incRefCount(id, this);
return *this;
}
inline Label::~Label()
{
- if (id && mgr) mgr->decRefCount(id);
+ if (id && mgr) mgr->decRefCount(id, this);
}
inline const uint8* Label::getAddress() const
{
@@ -2168,7 +2199,7 @@ public:
const Segment es, cs, ss, ds, fs, gs;
#endif
void L(const std::string& label) { labelMgr_.defineSlabel(label); }
- void L(const Label& label) { labelMgr_.defineClabel(label); }
+ void L(Label& label) { labelMgr_.defineClabel(label); }
Label L() { Label label; L(label); return label; }
void inLocalLabel() { labelMgr_.enterLocal(); }
void outLocalLabel() { labelMgr_.leaveLocal(); }
@@ -2200,7 +2231,7 @@ public:
// call(function pointer)
#ifdef XBYAK_VARIADIC_TEMPLATE
template<class Ret, class... Params>
- void call(Ret(*func)(Params...)) { call(CastTo<const void*>(func)); }
+ void call(Ret(*func)(Params...)) { call(reinterpret_cast<const void*>(func)); }
#endif
void call(const void *addr) { opJmpAbs(addr, T_NEAR, 0, 0xE8); }
diff --git a/vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak_mnemonic.h b/vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak_mnemonic.h
index 92a31f9a1..766f2f6ec 100644
--- a/vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak_mnemonic.h
+++ b/vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak_mnemonic.h
@@ -1,4 +1,4 @@
-const char *getVersionString() const { return "5.73"; }
+const char *getVersionString() const { return "5.751"; }
void adc(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x10, 2); }
void adc(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x10); }
void adcx(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0x66, isREG32_REG32orMEM, NONE, 0x38); }
diff --git a/vendor/github.com/dexon-foundation/mcl/test/aggregate_sig_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/aggregate_sig_test.cpp
new file mode 100644
index 000000000..c3a0e758d
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/aggregate_sig_test.cpp
@@ -0,0 +1,74 @@
+//#define MCLBN_FP_UNIT_SIZE 8
+#include <cybozu/test.hpp>
+#include <mcl/aggregate_sig.hpp>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/xorshift.hpp>
+
+using namespace mcl::aggs;
+
+CYBOZU_TEST_AUTO(init)
+{
+ AGGS::init();
+// AGGS::init(mcl::BN381_1);
+// AGGS::init(mcl::BLS12_381);
+ SecretKey sec;
+ sec.init();
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ const std::string m = "abc";
+ Signature sig;
+ sec.sign(sig, m);
+ CYBOZU_TEST_ASSERT(pub.verify(sig, m));
+}
+
+void aggregateTest(const std::vector<std::string>& msgVec)
+{
+ const size_t n = msgVec.size();
+ std::vector<SecretKey> secVec(n);
+ std::vector<PublicKey> pubVec(n);
+ std::vector<Signature> sigVec(n);
+ Signature aggSig;
+ for (size_t i = 0; i < n; i++) {
+ secVec[i].init();
+ secVec[i].getPublicKey(pubVec[i]);
+ secVec[i].sign(sigVec[i], msgVec[i]);
+ CYBOZU_TEST_ASSERT(pubVec[i].verify(sigVec[i], msgVec[i]));
+ }
+ aggSig.aggregate(sigVec);
+ CYBOZU_TEST_ASSERT(aggSig.verify(msgVec, pubVec));
+ CYBOZU_BENCH_C("aggSig.verify", 10, aggSig.verify, msgVec, pubVec);
+}
+
+CYBOZU_TEST_AUTO(aggregate)
+{
+#if 0
+ /*
+ Core i7-7700 CPU @ 3.60GHz
+ BN254 Fp382 Fp462
+ security bit 100 115? 128
+ # of sig 100 69 200 476
+ 1000 693 2037 4731
+ 10000 6969 20448 47000(Mclk)
+ */
+ const size_t n = 1000;
+ const size_t msgSize = 16;
+ std::vector<std::string> msgVec(n);
+ cybozu::XorShift rg;
+ for (size_t i = 0; i < n; i++) {
+ std::string& msg = msgVec[i];
+ msg.resize(msgSize);
+ for (size_t j = 0; j < msgSize; j++) {
+ msg[j] = (char)rg();
+ }
+ }
+ aggregateTest(msgVec);
+#else
+ const std::string msgArray[] = { "abc", "12345", "xyz", "pqr", "aggregate signature" };
+ const size_t n = sizeof(msgArray) / sizeof(msgArray[0]);
+ std::vector<std::string> msgVec(n);
+ for (size_t i = 0; i < n; i++) {
+ msgVec[i] = msgArray[i];
+ }
+ aggregateTest(msgVec);
+#endif
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/array_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/array_test.cpp
new file mode 100644
index 000000000..2168a28fa
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/array_test.cpp
@@ -0,0 +1,104 @@
+#include <mcl/array.hpp>
+#include <cybozu/test.hpp>
+
+template<class Array, size_t n>
+void setArray(Array& a, const int (&tbl)[n])
+{
+ CYBOZU_TEST_ASSERT(a.resize(n));
+ for (size_t i = 0; i < n; i++) a[i] = tbl[i];
+}
+
+template<class Array, size_t an, size_t bn>
+void swapTest(const int (&a)[an], const int (&b)[bn])
+{
+ Array s, t;
+ setArray(s, a);
+ setArray(t, b);
+ s.swap(t);
+ CYBOZU_TEST_EQUAL(s.size(), bn);
+ CYBOZU_TEST_EQUAL(t.size(), an);
+ CYBOZU_TEST_EQUAL_ARRAY(s, b, s.size());
+ CYBOZU_TEST_EQUAL_ARRAY(t, a, t.size());
+}
+
+CYBOZU_TEST_AUTO(resize)
+{
+ mcl::Array<int> a, b;
+ CYBOZU_TEST_EQUAL(a.size(), 0);
+ CYBOZU_TEST_EQUAL(b.size(), 0);
+
+ const size_t n = 5;
+ bool ok = a.resize(n);
+ CYBOZU_TEST_ASSERT(ok);
+ CYBOZU_TEST_EQUAL(n, a.size());
+ for (size_t i = 0; i < n; i++) {
+ a[i] = i;
+ }
+ ok = b.copy(a);
+ CYBOZU_TEST_ASSERT(ok);
+ CYBOZU_TEST_EQUAL(b.size(), n);
+ CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), n);
+
+ const size_t small = n - 1;
+ ok = b.resize(small);
+ CYBOZU_TEST_ASSERT(ok);
+ CYBOZU_TEST_EQUAL(b.size(), small);
+ CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), small);
+ const size_t large = n * 2;
+ ok = b.resize(large);
+ CYBOZU_TEST_ASSERT(ok);
+ CYBOZU_TEST_EQUAL(b.size(), large);
+ CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), small);
+
+ const int aTbl[] = { 3, 4 };
+ const int bTbl[] = { 7, 6, 5, 3 };
+ swapTest<mcl::Array<int> >(aTbl, bTbl);
+ swapTest<mcl::Array<int> >(bTbl, aTbl);
+}
+
+CYBOZU_TEST_AUTO(FixedArray)
+{
+ const size_t n = 5;
+ mcl::FixedArray<int, n> a, b;
+ CYBOZU_TEST_EQUAL(a.size(), 0);
+ CYBOZU_TEST_EQUAL(b.size(), 0);
+
+ bool ok = a.resize(n);
+ CYBOZU_TEST_ASSERT(ok);
+ CYBOZU_TEST_EQUAL(n, a.size());
+ for (size_t i = 0; i < n; i++) {
+ a[i] = i;
+ }
+ ok = b.copy(a);
+ CYBOZU_TEST_ASSERT(ok);
+ CYBOZU_TEST_EQUAL(b.size(), n);
+ CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), n);
+
+ const size_t small = n - 1;
+ ok = b.resize(small);
+ CYBOZU_TEST_ASSERT(ok);
+ CYBOZU_TEST_EQUAL(b.size(), small);
+ CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), small);
+ const size_t large = n + 1;
+ ok = b.resize(large);
+ CYBOZU_TEST_ASSERT(!ok);
+
+ const int aTbl[] = { 3, 4 };
+ const int bTbl[] = { 7, 6, 5, 3 };
+ swapTest<mcl::FixedArray<int, n> >(aTbl, bTbl);
+ swapTest<mcl::FixedArray<int, n> >(bTbl, aTbl);
+}
+
+#ifndef CYBOZU_DONT_USE_EXCEPTION
+CYBOZU_TEST_AUTO(assign)
+{
+ const int aTbl[] = { 3, 4, 2 };
+ const int bTbl[] = { 3, 4, 2, 1, 5 };
+ mcl::Array<int> a, b;
+ setArray(a, aTbl);
+ setArray(b, bTbl);
+ a = b;
+ CYBOZU_TEST_EQUAL(a.size(), b.size());
+ CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), a.size());
+}
+#endif
diff --git a/vendor/github.com/dexon-foundation/mcl/test/base_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/base_test.cpp
new file mode 100644
index 000000000..2733d17ca
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/base_test.cpp
@@ -0,0 +1,392 @@
+// not compiled
+#include <map>
+#include <mcl/op.hpp>
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/xorshift.hpp>
+#include <cybozu/bit_operation.hpp>
+#include <mcl/conversion.hpp>
+#include <mcl/fp.hpp>
+
+#include "../src/fp_generator.hpp"
+#if (CYBOZU_HOST == CYBOZU_HOST_INTEL) && (MCL_SIZEOF_UNIT == 8)
+ #define USE_XBYAK
+ static mcl::FpGenerator fg;
+#endif
+#define PUT(x) std::cout << #x "=" << (x) << std::endl
+
+const size_t MAX_N = 32;
+typedef mcl::fp::Unit Unit;
+
+size_t getUnitSize(size_t bitSize)
+{
+ return (bitSize + sizeof(Unit) * 8 - 1) / (sizeof(Unit) * 8);
+}
+
+void setMpz(mpz_class& mx, const Unit *x, size_t n)
+{
+ mcl::gmp::setArray(mx, x, n);
+}
+void getMpz(Unit *x, size_t n, const mpz_class& mx)
+{
+ mcl::fp::toArray(x, n, mx.get_mpz_t());
+}
+
+struct Montgomery {
+ mpz_class p_;
+ mpz_class R_; // (1 << (n_ * 64)) % p
+ mpz_class RR_; // (R * R) % p
+ Unit r_; // p * r = -1 mod M = 1 << 64
+ size_t n_;
+ Montgomery() {}
+ explicit Montgomery(const mpz_class& p)
+ {
+ p_ = p;
+ r_ = mcl::montgomery::getCoff(mcl::gmp::getUnit(p, 0));
+ n_ = mcl::gmp::getUnitSize(p);
+ R_ = 1;
+ R_ = (R_ << (n_ * 64)) % p_;
+ RR_ = (R_ * R_) % p_;
+ }
+
+ void toMont(mpz_class& x) const { mul(x, x, RR_); }
+ void fromMont(mpz_class& x) const { mul(x, x, 1); }
+
+ void mont(Unit *z, const Unit *x, const Unit *y) const
+ {
+ mpz_class mx, my;
+ setMpz(mx, x, n_);
+ setMpz(my, y, n_);
+ mul(mx, mx, my);
+ getMpz(z, n_, mx);
+ }
+ void mul(mpz_class& z, const mpz_class& x, const mpz_class& y) const
+ {
+#if 1
+ const size_t ySize = mcl::gmp::getUnitSize(y);
+ mpz_class c = y == 0 ? mpz_class(0) : x * mcl::gmp::getUnit(y, 0);
+ Unit q = c == 0 ? 0 : mcl::gmp::getUnit(c, 0) * r_;
+ c += p_ * q;
+ c >>= sizeof(Unit) * 8;
+ for (size_t i = 1; i < n_; i++) {
+ if (i < ySize) {
+ c += x * mcl::gmp::getUnit(y, i);
+ }
+ Unit q = c == 0 ? 0 : mcl::gmp::getUnit(c, 0) * r_;
+ c += p_ * q;
+ c >>= sizeof(Unit) * 8;
+ }
+ if (c >= p_) {
+ c -= p_;
+ }
+ z = c;
+#else
+ z = x * y;
+ const size_t zSize = mcl::gmp::getUnitSize(z);
+ for (size_t i = 0; i < n_; i++) {
+ if (i < zSize) {
+ Unit q = mcl::gmp::getUnit(z, 0) * r_;
+ z += p_ * (mp_limb_t)q;
+ }
+ z >>= sizeof(Unit) * 8;
+ }
+ if (z >= p_) {
+ z -= p_;
+ }
+#endif
+ }
+};
+
+void put(const char *msg, const Unit *x, size_t n)
+{
+ printf("%s ", msg);
+ for (size_t i = 0; i < n; i++) printf("%016llx ", (long long)x[n - 1 - i]);
+ printf("\n");
+}
+void verifyEqual(const Unit *x, const Unit *y, size_t n, const char *file, int line)
+{
+ bool ok = mcl::fp::isEqualArray(x, y, n);
+ CYBOZU_TEST_ASSERT(ok);
+ if (ok) return;
+ printf("%s:%d\n", file, line);
+ put("L", x, n);
+ put("R", y, n);
+ exit(1);
+}
+#define VERIFY_EQUAL(x, y, n) verifyEqual(x, y, n, __FILE__, __LINE__)
+
+void addC(Unit *z, const Unit *x, const Unit *y, const Unit *p, size_t n)
+{
+ mpz_class mx, my, mp;
+ setMpz(mx, x, n);
+ setMpz(my, y, n);
+ setMpz(mp, p, n);
+ mx += my;
+ if (mx >= mp) mx -= mp;
+ getMpz(z, n, mx);
+}
+void subC(Unit *z, const Unit *x, const Unit *y, const Unit *p, size_t n)
+{
+ mpz_class mx, my, mp;
+ setMpz(mx, x, n);
+ setMpz(my, y, n);
+ setMpz(mp, p, n);
+ mx -= my;
+ if (mx < 0) mx += mp;
+ getMpz(z, n, mx);
+}
+static inline void set_zero(mpz_t& z, Unit *p, size_t n)
+{
+ z->_mp_alloc = (int)n;
+ z->_mp_size = 0;
+ z->_mp_d = (mp_limb_t*)p;
+}
+static inline void set_mpz_t(mpz_t& z, const Unit* p, int n)
+{
+ z->_mp_alloc = n;
+ int i = n;
+ while (i > 0 && p[i - 1] == 0) {
+ i--;
+ }
+ z->_mp_size = i;
+ z->_mp_d = (mp_limb_t*)p;
+}
+
+// z[2n] <- x[n] * y[n]
+void mulPreC(Unit *z, const Unit *x, const Unit *y, size_t n)
+{
+#if 1
+ mpz_t mx, my, mz;
+ set_zero(mz, z, n * 2);
+ set_mpz_t(mx, x, n);
+ set_mpz_t(my, y, n);
+ mpz_mul(mz, mx, my);
+ mcl::fp::toArray(z, n * 2, mz);
+#else
+ mpz_class mx, my;
+ setMpz(mx, x, n);
+ setMpz(my, y, n);
+ mx *= my;
+ getMpz(z, n * 2, mx);
+#endif
+}
+
+void modC(Unit *y, const Unit *x, const Unit *p, size_t n)
+{
+ mpz_t mx, my, mp;
+ set_mpz_t(mx, x, n * 2);
+ set_mpz_t(my, y, n);
+ set_mpz_t(mp, p, n);
+ mpz_mod(my, mx, mp);
+ mcl::fp::clearArray(y, my->_mp_size, n);
+}
+
+void mul(Unit *z, const Unit *x, const Unit *y, const Unit *p, size_t n)
+{
+ Unit ret[MAX_N * 2];
+ mpz_t mx, my, mz, mp;
+ set_zero(mz, ret, MAX_N * 2);
+ set_mpz_t(mx, x, n);
+ set_mpz_t(my, y, n);
+ set_mpz_t(mp, p, n);
+ mpz_mul(mz, mx, my);
+ mpz_mod(mz, mz, mp);
+ mcl::fp::toArray(z, n, mz);
+}
+
+typedef mcl::fp::void3op void3op;
+typedef mcl::fp::void4op void4op;
+typedef mcl::fp::void4Iop void4Iop;
+
+const struct FuncOp {
+ size_t bitSize;
+ void4op addS;
+ void4op addL;
+ void4op subS;
+ void4op subL;
+ void3op mulPre;
+ void4Iop mont;
+} gFuncOpTbl[] = {
+ { 128, mcl_fp_add128S, mcl_fp_add128L, mcl_fp_sub128S, mcl_fp_sub128L, mcl_fp_mul128pre, mcl_fp_mont128 },
+ { 192, mcl_fp_add192S, mcl_fp_add192L, mcl_fp_sub192S, mcl_fp_sub192L, mcl_fp_mul192pre, mcl_fp_mont192 },
+ { 256, mcl_fp_add256S, mcl_fp_add256L, mcl_fp_sub256S, mcl_fp_sub256L, mcl_fp_mul256pre, mcl_fp_mont256 },
+ { 320, mcl_fp_add320S, mcl_fp_add320L, mcl_fp_sub320S, mcl_fp_sub320L, mcl_fp_mul320pre, mcl_fp_mont320 },
+ { 384, mcl_fp_add384S, mcl_fp_add384L, mcl_fp_sub384S, mcl_fp_sub384L, mcl_fp_mul384pre, mcl_fp_mont384 },
+ { 448, mcl_fp_add448S, mcl_fp_add448L, mcl_fp_sub448S, mcl_fp_sub448L, mcl_fp_mul448pre, mcl_fp_mont448 },
+ { 512, mcl_fp_add512S, mcl_fp_add512L, mcl_fp_sub512S, mcl_fp_sub512L, mcl_fp_mul512pre, mcl_fp_mont512 },
+#if MCL_SIZEOF_UNIT == 4
+ { 160, mcl_fp_add160S, mcl_fp_add160L, mcl_fp_sub160S, mcl_fp_sub160L, mcl_fp_mul160pre, mcl_fp_mont160 },
+ { 224, mcl_fp_add224S, mcl_fp_add224L, mcl_fp_sub224S, mcl_fp_sub224L, mcl_fp_mul224pre, mcl_fp_mont224 },
+ { 288, mcl_fp_add288S, mcl_fp_add288L, mcl_fp_sub288S, mcl_fp_sub288L, mcl_fp_mul288pre, mcl_fp_mont288 },
+ { 352, mcl_fp_add352S, mcl_fp_add352L, mcl_fp_sub352S, mcl_fp_sub352L, mcl_fp_mul352pre, mcl_fp_mont352 },
+ { 416, mcl_fp_add416S, mcl_fp_add416L, mcl_fp_sub416S, mcl_fp_sub416L, mcl_fp_mul416pre, mcl_fp_mont416 },
+ { 480, mcl_fp_add480S, mcl_fp_add480L, mcl_fp_sub480S, mcl_fp_sub480L, mcl_fp_mul480pre, mcl_fp_mont480 },
+ { 544, mcl_fp_add544S, mcl_fp_add544L, mcl_fp_sub544S, mcl_fp_sub544L, mcl_fp_mul544pre, mcl_fp_mont544 },
+#else
+ { 576, mcl_fp_add576S, mcl_fp_add576L, mcl_fp_sub576S, mcl_fp_sub576L, mcl_fp_mul576pre, mcl_fp_mont576 },
+#endif
+};
+
+FuncOp getFuncOp(size_t bitSize)
+{
+ typedef std::map<size_t, FuncOp> Map;
+ static Map map;
+ static bool init = false;
+ if (!init) {
+ init = true;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(gFuncOpTbl); i++) {
+ map[gFuncOpTbl[i].bitSize] = gFuncOpTbl[i];
+ }
+ }
+ for (Map::const_iterator i = map.begin(), ie = map.end(); i != ie; ++i) {
+ if (bitSize <= i->second.bitSize) {
+ return i->second;
+ }
+ }
+ printf("ERR bitSize=%d\n", (int)bitSize);
+ exit(1);
+}
+
+void test(const Unit *p, size_t bitSize)
+{
+ printf("bitSize %d\n", (int)bitSize);
+ const size_t n = getUnitSize(bitSize);
+#ifdef NDEBUG
+ bool doBench = true;
+#else
+ bool doBench = false;
+#endif
+ const FuncOp funcOp = getFuncOp(bitSize);
+ const void4op addS = funcOp.addS;
+ const void4op addL = funcOp.addL;
+ const void4op subS = funcOp.subS;
+ const void4op subL = funcOp.subL;
+ const void3op mulPre = funcOp.mulPre;
+ const void4Iop mont = funcOp.mont;
+
+ mcl::fp::Unit x[MAX_N], y[MAX_N];
+ mcl::fp::Unit z[MAX_N], w[MAX_N];
+ mcl::fp::Unit z2[MAX_N * 2];
+ mcl::fp::Unit w2[MAX_N * 2];
+ cybozu::XorShift rg;
+ mcl::fp::getRandVal(x, rg, p, bitSize);
+ mcl::fp::getRandVal(y, rg, p, bitSize);
+ const size_t C = 10;
+
+ addC(z, x, y, p, n);
+ addS(w, x, y, p);
+ VERIFY_EQUAL(z, w, n);
+ for (size_t i = 0; i < C; i++) {
+ addC(z, y, z, p, n);
+ addS(w, y, w, p);
+ VERIFY_EQUAL(z, w, n);
+ addC(z, y, z, p, n);
+ addL(w, y, w, p);
+ VERIFY_EQUAL(z, w, n);
+ subC(z, x, z, p, n);
+ subS(w, x, w, p);
+ VERIFY_EQUAL(z, w, n);
+ subC(z, x, z, p, n);
+ subL(w, x, w, p);
+ VERIFY_EQUAL(z, w, n);
+ mulPreC(z2, x, z, n);
+ mulPre(w2, x, z);
+ VERIFY_EQUAL(z2, w2, n * 2);
+ }
+ {
+ mpz_class mp;
+ setMpz(mp, p, n);
+ Montgomery m(mp);
+#ifdef USE_XBYAK
+ if (bitSize > 128) fg.init(p, n);
+#endif
+ /*
+ real mont
+ 0 0
+ 1 R^-1
+ R 1
+ -1 -R^-1
+ -R -1
+ */
+ mpz_class t = 1;
+ const mpz_class R = (t << (n * 64)) % mp;
+ const mpz_class tbl[] = {
+ 0, 1, R, mp - 1, mp - R
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const mpz_class& mx = tbl[i];
+ for (size_t j = i; j < CYBOZU_NUM_OF_ARRAY(tbl); j++) {
+ const mpz_class& my = tbl[j];
+ getMpz(x, n, mx);
+ getMpz(y, n, my);
+ m.mont(z, x, y);
+ mont(w, x, y, p, m.r_);
+ VERIFY_EQUAL(z, w, n);
+#ifdef USE_XBYAK
+ if (bitSize > 128) {
+ fg.mul_(w, x, y);
+ VERIFY_EQUAL(z, w, n);
+ }
+#endif
+ }
+ }
+ if (doBench) {
+// CYBOZU_BENCH("montC", m.mont, x, y, x);
+ CYBOZU_BENCH("montA ", mont, x, y, x, p, m.r_);
+ }
+ }
+ if (doBench) {
+// CYBOZU_BENCH("addS", addS, x, y, x, p); // slow
+// CYBOZU_BENCH("subS", subS, x, y, x, p);
+// CYBOZU_BENCH("addL", addL, x, y, x, p);
+// CYBOZU_BENCH("subL", subL, x, y, x, p);
+ CYBOZU_BENCH("mulPreA", mulPre, w2, y, x);
+ CYBOZU_BENCH("mulPreC", mulPreC, w2, y, x, n);
+ CYBOZU_BENCH("modC ", modC, x, w2, p, n);
+ }
+#ifdef USE_XBYAK
+ if (bitSize <= 128) return;
+ if (doBench) {
+ fg.init(p, n);
+ CYBOZU_BENCH("addA ", fg.add_, x, y, x);
+ CYBOZU_BENCH("subA ", fg.sub_, x, y, x);
+// CYBOZU_BENCH("mulA", fg.mul_, x, y, x);
+ }
+#endif
+ printf("mont test %d\n", (int)bitSize);
+}
+
+CYBOZU_TEST_AUTO(all)
+{
+ const struct {
+ size_t n;
+ const uint64_t p[9];
+ } tbl[] = {
+// { 2, { 0xf000000000000001, 1, } },
+ { 2, { 0x000000000000001d, 0x8000000000000000, } },
+ { 3, { 0x000000000000012b, 0x0000000000000000, 0x0000000080000000, } },
+// { 3, { 0x0f69466a74defd8d, 0xfffffffe26f2fc17, 0x07ffffffffffffff, } },
+// { 3, { 0x7900342423332197, 0x1234567890123456, 0x1480948109481904, } },
+ { 3, { 0x0f69466a74defd8d, 0xfffffffe26f2fc17, 0xffffffffffffffff, } },
+// { 4, { 0x7900342423332197, 0x4242342420123456, 0x1234567892342342, 0x1480948109481904, } },
+// { 4, { 0x0f69466a74defd8d, 0xfffffffe26f2fc17, 0x17ffffffffffffff, 0x1513423423423415, } },
+ { 4, { 0xa700000000000013, 0x6121000000000013, 0xba344d8000000008, 0x2523648240000001, } },
+// { 5, { 0x0000000000000009, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x8000000000000000, } },
+ { 5, { 0xfffffffffffffc97, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, } },
+// { 6, { 0x4720422423332197, 0x0034230847204720, 0x3456789012345679, 0x4820984290482212, 0x9482094820948209, 0x0194810841094810, } },
+// { 6, { 0x7204224233321972, 0x0342308472047204, 0x4567890123456790, 0x0948204204243123, 0x2098420984209482, 0x2093482094810948, } },
+ { 6, { 0x00000000ffffffff, 0xffffffff00000000, 0xfffffffffffffffe, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, } },
+// { 7, { 0x0000000000000063, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x8000000000000000, } },
+ { 7, { 0x000000000fffcff1, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, } },
+ { 8, { 0xffffffffffffd0c9, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, } },
+ { 9, { 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x00000000000001ff, } },
+// { 9, { 0x4720422423332197, 0x0034230847204720, 0x3456789012345679, 0x2498540975555312, 0x9482904924029424, 0x0948209842098402, 0x1098410948109482, 0x0820958209582094, 0x0000000000000029, } },
+// { 9, { 0x0f69466a74defd8d, 0xfffffffe26f2fc17, 0x7fffffffffffffff, 0x8572938572398583, 0x5732057823857293, 0x9820948205872380, 0x3409238420492034, 0x9483842098340298, 0x0000000000000003, } },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const size_t n = tbl[i].n;
+ const size_t bitSize = (n - 1) * 64 + cybozu::bsr<uint64_t>(tbl[i].p[n - 1]) + 1;
+ test((const Unit*)tbl[i].p, bitSize);
+ }
+}
+
diff --git a/vendor/github.com/dexon-foundation/mcl/test/bench.hpp b/vendor/github.com/dexon-foundation/mcl/test/bench.hpp
new file mode 100644
index 000000000..cc1639e6e
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/bench.hpp
@@ -0,0 +1,192 @@
+#include <mcl/lagrange.hpp>
+
+void benchAddDblG1()
+{
+ puts("benchAddDblG1");
+ const int C = 100000;
+ G1 P1, P2, P3;
+ hashAndMapToG1(P1, "a");
+ hashAndMapToG1(P2, "b");
+ P1 += P2;
+ P2 += P1;
+ printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne());
+ CYBOZU_BENCH_C("G1::add(1)", C, G1::add, P3, P1, P2);
+ P1.normalize();
+ printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne());
+ CYBOZU_BENCH_C("G1::add(2)", C, G1::add, P3, P1, P2);
+ CYBOZU_BENCH_C("G1::add(3)", C, G1::add, P3, P2, P1);
+ P2.normalize();
+ printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne());
+ CYBOZU_BENCH_C("G1::add(4)", C, G1::add, P3, P1, P2);
+ P1 = P3;
+ printf("z.isOne()=%d\n", P1.z.isOne());
+ CYBOZU_BENCH_C("G1::dbl(1)", C, G1::dbl, P3, P1);
+ P1.normalize();
+ printf("z.isOne()=%d\n", P1.z.isOne());
+ CYBOZU_BENCH_C("G1::dbl(2)", C, G1::dbl, P3, P1);
+}
+
+void benchAddDblG2()
+{
+ puts("benchAddDblG2");
+ const int C = 100000;
+ G2 P1, P2, P3;
+ hashAndMapToG2(P1, "a");
+ hashAndMapToG2(P2, "b");
+ P1 += P2;
+ P2 += P1;
+ printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne());
+ CYBOZU_BENCH_C("G2::add(1)", C, G2::add, P3, P1, P2);
+ P1.normalize();
+ printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne());
+ CYBOZU_BENCH_C("G2::add(2)", C, G2::add, P3, P1, P2);
+ CYBOZU_BENCH_C("G2::add(3)", C, G2::add, P3, P2, P1);
+ P2.normalize();
+ printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne());
+ CYBOZU_BENCH_C("G2::add(4)", C, G2::add, P3, P1, P2);
+ P1 = P3;
+ printf("z.isOne()=%d\n", P1.z.isOne());
+ CYBOZU_BENCH_C("G2::dbl(1)", C, G2::dbl, P3, P1);
+ P1.normalize();
+ printf("z.isOne()=%d\n", P1.z.isOne());
+ CYBOZU_BENCH_C("G2::dbl(2)", C, G2::dbl, P3, P1);
+}
+
+
+void testBench(const G1& P, const G2& Q)
+{
+ G1 Pa;
+ G2 Qa;
+ Fp12 e1, e2;
+ pairing(e1, P, Q);
+ Fp12::pow(e2, e1, 12345);
+ Fp x, y;
+ x.setHashOf("abc");
+ y.setHashOf("xyz");
+ const int C = 1000;
+ const int C3 = 100000;
+#if 1
+ const int C2 = 3000;
+ mpz_class a = x.getMpz();
+ CYBOZU_BENCH_C("G1::mulCT ", C, G1::mulCT, Pa, P, a);
+ CYBOZU_BENCH_C("G1::mul ", C, G1::mul, Pa, Pa, a);
+ CYBOZU_BENCH_C("G1::add ", C, G1::add, Pa, Pa, P);
+ CYBOZU_BENCH_C("G1::dbl ", C, G1::dbl, Pa, Pa);
+ CYBOZU_BENCH_C("G2::mulCT ", C, G2::mulCT, Qa, Q, a);
+ CYBOZU_BENCH_C("G2::mul ", C, G2::mul, Qa, Qa, a);
+ CYBOZU_BENCH_C("G2::add ", C, G2::add, Qa, Qa, Q);
+ CYBOZU_BENCH_C("G2::dbl ", C, G2::dbl, Qa, Qa);
+ CYBOZU_BENCH_C("GT::pow ", C, GT::pow, e1, e1, a);
+// CYBOZU_BENCH_C("GT::powGLV ", C, BN::param.glv2.pow, e1, e1, a);
+ G1 PP;
+ G2 QQ;
+ std::string s;
+ s = P.getStr();
+ CYBOZU_BENCH_C("G1::setStr chk", C, PP.setStr, s);
+ verifyOrderG1(false);
+ CYBOZU_BENCH_C("G1::setStr ", C, PP.setStr, s);
+ verifyOrderG1(true);
+ s = Q.getStr();
+ CYBOZU_BENCH_C("G2::setStr chk", C, QQ.setStr, s);
+ verifyOrderG2(false);
+ CYBOZU_BENCH_C("G2::setStr ", C, QQ.setStr, s);
+ verifyOrderG2(true);
+ CYBOZU_BENCH_C("hashAndMapToG1", C, hashAndMapToG1, PP, "abc", 3);
+ CYBOZU_BENCH_C("hashAndMapToG2", C, hashAndMapToG2, QQ, "abc", 3);
+#endif
+ CYBOZU_BENCH_C("Fp::add ", C3, Fp::add, x, x, y);
+ CYBOZU_BENCH_C("Fp::sub ", C3, Fp::sub, x, x, y);
+ CYBOZU_BENCH_C("Fp::neg ", C3, Fp::neg, x, x);
+ CYBOZU_BENCH_C("Fp::mul ", C3, Fp::mul, x, x, y);
+ CYBOZU_BENCH_C("Fp::sqr ", C3, Fp::sqr, x, x);
+ CYBOZU_BENCH_C("Fp::inv ", C3, Fp::inv, x, x);
+ Fp2 xx, yy;
+ xx.a = x;
+ xx.b = 3;
+ yy.a = y;
+ yy.b = -5;
+ FpDbl d0, d1;
+ x = 9;
+ y = 3;
+#if 1
+ CYBOZU_BENCH_C("Fp2::add ", C3, Fp2::add, xx, xx, yy);
+ CYBOZU_BENCH_C("Fp2::sub ", C3, Fp2::sub, xx, xx, yy);
+ CYBOZU_BENCH_C("Fp2::neg ", C3, Fp2::neg, xx, xx);
+ CYBOZU_BENCH_C("Fp2::mul ", C3, Fp2::mul, xx, xx, yy);
+ CYBOZU_BENCH_C("Fp2::mul_xi ", C3, Fp2::mul_xi, xx, xx);
+ CYBOZU_BENCH_C("Fp2::sqr ", C3, Fp2::sqr, xx, xx);
+ CYBOZU_BENCH_C("Fp2::inv ", C3, Fp2::inv, xx, xx);
+ CYBOZU_BENCH_C("FpDbl::addPre ", C3, FpDbl::addPre, d1, d1, d0);
+ CYBOZU_BENCH_C("FpDbl::subPre ", C3, FpDbl::subPre, d1, d1, d0);
+ CYBOZU_BENCH_C("FpDbl::add ", C3, FpDbl::add, d1, d1, d0);
+ CYBOZU_BENCH_C("FpDbl::sub ", C3, FpDbl::sub, d1, d1, d0);
+ CYBOZU_BENCH_C("FpDbl::mulPre ", C3, FpDbl::mulPre, d0, x, y);
+ CYBOZU_BENCH_C("FpDbl::sqrPre ", C3, FpDbl::sqrPre, d1, x);
+ CYBOZU_BENCH_C("FpDbl::mod ", C3, FpDbl::mod, x, d0);
+ Fp2Dbl D;
+ CYBOZU_BENCH_C("Fp2Dbl::mulPre ", C3, Fp2Dbl::mulPre, D, xx, yy);
+ CYBOZU_BENCH_C("Fp2Dbl::sqrPre ", C3, Fp2Dbl::sqrPre, D, xx);
+
+ CYBOZU_BENCH_C("GT::add ", C2, GT::add, e1, e1, e2);
+ CYBOZU_BENCH_C("GT::mul ", C2, GT::mul, e1, e1, e2);
+ CYBOZU_BENCH_C("GT::sqr ", C2, GT::sqr, e1, e1);
+ CYBOZU_BENCH_C("GT::inv ", C2, GT::inv, e1, e1);
+#endif
+ CYBOZU_BENCH_C("FpDbl::mulPre ", C3, FpDbl::mulPre, d0, x, y);
+ CYBOZU_BENCH_C("pairing ", 3000, pairing, e1, P, Q);
+ CYBOZU_BENCH_C("millerLoop ", 3000, millerLoop, e1, P, Q);
+ CYBOZU_BENCH_C("finalExp ", 3000, finalExp, e1, e1);
+//exit(1);
+ std::vector<Fp6> Qcoeff;
+ CYBOZU_BENCH_C("precomputeG2 ", C, precomputeG2, Qcoeff, Q);
+ precomputeG2(Qcoeff, Q);
+ CYBOZU_BENCH_C("precomputedML ", C, precomputedMillerLoop, e2, P, Qcoeff);
+}
+
+inline void SquareRootPrecomputeTest(const mpz_class& p)
+{
+ mcl::SquareRoot sq1, sq2;
+ bool b;
+ sq1.set(&b, p, true);
+ CYBOZU_TEST_ASSERT(b);
+ CYBOZU_TEST_ASSERT(sq1.isPrecomputed());
+ sq2.set(&b, p, false);
+ CYBOZU_TEST_ASSERT(sq1 == sq2);
+ if (sq1 != sq2) {
+ puts("dump");
+ puts("sq1");
+ sq1.dump();
+ puts("sq2");
+ sq2.dump();
+ puts("---");
+ }
+}
+
+void testSquareRoot()
+{
+ if (BN::param.cp == mcl::BN254 || BN::param.cp == mcl::BLS12_381) {
+ SquareRootPrecomputeTest(BN::param.p);
+ SquareRootPrecomputeTest(BN::param.r);
+ }
+}
+
+void testLagrange()
+{
+ puts("testLagrange");
+ const int k = 7;
+ Fr c[k], x[k], y[k];
+ for (size_t i = 0; i < k; i++) {
+ c[i].setByCSPRNG();
+ x[i].setByCSPRNG();
+ }
+ for (size_t i = 0; i < k; i++) {
+ mcl::evaluatePolynomial(y[i], c, k, x[i]);
+ }
+ Fr s;
+ mcl::LagrangeInterpolation(s, x, y, k);
+ CYBOZU_TEST_EQUAL(s, c[0]);
+ mcl::LagrangeInterpolation(s, x, y, 1);
+ CYBOZU_TEST_EQUAL(s, y[0]);
+ mcl::evaluatePolynomial(y[0], c, 1, x[0]);
+ CYBOZU_TEST_EQUAL(y[0], c[0]);
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/bls12_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bls12_test.cpp
new file mode 100644
index 000000000..7011516bd
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/bls12_test.cpp
@@ -0,0 +1,720 @@
+#define PUT(x) std::cout << #x "=" << x << std::endl;
+#define CYBOZU_TEST_DISABLE_AUTO_RUN
+#include <cybozu/benchmark.hpp>
+cybozu::CpuClock clk;
+#include <cybozu/test.hpp>
+#include <mcl/bls12_381.hpp>
+#include <cybozu/option.hpp>
+#include <cybozu/xorshift.hpp>
+
+#if defined(__EMSCRIPTEN__) && !defined(MCL_AVOID_EXCEPTION_TEST)
+ #define MCL_AVOID_EXCEPTION_TEST
+#endif
+
+using namespace mcl::bls12;
+
+mcl::fp::Mode g_mode;
+
+const struct TestSet {
+ mcl::CurveParam cp;
+ const char *name;
+ const char *p;
+ const char *r;
+ struct G2 {
+ const char *aa;
+ const char *ab;
+ const char *ba;
+ const char *bb;
+ } g2;
+ struct G1 {
+ const char *a;
+ const char *b;
+ } g1;
+ const char *e;
+} g_testSetTbl[] = {
+ {
+ mcl::BLS12_381,
+ "BLS12_381",
+ "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
+ "0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001",
+ {
+ "0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8",
+ "0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e",
+ "0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801",
+ "0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be",
+ },
+ {
+ "0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb",
+ "0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1",
+ },
+ "0x1250EBD871FC0A92A7B2D83168D0D727272D441BEFA15C503DD8E90CE98DB3E7B6D194F60839C508A84305AACA1789B6 "
+ "0x089A1C5B46E5110B86750EC6A532348868A84045483C92B7AF5AF689452EAFABF1A8943E50439F1D59882A98EAA0170F "
+ "0x1368BB445C7C2D209703F239689CE34C0378A68E72A6B3B216DA0E22A5031B54DDFF57309396B38C881C4C849EC23E87 "
+ "0x193502B86EDB8857C273FA075A50512937E0794E1E65A7617C90D8BD66065B1FFFE51D7A579973B1315021EC3C19934F "
+ "0x01B2F522473D171391125BA84DC4007CFBF2F8DA752F7C74185203FCCA589AC719C34DFFBBAAD8431DAD1C1FB597AAA5 "
+ "0x018107154F25A764BD3C79937A45B84546DA634B8F6BE14A8061E55CCEBA478B23F7DACAA35C8CA78BEAE9624045B4B6 "
+ "0x19F26337D205FB469CD6BD15C3D5A04DC88784FBB3D0B2DBDEA54D43B2B73F2CBB12D58386A8703E0F948226E47EE89D "
+ "0x06FBA23EB7C5AF0D9F80940CA771B6FFD5857BAAF222EB95A7D2809D61BFE02E1BFD1B68FF02F0B8102AE1C2D5D5AB1A "
+ "0x11B8B424CD48BF38FCEF68083B0B0EC5C81A93B330EE1A677D0D15FF7B984E8978EF48881E32FAC91B93B47333E2BA57 "
+ "0x03350F55A7AEFCD3C31B4FCB6CE5771CC6A0E9786AB5973320C806AD360829107BA810C5A09FFDD9BE2291A0C25A99A2 "
+ "0x04C581234D086A9902249B64728FFD21A189E87935A954051C7CDBA7B3872629A4FAFC05066245CB9108F0242D0FE3EF "
+ "0x0F41E58663BF08CF068672CBD01A7EC73BACA4D72CA93544DEFF686BFD6DF543D48EAA24AFE47E1EFDE449383B676631 "
+ },
+};
+
+CYBOZU_TEST_AUTO(size)
+{
+ CYBOZU_TEST_EQUAL(sizeof(Fp), 48u);
+ CYBOZU_TEST_EQUAL(sizeof(Fr), 32u);
+ CYBOZU_TEST_EQUAL(sizeof(Fp2), sizeof(Fp) * 2);
+ CYBOZU_TEST_EQUAL(sizeof(Fp6), sizeof(Fp) * 6);
+ CYBOZU_TEST_EQUAL(sizeof(Fp12), sizeof(Fp) * 12);
+ CYBOZU_TEST_EQUAL(sizeof(G1), sizeof(Fp) * 3);
+ CYBOZU_TEST_EQUAL(sizeof(G2), sizeof(Fp2) * 3);
+}
+
+void testParam(const TestSet& ts)
+{
+ CYBOZU_TEST_EQUAL(BN::param.r, mpz_class(ts.r));
+ CYBOZU_TEST_EQUAL(BN::param.p, mpz_class(ts.p));
+}
+
+void finalExpC(Fp12& y, const Fp12& x)
+{
+ const mpz_class& r = BN::param.r;
+ const mpz_class& p = BN::param.p;
+ mpz_class p2 = p * p;
+ mpz_class p4 = p2 * p2;
+#if 1
+ Fp12::pow(y, x, p2 + 1);
+ Fp12::pow(y, y, p4 * p2 - 1);
+ Fp12::pow(y, y, (p4 - p2 + 1) / r * 3);
+#else
+ Fp12::pow(y, x, (p4 * p4 * p4 - 1) / r * 3);
+#endif
+}
+
+void pairingC(Fp12& e, const G1& P, const G2& Q)
+{
+ millerLoop(e, P, Q);
+ finalExp(e, e);
+}
+void testIoAll(const G1& P, const G2& Q)
+{
+ const int FpTbl[] = { 0, 2, 2|mcl::IoPrefix, 10, 16, 16|mcl::IoPrefix, mcl::IoArray, mcl::IoArrayRaw };
+ const int EcTbl[] = { mcl::IoEcAffine, mcl::IoEcProj, mcl::IoEcCompY, mcl::IoSerialize };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(FpTbl); i++) {
+ for (size_t j = 0; j < CYBOZU_NUM_OF_ARRAY(EcTbl); j++) {
+ G1 P2 = P, P3;
+ G2 Q2 = Q, Q3;
+ int ioMode = FpTbl[i] | EcTbl[j];
+ std::string s = P2.getStr(ioMode);
+ P3.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(P2, P3);
+ s = Q2.getStr(ioMode);
+ Q3.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(Q2, Q3);
+ s = P.x.getStr(ioMode);
+ Fp Px;
+ Px.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(P.x, Px);
+ s = Q.x.getStr(ioMode);
+ Fp2 Qx;
+ Qx.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(Q.x, Qx);
+ }
+ }
+}
+
+void testIo(const G1& P, const G2& Q)
+{
+ testIoAll(P, Q);
+ G1 Z1;
+ G2 Z2;
+ Z1.clear();
+ Z2.clear();
+ testIoAll(Z1, Z2);
+}
+
+void testSetStr(const G2& Q0)
+{
+ G2::setCompressedExpression();
+ G2 Q;
+ Q.clear();
+ for (int i = 0; i < 10; i++) {
+ G2 R;
+ R.setStr(Q.getStr());
+ CYBOZU_TEST_EQUAL(Q, R);
+ G2::add(Q, Q, Q0);
+ }
+}
+
+void testMapToG1()
+{
+ G1 g;
+ for (int i = 1; i < 10; i++) {
+ mapToG1(g, i);
+ CYBOZU_TEST_ASSERT(!g.isZero());
+ G1 gr;
+ G1::mul(gr, g, BN::param.r);
+ CYBOZU_TEST_ASSERT(gr.isZero());
+ }
+}
+
+void testMapToG2()
+{
+ G2 g;
+ for (int i = 1; i < 10; i++) {
+ mapToG2(g, i);
+ CYBOZU_TEST_ASSERT(!g.isZero());
+ G2 gr;
+ G2::mul(gr, g, BN::param.r);
+ CYBOZU_TEST_ASSERT(gr.isZero());
+ }
+ Fp x;
+ x.setHashOf("abc");
+ mapToG2(g, Fp2(x, 0));
+ CYBOZU_TEST_ASSERT(g.isValid());
+}
+
+void testPrecomputed(const G1& P, const G2& Q)
+{
+ Fp12 e1, e2;
+ pairing(e1, P, Q);
+ std::vector<Fp6> Qcoeff;
+ precomputeG2(Qcoeff, Q);
+ precomputedMillerLoop(e2, P, Qcoeff);
+ finalExp(e2, e2);
+ CYBOZU_TEST_EQUAL(e1, e2);
+}
+
+#if 0
+void testFp12pow(const G1& P, const G2& Q)
+{
+ Fp12 e, e1, e2;
+ pairing(e, P, Q);
+ cybozu::XorShift rg;
+ for (int i = -10; i < 10; i++) {
+ mpz_class xm = i;
+ Fp12::pow(e1, e, xm);
+ Fp12::powGeneric(e2, e, xm);
+ CYBOZU_TEST_EQUAL(e1, e2);
+ }
+ for (int i = 0; i < 10; i++) {
+ Fr x;
+ x.setRand(rg);
+ mpz_class xm = x.getMpz();
+ Fp12::pow(e1, e, xm);
+ param.glv2.pow(e2, e, xm);
+ CYBOZU_TEST_EQUAL(e1, e2);
+ }
+}
+#endif
+
+void testMillerLoop2(const G1& P1, const G2& Q1)
+{
+ Fp12 e1, e2, e3;
+ mpz_class c1("12342342423442");
+ mpz_class c2("329428049820348209482");
+ G2 Q2;
+ G1 P2;
+ G2::mul(Q2, Q1, c1);
+ G1::mul(P2, P1, c2);
+ pairing(e1, P1, Q1);
+ pairing(e2, P2, Q2);
+ e1 *= e2;
+
+ std::vector<Fp6> Q1coeff, Q2coeff;
+ precomputeG2(Q1coeff, Q1);
+ precomputeG2(Q2coeff, Q2);
+ precomputedMillerLoop2(e2, P1, Q1coeff, P2, Q2coeff);
+ precomputedMillerLoop2mixed(e3, P1, Q1, P2, Q2coeff);
+ CYBOZU_TEST_EQUAL(e2, e3);
+ finalExp(e2, e2);
+ CYBOZU_TEST_EQUAL(e1, e2);
+
+ // special value
+ G2 Z;
+ Z.clear();
+ Q2 += Q2;
+ precomputeG2(Q1coeff, Z);
+ precomputeG2(Q2coeff, Q2);
+ precomputedMillerLoop2(e2, P1, Q1coeff, P2, Q2coeff);
+ precomputedMillerLoop2mixed(e3, P1, Z, P2, Q2coeff);
+ finalExp(e2, e2);
+ finalExp(e3, e3);
+ CYBOZU_TEST_EQUAL(e2, e3);
+}
+
+void testPairing(const G1& P, const G2& Q, const char *eStr)
+{
+ Fp12 e1;
+ pairing(e1, P, Q);
+ Fp12 e2;
+ {
+ std::stringstream ss(eStr);
+ ss >> e2;
+ }
+ CYBOZU_TEST_EQUAL(e1, e2);
+ Fp12 e = e1, ea;
+ G1 Pa;
+ G2 Qa;
+#if defined(__EMSCRIPTEN__) || MCL_SIZEOF_UNIT == 4
+ const int count = 100;
+#else
+ const int count = 1000;
+#endif
+ mpz_class a;
+ cybozu::XorShift rg;
+ for (int i = 0; i < count; i++) {
+ Fr r;
+ r.setRand(rg);
+ a = r.getMpz();
+ Fp12::pow(ea, e, a);
+ G1::mul(Pa, P, a);
+ G2::mul(Qa, Q, a);
+ G1 T;
+ G1::mulCT(T, P, a);
+ CYBOZU_TEST_EQUAL(Pa, T);
+ pairing(e1, Pa, Q);
+ pairing(e2, P, Qa);
+ CYBOZU_TEST_EQUAL(ea, e1);
+ CYBOZU_TEST_EQUAL(ea, e2);
+ }
+}
+
+void testTrivial(const G1& P, const G2& Q)
+{
+ G1 Z1; Z1.clear();
+ G2 Z2; Z2.clear();
+ Fp12 e;
+ pairing(e, Z1, Q);
+ CYBOZU_TEST_EQUAL(e, 1);
+ pairing(e, P, Z2);
+ CYBOZU_TEST_EQUAL(e, 1);
+ pairing(e, Z1, Z2);
+ CYBOZU_TEST_EQUAL(e, 1);
+
+ std::vector<Fp6> Qcoeff;
+ precomputeG2(Qcoeff, Z2);
+ precomputedMillerLoop(e, P, Qcoeff);
+ finalExp(e, e);
+ CYBOZU_TEST_EQUAL(e, 1);
+
+ precomputeG2(Qcoeff, Q);
+ precomputedMillerLoop(e, Z1, Qcoeff);
+ finalExp(e, e);
+ CYBOZU_TEST_EQUAL(e, 1);
+}
+
+#include "bench.hpp"
+
+CYBOZU_TEST_AUTO(naive)
+{
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(g_testSetTbl); i++) {
+ const TestSet& ts = g_testSetTbl[i];
+ printf("i=%d curve=%s\n", int(i), ts.name);
+ initPairing(ts.cp, g_mode);
+ const G1 P(Fp(ts.g1.a), Fp(ts.g1.b));
+ const G2 Q(Fp2(ts.g2.aa, ts.g2.ab), Fp2(ts.g2.ba, ts.g2.bb));
+#ifdef ONLY_BENCH
+ {
+ Fp12 e;
+ for (int i = 0; i < 1000; i++) pairing(e, P, Q);
+ }
+ clk.put();
+ return;
+#endif
+ testParam(ts);
+ testIo(P, Q);
+// testFp12pow(P, Q);
+ testTrivial(P, Q);
+ testSetStr(Q);
+ testMapToG1();
+ testMapToG2();
+ testPairing(P, Q, ts.e);
+ testPrecomputed(P, Q);
+ testMillerLoop2(P, Q);
+ testBench(P, Q);
+ }
+ int count = (int)clk.getCount();
+ if (count) {
+ printf("count=%d ", count);
+ clk.put();
+ }
+}
+
+CYBOZU_TEST_AUTO(finalExp)
+{
+ const char *e0Str =
+"012974491575E232199B73B30FE53FF643FEAE11023BCA7AF961C3600B45DFECFE4B30D52A62E73DA4C0409810304997\n"
+"05CE2FB890FE65E20EC36347190ECB4884E401A64B666557B53E561F6D0979B7A96AD9E647ED78BD47187195C00F563C\n"
+"02E85D1E559488603A70FEE99354DA8847215EC97282CA230DE96FED6DD5D4DD4EF4D901DB7F544A1A45EBEBA1450109\n"
+"048FB1E44DDABF18D55C95704158A24678AA2A6ED0844108762E88306E5880E8C67BF44E24E40AB3F93D9E3713170341\n"
+"07EF7BE685DC0DBA1B3E1D2E9090CD98EAD1325B60881772F17077386A3182B117F5FD839363F5891D08E82B88EC6F12\n"
+"17803435700EF7A16C06404C6D17EB4FD84079FE9872207302A36C791B6E90447B33D703BBFE04ECB641C3A573E2CD50\n"
+"19A494E6A872E46FC85D09FD6D30844B6FF05729BC253A9640F7BE64AAA8C2C8E0AE014A9DD816C53A3EDEBB2FA649EB\n"
+"020949ABAA14F1DCE17FA9E091DDA963E9E492BA788E12B9B610E80A4D94DB9CC50341ED107C7D50E5738052595D4A27\n"
+"09E217B513B3603723DAC3188A2F7CBDD84A56E7E5004446E7D4C63D6E378DA26E411C10898E48DB4B0C065E4699A9C5\n"
+"12393BD23D0EC122082A1EC892A982F3C9AFD14240CE85258D8A3EF0A13CB545D6EF7848FD40DD4AEF1554341C5C5BBF\n"
+"07EA8A0D6A57C78E5663F94E2B1ABC0D760ED18DBA64305EAD5EE350FB0342A7A81C0D5C8B3AD826D009276B0F32D2C8\n"
+"16804D0D4A2633ED01568B0F8F06C4497E46E88D05FD191AAE530ACA791D0E114D74874FA88E33FAF48757153B09BB0E";
+
+const char *e1Str =
+"0E05D19E90D2C501E5502C7AC80D77201C47DF147DD1076440F0DF0179DF9802CA0775E0E73DD9174F1094D2280787B3\n"
+"14D2F5C84279E7177A3543FBEAE261DE8F6C97EFD5F3FF3F959EC9FC0303F620A4B3AF00DF409496CECADDD0A7F0A164\n"
+"1414E9B9DF8DF1EAC2E70D5538018377788C62016A54F28B037A68740705089AE431B86756F98CBE19690A5EAC0C2466\n"
+"12D8B32157836A131CCA3CA313DAAAF909BC3AD6BDD15885BB429922B9CD7D1246D1163E5E6F88D68BF1B75E451EFABB\n"
+"102C9A839A924E0D603D13F2E08A919E0B9EE2A269FC75727BA13D66027C157B9BB4077977FA94557DE4427BF11B234B\n"
+"19DBEB7F2E3096AFFD44837655BD8249741B484B0EB0DBEE569DEA8D9E38AE09D210C8BC16AA6DFBC923095B2C9A8B2B\n"
+"19B9A6DCCD01FA0D04D5CE94D8BDCE1DF64AFEB7FD493B955180A5C6B236E469F0E07CC9BB4203FCAC46AE6F8E5419D6\n"
+"02BFA87AF7A3726A7ABACDCFDD53694AF651554F3A431AB4274F67D5DAD2D6C88AF794705FF456A936C83594731AD8DC\n"
+"0F21E0173E3B50DD98EFA815B410631A57399B451FD6E1056FFD09C9FE50EFAD3D026F0C46C8BB1583A50B7853D990DA\n"
+"02230237AE04B61F9269F6E7CD2FCF1231CEE4690AA658B0018EFC0D0770FD0A56B3B7294086E8D306B1465CDDD858CD\n"
+"087EB8F6547015661E9CD48D6525C808636FCB8420B867CB2A87E006B2A93BBD5EF675E6CDDA9E6F94519C49EA8BB689\n"
+"19F5C988B2DD6E33D7D3D34EFB1991F80DC28006AC75E0AB53FD98FC6F2476D05DD4ECA582F5FF72B8DDD9DDDE80FFC9";
+
+ Fp12 e0, e1, e2;
+ e0.setStr(e0Str, 16);
+ e1.setStr(e1Str, 16);
+ finalExp(e2, e0);
+// finalExpC(e2, e0);
+ CYBOZU_TEST_EQUAL(e1, e2);
+ CYBOZU_BENCH_C("finalExp", 100, finalExp, e2, e0);
+}
+
+CYBOZU_TEST_AUTO(addLine)
+{
+const char *l0Str=
+"0EF586FCDB69442CB41C0DA719AC5C92BD99A916C1F01BCFC7606AA7A23D680C04620FDFC2144E0EA6025F05241A791F\n"
+"164CFDADE9B91150C6D2C7F7CDF29BC3105A7EA51217283CDF801EBEE9E86CE5078253E322C72129DAA42F6DBAD17D37";
+const char *l1Str =
+"07A124F536BE83CCB3AF8D3DA2AE094942755040B9DA8E0796C462ACE3805D6916ACA7E9281261D8025571E2F31AAF0D\n"
+"12D05751A9B255143541D0A4E57E120F937D51F9A07D31982390CA6EB5DF8CC0640FD291521069BF9964AE33EDD1323D";
+const char *l4Str =
+"0D609DE41CF1260B332C1A53AA54703F62AB8224777E34FEEAB09AA06187CA71D8C7C2EB66F59D3622D431BE17D0FEE6\n"
+"0A93C2984041171BE701560017D64D0640B6F61D7DCA8F527FA6B6A1A1033261C0761CAA56A00D4D16C9D3B7371E02D9";
+
+const char *rStr =
+"4 0A8DFA69FDD43EDCCC6375750373B443157EF4641E5B4CA82FBF23E3E8EA72351EA754168CEC77573D337E6227C0D0DD\n"
+"12C8508CF1828C52A9A1A71779129D605327191EE459AED3C0B4B14657B08B2927173FADF8E4275188E8D49E57A75B33\n"
+"12AD7EB96734F2C93B669FD54845CD2FF351AFDF0123E96772021DC3F4F3B456DB1B37CB1C380B1947616165FF0DDAEA\n"
+"03D80F92C8A6005DEB291AF28406B7B4FCEDD81A244997DBB719B01D162BD7D71F0FD63BF76F8F1AC90618C3702294DF\n"
+"199F7A719EA1CA2CD03CFFBB9A4BC2FE1BD8BCA7C772D223E6CB20C1313C3D3C52CFBB88445E56C833908C52A4EC68F1\n"
+"0A3F6B27A6DDA00DB848574ECB06F179271D5844BDA66CD5AE1792A8FDD25E3A504A95839113BAA8B1FCB53EEE5F1FF0";
+
+const char *qStr =
+"4 0B5C339C23F8EAB3647E974BCDDF72C96F97A444346BE72CA73AB1323B83B8F6161257AB34C7E0CF34F6C45086CA5868\n"
+"13C2235E9F9DFB33344BA2EE5A71435859022880732EDC9EC75AC79AE9DA972593CDC40A0AC334D6D2E8D7FAD1D98D0B\n"
+"134B8EED8196A00D3B70ADBC26FF963B725A351CF0B73FE1A541788AFB0BB081AF82A438021B5E878B15D53B1D27C6A7\n"
+"18CC69F847BEE826B939DCB4030D33020D03B046465C9EE103AA8009A175DB169070294E75771586687FE361DB884BCD\n"
+"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\n"
+"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+
+const char *pStr =
+"4 0FD3977C60EC322BC281C915955ED534B491E39C72E8E800271CEF3F0492D890829FA69C45FCE93D9847A0CAB325D871\n"
+"17CC2C36C5D283C05BFCECCF48DBB2050332DA058DD67326A9EE520967DBCAEDFCB5F05A085D1A49DF08BB968CC782C5\n"
+"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001";
+
+const char *m0Str =
+"1010A4F9944514352AAD5D290AFB95C435EB64B5E74519807C9602DABCD6B6F5494E419758AE9A43F539F812252C65E5\n"
+"1622F7A52BAAC10EBFF0977F61866544BF9B91315FA66ADB6AC200AFF7A3676C1AD3480340B23C66F7C6AE50A703F245";
+const char *m1Str =
+"0905180B20FCE2AA545A73D6B9EA1F82479EF3FB5A3BA8DDB656D9B2A4DA7B63CCF75538D15093949B442E27804C8CE2\n"
+"0FE834508BBAD2F22DCBF1C3C1BCCD69561827613EB63F4907832A7ABBBC6040CF2E517D0D5E22D3812EEE1EC55640DD";
+const char *m4Str =
+"1197D94A8DAFE6F72B17A31964CA5D0C3B2A12BEFF959F7DF7A37938C64C01508D12C24479E5C3D314F862A9977D6C7D\n"
+"0B0254A26810307964E2A05680C19DE7C63CCBD7CC3558AD366BA48D9F7049E245BF2C54EA0339301739851E6EB2158F";
+
+const char *r1Str =
+"4 16A33C4ED01E95833D39EECE223380FE860B6DC1F71B1DDBEE2BE39B5D682B090F18758495E202010D3B9B45A46FF80E\n"
+"01CECF5CC255E32B833C16EF3F983CCA9996A33504615909AD5685D9F637BF2357442BEC89DAFC747B69EFEF57D5A213\n"
+"061C33850E5E4A418F3B68D6097C3911A551D6DB3C7E21196410F69D510C1A888635B6B699F98C14912A8D97742D36A9\n"
+"0457FB78282C2B8F8BA803E77D058EF3BF6B06C6241D6FA6E2B1607F3E9D7597D1A10B7AA4E06B89FBA01736901AD826\n"
+"0B45E9B7D311B8C37F7E9262227A4D721F2D148DE6F12EC5D599B45E4790F35B37A1D6928709F438849324A807EC1913\n"
+"0E771545F892C247A5365BA1F14934D8ED37483A6B7DD3EB4C3FBA0AC884D7EE9C080C3B39ADA64AE545E7339F83AFB0";
+
+ const int mode = mcl::IoEcProj | 16;
+ Fp6 l, m;
+ G2 R, Q, R1;
+ G1 P;
+
+ R.setStr(rStr, mode);
+ Q.setStr(qStr, mode);
+ P.setStr(pStr, mode);
+ l.a.setStr(l0Str, mode);
+ l.b.setStr(l4Str, mode);
+ l.c.setStr(l1Str, mode);
+ local::addLine(l, R, Q, P);
+ m.a.setStr(m0Str, mode);
+ m.b.setStr(m4Str, mode);
+ m.c.setStr(m1Str, mode);
+ R1.setStr(r1Str, mode);
+ CYBOZU_TEST_EQUAL(l, m);
+ CYBOZU_TEST_EQUAL(R, R1);
+}
+
+CYBOZU_TEST_AUTO(dblLine)
+{
+const char *l0Str=
+"0905F47F07FA2177E4B73559D93D9B41A2FD20E0440167E63A0F62321EB73C784405DE360477245F5E4AE8FA2EAEC6FF\n"
+"02DA455C573517EE8BD4E40A60851E2EC85CF514351681B89B1B72664E384A3678A25DC5C4CF84C086C13968BC701F91";
+const char *l1Str =
+"0F48059E31CEF9546D41DEF31FB3BFD13BBCC38248E4846AFD216350B4B661FA1382E74BCF904BE8E33C26FF0D29ABA0\n"
+"0D7FAEE426E4A6F32E4DE1CCB76BBA870A183113589CF58A358DC9C284C82B54C65A754F9A71EAD87304744CFD105051";
+
+const char *l4Str =
+"162AE8B029F8420BEDE5A399BA19C09FED01DE2748F4458065DBE51044FBFE749B28EF1B7F79A5E4545EB550DD0CFE02\n"
+"091042B589FD59FBF286D21475CCCF444D8DCC49389EA3B98AF864DDB9C08BDDEB320D6D88F0C07D7CD1733A41404C1F";
+
+const char *qStr =
+"4 047ACF79048EDCA97A19DB1779A44CE610CEA9FDCC62D1C4014B335834BC63414F55B670CCF15A86E58BC3737FB70919\n"
+"11D8063B2FFA2E1F5224593FF74D0E9650CAB6AF702B74159F7F97E2CF0843FBCD561D41FEC779BEB48746CD2F30FF74\n"
+"17684E8EA85C990DF5472B4EBAF51002CDBBECF79BA2988FC610A5CE09F4A584248DCC506E78C39C9BB4F6008115DE64\n"
+"1334CA7263ED9395BBEDBB6C938C642200C239FB0CADF1F652332A037FFBC7E567CCE09540939F25316CBC4FC68CE4DB\n"
+"0670DCF344F027CB92F7B1F569B281C8FF756D83CD7B65EB118FE95FBE16ED28649B8F739FE3A2BECA1979FC18484ECD\n"
+"13E3E30759DCC1FA9F1A62D54BEF0EE1CC75E194A559F2D6BE3025BE4BEB9F7351A7608FE8D4CCAD30BA2A8748205487";
+
+const char *pStr =
+"4 1579B48AE944AFE8FC69B38A7CD0D2C6B93E5F506535A5410E25FB1C1707938D6932F3D620A2BBB90ED7E2601971DEA8\n"
+"0234E5B373AD62D9EF1EBAE6FA6FFAD26144717F65AE9F98BD4280978ED52B3621F60FA4A8F6E5B5DAF64469733827E6\n"
+"0B4D1755924541041F75FF399E3B5F535BC85D5A982AEEC5FC2404F06AC7F062C090C4545D1602C3D8B559801EE7B9A2";
+
+const char *m0Str =
+"198D1123A9817C40A914A3FF9E29BB16DD2F0DF98D0AB5C3A6014D60E31AE973051C35ADCEA0A41F32BB16E6688DC73F\n"
+"10339DB2F26D1B867FD3E60A24F938210EABEFC51536845A490F28A088A4AC53575DBBAA218D70D34E28EBDE14DB3465\n";
+const char *m1Str =
+"066852248D915F6378B3F4A8E6173AC748FBFAE236AAEEAECC3F34D2D22706A06B925A83DD8276B2B240F61D761587B0\n"
+"17CC8195E6607FF19A26AA69CA50C32487E35D2D75301AC4B6988F1B77523BF472927EE5710DF49A563534D86C684BE0\n";
+const char *m4Str =
+"10B67D1A0CE430B7AD74F64DD6C2E44C4788EADF8340909843C96B918BF54703CC14686B26E350EB1140ACC3337EEEB4\n"
+"0F5D52E6F0B10A081EFF885CC858109241B379985ADD8982E6B8A202FD283897EFBA4CBE444C29751410A61FC8346545";
+
+const char *q1Str =
+"4 17B5E51EC931E724ABACE9C7F8AFDD51F3929478B47C222F99844D166936063D3BFCDF7AD7079EEF4BE8514E3D09EF0F\n"
+"0F5794F38BAEC0FA3C30AC4C0B8E9024B2047F2F4576434F91768F2B51AD58C48E88414B1D4B7A9119A947D3CFEDEF0A\n"
+"1320714A8B7E23C4C558D2B1C556CC8FB6B41F3669EFD70B6D204C2A7C6EF2E0CBCA945AA7BACB402E00ED338F7D12FC\n"
+"0C2846E386161F123344704528D9944677806C3F784E3997857C91D2F3F37AB6AD92360CD97CABD5D631E9FC74708AD3\n"
+"17F92FF3D71B473B802F2DE90C19A5F5DBFAA397293871AB58E5B813F7D686EA8E1814C69C50C02D062F3A13C1D045E1\n"
+"05214392858DE04B3B468B2D0C703A485508C29157D81E9F799BAB2FEF0F514C99D5F8085D8062281418C6CCE5621D18\n";
+
+ const int mode = mcl::IoEcProj | 16;
+ Fp6 l, m;
+ G2 Q, Q1;
+ G1 P;
+
+ G1::setOrder(0);
+ Q.setStr(qStr, mode);
+ P.setStr(pStr, mode);
+ l.a.setStr(l0Str, mode);
+ l.b.setStr(l4Str, mode);
+ l.c.setStr(l1Str, mode);
+ local::dblLine(l, Q, P);
+ m.a.setStr(m0Str, mode);
+ m.b.setStr(m4Str, mode);
+ m.c.setStr(m1Str, mode);
+ Q1.setStr(q1Str, mode);
+ CYBOZU_TEST_EQUAL(l, m);
+ CYBOZU_TEST_EQUAL(Q, Q1);
+ G1::setOrder(BN::param.r);
+}
+
+CYBOZU_TEST_AUTO(mul_012)
+{
+ const char *fStr =
+"087590AFBFEB8F85DD912EC297C2B5DD7BC0A9B0914348C5D99F0089C09CDBA0DCDAF1C704A7B092D8FB9A75B7C06D88\n"
+"119DD8B08C40D4EB3D7AF19221E41639A98A10EF1A22F9AD8CB1350526B9335F47E76B2FFD6652E693A67440574D5A0C\n"
+"134ADA7C4ABFBA4324900D25E5077A119F9E55A7F337C03FD539D8DAC392B458F11261BEA007393D43657E9656B984D6\n"
+"01032DDB3CAEC38B7DA916CA111C46A013F1DC83AF13DFF5B71CC3789974F946CFC43FE7B8EE519E524627248369FCE7\n"
+"19E9455C14A9640139224BB1337E4EC5EE92BFF757DB179CC98CF0F09682E44ED4B6004F31D4788DE28BB2D8F41DDAE4\n"
+"0B9877DF6AC1015375AB421363A5B06D2DC1763B923FF674A06AE101306A4A39967A3F9EF12E870C124A26CE68E2D003\n"
+"02AA5AC5901C9C91CD0B43CA62F21FA541896802A8AAF0FD5EDF8DAF4A98CEC19F457A67369E795594543677B4A16EA4\n"
+"0604DB7CE2A0ABD8ADB5F4F06F20B01510BF9787C912B1036F570E7368D341D9B794F078DFD3265306841180865500D0\n"
+"08145045CF5751502778739EFE6FEA6036C8F14800F4818C2FD8BA5AF98E89B0BBE6510D511C4E5A83A2813A92B655F0\n"
+"0FDE93D3326321ECF6171FBC4665F1C171F19A6F1D521BFA1A1B80E0B08CEBB78B255AF0B5F7E45AA6C1D01005200FB1\n"
+"0F2A9EA2891A683AE15A79EDB0C6DF45FFAD4D22F3293AE59D3CE8F6E0E59A097673D05D81ACAD8C59817FFDD3E89CF1\n"
+"0724BD07BDDCA23775C1DECD80CE7722F98C10E75A0CD9A1FA81921A04EEFAC55BE0740C5F01ED83FDFC66380339D417\n";
+
+const char *l0Str =
+"198D1123A9817C40A914A3FF9E29BB16DD2F0DF98D0AB5C3A6014D60E31AE973051C35ADCEA0A41F32BB16E6688DC73F\n"
+"10339DB2F26D1B867FD3E60A24F938210EABEFC51536845A490F28A088A4AC53575DBBAA218D70D34E28EBDE14DB3465";
+const char *l1Str =
+"066852248D915F6378B3F4A8E6173AC748FBFAE236AAEEAECC3F34D2D22706A06B925A83DD8276B2B240F61D761587B0\n"
+"17CC8195E6607FF19A26AA69CA50C32487E35D2D75301AC4B6988F1B77523BF472927EE5710DF49A563534D86C684BE0\n";
+const char *l4Str =
+"10B67D1A0CE430B7AD74F64DD6C2E44C4788EADF8340909843C96B918BF54703CC14686B26E350EB1140ACC3337EEEB4\n"
+"0F5D52E6F0B10A081EFF885CC858109241B379985ADD8982E6B8A202FD283897EFBA4CBE444C29751410A61FC8346545\n";
+
+const char *f2Str =
+"10128E1A9BD00FC81F6550921D0FED3944F63F980ABF91FDB73B1ED162337ED16075730ACD60A0FA7DFABAD9FC9657C5\n"
+"055BE26091D8CDA32241F4991A1F184E403C3FFDD54858B23D5CE4B44402B65B26BCA6855DA7AC1C60F1D6651632DCD8\n"
+"0D70827981F0D33185DE8767FDDFEC26CEB6A28F82C83BBABB0057E432FCF9072B666974123274751E35F371E931D6CC\n"
+"02382B1A80E5BC95C75AE71BE2E097FD59365279CDD7EA358D87DEF132430744DABBF1B685D110CC731A9FDA40EEFC1B\n"
+"0AAB560FB99D57A9B1B6C753DAF6B0619ED598C9B5FB0908F2DAE83C530E6365DBEDE29B9357D63803F46247A1F41C73\n"
+"13C048F553BFC3C56516786DD26FF9D59ECFB9BE6B165F90E77CCED623BC66C6E93EFBF14576DB7E33C8C4F4E21F64DC\n"
+"0987D7DEBB96A10D977F256432871BEBB4B3A620E4AE822E089E9DAA192CD278E9FA0CF598444F6758628BC38C33A5AD\n"
+"0A4F1B75845B6C976BF49C35134AE73CA7A3C16D2E0BDA39C70367E3829E94EB7CAFBB0F8B57F4734B696D9CEF84FE73\n"
+"0DFAB9C035F3DA51226F27998A494A32245800F0313446D6437D2F5B3F34A9E91428818B0C9AF63EB3AA618E80055FD5\n"
+"06A58B9640FF8931616F6D08BA16ECE71F341C61F22E5EC5B556DF217179C3ECEC20E4BE425A3471F1D6648D14F89FBF\n"
+"1614391845CDC212937BC1070010603FB4DF99A6B3FA7E7CD3316C56BA8B633B3DC7D864B36DA2F9A1E6B977DB150100\n"
+"144A44415BCCB077EAA64C8DAC50631AF432C1420EBD8538818D65D6176BC1EB699579CED8340493306AF842B4B6822E";
+
+ Fp6 l;
+ Fp12 f, f2;
+ l.a.setStr(l0Str, 16);
+ l.b.setStr(l4Str, 16);
+ l.c.setStr(l1Str, 16);
+ f.setStr(fStr, 16);
+ f2.setStr(f2Str, 16);
+ local::mulSparse(f, l);
+ CYBOZU_TEST_EQUAL(f, f2);
+}
+
+CYBOZU_TEST_AUTO(pairing)
+{
+ const int mode = mcl::IoEcProj | 16;
+
+const char *pStr =
+"4 0FD3977C60EC322BC281C915955ED534B491E39C72E8E800271CEF3F0492D890829FA69C45FCE93D9847A0CAB325D871\n"
+"17CC2C36C5D283C05BFCECCF48DBB2050332DA058DD67326A9EE520967DBCAEDFCB5F05A085D1A49DF08BB968CC782C5\n"
+"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001";
+const char *qStr =
+"4 0B5C339C23F8EAB3647E974BCDDF72C96F97A444346BE72CA73AB1323B83B8F6161257AB34C7E0CF34F6C45086CA5868\n"
+"13C2235E9F9DFB33344BA2EE5A71435859022880732EDC9EC75AC79AE9DA972593CDC40A0AC334D6D2E8D7FAD1D98D0B\n"
+"134B8EED8196A00D3B70ADBC26FF963B725A351CF0B73FE1A541788AFB0BB081AF82A438021B5E878B15D53B1D27C6A7\n"
+"18CC69F847BEE826B939DCB4030D33020D03B046465C9EE103AA8009A175DB169070294E75771586687FE361DB884BCD\n"
+"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\n"
+"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+const char *eStr =
+"0E05D19E90D2C501E5502C7AC80D77201C47DF147DD1076440F0DF0179DF9802CA0775E0E73DD9174F1094D2280787B3\n"
+"14D2F5C84279E7177A3543FBEAE261DE8F6C97EFD5F3FF3F959EC9FC0303F620A4B3AF00DF409496CECADDD0A7F0A164\n"
+"1414E9B9DF8DF1EAC2E70D5538018377788C62016A54F28B037A68740705089AE431B86756F98CBE19690A5EAC0C2466\n"
+"12D8B32157836A131CCA3CA313DAAAF909BC3AD6BDD15885BB429922B9CD7D1246D1163E5E6F88D68BF1B75E451EFABB\n"
+"102C9A839A924E0D603D13F2E08A919E0B9EE2A269FC75727BA13D66027C157B9BB4077977FA94557DE4427BF11B234B\n"
+"19DBEB7F2E3096AFFD44837655BD8249741B484B0EB0DBEE569DEA8D9E38AE09D210C8BC16AA6DFBC923095B2C9A8B2B\n"
+"19B9A6DCCD01FA0D04D5CE94D8BDCE1DF64AFEB7FD493B955180A5C6B236E469F0E07CC9BB4203FCAC46AE6F8E5419D6\n"
+"02BFA87AF7A3726A7ABACDCFDD53694AF651554F3A431AB4274F67D5DAD2D6C88AF794705FF456A936C83594731AD8DC\n"
+"0F21E0173E3B50DD98EFA815B410631A57399B451FD6E1056FFD09C9FE50EFAD3D026F0C46C8BB1583A50B7853D990DA\n"
+"02230237AE04B61F9269F6E7CD2FCF1231CEE4690AA658B0018EFC0D0770FD0A56B3B7294086E8D306B1465CDDD858CD\n"
+"087EB8F6547015661E9CD48D6525C808636FCB8420B867CB2A87E006B2A93BBD5EF675E6CDDA9E6F94519C49EA8BB689\n"
+"19F5C988B2DD6E33D7D3D34EFB1991F80DC28006AC75E0AB53FD98FC6F2476D05DD4ECA582F5FF72B8DDD9DDDE80FFC9";
+ G1 P;
+ G2 Q;
+ P.setStr(pStr, mode);
+ Q.setStr(qStr, mode);
+ Fp12 e1, e2;
+ e1.setStr(eStr, 16);
+ pairing(e2, P, Q);
+ CYBOZU_TEST_EQUAL(e1, e2);
+}
+
+void testCurve(const mcl::CurveParam& cp)
+{
+ initPairing(cp, g_mode);
+ G1 P;
+ G2 Q;
+ mapToG1(P, 1);
+ mapToG2(Q, 1);
+ GT e1, e2;
+ pairing(e1, P, Q);
+ cybozu::XorShift rg;
+ mpz_class a, b;
+ Fr r;
+ r.setRand(rg); a = r.getMpz();
+ r.setRand(rg); b = r.getMpz();
+ G1 aP;
+ G2 bQ;
+ G1::mul(aP, P, a);
+ G2::mul(bQ, Q, b);
+ pairing(e2, aP, bQ);
+ GT::pow(e1, e1, a * b);
+ CYBOZU_TEST_EQUAL(e1, e2);
+}
+CYBOZU_TEST_AUTO(multi)
+{
+ G1 P;
+ G2 Q;
+ int i;
+ puts("BN254");
+ testCurve(mcl::BN254);
+ i = 1;
+ CYBOZU_BENCH_C("calcBN1", 100, (BN::param.mapTo.calcBN<G1, Fp>), P, i++);
+ CYBOZU_BENCH_C("naiveG2", 100, (BN::param.mapTo.naiveMapTo<G1, Fp>), P, i++);
+ CYBOZU_BENCH_C("calcBN2", 100, (BN::param.mapTo.calcBN<G2, Fp2>), Q, i++);
+ CYBOZU_BENCH_C("naiveG2", 100, (BN::param.mapTo.naiveMapTo<G2, Fp2>), Q, i++);
+ puts("BLS12_381");
+ testCurve(mcl::BLS12_381);
+ i = 1;
+ CYBOZU_BENCH_C("calcBN1", 100, (BN::param.mapTo.calcBN<G1, Fp>), P, i++);
+ CYBOZU_BENCH_C("naiveG1", 100, (BN::param.mapTo.naiveMapTo<G1, Fp>), P, i++);
+ CYBOZU_BENCH_C("calcBN2", 100, (BN::param.mapTo.calcBN<G2, Fp2>), Q, i++);
+ CYBOZU_BENCH_C("naiveG2", 100, (BN::param.mapTo.naiveMapTo<G2, Fp2>), Q, i++);
+}
+
+CYBOZU_TEST_AUTO(BLS12_G1mulCofactor)
+{
+ if (BN::param.cp.curveType != MCL_BLS12_381) return;
+}
+
+typedef std::vector<Fp> FpVec;
+
+void f(FpVec& zv, const FpVec& xv, const FpVec& yv)
+{
+ for (size_t i = 0; i < zv.size(); i++) {
+ Fp::mul(zv[i], xv[i], yv[i]);
+ }
+}
+int main(int argc, char *argv[])
+ try
+{
+ cybozu::Option opt;
+ std::string mode;
+ opt.appendOpt(&mode, "auto", "m", ": mode(gmp/gmp_mont/llvm/llvm_mont/xbyak)");
+ if (!opt.parse(argc, argv)) {
+ opt.usage();
+ return 1;
+ }
+ g_mode = mcl::fp::StrToMode(mode);
+ printf("JIT %d\n", mcl::fp::isEnableJIT());
+#if 0
+ initPairing(mcl::BLS12_381);
+ cybozu::XorShift rg;
+ const int n = 1;
+ std::vector<Fp> xv(n), yv(n), zv(n);
+ for (int i = 0; i < n; i++) {
+ xv[i].setByCSPRNG(rg);
+ yv[i].setByCSPRNG(rg);
+ }
+ FpDbl dx;
+ FpDbl::mulPre(dx, xv[0], yv[0]);
+ Fp2 x2, y2;
+ x2.a.setByCSPRNG(rg);
+ x2.b.setByCSPRNG(rg);
+ y2.a.setByCSPRNG(rg);
+ y2.b.setByCSPRNG(rg);
+ Fp2Dbl x2d, y2d;
+ Fp2Dbl::mulPre(x2d, x2, x2);
+ Fp2Dbl::mulPre(y2d, x2, y2);
+if(0){
+ puts("----------");
+ xv[0].dump();
+ yv[0].dump();
+ dx.dump();
+ puts("----------");
+// exit(1);
+}
+// CYBOZU_BENCH_C("Fp2::neg", 10000000, Fp2::neg, x2, x2);
+ CYBOZU_BENCH_C("Fp2::sqr", 10000000, Fp2::sqr, x2, x2);
+// CYBOZU_BENCH_C("Fp2::sqrPre", 100000000, Fp2Dbl::sqrPre, x2d, x2);
+// CYBOZU_BENCH_C("Fp2::mulPre", 100000000, Fp2Dbl::mulPre, x2d, x2, y2);
+// CYBOZU_BENCH_C("sqrPre", 100000000, FpDbl::sqrPre, dx, xv[0]);
+// CYBOZU_BENCH_C("mod ", 100000000, FpDbl::mod, xv[0], dx);
+// CYBOZU_BENCH_C("mul ", 100000000, Fp::mul, xv[0], yv[0], xv[0]);
+// CYBOZU_BENCH_C("sqr ", 100000000, Fp::sqr, xv[0], xv[0]);
+ return 0;
+#endif
+ return cybozu::test::autoRun.run(argc, argv);
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+ return 1;
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/bn384_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn384_test.cpp
new file mode 100644
index 000000000..b5674a918
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/bn384_test.cpp
@@ -0,0 +1,83 @@
+#define CYBOZU_TEST_DISABLE_AUTO_RUN
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/option.hpp>
+#include <cybozu/xorshift.hpp>
+#include <mcl/bn384.hpp>
+#include <mcl/bn.hpp>
+
+using namespace mcl::bn384;
+
+mcl::fp::Mode g_mode;
+
+#include "bench.hpp"
+
+void testCurve(const mcl::CurveParam& cp)
+{
+ initPairing(cp, g_mode);
+ G1 P;
+ G2 Q;
+ mapToG1(P, 1);
+ mapToG2(Q, 1);
+ GT e1, e2;
+#ifdef ONLY_BENCH
+ cybozu::CpuClock clk;
+ for (int i = 0; i < 10000; i++) { clk.begin(); pairing(e1, P, Q); clk.end(); }
+ clk.put();
+ return;
+#endif
+ pairing(e1, P, Q);
+ cybozu::XorShift rg;
+ mpz_class a, b;
+ Fr r;
+ r.setRand(rg); a = r.getMpz();
+ r.setRand(rg); b = r.getMpz();
+ G1 aP;
+ G2 bQ;
+ G1::mul(aP, P, a);
+ G2::mul(bQ, Q, b);
+ pairing(e2, aP, bQ);
+ GT::pow(e1, e1, a * b);
+ CYBOZU_TEST_EQUAL(e1, e2);
+ testBench(P, Q);
+ testSquareRoot();
+ testLagrange();
+}
+
+CYBOZU_TEST_AUTO(pairing)
+{
+// puts("BN160");
+// testCurve(mcl::BN160);
+ puts("BN254");
+ // support 256-bit pairing
+ testCurve(mcl::BN254);
+ puts("BN381_1");
+ testCurve(mcl::BN381_1);
+ puts("BN381_2");
+ testCurve(mcl::BN381_2);
+ puts("BLS12_381");
+ testCurve(mcl::BLS12_381);
+ // Q is not on EcT, but bad order
+ {
+ const char *s = "1 18d3d8c085a5a5e7553c3a4eb628e88b8465bf4de2612e35a0a4eb018fb0c82e9698896031e62fd7633ffd824a859474 1dc6edfcf33e29575d4791faed8e7203832217423bf7f7fbf1f6b36625b12e7132c15fbc15562ce93362a322fb83dd0d 65836963b1f7b6959030ddfa15ab38ce056097e91dedffd996c1808624fa7e2644a77be606290aa555cda8481cfb3cb 1b77b708d3d4f65aeedf54b58393463a42f0dc5856baadb5ce608036baeca398c5d9e6b169473a8838098fd72fd28b50";
+ G2 Q;
+ CYBOZU_TEST_EXCEPTION(Q.setStr(s, 16), std::exception);
+ }
+}
+
+int main(int argc, char *argv[])
+ try
+{
+ cybozu::Option opt;
+ std::string mode;
+ opt.appendOpt(&mode, "auto", "m", ": mode(gmp/gmp_mont/llvm/llvm_mont/xbyak)");
+ if (!opt.parse(argc, argv)) {
+ opt.usage();
+ return 1;
+ }
+ g_mode = mcl::fp::StrToMode(mode);
+ return cybozu::test::autoRun.run(argc, argv);
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+ return 1;
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/bn512_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn512_test.cpp
new file mode 100644
index 000000000..905bfd3db
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/bn512_test.cpp
@@ -0,0 +1,68 @@
+#define CYBOZU_TEST_DISABLE_AUTO_RUN
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/option.hpp>
+#include <cybozu/xorshift.hpp>
+#include <mcl/bn512.hpp>
+#include <mcl/bn.hpp>
+
+using namespace mcl::bn512;
+
+mcl::fp::Mode g_mode;
+
+#include "bench.hpp"
+
+void testCurve(const mcl::CurveParam& cp)
+{
+ initPairing(cp, g_mode);
+ G1 P;
+ G2 Q;
+ mapToG1(P, 1);
+ mapToG2(Q, 1);
+ GT e1, e2;
+ pairing(e1, P, Q);
+ cybozu::XorShift rg;
+ mpz_class a, b;
+ Fr r;
+ r.setRand(rg); a = r.getMpz();
+ r.setRand(rg); b = r.getMpz();
+ G1 aP;
+ G2 bQ;
+ G1::mul(aP, P, a);
+ G2::mul(bQ, Q, b);
+ pairing(e2, aP, bQ);
+ GT::pow(e1, e1, a * b);
+ CYBOZU_TEST_EQUAL(e1, e2);
+ testBench(P, Q);
+ testSquareRoot();
+ testLagrange();
+}
+
+CYBOZU_TEST_AUTO(pairing)
+{
+ puts("BN462");
+ testCurve(mcl::BN462);
+ puts("BN381_1");
+ testCurve(mcl::BN381_1);
+ puts("BLS12_381");
+ testCurve(mcl::BLS12_381);
+ puts("BN254");
+ testCurve(mcl::BN254);
+}
+
+int main(int argc, char *argv[])
+ try
+{
+ cybozu::Option opt;
+ std::string mode;
+ opt.appendOpt(&mode, "auto", "m", ": mode(gmp/gmp_mont/llvm/llvm_mont/xbyak)");
+ if (!opt.parse(argc, argv)) {
+ opt.usage();
+ return 1;
+ }
+ g_mode = mcl::fp::StrToMode(mode);
+ return cybozu::test::autoRun.run(argc, argv);
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+ return 1;
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/bn_c256_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn_c256_test.cpp
new file mode 100644
index 000000000..2ce85162d
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/bn_c256_test.cpp
@@ -0,0 +1,6 @@
+#include <mcl/bn256.hpp>
+using namespace mcl::bn256;
+#define MCLBN_DEFINE_STRUCT
+#define MCLBN_FP_UNIT_SIZE 4
+#include "bn_c_test.hpp"
+
diff --git a/vendor/github.com/dexon-foundation/mcl/test/bn_c384_256_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn_c384_256_test.cpp
new file mode 100644
index 000000000..e7bbefda9
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/bn_c384_256_test.cpp
@@ -0,0 +1,7 @@
+#include <mcl/bls12_381.hpp>
+using namespace mcl::bls12;
+#define MCLBN_DEFINE_STRUCT
+#define MCLBN_FP_UNIT_SIZE 6
+#define MCLBN_FR_UNIT_SIZE 4
+#include "bn_c_test.hpp"
+
diff --git a/vendor/github.com/dexon-foundation/mcl/test/bn_c384_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn_c384_test.cpp
new file mode 100644
index 000000000..a9f20243a
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/bn_c384_test.cpp
@@ -0,0 +1,6 @@
+#include <mcl/bn384.hpp>
+using namespace mcl::bn384;
+#define MCLBN_DEFINE_STRUCT
+#define MCLBN_FP_UNIT_SIZE 6
+#include "bn_c_test.hpp"
+
diff --git a/vendor/github.com/dexon-foundation/mcl/test/bn_c512_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn_c512_test.cpp
new file mode 100644
index 000000000..c6af3989f
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/bn_c512_test.cpp
@@ -0,0 +1,6 @@
+#include <mcl/bn512.hpp>
+using namespace mcl::bn512;
+#define MCLBN_DEFINE_STRUCT
+#define MCLBN_FP_UNIT_SIZE 8
+#include "bn_c_test.hpp"
+
diff --git a/vendor/github.com/dexon-foundation/mcl/test/bn_c_test.hpp b/vendor/github.com/dexon-foundation/mcl/test/bn_c_test.hpp
new file mode 100644
index 000000000..e9dc59393
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/bn_c_test.hpp
@@ -0,0 +1,699 @@
+/*
+ include from bn_if256_test.cpp and bn_if384_test.cpp
+*/
+#include <mcl/bn.h>
+#include <mcl/ecparam.hpp>
+#include <cybozu/test.hpp>
+#include <iostream>
+#include <gmpxx.h>
+
+template<size_t N>
+std::ostream& dump(std::ostream& os, const uint64_t (&x)[N])
+{
+ for (size_t i = 0; i < N; i++) {
+ char buf[64];
+ CYBOZU_SNPRINTF(buf, sizeof(buf), "%016llx", (long long)x[i]);
+ os << buf;
+ }
+ return os;
+}
+
+CYBOZU_TEST_AUTO(init)
+{
+ int ret;
+ CYBOZU_TEST_EQUAL(sizeof(mclBnFr), sizeof(Fr));
+ CYBOZU_TEST_EQUAL(sizeof(mclBnG1), sizeof(G1));
+ CYBOZU_TEST_EQUAL(sizeof(mclBnG2), sizeof(G2));
+ CYBOZU_TEST_EQUAL(sizeof(mclBnGT), sizeof(Fp12));
+
+#if MCLBN_FP_UNIT_SIZE >= 4
+ printf("test BN254 %d\n", MCLBN_FP_UNIT_SIZE);
+ ret = mclBn_init(MCL_BN254, MCLBN_COMPILED_TIME_VAR);
+#endif
+#if MCLBN_FP_UNIT_SIZE >= 6 && MCLBN_FR_UNIT_SIZE >= 4
+ printf("test BLS12_381 %d\n", MCLBN_FP_UNIT_SIZE);
+ ret = mclBn_init(MCL_BLS12_381, MCLBN_COMPILED_TIME_VAR);
+#endif
+#if MCLBN_FP_UNIT_SIZE >= 6 && MCLBN_FR_UNIT_SIZE >= 6
+ printf("test BN381_1 %d\n", MCLBN_FP_UNIT_SIZE);
+ ret = mclBn_init(MCL_BN381_1, MCLBN_COMPILED_TIME_VAR);
+#endif
+#if MCLBN_FP_UNIT_SIZE == 8
+ printf("test BN462 %d\n", MCLBN_FP_UNIT_SIZE);
+ ret = mclBn_init(MCL_BN462, MCLBN_COMPILED_TIME_VAR);
+#endif
+ CYBOZU_TEST_EQUAL(ret, 0);
+ if (ret != 0) exit(1);
+}
+
+CYBOZU_TEST_AUTO(Fr)
+{
+ mclBnFr x, y;
+ memset(&x, 0xff, sizeof(x));
+ CYBOZU_TEST_ASSERT(!mclBnFr_isValid(&x));
+ CYBOZU_TEST_ASSERT(!mclBnFr_isZero(&x));
+
+ mclBnFr_clear(&x);
+ CYBOZU_TEST_ASSERT(mclBnFr_isZero(&x));
+
+ mclBnFr_setInt(&x, 1);
+ CYBOZU_TEST_ASSERT(mclBnFr_isOne(&x));
+
+ mclBnFr_setInt(&y, -1);
+ CYBOZU_TEST_ASSERT(!mclBnFr_isEqual(&x, &y));
+
+ y = x;
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x, &y));
+
+ mclBnFr_setHashOf(&x, "", 0);
+ mclBnFr_setHashOf(&y, "abc", 3);
+ CYBOZU_TEST_ASSERT(!mclBnFr_isEqual(&x, &y));
+ mclBnFr_setHashOf(&x, "abc", 3);
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x, &y));
+
+ char buf[1024];
+ mclBnFr_setInt(&x, 12345678);
+ size_t size;
+ size = mclBnFr_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_EQUAL(size, 8);
+ CYBOZU_TEST_EQUAL(buf, "12345678");
+
+ mclBnFr_setInt(&x, -7654321);
+ mclBnFr_neg(&x, &x);
+ size = mclBnFr_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_EQUAL(size, 7);
+ CYBOZU_TEST_EQUAL(buf, "7654321");
+
+ mclBnFr_setInt(&y, 123 - 7654321);
+ mclBnFr_add(&x, &x, &y);
+ size = mclBnFr_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_EQUAL(size, 3);
+ CYBOZU_TEST_EQUAL(buf, "123");
+
+ mclBnFr_setInt(&y, 100);
+ mclBnFr_sub(&x, &x, &y);
+ size = mclBnFr_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_EQUAL(size, 2);
+ CYBOZU_TEST_EQUAL(buf, "23");
+
+ mclBnFr_mul(&x, &x, &y);
+ size = mclBnFr_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_EQUAL(size, 4);
+ CYBOZU_TEST_EQUAL(buf, "2300");
+
+ mclBnFr_div(&x, &x, &y);
+ size = mclBnFr_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_EQUAL(size, 2);
+ CYBOZU_TEST_EQUAL(buf, "23");
+
+ mclBnFr_mul(&x, &y, &y);
+ mclBnFr_sqr(&y, &y);
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x, &y));
+
+ const char *s = "12345678901234567";
+ CYBOZU_TEST_ASSERT(!mclBnFr_setStr(&x, s, strlen(s), 10));
+ s = "20000000000000000";
+ CYBOZU_TEST_ASSERT(!mclBnFr_setStr(&y, s, strlen(s), 10));
+ mclBnFr_add(&x, &x, &y);
+ size = mclBnFr_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_EQUAL(size, 17);
+ CYBOZU_TEST_EQUAL(buf, "32345678901234567");
+
+ mclBnFr_setInt(&x, 1);
+ mclBnFr_neg(&x, &x);
+ size = mclBnFr_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_ASSERT(size > 0);
+ CYBOZU_TEST_EQUAL(size, strlen(buf));
+ CYBOZU_TEST_ASSERT(!mclBnFr_setStr(&y, buf, size, 10));
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x, &y));
+
+ for (int i = 0; i < 10; i++) {
+ mclBnFr_setByCSPRNG(&x);
+ mclBnFr_getStr(buf, sizeof(buf), &x, 16);
+ printf("%s\n", buf);
+ }
+}
+
+void G1test()
+{
+ mclBnG1 x, y, z;
+ memset(&x, 0x1, sizeof(x));
+ /*
+ assert() of carry operation fails if use 0xff, so use 0x1
+ */
+ CYBOZU_TEST_ASSERT(!mclBnG1_isValid(&x));
+ mclBnG1_clear(&x);
+ CYBOZU_TEST_ASSERT(mclBnG1_isValid(&x));
+ CYBOZU_TEST_ASSERT(mclBnG1_isZero(&x));
+
+ CYBOZU_TEST_ASSERT(!mclBnG1_hashAndMapTo(&y, "abc", 3));
+ CYBOZU_TEST_ASSERT(mclBnG1_isValidOrder(&y));
+
+ char buf[1024];
+ size_t size;
+ size = mclBnG1_getStr(buf, sizeof(buf), &y, 10);
+ CYBOZU_TEST_ASSERT(size > 0);
+ CYBOZU_TEST_EQUAL(size, strlen(buf));
+ CYBOZU_TEST_ASSERT(!mclBnG1_setStr(&x, buf, strlen(buf), 10));
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&x, &y));
+
+ mclBnG1_neg(&x, &x);
+ mclBnG1_add(&x, &x, &y);
+ CYBOZU_TEST_ASSERT(mclBnG1_isZero(&x));
+
+ mclBnG1_dbl(&x, &y); // x = 2y
+ mclBnG1_add(&z, &y, &y);
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&x, &z));
+ mclBnG1_add(&z, &z, &y); // z = 3y
+ mclBnFr n;
+ mclBnFr_setInt(&n, 3);
+ mclBnG1_mul(&x, &y, &n); // x = 3y
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&x, &z));
+ mclBnG1_sub(&x, &x, &y); // x = 2y
+
+ mclBnFr_setInt(&n, 2);
+ mclBnG1_mul(&z, &y, &n); // z = 2y
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&x, &z));
+ mclBnG1_normalize(&y, &z);
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&y, &z));
+}
+
+CYBOZU_TEST_AUTO(G1)
+{
+ G1test();
+}
+
+CYBOZU_TEST_AUTO(G2)
+{
+ mclBnG2 x, y, z;
+ /*
+ assert() of carry operation fails if use 0xff, so use 0x1
+ */
+ memset(&x, 0x1, sizeof(x));
+ CYBOZU_TEST_ASSERT(!mclBnG2_isValid(&x));
+ mclBnG2_clear(&x);
+ CYBOZU_TEST_ASSERT(mclBnG2_isValid(&x));
+ CYBOZU_TEST_ASSERT(mclBnG2_isZero(&x));
+
+ CYBOZU_TEST_ASSERT(!mclBnG2_hashAndMapTo(&x, "abc", 3));
+ CYBOZU_TEST_ASSERT(mclBnG2_isValidOrder(&x));
+
+ char buf[1024];
+ size_t size;
+ size = mclBnG2_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_ASSERT(size > 0);
+ CYBOZU_TEST_EQUAL(size, strlen(buf));
+ CYBOZU_TEST_ASSERT(!mclBnG2_setStr(&y, buf, strlen(buf), 10));
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&x, &y));
+
+ mclBnG2_neg(&x, &x);
+ mclBnG2_add(&x, &x, &y);
+ CYBOZU_TEST_ASSERT(mclBnG2_isZero(&x));
+
+ mclBnG2_dbl(&x, &y); // x = 2y
+ mclBnG2_add(&z, &y, &y);
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&x, &z));
+ mclBnG2_add(&z, &z, &y); // z = 3y
+ mclBnFr n;
+ mclBnFr_setInt(&n, 3);
+ mclBnG2_mul(&x, &y, &n); // x = 3y
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&x, &z));
+ mclBnG2_sub(&x, &x, &y); // x = 2y
+
+ mclBnFr_setInt(&n, 2);
+ mclBnG2_mul(&z, &y, &n); // z = 2y
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&x, &z));
+ mclBnG2_normalize(&y, &z);
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&y, &z));
+}
+
+CYBOZU_TEST_AUTO(GT)
+{
+ mclBnGT x, y, z;
+ memset(&x, 1, sizeof(x));
+ CYBOZU_TEST_ASSERT(!mclBnGT_isZero(&x));
+
+ mclBnGT_clear(&x);
+ CYBOZU_TEST_ASSERT(mclBnGT_isZero(&x));
+
+ mclBnGT_setInt(&x, 1);
+ CYBOZU_TEST_ASSERT(mclBnGT_isOne(&x));
+ char buf[2048];
+ size_t size;
+ size = mclBnGT_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_ASSERT(size > 0);
+ CYBOZU_TEST_EQUAL(size, strlen(buf));
+ const char *s = "1 0 0 0 0 0 0 0 0 0 0 0";
+ CYBOZU_TEST_EQUAL(buf, s);
+
+ s = "1 2 3 4 5 6 7 8 9 10 11 12";
+ CYBOZU_TEST_ASSERT(!mclBnGT_setStr(&x,s , strlen(s), 10));
+ size = mclBnGT_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_ASSERT(size > 0);
+ CYBOZU_TEST_EQUAL(size, strlen(buf));
+ CYBOZU_TEST_EQUAL(buf, s);
+
+ y = x;
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&x, &y));
+
+ s = "-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12";
+ CYBOZU_TEST_ASSERT(!mclBnGT_setStr(&z, s, strlen(s), 10));
+ size = mclBnGT_getStr(buf, sizeof(buf), &z, 10);
+ CYBOZU_TEST_ASSERT(size > 0);
+ CYBOZU_TEST_EQUAL(size, strlen(buf));
+ CYBOZU_TEST_ASSERT(!mclBnGT_setStr(&y, buf, size, 10));
+
+ mclBnGT_neg(&z, &y);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&x, &z));
+
+ mclBnGT_add(&y, &x, &y);
+ CYBOZU_TEST_ASSERT(mclBnGT_isZero(&y));
+
+ s = "2 0 0 0 0 0 0 0 0 0 0 0";
+ CYBOZU_TEST_ASSERT(!mclBnGT_setStr(&y, s, strlen(s), 10));
+ mclBnGT_mul(&z, &x, &y);
+ size = mclBnGT_getStr(buf, sizeof(buf), &z, 10);
+ CYBOZU_TEST_ASSERT(size > 0);
+ CYBOZU_TEST_EQUAL(size, strlen(buf));
+ CYBOZU_TEST_EQUAL(buf, "2 4 6 8 10 12 14 16 18 20 22 24");
+
+ mclBnGT_div(&z, &z, &y);
+ size = mclBnGT_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_ASSERT(size > 0);
+ CYBOZU_TEST_EQUAL(size, strlen(buf));
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&x, &z));
+
+ /*
+ can't use mclBnGT_pow because x is not in GT
+ */
+ mclBnFr n;
+ mclBnFr_setInt(&n, 3);
+ mclBnGT_powGeneric(&z, &x, &n);
+ mclBnGT_mul(&y, &x, &x);
+ mclBnGT_mul(&y, &y, &x);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&y, &z));
+
+ mclBnGT_mul(&x, &y, &y);
+ mclBnGT_sqr(&y, &y);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&x, &y));
+}
+
+CYBOZU_TEST_AUTO(pairing)
+{
+ mclBnFr a, b, ab;
+ mclBnFr_setInt(&a, 123);
+ mclBnFr_setInt(&b, 456);
+ mclBnFr_mul(&ab, &a, &b);
+ mclBnG1 P, aP;
+ mclBnG2 Q, bQ;
+ mclBnGT e, e1, e2;
+
+ CYBOZU_TEST_ASSERT(!mclBnG1_hashAndMapTo(&P, "1", 1));
+ CYBOZU_TEST_ASSERT(!mclBnG2_hashAndMapTo(&Q, "1", 1));
+
+ mclBnG1_mul(&aP, &P, &a);
+ mclBnG2_mul(&bQ, &Q, &b);
+
+ mclBn_pairing(&e, &P, &Q);
+ mclBnGT_pow(&e1, &e, &a);
+ mclBn_pairing(&e2, &aP, &Q);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &e2));
+
+ mclBnGT_pow(&e1, &e, &b);
+ mclBn_pairing(&e2, &P, &bQ);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &e2));
+
+ mclBnFr n;
+ mclBnFr_setInt(&n, 3);
+ mclBnGT_pow(&e1, &e, &n);
+ mclBnGT_mul(&e2, &e, &e);
+ mclBnGT_mul(&e2, &e2, &e);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &e2));
+}
+
+CYBOZU_TEST_AUTO(precomputed)
+{
+ mclBnG1 P1, P2;
+ mclBnG2 Q1, Q2;
+ CYBOZU_TEST_ASSERT(!mclBnG1_hashAndMapTo(&P1, "1", 1));
+ CYBOZU_TEST_ASSERT(!mclBnG1_hashAndMapTo(&P2, "123", 3));
+ CYBOZU_TEST_ASSERT(!mclBnG2_hashAndMapTo(&Q1, "1", 1));
+ CYBOZU_TEST_ASSERT(!mclBnG2_hashAndMapTo(&Q2, "2", 1));
+
+ const int size = mclBn_getUint64NumToPrecompute();
+ std::vector<uint64_t> Q1buf, Q2buf;
+ Q1buf.resize(size);
+ Q2buf.resize(size);
+ mclBn_precomputeG2(Q1buf.data(), &Q1);
+ mclBn_precomputeG2(Q2buf.data(), &Q2);
+
+ mclBnGT e1, e2, f1, f2, f3, f4;
+ mclBn_pairing(&e1, &P1, &Q1);
+ mclBn_precomputedMillerLoop(&f1, &P1, Q1buf.data());
+ mclBn_finalExp(&f1, &f1);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &f1));
+
+ mclBn_pairing(&e2, &P2, &Q2);
+ mclBn_precomputedMillerLoop(&f2, &P2, Q2buf.data());
+ mclBn_finalExp(&f2, &f2);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e2, &f2));
+
+ mclBn_precomputedMillerLoop2(&f3, &P1, Q1buf.data(), &P2, Q2buf.data());
+ mclBn_precomputedMillerLoop2mixed(&f4, &P1, &Q1, &P2, Q2buf.data());
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&f3, &f4));
+ mclBn_finalExp(&f3, &f3);
+
+ mclBnGT_mul(&e1, &e1, &e2);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &f3));
+}
+
+CYBOZU_TEST_AUTO(serialize)
+{
+ const size_t FrSize = mclBn_getFrByteSize();
+ const size_t G1Size = mclBn_getG1ByteSize();
+ mclBnFr x1, x2;
+ mclBnG1 P1, P2;
+ mclBnG2 Q1, Q2;
+ char buf[1024];
+ size_t n;
+ size_t expectSize;
+ size_t ret;
+ // Fr
+ expectSize = FrSize;
+ mclBnFr_setInt(&x1, -1);
+ n = mclBnFr_serialize(buf, sizeof(buf), &x1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ ret = mclBnFr_deserialize(&x2, buf, n);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x1, &x2));
+
+ ret = mclBnFr_deserialize(&x2, buf, n - 1);
+ CYBOZU_TEST_EQUAL(ret, 0);
+
+ memset(&x2, 0, sizeof(x2));
+ ret = mclBnFr_deserialize(&x2, buf, n + 1);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x1, &x2));
+
+ n = mclBnFr_serialize(buf, expectSize, &x1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ // G1
+ expectSize = G1Size;
+ mclBnG1_hashAndMapTo(&P1, "1", 1);
+ n = mclBnG1_serialize(buf, sizeof(buf), &P1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ ret = mclBnG1_deserialize(&P2, buf, n);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&P1, &P2));
+
+ ret = mclBnG1_deserialize(&P2, buf, n - 1);
+ CYBOZU_TEST_EQUAL(ret, 0);
+
+ memset(&P2, 0, sizeof(P2));
+ ret = mclBnG1_deserialize(&P2, buf, n + 1);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&P1, &P2));
+
+ n = mclBnG1_serialize(buf, expectSize, &P1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ // G2
+ expectSize = G1Size * 2;
+ mclBnG2_hashAndMapTo(&Q1, "1", 1);
+ n = mclBnG2_serialize(buf, sizeof(buf), &Q1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ ret = mclBnG2_deserialize(&Q2, buf, n);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&Q1, &Q2));
+
+ ret = mclBnG2_deserialize(&Q2, buf, n - 1);
+ CYBOZU_TEST_EQUAL(ret, 0);
+
+ memset(&Q2, 0, sizeof(Q2));
+ ret = mclBnG2_deserialize(&Q2, buf, n + 1);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&Q1, &Q2));
+
+ n = mclBnG2_serialize(buf, expectSize, &Q1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+}
+
+CYBOZU_TEST_AUTO(serializeToHexStr)
+{
+ const size_t FrSize = mclBn_getFrByteSize();
+ const size_t G1Size = mclBn_getG1ByteSize();
+ mclBnFr x1, x2;
+ mclBnG1 P1, P2;
+ mclBnG2 Q1, Q2;
+ char buf[1024];
+ size_t n;
+ size_t expectSize;
+ size_t ret;
+ // Fr
+ expectSize = FrSize * 2; // hex string
+ mclBnFr_setInt(&x1, -1);
+ n = mclBnFr_getStr(buf, sizeof(buf), &x1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ ret = mclBnFr_setStr(&x2, buf, n, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x1, &x2));
+
+ ret = mclBnFr_setStr(&x2, buf, n - 1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_ASSERT(ret != 0);
+
+ memset(&x2, 0, sizeof(x2));
+ ret = mclBnFr_setStr(&x2, buf, n + 1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x1, &x2));
+
+ n = mclBnFr_getStr(buf, expectSize, &x1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ // G1
+ expectSize = G1Size * 2; // hex string
+ mclBnG1_hashAndMapTo(&P1, "1", 1);
+ n = mclBnG1_getStr(buf, sizeof(buf), &P1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ ret = mclBnG1_setStr(&P2, buf, n, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&P1, &P2));
+
+ ret = mclBnG1_setStr(&P2, buf, n - 1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_ASSERT(ret != 0);
+
+ memset(&P2, 0, sizeof(P2));
+ ret = mclBnG1_setStr(&P2, buf, n + 1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&P1, &P2));
+
+ n = mclBnG1_getStr(buf, expectSize, &P1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ // G2
+ expectSize = G1Size * 2 * 2; // hex string
+ mclBnG2_hashAndMapTo(&Q1, "1", 1);
+ n = mclBnG2_getStr(buf, sizeof(buf), &Q1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ ret = mclBnG2_setStr(&Q2, buf, n, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&Q1, &Q2));
+
+ ret = mclBnG2_setStr(&Q2, buf, n - 1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_ASSERT(ret != 0);
+
+ memset(&Q2, 0, sizeof(Q2));
+ ret = mclBnG2_setStr(&Q2, buf, n + 1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&Q1, &Q2));
+
+ n = mclBnG2_getStr(buf, expectSize, &Q1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+}
+
+#if MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE >= 6
+CYBOZU_TEST_AUTO(badG2)
+{
+ int ret;
+ ret = mclBn_init(MCL_BN381_1, MCLBN_COMPILED_TIME_VAR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ const char *s = "1 18d3d8c085a5a5e7553c3a4eb628e88b8465bf4de2612e35a0a4eb018fb0c82e9698896031e62fd7633ffd824a859474 1dc6edfcf33e29575d4791faed8e7203832217423bf7f7fbf1f6b36625b12e7132c15fbc15562ce93362a322fb83dd0d 65836963b1f7b6959030ddfa15ab38ce056097e91dedffd996c1808624fa7e2644a77be606290aa555cda8481cfb3cb 1b77b708d3d4f65aeedf54b58393463a42f0dc5856baadb5ce608036baeca398c5d9e6b169473a8838098fd72fd28b50";
+ mclBnG2 Q;
+ ret = mclBnG2_setStr(&Q, s, strlen(s), 16);
+ CYBOZU_TEST_ASSERT(ret != 0);
+}
+#endif
+
+struct Sequential {
+ uint32_t pos;
+ Sequential() : pos(0) {}
+ static uint32_t read(void *self, void *buf, uint32_t bufSize)
+ {
+ Sequential *seq = reinterpret_cast<Sequential*>(self);
+ uint8_t *p = reinterpret_cast<uint8_t*>(buf);
+ for (uint32_t i = 0; i < bufSize; i++) {
+ p[i] = uint8_t(seq->pos + i) & 0x1f; // mask is to make valid Fp
+ }
+ seq->pos += bufSize;
+ return bufSize;
+ }
+};
+
+CYBOZU_TEST_AUTO(setRandFunc)
+{
+ Sequential seq;
+ for (int j = 0; j < 3; j++) {
+ puts(j == 1 ? "sequential rand" : "true rand");
+ for (int i = 0; i < 5; i++) {
+ mclBnFr x;
+ int ret;
+ char buf[1024];
+ ret = mclBnFr_setByCSPRNG(&x);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ ret = mclBnFr_getStr(buf, sizeof(buf), &x, 16);
+ CYBOZU_TEST_ASSERT(ret > 0);
+ printf("%d %s\n", i, buf);
+ }
+ if (j == 0) {
+ mclBn_setRandFunc(&seq, Sequential::read);
+ } else {
+ mclBn_setRandFunc(0, 0);
+ }
+ }
+}
+
+CYBOZU_TEST_AUTO(Fp)
+{
+ mclBnFp x1, x2;
+ char buf[1024];
+ int ret = mclBnFp_setHashOf(&x1, "abc", 3);
+ CYBOZU_TEST_ASSERT(ret == 0);
+ mclSize n = mclBnFp_serialize(buf, sizeof(buf), &x1);
+ CYBOZU_TEST_ASSERT(n > 0);
+ n = mclBnFp_deserialize(&x2, buf, n);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_ASSERT(mclBnFp_isEqual(&x1, &x2));
+ for (size_t i = 0; i < n; i++) {
+ buf[i] = char(i);
+ }
+ ret = mclBnFp_setLittleEndian(&x1, buf, n);
+ CYBOZU_TEST_ASSERT(ret == 0);
+ memset(buf, 0, sizeof(buf));
+ n = mclBnFp_serialize(buf, sizeof(buf), &x1);
+ CYBOZU_TEST_ASSERT(n > 0);
+ for (size_t i = 0; i < n - 1; i++) {
+ CYBOZU_TEST_EQUAL(buf[i], char(i));
+ }
+ mclBnFp_clear(&x1);
+ memset(&x2, 0, sizeof(x2));
+ CYBOZU_TEST_ASSERT(mclBnFp_isEqual(&x1, &x2));
+}
+
+CYBOZU_TEST_AUTO(mod)
+{
+ {
+ // Fp
+ char buf[1024];
+ mclBn_getFieldOrder(buf, sizeof(buf));
+ mpz_class p(buf);
+ mpz_class x = mpz_class(1) << (mclBn_getFpByteSize() * 2);
+ mclBnFp y;
+ int ret = mclBnFp_setLittleEndianMod(&y, x.get_mpz_t()->_mp_d, x.get_mpz_t()->_mp_size * sizeof(void*));
+ CYBOZU_TEST_EQUAL(ret, 0);
+ mclBnFp_getStr(buf, sizeof(buf), &y, 10);
+ CYBOZU_TEST_EQUAL(mpz_class(buf), x % p);
+ }
+ {
+ // Fr
+ char buf[1024];
+ mclBn_getCurveOrder(buf, sizeof(buf));
+ mpz_class p(buf);
+ mpz_class x = mpz_class(1) << (mclBn_getFrByteSize() * 2);
+ mclBnFr y;
+ int ret = mclBnFr_setLittleEndianMod(&y, x.get_mpz_t()->_mp_d, x.get_mpz_t()->_mp_size * sizeof(void*));
+ CYBOZU_TEST_EQUAL(ret, 0);
+ mclBnFr_getStr(buf, sizeof(buf), &y, 10);
+ CYBOZU_TEST_EQUAL(mpz_class(buf), x % p);
+ }
+}
+
+CYBOZU_TEST_AUTO(Fp2)
+{
+ mclBnFp2 x1, x2;
+ char buf[1024];
+ int ret = mclBnFp_setHashOf(&x1.d[0], "abc", 3);
+ CYBOZU_TEST_ASSERT(ret == 0);
+ ret = mclBnFp_setHashOf(&x1.d[1], "xyz", 3);
+ CYBOZU_TEST_ASSERT(ret == 0);
+ mclSize n = mclBnFp2_serialize(buf, sizeof(buf), &x1);
+ CYBOZU_TEST_ASSERT(n > 0);
+ n = mclBnFp2_deserialize(&x2, buf, n);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_ASSERT(mclBnFp2_isEqual(&x1, &x2));
+ mclBnFp2_clear(&x1);
+ memset(&x2, 0, sizeof(x2));
+ CYBOZU_TEST_ASSERT(mclBnFp2_isEqual(&x1, &x2));
+}
+
+CYBOZU_TEST_AUTO(mapToG1)
+{
+ mclBnFp x;
+ mclBnG1 P1, P2;
+ mclBnFp_setHashOf(&x, "abc", 3);
+ int ret = mclBnFp_mapToG1(&P1, &x);
+ CYBOZU_TEST_ASSERT(ret == 0);
+ mclBnG1_hashAndMapTo(&P2, "abc", 3);
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&P1, &P2));
+}
+
+CYBOZU_TEST_AUTO(mapToG2)
+{
+ mclBnFp2 x;
+ mclBnG2 P1, P2;
+ mclBnFp_setHashOf(&x.d[0], "abc", 3);
+ mclBnFp_clear(&x.d[1]);
+ int ret = mclBnFp2_mapToG2(&P1, &x);
+ CYBOZU_TEST_ASSERT(ret == 0);
+ mclBnG2_hashAndMapTo(&P2, "abc", 3);
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&P1, &P2));
+}
+
+void G1onlyTest(int curve)
+{
+ printf("curve=%d\n", curve);
+ int ret;
+ ret = mclBn_init(curve, MCLBN_COMPILED_TIME_VAR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ mclBnG1 P0;
+ ret = mclBnG1_getBasePoint(&P0);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ char buf[256];
+ ret = mclBnG1_getStr(buf, sizeof(buf), &P0, 16);
+ CYBOZU_TEST_ASSERT(ret > 0);
+ printf("basePoint=%s\n", buf);
+ G1test();
+}
+
+CYBOZU_TEST_AUTO(G1only)
+{
+ const int tbl[] = {
+ MCL_SECP192K1,
+ MCL_NIST_P192,
+ MCL_SECP224K1,
+ MCL_NIST_P224, // hashAndMapTo is error
+ MCL_SECP256K1,
+ MCL_NIST_P256,
+#if MCLBN_FP_UNIT_SIZE >= 6 && MCLBN_FR_UNIT_SIZE >= 6
+ MCL_SECP384R1,
+#endif
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ G1onlyTest(tbl[i]);
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/bn_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn_test.cpp
new file mode 100644
index 000000000..071ec706c
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/bn_test.cpp
@@ -0,0 +1,408 @@
+#define PUT(x) std::cout << #x "=" << x << std::endl;
+#define CYBOZU_TEST_DISABLE_AUTO_RUN
+#include <cybozu/benchmark.hpp>
+cybozu::CpuClock clk;
+#include <cybozu/test.hpp>
+#include <mcl/bn256.hpp>
+#include <cybozu/option.hpp>
+#include <cybozu/xorshift.hpp>
+
+#if defined(__EMSCRIPTEN__) && !defined(MCL_AVOID_EXCEPTION_TEST)
+ #define MCL_AVOID_EXCEPTION_TEST
+#endif
+
+typedef mcl::bn::local::Compress Compress;
+using namespace mcl::bn;
+
+mcl::fp::Mode g_mode;
+
+const struct TestSet {
+ mcl::CurveParam cp;
+ const char *name;
+ struct G2 {
+ const char *aa;
+ const char *ab;
+ const char *ba;
+ const char *bb;
+ } g2;
+ struct G1 {
+ int a;
+ int b;
+ } g1;
+ const char *e;
+} g_testSetTbl[] = {
+ {
+ mcl::BN254,
+ "BN254",
+ {
+ "12723517038133731887338407189719511622662176727675373276651903807414909099441",
+ "4168783608814932154536427934509895782246573715297911553964171371032945126671",
+ "13891744915211034074451795021214165905772212241412891944830863846330766296736",
+ "7937318970632701341203597196594272556916396164729705624521405069090520231616",
+ },
+ {
+ -1, 1
+ },
+ "8118772341496577043438385328606447626730215814727396173233264007541007797690 "
+ "6742571767760762192519140673058087976840103832045324348366170860928670686713 "
+ "9727912590495366720378364920530546614235713408261568635512172059018197267630 "
+ "10180700148605185348549931182990442059136187839792856455707820203302941578832 "
+ "5054507763444412917986776641611331046146804026682679569910978464879371792565 "
+ "6917005519826733659554708445125877487590687705432214234949972860245110398023 "
+ "10448556317747236258066222816126375978842661908560317699736569642190930635294 "
+ "1516980358051268127904344653343215863076753141133525905743113718749531324025 "
+ "9794836735385959178744195210089532061310424844916928682580569566332541022353 "
+ "9375574834170998962484906689780052970915033987453510324648351251071086068423 "
+ "710778048594563655498360873129325895716179849942646859397874562033386335205 "
+ "10688745994254573144943003027511098295097561129365638275727908595677791826005"
+ },
+ {
+ mcl::BN_SNARK1,
+ "BN_SNARK1",
+ {
+ "15267802884793550383558706039165621050290089775961208824303765753922461897946",
+ "9034493566019742339402378670461897774509967669562610788113215988055021632533",
+ "644888581738283025171396578091639672120333224302184904896215738366765861164",
+ "20532875081203448695448744255224543661959516361327385779878476709582931298750",
+ },
+ {
+ 1, 2
+ },
+ "15163392945550945552839911839294582974434771053565812675833291179413834896953 "
+ "20389211011850518572149982239826345669421868561029856883955740401696801984953 "
+ "17766795911013516700216709333389761327222334145011922123798810516425387779347 "
+ "6064163297423711021549973931984064750876944939004405231004441199168710504090 "
+ "296093106139306574860102680862436174771023602986903675151017278048818344347 "
+ "1573596951222456889652521728261836933382094474023551133585236991207205981715 "
+ "3511871642997169996730611220058787939468653751355351269812083879279936651479 "
+ "17848534184080172844395614793152774197360421729995967636680357250333093768504 "
+ "3273860031361637906105800996652640969711942192883181518057117446820546419132 "
+ "7212721189663231589365009629980400132745687533815732336503876102977912682966 "
+ "18569236611881855981733896549089319395087993987737891870319625215675547032585 "
+ "10088832670068482545658647976676953228519838542958787800193793260459700064172 "
+ },
+};
+
+CYBOZU_TEST_AUTO(size)
+{
+ CYBOZU_TEST_EQUAL(sizeof(Fp), 32u);
+ CYBOZU_TEST_EQUAL(sizeof(Fp2), sizeof(Fp) * 2);
+ CYBOZU_TEST_EQUAL(sizeof(Fp6), sizeof(Fp) * 6);
+ CYBOZU_TEST_EQUAL(sizeof(Fp12), sizeof(Fp) * 12);
+ CYBOZU_TEST_EQUAL(sizeof(G1), sizeof(Fp) * 3);
+ CYBOZU_TEST_EQUAL(sizeof(G2), sizeof(Fp2) * 3);
+}
+
+void testSetStr(const G2& Q0)
+{
+ G2::setCompressedExpression();
+ G2 Q;
+ Q.clear();
+ for (int i = 0; i < 10; i++) {
+ G2 R;
+ R.setStr(Q.getStr());
+ CYBOZU_TEST_EQUAL(Q, R);
+ G2::add(Q, Q, Q0);
+ }
+}
+
+void testMapToG1()
+{
+ G1 g;
+ for (int i = 1; i < 10; i++) {
+ mapToG1(g, i);
+ CYBOZU_TEST_ASSERT(!g.isZero());
+ G1 gr;
+ G1::mulGeneric(gr, g, BN::param.r);
+ CYBOZU_TEST_ASSERT(gr.isZero());
+ }
+#ifndef MCL_AVOID_EXCEPTION_TEST
+ if (BN::param.cp.b == 2) {
+ Fp c1;
+ bool b = Fp::squareRoot(c1, -3);
+ CYBOZU_TEST_ASSERT(b);
+ CYBOZU_TEST_EXCEPTION(mapToG1(g, 0), cybozu::Exception);
+ CYBOZU_TEST_EXCEPTION(mapToG1(g, c1), cybozu::Exception);
+ CYBOZU_TEST_EXCEPTION(mapToG1(g, -c1), cybozu::Exception);
+ }
+#endif
+}
+
+void testMapToG2()
+{
+ G2 g;
+ for (int i = 1; i < 10; i++) {
+ mapToG2(g, i);
+ CYBOZU_TEST_ASSERT(!g.isZero());
+ G2 gr;
+ G2::mulGeneric(gr, g, BN::param.r);
+ CYBOZU_TEST_ASSERT(gr.isZero());
+ }
+#ifndef MCL_AVOID_EXCEPTION_TEST
+ if (BN::param.cp.b == 2) {
+ CYBOZU_TEST_EXCEPTION(mapToG2(g, 0), cybozu::Exception);
+ }
+#endif
+ Fp x;
+ x.setHashOf("abc");
+ mapToG2(g, Fp2(x, 0));
+ CYBOZU_TEST_ASSERT(g.isValid());
+}
+
+void testCyclotomic()
+{
+ Fp12 a;
+ for (int i = 0; i < 12; ++i) {
+ a.getFp0()[i] = i * i;
+ }
+ local::mapToCyclotomic(a, a);
+ Fp12 d;
+ Compress b(d, a);
+ a *= a;
+ Fp12 d2;
+ Compress c(d2, b);
+ Compress::square_n(c, 1);
+ c.decompress();
+ CYBOZU_TEST_EQUAL(a, d2);
+ Compress::square_n(b, 1);
+ b.decompress();
+ CYBOZU_TEST_EQUAL(a, d);
+}
+
+void testCompress(const G1& P, const G2& Q)
+{
+ if (BN::param.cp.curveType != MCL_BN254) return;
+ Fp12 a;
+ pairing(a, P, Q);
+ local::mapToCyclotomic(a, a);
+ Fp12 b;
+ Compress::fixed_power(b, a);
+ Fp12 c;
+ Fp12::pow(c, a, BN::param.abs_z);
+ CYBOZU_TEST_EQUAL(b, c);
+}
+
+void testPrecomputed(const G1& P, const G2& Q)
+{
+ Fp12 e1, e2;
+ pairing(e1, P, Q);
+ std::vector<Fp6> Qcoeff;
+ precomputeG2(Qcoeff, Q);
+ precomputedMillerLoop(e2, P, Qcoeff);
+ finalExp(e2, e2);
+ CYBOZU_TEST_EQUAL(e1, e2);
+}
+
+void testFp12pow(const G1& P, const G2& Q)
+{
+ Fp12 e, e1, e2;
+ pairing(e, P, Q);
+ cybozu::XorShift rg;
+ for (int i = -10; i < 10; i++) {
+ mpz_class xm = i;
+ Fp12::pow(e1, e, xm);
+ Fp12::powGeneric(e2, e, xm);
+ CYBOZU_TEST_EQUAL(e1, e2);
+ }
+ for (int i = 0; i < 10; i++) {
+ Fr x;
+ x.setRand(rg);
+ mpz_class xm = x.getMpz();
+ Fp12::pow(e1, e, xm);
+ BN::param.glv2.pow(e2, e, xm);
+ CYBOZU_TEST_EQUAL(e1, e2);
+ }
+}
+
+void testMillerLoop2(const G1& P1, const G2& Q1)
+{
+ Fp12 e1, e2, e3;
+ mpz_class c1("12342342423442");
+ mpz_class c2("329428049820348209482");
+ G2 Q2;
+ G1 P2;
+ G2::mul(Q2, Q1, c1);
+ G1::mul(P2, P1, c2);
+ pairing(e1, P1, Q1);
+ pairing(e2, P2, Q2);
+ e1 *= e2;
+
+ std::vector<Fp6> Q1coeff, Q2coeff;
+ precomputeG2(Q1coeff, Q1);
+ precomputeG2(Q2coeff, Q2);
+ precomputedMillerLoop2(e2, P1, Q1coeff, P2, Q2coeff);
+ precomputedMillerLoop2mixed(e3, P1, Q1, P2, Q2coeff);
+ CYBOZU_TEST_EQUAL(e2, e3);
+ finalExp(e2, e2);
+ CYBOZU_TEST_EQUAL(e1, e2);
+
+ // special value
+ G2 Z;
+ Z.clear();
+ Q2 += Q2;
+ precomputeG2(Q1coeff, Z);
+ precomputeG2(Q2coeff, Q2);
+ precomputedMillerLoop2(e2, P1, Q1coeff, P2, Q2coeff);
+ precomputedMillerLoop2mixed(e3, P1, Z, P2, Q2coeff);
+ finalExp(e2, e2);
+ finalExp(e3, e3);
+ CYBOZU_TEST_EQUAL(e2, e3);
+}
+
+void testPairing(const G1& P, const G2& Q, const char *eStr)
+{
+ Fp12 e1;
+ pairing(e1, P, Q);
+ Fp12 e2;
+ {
+ std::stringstream ss(eStr);
+ ss >> e2;
+ }
+ CYBOZU_TEST_EQUAL(e1, e2);
+
+ Fp12 e = e1, ea;
+ G1 Pa;
+ G2 Qa;
+#if defined(__EMSCRIPTEN__) || MCL_SIZEOF_UNIT == 4
+ const int count = 100;
+#else
+ const int count = 1000;
+#endif
+ mpz_class a;
+ cybozu::XorShift rg;
+ for (int i = 0; i < count; i++) {
+ Fr r;
+ r.setRand(rg);
+ a = r.getMpz();
+ Fp12::pow(ea, e, a);
+ G1::mul(Pa, P, a);
+ G2::mul(Qa, Q, a);
+ G1 T;
+ G1::mulCT(T, P, a);
+ CYBOZU_TEST_EQUAL(Pa, T);
+ pairing(e1, Pa, Q);
+ pairing(e2, P, Qa);
+ CYBOZU_TEST_EQUAL(ea, e1);
+ CYBOZU_TEST_EQUAL(ea, e2);
+ }
+}
+
+void testTrivial(const G1& P, const G2& Q)
+{
+ G1 Z1; Z1.clear();
+ G2 Z2; Z2.clear();
+ Fp12 e;
+ pairing(e, Z1, Q);
+ CYBOZU_TEST_EQUAL(e, 1);
+ pairing(e, P, Z2);
+ CYBOZU_TEST_EQUAL(e, 1);
+ pairing(e, Z1, Z2);
+ CYBOZU_TEST_EQUAL(e, 1);
+
+ std::vector<Fp6> Qcoeff;
+ precomputeG2(Qcoeff, Z2);
+ precomputedMillerLoop(e, P, Qcoeff);
+ finalExp(e, e);
+ CYBOZU_TEST_EQUAL(e, 1);
+
+ precomputeG2(Qcoeff, Q);
+ precomputedMillerLoop(e, Z1, Qcoeff);
+ finalExp(e, e);
+ CYBOZU_TEST_EQUAL(e, 1);
+}
+
+void testIoAll(const G1& P, const G2& Q)
+{
+ const int FpTbl[] = { 0, 2, 2|mcl::IoPrefix, 10, 16, 16|mcl::IoPrefix, mcl::IoArray, mcl::IoArrayRaw };
+ const int EcTbl[] = { mcl::IoEcAffine, mcl::IoEcProj, mcl::IoEcCompY, mcl::IoSerialize };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(FpTbl); i++) {
+ for (size_t j = 0; j < CYBOZU_NUM_OF_ARRAY(EcTbl); j++) {
+ G1 P2 = P, P3;
+ G2 Q2 = Q, Q3;
+ int ioMode = FpTbl[i] | EcTbl[j];
+ std::string s = P2.getStr(ioMode);
+ P3.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(P2, P3);
+ s = Q2.getStr(ioMode);
+ Q3.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(Q2, Q3);
+ s = P.x.getStr(ioMode);
+ Fp Px;
+ Px.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(P.x, Px);
+ s = Q.x.getStr(ioMode);
+ Fp2 Qx;
+ Qx.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(Q.x, Qx);
+ }
+ }
+}
+
+void testIo(const G1& P, const G2& Q)
+{
+ testIoAll(P, Q);
+ G1 Z1;
+ G2 Z2;
+ Z1.clear();
+ Z2.clear();
+ testIoAll(Z1, Z2);
+}
+
+#include "bench.hpp"
+
+CYBOZU_TEST_AUTO(naive)
+{
+ printf("mcl version=%03x\n", mcl::version);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(g_testSetTbl); i++) {
+ const TestSet& ts = g_testSetTbl[i];
+ printf("i=%d curve=%s\n", int(i), ts.name);
+ initPairing(ts.cp, g_mode);
+ const G1 P(ts.g1.a, ts.g1.b);
+ const G2 Q(Fp2(ts.g2.aa, ts.g2.ab), Fp2(ts.g2.ba, ts.g2.bb));
+#ifdef ONLY_BENCH
+ {
+ Fp12 e;
+ for (int i = 0; i < 10000; i++) { clk.begin(); pairing(e, P, Q); clk.end(); }
+ }
+ clk.put();
+ return;
+#endif
+ testFp12pow(P, Q);
+ testIo(P, Q);
+ testTrivial(P, Q);
+ testSetStr(Q);
+ testMapToG1();
+ testMapToG2();
+ testCyclotomic();
+ testCompress(P, Q);
+ testPairing(P, Q, ts.e);
+ testPrecomputed(P, Q);
+ testMillerLoop2(P, Q);
+ testBench(P, Q);
+ benchAddDblG1();
+ benchAddDblG2();
+ }
+ int count = (int)clk.getCount();
+ if (count) {
+ printf("count=%d ", count);
+ clk.put();
+ }
+}
+
+int main(int argc, char *argv[])
+ try
+{
+ cybozu::Option opt;
+ std::string mode;
+ opt.appendOpt(&mode, "auto", "m", ": mode(gmp/gmp_mont/llvm/llvm_mont/xbyak)");
+ if (!opt.parse(argc, argv)) {
+ opt.usage();
+ return 1;
+ }
+ g_mode = mcl::fp::StrToMode(mode);
+ printf("JIT %d\n", mcl::fp::isEnableJIT());
+ return cybozu::test::autoRun.run(argc, argv);
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+ return 1;
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/conversion_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/conversion_test.cpp
new file mode 100644
index 000000000..ec11fe900
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/conversion_test.cpp
@@ -0,0 +1,96 @@
+#include <cybozu/test.hpp>
+#include <mcl/conversion.hpp>
+
+CYBOZU_TEST_AUTO(arrayToDec)
+{
+ const struct {
+ uint32_t x[5];
+ size_t xn;
+ const char *s;
+ } tbl[] = {
+ { { 0, 0, 0, 0, 0 }, 1, "0" },
+ { { 9, 0, 0, 0, 0 }, 1, "9" },
+ { { 123456789, 0, 0, 0, 0 }, 1, "123456789" },
+ { { 2147483647, 0, 0, 0, 0 }, 1, "2147483647" },
+ { { 0xffffffff, 0, 0, 0, 0 }, 1, "4294967295" },
+ { { 0x540be400, 0x2, 0, 0, 0 }, 2, "10000000000" },
+ { { 0xffffffff, 0xffffffff, 0, 0, 0 }, 2, "18446744073709551615" },
+ { { 0x89e80001, 0x8ac72304, 0, 0, 0 }, 2, "10000000000000000001" },
+ { { 0xc582ca00, 0x8ac72304, 0, 0, 0 }, 2, "10000000001000000000" },
+ { { 0, 0, 1, 0, 0 }, 3, "18446744073709551616" },
+ { { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0 }, 4, "340282366920938463463374607431768211455" },
+ { { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }, 5, "1461501637330902918203684832716283019655932542975" },
+ { { 0x3b9aca00, 0x5e3f3700, 0x1cbfa532, 0x04f6433a, 0xd83ff078 }, 5, "1234567901234560000000000000000000000001000000000" },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const size_t bufSize = 128;
+ char buf[bufSize] = {};
+ const char *str = tbl[i].s;
+ const uint32_t *x = tbl[i].x;
+ const size_t strLen = strlen(str);
+ size_t n = mcl::fp::arrayToDec(buf, bufSize, x, tbl[i].xn);
+ CYBOZU_TEST_EQUAL(n, strLen);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + bufSize - n, str, n);
+ const size_t maxN = 32;
+ uint32_t xx[maxN] = {};
+ size_t xn = mcl::fp::decToArray(xx, maxN, str, strLen);
+ CYBOZU_TEST_EQUAL(xn, tbl[i].xn);
+ CYBOZU_TEST_EQUAL_ARRAY(xx, x, xn);
+ }
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const size_t bufSize = 128;
+ char buf[bufSize] = {};
+ const char *str = tbl[i].s;
+ const size_t strLen = strlen(str);
+ uint64_t x[8] = {};
+ size_t xn = (tbl[i].xn + 1) / 2;
+ memcpy(x, tbl[i].x, tbl[i].xn * sizeof(uint32_t));
+ size_t n = mcl::fp::arrayToDec(buf, bufSize, x, xn);
+ CYBOZU_TEST_EQUAL(n, strLen);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + bufSize - n, str, n);
+ const size_t maxN = 32;
+ uint64_t xx[maxN] = {};
+ size_t xxn = mcl::fp::decToArray(xx, maxN, str, strLen);
+ CYBOZU_TEST_EQUAL(xxn, xn);
+ CYBOZU_TEST_EQUAL_ARRAY(xx, x, xn);
+ }
+}
+
+CYBOZU_TEST_AUTO(writeHexStr)
+{
+ const char *hex1tbl = "0123456789abcdef";
+ const char *hex2tbl = "0123456789ABCDEF";
+ for (size_t i = 0; i < 16; i++) {
+ uint8_t v = 0xff;
+ CYBOZU_TEST_ASSERT(mcl::fp::local::hexCharToUint8(&v, hex1tbl[i]));
+ CYBOZU_TEST_EQUAL(v, i);
+ CYBOZU_TEST_ASSERT(mcl::fp::local::hexCharToUint8(&v, hex2tbl[i]));
+ CYBOZU_TEST_EQUAL(v, i);
+ }
+ const struct Tbl {
+ const char *bin;
+ size_t n;
+ const char *hex;
+ } tbl[] = {
+ { "", 0, "" },
+ { "\x12\x34\xab", 3, "1234ab" },
+ { "\xff\xfc\x00\x12", 4, "fffc0012" },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ char buf[32];
+ cybozu::MemoryOutputStream os(buf, sizeof(buf));
+ const char *bin = tbl[i].bin;
+ const char *hex = tbl[i].hex;
+ size_t n = tbl[i].n;
+ bool b;
+ mcl::fp::writeHexStr(&b, os, bin, n);
+ CYBOZU_TEST_ASSERT(b);
+ CYBOZU_TEST_EQUAL(os.getPos(), n * 2);
+ CYBOZU_TEST_EQUAL_ARRAY(buf, hex, n * 2);
+
+ cybozu::MemoryInputStream is(hex, n * 2);
+ size_t w = mcl::fp::readHexStr(buf, n, is);
+ CYBOZU_TEST_EQUAL(w, n);
+ CYBOZU_TEST_EQUAL_ARRAY(buf, bin, n);
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/ec_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/ec_test.cpp
new file mode 100644
index 000000000..ec49adbfe
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/ec_test.cpp
@@ -0,0 +1,573 @@
+//#define MCL_EC_USE_AFFINE
+#define PUT(x) std::cout << #x "=" << (x) << std::endl
+#define CYBOZU_TEST_DISABLE_AUTO_RUN
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+#include <mcl/gmp_util.hpp>
+
+#include <mcl/fp.hpp>
+#include <mcl/ec.hpp>
+#include <mcl/ecparam.hpp>
+#include <time.h>
+#include <math.h>
+
+typedef mcl::FpT<> Fp;
+struct tagZn;
+typedef mcl::FpT<tagZn> Zn;
+typedef mcl::EcT<Fp> Ec;
+
+CYBOZU_TEST_AUTO(sizeof)
+{
+ CYBOZU_TEST_EQUAL(sizeof(Fp), sizeof(mcl::fp::Unit) * Fp::maxSize);
+#ifdef MCL_EC_USE_AFFINE
+ CYBOZU_TEST_EQUAL(sizeof(Ec), sizeof(Fp) * 2 + sizeof(mcl::fp::Unit));
+#else
+ CYBOZU_TEST_EQUAL(sizeof(Ec), sizeof(Fp) * 3);
+#endif
+}
+
+struct Test {
+ const mcl::EcParam& para;
+ Test(const mcl::EcParam& para, mcl::fp::Mode fpMode, mcl::ec::Mode ecMode)
+ : para(para)
+ {
+ printf("fpMode=%s\n", mcl::fp::ModeToStr(fpMode));
+ Fp::init(para.p, fpMode);
+ Zn::init(para.n, fpMode);
+ Ec::init(para.a, para.b, ecMode);
+ }
+ void cstr() const
+ {
+ Ec O;
+ O.clear();
+ CYBOZU_TEST_ASSERT(O.isZero());
+ CYBOZU_TEST_ASSERT(O.isValid());
+ Ec P;
+ P.clear();
+ Ec::neg(P, O);
+ CYBOZU_TEST_EQUAL(P, O);
+ }
+ void pow2(Ec& Q, const Ec& P, int n) const
+ {
+ Q = P;
+ for (int i = 0; i < n; i++) {
+ Q += Q;
+ }
+ }
+ void pow2test(const Ec& P, int n) const
+ {
+ Ec Q, R;
+ pow2(Q, P, n);
+ Q -= P; // Q = (2^n - 1)P
+ Fp x = 1;
+ for (int i = 0; i < n; i++) {
+ x += x;
+ }
+ x -= 1; // x = 2^n - 1
+ Ec::mul(R, P, x);
+ CYBOZU_TEST_EQUAL(Q, R);
+ Q = P;
+ Ec::mul(Q, Q, x);
+ CYBOZU_TEST_EQUAL(Q, R);
+ }
+ void ope() const
+ {
+ Fp x(para.gx);
+ Fp y(para.gy);
+ Zn n = 0;
+ CYBOZU_TEST_NO_EXCEPTION(Ec(x, y));
+ CYBOZU_TEST_EXCEPTION(Ec(x, y + 1), cybozu::Exception);
+ Ec P(x, y), Q, R, O;
+ O.clear();
+ CYBOZU_TEST_ASSERT(P.isNormalized());
+ {
+ Ec::neg(Q, P);
+ CYBOZU_TEST_EQUAL(Q.x, P.x);
+ CYBOZU_TEST_EQUAL(Q.y, -P.y);
+
+ R = P + Q;
+ CYBOZU_TEST_ASSERT(R.isZero());
+ CYBOZU_TEST_ASSERT(R.isNormalized());
+ CYBOZU_TEST_ASSERT(R.isValid());
+
+ R = P + O;
+ CYBOZU_TEST_EQUAL(R, P);
+ R = O + P;
+ CYBOZU_TEST_EQUAL(R, P);
+ }
+
+ {
+ Ec::dbl(R, P);
+#ifndef MCL_EC_USE_AFFINE
+ CYBOZU_TEST_ASSERT(!R.isNormalized());
+#endif
+ CYBOZU_TEST_ASSERT(R.isValid());
+ Ec R2 = P + P;
+ CYBOZU_TEST_EQUAL(R, R2);
+ {
+ Ec P2 = P;
+ Ec::dbl(P2, P2);
+ CYBOZU_TEST_EQUAL(P2, R2);
+ }
+ Ec R3L = R2 + P;
+ Ec R3R = P + R2;
+ CYBOZU_TEST_EQUAL(R3L, R3R);
+ {
+ Ec RR = R2;
+ RR = RR + P;
+ CYBOZU_TEST_EQUAL(RR, R3L);
+ RR = R2;
+ RR = P + RR;
+ CYBOZU_TEST_EQUAL(RR, R3L);
+ RR = P;
+ RR = RR + RR;
+ CYBOZU_TEST_EQUAL(RR, R2);
+ }
+ Ec::mul(R, P, 2);
+ CYBOZU_TEST_EQUAL(R, R2);
+ Ec R4L = R3L + R2;
+ Ec R4R = R2 + R3L;
+ CYBOZU_TEST_EQUAL(R4L, R4R);
+ Ec::mul(R, P, 5);
+ CYBOZU_TEST_EQUAL(R, R4L);
+ }
+ {
+ R = P;
+ for (int i = 0; i < 10; i++) {
+ R += P;
+ }
+ Ec R2;
+ Ec::mul(R2, P, 11);
+ CYBOZU_TEST_EQUAL(R, R2);
+ }
+ Ec::mul(R, P, n - 1);
+ CYBOZU_TEST_EQUAL(R, -P);
+ R += P; // Ec::mul(R, P, n);
+ CYBOZU_TEST_ASSERT(R.isZero());
+ {
+ const int tbl[] = { 1, 2, 63, 64, 65, 127, 128, 129 };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ pow2test(P, tbl[i]);
+ }
+ }
+ {
+ Ec::mul(Q, P, 0);
+ CYBOZU_TEST_ASSERT(Q.isZero());
+ Q = P;
+ CYBOZU_TEST_ASSERT(!Q.isZero());
+ Ec::mul(Q, Q, 0);
+ CYBOZU_TEST_ASSERT(Q.isZero());
+ Ec::mul(Q, P, 1);
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ {
+ Ec R2;
+ P += P;
+ Q += P;
+ CYBOZU_TEST_ASSERT(!P.z.isOne());
+ CYBOZU_TEST_ASSERT(!Q.z.isOne());
+ Ec::add(R2, P, Q);
+
+ P.normalize();
+ CYBOZU_TEST_ASSERT(P.z.isOne());
+ CYBOZU_TEST_ASSERT(!Q.z.isOne());
+ // affine + generic
+ Ec::add(R, P, Q);
+ CYBOZU_TEST_EQUAL(R, R2);
+ // generic + affine
+ Ec::add(R, Q, P);
+ CYBOZU_TEST_EQUAL(R, R2);
+
+ Q.normalize();
+ CYBOZU_TEST_ASSERT(P.z.isOne());
+ CYBOZU_TEST_ASSERT(Q.z.isOne());
+ // affine + affine
+ Ec::add(R, P, Q);
+ CYBOZU_TEST_EQUAL(R, R2);
+
+ P += P;
+ CYBOZU_TEST_ASSERT(!P.z.isOne());
+ // generic
+ Ec::dbl(R2, P);
+
+ P.normalize();
+ CYBOZU_TEST_ASSERT(P.z.isOne());
+ // affine
+ Ec::dbl(R, P);
+ CYBOZU_TEST_EQUAL(R, R2);
+ }
+ }
+
+ void mul() const
+ {
+ Fp x(para.gx);
+ Fp y(para.gy);
+ Ec P(x, y);
+ Ec Q;
+ Ec R;
+ R.clear();
+ for (int i = 0; i < 100; i++) {
+ Ec::mul(Q, P, i);
+ CYBOZU_TEST_EQUAL(Q, R);
+ R += P;
+ }
+ }
+
+ void neg_mul() const
+ {
+ Fp x(para.gx);
+ Fp y(para.gy);
+ Ec P(x, y);
+ Ec Q;
+ Ec R;
+ R.clear();
+ for (int i = 0; i < 100; i++) {
+ Ec::mul(Q, P, -i);
+ CYBOZU_TEST_EQUAL(Q, R);
+ R -= P;
+ }
+ }
+ void squareRoot() const
+ {
+ Fp x(para.gx);
+ Fp y(para.gy);
+ bool odd = y.isOdd();
+ Fp yy;
+ bool b = Ec::getYfromX(yy, x, odd);
+ CYBOZU_TEST_ASSERT(b);
+ CYBOZU_TEST_EQUAL(yy, y);
+ Fp::neg(y, y);
+ odd = y.isOdd();
+ yy.clear();
+ b = Ec::getYfromX(yy, x, odd);
+ CYBOZU_TEST_ASSERT(b);
+ CYBOZU_TEST_EQUAL(yy, y);
+ }
+ void mul_fp() const
+ {
+ Fp x(para.gx);
+ Fp y(para.gy);
+ Ec P(x, y);
+ Ec Q;
+ Ec R;
+ R.clear();
+ for (int i = 0; i < 100; i++) {
+ Ec::mul(Q, P, Zn(i));
+ CYBOZU_TEST_EQUAL(Q, R);
+ R += P;
+ }
+ }
+ void str() const
+ {
+ const Fp x(para.gx);
+ const Fp y(para.gy);
+ Ec P(x, y);
+ Ec Q;
+ // not compressed
+ Ec::setCompressedExpression(false);
+ {
+ std::stringstream ss;
+ ss << P;
+ ss >> Q;
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ {
+ Q.clear();
+ CYBOZU_TEST_EQUAL(Q.getStr(), "0");
+ }
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 2; j++) {
+ int base = i == 0 ? 10 : 16;
+ bool withPrefix = j == 0;
+ int ioMode = base | (withPrefix ? mcl::IoPrefix : 0);
+ std::string expected = "1 " + x.getStr(ioMode) + " " + y.getStr(ioMode);
+ CYBOZU_TEST_EQUAL(P.getStr(ioMode), expected);
+ std::ostringstream os;
+ if (base == 16) {
+ os << std::hex;
+ }
+ if (withPrefix) {
+ os << std::showbase;
+ }
+ os << P;
+ CYBOZU_TEST_EQUAL(os.str(), expected);
+ }
+ }
+ {
+ P = -P;
+ std::stringstream ss;
+ ss << P;
+ ss >> Q;
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ P.clear();
+ {
+ std::stringstream ss;
+ ss << P;
+ ss >> Q;
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ CYBOZU_TEST_EXCEPTION(P.setStr("1 3 5"), cybozu::Exception);
+ // compressed
+ Ec::setCompressedExpression(true);
+ P.set(x, y);
+ {
+ std::stringstream ss;
+ ss << P;
+ ss >> Q;
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ {
+ P = -P;
+ std::stringstream ss;
+ ss << P;
+ ss >> Q;
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ P.clear();
+ {
+ std::stringstream ss;
+ ss << P;
+ ss >> Q;
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ // IoSerialize, IoSerializeHexStr
+ const size_t adj = Ec::isMSBserialize() ? 0 : 1;
+ P.set(x, y);
+ {
+ std::string s = P.getStr(mcl::IoSerialize);
+ CYBOZU_TEST_EQUAL(s.size(), Fp::getByteSize() + adj);
+ Q.setStr(s, mcl::IoSerialize);
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ {
+ std::string s = P.getStr(mcl::IoSerializeHexStr);
+ CYBOZU_TEST_EQUAL(s.size(), (Fp::getByteSize() + adj) * 2);
+ Q.setStr(s, mcl::IoSerializeHexStr);
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ P = -P;
+ {
+ std::string s = P.getStr(mcl::IoSerialize);
+ CYBOZU_TEST_EQUAL(s.size(), Fp::getByteSize() + adj);
+ Q.setStr(s, mcl::IoSerialize);
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ {
+ std::string s = P.getStr(mcl::IoSerializeHexStr);
+ CYBOZU_TEST_EQUAL(s.size(), (Fp::getByteSize() + adj) * 2);
+ Q.setStr(s, mcl::IoSerializeHexStr);
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ P.clear();
+ {
+ std::string s = P.getStr(mcl::IoSerialize);
+ CYBOZU_TEST_EQUAL(s.size(), Fp::getByteSize() + adj);
+ CYBOZU_TEST_ASSERT(mcl::fp::isZeroArray(s.c_str(), s.size()));
+ Q.setStr(s, mcl::IoSerialize);
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ {
+ std::string s = P.getStr(mcl::IoSerializeHexStr);
+ CYBOZU_TEST_EQUAL(s.size(), (Fp::getByteSize() + adj) * 2);
+ for (size_t i = 0; i < s.size(); i++) {
+ CYBOZU_TEST_EQUAL(s[i], '0');
+ }
+ Q.setStr(s, mcl::IoSerializeHexStr);
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ }
+ void ioMode() const
+ {
+ const Fp x(para.gx);
+ const Fp y(para.gy);
+ Ec P(x, y);
+ const mcl::IoMode tbl[] = {
+ mcl::IoBin,
+ mcl::IoDec,
+ mcl::IoHex,
+ mcl::IoArray,
+ mcl::IoArrayRaw,
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Fp::setIoMode(tbl[i]);
+ {
+ std::stringstream ss;
+ ss << P;
+ Ec Q;
+ ss >> Q;
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ {
+ std::stringstream ss;
+ Ec Q;
+ Q.clear();
+ ss << Q;
+ Ec R;
+ ss >> R;
+ CYBOZU_TEST_EQUAL(Q, R);
+ }
+ }
+ Fp::setIoMode(mcl::IoAuto);
+ }
+ void mulCT() const
+ {
+ Fp x(para.gx);
+ Fp y(para.gy);
+ Ec P(x, y), Q1, Q2;
+ for (int i = 0; i < 100; i++) {
+ Zn r = i;
+ Ec::mul(Q1, P, r);
+ Ec::mulCT(Q2, P, r);
+ CYBOZU_TEST_EQUAL(Q1, Q2);
+ }
+ }
+ void compare() const
+ {
+ Fp x(para.gx);
+ Fp y(para.gy);
+ Ec P1(x, y);
+ Ec P2(x, -y);
+ int c = Ec::compare(P1, P2);
+ int cx = Fp::compare(y, -y);
+ CYBOZU_TEST_EQUAL(c, cx);
+ c = Ec::compare(P2, P1);
+ cx = Fp::compare(-y, y);
+ CYBOZU_TEST_EQUAL(c, cx);
+ CYBOZU_TEST_EQUAL(Ec::compare(P1, P1), 0);
+ bool b1, b2;
+ b1 = P1 <= P2;
+ b2 = y <= -y;
+ CYBOZU_TEST_EQUAL(b1, b2);
+ b1 = P1 < P2;
+ b2 = y < -y;
+ CYBOZU_TEST_EQUAL(b1, b2);
+ CYBOZU_TEST_ASSERT(!(P1 < P1));
+ CYBOZU_TEST_ASSERT((P1 <= P1));
+ }
+
+ template<class F>
+ void test(F f, const char *msg) const
+ {
+ const int N = 300000;
+ Fp x(para.gx);
+ Fp y(para.gy);
+ Ec P(x, y);
+ Ec Q = P + P + P;
+ clock_t begin = clock();
+ for (int i = 0; i < N; i++) {
+ f(Q, P, Q);
+ }
+ clock_t end = clock();
+ printf("%s %.2fusec\n", msg, (end - begin) / double(CLOCKS_PER_SEC) / N * 1e6);
+ }
+/*
+Affine : sandy-bridge
+add 3.17usec
+sub 2.43usec
+dbl 3.32usec
+mul 905.00usec
+Jacobi
+add 2.34usec
+sub 2.65usec
+dbl 1.56usec
+mul 499.00usec
+*/
+ void run() const
+ {
+ cstr();
+ ope();
+ mul();
+ neg_mul();
+ mul_fp();
+ squareRoot();
+ str();
+ ioMode();
+ mulCT();
+ compare();
+ }
+private:
+ Test(const Test&);
+ void operator=(const Test&);
+};
+
+void test_sub_sub(const mcl::EcParam& para, mcl::fp::Mode fpMode)
+{
+ puts("Proj");
+ Test(para, fpMode, mcl::ec::Proj).run();
+ puts("Jacobi");
+ Test(para, fpMode, mcl::ec::Jacobi).run();
+}
+
+void test_sub(const mcl::EcParam *para, size_t paraNum)
+{
+ for (size_t i = 0; i < paraNum; i++) {
+ puts(para[i].name);
+ test_sub_sub(para[i], mcl::fp::FP_GMP);
+#ifdef MCL_USE_LLVM
+ test_sub_sub(para[i], mcl::fp::FP_LLVM);
+ test_sub_sub(para[i], mcl::fp::FP_LLVM_MONT);
+#endif
+#ifdef MCL_USE_XBYAK
+ test_sub_sub(para[i], mcl::fp::FP_XBYAK);
+#endif
+ }
+}
+
+int g_partial = -1;
+
+CYBOZU_TEST_AUTO(all)
+{
+ if (g_partial & (1 << 3)) {
+ const struct mcl::EcParam para3[] = {
+ // mcl::ecparam::p160_1,
+ mcl::ecparam::secp160k1,
+ mcl::ecparam::secp192k1,
+ mcl::ecparam::NIST_P192,
+ };
+ test_sub(para3, CYBOZU_NUM_OF_ARRAY(para3));
+ }
+
+ if (g_partial & (1 << 4)) {
+ const struct mcl::EcParam para4[] = {
+ mcl::ecparam::secp224k1,
+ mcl::ecparam::secp256k1,
+ mcl::ecparam::NIST_P224,
+ mcl::ecparam::NIST_P256,
+ };
+ test_sub(para4, CYBOZU_NUM_OF_ARRAY(para4));
+ }
+
+#if MCL_MAX_BIT_SIZE >= 384
+ if (g_partial & (1 << 6)) {
+ const struct mcl::EcParam para6[] = {
+ // mcl::ecparam::secp384r1,
+ mcl::ecparam::NIST_P384,
+ };
+ test_sub(para6, CYBOZU_NUM_OF_ARRAY(para6));
+ }
+#endif
+
+#if MCL_MAX_BIT_SIZE >= 521
+ if (g_partial & (1 << 9)) {
+ const struct mcl::EcParam para9[] = {
+ // mcl::ecparam::secp521r1,
+ mcl::ecparam::NIST_P521,
+ };
+ test_sub(para9, CYBOZU_NUM_OF_ARRAY(para9));
+ }
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc == 1) {
+ g_partial = -1;
+ } else {
+ g_partial = 0;
+ for (int i = 1; i < argc; i++) {
+ g_partial |= 1 << atoi(argv[i]);
+ }
+ }
+ return cybozu::test::autoRun.run(argc, argv);
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/ecdsa_c_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/ecdsa_c_test.cpp
new file mode 100644
index 000000000..e0af38182
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/ecdsa_c_test.cpp
@@ -0,0 +1,51 @@
+#include <mcl/ecdsa.h>
+#include <cybozu/test.hpp>
+#include <string.h>
+
+template<class T, class Serializer, class Deserializer>
+void serializeTest(const T& x, const Serializer& serialize, const Deserializer& deserialize)
+{
+ char buf[128];
+ size_t n = serialize(buf, sizeof(buf), &x);
+ CYBOZU_TEST_ASSERT(n > 0);
+ T y;
+ size_t m = deserialize(&y, buf, n);
+ CYBOZU_TEST_EQUAL(m, n);
+ CYBOZU_TEST_ASSERT(memcmp(&x, &y, n) == 0);
+}
+
+CYBOZU_TEST_AUTO(ecdsa)
+{
+ int ret;
+ ret = ecdsaInit();
+ CYBOZU_TEST_EQUAL(ret, 0);
+ ecdsaSecretKey sec;
+ ecdsaPublicKey pub;
+ ecdsaPrecomputedPublicKey *ppub;
+ ecdsaSignature sig;
+ const char *msg = "hello";
+ mclSize msgSize = strlen(msg);
+
+ ret = ecdsaSecretKeySetByCSPRNG(&sec);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ serializeTest(sec, ecdsaSecretKeySerialize, ecdsaSecretKeyDeserialize);
+
+ ecdsaGetPublicKey(&pub, &sec);
+ serializeTest(pub, ecdsaPublicKeySerialize, ecdsaPublicKeyDeserialize);
+ ecdsaSign(&sig, &sec, msg, msgSize);
+ serializeTest(sig, ecdsaSignatureSerialize, ecdsaSignatureDeserialize);
+ CYBOZU_TEST_ASSERT(ecdsaVerify(&sig, &pub, msg, msgSize));
+
+ ppub = ecdsaPrecomputedPublicKeyCreate();
+ CYBOZU_TEST_ASSERT(ppub);
+ ret = ecdsaPrecomputedPublicKeyInit(ppub, &pub);
+ CYBOZU_TEST_EQUAL(ret, 0);
+
+ CYBOZU_TEST_ASSERT(ecdsaVerifyPrecomputed(&sig, ppub, msg, msgSize));
+
+ sig.d[0]++;
+ CYBOZU_TEST_ASSERT(!ecdsaVerify(&sig, &pub, msg, msgSize));
+ CYBOZU_TEST_ASSERT(!ecdsaVerifyPrecomputed(&sig, ppub, msg, msgSize));
+
+ ecdsaPrecomputedPublicKeyDestroy(ppub);
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/ecdsa_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/ecdsa_test.cpp
new file mode 100644
index 000000000..332c9ee27
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/ecdsa_test.cpp
@@ -0,0 +1,69 @@
+#define PUT(x) std::cout << #x "=" << x << std::endl;
+#include <stdlib.h>
+#include <stdio.h>
+void put(const void *buf, size_t bufSize)
+{
+ const unsigned char* p = (const unsigned char*)buf;
+ for (size_t i = 0; i < bufSize; i++) {
+ printf("%02x", p[i]);
+ }
+ printf("\n");
+}
+#include <mcl/ecdsa.hpp>
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+
+using namespace mcl::ecdsa;
+
+CYBOZU_TEST_AUTO(ecdsa)
+{
+ init();
+ SecretKey sec;
+ PublicKey pub;
+ sec.setByCSPRNG();
+ getPublicKey(pub, sec);
+ Signature sig;
+ const std::string msg = "hello";
+ sign(sig, sec, msg.c_str(), msg.size());
+ CYBOZU_TEST_ASSERT(verify(sig, pub, msg.c_str(), msg.size()));
+ sig.s += 1;
+ CYBOZU_TEST_ASSERT(!verify(sig, pub, msg.c_str(), msg.size()));
+}
+
+CYBOZU_TEST_AUTO(value)
+{
+ const std::string msg = "hello";
+ const char *secStr = "83ecb3984a4f9ff03e84d5f9c0d7f888a81833643047acc58eb6431e01d9bac8";
+ const char *pubxStr = "653bd02ba1367e5d4cd695b6f857d1cd90d4d8d42bc155d85377b7d2d0ed2e71";
+ const char *pubyStr = "04e8f5da403ab78decec1f19e2396739ea544e2b14159beb5091b30b418b813a";
+ const char *sigStr = "a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5de5d79a2ba44e311d04fdca263639283965780bce9169822be9cc81756e95a24";
+
+ SecretKey sec;
+ sec.setStr(secStr, 16);
+ CYBOZU_TEST_EQUAL(sec.getStr(16), secStr);
+ PublicKey pub;
+ getPublicKey(pub, sec);
+ pub.normalize();
+ Ec t(Fp(pubxStr, 16), Fp(pubyStr, 16));
+ CYBOZU_TEST_EQUAL(pub, t);
+ Signature sig;
+ sig.r.setStr(std::string(sigStr, 64), 16);
+ sig.s.setStr(std::string(sigStr + 64, 64), 16);
+ PUT(sig);
+ CYBOZU_TEST_ASSERT(verify(sig, pub, msg.c_str(), msg.size()));
+}
+
+CYBOZU_TEST_AUTO(bench)
+{
+ const std::string msg = "hello";
+ SecretKey sec;
+ PublicKey pub;
+ PrecomputedPublicKey ppub;
+ sec.setByCSPRNG();
+ getPublicKey(pub, sec);
+ ppub.init(pub);
+ Signature sig;
+ CYBOZU_BENCH_C("sign", 1000, sign, sig, sec, msg.c_str(), msg.size());
+ CYBOZU_BENCH_C("pub.verify ", 1000, verify, sig, pub, msg.c_str(), msg.size());
+ CYBOZU_BENCH_C("ppub.verify", 1000, verify, sig, ppub, msg.c_str(), msg.size());
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/elgamal_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/elgamal_test.cpp
new file mode 100644
index 000000000..9532fc597
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/elgamal_test.cpp
@@ -0,0 +1,155 @@
+#include <cybozu/test.hpp>
+#include <cybozu/random_generator.hpp>
+#include <mcl/fp.hpp>
+#include <mcl/ecparam.hpp>
+#include <mcl/elgamal.hpp>
+
+struct TagZn;
+typedef mcl::FpT<> Fp;
+typedef mcl::FpT<TagZn> Zn;
+typedef mcl::EcT<Fp> Ec;
+typedef mcl::ElgamalT<Ec, Zn> ElgamalEc;
+
+const mcl::EcParam& para = mcl::ecparam::secp192k1;
+cybozu::RandomGenerator rg;
+
+CYBOZU_TEST_AUTO(testEc)
+{
+ Fp::init(para.p);
+ Zn::init(para.n);
+ Ec::init(para.a, para.b);
+ const Fp x0(para.gx);
+ const Fp y0(para.gy);
+ const size_t bitSize = Zn::getBitSize();
+ const Ec P(x0, y0);
+ /*
+ Zn = <P>
+ */
+ ElgamalEc::PrivateKey prv;
+ prv.init(P, bitSize, rg);
+ prv.setCache(0, 60000);
+ const ElgamalEc::PublicKey& pub = prv.getPublicKey();
+
+ const int m1 = 12345;
+ const int m2 = 17655;
+ ElgamalEc::CipherText c1, c2;
+ pub.enc(c1, m1, rg);
+ pub.enc(c2, m2, rg);
+ Zn dec1, dec2;
+ prv.dec(dec1, c1);
+ prv.dec(dec2, c2);
+ // dec(enc) = id
+ CYBOZU_TEST_EQUAL(dec1, m1);
+ CYBOZU_TEST_EQUAL(dec2, m2);
+ CYBOZU_TEST_EQUAL(prv.dec(c1), m1);
+ CYBOZU_TEST_EQUAL(prv.dec(c2), m2);
+ // iostream
+ {
+ ElgamalEc::PublicKey pub2;
+ ElgamalEc::PrivateKey prv2;
+ ElgamalEc::CipherText cc1, cc2;
+ {
+ std::stringstream ss;
+ ss << prv;
+ ss >> prv2;
+ }
+ Zn d;
+ prv2.dec(d, c1);
+ CYBOZU_TEST_EQUAL(d, m1);
+ {
+ std::stringstream ss;
+ ss << c1;
+ ss >> cc1;
+ }
+ d = 0;
+ prv2.dec(d, cc1);
+ CYBOZU_TEST_EQUAL(d, m1);
+ {
+ std::stringstream ss;
+ ss << pub;
+ ss >> pub2;
+ }
+ pub2.enc(cc2, m2, rg);
+ prv.dec(d, cc2);
+ CYBOZU_TEST_EQUAL(d, m2);
+ }
+ // enc(m1) enc(m2) = enc(m1 + m2)
+ c1.add(c2);
+ prv.dec(dec1, c1);
+ CYBOZU_TEST_EQUAL(dec1, m1 + m2);
+ // enc(m1) x = enc(m1 + x)
+ {
+ const int x = 555;
+ pub.add(c1, x);
+ prv.dec(dec1, c1);
+ CYBOZU_TEST_EQUAL(dec1, m1 + m2 + x);
+ }
+ // rerandomize
+ c1 = c2;
+ pub.rerandomize(c1, rg);
+ // verify c1 != c2
+ CYBOZU_TEST_ASSERT(c1.c1 != c2.c1);
+ CYBOZU_TEST_ASSERT(c1.c2 != c2.c2);
+ prv.dec(dec1, c1);
+ // dec(c1) = dec(c2)
+ CYBOZU_TEST_EQUAL(dec1, m2);
+
+ // check neg
+ {
+ ElgamalEc::CipherText c;
+ Zn m = 1234;
+ pub.enc(c, m, rg);
+ c.neg();
+ Zn dec;
+ prv.dec(dec, c);
+ CYBOZU_TEST_EQUAL(dec, -m);
+ }
+ // check mul
+ {
+ ElgamalEc::CipherText c;
+ Zn m = 123;
+ int x = 111;
+ pub.enc(c, m, rg);
+ Zn dec;
+ prv.dec(dec, c);
+ c.mul(x);
+ prv.dec(dec, c);
+ m *= x;
+ CYBOZU_TEST_EQUAL(dec, m);
+ }
+
+ // check negative value
+ for (int i = -10; i < 10; i++) {
+ ElgamalEc::CipherText c;
+ const Zn mm = i;
+ pub.enc(c, mm, rg);
+ Zn dec;
+ prv.dec(dec, c, 1000);
+ CYBOZU_TEST_EQUAL(dec, mm);
+ }
+
+ // isZeroMessage
+ for (int m = 0; m < 10; m++) {
+ ElgamalEc::CipherText c0;
+ pub.enc(c0, m, rg);
+ if (m == 0) {
+ CYBOZU_TEST_ASSERT(prv.isZeroMessage(c0));
+ } else {
+ CYBOZU_TEST_ASSERT(!prv.isZeroMessage(c0));
+ }
+ }
+ // zkp
+ {
+ ElgamalEc::Zkp zkp;
+ ElgamalEc::CipherText c;
+ pub.encWithZkp(c, zkp, 0, rg);
+ CYBOZU_TEST_ASSERT(pub.verify(c, zkp));
+ zkp.s0 += 1;
+ CYBOZU_TEST_ASSERT(!pub.verify(c, zkp));
+ pub.encWithZkp(c, zkp, 1, rg);
+ CYBOZU_TEST_ASSERT(pub.verify(c, zkp));
+ zkp.s0 += 1;
+ CYBOZU_TEST_ASSERT(!pub.verify(c, zkp));
+ CYBOZU_TEST_EXCEPTION_MESSAGE(pub.encWithZkp(c, zkp, 2, rg), cybozu::Exception, "encWithZkp");
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/fp_generator_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/fp_generator_test.cpp
new file mode 100644
index 000000000..60ec5cd41
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/fp_generator_test.cpp
@@ -0,0 +1,207 @@
+#include <cybozu/test.hpp>
+#if MCL_SIZEOF_UNIT == 4
+// not support
+#else
+#include <mcl/gmp_util.hpp>
+#include <stdint.h>
+#include <string>
+#include <cybozu/itoa.hpp>
+#include <mcl/fp.hpp>
+#include "../src/fp_generator.hpp"
+#include <iostream>
+#include <cybozu/xorshift.hpp>
+#include <cybozu/benchmark.hpp>
+
+typedef mcl::FpT<> Fp;
+
+const int MAX_N = 4;
+
+const char *primeTable[] = {
+ "0x7fffffffffffffffffffffffffffffff", // 127bit(not full)
+ "0xffffffffffffffffffffffffffffff61", // 128bit(full)
+ "0xfffffffffffffffffffffffffffffffffffffffeffffee37", // 192bit(full)
+ "0x2523648240000001ba344d80000000086121000000000013a700000000000013", // 254bit(not full)
+};
+
+void strToArray(uint64_t *p, size_t n, const char *pStr)
+{
+ mpz_class x;
+ mcl::gmp::setStr(x, pStr, 16);
+ mcl::gmp::getArray(p, n, x);
+}
+
+struct Int {
+ int vn;
+ uint64_t v[MAX_N];
+ Int()
+ : vn(0)
+ {
+ }
+ explicit Int(int vn)
+ {
+ if (vn > MAX_N) {
+ printf("vn(%d) is too large\n", vn);
+ exit(1);
+ }
+ this->vn = vn;
+ }
+ void set(const char *str) { setStr(str); }
+ void set(const Fp& rhs)
+ {
+ mcl::gmp::getArray(v, MAX_N, rhs.getMpz());
+ }
+ void set(const uint64_t* x)
+ {
+ for (int i = 0; i < vn; i++) v[i] = x[i];
+ }
+ void setStr(const char *str)
+ {
+ strToArray(v, MAX_N, str);
+ }
+ std::string getStr() const
+ {
+ std::string ret;
+ for (int i = 0; i < vn; i++) {
+ ret += cybozu::itohex(v[vn - 1 - i], false);
+ }
+ return ret;
+ }
+ void put(const char *msg = "") const
+ {
+ if (msg) printf("%s=", msg);
+ printf("%s\n", getStr().c_str());
+ }
+ bool operator==(const Int& rhs) const
+ {
+ if (vn != rhs.vn) return false;
+ for (int i = 0; i < vn; i++) {
+ if (v[i] != rhs.v[i]) return false;
+ }
+ return true;
+ }
+ bool operator!=(const Int& rhs) const { return !operator==(rhs); }
+ bool operator==(const Fp& rhs) const
+ {
+ Int t(vn);
+ t.set(rhs);
+ return operator==(t);
+ }
+ bool operator!=(const Fp& rhs) const { return !operator==(rhs); }
+};
+static inline std::ostream& operator<<(std::ostream& os, const Int& x)
+{
+ return os << x.getStr();
+}
+
+void testAddSub(const mcl::fp::Op& op)
+{
+ Fp x, y;
+ const uint64_t *p = op.p;
+ Int mx(op.N), my(op.N);
+ x.setStr("0x8811aabb23427cc");
+ y.setStr("0x8811aabb23427cc11");
+ mx.set(x);
+ my.set(y);
+ for (int i = 0; i < 30; i++) {
+ CYBOZU_TEST_EQUAL(mx, x);
+ x += x;
+ op.fp_add(mx.v, mx.v, mx.v, p);
+ }
+ for (int i = 0; i < 30; i++) {
+ CYBOZU_TEST_EQUAL(mx, x);
+ x += y;
+ op.fp_add(mx.v, mx.v, my.v, p);
+ }
+ for (int i = 0; i < 30; i++) {
+ CYBOZU_TEST_EQUAL(my, y);
+ y -= x;
+ op.fp_sub(my.v, my.v, mx.v, p);
+ }
+}
+
+void testNeg(const mcl::fp::Op& op)
+{
+ Fp x;
+ Int mx(op.N), my(op.N);
+ const char *tbl[] = {
+ "0",
+ "0x12346",
+ "0x11223344556677881122334455667788",
+ "0x0abbccddeeffaabb0000000000000000",
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ x.setStr(tbl[i]);
+ mx.set(x);
+ x = -x;
+ op.fp_neg(mx.v, mx.v, op.p);
+ CYBOZU_TEST_EQUAL(mx, x);
+ }
+}
+
+#if 0
+void testMulI(const mcl::fp::FpGenerator& fg, int pn)
+{
+ cybozu::XorShift rg;
+//printf("pn=%d, %p\n", pn, fg.mulUnit_);
+ for (int i = 0; i < 100; i++) {
+ uint64_t x[MAX_N];
+ uint64_t z[MAX_N + 1];
+ rg.read(x, pn);
+ uint64_t y = rg.get64();
+ mpz_class mx;
+ mcl::gmp::setArray(mx, x, pn);
+ mpz_class my;
+ mcl::gmp::set(my, y);
+ mx *= my;
+ uint64_t d = fg.mulUnit_(z, x, y);
+ z[pn] = d;
+ mcl::gmp::setArray(my, z, pn + 1);
+ CYBOZU_TEST_EQUAL(mx, my);
+ }
+ {
+ uint64_t x[MAX_N];
+ uint64_t z[MAX_N + 1];
+ rg.read(x, pn);
+ uint64_t y = rg.get64();
+ CYBOZU_BENCH_C("mulUnit", 10000000, fg.mulUnit_, z, x, y);
+ }
+}
+#endif
+
+void testShr1(const mcl::fp::Op& op, int pn)
+{
+ cybozu::XorShift rg;
+ for (int i = 0; i < 100; i++) {
+ uint64_t x[MAX_N];
+ uint64_t z[MAX_N];
+ rg.read(x, pn);
+ mpz_class mx;
+ mcl::gmp::setArray(mx, x, pn);
+ mx >>= 1;
+ op.fp_shr1(z, x);
+ mpz_class my;
+ mcl::gmp::setArray(my, z, pn);
+ CYBOZU_TEST_EQUAL(mx, my);
+ }
+}
+
+void test(const char *pStr)
+{
+ printf("test %s\n", pStr);
+ Fp::init(pStr, mcl::fp::FP_XBYAK);
+ const mcl::fp::Op& op = Fp::getOp();
+ const int pn = (int)op.N;
+ testAddSub(op);
+ testNeg(op);
+// testMulI(*op.fg, pn);
+ testShr1(op, pn);
+}
+
+CYBOZU_TEST_AUTO(all)
+{
+ if (!mcl::fp::isEnableJIT()) return;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(primeTable); i++) {
+ test(primeTable[i]);
+ }
+}
+#endif
diff --git a/vendor/github.com/dexon-foundation/mcl/test/fp_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/fp_test.cpp
new file mode 100644
index 000000000..dc1b01ef4
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/fp_test.cpp
@@ -0,0 +1,1046 @@
+#define PUT(x) std::cout << #x "=" << (x) << std::endl
+#define CYBOZU_TEST_DISABLE_AUTO_RUN
+#include <cybozu/test.hpp>
+#include <mcl/fp.hpp>
+#include "../src/low_func.hpp"
+#include "../src/proto.hpp"
+#include <time.h>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/option.hpp>
+#include <cybozu/sha2.hpp>
+
+#ifdef _MSC_VER
+ #pragma warning(disable: 4127) // const condition
+#endif
+
+typedef mcl::FpT<> Fp;
+
+CYBOZU_TEST_AUTO(sizeof)
+{
+ CYBOZU_TEST_EQUAL(sizeof(Fp), sizeof(mcl::fp::Unit) * Fp::maxSize);
+}
+
+void cstrTest()
+{
+ const struct {
+ const char *str;
+ int val;
+ } tbl[] = {
+ { "0", 0 },
+ { "1", 1 },
+ { "123", 123 },
+ { "0x123", 0x123 },
+ { "0b10101", 21 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ // string cstr
+ Fp x(tbl[i].str);
+ CYBOZU_TEST_EQUAL(x, tbl[i].val);
+
+ // int cstr
+ Fp y(tbl[i].val);
+ CYBOZU_TEST_EQUAL(y, x);
+
+ // copy cstr
+ Fp z(x);
+ CYBOZU_TEST_EQUAL(z, x);
+
+ // assign int
+ Fp w;
+ w = tbl[i].val;
+ CYBOZU_TEST_EQUAL(w, x);
+
+ // assign self
+ Fp u;
+ u = w;
+ CYBOZU_TEST_EQUAL(u, x);
+
+ // conv
+ std::ostringstream os;
+ os << tbl[i].val;
+
+ std::string str;
+ x.getStr(str);
+ CYBOZU_TEST_EQUAL(str, os.str());
+ }
+ const struct {
+ const char *str;
+ int val;
+ } tbl2[] = {
+ { "-123", 123 },
+ { "-0x123", 0x123 },
+ { "-0b10101", 21 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl2); i++) {
+ Fp x(tbl2[i].str);
+ x = -x;
+ CYBOZU_TEST_EQUAL(x, tbl2[i].val);
+ }
+}
+
+void setStrTest()
+{
+ const struct {
+ const char *in;
+ int out;
+ int base;
+ } tbl[] = {
+ { "100", 100, 0 }, // set base = 10 if base = 0
+ { "100", 4, 2 },
+ { "100", 256, 16 },
+ { "0b100", 4, 0 },
+ { "0b100", 4, 2 },
+ { "0x100", 256, 0 },
+ { "0x100", 256, 16 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Fp x;
+ x.setStr(tbl[i].in, tbl[i].base);
+ CYBOZU_TEST_EQUAL(x, tbl[i].out);
+ }
+ // use prefix if base conflicts with prefix
+ {
+ Fp x;
+ CYBOZU_TEST_EXCEPTION(x.setStr("0b100", 16), cybozu::Exception);
+ CYBOZU_TEST_EXCEPTION(x.setStr("0b100", 10), cybozu::Exception);
+ CYBOZU_TEST_EXCEPTION(x.setStr("0x100", 2), cybozu::Exception);
+ CYBOZU_TEST_EXCEPTION(x.setStr("0x100", 10), cybozu::Exception);
+ }
+}
+
+void streamTest()
+{
+ const struct {
+ const char *in;
+ int out10;
+ int out16;
+ } tbl[] = {
+ { "100", 100, 256 }, // set base = 10 if base = 0
+ { "0x100", 256, 256 },
+ };
+ Fp::setIoMode(0);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ {
+ std::istringstream is(tbl[i].in);
+ Fp x;
+ is >> x;
+ CYBOZU_TEST_EQUAL(x, tbl[i].out10);
+ }
+ {
+ std::istringstream is(tbl[i].in);
+ Fp x;
+ is >> std::hex >> x;
+ CYBOZU_TEST_EQUAL(x, tbl[i].out16);
+ }
+ }
+ // use prefix if base conflicts with prefix
+ std::istringstream is("0b100");
+ Fp x;
+ CYBOZU_TEST_EXCEPTION(is >> std::hex >> x, cybozu::Exception);
+ {
+ std::ostringstream os;
+ os << Fp(123);
+ CYBOZU_TEST_EQUAL(os.str(), "123");
+ }
+ {
+ std::ostringstream os;
+ os << std::hex << Fp(0x123);
+ CYBOZU_TEST_EQUAL(os.str(), "123");
+ }
+ {
+ std::ostringstream os;
+ os << std::hex << std::showbase << Fp(0x123);
+ CYBOZU_TEST_EQUAL(os.str(), "0x123");
+ }
+}
+
+void ioModeTest()
+{
+ Fp x(123);
+ const struct {
+ mcl::IoMode ioMode;
+ std::string expected;
+ } tbl[] = {
+ { mcl::IoBin, "1111011" },
+ { mcl::IoDec, "123" },
+ { mcl::IoHex, "7b" },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Fp::setIoMode(tbl[i].ioMode);
+ for (int j = 0; j < 2; j++) {
+ std::stringstream ss;
+ if (j == 1) {
+ ss << std::hex;
+ }
+ ss << x;
+ CYBOZU_TEST_EQUAL(ss.str(), tbl[i].expected);
+ Fp y;
+ y.clear();
+ ss >> y;
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+ }
+ for (int i = 0; i < 2; i++) {
+ if (i == 0) {
+ Fp::setIoMode(mcl::IoArray);
+ } else {
+ Fp::setIoMode(mcl::IoArrayRaw);
+ }
+ std::stringstream ss;
+ ss << x;
+ CYBOZU_TEST_EQUAL(ss.str().size(), Fp::getByteSize());
+ Fp y;
+ ss >> y;
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+ Fp::setIoMode(mcl::IoAuto);
+}
+
+void edgeTest()
+{
+ const mpz_class& m = Fp::getOp().mp;
+ /*
+ real mont
+ 0 0
+ 1 R^-1
+ R 1
+ -1 -R^-1
+ -R -1
+ */
+ mpz_class t = 1;
+ const size_t N = Fp::getUnitSize();
+ const mpz_class R = (t << (N * mcl::fp::UnitBitSize)) % m;
+ const mpz_class tbl[] = {
+ 0, 1, R, m - 1, m - R
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const mpz_class& x = tbl[i];
+ for (size_t j = i; j < CYBOZU_NUM_OF_ARRAY(tbl); j++) {
+ const mpz_class& y = tbl[j];
+ mpz_class z = (x * y) % m;
+ Fp xx, yy;
+ xx.setMpz(x);
+ yy.setMpz(y);
+ Fp zz = xx * yy;
+ zz.getMpz(t);
+ CYBOZU_TEST_EQUAL(z, t);
+ }
+ }
+ t = m;
+ t /= 2;
+ Fp x;
+ x.setMpz(t);
+ CYBOZU_TEST_EQUAL(x * 2, -1);
+ t += 1;
+ x.setMpz(t);
+ CYBOZU_TEST_EQUAL(x * 2, 1);
+}
+
+void convTest()
+{
+#if 1
+ const char *bin, *hex, *dec;
+ if (Fp::getBitSize() <= 117) {
+ bin = "0b1000000000000000000000000000000000000000000000000000000000001110";
+ hex = "0x800000000000000e";
+ dec = "9223372036854775822";
+ } else {
+ bin = "0b100100011010001010110011110001001000000010010001101000101011001111000100100000001001000110100010101100111100010010000";
+ hex = "0x123456789012345678901234567890";
+ dec = "94522879687365475552814062743484560";
+ }
+#else
+ const char *bin = "0b1001000110100";
+ const char *hex = "0x1234";
+ const char *dec = "4660";
+#endif
+ Fp b(bin);
+ Fp h(hex);
+ Fp d(dec);
+ CYBOZU_TEST_EQUAL(b, h);
+ CYBOZU_TEST_EQUAL(b, d);
+
+ std::string str;
+ b.getStr(str, mcl::IoBinPrefix);
+ CYBOZU_TEST_EQUAL(str, bin);
+ b.getStr(str);
+ CYBOZU_TEST_EQUAL(str, dec);
+ b.getStr(str, mcl::IoHexPrefix);
+ CYBOZU_TEST_EQUAL(str, hex);
+}
+
+void compareTest()
+{
+ {
+ const struct {
+ int lhs;
+ int rhs;
+ int cmp;
+ } tbl[] = {
+ { 0, 0, 0 },
+ { 1, 0, 1 },
+ { 0, 1, -1 },
+ { -1, 0, 1 }, // m-1, 0
+ { 0, -1, -1 }, // 0, m-1
+ { 123, 456, -1 },
+ { 456, 123, 1 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const Fp x(tbl[i].lhs);
+ const Fp y(tbl[i].rhs);
+ const int cmp = tbl[i].cmp;
+ if (cmp == 0) {
+ CYBOZU_TEST_EQUAL(x, y);
+ CYBOZU_TEST_ASSERT(x >= y);
+ CYBOZU_TEST_ASSERT(x <= y);
+ } else if (cmp > 0) {
+ CYBOZU_TEST_ASSERT(x > y);
+ CYBOZU_TEST_ASSERT(x >= y);
+ } else {
+ CYBOZU_TEST_ASSERT(x < y);
+ CYBOZU_TEST_ASSERT(x <= y);
+ }
+ }
+ }
+ {
+ Fp x(5);
+ CYBOZU_TEST_ASSERT(x < 10);
+ CYBOZU_TEST_ASSERT(x == 5);
+ CYBOZU_TEST_ASSERT(x > 2);
+ }
+ {
+ Fp x(1);
+ CYBOZU_TEST_ASSERT(x.isOne());
+ x = 2;
+ CYBOZU_TEST_ASSERT(!x.isOne());
+ }
+ {
+ const struct {
+ int v;
+ bool expected;
+ } tbl[] = {
+ { 0, false },
+ { 1, false },
+ { -1, true },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Fp x = tbl[i].v;
+ CYBOZU_TEST_EQUAL(x.isNegative(), tbl[i].expected);
+ }
+ std::string str;
+ Fp::getModulo(str);
+ char buf[1024];
+ size_t n = Fp::getModulo(buf, sizeof(buf));
+ CYBOZU_TEST_EQUAL(n, str.size());
+ CYBOZU_TEST_EQUAL(buf, str.c_str());
+ mpz_class half(str);
+ half = (half - 1) / 2;
+ Fp x;
+ x.setMpz(half - 1);
+ CYBOZU_TEST_ASSERT(!x.isNegative());
+ x.setMpz(half);
+ CYBOZU_TEST_ASSERT(!x.isNegative());
+ x.setMpz(half + 1);
+ CYBOZU_TEST_ASSERT(x.isNegative());
+ }
+}
+
+void moduloTest(const char *pStr)
+{
+ std::string str;
+ Fp::getModulo(str);
+ CYBOZU_TEST_EQUAL(str, mcl::gmp::getStr(mpz_class(pStr)));
+}
+
+void opeTest()
+{
+ const struct {
+ int x;
+ int y;
+ int add; // x + y
+ int sub; // x - y
+ int mul; // x * y
+ int sqr; // x^2
+ } tbl[] = {
+ { 0, 1, 1, -1, 0, 0 },
+ { 9, 5, 14, 4, 45, 81 },
+ { 10, 13, 23, -3, 130, 100 },
+ { 2000, 1000, 3000, 1000, 2000 * 1000, 2000 * 2000 },
+ { 12345, 9999, 12345 + 9999, 12345 - 9999, 12345 * 9999, 12345 * 12345 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const Fp x(tbl[i].x);
+ const Fp y(tbl[i].y);
+ Fp z;
+ Fp::add(z, x, y);
+ CYBOZU_TEST_EQUAL(z, tbl[i].add);
+ Fp::sub(z, x, y);
+ CYBOZU_TEST_EQUAL(z, tbl[i].sub);
+ Fp::mul(z, x, y);
+ CYBOZU_TEST_EQUAL(z, tbl[i].mul);
+
+ Fp r;
+ Fp::inv(r, y);
+ Fp::mul(z, z, r);
+ CYBOZU_TEST_EQUAL(z, tbl[i].x);
+ z = x + y;
+ CYBOZU_TEST_EQUAL(z, tbl[i].add);
+ z = x - y;
+ CYBOZU_TEST_EQUAL(z, tbl[i].sub);
+ z = x * y;
+ CYBOZU_TEST_EQUAL(z, tbl[i].mul);
+
+ Fp::sqr(z, x);
+ CYBOZU_TEST_EQUAL(z, tbl[i].sqr);
+
+ z = x / y;
+ z *= y;
+ CYBOZU_TEST_EQUAL(z, tbl[i].x);
+ }
+ if (!Fp::isFullBit()) {
+ Fp x(5), y(3), z;
+ Fp::addPre(z, x, y);
+ if (Fp::compareRaw(z, Fp::getP()) >= 0) {
+ Fp::subPre(z, z, Fp::getP());
+ }
+ CYBOZU_TEST_EQUAL(z, Fp(8));
+ if (Fp::compareRaw(x, y) < 0) {
+ Fp::addPre(x, x, Fp::getP());
+ }
+ Fp::subPre(x, x, y);
+ CYBOZU_TEST_EQUAL(x, Fp(2));
+ }
+}
+
+struct tag2;
+
+void powTest()
+{
+ Fp x, y, z;
+ x = 12345;
+ z = 1;
+ for (int i = 0; i < 100; i++) {
+ Fp::pow(y, x, i);
+ CYBOZU_TEST_EQUAL(y, z);
+ z *= x;
+ }
+ x = z;
+ Fp::pow(z, x, Fp::getOp().mp - 1);
+ CYBOZU_TEST_EQUAL(z, 1);
+ Fp::pow(z, x, Fp::getOp().mp);
+ CYBOZU_TEST_EQUAL(z, x);
+ typedef mcl::FpT<tag2, 128> Fp_other;
+ Fp_other::init("1009");
+ x = 5;
+ Fp_other n = 3;
+ z = 3;
+ Fp::pow(x, x, z);
+ CYBOZU_TEST_EQUAL(x, 125);
+ x = 5;
+ Fp::pow(x, x, n);
+ CYBOZU_TEST_EQUAL(x, 125);
+}
+
+void mulUnitTest()
+{
+ Fp x(-1), y, z;
+ for (unsigned int u = 0; u < 20; u++) {
+ Fp::mul(y, x, u);
+ Fp::mulUnit(z, x, u);
+ CYBOZU_TEST_EQUAL(y, z);
+ }
+}
+
+void powNegTest()
+{
+ Fp x, y, z;
+ x = 12345;
+ z = 1;
+ Fp rx = 1 / x;
+ for (int i = 0; i < 100; i++) {
+ Fp::pow(y, x, -i);
+ CYBOZU_TEST_EQUAL(y, z);
+ z *= rx;
+ }
+}
+
+void powFpTest()
+{
+ Fp x, y, z;
+ x = 12345;
+ z = 1;
+ for (int i = 0; i < 100; i++) {
+ Fp::pow(y, x, Fp(i));
+ CYBOZU_TEST_EQUAL(y, z);
+ z *= x;
+ }
+}
+
+void powGmp()
+{
+ Fp x, y, z;
+ x = 12345;
+ z = 1;
+ for (int i = 0; i < 100; i++) {
+ Fp::pow(y, x, mpz_class(i));
+ CYBOZU_TEST_EQUAL(y, z);
+ z *= x;
+ }
+}
+
+struct TagAnother;
+
+void anotherFpTest(mcl::fp::Mode mode)
+{
+ typedef mcl::FpT<TagAnother, 128> G;
+ G::init("13", mode);
+ G a = 3;
+ G b = 9;
+ a *= b;
+ CYBOZU_TEST_EQUAL(a, 1);
+}
+
+void setArrayTest1()
+{
+ char b1[] = { 0x56, 0x34, 0x12 };
+ Fp x;
+ x.setArray(b1, 3);
+ CYBOZU_TEST_EQUAL(x, 0x123456);
+ int b2[] = { 0x12, 0x34 };
+ x.setArray(b2, 2);
+ CYBOZU_TEST_EQUAL(x, Fp("0x3400000012"));
+}
+
+void setArrayTest2(mcl::fp::Mode mode)
+{
+ Fp::init("0x10000000000001234567a5", mode);
+ const struct {
+ uint32_t buf[3];
+ size_t bufN;
+ const char *expected;
+ } tbl[] = {
+ { { 0x234567a4, 0x00000001, 0x00100000}, 1, "0x234567a4" },
+ { { 0x234567a4, 0x00000001, 0x00100000}, 2, "0x1234567a4" },
+ { { 0x234567a4, 0x00000001, 0x00080000}, 3, "0x08000000000001234567a4" },
+ { { 0x234567a4, 0x00000001, 0x00100000}, 3, "0x10000000000001234567a4" },
+ };
+ Fp x;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ x.setArray(tbl[i].buf, tbl[i].bufN);
+ CYBOZU_TEST_EQUAL(x, Fp(tbl[i].expected));
+ }
+ uint32_t large[3] = { 0x234567a5, 0x00000001, 0x00100000};
+ CYBOZU_TEST_EXCEPTION(x.setArray(large, 3), cybozu::Exception);
+}
+
+void setArrayMaskTest1()
+{
+ char b1[] = { 0x56, 0x34, 0x12 };
+ Fp x;
+ x.setArrayMask(b1, 3);
+ CYBOZU_TEST_EQUAL(x, 0x123456);
+ int b2[] = { 0x12, 0x34 };
+ x.setArrayMask(b2, 2);
+ CYBOZU_TEST_EQUAL(x, Fp("0x3400000012"));
+}
+
+void setArrayMaskTest2(mcl::fp::Mode mode)
+{
+ Fp::init("0x10000000000001234567a5", mode);
+ const struct {
+ uint32_t buf[3];
+ size_t bufN;
+ const char *expected;
+ } tbl[] = {
+ { { 0x234567a4, 0x00000001, 0x00100000}, 1, "0x234567a4" },
+ { { 0x234567a4, 0x00000001, 0x00100000}, 2, "0x1234567a4" },
+ { { 0x234567a4, 0x00000001, 0x00100000}, 3, "0x10000000000001234567a4" },
+ { { 0x234567a5, 0xfffffff1, 0xffffffff}, 3, "0x0ffffffffffff1234567a5" },
+ };
+ Fp x;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ x.setArrayMask(tbl[i].buf, tbl[i].bufN);
+ CYBOZU_TEST_EQUAL(x, Fp(tbl[i].expected));
+ }
+}
+
+void setArrayModTest()
+{
+ const mpz_class& p = Fp::getOp().mp;
+ const mpz_class tbl[] = {
+ 0,
+ 1,
+ p - 1,
+ p,
+ p + 1,
+ p * 2 - 1,
+ p * 2,
+ p * 2 + 1,
+ p * (p - 1) - 1,
+ p * (p - 1),
+ p * (p - 1) + 1,
+ p * p - 1,
+ p * p,
+ p * p + 1,
+ (mpz_class(1) << Fp::getOp().N * mcl::fp::UnitBitSize * 2) - 1,
+ };
+ const size_t unitByteSize = sizeof(mcl::fp::Unit);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const mpz_class& x = tbl[i];
+ const mcl::fp::Unit *px = mcl::gmp::getUnit(x);
+ const size_t xn = mcl::gmp::getUnitSize(x);
+ const size_t xByteSize = xn * unitByteSize;
+ const size_t fpByteSize = unitByteSize * Fp::getOp().N;
+ Fp y;
+ bool b;
+ y.setArray(&b, px, xn, mcl::fp::Mod);
+ bool expected = xByteSize <= fpByteSize * 2;
+ CYBOZU_TEST_EQUAL(b, expected);
+ if (!b) continue;
+ CYBOZU_TEST_EQUAL(y.getMpz(), x % p);
+ }
+}
+
+CYBOZU_TEST_AUTO(set64bit)
+{
+ Fp::init("0x1000000000000000000f");
+ const struct {
+ const char *p;
+ int64_t i;
+ } tbl[] = {
+ { "0x1234567812345678", int64_t(0x1234567812345678ull) },
+ { "0xfffedcba987edcba997", -int64_t(0x1234567812345678ull) },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Fp x(tbl[i].p);
+ Fp y(tbl[i].i);
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+}
+
+void getUint64Test()
+{
+ const uint64_t tbl[] = {
+ 0, 1, 123, 0xffffffff, int64_t(0x7fffffffffffffffull)
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ uint64_t a = tbl[i];
+ Fp x(a);
+ uint64_t b = x.getUint64();
+ CYBOZU_TEST_ASSERT(!x.isNegative());
+ CYBOZU_TEST_EQUAL(a, b);
+ }
+ {
+ Fp x("0xffffffffffffffff");
+ CYBOZU_TEST_EQUAL(x.getUint64(), uint64_t(0xffffffffffffffffull));
+ }
+ {
+ Fp x("0x10000000000000000");
+ CYBOZU_TEST_EXCEPTION(x.getUint64(), cybozu::Exception);
+ x = -1;
+ CYBOZU_TEST_EXCEPTION(x.getUint64(), cybozu::Exception);
+ }
+ {
+ Fp x("0x10000000000000000");
+ bool b = true;
+ CYBOZU_TEST_EQUAL(x.getUint64(&b), 0u);
+ CYBOZU_TEST_ASSERT(!b);
+ }
+}
+
+void getInt64Test()
+{
+ const int64_t tbl[] = {
+ 0, 1, 123, 0xffffffff, int64_t(0x7fffffffffffffffull),
+ -1, -2, -12345678, int64_t(-9223372036854775808ull)/*-int64_t(1) << 63*/,
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ int64_t a = tbl[i];
+ Fp x(a);
+ CYBOZU_TEST_EQUAL(x.isNegative(), a < 0);
+ int64_t b = x.getInt64();
+ CYBOZU_TEST_EQUAL(a, b);
+ }
+ {
+ Fp x("0x8000000000000000");
+ CYBOZU_TEST_EXCEPTION(x.getInt64(), cybozu::Exception);
+ }
+ {
+ Fp x("0x8000000000000000");
+ bool b = true;
+ CYBOZU_TEST_EQUAL(x.getInt64(&b), 0u);
+ CYBOZU_TEST_ASSERT(!b);
+ }
+}
+
+void divBy2Test()
+{
+ const int tbl[] = { -4, -3, -2, -1, 0, 1, 2, 3 };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Fp x(tbl[i]), y;
+ Fp::divBy2(y, x);
+ y *= 2;
+ CYBOZU_TEST_EQUAL(y, x);
+ y = x;
+ Fp::divBy2(y, y);
+ y *= 2;
+ CYBOZU_TEST_EQUAL(y, x);
+ }
+}
+
+void getStrTest()
+{
+ Fp x(0);
+ std::string str;
+ str = x.getStr();
+ CYBOZU_TEST_EQUAL(str, "0");
+ str = x.getStr(mcl::IoBinPrefix);
+ CYBOZU_TEST_EQUAL(str, "0b0");
+ str = x.getStr(mcl::IoBin);
+ CYBOZU_TEST_EQUAL(str, "0");
+ str = x.getStr(mcl::IoHexPrefix);
+ CYBOZU_TEST_EQUAL(str, "0x0");
+ str = x.getStr(mcl::IoHex);
+ CYBOZU_TEST_EQUAL(str, "0");
+
+ x = 123;
+ str = x.getStr();
+ CYBOZU_TEST_EQUAL(str, "123");
+ str = x.getStr(mcl::IoBinPrefix);
+ CYBOZU_TEST_EQUAL(str, "0b1111011");
+ str = x.getStr(mcl::IoBin);
+ CYBOZU_TEST_EQUAL(str, "1111011");
+ str = x.getStr(mcl::IoHexPrefix);
+ CYBOZU_TEST_EQUAL(str, "0x7b");
+ str = x.getStr(mcl::IoHex);
+ CYBOZU_TEST_EQUAL(str, "7b");
+
+ {
+ std::ostringstream os;
+ os << x;
+ CYBOZU_TEST_EQUAL(os.str(), "123");
+ }
+ {
+ std::ostringstream os;
+ os << std::hex << std::showbase << x;
+ CYBOZU_TEST_EQUAL(os.str(), "0x7b");
+ }
+ {
+ std::ostringstream os;
+ os << std::hex << x;
+ CYBOZU_TEST_EQUAL(os.str(), "7b");
+ }
+ const char *tbl[] = {
+ "0x0",
+ "0x5",
+ "0x123",
+ "0x123456789012345679adbc",
+ "0xffffffff26f2fc170f69466a74defd8d",
+ "0x100000000000000000000000000000033",
+ "0x11ee12312312940000000000000000000000000002342343"
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const char *s = tbl[i];
+ mpz_class mx(s);
+ if (mx >= Fp::getOp().mp) continue;
+ Fp y(s);
+ std::string xs, ys;
+ mcl::gmp::getStr(xs, mx, 16);
+ y.getStr(ys, 16);
+ CYBOZU_TEST_EQUAL(xs, ys);
+ }
+}
+
+void setHashOfTest()
+{
+ const std::string msgTbl[] = {
+ "", "abc", "111111111111111111111111111111111111",
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(msgTbl); i++) {
+ size_t bitSize = Fp::getBitSize();
+ std::string digest;
+ if (bitSize <= 256) {
+ digest = cybozu::Sha256().digest(msgTbl[i]);
+ } else {
+ digest = cybozu::Sha512().digest(msgTbl[i]);
+ }
+ Fp x, y;
+ x.setArrayMask(digest.c_str(), digest.size());
+ y.setHashOf(msgTbl[i]);
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+}
+
+CYBOZU_TEST_AUTO(getArray)
+{
+ const struct {
+ const char *s;
+ uint32_t v[4];
+ size_t vn;
+ } tbl[] = {
+ { "0", { 0, 0, 0, 0 }, 1 },
+ { "1234", { 1234, 0, 0, 0 }, 1 },
+ { "0xaabbccdd12345678", { 0x12345678, 0xaabbccdd, 0, 0 }, 2 },
+ { "0x11112222333344445555666677778888", { 0x77778888, 0x55556666, 0x33334444, 0x11112222 }, 4 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ mpz_class x(tbl[i].s);
+ const size_t bufN = 8;
+ uint32_t buf[bufN];
+ mcl::gmp::getArray(buf, bufN, x);
+ size_t n = mcl::fp::getNonZeroArraySize(buf, bufN);
+ CYBOZU_TEST_EQUAL(n, tbl[i].vn);
+ CYBOZU_TEST_EQUAL_ARRAY(buf, tbl[i].v, n);
+ }
+}
+
+void serializeTest()
+{
+ const char *tbl[] = { "0", "-1", "123" };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ char buf[1024];
+ Fp x, y;
+ x.setStr(tbl[i]);
+ size_t n = x.serialize(buf, sizeof(buf));
+ CYBOZU_TEST_EQUAL(n, Fp::getByteSize());
+ y.deserialize(buf, n);
+ CYBOZU_TEST_EQUAL(x, y);
+
+ n = x.serialize(buf, sizeof(buf), mcl::IoSerializeHexStr);
+ CYBOZU_TEST_EQUAL(n, Fp::getByteSize() * 2);
+ y.deserialize(buf, n, mcl::IoSerializeHexStr);
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+}
+
+void modpTest()
+{
+ const mpz_class& p = Fp::getOp().mp;
+ const mpz_class tbl[] = {
+ 0,
+ 1,
+ p - 1,
+ p,
+ p + 1,
+ p * 2 - 1,
+ p * 2,
+ p * 2 + 1,
+ p * (p - 1) - 1,
+ p * (p - 1),
+ p * (p - 1) + 1,
+ p * p - 1,
+ p * p,
+ p * p + 1,
+ (mpz_class(1) << Fp::getOp().N * mcl::fp::UnitBitSize * 2) - 1,
+ };
+ mcl::Modp modp;
+ modp.init(p);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const mpz_class& x = tbl[i];
+ mpz_class r1, r2;
+ r1 = x % p;
+ modp.modp(r2, x);
+ CYBOZU_TEST_EQUAL(r1, r2);
+ }
+}
+
+#include <iostream>
+#if (defined(MCL_USE_LLVM) || defined(MCL_USE_XBYAK)) && (MCL_MAX_BIT_SIZE >= 521)
+CYBOZU_TEST_AUTO(mod_NIST_P521)
+{
+ const size_t len = 521;
+ const size_t N = len / mcl::fp::UnitBitSize;
+ const char *tbl[] = {
+ "0",
+ "0xffffffff",
+ "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0",
+ "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
+ "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0x20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00111423424",
+ "0x11111111111111112222222222222222333333333333333344444444444444445555555555555555666666666666666677777777777777778888888888888888aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccddddddddddddddddeeeeeeeeeeeeeeeeffffffffffffffff1234712341234123412341234123412341234",
+ "0x3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ };
+ const char *p = "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
+ Fp::init(p, mcl::fp::FP_XBYAK);
+ const mpz_class mp(p);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ mpz_class mx(tbl[i]);
+ mcl::fp::Unit in[N * 2 + 1] = {};
+ mcl::fp::Unit ok[N + 1];
+ mcl::fp::Unit ex[N + 1];
+ mcl::gmp::getArray(in, N * 2 + 1, mx);
+ mpz_class my = mx % mp;
+ mcl::gmp::getArray(ok, N + 1, my);
+#ifdef MCL_USE_LLVM
+ mcl_fpDbl_mod_NIST_P521L(ex, in, Fp::getOp().p);
+ CYBOZU_TEST_EQUAL_ARRAY(ex, ok, N + 1);
+#endif
+#ifdef MCL_USE_XBYAK
+ const mcl::fp::Op& op = Fp::getOp();
+ if (!op.isMont) {
+ op.fpDbl_mod(ex, in, op.p);
+ CYBOZU_TEST_EQUAL_ARRAY(ex, ok, N + 1);
+ }
+#endif
+ }
+}
+#endif
+
+void sub(mcl::fp::Mode mode)
+{
+ printf("mode=%s\n", mcl::fp::ModeToStr(mode));
+ const char *tbl[] = {
+ // N = 2
+ "0x0000000000000001000000000000000d",
+ "0x7fffffffffffffffffffffffffffffff",
+ "0x8000000000000000000000000000001d",
+ "0xffffffffffffffffffffffffffffff61",
+
+ // N = 3
+ "0x000000000000000100000000000000000000000000000033", // min prime
+ "0x00000000fffffffffffffffffffffffffffffffeffffac73",
+ "0x0000000100000000000000000001b8fa16dfab9aca16b6b3",
+ "0x000000010000000000000000000000000000000000000007",
+ "0x30000000000000000000000000000000000000000000002b",
+ "0x70000000000000000000000000000000000000000000001f",
+ "0x800000000000000000000000000000000000000000000005",
+ "0xfffffffffffffffffffffffffffffffffffffffeffffee37",
+ "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d",
+ "0xffffffffffffffffffffffffffffffffffffffffffffff13", // max prime
+
+ // N = 4
+ "0x0000000000000001000000000000000000000000000000000000000000000085", // min prime
+ "0x2523648240000001ba344d80000000086121000000000013a700000000000013",
+ "0x7523648240000001ba344d80000000086121000000000013a700000000000017",
+ "0x800000000000000000000000000000000000000000000000000000000000005f",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43", // max prime
+#if MCL_MAX_BIT_SIZE >= 384
+
+ // N = 6
+ "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff",
+#endif
+
+#if MCL_MAX_BIT_SIZE >= 521
+ // N = 9
+ "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+#endif
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const char *pStr = tbl[i];
+ printf("prime=%s\n", pStr);
+ Fp::init(pStr, mode);
+ cstrTest();
+ setStrTest();
+ streamTest();
+ ioModeTest();
+ edgeTest();
+ convTest();
+ compareTest();
+ moduloTest(pStr);
+ opeTest();
+ mulUnitTest();
+ powTest();
+ powNegTest();
+ powFpTest();
+ powGmp();
+ setArrayTest1();
+ setArrayMaskTest1();
+ setArrayModTest();
+ getUint64Test();
+ getInt64Test();
+ divBy2Test();
+ getStrTest();
+ setHashOfTest();
+ serializeTest();
+ modpTest();
+ }
+ anotherFpTest(mode);
+ setArrayTest2(mode);
+ setArrayMaskTest2(mode);
+}
+
+std::string g_mode;
+
+CYBOZU_TEST_AUTO(main)
+{
+ if (g_mode.empty() || g_mode == "auto") {
+ sub(mcl::fp::FP_AUTO);
+ }
+ if (g_mode.empty() || g_mode == "gmp") {
+ sub(mcl::fp::FP_GMP);
+ }
+ if (g_mode.empty() || g_mode == "gmp_mont") {
+ sub(mcl::fp::FP_GMP_MONT);
+ }
+#ifdef MCL_USE_LLVM
+ if (g_mode.empty() || g_mode == "llvm") {
+ sub(mcl::fp::FP_LLVM);
+ }
+ if (g_mode.empty() || g_mode == "llvm_mont") {
+ sub(mcl::fp::FP_LLVM_MONT);
+ }
+#endif
+#ifdef MCL_USE_XBYAK
+ if (g_mode.empty() || g_mode == "xbyak") {
+ sub(mcl::fp::FP_XBYAK);
+ }
+#endif
+}
+
+CYBOZU_TEST_AUTO(copyUnitToByteAsLE)
+{
+ using namespace mcl::fp;
+#if MCL_SIZEOF_UNIT == 4
+ const Unit src[] = { 0x12345678, 0xaabbccdd, 0xffeeddcc, 0x87654321 };
+#else
+ const Unit src[] = { uint64_t(0xaabbccdd12345678ull), uint64_t(0x87654321ffeeddcc) };
+#endif
+ const uint8_t ok[] = { 0x78, 0x56, 0x34, 0x12, 0xdd, 0xcc, 0xbb, 0xaa, 0xcc, 0xdd, 0xee, 0xff, 0x21, 0x43, 0x65, 0x87 };
+ const size_t okN = CYBOZU_NUM_OF_ARRAY(ok);
+ for (size_t i = 0; i < okN; i++) {
+ uint8_t buf[okN] = {};
+ copyUnitToByteAsLE(buf, src, i);
+ CYBOZU_TEST_EQUAL_ARRAY(ok, buf, i);
+ }
+ mcl::fp::Unit dst[2];
+ for (size_t i = 1; i <= sizeof(dst); i++) {
+ memset(dst, 0xff, sizeof(dst));
+ mcl::fp::copyByteToUnitAsLE(dst, ok, i);
+ if (i < sizeof(Unit)) {
+ CYBOZU_TEST_EQUAL(src[0] & ((uint64_t(1) << (i * 8)) - 1), dst[0]);
+ CYBOZU_TEST_EQUAL(dst[1], Unit(-1));
+ continue;
+ }
+ CYBOZU_TEST_EQUAL(dst[0], src[0]);
+ if (i == sizeof(Unit)) {
+ CYBOZU_TEST_EQUAL(dst[1], Unit(-1));
+ continue;
+ }
+ if (i < sizeof(dst)) {
+ CYBOZU_TEST_EQUAL(src[1] & ((uint64_t(1) << ((i - sizeof(Unit)) * 8)) - 1), dst[1]);
+ continue;
+ }
+ CYBOZU_TEST_EQUAL(src[1], dst[1]);
+ }
+ dst[0] = 1;
+ copyByteToUnitAsLE(dst, ok, 0);
+ CYBOZU_TEST_EQUAL(dst[0], 1u);
+}
+
+int main(int argc, char *argv[])
+ try
+{
+ cybozu::Option opt;
+ opt.appendOpt(&g_mode, "", "m", ": mode(auto/gmp/gmp_mont/llvm/llvm_mont/xbyak)");
+ opt.appendHelp("h", ": show this message");
+ if (!opt.parse(argc, argv)) {
+ opt.usage();
+ return 1;
+ }
+ return cybozu::test::autoRun.run(argc, argv);
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+ return 1;
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/fp_tower_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/fp_tower_test.cpp
new file mode 100644
index 000000000..a7123f7a5
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/fp_tower_test.cpp
@@ -0,0 +1,477 @@
+#define PUT(x) std::cout << #x "=" << (x) << std::endl
+#define CYBOZU_TEST_DISABLE_AUTO_RUN
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/xorshift.hpp>
+#include <time.h>
+#include <mcl/fp.hpp>
+#include <mcl/fp_tower.hpp>
+
+#ifdef _MSC_VER
+ #pragma warning(disable : 4456)
+#endif
+
+#if MCL_MAX_BIT_SIZE >= 768
+typedef mcl::FpT<mcl::FpTag, MCL_MAX_BIT_SIZE> Fp;
+#else
+typedef mcl::FpT<mcl::FpTag, 384> Fp;
+#endif
+typedef mcl::Fp2T<Fp> Fp2;
+typedef mcl::FpDblT<Fp> FpDbl;
+typedef mcl::Fp6T<Fp> Fp6;
+typedef mcl::Fp12T<Fp> Fp12;
+
+bool g_benchOnly = false;
+
+void testFp2()
+{
+ using namespace mcl;
+ puts(__FUNCTION__);
+#if MCL_MAX_BIT_SIZE < 768
+ const size_t FpSize = 48;
+ CYBOZU_TEST_EQUAL(sizeof(Fp), FpSize);
+ CYBOZU_TEST_EQUAL(sizeof(Fp2), FpSize * 2);
+ CYBOZU_TEST_EQUAL(sizeof(Fp6), FpSize * 6);
+ CYBOZU_TEST_EQUAL(sizeof(Fp12), FpSize * 12);
+#endif
+ Fp2 x, y, z;
+ x.a = 1;
+ x.b = 2;
+
+ {
+ std::stringstream os;
+ os << x;
+ os >> y;
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+ y.a = 3;
+ y.b = 4;
+ /*
+ x = 1 + 2i
+ y = 3 + 4i
+ */
+ Fp2::add(z, x, y);
+ CYBOZU_TEST_EQUAL(z, Fp2(4, 6));
+ Fp2::sub(z, x, y);
+ CYBOZU_TEST_EQUAL(z, Fp2(-2, -2));
+ Fp2::mul(z, x, y);
+ /*
+ (1 + 2i)(3 + 4i) = (3 - 8) + (4 + 6)i = -5 + 10i
+ */
+ CYBOZU_TEST_EQUAL(z, Fp2(-5, 10));
+ Fp2::neg(z, z);
+ CYBOZU_TEST_EQUAL(z, Fp2(5, -10));
+ /*
+ xi = xi_a + i
+ (1 - 2i)(xi_a + i) = (xi_a + 2) + (1 - 2 xi_a)i
+ */
+ z = Fp2(1, -2);
+ Fp2::mul_xi(z, z);
+ Fp a = Fp2::get_xi_a();
+ CYBOZU_TEST_EQUAL(z, Fp2(a + 2, a * (-2) + 1));
+ z = x * x;
+ Fp2::sqr(y, x);
+ CYBOZU_TEST_EQUAL(z, y);
+ x.a = -123456789;
+ x.b = 464652165165;
+ y = x * x;
+ Fp2::sqr(x, x);
+ CYBOZU_TEST_EQUAL(x, y);
+ {
+ std::ostringstream oss;
+ oss << x;
+ std::istringstream iss(oss.str());
+ Fp2 w;
+ iss >> w;
+ CYBOZU_TEST_EQUAL(x, w);
+ }
+ y = 1;
+ for (int i = 0; i < 10; i++) {
+ Fp2::pow(z, x, i);
+ CYBOZU_TEST_EQUAL(z, y);
+ y *= x;
+ }
+ /*
+ (a + bi)^p = a + bi if p % 4 = 1
+ (a + bi)^p = a - bi if p % 4 = 3
+ */
+ {
+ const mpz_class& mp = Fp::getOp().mp;
+ y = x;
+ Fp2::pow(z, y, mp);
+ if ((mp % 4) == 3) {
+ Fp::neg(z.b, z.b);
+ }
+ CYBOZU_TEST_EQUAL(z, y);
+ }
+ {
+ mpz_class t = Fp::getOp().mp;
+ t /= 2;
+ Fp x;
+ x.setMpz(t);
+ CYBOZU_TEST_EQUAL(x * 2, Fp(-1));
+ t += 1;
+ x.setMpz(t);
+ CYBOZU_TEST_EQUAL(x * 2, 1);
+ }
+ {
+ Fp2 a(1, 1);
+ Fp2 b(1, -1);
+ Fp2 c(Fp2(2) / a);
+ CYBOZU_TEST_EQUAL(c, b);
+ CYBOZU_TEST_EQUAL(a * b, Fp2(2));
+ CYBOZU_TEST_EQUAL(a * c, Fp2(2));
+ }
+ y = x;
+ Fp2::inv(y, x);
+ y *= x;
+ CYBOZU_TEST_EQUAL(y, 1);
+
+ // square root
+ for (int i = 0; i < 3; i++) {
+ x.a = i * i + i * 2;
+ x.b = i;
+ Fp2::sqr(y, x);
+ CYBOZU_TEST_ASSERT(Fp2::squareRoot(z, y));
+ CYBOZU_TEST_EQUAL(z * z, y);
+ CYBOZU_TEST_ASSERT(Fp2::squareRoot(y, y));
+ CYBOZU_TEST_EQUAL(z * z, y * y);
+ x.b = 0;
+ Fp2::sqr(y, x);
+ CYBOZU_TEST_ASSERT(Fp2::squareRoot(z, y));
+ CYBOZU_TEST_EQUAL(z * z, y);
+ x.a = 0;
+ x.b = i * i + i * 3;
+ Fp2::sqr(y, x);
+ CYBOZU_TEST_ASSERT(Fp2::squareRoot(z, y));
+ CYBOZU_TEST_EQUAL(z * z, y);
+ }
+}
+
+void testFp6sqr(const Fp2& a, const Fp2& b, const Fp2& c, const Fp6& x)
+{
+ Fp2 t;
+ t = b * c * 2;
+ Fp2::mul_xi(t, t);
+ t += a * a;
+ CYBOZU_TEST_EQUAL(x.a, t);
+ t = c * c;
+ Fp2::mul_xi(t, t);
+ t += a * b * 2;
+ CYBOZU_TEST_EQUAL(x.b, t);
+ t = b * b + a * c * 2;
+ CYBOZU_TEST_EQUAL(x.c, t);
+}
+
+void testFp6()
+{
+ using namespace mcl;
+ puts(__FUNCTION__);
+ Fp2 a(1, 2), b(3, 4), c(5, 6);
+ Fp6 x(a, b, c);
+ Fp6 y(Fp2(-1, 1), Fp2(4, -3), Fp2(-6, 2));
+ Fp6 z, w;
+ {
+ std::stringstream ss;
+ ss << x;
+ ss >> z;
+ CYBOZU_TEST_EQUAL(x, z);
+ }
+ Fp6::add(z, x, y);
+ CYBOZU_TEST_EQUAL(z, Fp6(Fp2(0, 3), Fp2(7, 1), Fp2(-1, 8)));
+ Fp6::sub(z, x, y);
+ CYBOZU_TEST_EQUAL(z, Fp6(Fp2(2, 1), Fp2(-1, 7), Fp2(11, 4)));
+ Fp6::neg(z, x);
+ CYBOZU_TEST_EQUAL(z, Fp6(-a, -b, -c));
+ Fp6::sqr(z, x);
+ Fp6::mul(w, x, x);
+ testFp6sqr(a, b, c, z);
+ testFp6sqr(a, b, c, w);
+ z = x;
+ Fp6::sqr(z, z);
+ Fp6::mul(w, x, x);
+ testFp6sqr(a, b, c, z);
+ testFp6sqr(a, b, c, w);
+ for (int i = 0; i < 10; i++) {
+ Fp6::inv(y, x);
+ Fp6::mul(z, y, x);
+ CYBOZU_TEST_EQUAL(z, 1);
+ x += y;
+ y = x;
+ Fp6::inv(y, y);
+ y *= x;
+ CYBOZU_TEST_EQUAL(y, 1);
+ }
+}
+
+void testFp12()
+{
+ puts(__FUNCTION__);
+ Fp6 xa(Fp2(1, 2), Fp2(3, 4), Fp2(5, 6));
+ Fp6 xb(Fp2(3, 1), Fp2(6, -1), Fp2(-2, 5));
+ Fp12 x(xa, xb);
+ Fp6 ya(Fp2(2, 1), Fp2(5, 3), Fp2(4, 1));
+ Fp6 yb(Fp2(1, -3), Fp2(2, -1), Fp2(-3, 1));
+ Fp12 y(ya, yb);
+ Fp12 z;
+ Fp12::add(z, x, y);
+ CYBOZU_TEST_EQUAL(z, Fp12(Fp6(Fp2(3, 3), Fp2(8, 7), Fp2(9, 7)), Fp6(Fp2(4, -2), Fp2(8, -2), Fp2(-5, 6))));
+ Fp12::sub(z, x, y);
+ CYBOZU_TEST_EQUAL(z, Fp12(Fp6(Fp2(-1, 1), Fp2(-2, 1), Fp2(1, 5)), Fp6(Fp2(2, 4), Fp2(4, 0), Fp2(1, 4))));
+ Fp12::neg(z, x);
+ CYBOZU_TEST_EQUAL(z, Fp12(-xa, -xb));
+
+ y.b.clear();
+ z = y;
+ Fp12::sqr(z, z);
+ CYBOZU_TEST_EQUAL(z.a, y.a * y.a);
+ z = y * y;
+ CYBOZU_TEST_EQUAL(z.a, y.a * y.a);
+ CYBOZU_TEST_ASSERT(z.b.isZero());
+ Fp12 w;
+ y = x;
+ z = x * x;
+ w = x;
+ Fp12::sqr(w, w);
+ CYBOZU_TEST_EQUAL(z, w);
+ y = x;
+ y *= y;
+ Fp12::sqr(x, x);
+ CYBOZU_TEST_EQUAL(x, y);
+ for (int i = 0; i < 10; i++) {
+ w = x;
+ Fp12::inv(w, w);
+ Fp12::mul(y, w, x);
+ CYBOZU_TEST_EQUAL(y, 1);
+ x += y;
+ }
+}
+
+void testFpDbl()
+{
+ puts(__FUNCTION__);
+ {
+ std::string pstr;
+ Fp::getModulo(pstr);
+ mpz_class mp(pstr);
+ mp <<= Fp::getUnitSize() * mcl::fp::UnitBitSize;
+ mpz_class mp1 = mp - 1;
+ mcl::gmp::getStr(pstr, mp1);
+ const char *tbl[] = {
+ "0", "1", "123456", "123456789012345668909", pstr.c_str(),
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ mpz_class mx(tbl[i]);
+ FpDbl x;
+ x.setMpz(mx);
+ for (size_t j = 0; j < CYBOZU_NUM_OF_ARRAY(tbl); j++) {
+ FpDbl y, z;
+ mpz_class mz, mo;
+ mpz_class my(tbl[j]);
+ y.setMpz(my);
+ FpDbl::add(z, x, y);
+ mcl::gmp::addMod(mo, mx, my, mp);
+ z.getMpz(mz);
+ CYBOZU_TEST_EQUAL(mz, mo);
+ mcl::gmp::subMod(mo, mx, my, mp);
+ FpDbl::sub(z, x, y);
+ z.getMpz(mz);
+ CYBOZU_TEST_EQUAL(mz, mo);
+ if (!Fp::isFullBit()) {
+ FpDbl::addPre(z, x, y);
+ mo = mx + my;
+ z.getMpz(mz);
+ CYBOZU_TEST_EQUAL(mz, mo);
+ if (mx >= my) {
+ FpDbl::subPre(z, x, y);
+ mo = mx - my;
+ z.getMpz(mz);
+ CYBOZU_TEST_EQUAL(mz, mo);
+ }
+ }
+ }
+ }
+ }
+ {
+ std::string pstr;
+ Fp::getModulo(pstr);
+ const mpz_class mp(pstr);
+ cybozu::XorShift rg;
+ for (int i = 0; i < 3; i++) {
+ Fp x, y, z;
+ mpz_class mx, my, mz, mo;
+ x.setRand(rg);
+ y.setRand(rg);
+ x.getMpz(mx);
+ y.getMpz(my);
+ FpDbl d;
+ FpDbl::mulPre(d, x, y);
+ d.getMpz(mz);
+ {
+ Fp tx, ty;
+ tx = x;
+ ty = y;
+ tx.toMont();
+ ty.toMont();
+ mpz_class mtx, mty;
+ tx.getMpz(mtx);
+ ty.getMpz(mty);
+ mo = mtx * mty;
+ }
+ CYBOZU_TEST_EQUAL(mz, mo);
+
+ FpDbl::mod(z, d);
+ z.getMpz(mz);
+ mo = (mx * my) % mp;
+ CYBOZU_TEST_EQUAL(mz, mo);
+ CYBOZU_TEST_EQUAL(z, x * y);
+
+ FpDbl::sqrPre(d, x);
+ d.getMpz(mz);
+ {
+ Fp tx;
+ tx = x;
+ tx.toMont();
+ mpz_class mtx;
+ tx.getMpz(mtx);
+ mo = mtx * mtx;
+ }
+ CYBOZU_TEST_EQUAL(mz, mo);
+
+ FpDbl::mod(z, d);
+ z.getMpz(mz);
+ mo = (mx * mx) % mp;
+ CYBOZU_TEST_EQUAL(mz, mo);
+ CYBOZU_TEST_EQUAL(z, x * x);
+ }
+ }
+}
+
+void testIo()
+{
+ int modeTbl[] = { 0, 2, 2 | mcl::IoPrefix, 10, 16, 16 | mcl::IoPrefix, mcl::IoArray, mcl::IoArrayRaw };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(modeTbl); i++) {
+ int ioMode = modeTbl[i];
+ Fp12 x;
+ for (int j = 0; j < 12; j++) {
+ x.getFp0()[j] = j * j;
+ }
+ std::string s = x.getStr(ioMode);
+ Fp12 y;
+ y.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+}
+
+void benchFp2()
+{
+ puts(__FUNCTION__);
+ Fp2 x, y;
+ x.a.setStr("4");
+ x.b.setStr("464652165165");
+ y = x * x;
+ double addT, subT, mulT, sqrT, invT, mul_xiT;
+ CYBOZU_BENCH_T(addT, Fp2::add, x, x, y);
+ CYBOZU_BENCH_T(subT, Fp2::sub, x, x, y);
+ CYBOZU_BENCH_T(mulT, Fp2::mul, x, x, y);
+ CYBOZU_BENCH_T(sqrT, Fp2::sqr, x, x);
+ CYBOZU_BENCH_T(invT, Fp2::inv, x, x);
+ CYBOZU_BENCH_T(mul_xiT, Fp2::mul_xi, x, x);
+// CYBOZU_BENCH("Fp2::mul_Fp_0", Fp2::mul_Fp_0, x, x, Param::half);
+// CYBOZU_BENCH("Fp2::mul_Fp_1", Fp2::mul_Fp_1, x, Param::half);
+// CYBOZU_BENCH("Fp2::divBy2 ", Fp2::divBy2, x, x);
+// CYBOZU_BENCH("Fp2::divBy4 ", Fp2::divBy4, x, x);
+ printf("add %8.2f|sub %8.2f|mul %8.2f|sqr %8.2f|inv %8.2f|mul_xi %8.2f\n", addT, subT, mulT, sqrT, invT, mul_xiT);
+}
+
+void test(const char *p, mcl::fp::Mode mode)
+{
+ const int xi_a = 1;
+ Fp::init(xi_a, p, mode);
+ printf("mode=%s\n", mcl::fp::ModeToStr(mode));
+ Fp2::init();
+#if 0
+ if (Fp::getBitSize() > 256) {
+ printf("not support p=%s\n", p);
+ return;
+ }
+#endif
+ if (g_benchOnly) {
+ benchFp2();
+ return;
+ }
+ testFp2();
+ testFpDbl();
+ testFp6();
+ testFp12();
+ testIo();
+}
+
+void testAll()
+{
+ const char *tbl[] = {
+ // N = 2
+ "0x0000000000000001000000000000000d",
+ "0x7fffffffffffffffffffffffffffffff",
+ "0x8000000000000000000000000000001d",
+ "0xffffffffffffffffffffffffffffff61",
+
+ // N = 3
+ "0x000000000000000100000000000000000000000000000033", // min prime
+ "0x00000000fffffffffffffffffffffffffffffffeffffac73",
+ "0x0000000100000000000000000001b8fa16dfab9aca16b6b3",
+ "0x000000010000000000000000000000000000000000000007",
+ "0x30000000000000000000000000000000000000000000002b",
+ "0x70000000000000000000000000000000000000000000001f",
+ "0x800000000000000000000000000000000000000000000005",
+ "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
+ "0xfffffffffffffffffffffffffffffffffffffffeffffee37",
+ "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d",
+ "0xffffffffffffffffffffffffffffffffffffffffffffff13", // max prime
+
+ // N = 4
+ "0x0000000000000001000000000000000000000000000000000000000000000085", // min prime
+ "0x2523648240000001ba344d80000000086121000000000013a700000000000013",
+ "0x7523648240000001ba344d80000000086121000000000013a700000000000017",
+ "0x800000000000000000000000000000000000000000000000000000000000005f",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43", // max prime
+#if MCL_MAX_BIT_SIZE >= 384
+ // N = 6
+ "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
+ "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff",
+#endif
+#if MCL_MAX_BIT_SIZE >= 768
+ "776259046150354467574489744231251277628443008558348305569526019013025476343188443165439204414323238975243865348565536603085790022057407195722143637520590569602227488010424952775132642815799222412631499596858234375446423426908029627",
+#endif
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const char *p = tbl[i];
+ printf("prime=%s %d\n", p, (int)(strlen(p) - 2) * 4);
+ test(p, mcl::fp::FP_GMP);
+#ifdef MCL_USE_LLVM
+ test(p, mcl::fp::FP_LLVM);
+ test(p, mcl::fp::FP_LLVM_MONT);
+#endif
+#ifdef MCL_USE_XBYAK
+ test(p, mcl::fp::FP_XBYAK);
+#endif
+ }
+}
+
+CYBOZU_TEST_AUTO(testAll)
+{
+ testAll();
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc > 1 && strcmp(argv[1], "-bench") == 0) {
+ g_benchOnly = true;
+ }
+ if (g_benchOnly) {
+ testAll();
+ return 0;
+ } else {
+ return cybozu::test::autoRun.run(argc, argv);
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/fp_util_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/fp_util_test.cpp
new file mode 100644
index 000000000..e8a9f9aa5
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/fp_util_test.cpp
@@ -0,0 +1,270 @@
+#define PUT(x) std::cout << #x "=" << (x) << std::endl
+#include <cybozu/test.hpp>
+#include <mcl/conversion.hpp>
+#include <mcl/gmp_util.hpp>
+#include <mcl/fp.hpp>
+#include <vector>
+
+CYBOZU_TEST_AUTO(arrayToHex)
+{
+ const struct {
+ uint32_t x[4];
+ size_t n;
+ const char *str;
+ } tbl[] = {
+ { { 0, 0, 0, 0 }, 0, "0" },
+ { { 0x123, 0, 0, 0 }, 1, "123" },
+ { { 0x12345678, 0xaabbcc, 0, 0 }, 2, "aabbcc12345678" },
+ { { 0, 0x12, 0x234a, 0 }, 3, "234a0000001200000000" },
+ { { 1, 2, 0xffffffff, 0x123abc }, 4, "123abcffffffff0000000200000001" },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ char buf[64];
+ size_t n = mcl::fp::arrayToHex(buf, sizeof(buf), tbl[i].x, tbl[i].n, false);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, tbl[i].str, n);
+ n = mcl::fp::arrayToHex(buf, sizeof(buf), tbl[i].x, tbl[i].n, true);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, (std::string("0x") + tbl[i].str).c_str(), n);
+ }
+}
+
+CYBOZU_TEST_AUTO(arrayToBin)
+{
+ const struct {
+ uint32_t x[4];
+ size_t n;
+ const char *str;
+ } tbl[] = {
+ { { 0, 0, 0, 0 }, 0, "0" },
+ { { 0x123, 0, 0, 0 }, 1, "100100011" },
+ { { 0x12345678, 0xaabbcc, 0, 0 }, 2, "10101010101110111100110000010010001101000101011001111000" },
+ { { 0, 0x12, 0x234a, 0 }, 3, "100011010010100000000000000000000000000001001000000000000000000000000000000000" },
+ { { 1, 2, 0xffffffff, 0x123abc }, 4, "100100011101010111100111111111111111111111111111111110000000000000000000000000000001000000000000000000000000000000001" },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ char buf[512];
+ size_t n = mcl::fp::arrayToBin(buf, sizeof(buf), tbl[i].x, tbl[i].n, false);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, tbl[i].str, n);
+ n = mcl::fp::arrayToBin(buf, sizeof(buf), tbl[i].x, tbl[i].n, true);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, (std::string("0b") + tbl[i].str).c_str(), n);
+ }
+}
+// CYBOZU_TEST_AUTO(verifyStr) // QQQ
+
+CYBOZU_TEST_AUTO(hexToArray)
+{
+ const struct {
+ const char *str;
+ uint64_t x[4];
+ } tbl[] = {
+ { "0", { 0, 0, 0, 0 } },
+ { "5", { 5, 0, 0, 0 } },
+ { "123", { 0x123, 0, 0, 0 } },
+ { "123456789012345679adbc", { uint64_t(0x789012345679adbcull), 0x123456, 0, 0 } },
+ { "ffffffff26f2fc170f69466a74defd8d", { uint64_t(0x0f69466a74defd8dull), uint64_t(0xffffffff26f2fc17ull), 0, 0 } },
+ { "100000000000000000000000000000033", { uint64_t(0x0000000000000033ull), 0, 1, 0 } },
+ { "11ee12312312940000000000000000000000000002342343", { uint64_t(0x0000000002342343ull), uint64_t(0x0000000000000000ull), uint64_t(0x11ee123123129400ull), 0 } },
+ { "1234567890abcdefABCDEF123456789aba32134723424242424", { uint64_t(0x2134723424242424ull), uint64_t(0xDEF123456789aba3ull), uint64_t(0x4567890abcdefABCull), 0x123 } },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const size_t xN = 4;
+ uint64_t x[xN];
+ size_t n = mcl::fp::hexToArray(x, xN, tbl[i].str, strlen(tbl[i].str));
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL_ARRAY(x, tbl[i].x, n);
+ }
+}
+
+CYBOZU_TEST_AUTO(compareArray)
+{
+ const struct {
+ uint32_t a[4];
+ uint32_t b[4];
+ size_t n;
+ int expect;
+ } tbl[] = {
+ { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, 0 },
+ { { 1, 0, 0, 0 }, { 0, 0, 0, 0 }, 1, 1 },
+ { { 0, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, -1 },
+ { { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, 0 },
+ { { 3, 1, 1, 0 }, { 2, 1, 1, 0 }, 4, 1 },
+ { { 9, 2, 1, 1 }, { 1, 3, 1, 1 }, 4, -1 },
+ { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 3, 0 },
+ { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 4, -1 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ int e = mcl::fp::compareArray(tbl[i].a, tbl[i].b, tbl[i].n);
+ CYBOZU_TEST_EQUAL(e, tbl[i].expect);
+ }
+}
+
+CYBOZU_TEST_AUTO(isLessArray)
+{
+ const struct {
+ uint32_t a[4];
+ uint32_t b[4];
+ size_t n;
+ bool expect;
+ } tbl[] = {
+ { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, false },
+ { { 1, 0, 0, 0 }, { 0, 0, 0, 0 }, 1, false },
+ { { 0, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, true },
+ { { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, false },
+ { { 3, 1, 1, 0 }, { 2, 1, 1, 0 }, 4, false },
+ { { 3, 1, 2, 0 }, { 2, 2, 2, 0 }, 4, true },
+ { { 9, 2, 1, 1 }, { 1, 3, 1, 1 }, 4, true },
+ { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 3, false },
+ { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 4, true },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ bool e = mcl::fp::isLessArray(tbl[i].a, tbl[i].b, tbl[i].n);
+ CYBOZU_TEST_EQUAL(e, tbl[i].expect);
+ e = mcl::fp::isGreaterArray(tbl[i].b, tbl[i].a, tbl[i].n);
+ CYBOZU_TEST_EQUAL(e, tbl[i].expect);
+ }
+}
+
+CYBOZU_TEST_AUTO(isLessOrEqualArray)
+{
+ const struct {
+ uint32_t a[4];
+ uint32_t b[4];
+ size_t n;
+ bool expect;
+ } tbl[] = {
+ { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, true },
+ { { 1, 0, 0, 0 }, { 0, 0, 0, 0 }, 1, false },
+ { { 0, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, true },
+ { { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, true },
+ { { 3, 1, 1, 0 }, { 2, 1, 1, 0 }, 4, false },
+ { { 3, 1, 2, 0 }, { 2, 2, 2, 0 }, 4, true },
+ { { 9, 2, 1, 1 }, { 1, 3, 1, 1 }, 4, true },
+ { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 3, true },
+ { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 4, true },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ bool e = mcl::fp::isLessOrEqualArray(tbl[i].a, tbl[i].b, tbl[i].n);
+ CYBOZU_TEST_EQUAL(e, tbl[i].expect);
+ e = mcl::fp::isGreaterOrEqualArray(tbl[i].b, tbl[i].a, tbl[i].n);
+ CYBOZU_TEST_EQUAL(e, tbl[i].expect);
+ }
+}
+
+struct Rand {
+ std::vector<uint32_t> v;
+ const uint8_t *p;
+ size_t pos;
+ size_t endPos;
+ void read(bool *pb, void *x, size_t n)
+ {
+ if (pos + n > endPos) {
+ *pb = false;
+ return;
+ }
+ uint8_t *dst = (uint8_t*)x;
+ memcpy(dst, p + pos, n);
+ pos += n;
+ *pb = true;
+ }
+ void read(void *x, size_t n)
+ {
+ bool b;
+ read(&b, x, n);
+ if (!b) throw cybozu::Exception("Rand") << n;
+ }
+ uint32_t operator()()
+ {
+ char buf[4];
+ read(buf, 4);
+ uint32_t v;
+ memcpy(&v, buf, 4);
+ return v;
+ }
+ Rand(const uint32_t *x, size_t n)
+ : p(0)
+ , pos(0)
+ {
+ for (size_t i = 0; i < n; i++) {
+ v.push_back(x[i]);
+ }
+ p = (uint8_t*)&v[0];
+ endPos = v.size() * 4;
+ }
+};
+
+CYBOZU_TEST_AUTO(maskArray)
+{
+#if 1
+ const size_t n = 2;
+ uint32_t org[n] = { 0xabce1234, 0xffffef32 };
+ for (size_t i = 0; i <= sizeof(org) * 8; i++) {
+ uint32_t x[n];
+ memcpy(x, org, sizeof(org));
+ mcl::fp::maskArray(x, n, i);
+ mpz_class t;
+ mcl::gmp::setArray(t, org, n);
+ t &= (mpz_class(1) << i) - 1;
+ uint32_t y[n];
+ mcl::gmp::getArray(y, n, t);
+ CYBOZU_TEST_EQUAL_ARRAY(x, y, n);
+ }
+#else
+ const size_t n = 4;
+ uint16_t org[n] = { 0x1234, 0xabce, 0xef32, 0xffff };
+ for (size_t i = 0; i <= sizeof(org) * 8; i++) {
+ uint16_t x[n];
+ memcpy(x, org, sizeof(org));
+ mcl::fp::maskArray(x, n, i);
+ mpz_class t;
+ mcl::gmp::setArray(t, org, n);
+ t &= (mpz_class(1) << i) - 1;
+ uint16_t y[n];
+ mcl::gmp::getArray(y, n, t);
+ CYBOZU_TEST_EQUAL_ARRAY(x, y, n);
+ }
+#endif
+}
+
+CYBOZU_TEST_AUTO(stream)
+{
+ const char *nulTbl[] = { "", " ", " \t\t\n\n " };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(nulTbl); i++) {
+ const char *p = nulTbl[i];
+ cybozu::MemoryInputStream is(p, strlen(p));
+ std::string w = "abc";
+ mcl::fp::local::loadWord(w, is);
+ CYBOZU_TEST_ASSERT(w.empty());
+ }
+ const struct {
+ const char *buf;
+ const char *expect[2];
+ size_t n;
+ } tbl[] = {
+ { "\t\t \n\rabc\r\r\n def", { "abc", "def" }, 2 },
+ { "123", { "123" }, 1 },
+ { "123\n", { "123" }, 1 },
+ { "123 456", { "123", "456" }, 2 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const char *buf = tbl[i].buf;
+ {
+ cybozu::MemoryInputStream is(buf, strlen(buf));
+ for (size_t j = 0; j < tbl[i].n; j++) {
+ std::string w;
+ mcl::fp::local::loadWord(w, is);
+ CYBOZU_TEST_EQUAL(w, tbl[i].expect[j]);
+ }
+ }
+ {
+ std::istringstream is(buf);
+ for (size_t j = 0; j < tbl[i].n; j++) {
+ std::string w;
+ mcl::fp::local::loadWord(w, is);
+ CYBOZU_TEST_EQUAL(w, tbl[i].expect[j]);
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/glv_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/glv_test.cpp
new file mode 100644
index 000000000..a917f51f4
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/glv_test.cpp
@@ -0,0 +1,209 @@
+#define PUT(x) std::cout << #x "=" << (x) << std::endl;
+#include <cybozu/test.hpp>
+#include <cybozu/xorshift.hpp>
+#include <cybozu/benchmark.hpp>
+
+#if 1
+#include <mcl/bn384.hpp>
+using namespace mcl::bn384;
+#else
+#include <mcl/bn256.hpp>
+using namespace mcl::bn256;
+#endif
+
+#define PUT(x) std::cout << #x "=" << (x) << std::endl;
+
+/*
+ Skew Frobenius Map and Efficient Scalar Multiplication for Pairing-Based Cryptography
+ Y. Sakemi, Y. Nogami, K. Okeya, H. Kato, Y. Morikawa
+*/
+struct oldGLV {
+ Fp w; // (-1 + sqrt(-3)) / 2
+ mpz_class r;
+ mpz_class v; // 6z^2 + 4z + 1 > 0
+ mpz_class c; // 2z + 1
+ void init(const mpz_class& r, const mpz_class& z)
+ {
+ if (!Fp::squareRoot(w, -3)) throw cybozu::Exception("oldGLV:init");
+ w = (w - 1) / 2;
+ this->r = r;
+ v = 1 + z * (4 + z * 6);
+ c = 2 * z + 1;
+ }
+ /*
+ (p^2 mod r) (x, y) = (wx, -y)
+ */
+ void mulP2(G1& Q, const G1& P) const
+ {
+ Fp::mul(Q.x, P.x, w);
+ Fp::neg(Q.y, P.y);
+ Q.z = P.z;
+ }
+ /*
+ x = ap^2 + b mod r
+ assume(x < r);
+ */
+ void split(mpz_class& a, mpz_class& b, const mpz_class& x) const
+ {
+ assert(0 < x && x < r);
+ /*
+ x = s1 * v + s2 // s1 = x / v, s2 = x % v
+ = s1 * c * p^2 + s2 // vP = cp^2 P
+ = (s3 * v + s4) * p^2 + s2 // s3 = (s1 * c) / v, s4 = (s1 * c) % v
+ = (s3 * c * p^2 + s4) * p^2 + s2
+ = (s3 * c) * p^4 + s4 * p^2 + s2 // s5 = s3 * c, p^4 = p^2 - 1
+ = s5 * (p^2 - 1) + s4 * p^2 + s2
+ = (s4 + s5) * p^2 + (s2 - s5)
+ */
+ mpz_class t;
+ mcl::gmp::divmod(a, t, x, v); // a = t / v, t = t % v
+ a *= c;
+ mcl::gmp::divmod(b, a, a, v); // b = a / v, a = a % v
+ b *= c;
+ a += b;
+ b = t - b;
+ }
+ template<class G1>
+ void mul(G1& Q, const G1& P, const mpz_class& x) const
+ {
+ G1 A, B;
+ mpz_class a, b;
+ split(a, b, x);
+ mulP2(A, P);
+ G1::mul(A, A, a);
+ G1::mul(B, P, b);
+ G1::add(Q, A, B);
+ }
+};
+
+template<class GLV1, class GLV2>
+void compareLength(const GLV1& rhs, const GLV2& lhs)
+{
+ cybozu::XorShift rg;
+ int lt = 0;
+ int eq = 0;
+ int gt = 0;
+ mpz_class R0, R1, L0, L1, x;
+ Fr r;
+ for (int i = 1; i < 1000; i++) {
+ r.setRand(rg);
+ x = r.getMpz();
+ rhs.split(R0, R1, x);
+ lhs.split(L0, L1, x);
+
+ size_t R0n = mcl::gmp::getBitSize(R0);
+ size_t R1n = mcl::gmp::getBitSize(R1);
+ size_t L0n = mcl::gmp::getBitSize(L0);
+ size_t L1n = mcl::gmp::getBitSize(L1);
+ size_t Rn = std::max(R0n, R1n);
+ size_t Ln = std::max(L0n, L1n);
+ if (Rn == Ln) {
+ eq++;
+ }
+ if (Rn > Ln) {
+ gt++;
+ }
+ if (Rn < Ln) {
+ lt++;
+ }
+ }
+ printf("#of{<} = %d, #of{=} = %d #of{>} = %d\n", lt, eq, gt);
+}
+
+void testGLV1()
+{
+ G1 P0, P1, P2;
+ mapToG1(P0, 1);
+ cybozu::XorShift rg;
+
+ oldGLV oldGlv;
+ if (!BN::param.isBLS12) {
+ oldGlv.init(BN::param.r, BN::param.z);
+ }
+
+ mcl::bn::local::GLV1 glv;
+ glv.init(BN::param.r, BN::param.z, BN::param.isBLS12);
+ if (!BN::param.isBLS12) {
+ compareLength(glv, oldGlv);
+ }
+
+ for (int i = 1; i < 100; i++) {
+ mapToG1(P0, i);
+ Fr s;
+ s.setRand(rg);
+ mpz_class ss = s.getMpz();
+ G1::mulGeneric(P1, P0, ss);
+ glv.mul(P2, P0, ss);
+ CYBOZU_TEST_EQUAL(P1, P2);
+ glv.mul(P2, P0, ss, true);
+ CYBOZU_TEST_EQUAL(P1, P2);
+ if (!BN::param.isBLS12) {
+ oldGlv.mul(P2, P0, ss);
+ CYBOZU_TEST_EQUAL(P1, P2);
+ }
+ }
+ for (int i = -100; i < 100; i++) {
+ mpz_class ss = i;
+ G1::mulGeneric(P1, P0, ss);
+ glv.mul(P2, P0, ss);
+ CYBOZU_TEST_EQUAL(P1, P2);
+ glv.mul(P2, P0, ss, true);
+ CYBOZU_TEST_EQUAL(P1, P2);
+ }
+ Fr s;
+ mapToG1(P0, 123);
+ CYBOZU_BENCH_C("Ec::mul", 100, P1 = P0; s.setRand(rg); G1::mulGeneric, P2, P1, s.getMpz());
+ CYBOZU_BENCH_C("Ec::glv", 100, P1 = P0; s.setRand(rg); glv.mul, P2, P1, s.getMpz());
+}
+
+/*
+ lambda = 6 * z * z
+ mul (lambda * 2) = FrobeniusOnTwist * 2
+*/
+void testGLV2()
+{
+ G2 Q0, Q1, Q2;
+ mpz_class z = BN::param.z;
+ mpz_class r = BN::param.r;
+ mpz_class lambda = 6 * z * z;
+ mcl::bn::local::GLV2 glv2;
+ glv2.init(r, z, BN::param.isBLS12);
+ mpz_class n;
+ cybozu::XorShift rg;
+ mapToG2(Q0, 1);
+ for (int i = -10; i < 10; i++) {
+ n = i;
+ G2::mulGeneric(Q1, Q0, n);
+ glv2.mul(Q2, Q0, n);
+ CYBOZU_TEST_EQUAL(Q1, Q2);
+ }
+ for (int i = 1; i < 100; i++) {
+ mcl::gmp::getRand(n, glv2.rBitSize, rg);
+ n %= r;
+ n -= r/2;
+ mapToG2(Q0, i);
+ G2::mulGeneric(Q1, Q0, n);
+ glv2.mul(Q2, Q0, n);
+ CYBOZU_TEST_EQUAL(Q1, Q2);
+ }
+ Fr s;
+ mapToG2(Q0, 123);
+ CYBOZU_BENCH_C("G2::mul", 1000, Q2 = Q0; s.setRand(rg); G2::mulGeneric, Q2, Q1, s.getMpz());
+ CYBOZU_BENCH_C("G2::glv", 1000, Q1 = Q0; s.setRand(rg); glv2.mul, Q2, Q1, s.getMpz());
+}
+
+CYBOZU_TEST_AUTO(glv)
+{
+ const mcl::CurveParam tbl[] = {
+ mcl::BN254,
+ mcl::BN381_1,
+ mcl::BN381_2,
+ mcl::BLS12_381,
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const mcl::CurveParam& cp = tbl[i];
+ initPairing(cp);
+ testGLV1();
+ testGLV2();
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/gmp_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/gmp_test.cpp
new file mode 100644
index 000000000..1fe9d4eb6
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/gmp_test.cpp
@@ -0,0 +1,70 @@
+#include <mcl/gmp_util.hpp>
+#include <vector>
+#include <cybozu/test.hpp>
+
+CYBOZU_TEST_AUTO(testBit)
+{
+ const size_t maxBit = 100;
+ const size_t tbl[] = {
+ 3, 9, 5, 10, 50, maxBit
+ };
+ mpz_class a;
+ std::vector<bool> b(maxBit + 1);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ a |= mpz_class(1) << tbl[i];
+ b[tbl[i]] = 1;
+ }
+ for (size_t i = 0; i <= maxBit; i++) {
+ bool c1 = mcl::gmp::testBit(a, i);
+ bool c2 = b[i] != 0;
+ CYBOZU_TEST_EQUAL(c1, c2);
+ }
+}
+
+CYBOZU_TEST_AUTO(getStr)
+{
+ const struct {
+ int x;
+ const char *dec;
+ const char *hex;
+ } tbl[] = {
+ { 0, "0", "0" },
+ { 1, "1", "1" },
+ { 10, "10", "a" },
+ { 16, "16", "10" },
+ { 123456789, "123456789", "75bcd15" },
+ { -1, "-1", "-1" },
+ { -10, "-10", "-a" },
+ { -16, "-16", "-10" },
+ { -100000000, "-100000000", "-5f5e100" },
+ { -987654321, "-987654321", "-3ade68b1" },
+ { -2147483647, "-2147483647", "-7fffffff" },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ mpz_class x = tbl[i].x;
+ char buf[32];
+ size_t n, len;
+ len = strlen(tbl[i].dec);
+ n = mcl::gmp::getStr(buf, len, x, 10);
+ CYBOZU_TEST_EQUAL(n, 0);
+ n = mcl::gmp::getStr(buf, len + 1, x, 10);
+ CYBOZU_TEST_EQUAL(n, len);
+ CYBOZU_TEST_EQUAL_ARRAY(buf, tbl[i].dec, n);
+
+ len = strlen(tbl[i].hex);
+ n = mcl::gmp::getStr(buf, len, x, 16);
+ CYBOZU_TEST_EQUAL(n, 0);
+ n = mcl::gmp::getStr(buf, len + 1, x, 16);
+ CYBOZU_TEST_EQUAL(n, len);
+ CYBOZU_TEST_EQUAL_ARRAY(buf, tbl[i].hex, n);
+ }
+}
+
+CYBOZU_TEST_AUTO(getRandPrime)
+{
+ for (int i = 0; i < 10; i++) {
+ mpz_class z;
+ mcl::gmp::getRandPrime(z, i * 10 + 3);
+ CYBOZU_TEST_ASSERT(mcl::gmp::isPrime(z));
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/low_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/low_test.cpp
new file mode 100644
index 000000000..f5e72a0b3
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/low_test.cpp
@@ -0,0 +1,73 @@
+#ifndef MCL_USE_LLVM
+ #define MCL_USE_LLVM
+#endif
+#include <cybozu/test.hpp>
+#include <cybozu/xorshift.hpp>
+#include <cybozu/itoa.hpp>
+#include "../src/low_func.hpp"
+#include <cybozu/benchmark.hpp>
+
+cybozu::XorShift rg;
+
+extern "C" void add_test(mcl::fp::Unit *z, const mcl::fp::Unit *x, const mcl::fp::Unit *y);
+
+template<size_t bit>
+void bench()
+{
+ using namespace mcl::fp;
+ const size_t N = bit / UnitBitSize;
+ Unit x[N], y[N];
+ for (int i = 0; i < 10; i++) {
+ Unit z[N];
+ Unit w[N];
+ rg.read(x, N);
+ rg.read(y, N);
+ AddPre<N, Gtag>::f(z, x, y);
+ AddPre<N, Ltag>::f(w, x, y);
+ CYBOZU_TEST_EQUAL_ARRAY(z, w, N);
+
+ SubPre<N, Gtag>::f(z, x, y);
+ SubPre<N, Ltag>::f(w, x, y);
+ CYBOZU_TEST_EQUAL_ARRAY(z, w, N);
+ }
+ const std::string bitS = cybozu::itoa(bit);
+ std::string name;
+ name = "add" + bitS; CYBOZU_BENCH(name.c_str(), (AddPre<N, Ltag>::f), x, x, y);
+ name = "sub" + bitS; CYBOZU_BENCH(name.c_str(), (SubPre<N, Ltag>::f), x, x, y);
+}
+
+CYBOZU_TEST_AUTO(addPre64) { bench<64>(); }
+CYBOZU_TEST_AUTO(addPre128) { bench<128>(); }
+CYBOZU_TEST_AUTO(addPre192) { bench<192>(); }
+CYBOZU_TEST_AUTO(addPre256) { bench<256>(); }
+CYBOZU_TEST_AUTO(addPre320) { bench<320>(); }
+CYBOZU_TEST_AUTO(addPre384) { bench<384>(); }
+CYBOZU_TEST_AUTO(addPre448) { bench<448>(); }
+CYBOZU_TEST_AUTO(addPre512) { bench<512>(); }
+//CYBOZU_TEST_AUTO(addPre96) { bench<96>(); }
+//CYBOZU_TEST_AUTO(addPre160) { bench<160>(); }
+//CYBOZU_TEST_AUTO(addPre224) { bench<224>(); }
+#if 0
+CYBOZU_TEST_AUTO(addPre)
+{
+ using namespace mcl::fp;
+ const size_t bit = 128;
+ const size_t N = bit / UnitBitSize;
+ Unit x[N], y[N];
+ for (int i = 0; i < 10; i++) {
+ Unit z[N];
+ Unit w[N];
+ rg.read(x, N);
+ rg.read(y, N);
+ low_addPre_G<N>(z, x, y);
+ addPre<bit>(w, x, y);
+ CYBOZU_TEST_EQUAL_ARRAY(z, w, N);
+ add_test(w, x, y);
+ CYBOZU_TEST_EQUAL_ARRAY(z, w, N);
+ }
+ std::string name = "add" + cybozu::itoa(bit);
+ CYBOZU_BENCH(name.c_str(), addPre<bit>, x, x, y);
+ CYBOZU_BENCH("add", add_test, x, x, y);
+}
+#endif
+
diff --git a/vendor/github.com/dexon-foundation/mcl/test/mk32.sh b/vendor/github.com/dexon-foundation/mcl/test/mk32.sh
new file mode 100644
index 000000000..4d5f60711
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/mk32.sh
@@ -0,0 +1 @@
+g++ -O3 -march=native base_test.cpp ../src/x86.s -m32 -I ~/32/include/ -I ../include/ -I ../../xbyak/ -I ../../cybozulib/include ~/32/lib/libgmp.a ~/32/lib/libgmpxx.a -I ~/32/lib -DNDEBUG
diff --git a/vendor/github.com/dexon-foundation/mcl/test/modp_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/modp_test.cpp
new file mode 100644
index 000000000..bf9da38bf
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/modp_test.cpp
@@ -0,0 +1,37 @@
+#include <mcl/gmp_util.hpp>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/test.hpp>
+
+#define PUT(x) std::cout << #x << "=" << x << std::endl;
+
+CYBOZU_TEST_AUTO(modp)
+{
+ const int C = 1000000;
+ const char *pTbl[] = {
+ "0x2523648240000001ba344d8000000007ff9f800000000010a10000000000000d",
+ "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
+ "0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001",
+ };
+ const char *xTbl[] = {
+ "0x12345678892082039482094823",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x10000000000000000000000000000000000000000000000000000000000000000",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ };
+ mcl::Modp modp;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(pTbl); i++) {
+ const mpz_class p(pTbl[i]);
+ std::cout << std::hex << "p=" << p << std::endl;
+ modp.init(p);
+ for (size_t j = 0; j < CYBOZU_NUM_OF_ARRAY(xTbl); j++) {
+ const mpz_class x(xTbl[j]);
+ std::cout << std::hex << "x=" << x << std::endl;
+ mpz_class r1, r2;
+ r1 = x % p;
+ modp.modp(r2, x);
+ CYBOZU_TEST_EQUAL(r1, r2);
+ CYBOZU_BENCH_C("x % p", C, mcl::gmp::mod, r1, x, p);
+ CYBOZU_BENCH_C("modp ", C, modp.modp, r2, x);
+ }
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/mont_fp_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/mont_fp_test.cpp
new file mode 100644
index 000000000..e41e77a53
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/mont_fp_test.cpp
@@ -0,0 +1,332 @@
+#define PUT(x) std::cout << #x "=" << (x) << std::endl
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/xorshift.hpp>
+#include <time.h>
+
+#if 0
+#include <mcl/bls12_381.hpp>
+using namespace mcl::bls12;
+typedef Fr Zn;
+#else
+#include <mcl/fp.hpp>
+struct ZnTag;
+typedef mcl::FpT<ZnTag> Zn;
+typedef mcl::FpT<> Fp;
+#endif
+
+struct Montgomery {
+ typedef mcl::fp::Unit Unit;
+ mpz_class p_;
+ mpz_class R_; // (1 << (pn_ * 64)) % p
+ mpz_class RR_; // (R * R) % p
+ Unit rp_; // rp * p = -1 mod M = 1 << 64
+ size_t pn_;
+ Montgomery() {}
+ explicit Montgomery(const mpz_class& p)
+ {
+ p_ = p;
+ rp_ = mcl::fp::getMontgomeryCoeff(mcl::gmp::getUnit(p, 0));
+ pn_ = mcl::gmp::getUnitSize(p);
+ R_ = 1;
+ R_ = (R_ << (pn_ * 64)) % p_;
+ RR_ = (R_ * R_) % p_;
+ }
+
+ void toMont(mpz_class& x) const { mul(x, x, RR_); }
+ void fromMont(mpz_class& x) const { mul(x, x, 1); }
+
+ void mul(mpz_class& z, const mpz_class& x, const mpz_class& y) const
+ {
+#if 0
+ const size_t ySize = mcl::gmp::getUnitSize(y);
+ mpz_class c = x * mcl::gmp::getUnit(y, 0);
+ Unit q = mcl::gmp::getUnit(c, 0) * rp_;
+ c += p_ * q;
+ c >>= sizeof(Unit) * 8;
+ for (size_t i = 1; i < pn_; i++) {
+ if (i < ySize) {
+ c += x * mcl::gmp::getUnit(y, i);
+ }
+ Unit q = mcl::gmp::getUnit(c, 0) * rp_;
+ c += p_ * q;
+ c >>= sizeof(Unit) * 8;
+ }
+ if (c >= p_) {
+ c -= p_;
+ }
+ z = c;
+#else
+ z = x * y;
+ for (size_t i = 0; i < pn_; i++) {
+ Unit q = mcl::gmp::getUnit(z, 0) * rp_;
+#ifdef MCL_USE_VINT
+ z += p_ * q;
+#else
+ mpz_class t;
+ mcl::gmp::set(t, q);
+ z += p_ * t;
+#endif
+ z >>= sizeof(Unit) * 8;
+ }
+ if (z >= p_) {
+ z -= p_;
+ }
+#endif
+ }
+ void mod(mpz_class& z, const mpz_class& xy) const
+ {
+ z = xy;
+ for (size_t i = 0; i < pn_; i++) {
+//printf("i=%zd\n", i);
+//std::cout << "z=" << std::hex << z << std::endl;
+ Unit q = mcl::gmp::getUnit(z, 0) * rp_;
+//std::cout << "q=" << q << std::endl;
+ mpz_class t;
+ mcl::gmp::set(t, q);
+ z += p_ * t;
+ z >>= sizeof(Unit) * 8;
+//std::cout << "z=" << std::hex << z << std::endl;
+ }
+ if (z >= p_) {
+ z -= p_;
+ }
+//std::cout << "z=" << std::hex << z << std::endl;
+ }
+};
+
+template<class T>
+mpz_class getMpz(const T& x)
+{
+ std::string str = x.getStr();
+ mpz_class t;
+ mcl::gmp::setStr(t, str);
+ return t;
+}
+
+template<class T>
+std::string getStr(const T& x)
+{
+ std::ostringstream os;
+ os << x;
+ return os.str();
+}
+
+template<class T, class U>
+T castTo(const U& x)
+{
+ T t;
+ t.setStr(getStr(x));
+ return t;
+}
+
+template<class T>
+void putRaw(const T& x)
+{
+ const uint64_t *p = x.getInnerValue();
+ for (size_t i = 0, n = T::BlockSize; i < n; i++) {
+ printf("%016llx", p[n - 1 - i]);
+ }
+ printf("\n");
+}
+
+template<size_t N>
+void put(const uint64_t (&x)[N])
+{
+ for (size_t i = 0; i < N; i++) {
+ printf("%016llx", x[N - 1 - i]);
+ }
+ printf("\n");
+}
+
+struct Test {
+ typedef mcl::FpT<> Fp;
+ void run(const char *p)
+ {
+ Fp::init(p);
+ Fp x("-123456789");
+ Fp y("-0x7ffffffff");
+ CYBOZU_BENCH("add", operator+, x, x);
+ CYBOZU_BENCH("sub", operator-, x, y);
+ CYBOZU_BENCH("mul", operator*, x, x);
+ CYBOZU_BENCH("sqr", Fp::sqr, x, x);
+ CYBOZU_BENCH("div", y += x; operator/, x, y);
+ }
+};
+
+void customTest(const char *pStr, const char *xStr, const char *yStr)
+{
+#if 0
+ {
+ pStr = "0xfffffffffffffffffffffffffffffffffffffffeffffee37",
+ Fp::init(pStr);
+ static uint64_t x[3] = { 1, 0, 0 };
+ uint64_t z[3];
+std::cout<<std::hex;
+ Fp::inv(*(Fp*)z, *(const Fp*)x);
+put(z);
+ exit(1);
+ }
+#endif
+#if 0
+ std::cout << std::hex;
+ uint64_t x[9] = { 0xff7fffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x1ff };
+ uint64_t y[9] = { 0xff7fffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x1ff };
+ uint64_t z1[9], z2[9];
+ Fp::init(pStr);
+ Fp::fg_.mul_(z2, x, y);
+ put(z2);
+ {
+ puts("C");
+ mpz_class p(pStr);
+ Montgomery mont(p);
+ mpz_class xx, yy;
+ mcl::gmp::setArray(xx, x, CYBOZU_NUM_OF_ARRAY(x));
+ mcl::gmp::setArray(yy, y, CYBOZU_NUM_OF_ARRAY(y));
+ mpz_class z;
+ mont.mul(z, xx, yy);
+ std::cout << std::hex << z << std::endl;
+ }
+ exit(1);
+#else
+ std::string rOrg, rC, rAsm;
+ Zn::init(pStr);
+ Zn s(xStr), t(yStr);
+ s *= t;
+ rOrg = getStr(s);
+ {
+ puts("C");
+ mpz_class p(pStr);
+ Montgomery mont(p);
+ mpz_class x(xStr), y(yStr);
+ mont.toMont(x);
+ mont.toMont(y);
+ mpz_class z;
+ mont.mul(z, x, y);
+ mont.fromMont(z);
+ rC = getStr(z);
+ }
+
+ puts("asm");
+ Fp::init(pStr);
+ Fp x(xStr), y(yStr);
+ x *= y;
+ rAsm = getStr(x);
+ CYBOZU_TEST_EQUAL(rOrg, rC);
+ CYBOZU_TEST_EQUAL(rOrg, rAsm);
+#endif
+}
+
+#if MCL_MAX_BIT_SIZE >= 521
+CYBOZU_TEST_AUTO(customTest)
+{
+ const struct {
+ const char *p;
+ const char *x;
+ const char *y;
+ } tbl[] = {
+ {
+ "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+// "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff",
+// "0xfffffffffffffffffffffffffffffffffffffffeffffee37",
+ "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
+ "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
+ },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ customTest(tbl[i].p, tbl[i].x, tbl[i].y);
+ }
+}
+#endif
+
+CYBOZU_TEST_AUTO(test)
+{
+ Test test;
+ const char *tbl[] = {
+#if 1
+ // N = 2
+ "0x0000000000000001000000000000000d",
+ "0x7fffffffffffffffffffffffffffffff",
+ "0x8000000000000000000000000000001d",
+ "0xffffffffffffffffffffffffffffff61",
+
+ // N = 3
+ "0x000000000000000100000000000000000000000000000033", // min prime
+ "0x00000000fffffffffffffffffffffffffffffffeffffac73",
+ "0x0000000100000000000000000001b8fa16dfab9aca16b6b3",
+ "0x000000010000000000000000000000000000000000000007",
+ "0x30000000000000000000000000000000000000000000002b",
+ "0x70000000000000000000000000000000000000000000001f",
+ "0x800000000000000000000000000000000000000000000005",
+ "0xfffffffffffffffffffffffffffffffffffffffeffffee37",
+ "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d",
+ "0xffffffffffffffffffffffffffffffffffffffffffffff13", // max prime
+
+ // N = 4
+ "0x0000000000000001000000000000000000000000000000000000000000000085", // min prime
+ "0x2523648240000001ba344d80000000086121000000000013a700000000000013",
+ "0x7523648240000001ba344d80000000086121000000000013a700000000000017",
+ "0x800000000000000000000000000000000000000000000000000000000000005f",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43", // max prime
+#endif
+
+#if MCL_MAX_BIT_SIZE >= 384
+ // N = 6
+ "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
+ "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff",
+#endif
+
+#if MCL_MAX_BIT_SIZE >= 521
+ // N = 9
+ "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+#endif
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ printf("prime=%s\n", tbl[i]);
+#if 0
+ mpz_class p(tbl[i]);
+ initPairing(mcl::BLS12_381);
+#if 1
+ cybozu::XorShift rg;
+ for (int i = 0; i < 1000; i++) {
+ Fp x, y, z;
+ FpDbl xy;
+ x.setByCSPRNG(rg);
+ y.setByCSPRNG(rg);
+ FpDbl::mulPre(xy, x, y);
+ FpDbl::mod(z, xy);
+ if (z != x * y) {
+ puts("ERR");
+ std::cout << std::hex;
+ PUT(x);
+ PUT(y);
+ PUT(z);
+ PUT(x * y);
+ exit(1);
+ }
+ }
+#else
+ Montgomery mont(p);
+ mpz_class x("19517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ffc", 16);
+ mpz_class y("139517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ff", 16);
+ std::cout << std::hex;
+ PUT(x);
+ PUT(y);
+ mpz_class z;
+ mont.mul(z, x, y);
+ PUT(z);
+ Fp x1, y1, z1;
+ puts("aaa");
+ memcpy(&x1, mcl::gmp::getUnit(x), sizeof(x1));
+ memcpy(&y1, mcl::gmp::getUnit(y), sizeof(y1));
+ z1.clear();
+ x1.dump();
+ y1.dump();
+ Fp::mul(z1, x1, y1);
+ z1.dump();
+#endif
+ exit(1);
+#endif
+ test.run(tbl[i]);
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/paillier_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/paillier_test.cpp
new file mode 100644
index 000000000..31d2b26fc
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/paillier_test.cpp
@@ -0,0 +1,24 @@
+#include <cybozu/test.hpp>
+#include <mcl/paillier.hpp>
+
+CYBOZU_TEST_AUTO(paillier)
+{
+ using namespace mcl::paillier;
+ SecretKey sec;
+ sec.init(2048);
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ mpz_class m1("12342340928409"), m2("23049820498204");
+ mpz_class c1, c2, c3;
+ pub.enc(c1, m1);
+ pub.enc(c2, m2);
+ std::cout << std::hex << "c1=" << c1 << "\nc2=" << c2 << std::endl;
+ pub.add(c3, c1, c2);
+ mpz_class d1, d2, d3;
+ sec.dec(d1, c1);
+ sec.dec(d2, c2);
+ sec.dec(d3, c3);
+ CYBOZU_TEST_EQUAL(m1, d1);
+ CYBOZU_TEST_EQUAL(m2, d2);
+ CYBOZU_TEST_EQUAL(m1 + m2, d3);
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/proj/bn_test/bn_test.vcxproj b/vendor/github.com/dexon-foundation/mcl/test/proj/bn_test/bn_test.vcxproj
new file mode 100644
index 000000000..936e075aa
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/proj/bn_test/bn_test.vcxproj
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{9F935350-2F4C-45FA-A1C2-1D5AA0EADC96}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>bn_test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)debug.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)release.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)test\\bn_test.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/vendor/github.com/dexon-foundation/mcl/test/proj/ec_test/ec_test.vcxproj b/vendor/github.com/dexon-foundation/mcl/test/proj/ec_test/ec_test.vcxproj
new file mode 100644
index 000000000..4bdfda2cb
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/proj/ec_test/ec_test.vcxproj
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{46B6E88E-739A-406B-9F68-BC46C5950FA3}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>ec_test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)debug.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)release.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)test\ec_test.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/vendor/github.com/dexon-foundation/mcl/test/proj/fp_test/fp_test.vcxproj b/vendor/github.com/dexon-foundation/mcl/test/proj/fp_test/fp_test.vcxproj
new file mode 100644
index 000000000..f705982bf
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/proj/fp_test/fp_test.vcxproj
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{51266DE6-B57B-4AE3-B85C-282F170E1728}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>fp_test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)debug.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)release.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)test\\fp_test.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/vendor/github.com/dexon-foundation/mcl/test/proj/fp_tower_test/fp_tower_test.vcxproj b/vendor/github.com/dexon-foundation/mcl/test/proj/fp_tower_test/fp_tower_test.vcxproj
new file mode 100644
index 000000000..d5720678f
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/proj/fp_tower_test/fp_tower_test.vcxproj
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{733B6250-D249-4A99-B2A6-C8FAF6A90E97}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>fp_tower_test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)debug.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)release.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)test\\fp_tower_test.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/vendor/github.com/dexon-foundation/mcl/test/she_c256_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/she_c256_test.cpp
new file mode 100644
index 000000000..3e458b623
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/she_c256_test.cpp
@@ -0,0 +1,2 @@
+#define MCLBN_FP_UNIT_SIZE 4
+#include "she_c_test.hpp"
diff --git a/vendor/github.com/dexon-foundation/mcl/test/she_c384_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/she_c384_test.cpp
new file mode 100644
index 000000000..5c7bd9882
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/she_c384_test.cpp
@@ -0,0 +1,2 @@
+#define MCLBN_FP_UNIT_SIZE 6
+#include "she_c_test.hpp"
diff --git a/vendor/github.com/dexon-foundation/mcl/test/she_c_test.hpp b/vendor/github.com/dexon-foundation/mcl/test/she_c_test.hpp
new file mode 100644
index 000000000..8287c0e0a
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/she_c_test.hpp
@@ -0,0 +1,535 @@
+#include <mcl/she.h>
+#define CYBOZU_TEST_DISABLE_AUTO_RUN
+#include <cybozu/test.hpp>
+#include <cybozu/option.hpp>
+#include <fstream>
+
+const size_t hashSize = 1 << 10;
+const size_t tryNum = 1024;
+
+CYBOZU_TEST_AUTO(init)
+{
+ int curve;
+#if MCLBN_FP_UNIT_SIZE == 4
+ curve = MCL_BN254;
+#elif MCLBN_FP_UNIT_SIZE == 6
+// curve = MCL_BN381_1;
+ curve = MCL_BLS12_381;
+#elif MCLBN_FP_UNIT_SIZE == 8
+ curve = MCL_BN462;
+#endif
+ int ret;
+ ret = sheInit(curve, MCLBN_COMPILED_TIME_VAR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ ret = sheSetRangeForDLP(hashSize);
+ CYBOZU_TEST_EQUAL(ret, 0);
+}
+
+CYBOZU_TEST_AUTO(encDec)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ int64_t m = 123;
+ sheCipherTextG1 c1;
+ sheCipherTextG2 c2;
+ sheCipherTextGT ct;
+ sheEncG1(&c1, &pub, m);
+ sheEncG2(&c2, &pub, m);
+ sheEncGT(&ct, &pub, m);
+
+ int64_t dec;
+ CYBOZU_TEST_EQUAL(sheDecG1(&dec, &sec, &c1), 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+ dec = 0;
+ CYBOZU_TEST_EQUAL(sheDecG1ViaGT(&dec, &sec, &c1), 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+ dec = 0;
+ CYBOZU_TEST_EQUAL(sheDecG2(&dec, &sec, &c2), 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+ dec = 0;
+ CYBOZU_TEST_EQUAL(sheDecG2ViaGT(&dec, &sec, &c2), 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+ dec = 0;
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+
+ for (int m = -3; m < 3; m++) {
+ sheEncG1(&c1, &pub, m);
+ CYBOZU_TEST_EQUAL(sheIsZeroG1(&sec, &c1), m == 0);
+ sheEncG2(&c2, &pub, m);
+ CYBOZU_TEST_EQUAL(sheIsZeroG2(&sec, &c2), m == 0);
+ sheEncGT(&ct, &pub, m);
+ CYBOZU_TEST_EQUAL(sheIsZeroGT(&sec, &ct), m == 0);
+ }
+}
+
+CYBOZU_TEST_AUTO(addMul)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ int64_t m1 = 12;
+ int64_t m2 = -9;
+ sheCipherTextG1 c1;
+ sheCipherTextG2 c2;
+ sheCipherTextGT ct;
+ sheEncG1(&c1, &pub, m1);
+ sheEncG2(&c2, &pub, m2);
+ sheMul(&ct, &c1, &c2);
+
+ int64_t dec;
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, m1 * m2);
+}
+
+CYBOZU_TEST_AUTO(allOp)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ int64_t m1 = 12;
+ int64_t m2 = -9;
+ int64_t m3 = 12;
+ int64_t m4 = -9;
+ int64_t dec;
+ sheCipherTextG1 c11, c12;
+ sheCipherTextG2 c21, c22;
+ sheCipherTextGT ct;
+
+ sheEncG1(&c11, &pub, m1);
+ sheNegG1(&c12, &c11);
+ CYBOZU_TEST_EQUAL(sheDecG1(&dec, &sec, &c12), 0);
+ CYBOZU_TEST_EQUAL(dec, -m1);
+
+ sheEncG1(&c12, &pub, m2);
+ sheSubG1(&c11, &c11, &c12); // m1 - m2
+ sheMulG1(&c11, &c11, 4); // 4 * (m1 - m2)
+
+ sheEncG2(&c21, &pub, m3);
+ sheNegG2(&c22, &c21);
+ CYBOZU_TEST_EQUAL(sheDecG2(&dec, &sec, &c22), 0);
+ CYBOZU_TEST_EQUAL(dec, -m3);
+ sheEncG2(&c22, &pub, m4);
+ sheSubG2(&c21, &c21, &c22); // m3 - m4
+ sheMulG2(&c21, &c21, -5); // -5 * (m3 - m4)
+ sheMul(&ct, &c11, &c21); // -20 * (m1 - m2) * (m3 - m4)
+ sheAddGT(&ct, &ct, &ct); // -40 * (m1 - m2) * (m3 - m4)
+ sheMulGT(&ct, &ct, -4); // 160 * (m1 - m2) * (m3 - m4)
+
+ int64_t t = 160 * (m1 - m2) * (m3 - m4);
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, t);
+
+ sheCipherTextGT ct2;
+ sheNegGT(&ct2, &ct);
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct2), 0);
+ CYBOZU_TEST_EQUAL(dec, -t);
+}
+
+CYBOZU_TEST_AUTO(rerand)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ int64_t m1 = 12;
+ int64_t m2 = -9;
+ int64_t m3 = 12;
+ sheCipherTextG1 c1;
+ sheCipherTextG2 c2;
+ sheCipherTextGT ct1, ct2;
+ sheEncG1(&c1, &pub, m1);
+ sheReRandG1(&c1, &pub);
+
+ sheEncG2(&c2, &pub, m2);
+ sheReRandG2(&c2, &pub);
+
+ sheEncGT(&ct1, &pub, m3);
+ sheReRandGT(&ct1, &pub);
+
+ sheMul(&ct2, &c1, &c2);
+ sheReRandGT(&ct2, &pub);
+ sheAddGT(&ct1, &ct1, &ct2);
+
+ int64_t dec;
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct1), 0);
+ CYBOZU_TEST_EQUAL(dec, m1 * m2 + m3);
+}
+
+CYBOZU_TEST_AUTO(serialize)
+{
+ sheSecretKey sec1, sec2;
+ sheSecretKeySetByCSPRNG(&sec1);
+ shePublicKey pub1, pub2;
+ sheGetPublicKey(&pub1, &sec1);
+
+ char buf1[4096], buf2[4096];
+ size_t n1, n2;
+ size_t r, size;
+ const size_t sizeofFr = mclBn_getFrByteSize();
+ const size_t sizeofFp = mclBn_getG1ByteSize();
+
+ size = sizeofFr * 2;
+ n1 = sheSecretKeySerialize(buf1, sizeof(buf1), &sec1);
+ CYBOZU_TEST_EQUAL(n1, size);
+ r = sheSecretKeyDeserialize(&sec2, buf1, n1);
+ CYBOZU_TEST_EQUAL(r, n1);
+ n2 = sheSecretKeySerialize(buf2, sizeof(buf2), &sec2);
+ CYBOZU_TEST_EQUAL(n2, size);
+ CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2);
+
+ size = sizeofFp * 3;
+ n1 = shePublicKeySerialize(buf1, sizeof(buf1), &pub1);
+ CYBOZU_TEST_EQUAL(n1, size);
+ r = shePublicKeyDeserialize(&pub2, buf1, n1);
+ CYBOZU_TEST_EQUAL(r, n1);
+ n2 = shePublicKeySerialize(buf2, sizeof(buf2), &pub2);
+ CYBOZU_TEST_EQUAL(n2, size);
+ CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2);
+
+ int m = 123;
+ sheCipherTextG1 c11, c12;
+ sheCipherTextG2 c21, c22;
+ sheCipherTextGT ct1, ct2;
+ sheEncG1(&c11, &pub2, m);
+ sheEncG2(&c21, &pub2, m);
+ sheEncGT(&ct1, &pub2, m);
+
+ size = sizeofFp * 2;
+ n1 = sheCipherTextG1Serialize(buf1, sizeof(buf1), &c11);
+ CYBOZU_TEST_EQUAL(n1, size);
+ r = sheCipherTextG1Deserialize(&c12, buf1, n1);
+ CYBOZU_TEST_EQUAL(r, n1);
+ n2 = sheCipherTextG1Serialize(buf2, sizeof(buf2), &c12);
+ CYBOZU_TEST_EQUAL(n2, size);
+ CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2);
+
+ size = sizeofFp * 4;
+ n1 = sheCipherTextG2Serialize(buf1, sizeof(buf1), &c21);
+ CYBOZU_TEST_EQUAL(n1, size);
+ r = sheCipherTextG2Deserialize(&c22, buf1, n1);
+ CYBOZU_TEST_EQUAL(r, n1);
+ n2 = sheCipherTextG2Serialize(buf2, sizeof(buf2), &c22);
+ CYBOZU_TEST_EQUAL(n2, size);
+ CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2);
+
+ size = sizeofFp * 12 * 4;
+ n1 = sheCipherTextGTSerialize(buf1, sizeof(buf1), &ct1);
+ CYBOZU_TEST_EQUAL(n1, size);
+ r = sheCipherTextGTDeserialize(&ct2, buf1, n1);
+ CYBOZU_TEST_EQUAL(r, n1);
+ n2 = sheCipherTextGTSerialize(buf2, sizeof(buf2), &ct2);
+ CYBOZU_TEST_EQUAL(n2, size);
+ CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2);
+}
+
+CYBOZU_TEST_AUTO(convert)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+ sheCipherTextGT ct;
+ const int64_t m = 123;
+ int64_t dec;
+ sheCipherTextG1 c1;
+ sheEncG1(&c1, &pub, m);
+ CYBOZU_TEST_EQUAL(sheDecG1(&dec, &sec, &c1), 0);
+ CYBOZU_TEST_EQUAL(dec, 123);
+ sheConvertG1(&ct, &pub, &c1);
+ dec = 0;
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, 123);
+
+ sheCipherTextG2 c2;
+ sheEncG2(&c2, &pub, m);
+ CYBOZU_TEST_EQUAL(sheDecG2(&dec, &sec, &c2), 0);
+ CYBOZU_TEST_EQUAL(dec, 123);
+ sheConvertG2(&ct, &pub, &c2);
+ dec = 0;
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, 123);
+}
+
+CYBOZU_TEST_AUTO(precomputed)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+ shePrecomputedPublicKey *ppub = shePrecomputedPublicKeyCreate();
+ CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyInit(ppub, &pub), 0);
+ const int64_t m = 152;
+ sheCipherTextG1 c1;
+ sheCipherTextG2 c2;
+ sheCipherTextGT ct;
+ int64_t dec = 0;
+ CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyEncG1(&c1, ppub, m), 0);
+ CYBOZU_TEST_EQUAL(sheDecG1(&dec, &sec, &c1), 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+ dec = 0;
+ CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyEncG2(&c2, ppub, m), 0);
+ CYBOZU_TEST_EQUAL(sheDecG2(&dec, &sec, &c2), 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+ dec = 0;
+ CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyEncGT(&ct, ppub, m), 0);
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+
+ shePrecomputedPublicKeyDestroy(ppub);
+}
+
+template<class CT, class PK, class encWithZkpFunc, class decFunc, class verifyFunc>
+void ZkpBinTest(const sheSecretKey *sec, const PK *pub, encWithZkpFunc encWithZkp, decFunc dec, verifyFunc verify)
+{
+ CT c;
+ sheZkpBin zkp;
+ for (int m = 0; m < 2; m++) {
+ CYBOZU_TEST_EQUAL(encWithZkp(&c, &zkp, pub, m), 0);
+ mclInt mDec;
+ CYBOZU_TEST_EQUAL(dec(&mDec, sec, &c), 0);
+ CYBOZU_TEST_EQUAL(mDec, m);
+ CYBOZU_TEST_EQUAL(verify(pub, &c, &zkp), 1);
+ {
+ char buf[4096];
+ size_t n = sheZkpBinSerialize(buf, sizeof(buf), &zkp);
+ CYBOZU_TEST_EQUAL(n, mclBn_getFrByteSize() * CYBOZU_NUM_OF_ARRAY(zkp.d));
+ sheZkpBin zkp2;
+ size_t r = sheZkpBinDeserialize(&zkp2, buf, n);
+ CYBOZU_TEST_EQUAL(r, n);
+ CYBOZU_TEST_EQUAL(r, n);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(zkp.d); i++) {
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&zkp.d[i], &zkp2.d[i]));
+ }
+ }
+ zkp.d[0].d[0]++;
+ CYBOZU_TEST_EQUAL(verify(pub, &c, &zkp), 0);
+ }
+ CYBOZU_TEST_ASSERT(encWithZkp(&c, &zkp, pub, 2) != 0);
+}
+
+CYBOZU_TEST_AUTO(ZkpBin)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ ZkpBinTest<sheCipherTextG1>(&sec, &pub, sheEncWithZkpBinG1, sheDecG1, sheVerifyZkpBinG1);
+ ZkpBinTest<sheCipherTextG2>(&sec, &pub, sheEncWithZkpBinG2, sheDecG2, sheVerifyZkpBinG2);
+
+ shePrecomputedPublicKey *ppub = shePrecomputedPublicKeyCreate();
+ CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyInit(ppub, &pub), 0);
+
+ ZkpBinTest<sheCipherTextG1>(&sec, ppub, shePrecomputedPublicKeyEncWithZkpBinG1, sheDecG1, shePrecomputedPublicKeyVerifyZkpBinG1);
+ ZkpBinTest<sheCipherTextG2>(&sec, ppub, shePrecomputedPublicKeyEncWithZkpBinG2, sheDecG2, shePrecomputedPublicKeyVerifyZkpBinG2);
+
+ shePrecomputedPublicKeyDestroy(ppub);
+}
+
+template<class PK, class encWithZkpFunc, class verifyFunc>
+void ZkpBinEqTest(const sheSecretKey *sec, const PK *pub, encWithZkpFunc encWithZkp, verifyFunc verify)
+{
+ sheCipherTextG1 c1;
+ sheCipherTextG2 c2;
+ sheZkpBinEq zkp;
+ for (int m = 0; m < 2; m++) {
+ CYBOZU_TEST_EQUAL(encWithZkp(&c1, &c2, &zkp, pub, m), 0);
+ mclInt mDec = -1;
+ CYBOZU_TEST_EQUAL(sheDecG1(&mDec, sec, &c1), 0);
+ CYBOZU_TEST_EQUAL(mDec, m);
+ mDec = -1;
+ CYBOZU_TEST_EQUAL(sheDecG2(&mDec, sec, &c2), 0);
+ CYBOZU_TEST_EQUAL(mDec, m);
+ CYBOZU_TEST_EQUAL(verify(pub, &c1, &c2, &zkp), 1);
+ {
+ char buf[2048];
+ size_t n = sheZkpBinEqSerialize(buf, sizeof(buf), &zkp);
+ CYBOZU_TEST_EQUAL(n, mclBn_getFrByteSize() * CYBOZU_NUM_OF_ARRAY(zkp.d));
+ sheZkpBinEq zkp2;
+ size_t r = sheZkpBinEqDeserialize(&zkp2, buf, n);
+ CYBOZU_TEST_EQUAL(r, n);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(zkp.d); i++) {
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&zkp.d[i], &zkp2.d[i]));
+ }
+ }
+ zkp.d[0].d[0]++;
+ CYBOZU_TEST_EQUAL(verify(pub, &c1, &c2, &zkp), 0);
+ }
+ CYBOZU_TEST_ASSERT(encWithZkp(&c1, &c2, &zkp, pub, 2) != 0);
+}
+
+CYBOZU_TEST_AUTO(ZkpBinEq)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ ZkpBinEqTest(&sec, &pub, sheEncWithZkpBinEq, sheVerifyZkpBinEq);
+
+ shePrecomputedPublicKey *ppub = shePrecomputedPublicKeyCreate();
+ CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyInit(ppub, &pub), 0);
+
+ ZkpBinEqTest(&sec, ppub, shePrecomputedPublicKeyEncWithZkpBinEq, shePrecomputedPublicKeyVerifyZkpBinEq);
+
+ shePrecomputedPublicKeyDestroy(ppub);
+}
+
+template<class PK, class encWithZkpFunc, class verifyFunc>
+void ZkpEqTest(const sheSecretKey *sec, const PK *pub, encWithZkpFunc encWithZkp, verifyFunc verify)
+{
+ sheCipherTextG1 c1;
+ sheCipherTextG2 c2;
+ sheZkpEq zkp;
+ for (int m = -5; m < 5; m++) {
+ CYBOZU_TEST_EQUAL(encWithZkp(&c1, &c2, &zkp, pub, m), 0);
+ mclInt mDec = -1;
+ CYBOZU_TEST_EQUAL(sheDecG1(&mDec, sec, &c1), 0);
+ CYBOZU_TEST_EQUAL(mDec, m);
+ mDec = -1;
+ CYBOZU_TEST_EQUAL(sheDecG2(&mDec, sec, &c2), 0);
+ CYBOZU_TEST_EQUAL(mDec, m);
+ CYBOZU_TEST_EQUAL(verify(pub, &c1, &c2, &zkp), 1);
+ {
+ char buf[2048];
+ size_t n = sheZkpEqSerialize(buf, sizeof(buf), &zkp);
+ CYBOZU_TEST_EQUAL(n, mclBn_getFrByteSize() * CYBOZU_NUM_OF_ARRAY(zkp.d));
+ sheZkpEq zkp2;
+ size_t r = sheZkpEqDeserialize(&zkp2, buf, n);
+ CYBOZU_TEST_EQUAL(r, n);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(zkp.d); i++) {
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&zkp.d[i], &zkp2.d[i]));
+ }
+ }
+ zkp.d[0].d[0]++;
+ CYBOZU_TEST_EQUAL(verify(pub, &c1, &c2, &zkp), 0);
+ }
+}
+
+CYBOZU_TEST_AUTO(ZkpEq)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ ZkpEqTest(&sec, &pub, sheEncWithZkpEq, sheVerifyZkpEq);
+
+ shePrecomputedPublicKey *ppub = shePrecomputedPublicKeyCreate();
+ CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyInit(ppub, &pub), 0);
+
+ ZkpEqTest(&sec, ppub, shePrecomputedPublicKeyEncWithZkpEq, shePrecomputedPublicKeyVerifyZkpEq);
+
+ shePrecomputedPublicKeyDestroy(ppub);
+}
+
+CYBOZU_TEST_AUTO(finalExp)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+ const int64_t m11 = 5;
+ const int64_t m12 = 7;
+ const int64_t m21 = -3;
+ const int64_t m22 = 9;
+ sheCipherTextG1 c11, c12;
+ sheCipherTextG2 c21, c22;
+ sheCipherTextGT ct1, ct2;
+ sheCipherTextGT ct;
+ sheEncG1(&c11, &pub, m11);
+ sheEncG1(&c12, &pub, m12);
+ sheEncG2(&c21, &pub, m21);
+ sheEncG2(&c22, &pub, m22);
+
+ int64_t dec;
+ // sheMul = sheMulML + sheFinalExpGT
+ sheMul(&ct1, &c11, &c21);
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct1), 0);
+ CYBOZU_TEST_EQUAL(dec, m11 * m21);
+
+ sheMulML(&ct1, &c11, &c21);
+ sheFinalExpGT(&ct, &ct1);
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, m11 * m21);
+
+ sheMulML(&ct2, &c12, &c22);
+ sheFinalExpGT(&ct, &ct2);
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, m12 * m22);
+
+ /*
+ Mul(c11, c21) + Mul(c21, c22)
+ = finalExp(ML(c11, c21) + ML(c21, c22))
+ */
+ sheAddGT(&ct, &ct1, &ct2);
+ sheFinalExpGT(&ct, &ct);
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, (m11 * m21) + (m12 * m22));
+}
+
+int g_hashBitSize = 8;
+std::string g_tableName;
+
+CYBOZU_TEST_AUTO(saveLoad)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+ const size_t hashSize = 1 << g_hashBitSize;
+ const size_t byteSizePerEntry = 8;
+ sheSetRangeForGTDLP(hashSize);
+ std::string buf;
+ buf.resize(hashSize * byteSizePerEntry + 1024);
+ const size_t n1 = sheSaveTableForGTDLP(&buf[0], buf.size());
+ CYBOZU_TEST_ASSERT(n1 > 0);
+ if (!g_tableName.empty()) {
+ printf("use table=%s\n", g_tableName.c_str());
+ std::ofstream ofs(g_tableName.c_str(), std::ios::binary);
+ ofs.write(buf.c_str(), n1);
+ }
+ const int64_t m = hashSize - 1;
+ sheCipherTextGT ct;
+ CYBOZU_TEST_ASSERT(sheEncGT(&ct, &pub, m) == 0);
+ sheSetRangeForGTDLP(1);
+ sheSetTryNum(1);
+ int64_t dec = 0;
+ CYBOZU_TEST_ASSERT(sheDecGT(&dec, &sec, &ct) != 0);
+ if (!g_tableName.empty()) {
+ std::ifstream ifs(g_tableName.c_str(), std::ios::binary);
+ buf.clear();
+ buf.resize(n1);
+ ifs.read(&buf[0], n1);
+ }
+ const size_t n2 = sheLoadTableForGTDLP(&buf[0], n1);
+ CYBOZU_TEST_ASSERT(n2 > 0);
+ CYBOZU_TEST_ASSERT(sheDecGT(&dec, &sec, &ct) == 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+}
+
+int main(int argc, char *argv[])
+ try
+{
+ cybozu::Option opt;
+ opt.appendOpt(&g_hashBitSize, 8, "bit", ": hashBitSize");
+ opt.appendOpt(&g_tableName, "", "f", ": table name");
+ opt.appendHelp("h", ": show this message");
+ if (!opt.parse(argc, argv)) {
+ opt.usage();
+ return 1;
+ }
+ return cybozu::test::autoRun.run(argc, argv);
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+ return 1;
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/she_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/she_test.cpp
new file mode 100644
index 000000000..9292c35f4
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/she_test.cpp
@@ -0,0 +1,756 @@
+#define PUT(x) std::cout << #x << "=" << (x) << std::endl;
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/xorshift.hpp>
+#include <fstream>
+#include <time.h>
+#include <mcl/she.hpp>
+#include <mcl/ecparam.hpp> // for secp192k1
+
+using namespace mcl::she;
+
+SecretKey g_sec;
+
+CYBOZU_TEST_AUTO(log)
+{
+#if MCLBN_FP_UNIT_SIZE == 4
+ const mcl::CurveParam& cp = mcl::BN254;
+ puts("BN254");
+#elif MCLBN_FP_UNIT_SIZE == 6
+ const mcl::CurveParam& cp = mcl::BN381_1;
+ puts("BN381_1");
+#elif MCLBN_FP_UNIT_SIZE == 8
+ const mcl::CurveParam& cp = mcl::BN462;
+ puts("BN462");
+#endif
+ init(cp);
+ G1 P;
+ hashAndMapToG1(P, "abc");
+ for (int i = -5; i < 5; i++) {
+ G1 iP;
+ G1::mul(iP, P, i);
+ CYBOZU_TEST_EQUAL(mcl::she::local::log(P, iP), i);
+ }
+}
+
+//#define PAPER
+#ifdef PAPER
+double clk2msec(const cybozu::CpuClock& clk, int n)
+{
+ const double rate = (1 / 3.4e9) * 1.e3; // 3.4GHz
+ return clk.getClock() / (double)clk.getCount() / n * rate;
+}
+
+CYBOZU_TEST_AUTO(bench2)
+{
+ puts("msec");
+ setTryNum(1 << 16);
+ useDecG1ViaGT(true);
+ useDecG2ViaGT(true);
+#if 0
+ setRangeForDLP(1 << 21);
+#else
+ {
+ const char *tblName = "../she-dlp-table/she-dlp-0-20-gt.bin";
+ std::ifstream ifs(tblName, std::ios::binary);
+ getHashTableGT().load(ifs);
+ }
+#endif
+ SecretKey sec;
+ sec.setByCSPRNG();
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ PrecomputedPublicKey ppub;
+ ppub.init(pub);
+ const int C = 500;
+ double t1, t2;
+ int64_t m = (1ll << 31) - 12345;
+ CipherTextG1 c1, d1;
+ CipherTextG2 c2, d2;
+ CipherTextGT ct, dt;
+ CYBOZU_BENCH_C("", C, ppub.enc, c1, m);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), m);
+
+ CYBOZU_BENCH_C("", C, ppub.enc, c2, m);
+ t2 = clk2msec(cybozu::bench::g_clk, C);
+ CYBOZU_TEST_EQUAL(sec.dec(c2), m);
+ printf("Enc G1 %.2e\n", t1);
+ printf("Enc G2 %.2e\n", t2);
+ printf("Enc L1(G1+G2) %.2e\n", t1 + t2);
+
+ CYBOZU_BENCH_C("", C, ppub.enc, ct, m);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ CYBOZU_TEST_EQUAL(sec.dec(ct), m);
+ printf("Enc L2 %.2e\n", t1);
+
+ CYBOZU_BENCH_C("", C, sec.dec, c1);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ printf("Dec L1 %.2e\n", t1);
+
+ CYBOZU_BENCH_C("", C, sec.dec, ct);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ printf("Dec L2 %.2e\n", t1);
+
+ pub.enc(ct, 1234);
+ CYBOZU_BENCH_C("", C, sec.dec, ct);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ printf("Dec L2(small) %.2e\n", t1);
+
+ CYBOZU_BENCH_C("", C, add, d1, d1, c1);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+
+ CYBOZU_BENCH_C("", C, add, d2, d2, c2);
+ t2 = clk2msec(cybozu::bench::g_clk, C);
+ printf("Add G1 %.2e\n", t1);
+ printf("Add G2 %.2e\n", t2);
+ printf("Add L1(G1+G2) %.2e\n", t1 + t2);
+
+ CYBOZU_BENCH_C("", C, add, dt, dt, ct);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ printf("Add L2 %.2e\n", t1);
+
+ CYBOZU_BENCH_C("", C, mul, ct, c1, c2);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ printf("Mul %.2e\n", t1);
+
+ CYBOZU_BENCH_C("", C, ppub.reRand, c1);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ CYBOZU_BENCH_C("", C, ppub.reRand, c2);
+ t2 = clk2msec(cybozu::bench::g_clk, C);
+ printf("ReRand G1 %.2e\n", t1);
+ printf("ReRand G2 %.2e\n", t2);
+ printf("ReRand L1(G1+G2) %.2e\n", t1 + t2);
+
+ CYBOZU_BENCH_C("", C, ppub.reRand, ct);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ printf("ReRand L2 %.2e\n", t1);
+}
+#endif
+
+template<class G, class HashTbl>
+void GAHashTableTest(int maxSize, int tryNum, const G& P, const HashTbl& hashTbl)
+{
+ for (int i = -maxSize; i <= maxSize; i++) {
+ G xP;
+ G::mul(xP, P, i);
+ CYBOZU_TEST_EQUAL(hashTbl.basicLog(xP), i);
+ }
+ for (int i = -maxSize * tryNum; i <= maxSize * tryNum; i++) {
+ G xP;
+ G::mul(xP, P, i);
+ CYBOZU_TEST_EQUAL(hashTbl.log(xP), i);
+ }
+}
+
+template<class G>
+void HashTableTest(const G& P)
+{
+ mcl::she::local::HashTable<G> hashTbl, hashTbl2;
+ const int maxSize = 100;
+ const int tryNum = 3;
+ hashTbl.init(P, maxSize, tryNum);
+ GAHashTableTest(maxSize, tryNum, P, hashTbl);
+ std::stringstream ss;
+ hashTbl.save(ss);
+ hashTbl2.load(ss);
+ GAHashTableTest(maxSize, tryNum, P, hashTbl2);
+}
+
+CYBOZU_TEST_AUTO(HashTable)
+{
+ G1 P;
+ hashAndMapToG1(P, "abc");
+ G2 Q;
+ hashAndMapToG2(Q, "abc");
+ HashTableTest(P);
+ HashTableTest(Q);
+}
+
+template<class HashTbl>
+void GTHashTableTest(int maxSize, int tryNum, const GT& g, const HashTbl& hashTbl)
+{
+ for (int i = -maxSize; i <= maxSize; i++) {
+ GT gx;
+ GT::pow(gx, g, i);
+ CYBOZU_TEST_EQUAL(hashTbl.basicLog(gx), i);
+ }
+ for (int i = -maxSize * tryNum; i <= maxSize * tryNum; i++) {
+ GT gx;
+ GT::pow(gx, g, i);
+ CYBOZU_TEST_EQUAL(hashTbl.log(gx), i);
+ }
+}
+
+CYBOZU_TEST_AUTO(GTHashTable)
+{
+ mcl::she::local::HashTable<GT, false> hashTbl, hashTbl2;
+ GT g;
+ {
+ G1 P;
+ hashAndMapToG1(P, "abc");
+ G2 Q;
+ hashAndMapToG2(Q, "abc");
+ pairing(g, P, Q);
+ }
+ const int maxSize = 100;
+ const int tryNum = 3;
+ hashTbl.init(g, maxSize, tryNum);
+ GTHashTableTest(maxSize, tryNum, g, hashTbl);
+ std::stringstream ss;
+ hashTbl.save(ss);
+ hashTbl2.load(ss);
+ GTHashTableTest(maxSize, tryNum, g, hashTbl2);
+}
+
+CYBOZU_TEST_AUTO(enc_dec)
+{
+ SecretKey& sec = g_sec;
+ sec.setByCSPRNG();
+ setRangeForDLP(1024);
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ CipherText c;
+ for (int i = -5; i < 5; i++) {
+ pub.enc(c, i);
+ CYBOZU_TEST_EQUAL(sec.dec(c), i);
+ pub.reRand(c);
+ CYBOZU_TEST_EQUAL(sec.dec(c), i);
+ }
+ PrecomputedPublicKey ppub;
+ ppub.init(pub);
+ CipherTextG1 c1;
+ CipherTextG2 c2;
+ CipherTextGT ct1, ct2;
+ for (int i = -5; i < 5; i++) {
+ pub.enc(ct1, i);
+ CYBOZU_TEST_EQUAL(sec.dec(ct1), i);
+ CYBOZU_TEST_EQUAL(sec.isZero(ct1), i == 0);
+ ppub.enc(ct2, i);
+ CYBOZU_TEST_EQUAL(sec.dec(ct2), i);
+ ppub.enc(c1, i);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), i);
+ CYBOZU_TEST_EQUAL(sec.decViaGT(c1), i);
+ CYBOZU_TEST_EQUAL(sec.isZero(c1), i == 0);
+ ct1.clear();
+ pub.convert(ct1, c1);
+ CYBOZU_TEST_EQUAL(sec.dec(ct1), i);
+ ppub.enc(c2, i);
+ CYBOZU_TEST_EQUAL(sec.dec(c2), i);
+ CYBOZU_TEST_EQUAL(sec.decViaGT(c2), i);
+ CYBOZU_TEST_EQUAL(sec.isZero(c2), i == 0);
+ ct1.clear();
+ pub.convert(ct1, c2);
+ CYBOZU_TEST_EQUAL(sec.dec(ct1), i);
+ pub.enc(c, i);
+ CYBOZU_TEST_EQUAL(sec.isZero(c), i == 0);
+ }
+}
+
+template<class CT, class PK>
+void ZkpBinTest(const SecretKey& sec, const PK& pub)
+{
+ CT c;
+ ZkpBin zkp;
+ for (int m = 0; m < 2; m++) {
+ pub.encWithZkpBin(c, zkp, m);
+ CYBOZU_TEST_EQUAL(sec.dec(c), m);
+ CYBOZU_TEST_ASSERT(pub.verify(c, zkp));
+ zkp.d_[0] += 1;
+ CYBOZU_TEST_ASSERT(!pub.verify(c, zkp));
+ }
+ CYBOZU_TEST_EXCEPTION(pub.encWithZkpBin(c, zkp, 2), cybozu::Exception);
+}
+CYBOZU_TEST_AUTO(ZkpBin)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ ZkpBinTest<CipherTextG1>(sec, pub);
+ ZkpBinTest<CipherTextG2>(sec, pub);
+
+ PrecomputedPublicKey ppub;
+ ppub.init(pub);
+ ZkpBinTest<CipherTextG1>(sec, ppub);
+ ZkpBinTest<CipherTextG2>(sec, ppub);
+}
+
+template<class PubT>
+void ZkpEqTest(const SecretKey& sec, const PubT& pub)
+{
+ CipherTextG1 c1;
+ CipherTextG2 c2;
+ ZkpEq zkp;
+ for (int m = -4; m < 4; m++) {
+ pub.encWithZkpEq(c1, c2, zkp, m);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), m);
+ CYBOZU_TEST_EQUAL(sec.dec(c2), m);
+ CYBOZU_TEST_ASSERT(pub.verify(c1, c2, zkp));
+ zkp.d_[0] += 1;
+ CYBOZU_TEST_ASSERT(!pub.verify(c1, c2, zkp));
+ }
+}
+
+CYBOZU_TEST_AUTO(ZkpEq)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ PrecomputedPublicKey ppub;
+ ppub.init(pub);
+ ZkpEqTest(sec, pub);
+ ZkpEqTest(sec, ppub);
+}
+
+template<class PK>
+void ZkpBinEqTest(const SecretKey& sec, const PK& pub)
+{
+ CipherTextG1 c1;
+ CipherTextG2 c2;
+ ZkpBinEq zkp;
+ for (int m = 0; m < 2; m++) {
+ pub.encWithZkpBinEq(c1, c2, zkp, m);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), m);
+ CYBOZU_TEST_EQUAL(sec.dec(c2), m);
+ CYBOZU_TEST_ASSERT(pub.verify(c1, c2, zkp));
+ zkp.d_[0] += 1;
+ CYBOZU_TEST_ASSERT(!pub.verify(c1, c2, zkp));
+ }
+ CYBOZU_TEST_EXCEPTION(pub.encWithZkpBinEq(c1, c2, zkp, 2), cybozu::Exception);
+}
+
+CYBOZU_TEST_AUTO(ZkpBinEq)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ ZkpBinEqTest(sec, pub);
+
+ PrecomputedPublicKey ppub;
+ ppub.init(pub);
+ ZkpBinEqTest(sec, ppub);
+}
+
+CYBOZU_TEST_AUTO(add_sub_mul)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ for (int m1 = -5; m1 < 5; m1++) {
+ for (int m2 = -5; m2 < 5; m2++) {
+ CipherText c1, c2, c3;
+ pub.enc(c1, m1);
+ pub.enc(c2, m2);
+ add(c3, c1, c2);
+ CYBOZU_TEST_EQUAL(m1 + m2, sec.dec(c3));
+
+ pub.reRand(c3);
+ CYBOZU_TEST_EQUAL(m1 + m2, sec.dec(c3));
+
+ sub(c3, c1, c2);
+ CYBOZU_TEST_EQUAL(m1 - m2, sec.dec(c3));
+
+ mul(c3, c1, 5);
+ CYBOZU_TEST_EQUAL(m1 * 5, sec.dec(c3));
+ mul(c3, c1, -123);
+ CYBOZU_TEST_EQUAL(m1 * -123, sec.dec(c3));
+
+ mul(c3, c1, c2);
+ CYBOZU_TEST_EQUAL(m1 * m2, sec.dec(c3));
+
+ pub.reRand(c3);
+ CYBOZU_TEST_EQUAL(m1 * m2, sec.dec(c3));
+
+ CipherText::mul(c3, c3, -25);
+ CYBOZU_TEST_EQUAL(m1 * m2 * -25, sec.dec(c3));
+
+ pub.enc(c1, m1, true);
+ CYBOZU_TEST_EQUAL(m1, sec.dec(c1));
+ pub.enc(c2, m2, true);
+ add(c3, c1, c2);
+ CYBOZU_TEST_EQUAL(m1 + m2, sec.dec(c3));
+ }
+ }
+}
+
+CYBOZU_TEST_AUTO(largeEnc)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+
+ Fr x;
+ x.setRand();
+ CipherTextG1 c1, c2;
+ pub.enc(c1, x);
+ const int64_t m = 123;
+ pub.enc(c2, x + m);
+ sub(c1, c1, c2);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), -m);
+
+ pub.enc(c1, 0);
+ mul(c1, c1, x);
+ CYBOZU_TEST_ASSERT(sec.isZero(c1));
+ pub.enc(c1, 1);
+ mul(c1, c1, x);
+ CYBOZU_TEST_ASSERT(!sec.isZero(c1));
+}
+
+CYBOZU_TEST_AUTO(add_mul_add_sub)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ int m[8] = { 1, -2, 3, 4, -5, 6, -7, 8 };
+ CipherText c[8];
+ for (int i = 0; i < 8; i++) {
+ pub.enc(c[i], m[i]);
+ CYBOZU_TEST_EQUAL(sec.dec(c[i]), m[i]);
+ CYBOZU_TEST_ASSERT(!c[i].isMultiplied());
+ CipherText mc;
+ pub.convert(mc, c[i]);
+ CYBOZU_TEST_ASSERT(mc.isMultiplied());
+ CYBOZU_TEST_EQUAL(sec.dec(mc), m[i]);
+ }
+ int ok1 = (m[0] + m[1]) * (m[2] + m[3]);
+ int ok2 = (m[4] + m[5]) * (m[6] + m[7]);
+ int ok = ok1 + ok2;
+ for (int i = 0; i < 4; i++) {
+ c[i * 2].add(c[i * 2 + 1]);
+ CYBOZU_TEST_EQUAL(sec.dec(c[i * 2]), m[i * 2] + m[i * 2 + 1]);
+ }
+ c[0].mul(c[2]);
+ CYBOZU_TEST_EQUAL(sec.dec(c[0]), ok1);
+ c[4].mul(c[6]);
+ CYBOZU_TEST_EQUAL(sec.dec(c[4]), ok2);
+ c[0].add(c[4]);
+ CYBOZU_TEST_EQUAL(sec.dec(c[0]), ok);
+ c[0].sub(c[4]);
+ CYBOZU_TEST_EQUAL(sec.dec(c[0]), ok1);
+}
+
+CYBOZU_TEST_AUTO(finalExp)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ const int64_t m11 = 5;
+ const int64_t m12 = 3;
+ const int64_t m21 = -2;
+ const int64_t m22 = 9;
+ CipherTextG1 c11, c12;
+ CipherTextG2 c21, c22;
+ CipherTextGT ct1, ct2, ct;
+ pub.enc(c11, m11);
+ pub.enc(c12, m12);
+ pub.enc(c21, m21);
+ pub.enc(c22, m22);
+ CipherTextGT::mulML(ct1, c11, c21);
+ CipherTextGT::finalExp(ct, ct1);
+ CYBOZU_TEST_EQUAL(sec.dec(ct), m11 * m21);
+ CipherTextGT::mulML(ct2, c12, c22);
+ CipherTextGT::finalExp(ct, ct2);
+ CYBOZU_TEST_EQUAL(sec.dec(ct), m12 * m22);
+ CipherTextGT::add(ct1, ct1, ct2);
+ CipherTextGT::finalExp(ct1, ct1);
+ CYBOZU_TEST_EQUAL(sec.dec(ct1), (m11 * m21) + (m12 * m22));
+}
+
+CYBOZU_TEST_AUTO(innerProduct)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+
+ cybozu::XorShift rg;
+ const size_t n = 1000;
+ std::vector<int> v1, v2;
+ std::vector<CipherText> c1, c2;
+ v1.resize(n);
+ v2.resize(n);
+ c1.resize(n);
+ c2.resize(n);
+ int innerProduct = 0;
+ for (size_t i = 0; i < n; i++) {
+ v1[i] = rg() % 2;
+ v2[i] = rg() % 2;
+ innerProduct += v1[i] * v2[i];
+ pub.enc(c1[i], v1[i]);
+ pub.enc(c2[i], v2[i]);
+ }
+ CipherText c, t;
+ CipherText::mul(c, c1[0], c2[0]);
+ for (size_t i = 1; i < n; i++) {
+ CipherText::mul(t, c1[i], c2[i]);
+ c.add(t);
+ }
+ CYBOZU_TEST_EQUAL(innerProduct, sec.dec(c));
+}
+
+template<class T>
+T testIo(const T& x)
+{
+ std::stringstream ss;
+ ss << x;
+ T y;
+ ss >> y;
+ CYBOZU_TEST_EQUAL(x, y);
+ return y;
+}
+
+CYBOZU_TEST_AUTO(io)
+{
+ setRangeForDLP(100);
+ int64_t m;
+ for (int i = 0; i < 2; i++) {
+ if (i == 1) {
+ Fp::setIoMode(mcl::IoSerialize);
+ G1::setIoMode(mcl::IoSerialize);
+ }
+ SecretKey sec;
+ sec.setByCSPRNG();
+ testIo(sec);
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ testIo(pub);
+ CipherTextG1 g1;
+ pub.enc(g1, 3);
+ m = sec.dec(testIo(g1));
+ CYBOZU_TEST_EQUAL(m, 3);
+ CipherTextG2 g2;
+ pub.enc(g2, 5);
+ testIo(g2);
+ CipherTextA ca;
+ pub.enc(ca, -4);
+ m = sec.dec(testIo(ca));
+ CYBOZU_TEST_EQUAL(m, -4);
+ CipherTextGT ct;
+ CipherTextGT::mul(ct, g1, g2);
+ m = sec.dec(testIo(ct));
+ CYBOZU_TEST_EQUAL(m, 15);
+ }
+}
+
+#ifndef PAPER
+CYBOZU_TEST_AUTO(bench)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ CipherText c1, c2, c3;
+ CYBOZU_BENCH("enc", pub.enc, c1, 5);
+ pub.enc(c2, 4);
+ CYBOZU_BENCH("add", c1.add, c2);
+ CYBOZU_BENCH("mul", CipherText::mul, c3, c1, c2);
+ pub.enc(c1, 5);
+ pub.enc(c2, 4);
+ c1.mul(c2);
+ CYBOZU_BENCH("dec", sec.dec, c1);
+ c2 = c1;
+ CYBOZU_BENCH("add after mul", c1.add, c2);
+}
+#endif
+
+CYBOZU_TEST_AUTO(saveHash)
+{
+ mcl::she::local::HashTable<G1> hashTbl1, hashTbl2;
+ hashTbl1.init(SHE::P_, 1234, 123);
+ std::stringstream ss;
+ hashTbl1.save(ss);
+ hashTbl2.load(ss);
+ CYBOZU_TEST_ASSERT(hashTbl1 == hashTbl2);
+}
+
+static inline void putK(double t) { printf("%.2e\n", t * 1e-3); }
+
+template<class CT>
+void decBench(const char *msg, int C, const SecretKey& sec, const PublicKey& pub, int64_t (SecretKey::*dec)(const CT& c) const = &SecretKey::dec)
+{
+ int64_t begin = 1 << 20;
+ int64_t end = 1LL << 32;
+ while (begin < end) {
+ CT c;
+ int64_t x = begin - 1;
+ pub.enc(c, x);
+ printf("m=%08x ", (uint32_t)x);
+ CYBOZU_BENCH_C(msg, C, (sec.*dec), c);
+ CYBOZU_TEST_EQUAL((sec.*dec)(c), x);
+ begin *= 2;
+ }
+ int64_t mTbl[] = { -0x80000003ll, 0x80000000ll, 0x80000005ll };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(mTbl); i++) {
+ int64_t m = mTbl[i];
+ CT c;
+ pub.enc(c, m);
+ CYBOZU_TEST_EQUAL((sec.*dec)(c), m);
+ }
+}
+
+#ifndef PAPER
+CYBOZU_TEST_AUTO(hashBench)
+{
+ SecretKey& sec = g_sec;
+ sec.setByCSPRNG();
+ const int C = 500;
+ const size_t hashSize = 1u << 21;
+
+ clock_t begin = clock(), end;
+ setRangeForG1DLP(hashSize);
+ end = clock();
+ printf("init G1 DLP %f\n", double(end - begin) / CLOCKS_PER_SEC);
+ begin = end;
+ setRangeForG2DLP(hashSize);
+ end = clock();
+ printf("init G2 DLP %f\n", double(end - begin) / CLOCKS_PER_SEC);
+ begin = end;
+ setRangeForGTDLP(hashSize);
+ end = clock();
+ printf("init GT DLP %f\n", double(end - begin) / CLOCKS_PER_SEC);
+
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ PrecomputedPublicKey ppub;
+ ppub.init(pub);
+ puts("Kclk");
+ cybozu::bench::setPutCallback(putK);
+ decBench<CipherTextG1>("decG1", C, sec, pub);
+ puts("");
+ decBench<CipherTextG2>("decG2", C, sec, pub);
+ puts("");
+ decBench<CipherTextGT>("decGT", C, sec, pub);
+ puts("");
+ decBench<CipherTextG1>("decG1ViaGT", C, sec, pub, &SecretKey::decViaGT);
+ puts("");
+ decBench<CipherTextG2>("decG2ViaGT", C, sec, pub, &SecretKey::decViaGT);
+
+ G1 P, P2;
+ G2 Q, Q2;
+ GT e, e2;
+ mpz_class mr;
+ {
+ Fr r;
+ r.setRand();
+ mr = r.getMpz();
+ }
+ hashAndMapToG1(P, "abc");
+ hashAndMapToG2(Q, "abc");
+ pairing(e, P, Q);
+ P2.clear();
+ Q2.clear();
+ e2 = 1;
+
+ printf("large m\n");
+ CYBOZU_BENCH_C("G1::add ", C, G1::add, P2, P2, P);
+ CYBOZU_BENCH_C("G1::mul ", C, G1::mul, P, P, mr);
+ CYBOZU_BENCH_C("G2::add ", C, G2::add, Q2, Q2, Q);
+ CYBOZU_BENCH_C("G2::mul ", C, G2::mul, Q, Q, mr);
+ CYBOZU_BENCH_C("GT::mul ", C, GT::mul, e2, e2, e);
+ CYBOZU_BENCH_C("GT::pow ", C, GT::pow, e, e, mr);
+ CYBOZU_BENCH_C("G1window", C, SHE::PhashTbl_.mulByWindowMethod, P2, mr);
+ CYBOZU_BENCH_C("G2window", C, SHE::QhashTbl_.mulByWindowMethod, Q2, mr);
+ CYBOZU_BENCH_C("GTwindow", C, SHE::ePQhashTbl_.mulByWindowMethod, e, mr);
+#if 1
+ typedef mcl::GroupMtoA<Fp12> AG;
+ mcl::fp::WindowMethod<AG> wm;
+ wm.init(static_cast<AG&>(e), Fr::getBitSize(), 10);
+ for (int i = 0; i < 100; i++) {
+ GT t1, t2;
+ GT::pow(t1, e, i);
+ wm.mul(static_cast<AG&>(t2), i);
+ CYBOZU_TEST_EQUAL(t1, t2);
+ }
+// CYBOZU_BENCH_C("GTwindow", C, wm.mul, static_cast<AG&>(e), mr);
+#endif
+
+ CYBOZU_BENCH_C("miller ", C, millerLoop, e, P, Q);
+ CYBOZU_BENCH_C("finalExp", C, finalExp, e, e);
+ CYBOZU_BENCH_C("precomML", C, precomputedMillerLoop, e, P, SHE::Qcoeff_);
+
+ CipherTextG1 c1;
+ CipherTextG2 c2;
+ CipherTextGT ct;
+
+ int m = int(hashSize - 1);
+ printf("small m = %d\n", m);
+ CYBOZU_BENCH_C("G1::mul ", C, G1::mul, P, P, m);
+ CYBOZU_BENCH_C("G2::mul ", C, G2::mul, Q, Q, m);
+ CYBOZU_BENCH_C("GT::pow ", C, GT::pow, e, e, m);
+ CYBOZU_BENCH_C("G1window", C, SHE::PhashTbl_.mulByWindowMethod, P2, m);
+ CYBOZU_BENCH_C("G2window", C, SHE::QhashTbl_.mulByWindowMethod, Q2, m);
+ CYBOZU_BENCH_C("GTwindow", C, SHE::ePQhashTbl_.mulByWindowMethod, e, m);
+// CYBOZU_BENCH_C("GTwindow", C, wm.mul, static_cast<AG&>(e), m);
+
+ CYBOZU_BENCH_C("encG1 ", C, pub.enc, c1, m);
+ CYBOZU_BENCH_C("encG2 ", C, pub.enc, c2, m);
+ CYBOZU_BENCH_C("encGT ", C, pub.enc, ct, m);
+ CYBOZU_BENCH_C("encG1pre", C, ppub.enc, c1, m);
+ CYBOZU_BENCH_C("encG2pre", C, ppub.enc, c2, m);
+ CYBOZU_BENCH_C("encGTpre", C, ppub.enc, ct, m);
+
+ CYBOZU_BENCH_C("decG1 ", C, sec.dec, c1);
+ CYBOZU_BENCH_C("decG2 ", C, sec.dec, c2);
+ CYBOZU_BENCH_C("degGT ", C, sec.dec, ct);
+
+ CYBOZU_BENCH_C("CT:mul ", C, CipherTextGT::mul, ct, c1, c2);
+ CYBOZU_BENCH_C("CT:mulML", C, CipherTextGT::mulML, ct, c1, c2);
+ CYBOZU_BENCH_C("CT:finalExp", C, CipherTextGT::finalExp, ct, ct);
+
+ CYBOZU_BENCH_C("addG1 ", C, CipherTextG1::add, c1, c1, c1);
+ CYBOZU_BENCH_C("addG2 ", C, CipherTextG2::add, c2, c2, c2);
+ CYBOZU_BENCH_C("addGT ", C, CipherTextGT::add, ct, ct, ct);
+ CYBOZU_BENCH_C("reRandG1", C, pub.reRand, c1);
+ CYBOZU_BENCH_C("reRandG2", C, pub.reRand, c2);
+ CYBOZU_BENCH_C("reRandGT", C, pub.reRand, ct);
+ CYBOZU_BENCH_C("reRandG1pre", C, ppub.reRand, c1);
+ CYBOZU_BENCH_C("reRandG2pre", C, ppub.reRand, c2);
+ CYBOZU_BENCH_C("reRandGTpre", C, ppub.reRand, ct);
+ CYBOZU_BENCH_C("mulG1 ", C, CipherTextG1::mul, c1, c1, m);
+ CYBOZU_BENCH_C("mulG2 ", C, CipherTextG2::mul, c2, c2, m);
+ CYBOZU_BENCH_C("mulGT ", C, CipherTextGT::mul, ct, ct, m);
+
+ CYBOZU_BENCH_C("convG1toGT", C, pub.convert, ct, c1);
+ CYBOZU_BENCH_C("convG2toGT", C, pub.convert, ct, c2);
+}
+#endif
+
+CYBOZU_TEST_AUTO(liftedElGamal)
+{
+ const size_t hashSize = 1024;
+ initG1only(mcl::ecparam::secp192k1, hashSize);
+ const size_t byteSize = 192 / 8;
+ SecretKey sec;
+ sec.setByCSPRNG();
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ CipherTextG1 c1, c2, c3;
+ int m1 = 12, m2 = 34;
+ pub.enc(c1, m1);
+ pub.enc(c2, m2);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), m1);
+ CYBOZU_TEST_EQUAL(sec.dec(c2), m2);
+ add(c3, c1, c2);
+ CYBOZU_TEST_EQUAL(sec.dec(c3), m1 + m2);
+ neg(c1, c2);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), -m2);
+ mul(c1, c2, m1);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), m2 * m1);
+
+ char buf[1024];
+ size_t n = sec.serialize(buf, sizeof(buf));
+ CYBOZU_TEST_EQUAL(n, byteSize);
+ SecretKey sec2;
+ n = sec2.deserialize(buf, n);
+ CYBOZU_TEST_EQUAL(n, byteSize);
+ CYBOZU_TEST_EQUAL(sec, sec2);
+
+ n = pub.serialize(buf, sizeof(buf));
+ CYBOZU_TEST_EQUAL(n, byteSize + 1); // +1 is for sign of y
+ PublicKey pub2;
+ n = pub2.deserialize(buf, n);
+ CYBOZU_TEST_EQUAL(n, byteSize + 1);
+ CYBOZU_TEST_EQUAL(pub, pub2);
+
+ PublicKey pub3;
+ sec2.getPublicKey(pub3);
+ CYBOZU_TEST_EQUAL(pub, pub3);
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/sq_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/sq_test.cpp
new file mode 100644
index 000000000..4c386d23b
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/sq_test.cpp
@@ -0,0 +1,21 @@
+#include <mcl/gmp_util.hpp>
+#include <cybozu/test.hpp>
+#include <iostream>
+
+CYBOZU_TEST_AUTO(sqrt)
+{
+ const int tbl[] = { 3, 5, 7, 11, 13, 17, 19, 257, 997, 1031 };
+ mcl::SquareRoot sq;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const mpz_class p = tbl[i];
+ sq.set(p);
+ for (mpz_class a = 0; a < p; a++) {
+ mpz_class x;
+ if (sq.get(x, a)) {
+ mpz_class y;
+ y = (x * x) % p;
+ CYBOZU_TEST_EQUAL(a, y);
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/dexon-foundation/mcl/test/vint_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/vint_test.cpp
new file mode 100644
index 000000000..15e14266a
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/vint_test.cpp
@@ -0,0 +1,1353 @@
+#include <stdio.h>
+#include <mcl/vint.hpp>
+#include <iostream>
+#include <sstream>
+#include <set>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/test.hpp>
+#include <cybozu/xorshift.hpp>
+#ifndef DONT_USE_GMP_IN_TEST
+#include <gmpxx.h>
+#endif
+
+#define PUT(x) std::cout << #x "=" << x << std::endl;
+
+#if defined(__EMSCRIPTEN__) && !defined(MCL_AVOID_EXCEPTION_TEST)
+ #define MCL_AVOID_EXCEPTION_TEST
+#endif
+
+using namespace mcl;
+
+struct V {
+ int n;
+ unsigned int p[16];
+};
+
+CYBOZU_TEST_AUTO(addSub)
+{
+ static const struct {
+ V a;
+ V b;
+ V c;
+ } tbl[] = {
+ {
+ { 1, { 123, } },
+ { 1, { 456, } },
+ { 1, { 579, } },
+ },
+ {
+ { 1, { 0xffffffff, } },
+ { 1, { 3, } },
+ { 2, { 2, 1 } },
+ },
+ {
+ { 3, { 0xffffffff, 1, 0xffffffff } },
+ { 2, { 1, 0xfffffffe, } },
+ { 4, { 0, 0, 0, 1 } },
+ },
+ {
+ { 3, { 0xffffffff, 5, 0xffffffff } },
+ { 2, { 1, 0xfffffffe, } },
+ { 4, { 0, 4, 0, 1 } },
+ },
+ {
+ { 3, { 0xffffffff, 5, 0xffffffff } },
+ { 1, { 1, } },
+ { 3, { 0, 6, 0xffffffff } },
+ },
+ {
+ { 3, { 1, 0xffffffff, 1 } },
+ { 3, { 0xffffffff, 0, 1 } },
+ { 3, { 0, 0, 3 } },
+ },
+ {
+ { 1, { 1 } },
+ { 3, { 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 4, { 0, 0, 0, 1 } },
+ },
+ {
+ { 1, { 0xffffffff } },
+ { 1, { 0xffffffff } },
+ { 2, { 0xfffffffe, 1 } },
+ },
+ {
+ { 2, { 0xffffffff, 0xffffffff } },
+ { 2, { 0xffffffff, 0xffffffff } },
+ { 3, { 0xfffffffe, 0xffffffff, 1 } },
+ },
+ {
+ { 3, { 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 3, { 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 4, { 0xfffffffe, 0xffffffff, 0xffffffff, 1 } },
+ },
+ {
+ { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 5, { 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 1 } },
+ },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Vint x, y, z, t;
+ x.setArray(tbl[i].a.p, tbl[i].a.n);
+ y.setArray(tbl[i].b.p, tbl[i].b.n);
+ z.setArray(tbl[i].c.p, tbl[i].c.n);
+ Vint::add(t, x, y);
+ CYBOZU_TEST_EQUAL(t, z);
+
+ Vint::add(t, y, x);
+ CYBOZU_TEST_EQUAL(t, z);
+
+ Vint::sub(t, z, x);
+ CYBOZU_TEST_EQUAL(t, y);
+ }
+ {
+ const uint32_t in[] = { 0xffffffff, 0xffffffff };
+ const uint32_t out[] = { 0xfffffffe, 0xffffffff, 1 };
+ Vint x, y;
+ x.setArray(in, 2);
+ y.setArray(out, 3);
+ Vint::add(x, x, x);
+ CYBOZU_TEST_EQUAL(x, y);
+ Vint::sub(x, x, x);
+ y.clear();
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+ {
+ const uint32_t t0[] = {1, 2};
+ const uint32_t t1[] = {3, 4, 5};
+ const uint32_t t2[] = {4, 6, 5};
+ Vint x, y, z;
+ z.setArray(t2, 3);
+
+ x.setArray(t0, 2);
+ y.setArray(t1, 3);
+ Vint::add(x, x, y);
+ CYBOZU_TEST_EQUAL(x, z);
+
+ x.setArray(t0, 2);
+ y.setArray(t1, 3);
+ Vint::add(x, y, x);
+ CYBOZU_TEST_EQUAL(x, z);
+
+ x.setArray(t0, 2);
+ y.setArray(t1, 3);
+ Vint::add(y, x, y);
+ CYBOZU_TEST_EQUAL(y, z);
+
+ x.setArray(t0, 2);
+ y.setArray(t1, 3);
+ Vint::add(y, y, x);
+ CYBOZU_TEST_EQUAL(y, z);
+ }
+}
+
+CYBOZU_TEST_AUTO(mul1)
+{
+ static const struct {
+ V a;
+ int b;
+ V c;
+ } tbl[] = {
+ {
+ { 1, { 12, } },
+ 5,
+ { 1, { 60, } },
+ },
+ {
+ { 1, { 1234567, } },
+ 1,
+ { 1, { 1234567, } },
+ },
+ {
+ { 1, { 1234567, } },
+ 89012345,
+ { 2, { 0x27F6EDCF, 0x63F2, } },
+ },
+ {
+ { 3, { 0xffffffff, 0xffffffff, 0xffffffff, } },
+ 0x7fffffff,
+ { 4, { 0x80000001, 0xffffffff, 0xffffffff, 0x7ffffffe } },
+ },
+ {
+ { 3, { 0xffffffff, 0xffffffff, 0xffffffff, } },
+ 1,
+ { 3, { 0xffffffff, 0xffffffff, 0xffffffff, } },
+ },
+ {
+ { 2, { 0xffffffff, 1 } },
+ 0x7fffffff,
+ { 2, { 0x80000001, 0xfffffffd } },
+ },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Vint x, z, t;
+ int y;
+ x.setArray(tbl[i].a.p, tbl[i].a.n);
+ y = tbl[i].b;
+ z.setArray(tbl[i].c.p, tbl[i].c.n);
+ Vint::mul(t, x, y);
+ CYBOZU_TEST_EQUAL(t, z);
+
+ Vint::mul(x, x, y);
+ CYBOZU_TEST_EQUAL(x, z);
+ }
+}
+
+CYBOZU_TEST_AUTO(mul2)
+{
+ static const struct {
+ V a;
+ V b;
+ V c;
+ } tbl[] = {
+ {
+ { 1, { 12, } },
+ { 1, { 5, } },
+ { 1, { 60, } },
+ },
+ {
+ { 1, { 1234567, } },
+ { 1, { 89012345, } },
+ { 2, { 0x27F6EDCF, 0x63F2, } },
+ },
+ {
+ { 3, { 0xffffffff, 0xffffffff, 0xffffffff, } },
+ { 1, { 0xffffffff, } },
+ { 4, { 0x00000001, 0xffffffff, 0xffffffff, 0xfffffffe } },
+ },
+ {
+ { 2, { 0xffffffff, 1 } },
+ { 1, { 0xffffffff, } },
+ { 3, { 0x00000001, 0xfffffffd, 1 } },
+ },
+ {
+ { 2, { 0xffffffff, 1 } },
+ { 1, { 0xffffffff, } },
+ { 3, { 0x00000001, 0xfffffffd, 1 } },
+ },
+ {
+ { 2, { 1, 1 } },
+ { 2, { 1, 1 } },
+ { 3, { 1, 2, 1 } },
+ },
+ {
+ { 3, { 0xffffffff, 0xffffffff, 1 } },
+ { 2, { 0xffffffff, 0xffffffff } },
+ { 5, { 1, 0, 0xfffffffd, 0xffffffff, 1 } },
+ },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Vint x, y, z, t;
+ x.setArray(tbl[i].a.p, tbl[i].a.n);
+ y.setArray(tbl[i].b.p, tbl[i].b.n);
+ z.setArray(tbl[i].c.p, tbl[i].c.n);
+ Vint::mul(t, x, y);
+ CYBOZU_TEST_EQUAL(t, z);
+
+ Vint::mul(t, y, x);
+ CYBOZU_TEST_EQUAL(t, z);
+ }
+ {
+ const uint32_t in[] = { 0xffffffff, 1 };
+ const uint32_t out[] = { 1, 0xfffffffc, 3 };
+ Vint x, y, z;
+ y.setArray(out, 3);
+ x.setArray(in, 2);
+ z = x;
+ Vint::mul(x, x, x);
+ CYBOZU_TEST_EQUAL(x, y);
+
+ x.setArray(in, 2);
+ Vint::mul(x, x, z);
+ CYBOZU_TEST_EQUAL(x, y);
+
+ x.setArray(in, 2);
+ Vint::mul(x, z, x);
+ CYBOZU_TEST_EQUAL(x, y);
+
+ x.setArray(in, 2);
+ Vint::mul(x, z, z);
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+ {
+ Vint a("285434247217355341057");
+ a *= a;
+ CYBOZU_TEST_EQUAL(a, Vint("81472709484538325259309302444004789877249"));
+ }
+}
+
+CYBOZU_TEST_AUTO(div1)
+{
+ static const struct {
+ V a;
+ unsigned int b;
+ unsigned int r;
+ V c;
+ } tbl[] = {
+ {
+ { 1, { 100, } },
+ 1, 0,
+ { 1, { 100, } },
+ },
+ {
+ { 1, { 100, } },
+ 100, 0,
+ { 1, { 1, } },
+ },
+ {
+ { 1, { 100, } },
+ 101, 100,
+ { 1, { 0, } },
+ },
+ {
+ { 1, { 100, } },
+ 2, 0,
+ { 1, { 50, } },
+ },
+ {
+ { 1, { 100, } },
+ 3, 1,
+ { 1, { 33, } },
+ },
+ {
+ { 2, { 0xffffffff, 0xffffffff } },
+ 1, 0,
+ { 2, { 0xffffffff, 0xffffffff, } },
+ },
+ {
+ { 2, { 0xffffffff, 0xffffffff } },
+ 123, 15,
+ { 2, { 0x4d0214d0, 0x214d021 } },
+ },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Vint x, z, t;
+ unsigned int b, r, u;
+ x.setArray(tbl[i].a.p, tbl[i].a.n);
+ b = tbl[i].b;
+ r = tbl[i].r;
+ z.setArray(tbl[i].c.p, tbl[i].c.n);
+
+ u = (unsigned int)Vint::divMods1(&t, x, b);
+ CYBOZU_TEST_EQUAL(t, z);
+ CYBOZU_TEST_EQUAL(u, r);
+
+ u = (unsigned int)Vint::divMods1(&x, x, b);
+ CYBOZU_TEST_EQUAL(x, z);
+ CYBOZU_TEST_EQUAL(u, r);
+ }
+}
+
+CYBOZU_TEST_AUTO(div2)
+{
+ static const struct {
+ V x;
+ V y;
+ V q;
+ V r;
+ } tbl[] = {
+ {
+ { 1, { 100 } },
+ { 1, { 3 } },
+ { 1, { 33 } },
+ { 1, { 1 } },
+ },
+ {
+ { 2, { 1, 1 } },
+ { 2, { 0, 1 } },
+ { 1, { 1 } },
+ { 1, { 1 } },
+ },
+ {
+ { 2, { 0xffffffff, 0xffffffff } },
+ { 2, { 0, 1 } },
+ { 1, { 0xffffffff } },
+ { 1, { 0xffffffff } },
+ },
+ {
+ { 2, { 0xffffffff, 0xffffffff } },
+ { 2, { 0xffffffff, 1 } },
+ { 1, { 0x80000000 } },
+ { 1, { 0x7fffffff } },
+ },
+ {
+ { 3, { 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 2, { 0xffffffff, 1 } },
+ { 2, { 0x40000000, 0x80000000 } },
+ { 1, { 0x3fffffff } },
+ },
+ {
+ { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 3, { 1, 0, 1 } },
+ { 2, { 0xffffffff, 0xffffffff } },
+ { 1, { 0 } },
+ },
+ {
+ { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 3, { 1, 0xffffffff, 0xffffffff } },
+ { 2, { 0, 1 } },
+ { 2, { 0xffffffff, 0xfffffffe } },
+ },
+ {
+ { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 3, { 1, 0, 0xffffffff } },
+ { 2, { 1, 1 } },
+ { 2, { 0xfffffffe, 0xfffffffe } },
+ },
+ {
+ { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 1 } },
+ { 3, { 1, 0, 0xffffffff } },
+ { 1, { 2 } },
+ { 3, { 0xfffffffd, 0xffffffff, 1 } },
+ },
+ {
+ { 4, { 0, 0, 1, 1 } },
+ { 2, { 1, 1 } },
+ { 3, { 0, 0, 1 } },
+ { 1, { 0 } },
+ },
+ {
+ { 3, { 5, 5, 1} },
+ { 2, { 1, 2 } },
+ { 1, { 0x80000002 } },
+ { 1, { 0x80000003, } },
+ },
+ {
+ { 2, { 5, 5} },
+ { 2, { 1, 1 } },
+ { 1, { 5 } },
+ { 1, { 0, } },
+ },
+ {
+ { 2, { 5, 5} },
+ { 2, { 2, 1 } },
+ { 1, { 4 } },
+ { 1, { 0xfffffffd, } },
+ },
+ {
+ { 3, { 5, 0, 5} },
+ { 3, { 2, 0, 1 } },
+ { 1, { 4 } },
+ { 2, { 0xfffffffd, 0xffffffff } },
+ },
+ {
+ { 2, { 4, 5 } },
+ { 2, { 5, 5 } },
+ { 1, { 0 } },
+ { 2, { 4, 5 } },
+ },
+ {
+ { 1, { 123 } },
+ { 2, { 1, 1 } },
+ { 1, { 0 } },
+ { 1, { 123 } },
+ },
+ {
+ { 1, { 123 } },
+ { 3, { 1, 1, 1 } },
+ { 1, { 0 } },
+ { 1, { 123 } },
+ },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Vint x, y, q, r;
+ x.setArray(tbl[i].x.p, tbl[i].x.n);
+ y.setArray(tbl[i].y.p, tbl[i].y.n);
+ q.setArray(tbl[i].q.p, tbl[i].q.n);
+ r.setArray(tbl[i].r.p, tbl[i].r.n);
+
+ Vint qt, rt;
+ Vint::quotRem(&qt, rt, x, y);
+ CYBOZU_TEST_EQUAL(qt, q);
+ CYBOZU_TEST_EQUAL(rt, r);
+
+ Vint::mul(y, y, qt);
+ Vint::add(y, y, rt);
+ CYBOZU_TEST_EQUAL(x, y);
+
+ x.setArray(tbl[i].x.p, tbl[i].x.n);
+ y.setArray(tbl[i].y.p, tbl[i].y.n);
+ Vint::quotRem(&x, rt, x, y);
+ CYBOZU_TEST_EQUAL(x, q);
+ CYBOZU_TEST_EQUAL(rt, r);
+
+ x.setArray(tbl[i].x.p, tbl[i].x.n);
+ y.setArray(tbl[i].y.p, tbl[i].y.n);
+ Vint::quotRem(&y, rt, x, y);
+ CYBOZU_TEST_EQUAL(y, q);
+ CYBOZU_TEST_EQUAL(rt, r);
+
+ x.setArray(tbl[i].x.p, tbl[i].x.n);
+ y.setArray(tbl[i].y.p, tbl[i].y.n);
+ Vint::quotRem(&x, y, x, y);
+ CYBOZU_TEST_EQUAL(x, q);
+ CYBOZU_TEST_EQUAL(y, r);
+
+ x.setArray(tbl[i].x.p, tbl[i].x.n);
+ y.setArray(tbl[i].y.p, tbl[i].y.n);
+ Vint::quotRem(&y, x, x, y);
+ CYBOZU_TEST_EQUAL(y, q);
+ CYBOZU_TEST_EQUAL(x, r);
+ }
+ {
+ const uint32_t in[] = { 1, 1 };
+ Vint x, y, z;
+ x.setArray(in, 2);
+ Vint::quotRem(&x, y, x, x);
+ z = 1;
+ CYBOZU_TEST_EQUAL(x, z);
+ z.clear();
+ CYBOZU_TEST_EQUAL(y, z);
+
+ Vint::quotRem(&y, x, x, x);
+ z = 1;
+ CYBOZU_TEST_EQUAL(y, z);
+ z.clear();
+ CYBOZU_TEST_EQUAL(x, z);
+ }
+}
+
+CYBOZU_TEST_AUTO(quotRem)
+{
+ const struct {
+ const char *x;
+ const char *y;
+ const char *r;
+ } tbl[] = {
+ {
+ "1448106640508192452750709206294683535529268965445799785581837640324321797831381715960812126274894517677713278300997728292641936248881345120394299128611830",
+ "82434016654300679721217353503190038836571781811386228921167322412819029493183",
+ "72416512377294697540770834088766459385112079195086911762075702918882982361282"
+ },
+ {
+ "97086308670107713719105336221824613370040805954034005192338040686500414395543303807941158656814978071549225072789349941064484974666540443679601226744652",
+ "82434016654300679721217353503190038836571781811386228921167322412819029493183",
+ "41854959563040430269871677548536437787164514279279911478858426970427834388586",
+ },
+ {
+ "726838724295606887174238120788791626017347752989142414466410919788841485181240131619880050064495352797213258935807786970844241989010252",
+ "82434016654300679721217353503190038836571781811386228921167322412819029493183",
+ "81378967132566843036693176764684783485107373533583677681931133755003929106966",
+ },
+ {
+ "85319207237201203511459960875801690195851794174784746933408178697267695525099750",
+ "82434016654300679721217353503190038836571781811386228921167322412819029493183",
+ "82434016654300679721217353503190038836571781811386228921167322412819029148528",
+ },
+ {
+ "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x100000000000000000000000000000000000000000000000001",
+ "1606938044258990275541962092341162602522202993782724115824640",
+ },
+ {
+ "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x1000000000000000000000000000000000000000000000000000000000000000000000000000000001",
+ "34175792574734561318320347298712833833643272357332299899995954578095372295314880347335474659983360",
+ },
+ {
+ "0xfffffffffffff000000000000000000000000000000000000000000000000000000000000000000",
+ "0x100000000000000000000000000000000000000000000000000000000000000000001",
+ "7558907585412001237250713901367146624661464598973016020495791084036551510708977665",
+ },
+ {
+ "0xfffffffffffff000000000000000000000000000000000000000000000000000000000000000000",
+ "0xfffffffffffff0000000000000000000000000000000000000000000000000000000000000001",
+ "521481209941628322292632858916605385658190900090571826892867289394157573281830188869820088065",
+ },
+ {
+ "0x1230000000000000456",
+ "0x1230000000000000457",
+ "0x1230000000000000456",
+ },
+ {
+ "0x1230000000000000456",
+ "0x1230000000000000456",
+ "0",
+ },
+ {
+ "0x1230000000000000456",
+ "0x1230000000000000455",
+ "1",
+ },
+ {
+ "0x1230000000000000456",
+ "0x2000000000000000000",
+ "0x1230000000000000456",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffff",
+ "0x80000000000000000000000000000000",
+ "0x7fffffffffffffffffffffffffffffff",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffff",
+ "0x7fffffffffffffffffffffffffffffff",
+ "1",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffff",
+ "0x70000000000000000000000000000000",
+ "0x1fffffffffffffffffffffffffffffff",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffff",
+ "0x30000000000000000000000000000000",
+ "0x0fffffffffffffffffffffffffffffff",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffff",
+ "0x10000000000000000000000000000000",
+ "0x0fffffffffffffffffffffffffffffff",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x2523648240000001ba344d80000000086121000000000013a700000000000013",
+ "0x212ba4f27ffffff5a2c62effffffffcdb939ffffffffff8a15ffffffffffff8d",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x2523648240000001ba344d8000000007ff9f800000000010a10000000000000d",
+ "0x212ba4f27ffffff5a2c62effffffffd00242ffffffffff9c39ffffffffffffb1",
+ },
+ };
+ mcl::Vint x, y, q, r1, r2;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ x.setStr(tbl[i].x);
+ y.setStr(tbl[i].y);
+ r1.setStr(tbl[i].r);
+ mcl::Vint::divMod(&q, r2, x, y);
+ CYBOZU_TEST_EQUAL(r1, r2);
+ CYBOZU_TEST_EQUAL(x, q * y + r2);
+ }
+}
+
+CYBOZU_TEST_AUTO(string)
+{
+ const struct {
+ uint32_t v[5];
+ size_t vn;
+ const char *str;
+ const char *hex;
+ const char *bin;
+ } tbl[] = {
+ { { 0 }, 0, "0", "0x0", "0b0" },
+ { { 12345 }, 1, "12345", "0x3039", "0b11000000111001" },
+ { { 0xffffffff }, 1, "4294967295", "0xffffffff", "0b11111111111111111111111111111111" },
+ { { 0, 1 }, 2, "4294967296", "0x100000000", "0b100000000000000000000000000000000" },
+ { { 0, 0, 0, 0, 1 }, 5, "340282366920938463463374607431768211456", "0x100000000000000000000000000000000", "0b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" },
+ { { 0, 0x0b22a000, 0xe2f768a0, 0xe086b93c, 0x2cd76f }, 5, "1000000000000000000000000000000000000000000000", "0x2cd76fe086b93ce2f768a00b22a00000000000", "0b101100110101110110111111100000100001101011100100111100111000101111011101101000101000000000101100100010101000000000000000000000000000000000000000000000" },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Vint x, y;
+ x.setArray(tbl[i].v,tbl[i].vn);
+ CYBOZU_TEST_EQUAL(x.getStr(10), tbl[i].str);
+ char buf[1024];
+ size_t n = x.getStr(buf, sizeof(buf), 10);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL(tbl[i].str, buf);
+ y.setStr(tbl[i].str);
+ CYBOZU_TEST_EQUAL(x.getStr(16), tbl[i].hex + 2);
+ n = x.getStr(buf, sizeof(buf), 16);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL(tbl[i].hex + 2, buf);
+ CYBOZU_TEST_EQUAL(x, y);
+ x = 1;
+ x.setStr(tbl[i].hex);
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+}
+
+CYBOZU_TEST_AUTO(shift)
+{
+ Vint x("123423424918471928374192874198274981274918274918274918243");
+ Vint y, z;
+
+ const size_t unitBitSize = Vint::unitBitSize;
+ Vint s;
+ // shl
+ for (size_t i = 1; i < 31; i++) {
+ Vint::shl(y, x, i);
+ z = x * (Vint::Unit(1) << i);
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x << i;
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x;
+ y <<= i;
+ CYBOZU_TEST_EQUAL(y, z);
+ }
+ for (int i = 0; i < 4; i++) {
+ Vint::shl(y, x, i * unitBitSize);
+ Vint::pow(s, Vint(2), i * unitBitSize);
+ z = x * s;
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x << (i * unitBitSize);
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x;
+ y <<= (i * unitBitSize);
+ CYBOZU_TEST_EQUAL(y, z);
+ }
+ for (int i = 0; i < 100; i++) {
+ y = x << i;
+ Vint::pow(s, Vint(2), i);
+ z = x * s;
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x;
+ y <<= i;
+ CYBOZU_TEST_EQUAL(y, z);
+ }
+
+ // shr
+ for (size_t i = 1; i < 31; i++) {
+ Vint::shr(y, x, i);
+ z = x / (Vint::Unit(1) << i);
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x >> i;
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x;
+ y >>= i;
+ CYBOZU_TEST_EQUAL(y, z);
+ }
+ for (int i = 0; i < 3; i++) {
+ Vint::shr(y, x, i * unitBitSize);
+ Vint::pow(s, Vint(2), i * unitBitSize);
+ z = x / s;
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x >> (i * unitBitSize);
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x;
+ y >>= (i * unitBitSize);
+ CYBOZU_TEST_EQUAL(y, z);
+ }
+ for (int i = 0; i < 100; i++) {
+ y = x >> i;
+ Vint::pow(s, Vint(2), i);
+ z = x / s;
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x;
+ y >>= i;
+ CYBOZU_TEST_EQUAL(y, z);
+ }
+ {
+ Vint a = 0, zero = 0;
+ a <<= Vint::unitBitSize;
+ CYBOZU_TEST_EQUAL(a, zero);
+ }
+}
+
+CYBOZU_TEST_AUTO(getBitSize)
+{
+ {
+ Vint zero = 0;
+ CYBOZU_TEST_EQUAL(zero.getBitSize(), 1);
+ zero <<= (Vint::unitBitSize - 1);
+ CYBOZU_TEST_EQUAL(zero.getBitSize(), 1);
+ zero <<= Vint::unitBitSize;
+ CYBOZU_TEST_EQUAL(zero.getBitSize(), 1);
+ }
+
+ {
+ Vint a = 1;
+ CYBOZU_TEST_EQUAL(a.getBitSize(), 1);
+ a = 2;
+ CYBOZU_TEST_EQUAL(a.getBitSize(), 2);
+ a = 3;
+ CYBOZU_TEST_EQUAL(a.getBitSize(), 2);
+ a = 4;
+ CYBOZU_TEST_EQUAL(a.getBitSize(), 3);
+ }
+
+ {
+ Vint a = 5;
+ const size_t msbindex = a.getBitSize();
+ const size_t width = 100;
+ const size_t time = 3;
+ for (size_t i = 0; i < time; ++i) {
+ a <<= width;
+ CYBOZU_TEST_EQUAL(a.getBitSize(), msbindex + width*(i + 1));
+ }
+
+ for (size_t i = 0; i < time*2; ++i) {
+ a >>= width/2;
+ CYBOZU_TEST_EQUAL(a.getBitSize(), msbindex + width*time - (width/2)*(i + 1));
+ }
+ a >>= width;
+ CYBOZU_TEST_ASSERT(a.isZero());
+ CYBOZU_TEST_EQUAL(a.getBitSize(), 1);
+ }
+
+ {
+ Vint b("12"), c("345"), d("67890");
+ size_t bl = b.getBitSize(), cl = c.getBitSize(), dl = d.getBitSize();
+ CYBOZU_TEST_ASSERT((b*c).getBitSize() <= bl + cl);
+ CYBOZU_TEST_ASSERT((c*d).getBitSize() <= cl + dl);
+ CYBOZU_TEST_ASSERT((b*c*d).getBitSize() <= bl + cl + dl);
+ }
+}
+
+CYBOZU_TEST_AUTO(bit)
+{
+ Vint a;
+ a.setStr("0x1234567890abcdef");
+ bool tvec[] = {
+ 1,1,1,1,0 ,1,1,1,1,0
+ ,1,1,0,0,1 ,1,1,1,0,1
+ ,0,1,0,1,0 ,0,0,0,1,0
+ ,0,1,0,0,0 ,1,1,1,1,0
+ ,0,1,1,0,1 ,0,1,0,0,0
+ ,1,0,1,1,0 ,0,0,1,0,0
+ ,1
+ };
+ CYBOZU_TEST_EQUAL(a.getBitSize(), sizeof(tvec)/sizeof(*tvec));
+ for (int i = (int)a.getBitSize() - 1; i >= 0; --i) {
+ CYBOZU_TEST_EQUAL(a.testBit(i), tvec[i]);
+ }
+}
+
+CYBOZU_TEST_AUTO(sample)
+{
+ using namespace mcl;
+ Vint x(1);
+ Vint y("123456789");
+ Vint z;
+
+ x = 1; // set by int
+ y.setStr("123456789"); // set by decimal
+ z.setStr("0xffffffff"); // set by hex
+ x += z;
+
+ x = 2;
+ y = 250;
+ Vint::pow(x, x, y);
+ Vint r, q;
+ r = x % y;
+ q = x / y;
+ CYBOZU_TEST_EQUAL(q * y + r, x);
+
+ Vint::quotRem(&q, r, x, y); // get both r and q
+ CYBOZU_TEST_EQUAL(q * y + r, x);
+}
+
+CYBOZU_TEST_AUTO(Vint)
+{
+ const struct {
+ int a;
+ int b;
+ /*
+ q, r ; like C
+ q2, r2 ; like Python
+ */
+ int add, sub, mul, q, r, q2, r2;
+ } tbl[] = {
+ { 13, 5, 18, 8, 65, 2, 3, 2, 3 },
+ { 13, -5, 8, 18, -65, -2, 3, -3, -2 },
+ { -13, 5, -8, -18, -65, -2, -3, -3, 2 },
+ { -13, -5, -18, -8, 65, 2, -3, 2, -3 },
+ { 5, 13, 18, -8, 65, 0, 5 , 0, 5},
+ { 5, -13, -8, 18, -65, 0, 5 , -1, -8},
+ { -5, 13, 8, -18, -65, 0, -5 , -1, 8},
+ { -5, -13, -18, 8, 65, 0, -5 , 0, -5},
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Vint a = tbl[i].a;
+ Vint b = tbl[i].b;
+ Vint add = a + b;
+ Vint sub = a - b;
+ Vint mul = a * b;
+ Vint q = a / b;
+ Vint r = a % b;
+ Vint q2, r2;
+ Vint::quotRem(&q2, r2, a, b);
+ CYBOZU_TEST_EQUAL(add, tbl[i].add);
+ CYBOZU_TEST_EQUAL(sub, tbl[i].sub);
+ CYBOZU_TEST_EQUAL(mul, tbl[i].mul);
+ CYBOZU_TEST_EQUAL(q, tbl[i].q);
+ CYBOZU_TEST_EQUAL(r, tbl[i].r);
+ CYBOZU_TEST_EQUAL(q * b + r, a);
+ CYBOZU_TEST_EQUAL(q2, tbl[i].q2);
+ CYBOZU_TEST_EQUAL(r2, tbl[i].r2);
+ CYBOZU_TEST_EQUAL(q2 * b + r2, a);
+ }
+ CYBOZU_TEST_EQUAL(Vint("15") / Vint("3"), Vint("5"));
+ CYBOZU_TEST_EQUAL(Vint("15") / Vint("-3"), Vint("-5"));
+ CYBOZU_TEST_EQUAL(Vint("-15") / Vint("3"), Vint("-5"));
+ CYBOZU_TEST_EQUAL(Vint("-15") / Vint("-3"), Vint("5"));
+
+ CYBOZU_TEST_EQUAL(Vint("15") % Vint("3"), Vint("0"));
+ CYBOZU_TEST_EQUAL(Vint("15") % Vint("-3"), Vint("0"));
+ CYBOZU_TEST_EQUAL(Vint("-15") % Vint("3"), Vint("0"));
+ CYBOZU_TEST_EQUAL(Vint("-15") % Vint("-3"), Vint("0"));
+
+ CYBOZU_TEST_EQUAL(Vint("-0") + Vint("-3"), Vint("-3"));
+ CYBOZU_TEST_EQUAL(Vint("-0") - Vint("-3"), Vint("3"));
+ CYBOZU_TEST_EQUAL(Vint("-3") + Vint("-0"), Vint("-3"));
+ CYBOZU_TEST_EQUAL(Vint("-3") - Vint("-0"), Vint("-3"));
+
+ CYBOZU_TEST_EQUAL(Vint("-0") + Vint("3"), Vint("3"));
+ CYBOZU_TEST_EQUAL(Vint("-0") - Vint("3"), Vint("-3"));
+ CYBOZU_TEST_EQUAL(Vint("3") + Vint("-0"), Vint("3"));
+ CYBOZU_TEST_EQUAL(Vint("3") - Vint("-0"), Vint("3"));
+
+ CYBOZU_TEST_EQUAL(Vint("0"), Vint("0"));
+ CYBOZU_TEST_EQUAL(Vint("0"), Vint("-0"));
+ CYBOZU_TEST_EQUAL(Vint("-0"), Vint("0"));
+ CYBOZU_TEST_EQUAL(Vint("-0"), Vint("-0"));
+
+ CYBOZU_TEST_ASSERT(Vint("2") < Vint("3"));
+ CYBOZU_TEST_ASSERT(Vint("-2") < Vint("3"));
+ CYBOZU_TEST_ASSERT(Vint("-5") < Vint("-3"));
+ CYBOZU_TEST_ASSERT(Vint("-0") < Vint("1"));
+ CYBOZU_TEST_ASSERT(Vint("-1") < Vint("-0"));
+
+ CYBOZU_TEST_ASSERT(Vint("5") > Vint("3"));
+ CYBOZU_TEST_ASSERT(Vint("5") > Vint("-3"));
+ CYBOZU_TEST_ASSERT(Vint("-2") > Vint("-3"));
+ CYBOZU_TEST_ASSERT(Vint("3") > Vint("-0"));
+ CYBOZU_TEST_ASSERT(Vint("-0") > Vint("-1"));
+
+ {
+ const struct {
+ const char *str;
+ int s;
+ int shl;
+ int shr;
+ } tbl2[] = {
+ { "0", 1, 0, 0 },
+ { "-0", 1, 0, 0 },
+ { "1", 1, 2, 0 },
+ { "-1", 1, -2, 0 },
+ { "12345", 3, 98760, 1543 },
+ { "-12345", 3, -98760, 0 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl2); i++) {
+ Vint a = Vint(tbl2[i].str);
+ Vint shl = a << tbl2[i].s;
+ CYBOZU_TEST_EQUAL(shl, tbl2[i].shl);
+ if (!a.isNegative()) {
+ Vint shr = a >> tbl2[i].s;
+ CYBOZU_TEST_EQUAL(shr, tbl2[i].shr);
+ }
+ }
+ }
+}
+
+CYBOZU_TEST_AUTO(add2)
+{
+ Vint x, y, z, w;
+ x.setStr("2416089439321382744001761632872637936198961520379024187947524965775137204955564426500438089001375107581766516460437532995850581062940399321788596606850");
+ y.setStr("2416089439321382743300544243711595219403446085161565705825288050160594425031420687263897209379984490503106207071010949258995096347962762372787916800000");
+ z.setStr("701217389161042716795515435217458482122236915614542779924143739236540879621390617078660309389426583736855484714977636949000679806850");
+ Vint::sub(w, x, y);
+ CYBOZU_TEST_EQUAL(w, z);
+
+ Vint a, c, d;
+
+ a.setStr("-2416089439321382744001761632872637936198961520379024187947524965775137204955564426500438089001375107581766516460437532995850581062940399321788596606850");
+ c.setStr("2416089439321382743300544243711595219403446085161565705825288050160594425031420687263897209379984490503106207071010949258995096347962762372787916800000");
+ a = a + c;
+
+ d.setStr("-701217389161042716795515435217458482122236915614542779924143739236540879621390617078660309389426583736855484714977636949000679806850");
+ CYBOZU_TEST_EQUAL(a, d);
+}
+
+CYBOZU_TEST_AUTO(stream)
+{
+ {
+ Vint x, y, z, w;
+ x.setStr("12345678901232342424242423423429922");
+ y.setStr("23423423452424242343");
+ std::ostringstream oss;
+ oss << x << ' ' << y;
+ std::istringstream iss(oss.str());
+ iss >> z >> w;
+ CYBOZU_TEST_EQUAL(x, z);
+ CYBOZU_TEST_EQUAL(y, w);
+ }
+ {
+ Vint x, y, z, w;
+ x.setStr("0x100");
+ y.setStr("123");
+ std::ostringstream oss;
+ oss << x << ' ' << y;
+ std::istringstream iss(oss.str());
+ iss >> z >> w;
+ CYBOZU_TEST_EQUAL(x, z);
+ CYBOZU_TEST_EQUAL(y, w);
+ }
+ {
+ Vint x, y, z, w;
+ x.setStr("12345678901232342424242423423429922");
+ y.setStr("-23423423452424242343");
+ std::ostringstream oss;
+ oss << x << ' ' << y;
+ std::istringstream iss(oss.str());
+ iss >> z >> w;
+ CYBOZU_TEST_EQUAL(x, z);
+ CYBOZU_TEST_EQUAL(y, w);
+ }
+}
+
+CYBOZU_TEST_AUTO(inc_dec)
+{
+ Vint x = 3;
+ CYBOZU_TEST_EQUAL(x++, 3);
+ CYBOZU_TEST_EQUAL(x, 4);
+ CYBOZU_TEST_EQUAL(++x, 5);
+ CYBOZU_TEST_EQUAL(x, 5);
+
+ CYBOZU_TEST_EQUAL(x--, 5);
+ CYBOZU_TEST_EQUAL(x, 4);
+ CYBOZU_TEST_EQUAL(--x, 3);
+ CYBOZU_TEST_EQUAL(x, 3);
+}
+
+CYBOZU_TEST_AUTO(withInt)
+{
+ Vint x = 15;
+ x += 3;
+ CYBOZU_TEST_EQUAL(x, 18);
+ x -= 2;
+ CYBOZU_TEST_EQUAL(x, 16);
+ x *= 2;
+ CYBOZU_TEST_EQUAL(x, 32);
+ x /= 3;
+ CYBOZU_TEST_EQUAL(x, 10);
+ x = -x;
+ CYBOZU_TEST_EQUAL(x, -10);
+ x += 1;
+ CYBOZU_TEST_EQUAL(x, -9);
+ x -= 2;
+ CYBOZU_TEST_EQUAL(x, -11);
+ x *= 2;
+ CYBOZU_TEST_EQUAL(x, -22);
+ x /= 5;
+ CYBOZU_TEST_EQUAL(x, -4);
+ x = -22;
+ x %= 5;
+ CYBOZU_TEST_EQUAL(x, -2);
+
+ x = 3;
+ x += -2;
+ CYBOZU_TEST_EQUAL(x, 1);
+ x += -5;
+ CYBOZU_TEST_EQUAL(x, -4);
+ x -= -7;
+ CYBOZU_TEST_EQUAL(x, 3);
+ x *= -1;
+ CYBOZU_TEST_EQUAL(x, -3);
+ x /= -1;
+ CYBOZU_TEST_EQUAL(x, 3);
+
+ x++;
+ CYBOZU_TEST_EQUAL(x, 4);
+ x--;
+ CYBOZU_TEST_EQUAL(x, 3);
+ x = -3;
+ x++;
+ CYBOZU_TEST_EQUAL(x, -2);
+ x--;
+ CYBOZU_TEST_EQUAL(x, -3);
+
+ ++x;
+ CYBOZU_TEST_EQUAL(x, -2);
+ --x;
+ CYBOZU_TEST_EQUAL(x, -3);
+ x = 3;
+ ++x;
+ CYBOZU_TEST_EQUAL(x, 4);
+ --x;
+ CYBOZU_TEST_EQUAL(x, 3);
+}
+
+CYBOZU_TEST_AUTO(addu1)
+{
+ Vint x = 4;
+ Vint::addu1(x, x, 2);
+ CYBOZU_TEST_EQUAL(x, 6);
+ Vint::subu1(x, x, 2);
+ CYBOZU_TEST_EQUAL(x, 4);
+ Vint::subu1(x, x, 10);
+ CYBOZU_TEST_EQUAL(x, -6);
+ x = -4;
+ Vint::addu1(x, x, 2);
+ CYBOZU_TEST_EQUAL(x, -2);
+ Vint::subu1(x, x, 2);
+ CYBOZU_TEST_EQUAL(x, -4);
+ Vint::addu1(x, x, 10);
+ CYBOZU_TEST_EQUAL(x, 6);
+
+ x.setStr("0x10000000000000000000000002");
+ Vint::subu1(x, x, 3);
+ CYBOZU_TEST_EQUAL(x, Vint("0xfffffffffffffffffffffffff"));
+ x.setStr("-0x10000000000000000000000000");
+ Vint::addu1(x, x, 5);
+ CYBOZU_TEST_EQUAL(x, Vint("-0xffffffffffffffffffffffffb"));
+}
+
+CYBOZU_TEST_AUTO(pow)
+{
+ Vint x = 2;
+ Vint y;
+ Vint::pow(y, x, 3);
+ CYBOZU_TEST_EQUAL(y, 8);
+ x = -2;
+ Vint::pow(y, x, 3);
+ CYBOZU_TEST_EQUAL(y, -8);
+#ifndef MCL_AVOID_EXCEPTION_TEST
+// CYBOZU_TEST_EXCEPTION(Vint::pow(y, x, -2), cybozu::Exception);
+#endif
+}
+
+CYBOZU_TEST_AUTO(powMod)
+{
+ Vint x = 7;
+ Vint m = 65537;
+ Vint y;
+ Vint::powMod(y, x, 20, m);
+ CYBOZU_TEST_EQUAL(y, 55277);
+ Vint::powMod(y, x, m - 1, m);
+ CYBOZU_TEST_EQUAL(y, 1);
+}
+
+CYBOZU_TEST_AUTO(andOr)
+{
+ Vint x("1223480928420984209849242");
+ Vint y("29348220482094820948208420984209482048204289482");
+ Vint z;
+ z = x & y;
+ CYBOZU_TEST_EQUAL(z, Vint("1209221003550923564822922"));
+ z = x | y;
+ CYBOZU_TEST_EQUAL(z, Vint("29348220482094820948208435244134352108849315802"));
+#ifndef MCL_AVOID_EXCEPTION_TEST
+// CYBOZU_TEST_EXCEPTION(Vint("-2") | Vint("5"), cybozu::Exception);
+// CYBOZU_TEST_EXCEPTION(Vint("-2") & Vint("5"), cybozu::Exception);
+#endif
+ x = 8;
+ x |= 7;
+ CYBOZU_TEST_EQUAL(x, 15);
+ x = 65536;
+ y = 8;
+ y &= x;
+ CYBOZU_TEST_EQUAL(y, 0);
+}
+
+CYBOZU_TEST_AUTO(invMod)
+{
+ Vint m("100000000000000000039");
+ for (int i = 1; i < 100; i++) {
+ Vint x = i;
+ Vint y;
+ Vint::invMod(y, x, m);
+ CYBOZU_TEST_EQUAL((y * x) % m, 1);
+ }
+}
+
+CYBOZU_TEST_AUTO(isPrime)
+{
+ int primeTbl[] = {
+ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
+ 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,
+ 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193,197, 199, 211,
+ 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
+ 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379,
+ 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461,
+ 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563,
+ 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643,
+ 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739,
+ 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
+ 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,
+ 941, 947, 953, 967, 971, 977, 983, 991, 997
+ };
+ typedef std::set<int> IntSet;
+ IntSet primes;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(primeTbl); i++) {
+ primes.insert(primeTbl[i]);
+ }
+ for (int i = 0; i < 1000; i++) {
+ bool ok = primes.find(i) != primes.end();
+ bool my = Vint(i).isPrime();
+ CYBOZU_TEST_EQUAL(ok, my);
+ }
+ const struct {
+ const char *n;
+ bool isPrime;
+ } tbl[] = {
+ { "65537", true },
+ { "449065", false },
+ { "488881", false },
+ { "512461", false },
+ { "18446744073709551629", true },
+ { "18446744073709551631", false },
+ { "0x10000000000000000000000000000000000000007", true },
+ { "0x10000000000000000000000000000000000000009", false },
+ { "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", true },
+ { "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", false },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Vint x(tbl[i].n);
+ CYBOZU_TEST_EQUAL(x.isPrime(), tbl[i].isPrime);
+ }
+}
+
+CYBOZU_TEST_AUTO(gcd)
+{
+ Vint x = 12;
+ Vint y = 18;
+ Vint z;
+ Vint::gcd(z, x, y);
+ CYBOZU_TEST_EQUAL(z, 6);
+ Vint::lcm(z, x, y);
+ CYBOZU_TEST_EQUAL(z, 36);
+ Vint::lcm(x, x, y);
+ CYBOZU_TEST_EQUAL(x, 36);
+ Vint::lcm(x, x, x);
+ CYBOZU_TEST_EQUAL(x, 36);
+}
+
+CYBOZU_TEST_AUTO(jacobi)
+{
+ const struct {
+ const char *m;
+ const char *n;
+ int ok;
+ } tbl[] = {
+ { "0", "1", 1 },
+ { "1", "1", 1 },
+ { "123", "1", 1 },
+ { "45", "77", -1 },
+ { "60", "121", 1 },
+ { "12345672342342342342428", "923423423424753211", 1 },
+ { "12345672342342342342428","34592342234235424753211", -1 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ int my = Vint::jacobi(Vint(tbl[i].m), Vint(tbl[i].n));
+ CYBOZU_TEST_EQUAL(my, tbl[i].ok);
+ }
+}
+
+CYBOZU_TEST_AUTO(bench)
+{
+ Vint x, y, z;
+ x.setStr("0x2523648240000001ba344d80000000086121000000000013a700000000000013");
+ y.setStr("0x1802938109810498104982094820498203942804928049284092424902424243");
+
+ int N = 100000;
+ CYBOZU_BENCH_C("add", N, Vint::add, z, x, y);
+ CYBOZU_BENCH_C("sub", N, Vint::sub, z, x, y);
+ CYBOZU_BENCH_C("mul", N, Vint::mul, z, x, y);
+ CYBOZU_BENCH_C("div", N, Vint::div, y, z, x);
+
+ const struct {
+ const char *x;
+ const char *y;
+ } tbl[] = {
+ {
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x2523648240000001ba344d8000000007ff9f800000000010a10000000000000d"
+ },
+ {
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001",
+ },
+
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ x.setStr(tbl[i].x);
+ y.setStr(tbl[i].y);
+ CYBOZU_BENCH_C("fast div", N, Vint::div, z, x, y);
+#ifndef DONT_USE_GMP_IN_TEST
+ {
+ mpz_class mx(tbl[i].x), my(tbl[i].y), mz;
+ CYBOZU_BENCH_C("gmp", N, mpz_div, mz.get_mpz_t(), mx.get_mpz_t(), my.get_mpz_t());
+ }
+#endif
+ }
+}
+
+struct Seq {
+ const uint32_t *tbl;
+ size_t n;
+ size_t i, j;
+ Seq(const uint32_t *tbl, size_t n) : tbl(tbl), n(n), i(0), j(0) {}
+ bool next(uint64_t *v)
+ {
+ if (i == n) {
+ if (j == n - 1) return false;
+ i = 0;
+ j++;
+ }
+ *v = (uint64_t(tbl[j]) << 32) | tbl[i];
+ i++;
+ return true;
+ }
+};
+
+#if MCL_SIZEOF_UNIT == 8
+CYBOZU_TEST_AUTO(divUnit)
+{
+ const uint32_t tbl[] = {
+ 0, 1, 3,
+ 0x7fffffff,
+ 0x80000000,
+ 0x80000001,
+ 0xffffffff,
+ };
+ const size_t n = sizeof(tbl) / sizeof(tbl[0]);
+ Seq seq3(tbl, n);
+ uint64_t y;
+ while (seq3.next(&y)) {
+ if (y == 0) continue;
+ Seq seq2(tbl, n);
+ uint64_t r;
+ while (seq2.next(&r)) {
+ if (r >= y) break;
+ Seq seq1(tbl, n);
+ uint64_t q;
+ while (seq1.next(&q)) {
+ uint64_t x[2];
+ x[0] = mcl::vint::mulUnit(&x[1], q, y);
+ mcl::vint::addu1(x, x, 2, r);
+ uint64_t Q, R;
+//printf("q=0x%016llxull, r=0x%016llxull, y=0x%016llxull\n", (long long)q, (long long)r, (long long)y);
+ Q = mcl::vint::divUnit(&R, x[1], x[0], y);
+ CYBOZU_TEST_EQUAL(q, Q);
+ CYBOZU_TEST_EQUAL(r, R);
+ }
+ }
+ }
+}
+
+void compareMod(const uint64_t *x, const uint64_t *p)
+{
+ uint64_t y1[4] = {};
+ uint64_t y2[4] = {};
+ mcl::vint::divNM((uint64_t*)0, 0, y1, x, 8, p, 4);
+ mcl::vint::mcl_fpDbl_mod_SECP256K1(y2, x, p);
+ CYBOZU_TEST_EQUAL_ARRAY(y1, y2, 4);
+}
+CYBOZU_TEST_AUTO(SECP256k1)
+{
+ const uint64_t F = uint64_t(-1);
+ const uint64_t p[4] = { uint64_t(0xfffffffefffffc2full), F, F, F };
+ const uint64_t tbl[][8] = {
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { F, F, F, F, F, F, F, F },
+ { F, F, F, F, 1, 0, 0, 0 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const uint64_t *x = tbl[i];
+ compareMod(x, p);
+ }
+ cybozu::XorShift rg;
+ for (size_t i = 0; i < 100; i++) {
+ uint64_t x[8];
+ for (int j = 0; j < 8; j++) {
+ x[j] = rg();
+ }
+ compareMod(x, p);
+ }
+}
+#endif
diff --git a/vendor/github.com/dexon-foundation/mcl/test/window_method_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/window_method_test.cpp
new file mode 100644
index 000000000..1b0f702af
--- /dev/null
+++ b/vendor/github.com/dexon-foundation/mcl/test/window_method_test.cpp
@@ -0,0 +1,70 @@
+#include <cybozu/test.hpp>
+#include <mcl/window_method.hpp>
+#include <mcl/ec.hpp>
+#include <mcl/fp.hpp>
+#include <mcl/ecparam.hpp>
+
+CYBOZU_TEST_AUTO(ArrayIterator)
+{
+ const uint32_t in[2] = { 0x12345678, 0xabcdef89 };
+ const size_t bitSize = 64;
+ for (size_t w = 1; w <= 32; w++) {
+ const uint32_t mask = uint32_t((uint64_t(1) << w) - 1);
+ mpz_class x;
+ mcl::gmp::setArray(x, in, 2);
+ mcl::fp::ArrayIterator<uint32_t> ai(in, bitSize, w);
+ size_t n = (bitSize + w - 1) / w;
+ for (size_t j = 0; j < n; j++) {
+ CYBOZU_TEST_ASSERT(ai.hasNext());
+ uint32_t v = ai.getNext();
+ CYBOZU_TEST_EQUAL(x & mask, v);
+ x >>= w;
+ }
+ CYBOZU_TEST_ASSERT(!ai.hasNext());
+ }
+}
+
+CYBOZU_TEST_AUTO(int)
+{
+ typedef mcl::FpT<> Fp;
+ typedef mcl::EcT<Fp> Ec;
+ const struct mcl::EcParam& para = mcl::ecparam::secp192k1;
+ Fp::init(para.p);
+ Ec::init(para.a, para.b);
+ const Fp x(para.gx);
+ const Fp y(para.gy);
+ const Ec P(x, y);
+
+ typedef mcl::fp::WindowMethod<Ec> PW;
+ const size_t bitSize = 13;
+ Ec Q, R;
+
+ for (size_t winSize = 10; winSize <= bitSize; winSize++) {
+ PW pw(P, bitSize, winSize);
+ for (int i = 0; i < (1 << bitSize); i++) {
+ pw.mul(Q, i);
+ Ec::mul(R, P, i);
+ CYBOZU_TEST_EQUAL(Q, R);
+ }
+ }
+ PW pw(P, para.bitSize, 10);
+ pw.mul(Q, -12345);
+ Ec::mul(R, P, -12345);
+ CYBOZU_TEST_EQUAL(Q, R);
+ mpz_class t(para.gx);
+ pw.mul(Q, t);
+ Ec::mul(R, P, t);
+ CYBOZU_TEST_EQUAL(Q, R);
+ t = -t;
+ pw.mul(Q, t);
+ Ec::mul(R, P, t);
+ CYBOZU_TEST_EQUAL(Q, R);
+
+ pw.mul(Q, x);
+ Ec::mul(R, P, x);
+ CYBOZU_TEST_EQUAL(Q, R);
+
+ pw.mul(Q, y);
+ Ec::mul(R, P, y);
+ CYBOZU_TEST_EQUAL(Q, R);
+}
diff --git a/vendor/vendor.json b/vendor/vendor.json
index 7cccb564a..f94f0e307 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -141,16 +141,16 @@
{
"checksumSHA1": "In6vBHYUsX7DUIGiFN2hQggBgvI=",
"path": "github.com/dexon-foundation/dexon-consensus/common",
- "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d",
- "revisionTime": "2019-04-10T14:52:57Z",
+ "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac",
+ "revisionTime": "2019-04-11T06:42:07Z",
"version": "single-chain",
"versionExact": "single-chain"
},
{
"checksumSHA1": "9uNk7orRE3xuTv2m/y6vO/4uDAg=",
"path": "github.com/dexon-foundation/dexon-consensus/core",
- "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d",
- "revisionTime": "2019-04-10T14:52:57Z",
+ "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac",
+ "revisionTime": "2019-04-11T06:42:07Z",
"version": "single-chain",
"versionExact": "single-chain"
},
@@ -165,64 +165,64 @@
{
"checksumSHA1": "tQSbYCu5P00lUhKsx3IbBZCuSLY=",
"path": "github.com/dexon-foundation/dexon-consensus/core/crypto",
- "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d",
- "revisionTime": "2019-04-10T14:52:57Z",
+ "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac",
+ "revisionTime": "2019-04-11T06:42:07Z",
"version": "single-chain",
"versionExact": "single-chain"
},
{
- "checksumSHA1": "m5lUT04qSHKtFukvxjnFX5Jo2hI=",
+ "checksumSHA1": "4besQaa0rm8jRUAJjpEaLZ/ZOYs=",
"path": "github.com/dexon-foundation/dexon-consensus/core/crypto/dkg",
- "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d",
- "revisionTime": "2019-04-10T14:52:57Z",
+ "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac",
+ "revisionTime": "2019-04-11T06:42:07Z",
"version": "single-chain",
"versionExact": "single-chain"
},
{
"checksumSHA1": "BhLKK8RveoLaeXc9UyUKMwQqchU=",
"path": "github.com/dexon-foundation/dexon-consensus/core/crypto/ecdsa",
- "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d",
- "revisionTime": "2019-04-10T14:52:57Z",
+ "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac",
+ "revisionTime": "2019-04-11T06:42:07Z",
"version": "single-chain",
"versionExact": "single-chain"
},
{
"checksumSHA1": "3Ludp/1V4dMBZH/c1oIVjHj0CqY=",
"path": "github.com/dexon-foundation/dexon-consensus/core/db",
- "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d",
- "revisionTime": "2019-04-10T14:52:57Z",
+ "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac",
+ "revisionTime": "2019-04-11T06:42:07Z",
"version": "single-chain",
"versionExact": "single-chain"
},
{
"checksumSHA1": "/OcEQKdtWDyRZibazIsAxJWHUyg=",
"path": "github.com/dexon-foundation/dexon-consensus/core/syncer",
- "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d",
- "revisionTime": "2019-04-10T14:52:57Z",
+ "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac",
+ "revisionTime": "2019-04-11T06:42:07Z",
"version": "single-chain",
"versionExact": "single-chain"
},
{
"checksumSHA1": "zIgCdN4FJiAuPGMhB+/9YGK/Wgk=",
"path": "github.com/dexon-foundation/dexon-consensus/core/types",
- "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d",
- "revisionTime": "2019-04-10T14:52:57Z",
+ "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac",
+ "revisionTime": "2019-04-11T06:42:07Z",
"version": "single-chain",
"versionExact": "single-chain"
},
{
"checksumSHA1": "lbG7yqVgzo2CV/CQPYjG78xp5jg=",
"path": "github.com/dexon-foundation/dexon-consensus/core/types/dkg",
- "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d",
- "revisionTime": "2019-04-10T14:52:57Z",
+ "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac",
+ "revisionTime": "2019-04-11T06:42:07Z",
"version": "single-chain",
"versionExact": "single-chain"
},
{
"checksumSHA1": "1VsJIshz0loXnGwCtrMM8SuIo6Y=",
"path": "github.com/dexon-foundation/dexon-consensus/core/utils",
- "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d",
- "revisionTime": "2019-04-10T14:52:57Z",
+ "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac",
+ "revisionTime": "2019-04-11T06:42:07Z",
"version": "single-chain",
"versionExact": "single-chain"
},