Browse Source

Merge pull request #109 from FireMartZ/v1.0.14-dev

Merge FireMartZ/v1.0.14-dev
pull/110/head
FireMartZ 6 years ago
committed by GitHub
parent
commit
f9bd8b052a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      README.md
  2. 17
      configure.ac
  3. 1
      contrib/ci-workers/grind.yml
  4. 2
      contrib/devtools/README.md
  5. 8
      depends/builders/darwin.mk
  6. 7
      depends/packages/bdb.mk
  7. 8
      depends/packages/boost.mk
  8. 6
      depends/packages/googlemock.mk
  9. 7
      depends/packages/googletest.mk
  10. 1
      qa/pull-tester/rpc-tests.sh
  11. 8
      qa/rpc-tests/README.md
  12. 1
      qa/rpc-tests/bip65-cltv-p2p.py
  13. 1
      qa/rpc-tests/bipdersig-p2p.py
  14. 33
      qa/rpc-tests/mempool_tx_input_limit.py
  15. 17
      qa/rpc-tests/nodehandling.py
  16. 47
      qa/rpc-tests/paymentdisclosure.py
  17. 28
      qa/rpc-tests/prioritisetransaction.py
  18. 1
      qa/rpc-tests/proxy_test.py
  19. 1
      qa/rpc-tests/test_framework/blocktools.py
  20. 1
      qa/rpc-tests/test_framework/equihash.py
  21. 1
      qa/rpc-tests/test_framework/netutil.py
  22. 30
      qa/rpc-tests/test_framework/util.py
  23. 29
      qa/rpc-tests/wallet_1941.py
  24. 45
      qa/rpc-tests/wallet_nullifiers.py
  25. 53
      qa/rpc-tests/wallet_protectcoinbase.py
  26. 96
      qa/rpc-tests/wallet_shieldcoinbase.py
  27. 36
      qa/rpc-tests/wallet_treestate.py
  28. 9
      qa/rpc-tests/walletbackup.py
  29. 189
      qa/rpc-tests/zkey_import_export.py
  30. 2
      share/ui.rc
  31. 1
      src/Makefile.gtest.include
  32. 75
      src/base58.cpp
  33. 36
      src/base58.h
  34. 19
      src/chain.h
  35. 6
      src/chainparams.cpp
  36. 1
      src/chainparams.h
  37. 2
      src/clientversion.h
  38. 1
      src/consensus/params.h
  39. 5
      src/gtest/main.cpp
  40. 1
      src/gtest/test_circuit.cpp
  41. 3
      src/gtest/test_joinsplit.cpp
  42. 69
      src/gtest/test_keystore.cpp
  43. 1
      src/gtest/test_merkletree.cpp
  44. 5
      src/gtest/test_paymentdisclosure.cpp
  45. 1
      src/gtest/test_proofs.cpp
  46. 86
      src/gtest/test_validation.cpp
  47. 36
      src/keystore.cpp
  48. 19
      src/keystore.h
  49. 2
      src/leveldbwrapper.cpp
  50. 25
      src/main.cpp
  51. 9
      src/miner.cpp
  52. 1
      src/paymentdisclosure.cpp
  53. 2
      src/paymentdisclosure.h
  54. 1
      src/paymentdisclosuredb.cpp
  55. 1
      src/paymentdisclosuredb.h
  56. 7
      src/reverselock.h
  57. 29
      src/rpcblockchain.cpp
  58. 4
      src/rpcclient.cpp
  59. 3
      src/rpcmisc.cpp
  60. 2
      src/rpcserver.cpp
  61. 2
      src/rpcserver.h
  62. 16
      src/scheduler.cpp
  63. 10
      src/secp256k1/contrib/lax_der_parsing.h
  64. 10
      src/secp256k1/contrib/lax_der_privatekey_parsing.h
  65. 23
      src/secp256k1/include/secp256k1.h
  66. 16
      src/secp256k1/include/secp256k1_ecdh.h
  67. 16
      src/secp256k1/include/secp256k1_recovery.h
  68. 4
      src/secp256k1/sage/group_prover.sage
  69. 4
      src/secp256k1/src/asm/field_10x26_arm.s
  70. 9
      src/secp256k1/src/basic-config.h
  71. 6
      src/secp256k1/src/bench.h
  72. 8
      src/secp256k1/src/bench_ecdh.c
  73. 62
      src/secp256k1/src/bench_internal.c
  74. 8
      src/secp256k1/src/bench_recover.c
  75. 12
      src/secp256k1/src/bench_sign.c
  76. 6
      src/secp256k1/src/ecdsa.h
  77. 8
      src/secp256k1/src/ecdsa_impl.h
  78. 6
      src/secp256k1/src/eckey.h
  79. 17
      src/secp256k1/src/eckey_impl.h
  80. 6
      src/secp256k1/src/ecmult.h
  81. 6
      src/secp256k1/src/ecmult_const.h
  82. 13
      src/secp256k1/src/ecmult_const_impl.h
  83. 6
      src/secp256k1/src/ecmult_gen.h
  84. 8
      src/secp256k1/src/ecmult_gen_impl.h
  85. 6
      src/secp256k1/src/ecmult_impl.h
  86. 6
      src/secp256k1/src/field.h
  87. 7
      src/secp256k1/src/field_10x26.h
  88. 6
      src/secp256k1/src/field_10x26_impl.h
  89. 6
      src/secp256k1/src/field_5x52.h
  90. 6
      src/secp256k1/src/field_5x52_asm_impl.h
  91. 6
      src/secp256k1/src/field_5x52_impl.h
  92. 6
      src/secp256k1/src/field_5x52_int128_impl.h
  93. 6
      src/secp256k1/src/field_impl.h
  94. 6
      src/secp256k1/src/group.h
  95. 6
      src/secp256k1/src/group_impl.h
  96. 32
      src/secp256k1/src/hash.h
  97. 32
      src/secp256k1/src/hash_impl.h
  98. 8
      src/secp256k1/src/modules/ecdh/main_impl.h
  99. 8
      src/secp256k1/src/modules/ecdh/tests_impl.h
  100. 6
      src/secp256k1/src/modules/recovery/main_impl.h
  101. 6
      src/secp256k1/src/modules/recovery/tests_impl.h
  102. 6
      src/secp256k1/src/num.h
  103. 6
      src/secp256k1/src/num_gmp.h
  104. 6
      src/secp256k1/src/num_gmp_impl.h
  105. 6
      src/secp256k1/src/num_impl.h
  106. 6
      src/secp256k1/src/scalar.h
  107. 6
      src/secp256k1/src/scalar_4x64.h
  108. 6
      src/secp256k1/src/scalar_4x64_impl.h
  109. 6
      src/secp256k1/src/scalar_8x32.h
  110. 6
      src/secp256k1/src/scalar_8x32_impl.h
  111. 6
      src/secp256k1/src/scalar_impl.h
  112. 6
      src/secp256k1/src/scalar_low.h
  113. 6
      src/secp256k1/src/scalar_low_impl.h
  114. 2
      src/secp256k1/src/secp256k1.c
  115. 6
      src/secp256k1/src/testrand.h
  116. 8
      src/secp256k1/src/testrand_impl.h
  117. 6
      src/secp256k1/src/tests.c
  118. 6
      src/secp256k1/src/util.h
  119. 4
      src/serialize.h
  120. 1
      src/snark/.gitignore
  121. 8
      src/snark/src/algebra/curves/alt_bn128/alt_bn128_g1.cpp
  122. 10
      src/snark/src/algebra/curves/alt_bn128/alt_bn128_g1.hpp
  123. 8
      src/snark/src/algebra/curves/alt_bn128/alt_bn128_g2.cpp
  124. 10
      src/snark/src/algebra/curves/alt_bn128/alt_bn128_g2.hpp
  125. 6
      src/snark/src/algebra/curves/alt_bn128/alt_bn128_pairing.cpp
  126. 2
      src/snark/src/algebra/curves/curve_utils.tcc
  127. 42
      src/snark/src/algebra/curves/tests/test_bilinearity.cpp
  128. 101
      src/snark/src/algebra/curves/tests/test_groups.cpp
  129. 10
      src/snark/src/algebra/evaluation_domain/domains/basic_radix2_domain_aux.tcc
  130. 48
      src/snark/src/algebra/evaluation_domain/domains/extended_radix2_domain.hpp
  131. 180
      src/snark/src/algebra/evaluation_domain/domains/extended_radix2_domain.tcc
  132. 50
      src/snark/src/algebra/evaluation_domain/domains/step_radix2_domain.hpp
  133. 247
      src/snark/src/algebra/evaluation_domain/domains/step_radix2_domain.tcc
  134. 12
      src/snark/src/algebra/evaluation_domain/evaluation_domain.tcc
  135. 2
      src/snark/src/algebra/exponentiation/exponentiation.hpp
  136. 4
      src/snark/src/algebra/exponentiation/exponentiation.tcc
  137. 4
      src/snark/src/algebra/fields/bigint.hpp
  138. 15
      src/snark/src/algebra/fields/bigint.tcc
  139. 8
      src/snark/src/algebra/fields/field_utils.hpp
  140. 32
      src/snark/src/algebra/fields/field_utils.tcc
  141. 32
      src/snark/src/algebra/fields/fp.hpp
  142. 22
      src/snark/src/algebra/fields/fp.tcc
  143. 4
      src/snark/src/algebra/fields/fp12_2over3over2.hpp
  144. 10
      src/snark/src/algebra/fields/fp12_2over3over2.tcc
  145. 8
      src/snark/src/algebra/fields/fp2.hpp
  146. 8
      src/snark/src/algebra/fields/fp2.tcc
  147. 122
      src/snark/src/algebra/fields/fp3.hpp
  148. 259
      src/snark/src/algebra/fields/fp3.tcc
  149. 4
      src/snark/src/algebra/fields/fp6_3over2.hpp
  150. 4
      src/snark/src/algebra/fields/fp6_3over2.tcc
  151. 90
      src/snark/src/algebra/fields/tests/test_bigint.cpp
  152. 108
      src/snark/src/algebra/fields/tests/test_fields.cpp
  153. 1
      src/snark/src/algebra/scalar_multiplication/kc_multiexp.tcc
  154. 16
      src/snark/src/algebra/scalar_multiplication/multiexp.tcc
  155. 2
      src/snark/src/algebra/scalar_multiplication/wnaf.hpp
  156. 18
      src/snark/src/algebra/scalar_multiplication/wnaf.tcc
  157. 8
      src/snark/src/common/assert_except.hpp
  158. 18
      src/snark/src/common/data_structures/merkle_tree.tcc
  159. 14
      src/snark/src/common/data_structures/sparse_vector.hpp
  160. 36
      src/snark/src/common/data_structures/sparse_vector.tcc
  161. 69
      src/snark/src/common/profiling.cpp
  162. 10
      src/snark/src/common/profiling.hpp
  163. 28
      src/snark/src/common/utils.cpp
  164. 12
      src/snark/src/common/utils.hpp
  165. 2
      src/snark/src/common/utils.tcc
  166. 40
      src/snark/src/gadgetlib1/gadgets/basic_gadgets.tcc
  167. 2
      src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_aux.tcc
  168. 4
      src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_components.hpp
  169. 6
      src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_components.tcc
  170. 6
      src/snark/src/gadgetlib1/gadgets/hashes/sha256/tests/test_sha256_gadget.cpp
  171. 4
      src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.tcc
  172. 4
      src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.tcc
  173. 1
      src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.hpp
  174. 4
      src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.tcc
  175. 22
      src/snark/src/gadgetlib1/gadgets/merkle_tree/tests/test_merkle_tree_gadgets.cpp
  176. 4
      src/snark/src/gadgetlib1/pb_variable.hpp
  177. 4
      src/snark/src/gadgetlib1/pb_variable.tcc
  178. 31
      src/snark/src/relations/arithmetic_programs/qap/tests/test_qap.cpp
  179. 2
      src/snark/src/relations/variable.hpp
  180. 2
      src/snark/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.tcc
  181. 14
      src/snark/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp
  182. 7
      src/test/scheduler_tests.cpp
  183. 1
      src/txdb.cpp
  184. 6
      src/univalue/include/univalue.h
  185. 4
      src/util.cpp
  186. 2
      src/utiltest.cpp
  187. 2
      src/wallet/asyncrpcoperation_sendmany.cpp
  188. 8
      src/wallet/crypter.cpp
  189. 2
      src/wallet/crypter.h
  190. 2
      src/wallet/gtest/test_wallet.cpp
  191. 91
      src/wallet/gtest/test_wallet_zkeys.cpp
  192. 18
      src/wallet/rpcdisclosure.cpp
  193. 136
      src/wallet/rpcdump.cpp
  194. 90
      src/wallet/rpcwallet.cpp
  195. 83
      src/wallet/wallet.cpp
  196. 180
      src/wallet/wallet.h
  197. 42
      src/wallet/walletdb.cpp
  198. 5
      src/wallet/walletdb.h
  199. 14
      src/zcash/Address.cpp
  200. 42
      src/zcash/Address.hpp
  201. 7
      src/zcash/IncrementalMerkleTree.hpp
  202. 1
      src/zcash/JoinSplit.cpp
  203. 7
      src/zcash/JoinSplit.hpp
  204. 6
      src/zcash/Note.hpp
  205. 1
      src/zcash/NoteEncryption.cpp
  206. 1
      src/zcash/NoteEncryption.hpp
  207. 1
      src/zcash/Proof.cpp
  208. 6
      src/zcash/Proof.hpp
  209. 6
      src/zcash/Zcash.h
  210. 6
      src/zcash/prf.h
  211. 6
      src/zcash/util.h
  212. 2
      zcutil/build-debian-package.sh
  213. 2
      zcutil/cleanup-tags.sh
  214. 2
      zcutil/fetch-params.sh
  215. 57
      zcutil/make-release.py
  216. 41
      zcutil/release-notes.py

4
README.md

@ -1,4 +1,4 @@
# HUSH 1.0.13
# HUSH 1.0.14
## What is HUSH?
@ -99,4 +99,4 @@ A [HUSH GUI Wallet](https://github.com/MyHush/hush-swing-wallet-ui/releases/tag/
License
-------
For license information see the file [COPYING](COPYING).
For license information see the file [COPYING](COPYING).

17
configure.ac

@ -455,13 +455,22 @@ if test x$use_hardening != xno; then
HARDENED_CPPFLAGS="$HARDENED_CPPFLAGS -D_FORTIFY_SOURCE=2"
],[AC_MSG_ERROR(Cannot enable -D_FORTIFY_SOURCE=2)])
if test x$TARGET_OS != xwindows; then
if test x$BUILD_OS == xlinux; then
AX_CHECK_LINK_FLAG([[-Wl,-z,relro]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,relro"],[AC_MSG_ERROR(Cannot enable RELRO)])
AX_CHECK_LINK_FLAG([[-Wl,-z,now]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,now"],[AC_MSG_ERROR(Cannot enable BIND_NOW)])
else
AX_CHECK_LINK_FLAG([[-Wl,-z,relro]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,relro"],[AC_MSG_WARN(Cannot enable RELRO)])
AX_CHECK_LINK_FLAG([[-Wl,-z,now]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,now"],[AC_MSG_WARN(Cannot enable BIND_NOW)])
fi
if test x$TARGET_OS != xwindows; then
# All windows code is PIC, forcing it on just adds useless compile warnings
AX_CHECK_COMPILE_FLAG([-fPIE],[PIE_FLAGS="-fPIE"],[AC_MSG_ERROR(Cannot enable -fPIE)])
AX_CHECK_LINK_FLAG([[-pie]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -pie"],[AC_MSG_ERROR(Cannot enable -pie)])
if test x$BUILD_OS = xdarwin; then
AX_CHECK_LINK_FLAG([[-pie]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -pie"],[AC_MSG_WARN(Cannot enable -pie)])
else
AX_CHECK_LINK_FLAG([[-pie]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -pie"],[AC_MSG_ERROR(Cannot enable -pie)])
fi
else
# These are only available on Windows.
AX_CHECK_LINK_FLAG([[-Wl,--dynamicbase]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--dynamicbase"],[AC_MSG_ERROR(Cannot enable --dynamicbase)])
@ -721,6 +730,10 @@ AX_CHECK_COMPILE_FLAG([-fwrapv],[CXXFLAGS="$CXXFLAGS -fwrapv"])
AX_CHECK_COMPILE_FLAG([-fno-strict-aliasing],[CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"])
AX_CHECK_COMPILE_FLAG([-Wno-builtin-declaration-mismatch],[CXXFLAGS="$CXXFLAGS -Wno-builtin-declaration-mismatch"],,[[$CXXFLAG_WERROR]])
if test x$BUILD_OS = xdarwin; then
AX_CHECK_COMPILE_FLAG([-Wno-undefined-var-template],[CXXFLAGS="$CXXFLAGS -Wno-undefined-var-template"],,[[$CXXFLAG_WERROR]])
fi
LIBZCASH_LIBS="-lgmp -lgmpxx -lboost_system-mt -lcrypto -lsodium $RUST_LIBS"
AC_MSG_CHECKING([whether to build bitcoind])

1
contrib/ci-workers/grind.yml

@ -25,4 +25,3 @@
name: "{{ item }}"
state: present
with_items: "{{ grind_deps }}"

2
contrib/devtools/README.md

@ -98,4 +98,4 @@ maintained:
* for sec/leveldb: https://github.com/bitcoin/leveldb.git (branch bitcoin-fork)
Usage: git-subtree-check.sh DIR COMMIT
COMMIT may be omitted, in which case HEAD is used.
COMMIT may be omitted, in which case HEAD is used.

8
depends/builders/darwin.mk

@ -1,5 +1,5 @@
build_darwin_CC = gcc-5
build_darwin_CXX = g++-5
build_darwin_CC: = $(shell xcrun -f clang)
build_darwin_CXX: = $(shell xcrun -f clang++)
build_darwin_AR: = $(shell xcrun -f ar)
build_darwin_RANLIB: = $(shell xcrun -f ranlib)
build_darwin_STRIP: = $(shell xcrun -f strip)
@ -10,8 +10,8 @@ build_darwin_SHA256SUM = shasum -a 256
build_darwin_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o
#darwin host on darwin builder. overrides darwin host preferences.
darwin_CC= gcc-5
darwin_CXX= g++-5
darwin_CC=$(shell xcrun -f clang) -mmacosx-version-min=$(OSX_MIN_VERSION)
darwin_CXX:=$(shell xcrun -f clang++) -mmacosx-version-min=$(OSX_MIN_VERSION) -stdlib=libc++
darwin_AR:=$(shell xcrun -f ar)
darwin_RANLIB:=$(shell xcrun -f ranlib)
darwin_STRIP:=$(shell xcrun -f strip)

7
depends/packages/bdb.mk

@ -14,17 +14,14 @@ endef
define $(package)_preprocess_cmds
sed -i.old 's/__atomic_compare_exchange\\(/__atomic_compare_exchange_db(/' src/dbinc/atomic.h && \
sed -i.old 's/atomic_init/atomic_init_db/' src/dbinc/atomic.h src/mp/mp_region.c src/mp/mp_mvcc.c src/mp/mp_fget.c src/mutex/mut_method.c src/mutex/mut_tas.c
sed -i.old 's/atomic_init/atomic_init_db/' src/dbinc/atomic.h src/mp/mp_region.c src/mp/mp_mvcc.c src/mp/mp_fget.c src/mutex/mut_method.c src/mutex/mut_tas.c && \
sed -i -e "s/WinIoCtl.h/winioctl.h/g" src/dbinc/win_db.h
endef
define $(package)_config_cmds
../dist/$($(package)_autoconf)
endef
define $(package)_preprocess_cmds
sed -i -e "s/WinIoCtl.h/winioctl.h/g" src/dbinc/win_db.h
endef
define $(package)_build_cmds
$(MAKE) libdb_cxx-6.2.a libdb-6.2.a
endef

8
depends/packages/boost.mk

@ -11,14 +11,14 @@ $(package)_config_opts_debug=variant=debug
$(package)_config_opts=--layout=tagged --build-type=complete --user-config=user-config.jam
$(package)_config_opts+=threading=multi link=static -sNO_BZIP2=1 -sNO_ZLIB=1
$(package)_config_opts_linux=threadapi=pthread runtime-link=shared
$(package)_config_opts_darwin=--toolset=gcc threadapi=pthread runtime-link=shared
$(package)_config_opts_darwin=--toolset=darwin-4.2.1 runtime-link=shared
$(package)_config_opts_mingw32=binary-format=pe target-os=windows threadapi=win32 runtime-link=static
$(package)_config_opts_x86_64_mingw32=address-model=64
$(package)_config_opts_i686_mingw32=address-model=32
$(package)_config_opts_i686_linux=address-model=32 architecture=x86
$(package)_toolset_$(host_os)=gcc
$(package)_archiver_$(host_os)=$($(package)_ar)
$(package)_toolset_darwin=gcc
$(package)_toolset_darwin=darwin
$(package)_archiver_darwin=$($(package)_libtool)
$(package)_config_libraries=chrono,filesystem,program_options,system,thread,test
$(package)_cxxflags=-std=c++11 -fvisibility=hidden
@ -36,9 +36,9 @@ define $(package)_config_cmds
endef
define $(package)_build_cmds
./b2 -d2 -j2 -d1 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) cxxflags=-std=c++11 stage
./b2 -d2 -j2 -d1 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) stage
endef
define $(package)_stage_cmds
./b2 -d0 -j4 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) cxxflags=-std=c++11 install
./b2 -d0 -j4 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) install
endef

6
depends/packages/googlemock.mk

@ -13,12 +13,6 @@ define $(package)_build_cmds
$(MAKE) -C make GTEST_DIR='$(host_prefix)' CXXFLAGS='-fPIC' gmock-all.o
endef
BUILD_OS := $(shell uname)
ifeq ($(BUILD_OS),Darwin)
$(package)_install=ginstall
else
$(package)_install=install
endif
define $(package)_stage_cmds
install -D ./make/gmock-all.o $($(package)_staging_dir)$(host_prefix)/lib/libgmock.a && \

7
depends/packages/googletest.mk

@ -5,13 +5,6 @@ $(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_download_file=release-$($(package)_version).tar.gz
$(package)_sha256_hash=58a6f4277ca2bc8565222b3bbd58a177609e9c488e8a72649359ba51450db7d8
BUILD_OS := $(shell uname)
ifeq ($(BUILD_OS),Darwin)
$(package)_install=ginstall
else
$(package)_install=install
endif
define $(package)_build_cmds
$(MAKE) -C googlemock/make CXXFLAGS=-fPIC gmock.a && \
$(MAKE) -C googletest/make CXXFLAGS=-fPIC gtest.a

1
qa/pull-tester/rpc-tests.sh

@ -46,6 +46,7 @@ testScripts=(
'disablewallet.py'
'zcjoinsplit.py'
'zcjoinsplitdoublespend.py'
'zkey_import_export.py'
'getblocktemplate.py'
'bip65-cltv-p2p.py'
'bipdersig-p2p.py'

8
qa/rpc-tests/README.md

@ -1,4 +1,10 @@
# Regression tests of RPC interface
Regression tests of RPC interface
=================================
### [python-bitcoinrpc](https://github.com/jgarzik/python-bitcoinrpc)
Git subtree of [https://github.com/jgarzik/python-bitcoinrpc](https://github.com/jgarzik/python-bitcoinrpc).
Changes to python-bitcoinrpc should be made upstream, and then
pulled here using git subtree.
### [test_framework/test_framework.py](test_framework/test_framework.py)
Base class for new regression tests.

1
qa/rpc-tests/bip65-cltv-p2p.py

@ -94,4 +94,3 @@ class BIP65Test(ComparisonTestFramework):
if __name__ == '__main__':
BIP65Test().main()

1
qa/rpc-tests/bipdersig-p2p.py

@ -100,4 +100,3 @@ class BIP66Test(ComparisonTestFramework):
if __name__ == '__main__':
BIP66Test().main()

33
qa/rpc-tests/mempool_tx_input_limit.py

@ -6,7 +6,7 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, initialize_chain_clean, \
start_node, connect_nodes
start_node, connect_nodes, wait_and_assert_operationid_status
import time
from decimal import Decimal
@ -33,34 +33,7 @@ class MempoolTxInputLimitTest(BitcoinTestFramework):
recipients = []
recipients.append({"address": to_addr, "amount": amount})
myopid = self.nodes[0].z_sendmany(from_addr, recipients)
return self.wait_and_assert_operationid_status(myopid)
def wait_and_assert_operationid_status(self, myopid, in_status='success', in_errormsg=None):
print('waiting for async operation {}'.format(myopid))
opids = []
opids.append(myopid)
timeout = 300
status = None
errormsg = None
txid = None
for x in xrange(1, timeout):
results = self.nodes[0].z_getoperationresult(opids)
if len(results)==0:
time.sleep(1)
else:
status = results[0]["status"]
if status == "failed":
errormsg = results[0]['error']['message']
elif status == "success":
txid = results[0]['result']['txid']
break
print('...returned status: {}'.format(status))
assert_equal(in_status, status)
if errormsg is not None:
assert(in_errormsg is not None)
assert_equal(in_errormsg in errormsg, True)
print('...returned error: {}'.format(errormsg))
return txid
return wait_and_assert_operationid_status(self.nodes[0], myopid)
def run_test(self):
self.nodes[0].generate(100)
@ -126,7 +99,7 @@ class MempoolTxInputLimitTest(BitcoinTestFramework):
recipients.append({"address":self.nodes[1].getnewaddress(), "amount": spend_taddr_amount - spend_taddr_output - spend_taddr_output})
myopid = self.nodes[0].z_sendmany(node0_zaddr, recipients)
self.wait_and_assert_operationid_status(myopid)
wait_and_assert_operationid_status(self.nodes[0], myopid)
self.nodes[1].generate(1)
self.sync_all()

17
qa/rpc-tests/nodehandling.py

@ -62,22 +62,5 @@ class NodeHandlingTest (BitcoinTestFramework):
found = True
assert(found)
###########################
# Connection to self (takes approx 5 min)
# Stress test for network layer. Trying to connect to self every 0.5 sec.
# Helps to discover different multi-threading problems.
###########################
url = urlparse.urlparse(self.nodes[0].url)
print "Connection to self stress test. " \
"Constantly trying to connect to self every 0.5 sec. " \
"The whole test takes approx 5 mins"
for x in xrange(600):
connect_nodes(self.nodes[0], 0)
time.sleep(0.5)
# self-connection should be disconnected during the version checking
for node in self.nodes[0].getpeerinfo():
assert(node['addr'] != url.hostname+":"+str(p2p_port(0)))
if __name__ == '__main__':
NodeHandlingTest ().main ()

47
qa/rpc-tests/paymentdisclosure.py

@ -6,9 +6,8 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, initialize_chain_clean, \
start_node, connect_nodes_bi
start_node, connect_nodes_bi, wait_and_assert_operationid_status
import time
from decimal import Decimal
class PaymentDisclosureTest (BitcoinTestFramework):
@ -31,34 +30,6 @@ class PaymentDisclosureTest (BitcoinTestFramework):
self.is_network_split=False
self.sync_all()
# Returns txid if operation was a success or None
def wait_and_assert_operationid_status(self, nodeid, myopid, in_status='success', in_errormsg=None):
print('waiting for async operation {}'.format(myopid))
opids = []
opids.append(myopid)
timeout = 300
status = None
errormsg = None
txid = None
for x in xrange(1, timeout):
results = self.nodes[nodeid].z_getoperationresult(opids)
if len(results)==0:
time.sleep(1)
else:
status = results[0]["status"]
if status == "failed":
errormsg = results[0]['error']['message']
elif status == "success":
txid = results[0]['result']['txid']
break
print('...returned status: {}'.format(status))
assert_equal(in_status, status)
if errormsg is not None:
assert(in_errormsg is not None)
assert(in_errormsg in errormsg)
print('...returned error: {}'.format(errormsg))
return txid
def run_test (self):
print "Mining blocks..."
@ -97,7 +68,7 @@ class PaymentDisclosureTest (BitcoinTestFramework):
# Shield coinbase utxos from node 0 of value 40, standard fee of 0.00010000
recipients = [{"address":myzaddr, "amount":Decimal('40.0')-Decimal('0.0001')}]
myopid = self.nodes[0].z_sendmany(mytaddr, recipients)
txid = self.wait_and_assert_operationid_status(0, myopid)
txid = wait_and_assert_operationid_status(self.nodes[0], myopid)
# Check the tx has joinsplits
assert( len(self.nodes[0].getrawtransaction("" + txid, 1)["vjoinsplit"]) > 0 )
@ -175,6 +146,17 @@ class PaymentDisclosureTest (BitcoinTestFramework):
assert_equal(result["message"], message)
assert_equal(result["value"], output_value_sum)
# Confirm that payment disclosure begins with prefix zpd:
assert(pd.startswith("zpd:"))
# Confirm that payment disclosure without prefix zpd: fails validation
try:
self.nodes[1].z_validatepaymentdisclosure(pd[4:])
assert(False)
except JSONRPCException as e:
errorString = e.error['message']
assert("payment disclosure prefix not found" in errorString)
# Check that total value of output index 0 and index 1 should equal shielding amount of 40 less standard fee.
pd = self.nodes[0].z_getpaymentdisclosure(txid, 0, 1)
result = self.nodes[0].z_validatepaymentdisclosure(pd)
@ -185,7 +167,7 @@ class PaymentDisclosureTest (BitcoinTestFramework):
node1zaddr = self.nodes[1].z_getnewaddress()
recipients = [{"address":node1zaddr, "amount":Decimal('1')}]
myopid = self.nodes[0].z_sendmany(myzaddr, recipients)
txid = self.wait_and_assert_operationid_status(0, myopid)
txid = wait_and_assert_operationid_status(self.nodes[0], myopid)
self.sync_all()
self.nodes[0].generate(1)
self.sync_all()
@ -231,4 +213,3 @@ class PaymentDisclosureTest (BitcoinTestFramework):
if __name__ == '__main__':
PaymentDisclosureTest().main()

28
qa/rpc-tests/prioritisetransaction.py

@ -26,34 +26,6 @@ class PrioritiseTransactionTest (BitcoinTestFramework):
self.is_network_split=False
self.sync_all()
# Returns txid if operation was a success or None
def wait_and_assert_operationid_status(self, myopid, in_status='success', in_errormsg=None):
print('waiting for async operation {}'.format(myopid))
opids = []
opids.append(myopid)
timeout = 300
status = None
errormsg = None
txid = None
for x in xrange(1, timeout):
results = self.nodes[0].z_getoperationresult(opids)
if len(results)==0:
time.sleep(1)
else:
status = results[0]["status"]
if status == "failed":
errormsg = results[0]['error']['message']
elif status == "success":
txid = results[0]['result']['txid']
break
print('...returned status: {}'.format(status))
assert_equal(in_status, status)
if errormsg is not None:
assert(in_errormsg is not None)
assert_equal(in_errormsg in errormsg, True)
print('...returned error: {}'.format(errormsg))
return txid
def run_test (self):
# tx priority is calculated: priority = sum(input_value_in_base_units * input_age)/size_in_bytes

1
qa/rpc-tests/proxy_test.py

@ -177,3 +177,4 @@ class ProxyTest(BitcoinTestFramework):
if __name__ == '__main__':
ProxyTest().main()

1
qa/rpc-tests/test_framework/blocktools.py

@ -76,4 +76,3 @@ def create_transaction(prevtx, n, sig, value):
tx.vout.append(CTxOut(value, ""))
tx.calc_sha256()
return tx

1
qa/rpc-tests/test_framework/equihash.py

@ -291,4 +291,3 @@ def validate_params(n, k):
raise ValueError('n must be larger than k')
if (((n/(k+1))+1) >= 32):
raise ValueError('Parameters must satisfy n/(k+1)+1 < 32')

1
qa/rpc-tests/test_framework/netutil.py

@ -137,4 +137,3 @@ def addr_to_hex(addr):
else:
raise ValueError('Could not parse address %s' % addr)
return binascii.hexlify(bytearray(addr))

30
qa/rpc-tests/test_framework/util.py

@ -368,3 +368,33 @@ def assert_raises(exc, fun, *args, **kwds):
raise AssertionError("Unexpected exception raised: "+type(e).__name__)
else:
raise AssertionError("No exception raised")
# Returns txid if operation was a success or None
def wait_and_assert_operationid_status(node, myopid, in_status='success', in_errormsg=None):
print('waiting for async operation {}'.format(myopid))
opids = []
opids.append(myopid)
timeout = 300
status = None
errormsg = None
txid = None
for x in xrange(1, timeout):
results = node.z_getoperationresult(opids)
if len(results)==0:
time.sleep(1)
else:
status = results[0]["status"]
if status == "failed":
errormsg = results[0]['error']['message']
elif status == "success":
txid = results[0]['result']['txid']
break
assert_equal(in_status, status)
if errormsg is not None:
assert(in_errormsg is not None)
assert_equal(in_errormsg in errormsg, True)
if os.getenv("PYTHON_DEBUG", ""):
print('...returned status: {}'.format(status))
if errormsg is not None:
print('...returned error: {}'.format(errormsg))
return txid

29
qa/rpc-tests/wallet_1941.py

@ -8,9 +8,8 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, initialize_chain_clean, \
initialize_datadir, start_nodes, start_node, connect_nodes_bi, \
bitcoind_processes
bitcoind_processes, wait_and_assert_operationid_status
import time
from decimal import Decimal
starttime = 1388534400
@ -41,30 +40,6 @@ class Wallet1941RegressionTest (BitcoinTestFramework):
connect_nodes_bi(self.nodes, 0, 1)
self.sync_all()
def wait_and_assert_operationid_status(self, myopid, in_status='success', in_errormsg=None):
print('waiting for async operation {}'.format(myopid))
opids = []
opids.append(myopid)
timeout = 300
status = None
errormsg = None
for x in xrange(1, timeout):
results = self.nodes[0].z_getoperationresult(opids)
if len(results)==0:
time.sleep(1)
else:
status = results[0]["status"]
if status == "failed":
errormsg = results[0]['error']['message']
break
print('...returned status: {}'.format(status))
print('...error msg: {}'.format(errormsg))
assert_equal(in_status, status)
if errormsg is not None:
assert(in_errormsg is not None)
assert_equal(in_errormsg in errormsg, True)
print('...returned error: {}'.format(errormsg))
def run_test (self):
print "Mining blocks..."
@ -78,7 +53,7 @@ class Wallet1941RegressionTest (BitcoinTestFramework):
recipients = []
recipients.append({"address":myzaddr, "amount":Decimal('10.0') - Decimal('0.0001')})
myopid = self.nodes[0].z_sendmany(mytaddr, recipients)
self.wait_and_assert_operationid_status(myopid)
wait_and_assert_operationid_status(self.nodes[0], myopid)
self.nodes[0].generate(1)
# Ensure the block times of the latest blocks exceed the variability

45
qa/rpc-tests/wallet_nullifiers.py

@ -170,5 +170,50 @@ class WalletNullifiersTest (BitcoinTestFramework):
assert_equal(self.nodes[1].z_getbalance(myzaddr), zaddrremaining2)
assert_equal(self.nodes[2].z_getbalance(myzaddr), zaddrremaining2)
# Test viewing keys
node3mined = Decimal('250.0')
assert_equal({k: Decimal(v) for k, v in self.nodes[3].z_gettotalbalance().items()}, {
'transparent': node3mined,
'private': zsendmany2notevalue,
'total': node3mined + zsendmany2notevalue,
})
# add node 1 address and node 2 viewing key to node 3
myzvkey = self.nodes[2].z_exportviewingkey(myzaddr)
self.nodes[3].importaddress(mytaddr1)
self.nodes[3].z_importviewingkey(myzvkey)
# Check the address has been imported
assert_equal(myzaddr in self.nodes[3].z_listaddresses(), False)
assert_equal(myzaddr in self.nodes[3].z_listaddresses(True), True)
# Node 3 should see the same received notes as node 2
assert_equal(
self.nodes[2].z_listreceivedbyaddress(myzaddr),
self.nodes[3].z_listreceivedbyaddress(myzaddr))
# Node 3's balances should be unchanged without explicitly requesting
# to include watch-only balances
assert_equal({k: Decimal(v) for k, v in self.nodes[3].z_gettotalbalance().items()}, {
'transparent': node3mined,
'private': zsendmany2notevalue,
'total': node3mined + zsendmany2notevalue,
})
# Wallet can't cache nullifiers for notes received by addresses it only has a
# viewing key for, and therefore can't detect spends. So it sees a balance
# corresponding to the sum of all notes the address received.
# TODO: Fix this during the Sapling upgrade (via #2277)
assert_equal({k: Decimal(v) for k, v in self.nodes[3].z_gettotalbalance(1, True).items()}, {
'transparent': node3mined + Decimal('1.0'),
'private': zsendmany2notevalue + zsendmanynotevalue + zaddrremaining + zaddrremaining2,
'total': node3mined + Decimal('1.0') + zsendmany2notevalue + zsendmanynotevalue + zaddrremaining + zaddrremaining2,
})
# Check individual balances reflect the above
assert_equal(self.nodes[3].z_getbalance(mytaddr1), Decimal('1.0'))
assert_equal(self.nodes[3].z_getbalance(myzaddr), zsendmanynotevalue + zaddrremaining + zaddrremaining2)
if __name__ == '__main__':
WalletNullifiersTest().main ()

53
qa/rpc-tests/wallet_protectcoinbase.py

@ -7,13 +7,23 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, initialize_chain_clean, \
start_nodes, connect_nodes_bi, stop_node
start_nodes, connect_nodes_bi, stop_node, wait_and_assert_operationid_status
import sys
import time
import timeit
from decimal import Decimal
def check_value_pool(node, name, total):
value_pools = node.getblockchaininfo()['valuePools']
found = False
for pool in value_pools:
if pool['id'] == name:
found = True
assert_equal(pool['monitored'], True)
assert_equal(pool['chainValue'], total)
assert(found)
class WalletProtectCoinbaseTest (BitcoinTestFramework):
def setup_chain(self):
@ -76,6 +86,11 @@ class WalletProtectCoinbaseTest (BitcoinTestFramework):
assert_equal(self.nodes[2].getbalance(), 0)
assert_equal(self.nodes[3].getbalance(), 0)
check_value_pool(self.nodes[0], 'sprout', 0)
check_value_pool(self.nodes[1], 'sprout', 0)
check_value_pool(self.nodes[2], 'sprout', 0)
check_value_pool(self.nodes[3], 'sprout', 0)
# Send will fail because we are enforcing the consensus rule that
# coinbase utxos can only be sent to a zaddr.
errorString = ""
@ -141,10 +156,11 @@ class WalletProtectCoinbaseTest (BitcoinTestFramework):
assert_equal("wallet does not allow any change" in errorString, True)
# This send will succeed. We send two coinbase utxos totalling 20.0 less a fee of 0.00010000, with no change.
shieldvalue = Decimal('20.0') - Decimal('0.0001')
recipients = []
recipients.append({"address":myzaddr, "amount": Decimal('20.0') - Decimal('0.0001')})
recipients.append({"address":myzaddr, "amount": shieldvalue})
myopid = self.nodes[0].z_sendmany(mytaddr, recipients)
mytxid = self.wait_and_assert_operationid_status(myopid)
mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid)
self.sync_all()
self.nodes[1].generate(1)
self.sync_all()
@ -169,11 +185,15 @@ class WalletProtectCoinbaseTest (BitcoinTestFramework):
assert_equal(Decimal(resp["private"]), Decimal('19.9999'))
assert_equal(Decimal(resp["total"]), Decimal('39.9999'))
# The Sprout value pool should reflect the send
sproutvalue = shieldvalue
check_value_pool(self.nodes[0], 'sprout', sproutvalue)
# A custom fee of 0 is okay. Here the node will send the note value back to itself.
recipients = []
recipients.append({"address":myzaddr, "amount": Decimal('19.9999')})
myopid = self.nodes[0].z_sendmany(myzaddr, recipients, 1, Decimal('0.0'))
mytxid = self.wait_and_assert_operationid_status(myopid)
mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid)
self.sync_all()
self.nodes[1].generate(1)
self.sync_all()
@ -182,11 +202,15 @@ class WalletProtectCoinbaseTest (BitcoinTestFramework):
assert_equal(Decimal(resp["private"]), Decimal('19.9999'))
assert_equal(Decimal(resp["total"]), Decimal('39.9999'))
# The Sprout value pool should be unchanged
check_value_pool(self.nodes[0], 'sprout', sproutvalue)
# convert note to transparent funds
unshieldvalue = Decimal('10.0')
recipients = []
recipients.append({"address":mytaddr, "amount":Decimal('10.0')})
recipients.append({"address":mytaddr, "amount": unshieldvalue})
myopid = self.nodes[0].z_sendmany(myzaddr, recipients)
mytxid = self.wait_and_assert_operationid_status(myopid)
mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid)
assert(mytxid is not None)
self.sync_all()
@ -198,10 +222,12 @@ class WalletProtectCoinbaseTest (BitcoinTestFramework):
self.sync_all()
# check balances
sproutvalue -= unshieldvalue + Decimal('0.0001')
resp = self.nodes[0].z_gettotalbalance()
assert_equal(Decimal(resp["transparent"]), Decimal('30.0'))
assert_equal(Decimal(resp["private"]), Decimal('9.9998'))
assert_equal(Decimal(resp["total"]), Decimal('39.9998'))
check_value_pool(self.nodes[0], 'sprout', sproutvalue)
# z_sendmany will return an error if there is transparent change output considered dust.
# UTXO selection in z_sendmany sorts in ascending order, so smallest utxos are consumed first.
@ -210,7 +236,7 @@ class WalletProtectCoinbaseTest (BitcoinTestFramework):
amount = Decimal('10.0') - Decimal('0.00010000') - Decimal('0.00000001') # this leaves change at 1 zatoshi less than dust threshold
recipients.append({"address":self.nodes[0].getnewaddress(), "amount":amount })
myopid = self.nodes[0].z_sendmany(mytaddr, recipients)
self.wait_and_assert_operationid_status(myopid, "failed", "Insufficient transparent funds, have 10.00, need 0.00000053 more to avoid creating invalid change output 0.00000001 (dust threshold is 0.00000054)")
wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Insufficient transparent funds, have 10.00, need 0.00000053 more to avoid creating invalid change output 0.00000001 (dust threshold is 0.00000054)")
# Send will fail because send amount is too big, even when including coinbase utxos
errorString = ""
@ -224,9 +250,9 @@ class WalletProtectCoinbaseTest (BitcoinTestFramework):
recipients = []
recipients.append({"address":self.nodes[1].getnewaddress(), "amount":Decimal('10000.0')})
myopid = self.nodes[0].z_sendmany(mytaddr, recipients)
self.wait_and_assert_operationid_status(myopid, "failed", "Insufficient transparent funds, have 10.00, need 10000.0001")
wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Insufficient transparent funds, have 10.00, need 10000.0001")
myopid = self.nodes[0].z_sendmany(myzaddr, recipients)
self.wait_and_assert_operationid_status(myopid, "failed", "Insufficient protected funds, have 9.9998, need 10000.0001")
wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Insufficient protected funds, have 9.9998, need 10000.0001")
# Send will fail because of insufficient funds unless sender uses coinbase utxos
try:
@ -263,7 +289,7 @@ class WalletProtectCoinbaseTest (BitcoinTestFramework):
myopid = self.nodes[0].z_sendmany(myzaddr, recipients)
try:
self.wait_and_assert_operationid_status(myopid)
wait_and_assert_operationid_status(self.nodes[0], myopid)
except JSONRPCException as e:
print("JSONRPC error: "+e.error['message'])
assert(False)
@ -277,7 +303,9 @@ class WalletProtectCoinbaseTest (BitcoinTestFramework):
# check balance
node2balance = amount_per_recipient * num_t_recipients
sproutvalue -= node2balance + Decimal('0.0001')
assert_equal(self.nodes[2].getbalance(), node2balance)
check_value_pool(self.nodes[0], 'sprout', sproutvalue)
# Send will fail because fee is negative
try:
@ -326,7 +354,7 @@ class WalletProtectCoinbaseTest (BitcoinTestFramework):
newzaddr = self.nodes[2].z_getnewaddress()
recipients.append({"address":newzaddr, "amount":amount_per_recipient})
myopid = self.nodes[0].z_sendmany(myzaddr, recipients, minconf, custom_fee)
self.wait_and_assert_operationid_status(myopid)
wait_and_assert_operationid_status(self.nodes[0], myopid)
self.sync_all()
self.nodes[1].generate(1)
self.sync_all()
@ -336,7 +364,8 @@ class WalletProtectCoinbaseTest (BitcoinTestFramework):
assert_equal(Decimal(resp["private"]), send_amount)
resp = self.nodes[0].z_getbalance(myzaddr)
assert_equal(Decimal(resp), zbalance - custom_fee - send_amount)
sproutvalue -= custom_fee
check_value_pool(self.nodes[0], 'sprout', sproutvalue)
if __name__ == '__main__':
WalletProtectCoinbaseTest().main()

96
qa/rpc-tests/wallet_shieldcoinbase.py

@ -7,9 +7,9 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, initialize_chain_clean, \
start_node, connect_nodes_bi, sync_blocks
start_node, connect_nodes_bi, sync_blocks, sync_mempools, \
wait_and_assert_operationid_status
import time
from decimal import Decimal
class WalletShieldCoinbaseTest (BitcoinTestFramework):
@ -19,11 +19,11 @@ class WalletShieldCoinbaseTest (BitcoinTestFramework):
initialize_chain_clean(self.options.tmpdir, 4)
def setup_network(self, split=False):
args = ['-regtestprotectcoinbase', '-debug=zrpcunsafe', '-experimentalfeatures', '-zshieldcoinbase']
args = ['-regtestprotectcoinbase', '-debug=zrpcunsafe']
self.nodes = []
self.nodes.append(start_node(0, self.options.tmpdir, args))
self.nodes.append(start_node(1, self.options.tmpdir, args))
args2 = ['-regtestprotectcoinbase', '-debug=zrpcunsafe', '-experimentalfeatures', '-zshieldcoinbase', "-mempooltxinputlimit=7"]
args2 = ['-regtestprotectcoinbase', '-debug=zrpcunsafe', "-mempooltxinputlimit=7"]
self.nodes.append(start_node(2, self.options.tmpdir, args2))
connect_nodes_bi(self.nodes,0,1)
connect_nodes_bi(self.nodes,1,2)
@ -31,34 +31,6 @@ class WalletShieldCoinbaseTest (BitcoinTestFramework):
self.is_network_split=False
self.sync_all()
# Returns txid if operation was a success or None
def wait_and_assert_operationid_status(self, nodeid, myopid, in_status='success', in_errormsg=None):
print('waiting for async operation {}'.format(myopid))
opids = []
opids.append(myopid)
timeout = 300
status = None
errormsg = None
txid = None
for x in xrange(1, timeout):
results = self.nodes[nodeid].z_getoperationresult(opids)
if len(results)==0:
time.sleep(1)
else:
status = results[0]["status"]
if status == "failed":
errormsg = results[0]['error']['message']
elif status == "success":
txid = results[0]['result']['txid']
break
print('...returned status: {}'.format(status))
assert_equal(in_status, status)
if errormsg is not None:
assert(in_errormsg is not None)
assert_equal(in_errormsg in errormsg, True)
print('...returned error: {}'.format(errormsg))
return txid
def run_test (self):
print "Mining blocks..."
@ -115,9 +87,23 @@ class WalletShieldCoinbaseTest (BitcoinTestFramework):
errorString = e.error['message']
assert_equal("Insufficient coinbase funds" in errorString, True)
# Shielding will fail because limit parameter must be at least 0
try:
self.nodes[0].z_shieldcoinbase("*", myzaddr, Decimal('0.001'), -1)
except JSONRPCException,e:
errorString = e.error['message']
assert_equal("Limit on maximum number of utxos cannot be negative" in errorString, True)
# Shielding will fail because limit parameter is absurdly large
try:
self.nodes[0].z_shieldcoinbase("*", myzaddr, Decimal('0.001'), 99999999999999)
except JSONRPCException,e:
errorString = e.error['message']
assert_equal("JSON integer out of range" in errorString, True)
# Shield coinbase utxos from node 0 of value 40, standard fee of 0.00010000
result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr)
self.wait_and_assert_operationid_status(0, result['opid'])
wait_and_assert_operationid_status(self.nodes[0], result['opid'])
self.sync_all()
self.nodes[1].generate(1)
self.sync_all()
@ -131,7 +117,7 @@ class WalletShieldCoinbaseTest (BitcoinTestFramework):
# Shield coinbase utxos from any node 2 taddr, and set fee to 0
result = self.nodes[2].z_shieldcoinbase("*", myzaddr, 0)
self.wait_and_assert_operationid_status(2, result['opid'])
wait_and_assert_operationid_status(self.nodes[2], result['opid'])
self.sync_all()
self.nodes[1].generate(1)
self.sync_all()
@ -152,14 +138,15 @@ class WalletShieldCoinbaseTest (BitcoinTestFramework):
# Shielding the 800 utxos will occur over two transactions, since max tx size is 100,000 bytes.
# We don't verify shieldingValue as utxos are not selected in any specific order, so value can change on each test run.
result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr, 0)
# We set an unrealistically high limit parameter of 99999, to verify that max tx size will constrain the number of utxos.
result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr, 0, 99999)
assert_equal(result["shieldingUTXOs"], Decimal('662'))
assert_equal(result["remainingUTXOs"], Decimal('138'))
remainingValue = result["remainingValue"]
opid1 = result['opid']
# Verify that utxos are locked (not available for selection) by queuing up another shielding operation
result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr)
result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr, 0, 0)
assert_equal(result["shieldingValue"], Decimal(remainingValue))
assert_equal(result["shieldingUTXOs"], Decimal('138'))
assert_equal(result["remainingValue"], Decimal('0'))
@ -167,24 +154,47 @@ class WalletShieldCoinbaseTest (BitcoinTestFramework):
opid2 = result['opid']
# wait for both aysnc operations to complete
self.wait_and_assert_operationid_status(0, opid1)
self.wait_and_assert_operationid_status(0, opid2)
wait_and_assert_operationid_status(self.nodes[0], opid1)
wait_and_assert_operationid_status(self.nodes[0], opid2)
# sync_all() invokes sync_mempool() but node 2's mempool limit will cause tx1 and tx2 to be rejected.
# So instead, we sync on blocks, and after a new block is generated, all nodes will have an empty mempool.
sync_blocks(self.nodes)
# So instead, we sync on blocks and mempool for node 0 and node 1, and after a new block is generated
# which mines tx1 and tx2, all nodes will have an empty mempool which can then be synced.
sync_blocks(self.nodes[:2])
sync_mempools(self.nodes[:2])
self.nodes[1].generate(1)
self.sync_all()
# Verify maximum number of utxos which node 2 can shield is limited by option -mempooltxinputlimit
# This option is used when the limit parameter is set to 0.
mytaddr = self.nodes[2].getnewaddress()
result = self.nodes[2].z_shieldcoinbase(mytaddr, myzaddr, 0)
result = self.nodes[2].z_shieldcoinbase(mytaddr, myzaddr, Decimal('0.0001'), 0)
assert_equal(result["shieldingUTXOs"], Decimal('7'))
assert_equal(result["remainingUTXOs"], Decimal('13'))
self.wait_and_assert_operationid_status(2, result['opid'])
wait_and_assert_operationid_status(self.nodes[2], result['opid'])
self.sync_all()
self.nodes[1].generate(1)
self.sync_all()
# Verify maximum number of utxos which node 0 can shield is set by default limit parameter of 50
self.nodes[0].generate(200)
self.sync_all()
mytaddr = self.nodes[0].getnewaddress()
result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr, Decimal('0.0001'))
assert_equal(result["shieldingUTXOs"], Decimal('50'))
assert_equal(result["remainingUTXOs"], Decimal('50'))
wait_and_assert_operationid_status(self.nodes[0], result['opid'])
# Verify maximum number of utxos which node 0 can shield can be set by the limit parameter
result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr, Decimal('0.0001'), 33)
assert_equal(result["shieldingUTXOs"], Decimal('33'))
assert_equal(result["remainingUTXOs"], Decimal('17'))
wait_and_assert_operationid_status(self.nodes[0], result['opid'])
# Don't sync node 2 which rejects the tx due to its mempooltxinputlimit
sync_blocks(self.nodes[:2])
sync_mempools(self.nodes[:2])
self.nodes[1].generate(1)
self.sync_all()
if __name__ == '__main__':
WalletShieldCoinbaseTest().main()
WalletShieldCoinbaseTest().main()

36
qa/rpc-tests/wallet_treestate.py

@ -6,7 +6,7 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, initialize_chain_clean, \
start_nodes, connect_nodes_bi
start_nodes, connect_nodes_bi, wait_and_assert_operationid_status
import time
from decimal import Decimal
@ -26,30 +26,6 @@ class WalletTreeStateTest (BitcoinTestFramework):
self.is_network_split=False
self.sync_all()
def wait_and_assert_operationid_status(self, myopid, in_status='success', in_errormsg=None):
print('waiting for async operation {}'.format(myopid))
opids = []
opids.append(myopid)
timeout = 300
status = None
errormsg = None
for x in xrange(1, timeout):
results = self.nodes[0].z_getoperationresult(opids)
if len(results)==0:
time.sleep(1)
else:
status = results[0]["status"]
if status == "failed":
errormsg = results[0]['error']['message']
break
print('...returned status: {}'.format(status))
print('...error msg: {}'.format(errormsg))
assert_equal(in_status, status)
if errormsg is not None:
assert(in_errormsg is not None)
assert_equal(in_errormsg in errormsg, True)
print('...returned error: {}'.format(errormsg))
def run_test (self):
print "Mining blocks..."
@ -65,17 +41,17 @@ class WalletTreeStateTest (BitcoinTestFramework):
recipients = []
recipients.append({"address":myzaddr, "amount":Decimal('10.0') - Decimal('0.0001')})
myopid = self.nodes[0].z_sendmany(mytaddr, recipients)
self.wait_and_assert_operationid_status(myopid)
wait_and_assert_operationid_status(self.nodes[0], myopid)
self.sync_all()
self.nodes[1].generate(1)
self.sync_all()
myopid = self.nodes[0].z_sendmany(mytaddr, recipients)
self.wait_and_assert_operationid_status(myopid)
wait_and_assert_operationid_status(self.nodes[0], myopid)
self.sync_all()
self.nodes[1].generate(1)
self.sync_all()
myopid = self.nodes[0].z_sendmany(mytaddr, recipients)
self.wait_and_assert_operationid_status(myopid)
wait_and_assert_operationid_status(self.nodes[0], myopid)
self.sync_all()
self.nodes[1].generate(1)
self.sync_all()
@ -92,7 +68,7 @@ class WalletTreeStateTest (BitcoinTestFramework):
recipients = []
recipients.append({"address":self.nodes[2].z_getnewaddress(), "amount":Decimal('10.0') - Decimal('0.0001')})
myopid = self.nodes[0].z_sendmany(mytaddr, recipients)
self.wait_and_assert_operationid_status(myopid)
wait_and_assert_operationid_status(self.nodes[0], myopid)
# Tx 2 will consume all three notes, which must take at least two joinsplits. This is regardless of
# the z_sendmany implementation because there are only two inputs per joinsplit.
@ -115,7 +91,7 @@ class WalletTreeStateTest (BitcoinTestFramework):
self.sync_all()
# Wait for Tx 2 to be created
self.wait_and_assert_operationid_status(myopid)
wait_and_assert_operationid_status(self.nodes[0], myopid)
# Note that a bug existed in v1.0.0-1.0.3 where Tx 2 creation would fail with an error:
# "Witness for spendable note does not have same anchor as change input"

9
qa/rpc-tests/walletbackup.py

@ -34,6 +34,7 @@ and confirm again balances are correct.
"""
from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, initialize_chain_clean, \
start_nodes, start_node, connect_nodes, stop_node, \
sync_blocks, sync_mempools
@ -141,6 +142,14 @@ class WalletBackupTest(BitcoinTestFramework):
self.nodes[2].backupwallet("walletbak")
self.nodes[2].dumpwallet("walletdump")
# Verify dumpwallet cannot overwrite an existing file
try:
self.nodes[2].dumpwallet("walletdump")
assert(False)
except JSONRPCException as e:
errorString = e.error['message']
assert("Cannot overwrite existing file" in errorString)
logging.info("More transactions")
for i in range(5):
self.do_one_round()

189
qa/rpc-tests/zkey_import_export.py

@ -0,0 +1,189 @@
#!/usr/bin/env python2
# Copyright (c) 2017 The Zcash developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_greater_than, start_nodes, initialize_chain_clean, connect_nodes_bi
import logging
import time
import math
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
class ZkeyImportExportTest (BitcoinTestFramework):
def setup_chain(self):
print("Initializing test directory "+self.options.tmpdir)
initialize_chain_clean(self.options.tmpdir, 5)
def setup_network(self, split=False):
self.nodes = start_nodes(5, self.options.tmpdir )
connect_nodes_bi(self.nodes,0,1)
connect_nodes_bi(self.nodes,1,2)
connect_nodes_bi(self.nodes,0,2)
connect_nodes_bi(self.nodes,0,3)
connect_nodes_bi(self.nodes,0,4)
self.is_network_split=False
self.sync_all()
# TODO: Refactor in z_addr test_framework file
# Returns txid if operation was a success or None
def wait_and_assert_operationid_status(self, node, myopid, in_status='success', in_errormsg=None):
print('waiting for async operation {}'.format(myopid))
opids = []
opids.append(myopid)
timeout = 300
status = None
errormsg = None
txid = None
for x in xrange(1, timeout):
results = node.z_getoperationresult(opids)
if len(results)==0:
time.sleep(1)
else:
print("Results", results[0])
status = results[0]["status"]
if status == "failed":
errormsg = results[0]['error']['message']
elif status == "success":
txid = results[0]['result']['txid']
break
print('...returned status: {}'.format(status))
assert_equal(in_status, status)
if errormsg is not None:
assert(in_errormsg is not None)
assert_equal(in_errormsg in errormsg, True)
print('...returned error: {}'.format(errormsg))
return txid
def run_test(self):
[alice, bob, charlie, david, miner] = self.nodes
def z_send(from_node, from_addr, to_addr, amount):
opid = from_node.z_sendmany(from_addr, [{"address": to_addr, "amount": Decimal(amount)}])
self.wait_and_assert_operationid_status(from_node, opid)
self.sync_all()
miner.generate(1)
self.sync_all()
def z_getbalance(node, zaddr):
bal = node.z_getbalance(zaddr)
# Ignore fees for sake of comparison
round_balance = math.ceil(bal*100)/100
return round_balance
def verify_utxos(node, amts, zaddr):
amts.sort(reverse=True)
txs = node.z_listreceivedbyaddress(zaddr)
def cmp_confirmations_high_to_low(a, b):
return cmp(b["amount"], a["amount"])
txs.sort(cmp_confirmations_high_to_low)
print("Sorted txs", txs)
print("amts", amts)
try:
assert_equal(amts, [tx["amount"] for tx in txs])
except AssertionError:
logging.error(
'Expected amounts: %r; txs: %r',
amts, txs)
raise
def get_private_balance(node):
balance = node.z_gettotalbalance()
return balance['private']
def find_imported_key(node, import_zaddr):
zaddrs = node.z_listaddresses()
assert(import_zaddr in zaddrs)
return import_zaddr
# Seed Alice with some funds
alice.generate(10)
self.sync_all()
miner.generate(100)
self.sync_all()
# Shield Alice's coinbase funds to her zaddr
alice_zaddr = alice.z_getnewaddress()
res = alice.z_shieldcoinbase("*", alice_zaddr)
self.wait_and_assert_operationid_status(alice, res['opid'])
miner.generate(6)
self.sync_all()
# Now get a pristine z-address for receiving transfers:
bob_zaddr = bob.z_getnewaddress()
verify_utxos(bob, [], bob_zaddr)
# TODO: Verify that charlie doesn't have funds in addr
# verify_utxos(charlie, [])
# the amounts of each txn embodied which generates a single UTXO:
amounts = map(Decimal, ['2.3', '3.7', '0.1', '0.5', '1.0', '0.19'])
# Internal test consistency assertion:
assert_greater_than(
get_private_balance(alice),
reduce(Decimal.__add__, amounts))
logging.info("Sending pre-export txns...")
for amount in amounts[0:2]:
z_send(alice, alice_zaddr, bob_zaddr, amount)
logging.info("Exporting privkey from bob...")
privkey = bob.z_exportkey(bob_zaddr)
logging.info("Sending post-export txns...")
for amount in amounts[2:4]:
z_send(alice, alice_zaddr, bob_zaddr, amount)
print("Bob amounts:", amounts[:4])
verify_utxos(bob, amounts[:4], bob_zaddr)
# verify_utxos(charlie, [])
logging.info("Importing privkey into charlie...")
# z_importkey rescan defaults to "whenkeyisnew", so should rescan here
charlie.z_importkey(privkey)
ipk_zaddr = find_imported_key(charlie, bob_zaddr)
# z_importkey should have rescanned for new key, so this should pass:
verify_utxos(charlie, amounts[:4], ipk_zaddr)
# Verify idempotent behavior:
charlie.z_importkey(privkey)
ipk_zaddr2 = find_imported_key(charlie, bob_zaddr)
# amounts should be unchanged
verify_utxos(charlie, amounts[:4], ipk_zaddr2)
logging.info("Sending post-import txns...")
for amount in amounts[4:]:
z_send(alice, alice_zaddr, bob_zaddr, amount)
verify_utxos(bob, amounts, bob_zaddr)
verify_utxos(charlie, amounts, ipk_zaddr)
verify_utxos(charlie, amounts, ipk_zaddr2)
# Try to reproduce zombie balance reported in #1936
# At generated zaddr, receive ZEC, and send ZEC back out. bob -> alice
for amount in amounts[:2]:
print("Sending amount from bob to alice: ", amount)
z_send(bob, bob_zaddr, alice_zaddr, amount)
balance = float(sum(amounts) - sum(amounts[:2]))
assert_equal(z_getbalance(bob, bob_zaddr), balance)
# z_import onto new node "david" (blockchain rescan, default or True?)
david.z_importkey(privkey)
d_ipk_zaddr = find_imported_key(david, bob_zaddr)
# Check if amt bob spent is deducted for charlie and david
assert_equal(z_getbalance(charlie, ipk_zaddr), balance)
assert_equal(z_getbalance(david, d_ipk_zaddr), balance)
if __name__ == '__main__':
ZkeyImportExportTest().main()

2
share/ui.rc

@ -12,4 +12,4 @@ addressbook16 BITMAP "pixmaps/addressbook16.bmp"
addressbook16mask BITMAP "pixmaps/addressbook16mask.bmp"
addressbook20 BITMAP "pixmaps/addressbook20.bmp"
addressbook20mask BITMAP "pixmaps/addressbook20mask.bmp"
favicon ICON "pixmaps/favicon.ico"
favicon ICON "pixmaps/favicon.ico"

1
src/Makefile.gtest.include

@ -1,4 +1,3 @@
TESTS += zcash-gtest
noinst_PROGRAMS += zcash-gtest

75
src/base58.cpp

@ -340,67 +340,60 @@ bool CBitcoinSecret::SetString(const std::string& strSecret)
return SetString(strSecret.c_str());
}
bool CZCPaymentAddress::Set(const libzcash::PaymentAddress& addr)
template<class DATA_TYPE, CChainParams::Base58Type PREFIX, size_t SER_SIZE>
bool CZCEncoding<DATA_TYPE, PREFIX, SER_SIZE>::Set(const DATA_TYPE& addr)
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << addr;
std::vector<unsigned char> addrSerialized(ss.begin(), ss.end());
assert(addrSerialized.size() == libzcash::SerializedPaymentAddressSize);
SetData(Params().Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS), &addrSerialized[0], libzcash::SerializedPaymentAddressSize);
assert(addrSerialized.size() == SER_SIZE);
SetData(Params().Base58Prefix(PREFIX), &addrSerialized[0], SER_SIZE);
return true;
}
libzcash::PaymentAddress CZCPaymentAddress::Get() const
template<class DATA_TYPE, CChainParams::Base58Type PREFIX, size_t SER_SIZE>
DATA_TYPE CZCEncoding<DATA_TYPE, PREFIX, SER_SIZE>::Get() const
{
if (vchData.size() != libzcash::SerializedPaymentAddressSize) {
if (vchData.size() != SER_SIZE) {
throw std::runtime_error(
"payment address is invalid"
PrependName(" is invalid")
);
}
if (vchVersion != Params().Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS)) {
if (vchVersion != Params().Base58Prefix(PREFIX)) {
throw std::runtime_error(
"payment address is for wrong network type"
PrependName(" is for wrong network type")
);
}
std::vector<unsigned char> serialized(vchData.begin(), vchData.end());
CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
libzcash::PaymentAddress ret;
ss >> ret;
return ret;
}
bool CZCSpendingKey::Set(const libzcash::SpendingKey& addr)
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << addr;
std::vector<unsigned char> addrSerialized(ss.begin(), ss.end());
assert(addrSerialized.size() == libzcash::SerializedSpendingKeySize);
SetData(Params().Base58Prefix(CChainParams::ZCSPENDING_KEY), &addrSerialized[0], libzcash::SerializedSpendingKeySize);
return true;
}
libzcash::SpendingKey CZCSpendingKey::Get() const
{
if (vchData.size() != libzcash::SerializedSpendingKeySize) {
throw std::runtime_error(
"spending key is invalid"
);
}
if (vchVersion != Params().Base58Prefix(CChainParams::ZCSPENDING_KEY)) {
throw std::runtime_error(
"spending key is for wrong network type"
);
}
std::vector<unsigned char> serialized(vchData.begin(), vchData.end());
CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
libzcash::SpendingKey ret;
DATA_TYPE ret;
ss >> ret;
return ret;
}
// Explicit instantiations for libzcash::PaymentAddress
template bool CZCEncoding<libzcash::PaymentAddress,
CChainParams::ZCPAYMENT_ADDRRESS,
libzcash::SerializedPaymentAddressSize>::Set(const libzcash::PaymentAddress& addr);
template libzcash::PaymentAddress CZCEncoding<libzcash::PaymentAddress,
CChainParams::ZCPAYMENT_ADDRRESS,
libzcash::SerializedPaymentAddressSize>::Get() const;
// Explicit instantiations for libzcash::ViewingKey
template bool CZCEncoding<libzcash::ViewingKey,
CChainParams::ZCVIEWING_KEY,
libzcash::SerializedViewingKeySize>::Set(const libzcash::ViewingKey& vk);
template libzcash::ViewingKey CZCEncoding<libzcash::ViewingKey,
CChainParams::ZCVIEWING_KEY,
libzcash::SerializedViewingKeySize>::Get() const;
// Explicit instantiations for libzcash::SpendingKey
template bool CZCEncoding<libzcash::SpendingKey,
CChainParams::ZCSPENDING_KEY,
libzcash::SerializedSpendingKeySize>::Set(const libzcash::SpendingKey& sk);
template libzcash::SpendingKey CZCEncoding<libzcash::SpendingKey,
CChainParams::ZCSPENDING_KEY,
libzcash::SerializedSpendingKeySize>::Get() const;

36
src/base58.h

@ -96,26 +96,48 @@ public:
bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; }
};
class CZCPaymentAddress : public CBase58Data {
template<class DATA_TYPE, CChainParams::Base58Type PREFIX, size_t SER_SIZE>
class CZCEncoding : public CBase58Data {
protected:
virtual std::string PrependName(const std::string& s) const = 0;
public:
bool Set(const DATA_TYPE& addr);
DATA_TYPE Get() const;
};
class CZCPaymentAddress : public CZCEncoding<libzcash::PaymentAddress, CChainParams::ZCPAYMENT_ADDRRESS, libzcash::SerializedPaymentAddressSize> {
protected:
std::string PrependName(const std::string& s) const { return "payment address" + s; }
public:
bool Set(const libzcash::PaymentAddress& addr);
CZCPaymentAddress() {}
CZCPaymentAddress(const std::string& strAddress) { SetString(strAddress.c_str(), 2); }
CZCPaymentAddress(const libzcash::PaymentAddress& addr) { Set(addr); }
};
class CZCViewingKey : public CZCEncoding<libzcash::ViewingKey, CChainParams::ZCVIEWING_KEY, libzcash::SerializedViewingKeySize> {
protected:
std::string PrependName(const std::string& s) const { return "viewing key" + s; }
public:
CZCViewingKey() {}
libzcash::PaymentAddress Get() const;
CZCViewingKey(const std::string& strViewingKey) { SetString(strViewingKey.c_str(), 3); }
CZCViewingKey(const libzcash::ViewingKey& vk) { Set(vk); }
};
class CZCSpendingKey : public CBase58Data {
class CZCSpendingKey : public CZCEncoding<libzcash::SpendingKey, CChainParams::ZCSPENDING_KEY, libzcash::SerializedSpendingKeySize> {
protected:
std::string PrependName(const std::string& s) const { return "spending key" + s; }
public:
bool Set(const libzcash::SpendingKey& addr);
CZCSpendingKey() {}
CZCSpendingKey(const std::string& strAddress) { SetString(strAddress.c_str(), 2); }
CZCSpendingKey(const libzcash::SpendingKey& addr) { Set(addr); }
libzcash::SpendingKey Get() const;
};
/** base58-encoded Bitcoin addresses.

19
src/chain.h

@ -16,6 +16,8 @@
#include <boost/foreach.hpp>
static const int SPROUT_VALUE_VERSION = 1001400;
struct CDiskBlockPos
{
int nFile;
@ -144,6 +146,15 @@ public:
//! (memory only) The anchor for the tree state up to the end of this block
uint256 hashAnchorEnd;
//! Change in value held by the Sprout circuit over this block.
//! Will be boost::none for older blocks on old nodes until a reindex has taken place.
boost::optional<CAmount> nSproutValue;
//! (memory only) Total value held by the Sprout circuit up to and including this block.
//! Will be boost::none for on old nodes until a reindex has taken place.
//! Will be boost::none if nChainTx is zero.
boost::optional<CAmount> nChainSproutValue;
//! block header
int nVersion;
uint256 hashMerkleRoot;
@ -172,6 +183,8 @@ public:
hashAnchor = uint256();
hashAnchorEnd = uint256();
nSequenceId = 0;
nSproutValue = boost::none;
nChainSproutValue = boost::none;
nVersion = 0;
hashMerkleRoot = uint256();
@ -339,6 +352,12 @@ public:
READWRITE(nBits);
READWRITE(nNonce);
READWRITE(nSolution);
// Only read/write nSproutValue if the client version used to create
// this index was storing them.
if ((nType & SER_DISK) && (nVersion >= SPROUT_VALUE_VERSION)) {
READWRITE(nSproutValue);
}
}
uint256 GetBlockHash() const

6
src/chainparams.cpp

@ -50,7 +50,6 @@ public:
consensus.nPowMaxAdjustDown = 32; // 32% adjustment down
consensus.nPowMaxAdjustUp = 16; // 16% adjustment up
consensus.nPowTargetSpacing = 2.5 * 60;
consensus.fPowAllowMinDifficultyBlocks = false;
/**
* The message start string should be awesome!
*/
@ -113,6 +112,8 @@ public:
base58Prefixes[EXT_SECRET_KEY] = {0x04,0x88,0xAD,0xE4};
// guarantees the first 2 characters, when base58 encoded, are "zc"
base58Prefixes[ZCPAYMENT_ADDRRESS] = {0x16,0x9A};
// guarantees the first 4 characters, when base58 encoded, are "ZiVK"
base58Prefixes[ZCVIEWING_KEY] = {0xA8,0xAB,0xD3};
// guarantees the first 2 characters, when base58 encoded, are "SK"
base58Prefixes[ZCSPENDING_KEY] = {0xAB,0x36};
@ -210,7 +211,6 @@ public:
consensus.nMajorityWindow = 400;
consensus.powLimit = uint256S("07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
assert(maxUint/UintToArith256(consensus.powLimit) >= consensus.nPowAveragingWindow);
consensus.fPowAllowMinDifficultyBlocks = true;
pchMessageStart[0] = 0xfa;
pchMessageStart[1] = 0x1a;
pchMessageStart[2] = 0xf9;
@ -244,6 +244,8 @@ public:
base58Prefixes[EXT_SECRET_KEY] = {0x04,0x35,0x83,0x94};
// guarantees the first 2 characters, when base58 encoded, are "zt"
base58Prefixes[ZCPAYMENT_ADDRRESS] = {0x16,0xB6};
// guarantees the first 4 characters, when base58 encoded, are "ZiVt"
base58Prefixes[ZCVIEWING_KEY] = {0xA8,0xAC,0x0C};
// guarantees the first 2 characters, when base58 encoded, are "ST"
base58Prefixes[ZCSPENDING_KEY] = {0xAC,0x08};

1
src/chainparams.h

@ -44,6 +44,7 @@ public:
ZCPAYMENT_ADDRRESS,
ZCSPENDING_KEY,
ZCVIEWING_KEY,
MAX_BASE58_TYPES
};

2
src/clientversion.h

@ -18,7 +18,7 @@
//! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it
#define CLIENT_VERSION_MAJOR 1
#define CLIENT_VERSION_MINOR 0
#define CLIENT_VERSION_REVISION 13
#define CLIENT_VERSION_REVISION 14
#define CLIENT_VERSION_BUILD 50
//! Set to true for release, false for prerelease or test build

1
src/consensus/params.h

@ -41,7 +41,6 @@ struct Params {
int nMajorityWindow;
/** Proof of work parameters */
uint256 powLimit;
bool fPowAllowMinDifficultyBlocks;
int64_t nPowAveragingWindow;
int64_t nPowMaxAdjustDown;
int64_t nPowMaxAdjustUp;

5
src/gtest/main.cpp

@ -1,4 +1,4 @@
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "crypto/common.h"
#include "pubkey.h"
#include "zcash/JoinSplit.hpp"
@ -25,7 +25,6 @@ int main(int argc, char **argv) {
boost::filesystem::path vk_path = ZC_GetParamsDir() / "sprout-verifying.key";
params = ZCJoinSplit::Prepared(vk_path.string(), pk_path.string());
testing::InitGoogleTest(&argc, argv);
testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}

1
src/gtest/test_circuit.cpp

@ -181,4 +181,3 @@ TEST(circuit, merkle_tree_gadget_weirdness)
// Test the last again, except this time write the root first.
ASSERT_TRUE(test_merkle_gadget<FieldT>(false, true, true));
}

3
src/gtest/test_joinsplit.cpp

@ -89,7 +89,7 @@ void test_full_api(ZCJoinSplit* js)
// Recipient should decrypt
// Now the recipient should spend the money again
auto h_sig = js->h_sig(randomSeed, nullifiers, pubKeyHash);
ZCNoteDecryption decryptor(recipient_key.viewing_key());
ZCNoteDecryption decryptor(recipient_key.receiving_key());
auto note_pt = NotePlaintext::decrypt(
decryptor,
@ -547,4 +547,3 @@ TEST(joinsplit, note_plaintexts)
ASSERT_TRUE(decrypted.memo == note_pt.memo);
}

69
src/gtest/test_keystore.cpp

@ -43,7 +43,64 @@ TEST(keystore_tests, store_and_retrieve_note_decryptor) {
keyStore.AddSpendingKey(sk);
EXPECT_TRUE(keyStore.GetNoteDecryptor(addr, decOut));
EXPECT_EQ(ZCNoteDecryption(sk.viewing_key()), decOut);
EXPECT_EQ(ZCNoteDecryption(sk.receiving_key()), decOut);
}
TEST(keystore_tests, StoreAndRetrieveViewingKey) {
CBasicKeyStore keyStore;
libzcash::ViewingKey vkOut;
libzcash::SpendingKey skOut;
ZCNoteDecryption decOut;
auto sk = libzcash::SpendingKey::random();
auto vk = sk.viewing_key();
auto addr = sk.address();
// Sanity-check: we can't get a viewing key we haven't added
EXPECT_FALSE(keyStore.HaveViewingKey(addr));
EXPECT_FALSE(keyStore.GetViewingKey(addr, vkOut));
// and we shouldn't have a spending key or decryptor either
EXPECT_FALSE(keyStore.HaveSpendingKey(addr));
EXPECT_FALSE(keyStore.GetSpendingKey(addr, skOut));
EXPECT_FALSE(keyStore.GetNoteDecryptor(addr, decOut));
// and we can't find it in our list of addresses
std::set<libzcash::PaymentAddress> addresses;
keyStore.GetPaymentAddresses(addresses);
EXPECT_FALSE(addresses.count(addr));
keyStore.AddViewingKey(vk);
EXPECT_TRUE(keyStore.HaveViewingKey(addr));
EXPECT_TRUE(keyStore.GetViewingKey(addr, vkOut));
EXPECT_EQ(vk, vkOut);
// We should still not have the spending key...
EXPECT_FALSE(keyStore.HaveSpendingKey(addr));
EXPECT_FALSE(keyStore.GetSpendingKey(addr, skOut));
// ... but we should have a decryptor
EXPECT_TRUE(keyStore.GetNoteDecryptor(addr, decOut));
EXPECT_EQ(ZCNoteDecryption(sk.receiving_key()), decOut);
// ... and we should find it in our list of addresses
addresses.clear();
keyStore.GetPaymentAddresses(addresses);
EXPECT_TRUE(addresses.count(addr));
keyStore.RemoveViewingKey(vk);
EXPECT_FALSE(keyStore.HaveViewingKey(addr));
EXPECT_FALSE(keyStore.GetViewingKey(addr, vkOut));
EXPECT_FALSE(keyStore.HaveSpendingKey(addr));
EXPECT_FALSE(keyStore.GetSpendingKey(addr, skOut));
addresses.clear();
keyStore.GetPaymentAddresses(addresses);
EXPECT_FALSE(addresses.count(addr));
// We still have a decryptor because those are cached in memory
// (and also we only remove viewing keys when adding a spending key)
EXPECT_TRUE(keyStore.GetNoteDecryptor(addr, decOut));
EXPECT_EQ(ZCNoteDecryption(sk.receiving_key()), decOut);
}
#ifdef ENABLE_WALLET
@ -72,13 +129,13 @@ TEST(keystore_tests, store_and_retrieve_spending_key_in_encrypted_store) {
ASSERT_TRUE(keyStore.GetSpendingKey(addr, keyOut));
ASSERT_EQ(sk, keyOut);
EXPECT_TRUE(keyStore.GetNoteDecryptor(addr, decOut));
EXPECT_EQ(ZCNoteDecryption(sk.viewing_key()), decOut);
EXPECT_EQ(ZCNoteDecryption(sk.receiving_key()), decOut);
ASSERT_TRUE(keyStore.EncryptKeys(vMasterKey));
ASSERT_TRUE(keyStore.HaveSpendingKey(addr));
ASSERT_FALSE(keyStore.GetSpendingKey(addr, keyOut));
EXPECT_TRUE(keyStore.GetNoteDecryptor(addr, decOut));
EXPECT_EQ(ZCNoteDecryption(sk.viewing_key()), decOut);
EXPECT_EQ(ZCNoteDecryption(sk.receiving_key()), decOut);
// Unlocking with a random key should fail
uint256 r2 {GetRandHash()};
@ -109,19 +166,19 @@ TEST(keystore_tests, store_and_retrieve_spending_key_in_encrypted_store) {
ASSERT_TRUE(keyStore.GetSpendingKey(addr2, keyOut));
ASSERT_EQ(sk2, keyOut);
EXPECT_TRUE(keyStore.GetNoteDecryptor(addr2, decOut));
EXPECT_EQ(ZCNoteDecryption(sk2.viewing_key()), decOut);
EXPECT_EQ(ZCNoteDecryption(sk2.receiving_key()), decOut);
ASSERT_TRUE(keyStore.Lock());
ASSERT_TRUE(keyStore.HaveSpendingKey(addr2));
ASSERT_FALSE(keyStore.GetSpendingKey(addr2, keyOut));
EXPECT_TRUE(keyStore.GetNoteDecryptor(addr2, decOut));
EXPECT_EQ(ZCNoteDecryption(sk2.viewing_key()), decOut);
EXPECT_EQ(ZCNoteDecryption(sk2.receiving_key()), decOut);
ASSERT_TRUE(keyStore.Unlock(vMasterKey));
ASSERT_TRUE(keyStore.GetSpendingKey(addr2, keyOut));
ASSERT_EQ(sk2, keyOut);
EXPECT_TRUE(keyStore.GetNoteDecryptor(addr2, decOut));
EXPECT_EQ(ZCNoteDecryption(sk2.viewing_key()), decOut);
EXPECT_EQ(ZCNoteDecryption(sk2.receiving_key()), decOut);
keyStore.GetPaymentAddresses(addrs);
ASSERT_EQ(2, addrs.size());

1
src/gtest/test_merkletree.cpp

@ -299,4 +299,3 @@ TEST(merkletree, testZeroElements) {
ASSERT_TRUE(newTree.root() == oldroot);
}
}

5
src/gtest/test_paymentdisclosure.cpp

@ -87,7 +87,9 @@ public:
// This test creates random payment disclosure blobs and checks that they can be
// 1. inserted and retrieved from a database
// 2. serialized and deserialized without corruption
// 2. serialized and deserialized without corruption
// Note that the zpd: prefix is not part of the payment disclosure blob itself. It is only
// used as convention to improve the user experience when sharing payment disclosure blobs.
TEST(paymentdisclosure, mainnet) {
ECC_Start();
SelectParams(CBaseChainParams::MAIN);
@ -208,4 +210,3 @@ TEST(paymentdisclosure, mainnet) {
ECC_Stop();
}

1
src/gtest/test_proofs.cpp

@ -700,4 +700,3 @@ TEST(proofs, g2_test_vectors)
ASSERT_TRUE(expected.to_libsnark_g2<curve_G2>() == e);
}
}

86
src/gtest/test_validation.cpp

@ -2,6 +2,18 @@
#include "consensus/validation.h"
#include "main.h"
#include "utiltest.h"
extern ZCJoinSplit* params;
extern bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos);
void ExpectOptionalAmount(CAmount expected, boost::optional<CAmount> actual) {
EXPECT_TRUE((bool)actual);
if (actual) {
EXPECT_EQ(expected, *actual);
}
}
// Fake an empty view
class FakeCoinsViewDB : public CCoinsView {
@ -61,3 +73,77 @@ TEST(Validation, ContextualCheckInputsPassesWithCoinbase) {
CValidationState state;
EXPECT_TRUE(ContextualCheckInputs(tx, state, view, false, 0, false, Params(CBaseChainParams::MAIN).GetConsensus()));
}
TEST(Validation, ReceivedBlockTransactions) {
auto sk = libzcash::SpendingKey::random();
// Create a fake genesis block
CBlock block1;
block1.vtx.push_back(GetValidReceive(*params, sk, 5, true));
block1.hashMerkleRoot = block1.BuildMerkleTree();
CBlockIndex fakeIndex1 {block1};
// Create a fake child block
CBlock block2;
block2.hashPrevBlock = block1.GetHash();
block2.vtx.push_back(GetValidReceive(*params, sk, 10, true));
block2.hashMerkleRoot = block2.BuildMerkleTree();
CBlockIndex fakeIndex2 {block2};
fakeIndex2.pprev = &fakeIndex1;
CDiskBlockPos pos1;
CDiskBlockPos pos2;
// Set initial state of indices
ASSERT_TRUE(fakeIndex1.RaiseValidity(BLOCK_VALID_TREE));
ASSERT_TRUE(fakeIndex2.RaiseValidity(BLOCK_VALID_TREE));
EXPECT_TRUE(fakeIndex1.IsValid(BLOCK_VALID_TREE));
EXPECT_TRUE(fakeIndex2.IsValid(BLOCK_VALID_TREE));
EXPECT_FALSE(fakeIndex1.IsValid(BLOCK_VALID_TRANSACTIONS));
EXPECT_FALSE(fakeIndex2.IsValid(BLOCK_VALID_TRANSACTIONS));
// Sprout pool values should not be set
EXPECT_FALSE((bool)fakeIndex1.nSproutValue);
EXPECT_FALSE((bool)fakeIndex1.nChainSproutValue);
EXPECT_FALSE((bool)fakeIndex2.nSproutValue);
EXPECT_FALSE((bool)fakeIndex2.nChainSproutValue);
// Mark the second block's transactions as received first
CValidationState state;
EXPECT_TRUE(ReceivedBlockTransactions(block2, state, &fakeIndex2, pos2));
EXPECT_FALSE(fakeIndex1.IsValid(BLOCK_VALID_TRANSACTIONS));
EXPECT_TRUE(fakeIndex2.IsValid(BLOCK_VALID_TRANSACTIONS));
// Sprout pool value delta should now be set for the second block,
// but not any chain totals
EXPECT_FALSE((bool)fakeIndex1.nSproutValue);
EXPECT_FALSE((bool)fakeIndex1.nChainSproutValue);
{
SCOPED_TRACE("ExpectOptionalAmount call");
ExpectOptionalAmount(20, fakeIndex2.nSproutValue);
}
EXPECT_FALSE((bool)fakeIndex2.nChainSproutValue);
// Now mark the first block's transactions as received
EXPECT_TRUE(ReceivedBlockTransactions(block1, state, &fakeIndex1, pos1));
EXPECT_TRUE(fakeIndex1.IsValid(BLOCK_VALID_TRANSACTIONS));
EXPECT_TRUE(fakeIndex2.IsValid(BLOCK_VALID_TRANSACTIONS));
// Sprout pool values should now be set for both blocks
{
SCOPED_TRACE("ExpectOptionalAmount call");
ExpectOptionalAmount(10, fakeIndex1.nSproutValue);
}
{
SCOPED_TRACE("ExpectOptionalAmount call");
ExpectOptionalAmount(10, fakeIndex1.nChainSproutValue);
}
{
SCOPED_TRACE("ExpectOptionalAmount call");
ExpectOptionalAmount(20, fakeIndex2.nSproutValue);
}
{
SCOPED_TRACE("ExpectOptionalAmount call");
ExpectOptionalAmount(30, fakeIndex2.nChainSproutValue);
}
}

36
src/keystore.cpp

@ -89,6 +89,40 @@ bool CBasicKeyStore::AddSpendingKey(const libzcash::SpendingKey &sk)
LOCK(cs_SpendingKeyStore);
auto address = sk.address();
mapSpendingKeys[address] = sk;
mapNoteDecryptors.insert(std::make_pair(address, ZCNoteDecryption(sk.viewing_key())));
mapNoteDecryptors.insert(std::make_pair(address, ZCNoteDecryption(sk.receiving_key())));
return true;
}
bool CBasicKeyStore::AddViewingKey(const libzcash::ViewingKey &vk)
{
LOCK(cs_SpendingKeyStore);
auto address = vk.address();
mapViewingKeys[address] = vk;
mapNoteDecryptors.insert(std::make_pair(address, ZCNoteDecryption(vk.sk_enc)));
return true;
}
bool CBasicKeyStore::RemoveViewingKey(const libzcash::ViewingKey &vk)
{
LOCK(cs_SpendingKeyStore);
mapViewingKeys.erase(vk.address());
return true;
}
bool CBasicKeyStore::HaveViewingKey(const libzcash::PaymentAddress &address) const
{
LOCK(cs_SpendingKeyStore);
return mapViewingKeys.count(address) > 0;
}
bool CBasicKeyStore::GetViewingKey(const libzcash::PaymentAddress &address,
libzcash::ViewingKey &vkOut) const
{
LOCK(cs_SpendingKeyStore);
ViewingKeyMap::const_iterator mi = mapViewingKeys.find(address);
if (mi != mapViewingKeys.end()) {
vkOut = mi->second;
return true;
}
return false;
}

19
src/keystore.h

@ -55,12 +55,19 @@ public:
virtual bool HaveSpendingKey(const libzcash::PaymentAddress &address) const =0;
virtual bool GetSpendingKey(const libzcash::PaymentAddress &address, libzcash::SpendingKey& skOut) const =0;
virtual void GetPaymentAddresses(std::set<libzcash::PaymentAddress> &setAddress) const =0;
//! Support for viewing keys
virtual bool AddViewingKey(const libzcash::ViewingKey &vk) =0;
virtual bool RemoveViewingKey(const libzcash::ViewingKey &vk) =0;
virtual bool HaveViewingKey(const libzcash::PaymentAddress &address) const =0;
virtual bool GetViewingKey(const libzcash::PaymentAddress &address, libzcash::ViewingKey& vkOut) const =0;
};
typedef std::map<CKeyID, CKey> KeyMap;
typedef std::map<CScriptID, CScript > ScriptMap;
typedef std::set<CScript> WatchOnlySet;
typedef std::map<libzcash::PaymentAddress, libzcash::SpendingKey> SpendingKeyMap;
typedef std::map<libzcash::PaymentAddress, libzcash::ViewingKey> ViewingKeyMap;
typedef std::map<libzcash::PaymentAddress, ZCNoteDecryption> NoteDecryptorMap;
/** Basic key store, that keeps keys in an address->secret map */
@ -71,6 +78,7 @@ protected:
ScriptMap mapScripts;
WatchOnlySet setWatchOnly;
SpendingKeyMap mapSpendingKeys;
ViewingKeyMap mapViewingKeys;
NoteDecryptorMap mapNoteDecryptors;
public:
@ -166,8 +174,19 @@ public:
setAddress.insert((*mi).first);
mi++;
}
ViewingKeyMap::const_iterator mvi = mapViewingKeys.begin();
while (mvi != mapViewingKeys.end())
{
setAddress.insert((*mvi).first);
mvi++;
}
}
}
virtual bool AddViewingKey(const libzcash::ViewingKey &vk);
virtual bool RemoveViewingKey(const libzcash::ViewingKey &vk);
virtual bool HaveViewingKey(const libzcash::PaymentAddress &address) const;
virtual bool GetViewingKey(const libzcash::PaymentAddress &address, libzcash::ViewingKey& vkOut) const;
};
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;

2
src/leveldbwrapper.cpp

@ -86,4 +86,4 @@ bool CLevelDBWrapper::WriteBatch(CLevelDBBatch& batch, bool fSync)
leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
HandleError(status);
return true;
}
}

25
src/main.cpp

@ -3088,6 +3088,15 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
{
pindexNew->nTx = block.vtx.size();
pindexNew->nChainTx = 0;
CAmount sproutValue = 0;
for (auto tx : block.vtx) {
for (auto js : tx.vjoinsplit) {
sproutValue += js.vpub_old;
sproutValue -= js.vpub_new;
}
}
pindexNew->nSproutValue = sproutValue;
pindexNew->nChainSproutValue = boost::none;
pindexNew->nFile = pos.nFile;
pindexNew->nDataPos = pos.nPos;
pindexNew->nUndoPos = 0;
@ -3105,6 +3114,15 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
CBlockIndex *pindex = queue.front();
queue.pop_front();
pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx;
if (pindex->pprev) {
if (pindex->pprev->nChainSproutValue && pindex->nSproutValue) {
pindex->nChainSproutValue = *pindex->pprev->nChainSproutValue + *pindex->nSproutValue;
} else {
pindex->nChainSproutValue = boost::none;
}
} else {
pindex->nChainSproutValue = pindex->nSproutValue;
}
{
LOCK(cs_nBlockSequenceId);
pindex->nSequenceId = nBlockSequenceId++;
@ -3753,12 +3771,19 @@ bool static LoadBlockIndexDB()
if (pindex->pprev) {
if (pindex->pprev->nChainTx) {
pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx;
if (pindex->pprev->nChainSproutValue && pindex->nSproutValue) {
pindex->nChainSproutValue = *pindex->pprev->nChainSproutValue + *pindex->nSproutValue;
} else {
pindex->nChainSproutValue = boost::none;
}
} else {
pindex->nChainTx = 0;
pindex->nChainSproutValue = boost::none;
mapBlocksUnlinked.insert(std::make_pair(pindex->pprev, pindex));
}
} else {
pindex->nChainTx = pindex->nTx;
pindex->nChainSproutValue = pindex->nSproutValue;
}
}
if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && (pindex->nChainTx || pindex->pprev == NULL))

9
src/miner.cpp

@ -101,10 +101,6 @@ public:
void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
{
pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
// Updating time can change work required on testnet:
if (consensusParams.fPowAllowMinDifficultyBlocks)
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
}
CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
@ -706,11 +702,6 @@ void static BitcoinMiner()
// Update nNonce and nTime
pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1);
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks)
{
// Changing pblock->nTime can change work required on testnet:
hashTarget.SetCompact(pblock->nBits);
}
}
}
}

1
src/paymentdisclosure.cpp

@ -61,4 +61,3 @@ PaymentDisclosure::PaymentDisclosure(const uint256 &joinSplitPubKey, const Payme
std::string sigString = HexStr(payloadSig.data(), payloadSig.data() + payloadSig.size());
LogPrint("paymentdisclosure", "Payment Disclosure: signature = %s\n", sigString);
}

2
src/paymentdisclosure.h

@ -28,6 +28,8 @@
#define PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL 0
#define PAYMENT_DISCLOSURE_BLOB_STRING_PREFIX "zpd:"
typedef JSOutPoint PaymentDisclosureKey;
struct PaymentDisclosureInfo {

1
src/paymentdisclosuredb.cpp

@ -91,4 +91,3 @@ bool PaymentDisclosureDB::Get(const PaymentDisclosureKey& key, PaymentDisclosure
}
return true;
}

1
src/paymentdisclosuredb.h

@ -40,4 +40,3 @@ public:
#endif // ZCASH_PAYMENTDISCLOSUREDB_H

7
src/reverselock.h

@ -15,10 +15,12 @@ public:
explicit reverse_lock(Lock& lock) : lock(lock) {
lock.unlock();
lock.swap(templock);
}
~reverse_lock() noexcept(false) {
lock.lock();
~reverse_lock() {
templock.lock();
templock.swap(lock);
}
private:
@ -26,6 +28,7 @@ private:
reverse_lock& operator=(reverse_lock const&);
Lock& lock;
Lock templock;
};
#endif // BITCOIN_REVERSELOCK_H

29
src/rpcblockchain.cpp

@ -85,6 +85,25 @@ double GetNetworkDifficulty(const CBlockIndex* blockindex)
return GetDifficultyINTERNAL(blockindex, true);
}
static UniValue ValuePoolDesc(
const std::string &name,
const boost::optional<CAmount> chainValue,
const boost::optional<CAmount> valueDelta)
{
UniValue rv(UniValue::VOBJ);
rv.push_back(Pair("id", name));
rv.push_back(Pair("monitored", (bool)chainValue));
if (chainValue) {
rv.push_back(Pair("chainValue", ValueFromAmount(*chainValue)));
rv.push_back(Pair("chainValueZat", *chainValue));
}
if (valueDelta) {
rv.push_back(Pair("valueDelta", ValueFromAmount(*valueDelta)));
rv.push_back(Pair("valueDeltaZat", *valueDelta));
}
return rv;
}
UniValue blockheaderToJSON(const CBlockIndex* blockindex)
{
UniValue result(UniValue::VOBJ);
@ -255,6 +274,10 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
result.push_back(Pair("anchor", blockindex->hashAnchorEnd.GetHex()));
UniValue valuePools(UniValue::VARR);
valuePools.push_back(ValuePoolDesc("sprout", blockindex->nChainSproutValue, blockindex->nSproutValue));
result.push_back(Pair("valuePools", valuePools));
if (blockindex->pprev)
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
CBlockIndex *pnext = chainActive.Next(blockindex);
@ -902,8 +925,12 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), tree);
obj.push_back(Pair("commitments", tree.size()));
const Consensus::Params& consensusParams = Params().GetConsensus();
CBlockIndex* tip = chainActive.Tip();
UniValue valuePools(UniValue::VARR);
valuePools.push_back(ValuePoolDesc("sprout", tip->nChainSproutValue, boost::none));
obj.push_back(Pair("valuePools", valuePools));
const Consensus::Params& consensusParams = Params().GetConsensus();
UniValue softforks(UniValue::VARR);
softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));

4
src/rpcclient.cpp

@ -113,9 +113,12 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "zcbenchmark", 1 },
{ "zcbenchmark", 2 },
{ "getblocksubsidy", 0},
{ "z_listaddresses", 0},
{ "z_listreceivedbyaddress", 1},
{ "z_getbalance", 1},
{ "z_gettotalbalance", 0},
{ "z_gettotalbalance", 1},
{ "z_gettotalbalance", 2},
{ "z_sendmany", 1},
{ "z_sendmany", 2},
{ "z_sendmany", 3},
@ -124,6 +127,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "z_getoperationstatus", 0},
{ "z_getoperationresult", 0},
{ "z_importkey", 2 },
{ "z_importviewingkey", 2 },
{ "z_getpaymentdisclosure", 1},
{ "z_getpaymentdisclosure", 2}
};

3
src/rpcmisc.cpp

@ -228,7 +228,8 @@ UniValue z_validateaddress(const UniValue& params, bool fHelp)
"}\n"
"\nExamples:\n"
+ HelpExampleCli("validateaddress", "\"zcWsmqT4X2V4jgxbgiCzyrAfRT1vi1F4sn7M5Pkh66izzw8Uk7LBGAH3DtcSMJeUb2pi3W4SQF8LMKkU2cUuVP68yAGcomL\"")
+ HelpExampleCli("z_validateaddress", "\"zcWsmqT4X2V4jgxbgiCzyrAfRT1vi1F4sn7M5Pkh66izzw8Uk7LBGAH3DtcSMJeUb2pi3W4SQF8LMKkU2cUuVP68yAGcomL\"")
+ HelpExampleRpc("z_validateaddress", "\"zcWsmqT4X2V4jgxbgiCzyrAfRT1vi1F4sn7M5Pkh66izzw8Uk7LBGAH3DtcSMJeUb2pi3W4SQF8LMKkU2cUuVP68yAGcomL\"")
);

2
src/rpcserver.cpp

@ -405,6 +405,8 @@ static const CRPCCommand vRPCCommands[] =
{ "wallet", "z_listaddresses", &z_listaddresses, true },
{ "wallet", "z_exportkey", &z_exportkey, true },
{ "wallet", "z_importkey", &z_importkey, true },
{ "wallet", "z_exportviewingkey", &z_exportviewingkey, true },
{ "wallet", "z_importviewingkey", &z_importviewingkey, true },
{ "wallet", "z_exportwallet", &z_exportwallet, true },
{ "wallet", "z_importwallet", &z_importwallet, true },

2
src/rpcserver.h

@ -291,6 +291,8 @@ extern UniValue getblocksubsidy(const UniValue& params, bool fHelp);
extern UniValue z_exportkey(const UniValue& params, bool fHelp); // in rpcdump.cpp
extern UniValue z_importkey(const UniValue& params, bool fHelp); // in rpcdump.cpp
extern UniValue z_exportviewingkey(const UniValue& params, bool fHelp); // in rpcdump.cpp
extern UniValue z_importviewingkey(const UniValue& params, bool fHelp); // in rpcdump.cpp
extern UniValue z_getnewaddress(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue z_listaddresses(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue z_exportwallet(const UniValue& params, bool fHelp); // in rpcdump.cpp

16
src/scheduler.cpp

@ -20,13 +20,6 @@ CScheduler::~CScheduler()
}
#if BOOST_VERSION < 105000
static boost::system_time toPosixTime(const boost::chrono::system_clock::time_point& t)
{
return boost::posix_time::from_time_t(boost::chrono::system_clock::to_time_t(t));
}
#endif
void CScheduler::serviceQueue()
{
boost::unique_lock<boost::mutex> lock(newTaskMutex);
@ -45,20 +38,13 @@ void CScheduler::serviceQueue()
// Wait until either there is a new task, or until
// the time of the first item on the queue:
// wait_until needs boost 1.50 or later; older versions have timed_wait:
#if BOOST_VERSION < 105000
while (!shouldStop() && !taskQueue.empty() &&
newTaskScheduled.timed_wait(lock, toPosixTime(taskQueue.begin()->first))) {
// Keep waiting until timeout
}
#else
// Some boost versions have a conflicting overload of wait_until that returns void.
// Explicitly use a template here to avoid hitting that overload.
while (!shouldStop() && !taskQueue.empty() &&
newTaskScheduled.wait_until<>(lock, taskQueue.begin()->first) != boost::cv_status::timeout) {
// Keep waiting until timeout
}
#endif
// If there are multiple threads, the queue can empty while we're waiting (another
// thread may service the task we were waiting on).
if (shouldStop() || taskQueue.empty())

10
src/secp256k1/contrib/lax_der_parsing.h

@ -48,14 +48,14 @@
* 8.3.1.
*/
#ifndef _SECP256K1_CONTRIB_LAX_DER_PARSING_H_
#define _SECP256K1_CONTRIB_LAX_DER_PARSING_H_
#ifndef SECP256K1_CONTRIB_LAX_DER_PARSING_H
#define SECP256K1_CONTRIB_LAX_DER_PARSING_H
#include <secp256k1.h>
# ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
# endif
#endif
/** Parse a signature in "lax DER" format
*
@ -88,4 +88,4 @@ int ecdsa_signature_parse_der_lax(
}
#endif
#endif
#endif /* SECP256K1_CONTRIB_LAX_DER_PARSING_H */

10
src/secp256k1/contrib/lax_der_privatekey_parsing.h

@ -25,14 +25,14 @@
* library are sufficient.
*/
#ifndef _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_
#define _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_
#ifndef SECP256K1_CONTRIB_BER_PRIVATEKEY_H
#define SECP256K1_CONTRIB_BER_PRIVATEKEY_H
#include <secp256k1.h>
# ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
# endif
#endif
/** Export a private key in DER format.
*
@ -87,4 +87,4 @@ SECP256K1_WARN_UNUSED_RESULT int ec_privkey_import_der(
}
#endif
#endif
#endif /* SECP256K1_CONTRIB_BER_PRIVATEKEY_H */

23
src/secp256k1/include/secp256k1.h

@ -1,9 +1,9 @@
#ifndef _SECP256K1_
# define _SECP256K1_
#ifndef SECP256K1_H
#define SECP256K1_H
# ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
# endif
#endif
#include <stddef.h>
@ -61,7 +61,7 @@ typedef struct {
* however guaranteed to be 64 bytes in size, and can be safely copied/moved.
* If you need to convert to a format suitable for storage, transmission, or
* comparison, use the secp256k1_ecdsa_signature_serialize_* and
* secp256k1_ecdsa_signature_serialize_* functions.
* secp256k1_ecdsa_signature_parse_* functions.
*/
typedef struct {
unsigned char data[64];
@ -159,6 +159,13 @@ typedef int (*secp256k1_nonce_function)(
#define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION)
#define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION)
/** Prefix byte used to tag various encoded curvepoints for specific purposes */
#define SECP256K1_TAG_PUBKEY_EVEN 0x02
#define SECP256K1_TAG_PUBKEY_ODD 0x03
#define SECP256K1_TAG_PUBKEY_UNCOMPRESSED 0x04
#define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06
#define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07
/** Create a secp256k1 context object.
*
* Returns: a newly created context object.
@ -607,8 +614,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine(
size_t n
) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
# ifdef __cplusplus
#ifdef __cplusplus
}
# endif
#endif
#endif /* SECP256K1_H */

16
src/secp256k1/include/secp256k1_ecdh.h

@ -1,11 +1,11 @@
#ifndef _SECP256K1_ECDH_
# define _SECP256K1_ECDH_
#ifndef SECP256K1_ECDH_H
#define SECP256K1_ECDH_H
# include "secp256k1.h"
#include "secp256k1.h"
# ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
# endif
#endif
/** Compute an EC Diffie-Hellman secret in constant time
* Returns: 1: exponentiation was successful
@ -24,8 +24,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh(
const unsigned char *privkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
# ifdef __cplusplus
#ifdef __cplusplus
}
# endif
#endif
#endif /* SECP256K1_ECDH_H */

16
src/secp256k1/include/secp256k1_recovery.h

@ -1,11 +1,11 @@
#ifndef _SECP256K1_RECOVERY_
# define _SECP256K1_RECOVERY_
#ifndef SECP256K1_RECOVERY_H
#define SECP256K1_RECOVERY_H
# include "secp256k1.h"
#include "secp256k1.h"
# ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
# endif
#endif
/** Opaque data structured that holds a parsed ECDSA signature,
* supporting pubkey recovery.
@ -103,8 +103,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover(
const unsigned char *msg32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
# ifdef __cplusplus
#ifdef __cplusplus
}
# endif
#endif
#endif /* SECP256K1_RECOVERY_H */

4
src/secp256k1/sage/group_prover.sage

@ -3,7 +3,7 @@
# to independently set assumptions on input or intermediary variables.
#
# The general approach is:
# * A constraint is a tuple of two sets of of symbolic expressions:
# * A constraint is a tuple of two sets of symbolic expressions:
# the first of which are required to evaluate to zero, the second of which
# are required to evaluate to nonzero.
# - A constraint is said to be conflicting if any of its nonzero expressions
@ -17,7 +17,7 @@
# - A constraint describing the requirements of the law, called "require"
# * Implementations are transliterated into functions that operate as well on
# algebraic input points, and are called once per combination of branches
# exectured. Each execution returns:
# executed. Each execution returns:
# - A constraint describing the assumptions this implementation requires
# (such as Z1=1), called "assumeFormula"
# - A constraint describing the assumptions this specific branch requires,

4
src/secp256k1/src/asm/field_10x26_arm.s

@ -11,7 +11,7 @@ Note:
- To avoid unnecessary loads and make use of available registers, two
'passes' have every time been interleaved, with the odd passes accumulating c' and d'
which will be added to c and d respectively in the the even passes
which will be added to c and d respectively in the even passes
*/
@ -23,7 +23,7 @@ Note:
.eabi_attribute 10, 0 @ Tag_FP_arch = none
.eabi_attribute 24, 1 @ Tag_ABI_align_needed = 8-byte
.eabi_attribute 25, 1 @ Tag_ABI_align_preserved = 8-byte, except leaf SP
.eabi_attribute 30, 2 @ Tag_ABI_optimization_goals = Agressive Speed
.eabi_attribute 30, 2 @ Tag_ABI_optimization_goals = Aggressive Speed
.eabi_attribute 34, 1 @ Tag_CPU_unaligned_access = v6
.text

9
src/secp256k1/src/basic-config.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_BASIC_CONFIG_
#define _SECP256K1_BASIC_CONFIG_
#ifndef SECP256K1_BASIC_CONFIG_H
#define SECP256K1_BASIC_CONFIG_H
#ifdef USE_BASIC_CONFIG
@ -28,5 +28,6 @@
#define USE_FIELD_10X26 1
#define USE_SCALAR_8X32 1
#endif // USE_BASIC_CONFIG
#endif // _SECP256K1_BASIC_CONFIG_
#endif /* USE_BASIC_CONFIG */
#endif /* SECP256K1_BASIC_CONFIG_H */

6
src/secp256k1/src/bench.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_BENCH_H_
#define _SECP256K1_BENCH_H_
#ifndef SECP256K1_BENCH_H
#define SECP256K1_BENCH_H
#include <stdio.h>
#include <math.h>
@ -63,4 +63,4 @@ void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), v
printf("us\n");
}
#endif
#endif /* SECP256K1_BENCH_H */

8
src/secp256k1/src/bench_ecdh.c

@ -15,11 +15,11 @@ typedef struct {
secp256k1_context *ctx;
secp256k1_pubkey point;
unsigned char scalar[32];
} bench_ecdh_t;
} bench_ecdh;
static void bench_ecdh_setup(void* arg) {
int i;
bench_ecdh_t *data = (bench_ecdh_t*)arg;
bench_ecdh *data = (bench_ecdh*)arg;
const unsigned char point[] = {
0x03,
0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06,
@ -39,7 +39,7 @@ static void bench_ecdh_setup(void* arg) {
static void bench_ecdh(void* arg) {
int i;
unsigned char res[32];
bench_ecdh_t *data = (bench_ecdh_t*)arg;
bench_ecdh *data = (bench_ecdh*)arg;
for (i = 0; i < 20000; i++) {
CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar) == 1);
@ -47,7 +47,7 @@ static void bench_ecdh(void* arg) {
}
int main(void) {
bench_ecdh_t data;
bench_ecdh data;
run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, 20000);
return 0;

62
src/secp256k1/src/bench_internal.c

@ -25,10 +25,10 @@ typedef struct {
secp256k1_gej gej_x, gej_y;
unsigned char data[64];
int wnaf[256];
} bench_inv_t;
} bench_inv;
void bench_setup(void* arg) {
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
static const unsigned char init_x[32] = {
0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13,
@ -58,7 +58,7 @@ void bench_setup(void* arg) {
void bench_scalar_add(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 2000000; i++) {
secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
@ -67,7 +67,7 @@ void bench_scalar_add(void* arg) {
void bench_scalar_negate(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 2000000; i++) {
secp256k1_scalar_negate(&data->scalar_x, &data->scalar_x);
@ -76,7 +76,7 @@ void bench_scalar_negate(void* arg) {
void bench_scalar_sqr(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 200000; i++) {
secp256k1_scalar_sqr(&data->scalar_x, &data->scalar_x);
@ -85,7 +85,7 @@ void bench_scalar_sqr(void* arg) {
void bench_scalar_mul(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 200000; i++) {
secp256k1_scalar_mul(&data->scalar_x, &data->scalar_x, &data->scalar_y);
@ -95,7 +95,7 @@ void bench_scalar_mul(void* arg) {
#ifdef USE_ENDOMORPHISM
void bench_scalar_split(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 20000; i++) {
secp256k1_scalar l, r;
@ -107,7 +107,7 @@ void bench_scalar_split(void* arg) {
void bench_scalar_inverse(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 2000; i++) {
secp256k1_scalar_inverse(&data->scalar_x, &data->scalar_x);
@ -117,7 +117,7 @@ void bench_scalar_inverse(void* arg) {
void bench_scalar_inverse_var(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 2000; i++) {
secp256k1_scalar_inverse_var(&data->scalar_x, &data->scalar_x);
@ -127,7 +127,7 @@ void bench_scalar_inverse_var(void* arg) {
void bench_field_normalize(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 2000000; i++) {
secp256k1_fe_normalize(&data->fe_x);
@ -136,7 +136,7 @@ void bench_field_normalize(void* arg) {
void bench_field_normalize_weak(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 2000000; i++) {
secp256k1_fe_normalize_weak(&data->fe_x);
@ -145,7 +145,7 @@ void bench_field_normalize_weak(void* arg) {
void bench_field_mul(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 200000; i++) {
secp256k1_fe_mul(&data->fe_x, &data->fe_x, &data->fe_y);
@ -154,7 +154,7 @@ void bench_field_mul(void* arg) {
void bench_field_sqr(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 200000; i++) {
secp256k1_fe_sqr(&data->fe_x, &data->fe_x);
@ -163,7 +163,7 @@ void bench_field_sqr(void* arg) {
void bench_field_inverse(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 20000; i++) {
secp256k1_fe_inv(&data->fe_x, &data->fe_x);
@ -173,7 +173,7 @@ void bench_field_inverse(void* arg) {
void bench_field_inverse_var(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 20000; i++) {
secp256k1_fe_inv_var(&data->fe_x, &data->fe_x);
@ -183,7 +183,7 @@ void bench_field_inverse_var(void* arg) {
void bench_field_sqrt(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 20000; i++) {
secp256k1_fe_sqrt(&data->fe_x, &data->fe_x);
@ -193,7 +193,7 @@ void bench_field_sqrt(void* arg) {
void bench_group_double_var(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 200000; i++) {
secp256k1_gej_double_var(&data->gej_x, &data->gej_x, NULL);
@ -202,7 +202,7 @@ void bench_group_double_var(void* arg) {
void bench_group_add_var(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 200000; i++) {
secp256k1_gej_add_var(&data->gej_x, &data->gej_x, &data->gej_y, NULL);
@ -211,7 +211,7 @@ void bench_group_add_var(void* arg) {
void bench_group_add_affine(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 200000; i++) {
secp256k1_gej_add_ge(&data->gej_x, &data->gej_x, &data->ge_y);
@ -220,7 +220,7 @@ void bench_group_add_affine(void* arg) {
void bench_group_add_affine_var(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 200000; i++) {
secp256k1_gej_add_ge_var(&data->gej_x, &data->gej_x, &data->ge_y, NULL);
@ -229,7 +229,7 @@ void bench_group_add_affine_var(void* arg) {
void bench_group_jacobi_var(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 20000; i++) {
secp256k1_gej_has_quad_y_var(&data->gej_x);
@ -238,7 +238,7 @@ void bench_group_jacobi_var(void* arg) {
void bench_ecmult_wnaf(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 20000; i++) {
secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar_x, WINDOW_A);
@ -248,7 +248,7 @@ void bench_ecmult_wnaf(void* arg) {
void bench_wnaf_const(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 20000; i++) {
secp256k1_wnaf_const(data->wnaf, data->scalar_x, WINDOW_A);
@ -259,8 +259,8 @@ void bench_wnaf_const(void* arg) {
void bench_sha256(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
secp256k1_sha256_t sha;
bench_inv *data = (bench_inv*)arg;
secp256k1_sha256 sha;
for (i = 0; i < 20000; i++) {
secp256k1_sha256_initialize(&sha);
@ -271,8 +271,8 @@ void bench_sha256(void* arg) {
void bench_hmac_sha256(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
secp256k1_hmac_sha256_t hmac;
bench_inv *data = (bench_inv*)arg;
secp256k1_hmac_sha256 hmac;
for (i = 0; i < 20000; i++) {
secp256k1_hmac_sha256_initialize(&hmac, data->data, 32);
@ -283,8 +283,8 @@ void bench_hmac_sha256(void* arg) {
void bench_rfc6979_hmac_sha256(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
secp256k1_rfc6979_hmac_sha256_t rng;
bench_inv *data = (bench_inv*)arg;
secp256k1_rfc6979_hmac_sha256 rng;
for (i = 0; i < 20000; i++) {
secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64);
@ -311,7 +311,7 @@ void bench_context_sign(void* arg) {
#ifndef USE_NUM_NONE
void bench_num_jacobi(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
bench_inv *data = (bench_inv*)arg;
secp256k1_num nx, norder;
secp256k1_scalar_get_num(&nx, &data->scalar_x);
@ -340,7 +340,7 @@ int have_flag(int argc, char** argv, char *flag) {
}
int main(int argc, char **argv) {
bench_inv_t data;
bench_inv data;
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, 2000000);
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, 2000000);
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "sqr")) run_benchmark("scalar_sqr", bench_scalar_sqr, bench_setup, NULL, &data, 10, 200000);

8
src/secp256k1/src/bench_recover.c

@ -13,11 +13,11 @@ typedef struct {
secp256k1_context *ctx;
unsigned char msg[32];
unsigned char sig[64];
} bench_recover_t;
} bench_recover;
void bench_recover(void* arg) {
int i;
bench_recover_t *data = (bench_recover_t*)arg;
bench_recover *data = (bench_recover*)arg;
secp256k1_pubkey pubkey;
unsigned char pubkeyc[33];
@ -38,7 +38,7 @@ void bench_recover(void* arg) {
void bench_recover_setup(void* arg) {
int i;
bench_recover_t *data = (bench_recover_t*)arg;
bench_recover *data = (bench_recover*)arg;
for (i = 0; i < 32; i++) {
data->msg[i] = 1 + i;
@ -49,7 +49,7 @@ void bench_recover_setup(void* arg) {
}
int main(void) {
bench_recover_t data;
bench_recover data;
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);

12
src/secp256k1/src/bench_sign.c

@ -12,11 +12,11 @@ typedef struct {
secp256k1_context* ctx;
unsigned char msg[32];
unsigned char key[32];
} bench_sign_t;
} bench_sign;
static void bench_sign_setup(void* arg) {
int i;
bench_sign_t *data = (bench_sign_t*)arg;
bench_sign *data = (bench_sign*)arg;
for (i = 0; i < 32; i++) {
data->msg[i] = i + 1;
@ -26,9 +26,9 @@ static void bench_sign_setup(void* arg) {
}
}
static void bench_sign(void* arg) {
static void bench_sign_run(void* arg) {
int i;
bench_sign_t *data = (bench_sign_t*)arg;
bench_sign *data = (bench_sign*)arg;
unsigned char sig[74];
for (i = 0; i < 20000; i++) {
@ -45,11 +45,11 @@ static void bench_sign(void* arg) {
}
int main(void) {
bench_sign_t data;
bench_sign data;
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
run_benchmark("ecdsa_sign", bench_sign, bench_sign_setup, NULL, &data, 10, 20000);
run_benchmark("ecdsa_sign", bench_sign_run, bench_sign_setup, NULL, &data, 10, 20000);
secp256k1_context_destroy(data.ctx);
return 0;

6
src/secp256k1/src/ecdsa.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_ECDSA_
#define _SECP256K1_ECDSA_
#ifndef SECP256K1_ECDSA_H
#define SECP256K1_ECDSA_H
#include <stddef.h>
@ -18,4 +18,4 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message);
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid);
#endif
#endif /* SECP256K1_ECDSA_H */

8
src/secp256k1/src/ecdsa_impl.h

@ -5,8 +5,8 @@
**********************************************************************/
#ifndef _SECP256K1_ECDSA_IMPL_H_
#define _SECP256K1_ECDSA_IMPL_H_
#ifndef SECP256K1_ECDSA_IMPL_H
#define SECP256K1_ECDSA_IMPL_H
#include "scalar.h"
#include "field.h"
@ -81,8 +81,6 @@ static int secp256k1_der_read_len(const unsigned char **sigp, const unsigned cha
return -1;
}
while (lenleft > 0) {
if ((ret >> ((sizeof(size_t) - 1) * 8)) != 0) {
}
ret = (ret << 8) | **sigp;
if (ret + lenleft > (size_t)(sigend - *sigp)) {
/* Result exceeds the length of the passed array. */
@ -312,4 +310,4 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec
return 1;
}
#endif
#endif /* SECP256K1_ECDSA_IMPL_H */

6
src/secp256k1/src/eckey.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_ECKEY_
#define _SECP256K1_ECKEY_
#ifndef SECP256K1_ECKEY_H
#define SECP256K1_ECKEY_H
#include <stddef.h>
@ -22,4 +22,4 @@ static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx,
static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak);
static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak);
#endif
#endif /* SECP256K1_ECKEY_H */

17
src/secp256k1/src/eckey_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_ECKEY_IMPL_H_
#define _SECP256K1_ECKEY_IMPL_H_
#ifndef SECP256K1_ECKEY_IMPL_H
#define SECP256K1_ECKEY_IMPL_H
#include "eckey.h"
@ -15,16 +15,17 @@
#include "ecmult_gen.h"
static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) {
if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) {
if (size == 33 && (pub[0] == SECP256K1_TAG_PUBKEY_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_ODD)) {
secp256k1_fe x;
return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == 0x03);
return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == SECP256K1_TAG_PUBKEY_ODD);
} else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) {
secp256k1_fe x, y;
if (!secp256k1_fe_set_b32(&x, pub+1) || !secp256k1_fe_set_b32(&y, pub+33)) {
return 0;
}
secp256k1_ge_set_xy(elem, &x, &y);
if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07)) {
if ((pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD) &&
secp256k1_fe_is_odd(&y) != (pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) {
return 0;
}
return secp256k1_ge_is_valid_var(elem);
@ -42,10 +43,10 @@ static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *p
secp256k1_fe_get_b32(&pub[1], &elem->x);
if (compressed) {
*size = 33;
pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00);
pub[0] = secp256k1_fe_is_odd(&elem->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN;
} else {
*size = 65;
pub[0] = 0x04;
pub[0] = SECP256K1_TAG_PUBKEY_UNCOMPRESSED;
secp256k1_fe_get_b32(&pub[33], &elem->y);
}
return 1;
@ -96,4 +97,4 @@ static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx,
return 1;
}
#endif
#endif /* SECP256K1_ECKEY_IMPL_H */

6
src/secp256k1/src/ecmult.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_ECMULT_
#define _SECP256K1_ECMULT_
#ifndef SECP256K1_ECMULT_H
#define SECP256K1_ECMULT_H
#include "num.h"
#include "group.h"
@ -28,4 +28,4 @@ static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx
/** Double multiply: R = na*A + ng*G */
static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng);
#endif
#endif /* SECP256K1_ECMULT_H */

6
src/secp256k1/src/ecmult_const.h

@ -4,12 +4,12 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_ECMULT_CONST_
#define _SECP256K1_ECMULT_CONST_
#ifndef SECP256K1_ECMULT_CONST_H
#define SECP256K1_ECMULT_CONST_H
#include "scalar.h"
#include "group.h"
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q);
#endif
#endif /* SECP256K1_ECMULT_CONST_H */

13
src/secp256k1/src/ecmult_const_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_ECMULT_CONST_IMPL_
#define _SECP256K1_ECMULT_CONST_IMPL_
#ifndef SECP256K1_ECMULT_CONST_IMPL_H
#define SECP256K1_ECMULT_CONST_IMPL_H
#include "scalar.h"
#include "group.h"
@ -42,11 +42,12 @@
} while(0)
/** Convert a number to WNAF notation. The number becomes represented by sum(2^{wi} * wnaf[i], i=0..return_val)
* with the following guarantees:
/** Convert a number to WNAF notation.
* The number becomes represented by sum(2^{wi} * wnaf[i], i=0..WNAF_SIZE(w)+1) - return_val.
* It has the following guarantees:
* - each wnaf[i] an odd integer between -(1 << w) and (1 << w)
* - each wnaf[i] is nonzero
* - the number of words set is returned; this is always (WNAF_BITS + w - 1) / w
* - the number of words set is always WNAF_SIZE(w) + 1
*
* Adapted from `The Width-w NAF Method Provides Small Memory and Fast Elliptic Scalar
* Multiplications Secure against Side Channel Attacks`, Okeya and Tagaki. M. Joye (Ed.)
@ -236,4 +237,4 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
}
}
#endif
#endif /* SECP256K1_ECMULT_CONST_IMPL_H */

6
src/secp256k1/src/ecmult_gen.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_ECMULT_GEN_
#define _SECP256K1_ECMULT_GEN_
#ifndef SECP256K1_ECMULT_GEN_H
#define SECP256K1_ECMULT_GEN_H
#include "scalar.h"
#include "group.h"
@ -40,4 +40,4 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp25
static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32);
#endif
#endif /* SECP256K1_ECMULT_GEN_H */

8
src/secp256k1/src/ecmult_gen_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_ECMULT_GEN_IMPL_H_
#define _SECP256K1_ECMULT_GEN_IMPL_H_
#ifndef SECP256K1_ECMULT_GEN_IMPL_H
#define SECP256K1_ECMULT_GEN_IMPL_H
#include "scalar.h"
#include "group.h"
@ -161,7 +161,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
secp256k1_gej gb;
secp256k1_fe s;
unsigned char nonce32[32];
secp256k1_rfc6979_hmac_sha256_t rng;
secp256k1_rfc6979_hmac_sha256 rng;
int retry;
unsigned char keydata[64] = {0};
if (seed32 == NULL) {
@ -207,4 +207,4 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
secp256k1_gej_clear(&gb);
}
#endif
#endif /* SECP256K1_ECMULT_GEN_IMPL_H */

6
src/secp256k1/src/ecmult_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_ECMULT_IMPL_H_
#define _SECP256K1_ECMULT_IMPL_H_
#ifndef SECP256K1_ECMULT_IMPL_H
#define SECP256K1_ECMULT_IMPL_H
#include <string.h>
@ -403,4 +403,4 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej
}
}
#endif
#endif /* SECP256K1_ECMULT_IMPL_H */

6
src/secp256k1/src/field.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_FIELD_
#define _SECP256K1_FIELD_
#ifndef SECP256K1_FIELD_H
#define SECP256K1_FIELD_H
/** Field element module.
*
@ -129,4 +129,4 @@ static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_f
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */
static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag);
#endif
#endif /* SECP256K1_FIELD_H */

7
src/secp256k1/src/field_10x26.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_FIELD_REPR_
#define _SECP256K1_FIELD_REPR_
#ifndef SECP256K1_FIELD_REPR_H
#define SECP256K1_FIELD_REPR_H
#include <stdint.h>
@ -44,4 +44,5 @@ typedef struct {
#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}
#define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0]
#endif
#endif /* SECP256K1_FIELD_REPR_H */

6
src/secp256k1/src/field_10x26_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_FIELD_REPR_IMPL_H_
#define _SECP256K1_FIELD_REPR_IMPL_H_
#ifndef SECP256K1_FIELD_REPR_IMPL_H
#define SECP256K1_FIELD_REPR_IMPL_H
#include "util.h"
#include "num.h"
@ -1158,4 +1158,4 @@ static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const se
#endif
}
#endif
#endif /* SECP256K1_FIELD_REPR_IMPL_H */

6
src/secp256k1/src/field_5x52.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_FIELD_REPR_
#define _SECP256K1_FIELD_REPR_
#ifndef SECP256K1_FIELD_REPR_H
#define SECP256K1_FIELD_REPR_H
#include <stdint.h>
@ -44,4 +44,4 @@ typedef struct {
(d6) | (((uint64_t)(d7)) << 32) \
}}
#endif
#endif /* SECP256K1_FIELD_REPR_H */

6
src/secp256k1/src/field_5x52_asm_impl.h

@ -11,8 +11,8 @@
* - December 2014, Pieter Wuille: converted from YASM to GCC inline assembly
*/
#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_
#define _SECP256K1_FIELD_INNER5X52_IMPL_H_
#ifndef SECP256K1_FIELD_INNER5X52_IMPL_H
#define SECP256K1_FIELD_INNER5X52_IMPL_H
SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) {
/**
@ -499,4 +499,4 @@ __asm__ __volatile__(
);
}
#endif
#endif /* SECP256K1_FIELD_INNER5X52_IMPL_H */

6
src/secp256k1/src/field_5x52_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_FIELD_REPR_IMPL_H_
#define _SECP256K1_FIELD_REPR_IMPL_H_
#ifndef SECP256K1_FIELD_REPR_IMPL_H
#define SECP256K1_FIELD_REPR_IMPL_H
#if defined HAVE_CONFIG_H
#include "libsecp256k1-config.h"
@ -493,4 +493,4 @@ static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const se
#endif
}
#endif
#endif /* SECP256K1_FIELD_REPR_IMPL_H */

6
src/secp256k1/src/field_5x52_int128_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_
#define _SECP256K1_FIELD_INNER5X52_IMPL_H_
#ifndef SECP256K1_FIELD_INNER5X52_IMPL_H
#define SECP256K1_FIELD_INNER5X52_IMPL_H
#include <stdint.h>
@ -274,4 +274,4 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t
/* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
}
#endif
#endif /* SECP256K1_FIELD_INNER5X52_IMPL_H */

6
src/secp256k1/src/field_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_FIELD_IMPL_H_
#define _SECP256K1_FIELD_IMPL_H_
#ifndef SECP256K1_FIELD_IMPL_H
#define SECP256K1_FIELD_IMPL_H
#if defined HAVE_CONFIG_H
#include "libsecp256k1-config.h"
@ -312,4 +312,4 @@ static int secp256k1_fe_is_quad_var(const secp256k1_fe *a) {
#endif
}
#endif
#endif /* SECP256K1_FIELD_IMPL_H */

6
src/secp256k1/src/group.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_GROUP_
#define _SECP256K1_GROUP_
#ifndef SECP256K1_GROUP_H
#define SECP256K1_GROUP_H
#include "num.h"
#include "field.h"
@ -141,4 +141,4 @@ static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_g
/** Rescale a jacobian point by b which must be non-zero. Constant-time. */
static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b);
#endif
#endif /* SECP256K1_GROUP_H */

6
src/secp256k1/src/group_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_GROUP_IMPL_H_
#define _SECP256K1_GROUP_IMPL_H_
#ifndef SECP256K1_GROUP_IMPL_H
#define SECP256K1_GROUP_IMPL_H
#include "num.h"
#include "field.h"
@ -697,4 +697,4 @@ static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) {
return secp256k1_fe_is_quad_var(&yz);
}
#endif
#endif /* SECP256K1_GROUP_IMPL_H */

32
src/secp256k1/src/hash.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_HASH_
#define _SECP256K1_HASH_
#ifndef SECP256K1_HASH_H
#define SECP256K1_HASH_H
#include <stdlib.h>
#include <stdint.h>
@ -14,28 +14,28 @@ typedef struct {
uint32_t s[8];
uint32_t buf[16]; /* In big endian */
size_t bytes;
} secp256k1_sha256_t;
} secp256k1_sha256;
static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash);
static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t size);
static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32);
static void secp256k1_sha256_initialize(secp256k1_sha256 *hash);
static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size);
static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32);
typedef struct {
secp256k1_sha256_t inner, outer;
} secp256k1_hmac_sha256_t;
secp256k1_sha256 inner, outer;
} secp256k1_hmac_sha256;
static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t size);
static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size);
static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32);
static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size);
static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size);
static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32);
typedef struct {
unsigned char v[32];
unsigned char k[32];
int retry;
} secp256k1_rfc6979_hmac_sha256_t;
} secp256k1_rfc6979_hmac_sha256;
static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen);
static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen);
static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng);
static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen);
static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen);
static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng);
#endif
#endif /* SECP256K1_HASH_H */

32
src/secp256k1/src/hash_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_HASH_IMPL_H_
#define _SECP256K1_HASH_IMPL_H_
#ifndef SECP256K1_HASH_IMPL_H
#define SECP256K1_HASH_IMPL_H
#include "hash.h"
@ -33,7 +33,7 @@
#define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24))
#endif
static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash) {
static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) {
hash->s[0] = 0x6a09e667ul;
hash->s[1] = 0xbb67ae85ul;
hash->s[2] = 0x3c6ef372ul;
@ -128,7 +128,7 @@ static void secp256k1_sha256_transform(uint32_t* s, const uint32_t* chunk) {
s[7] += h;
}
static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t len) {
static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t len) {
size_t bufsize = hash->bytes & 0x3F;
hash->bytes += len;
while (bufsize + len >= 64) {
@ -145,7 +145,7 @@ static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char
}
}
static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32) {
static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32) {
static const unsigned char pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint32_t sizedesc[2];
uint32_t out[8];
@ -161,14 +161,14 @@ static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *o
memcpy(out32, (const unsigned char*)out, 32);
}
static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t keylen) {
static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) {
int n;
unsigned char rkey[64];
if (keylen <= 64) {
memcpy(rkey, key, keylen);
memset(rkey + keylen, 0, 64 - keylen);
} else {
secp256k1_sha256_t sha256;
secp256k1_sha256 sha256;
secp256k1_sha256_initialize(&sha256);
secp256k1_sha256_write(&sha256, key, keylen);
secp256k1_sha256_finalize(&sha256, rkey);
@ -189,11 +189,11 @@ static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, cons
memset(rkey, 0, 64);
}
static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size) {
static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size) {
secp256k1_sha256_write(&hash->inner, data, size);
}
static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32) {
static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32) {
unsigned char temp[32];
secp256k1_sha256_finalize(&hash->inner, temp);
secp256k1_sha256_write(&hash->outer, temp, 32);
@ -202,8 +202,8 @@ static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsign
}
static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen) {
secp256k1_hmac_sha256_t hmac;
static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) {
secp256k1_hmac_sha256 hmac;
static const unsigned char zero[1] = {0x00};
static const unsigned char one[1] = {0x01};
@ -232,11 +232,11 @@ static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha2
rng->retry = 0;
}
static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen) {
static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen) {
/* RFC6979 3.2.h. */
static const unsigned char zero[1] = {0x00};
if (rng->retry) {
secp256k1_hmac_sha256_t hmac;
secp256k1_hmac_sha256 hmac;
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
secp256k1_hmac_sha256_write(&hmac, zero, 1);
@ -247,7 +247,7 @@ static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256
}
while (outlen > 0) {
secp256k1_hmac_sha256_t hmac;
secp256k1_hmac_sha256 hmac;
int now = outlen;
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
@ -263,7 +263,7 @@ static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256
rng->retry = 1;
}
static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng) {
static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng) {
memset(rng->k, 0, 32);
memset(rng->v, 0, 32);
rng->retry = 0;
@ -278,4 +278,4 @@ static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256
#undef Maj
#undef Ch
#endif
#endif /* SECP256K1_HASH_IMPL_H */

8
src/secp256k1/src/modules/ecdh/main_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_MODULE_ECDH_MAIN_
#define _SECP256K1_MODULE_ECDH_MAIN_
#ifndef SECP256K1_MODULE_ECDH_MAIN_H
#define SECP256K1_MODULE_ECDH_MAIN_H
#include "include/secp256k1_ecdh.h"
#include "ecmult_const_impl.h"
@ -28,7 +28,7 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const se
} else {
unsigned char x[32];
unsigned char y[1];
secp256k1_sha256_t sha;
secp256k1_sha256 sha;
secp256k1_ecmult_const(&res, &pt, &s);
secp256k1_ge_set_gej(&pt, &res);
@ -51,4 +51,4 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const se
return ret;
}
#endif
#endif /* SECP256K1_MODULE_ECDH_MAIN_H */

8
src/secp256k1/src/modules/ecdh/tests_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_MODULE_ECDH_TESTS_
#define _SECP256K1_MODULE_ECDH_TESTS_
#ifndef SECP256K1_MODULE_ECDH_TESTS_H
#define SECP256K1_MODULE_ECDH_TESTS_H
void test_ecdh_api(void) {
/* Setup context that just counts errors */
@ -44,7 +44,7 @@ void test_ecdh_generator_basepoint(void) {
s_one[31] = 1;
/* Check against pubkey creation when the basepoint is the generator */
for (i = 0; i < 100; ++i) {
secp256k1_sha256_t sha;
secp256k1_sha256 sha;
unsigned char s_b32[32];
unsigned char output_ecdh[32];
unsigned char output_ser[32];
@ -102,4 +102,4 @@ void run_ecdh_tests(void) {
test_bad_scalar();
}
#endif
#endif /* SECP256K1_MODULE_ECDH_TESTS_H */

6
src/secp256k1/src/modules/recovery/main_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_MODULE_RECOVERY_MAIN_
#define _SECP256K1_MODULE_RECOVERY_MAIN_
#ifndef SECP256K1_MODULE_RECOVERY_MAIN_H
#define SECP256K1_MODULE_RECOVERY_MAIN_H
#include "include/secp256k1_recovery.h"
@ -190,4 +190,4 @@ int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubk
}
}
#endif
#endif /* SECP256K1_MODULE_RECOVERY_MAIN_H */

6
src/secp256k1/src/modules/recovery/tests_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_MODULE_RECOVERY_TESTS_
#define _SECP256K1_MODULE_RECOVERY_TESTS_
#ifndef SECP256K1_MODULE_RECOVERY_TESTS_H
#define SECP256K1_MODULE_RECOVERY_TESTS_H
static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) {
(void) msg32;
@ -390,4 +390,4 @@ void run_recovery_tests(void) {
test_ecdsa_recovery_edge_cases();
}
#endif
#endif /* SECP256K1_MODULE_RECOVERY_TESTS_H */

6
src/secp256k1/src/num.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_NUM_
#define _SECP256K1_NUM_
#ifndef SECP256K1_NUM_H
#define SECP256K1_NUM_H
#ifndef USE_NUM_NONE
@ -71,4 +71,4 @@ static void secp256k1_num_negate(secp256k1_num *r);
#endif
#endif
#endif /* SECP256K1_NUM_H */

6
src/secp256k1/src/num_gmp.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_NUM_REPR_
#define _SECP256K1_NUM_REPR_
#ifndef SECP256K1_NUM_REPR_H
#define SECP256K1_NUM_REPR_H
#include <gmp.h>
@ -17,4 +17,4 @@ typedef struct {
int limbs;
} secp256k1_num;
#endif
#endif /* SECP256K1_NUM_REPR_H */

6
src/secp256k1/src/num_gmp_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_NUM_REPR_IMPL_H_
#define _SECP256K1_NUM_REPR_IMPL_H_
#ifndef SECP256K1_NUM_REPR_IMPL_H
#define SECP256K1_NUM_REPR_IMPL_H
#include <string.h>
#include <stdlib.h>
@ -285,4 +285,4 @@ static void secp256k1_num_negate(secp256k1_num *r) {
r->neg ^= 1;
}
#endif
#endif /* SECP256K1_NUM_REPR_IMPL_H */

6
src/secp256k1/src/num_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_NUM_IMPL_H_
#define _SECP256K1_NUM_IMPL_H_
#ifndef SECP256K1_NUM_IMPL_H
#define SECP256K1_NUM_IMPL_H
#if defined HAVE_CONFIG_H
#include "libsecp256k1-config.h"
@ -21,4 +21,4 @@
#error "Please select num implementation"
#endif
#endif
#endif /* SECP256K1_NUM_IMPL_H */

6
src/secp256k1/src/scalar.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_SCALAR_
#define _SECP256K1_SCALAR_
#ifndef SECP256K1_SCALAR_H
#define SECP256K1_SCALAR_H
#include "num.h"
@ -103,4 +103,4 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar
/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */
static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift);
#endif
#endif /* SECP256K1_SCALAR_H */

6
src/secp256k1/src/scalar_4x64.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_SCALAR_REPR_
#define _SECP256K1_SCALAR_REPR_
#ifndef SECP256K1_SCALAR_REPR_H
#define SECP256K1_SCALAR_REPR_H
#include <stdint.h>
@ -16,4 +16,4 @@ typedef struct {
#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{((uint64_t)(d1)) << 32 | (d0), ((uint64_t)(d3)) << 32 | (d2), ((uint64_t)(d5)) << 32 | (d4), ((uint64_t)(d7)) << 32 | (d6)}}
#endif
#endif /* SECP256K1_SCALAR_REPR_H */

6
src/secp256k1/src/scalar_4x64_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_
#define _SECP256K1_SCALAR_REPR_IMPL_H_
#ifndef SECP256K1_SCALAR_REPR_IMPL_H
#define SECP256K1_SCALAR_REPR_IMPL_H
/* Limbs of the secp256k1 order. */
#define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL)
@ -946,4 +946,4 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r,
secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1);
}
#endif
#endif /* SECP256K1_SCALAR_REPR_IMPL_H */

6
src/secp256k1/src/scalar_8x32.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_SCALAR_REPR_
#define _SECP256K1_SCALAR_REPR_
#ifndef SECP256K1_SCALAR_REPR_H
#define SECP256K1_SCALAR_REPR_H
#include <stdint.h>
@ -16,4 +16,4 @@ typedef struct {
#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)}}
#endif
#endif /* SECP256K1_SCALAR_REPR_H */

6
src/secp256k1/src/scalar_8x32_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_
#define _SECP256K1_SCALAR_REPR_IMPL_H_
#ifndef SECP256K1_SCALAR_REPR_IMPL_H
#define SECP256K1_SCALAR_REPR_IMPL_H
/* Limbs of the secp256k1 order. */
#define SECP256K1_N_0 ((uint32_t)0xD0364141UL)
@ -718,4 +718,4 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r,
secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1);
}
#endif
#endif /* SECP256K1_SCALAR_REPR_IMPL_H */

6
src/secp256k1/src/scalar_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_SCALAR_IMPL_H_
#define _SECP256K1_SCALAR_IMPL_H_
#ifndef SECP256K1_SCALAR_IMPL_H
#define SECP256K1_SCALAR_IMPL_H
#include "group.h"
#include "scalar.h"
@ -330,4 +330,4 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar
#endif
#endif
#endif
#endif /* SECP256K1_SCALAR_IMPL_H */

6
src/secp256k1/src/scalar_low.h

@ -4,12 +4,12 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_SCALAR_REPR_
#define _SECP256K1_SCALAR_REPR_
#ifndef SECP256K1_SCALAR_REPR_H
#define SECP256K1_SCALAR_REPR_H
#include <stdint.h>
/** A scalar modulo the group order of the secp256k1 curve. */
typedef uint32_t secp256k1_scalar;
#endif
#endif /* SECP256K1_SCALAR_REPR_H */

6
src/secp256k1/src/scalar_low_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_
#define _SECP256K1_SCALAR_REPR_IMPL_H_
#ifndef SECP256K1_SCALAR_REPR_IMPL_H
#define SECP256K1_SCALAR_REPR_IMPL_H
#include "scalar.h"
@ -111,4 +111,4 @@ SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const
return *a == *b;
}
#endif
#endif /* SECP256K1_SCALAR_REPR_IMPL_H */

2
src/secp256k1/src/secp256k1.c

@ -310,7 +310,7 @@ int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_s
static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) {
unsigned char keydata[112];
int keylen = 64;
secp256k1_rfc6979_hmac_sha256_t rng;
secp256k1_rfc6979_hmac_sha256 rng;
unsigned int i;
/* We feed a byte array to the PRNG as input, consisting of:
* - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d.

6
src/secp256k1/src/testrand.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_TESTRAND_H_
#define _SECP256K1_TESTRAND_H_
#ifndef SECP256K1_TESTRAND_H
#define SECP256K1_TESTRAND_H
#if defined HAVE_CONFIG_H
#include "libsecp256k1-config.h"
@ -35,4 +35,4 @@ static void secp256k1_rand256_test(unsigned char *b32);
/** Generate pseudorandom bytes with long sequences of zero and one bits. */
static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len);
#endif
#endif /* SECP256K1_TESTRAND_H */

8
src/secp256k1/src/testrand_impl.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_TESTRAND_IMPL_H_
#define _SECP256K1_TESTRAND_IMPL_H_
#ifndef SECP256K1_TESTRAND_IMPL_H
#define SECP256K1_TESTRAND_IMPL_H
#include <stdint.h>
#include <string.h>
@ -13,7 +13,7 @@
#include "testrand.h"
#include "hash.h"
static secp256k1_rfc6979_hmac_sha256_t secp256k1_test_rng;
static secp256k1_rfc6979_hmac_sha256 secp256k1_test_rng;
static uint32_t secp256k1_test_rng_precomputed[8];
static int secp256k1_test_rng_precomputed_used = 8;
static uint64_t secp256k1_test_rng_integer;
@ -107,4 +107,4 @@ static void secp256k1_rand256_test(unsigned char *b32) {
secp256k1_rand_bytes_test(b32, 32);
}
#endif
#endif /* SECP256K1_TESTRAND_IMPL_H */

6
src/secp256k1/src/tests.c

@ -270,7 +270,7 @@ void run_sha256_tests(void) {
int i;
for (i = 0; i < 8; i++) {
unsigned char out[32];
secp256k1_sha256_t hasher;
secp256k1_sha256 hasher;
secp256k1_sha256_initialize(&hasher);
secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i]));
secp256k1_sha256_finalize(&hasher, out);
@ -313,7 +313,7 @@ void run_hmac_sha256_tests(void) {
};
int i;
for (i = 0; i < 6; i++) {
secp256k1_hmac_sha256_t hasher;
secp256k1_hmac_sha256 hasher;
unsigned char out[32];
secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i]));
secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i]));
@ -345,7 +345,7 @@ void run_rfc6979_hmac_sha256_tests(void) {
{0x75, 0x97, 0x88, 0x7c, 0xbd, 0x76, 0x32, 0x1f, 0x32, 0xe3, 0x04, 0x40, 0x67, 0x9a, 0x22, 0xcf, 0x7f, 0x8d, 0x9d, 0x2e, 0xac, 0x39, 0x0e, 0x58, 0x1f, 0xea, 0x09, 0x1c, 0xe2, 0x02, 0xba, 0x94}
};
secp256k1_rfc6979_hmac_sha256_t rng;
secp256k1_rfc6979_hmac_sha256 rng;
unsigned char out[32];
int i;

6
src/secp256k1/src/util.h

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_UTIL_H_
#define _SECP256K1_UTIL_H_
#ifndef SECP256K1_UTIL_H
#define SECP256K1_UTIL_H
#if defined HAVE_CONFIG_H
#include "libsecp256k1-config.h"
@ -110,4 +110,4 @@ static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_
SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t;
#endif
#endif
#endif /* SECP256K1_UTIL_H */

4
src/serialize.h

@ -661,7 +661,11 @@ void Serialize_impl(Stream& os, const std::vector<T, A>& v, int nType, int nVers
{
WriteCompactSize(os, v.size());
for (typename std::vector<T, A>::const_iterator vi = v.begin(); vi != v.end(); ++vi)
#if defined(__APPLE__)
::Serialize(os, static_cast<T>(*vi), nType, nVersion);
#else
::Serialize(os, (*vi), nType, nVersion);
#endif
}
template<typename Stream, typename T, typename A>

1
src/snark/.gitignore

@ -6,6 +6,7 @@ depinst/
depsrc/
README.html
doxygen/
src/gtests
src/gadgetlib2/examples/tutorial
src/gadgetlib2/tests/gadgetlib2_test

8
src/snark/src/algebra/curves/alt_bn128/alt_bn128_g1.cpp

@ -10,12 +10,12 @@
namespace libsnark {
#ifdef PROFILE_OP_COUNTS
int64_t alt_bn128_G1::add_cnt = 0;
int64_t alt_bn128_G1::dbl_cnt = 0;
long long alt_bn128_G1::add_cnt = 0;
long long alt_bn128_G1::dbl_cnt = 0;
#endif
std::vector<uint64_t> alt_bn128_G1::wnaf_window_table;
std::vector<uint64_t> alt_bn128_G1::fixed_base_exp_window_table;
std::vector<size_t> alt_bn128_G1::wnaf_window_table;
std::vector<size_t> alt_bn128_G1::fixed_base_exp_window_table;
alt_bn128_G1 alt_bn128_G1::G1_zero;
alt_bn128_G1 alt_bn128_G1::G1_one;

10
src/snark/src/algebra/curves/alt_bn128/alt_bn128_g1.hpp

@ -20,11 +20,11 @@ std::istream& operator>>(std::istream &, alt_bn128_G1&);
class alt_bn128_G1 {
public:
#ifdef PROFILE_OP_COUNTS
static int64_t add_cnt;
static int64_t dbl_cnt;
static long long add_cnt;
static long long dbl_cnt;
#endif
static std::vector<uint64_t> wnaf_window_table;
static std::vector<uint64_t> fixed_base_exp_window_table;
static std::vector<size_t> wnaf_window_table;
static std::vector<size_t> fixed_base_exp_window_table;
static alt_bn128_G1 G1_zero;
static alt_bn128_G1 G1_one;
@ -63,7 +63,7 @@ public:
static alt_bn128_G1 one();
static alt_bn128_G1 random_element();
static unsigned long long size_in_bits() { return base_field::size_in_bits() + 1; }
static size_t size_in_bits() { return base_field::size_in_bits() + 1; }
static bigint<base_field::num_limbs> base_field_char() { return base_field::field_char(); }
static bigint<scalar_field::num_limbs> order() { return scalar_field::field_char(); }

8
src/snark/src/algebra/curves/alt_bn128/alt_bn128_g2.cpp

@ -10,12 +10,12 @@
namespace libsnark {
#ifdef PROFILE_OP_COUNTS
int64_t alt_bn128_G2::add_cnt = 0;
int64_t alt_bn128_G2::dbl_cnt = 0;
long long alt_bn128_G2::add_cnt = 0;
long long alt_bn128_G2::dbl_cnt = 0;
#endif
std::vector<uint64_t> alt_bn128_G2::wnaf_window_table;
std::vector<uint64_t> alt_bn128_G2::fixed_base_exp_window_table;
std::vector<size_t> alt_bn128_G2::wnaf_window_table;
std::vector<size_t> alt_bn128_G2::fixed_base_exp_window_table;
alt_bn128_G2 alt_bn128_G2::G2_zero;
alt_bn128_G2 alt_bn128_G2::G2_one;

10
src/snark/src/algebra/curves/alt_bn128/alt_bn128_g2.hpp

@ -20,11 +20,11 @@ std::istream& operator>>(std::istream &, alt_bn128_G2&);
class alt_bn128_G2 {
public:
#ifdef PROFILE_OP_COUNTS
static int64_t add_cnt;
static int64_t dbl_cnt;
static long long add_cnt;
static long long dbl_cnt;
#endif
static std::vector<uint64_t> wnaf_window_table;
static std::vector<uint64_t> fixed_base_exp_window_table;
static std::vector<size_t> wnaf_window_table;
static std::vector<size_t> fixed_base_exp_window_table;
static alt_bn128_G2 G2_zero;
static alt_bn128_G2 G2_one;
@ -67,7 +67,7 @@ public:
static alt_bn128_G2 one();
static alt_bn128_G2 random_element();
static unsigned long long size_in_bits() { return twist_field::size_in_bits() + 1; }
static size_t size_in_bits() { return twist_field::size_in_bits() + 1; }
static bigint<base_field::num_limbs> base_field_char() { return base_field::field_char(); }
static bigint<scalar_field::num_limbs> order() { return scalar_field::field_char(); }

6
src/snark/src/algebra/curves/alt_bn128/alt_bn128_pairing.cpp

@ -324,7 +324,7 @@ alt_bn128_ate_G2_precomp alt_bn128_ate_precompute_G2(const alt_bn128_G2& Q)
bool found_one = false;
alt_bn128_ate_ell_coeffs c;
for (int64_t i = loop_count.max_bits(); i >= 0; --i)
for (long i = loop_count.max_bits(); i >= 0; --i)
{
const bool bit = loop_count.test_bit(i);
if (!found_one)
@ -378,7 +378,7 @@ alt_bn128_Fq12 alt_bn128_ate_miller_loop(const alt_bn128_ate_G1_precomp &prec_P,
const bigint<alt_bn128_Fr::num_limbs> &loop_count = alt_bn128_ate_loop_count;
alt_bn128_ate_ell_coeffs c;
for (int64_t i = loop_count.max_bits(); i >= 0; --i)
for (long i = loop_count.max_bits(); i >= 0; --i)
{
const bool bit = loop_count.test_bit(i);
if (!found_one)
@ -432,7 +432,7 @@ alt_bn128_Fq12 alt_bn128_ate_double_miller_loop(const alt_bn128_ate_G1_precomp &
size_t idx = 0;
const bigint<alt_bn128_Fr::num_limbs> &loop_count = alt_bn128_ate_loop_count;
for (int64_t i = loop_count.max_bits(); i >= 0; --i)
for (long i = loop_count.max_bits(); i >= 0; --i)
{
const bool bit = loop_count.test_bit(i);
if (!found_one)

2
src/snark/src/algebra/curves/curve_utils.tcc

@ -16,7 +16,7 @@ GroupT scalar_mul(const GroupT &base, const bigint<m> &scalar)
GroupT result = GroupT::zero();
bool found_one = false;
for (int64_t i = scalar.max_bits() - 1; i >= 0; --i)
for (long i = scalar.max_bits() - 1; i >= 0; --i)
{
if (found_one)
{

42
src/snark/src/algebra/curves/tests/test_bilinearity.cpp

@ -4,17 +4,13 @@
* and contributors (see AUTHORS).
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#include <iostream>
#include "common/profiling.hpp"
//#include "algebra/curves/edwards/edwards_pp.hpp"
#ifdef CURVE_BN128
#include "algebra/curves/bn128/bn128_pp.hpp"
#endif
#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp"
//#include "algebra/curves/mnt/mnt4/mnt4_pp.hpp"
//#include "algebra/curves/mnt/mnt6/mnt6_pp.hpp"
#include "algebra/curves/alt_bn128/alt_bn128_pairing.hpp"
#include "algebra/curves/alt_bn128/alt_bn128_pairing.cpp"
#include <gtest/gtest.h>
using namespace libsnark;
@ -49,11 +45,11 @@ void pairing_test()
ans1.print();
ans2.print();
ans3.print();
assert(ans1 == ans2);
assert(ans2 == ans3);
EXPECT_EQ(ans1, ans2);
EXPECT_EQ(ans2, ans3);
assert(ans1 != GT_one);
assert((ans1^Fr<ppT>::field_char()) == GT_one);
EXPECT_NE(ans1, GT_one);
EXPECT_EQ((ans1^Fr<ppT>::field_char()), GT_one);
printf("\n\n");
}
@ -73,7 +69,7 @@ void double_miller_loop_test()
const Fqk<ppT> ans_1 = ppT::miller_loop(prec_P1, prec_Q1);
const Fqk<ppT> ans_2 = ppT::miller_loop(prec_P2, prec_Q2);
const Fqk<ppT> ans_12 = ppT::double_miller_loop(prec_P1, prec_Q1, prec_P2, prec_Q2);
assert(ans_1 * ans_2 == ans_12);
EXPECT_EQ(ans_1 * ans_2, ans_12);
}
template<typename ppT>
@ -102,31 +98,17 @@ void affine_pairing_test()
ans1.print();
ans2.print();
ans3.print();
assert(ans1 == ans2);
assert(ans2 == ans3);
EXPECT_EQ(ans1, ans2);
EXPECT_EQ(ans2, ans3);
assert(ans1 != GT_one);
assert((ans1^Fr<ppT>::field_char()) == GT_one);
EXPECT_NE(ans1, GT_one);
EXPECT_EQ((ans1^Fr<ppT>::field_char()), GT_one);
printf("\n\n");
}
int main(void)
TEST(algebra, bilinearity)
{
start_profiling();
edwards_pp::init_public_params();
pairing_test<edwards_pp>();
double_miller_loop_test<edwards_pp>();
mnt6_pp::init_public_params();
pairing_test<mnt6_pp>();
double_miller_loop_test<mnt6_pp>();
affine_pairing_test<mnt6_pp>();
mnt4_pp::init_public_params();
pairing_test<mnt4_pp>();
double_miller_loop_test<mnt4_pp>();
affine_pairing_test<mnt4_pp>();
alt_bn128_pp::init_public_params();
pairing_test<alt_bn128_pp>();
double_miller_loop_test<alt_bn128_pp>();

101
src/snark/src/algebra/curves/tests/test_groups.cpp

@ -5,15 +5,14 @@
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#include "common/profiling.hpp"
//#include "algebra/curves/edwards/edwards_pp.hpp"
//#include "algebra/curves/mnt/mnt4/mnt4_pp.hpp"
//#include "algebra/curves/mnt/mnt6/mnt6_pp.hpp"
#ifdef CURVE_BN128
#include "algebra/curves/bn128/bn128_pp.hpp"
#endif
#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp"
#include <sstream>
#include <gtest/gtest.h>
using namespace libsnark;
template<typename GroupT>
@ -25,31 +24,31 @@ void test_mixed_add()
el = GroupT::zero();
el.to_special();
result = base.mixed_add(el);
assert(result == base + el);
EXPECT_EQ(result, base + el);
base = GroupT::zero();
el = GroupT::random_element();
el.to_special();
result = base.mixed_add(el);
assert(result == base + el);
EXPECT_EQ(result, base + el);
base = GroupT::random_element();
el = GroupT::zero();
el.to_special();
result = base.mixed_add(el);
assert(result == base + el);
EXPECT_EQ(result, base + el);
base = GroupT::random_element();
el = GroupT::random_element();
el.to_special();
result = base.mixed_add(el);
assert(result == base + el);
EXPECT_EQ(result, base + el);
base = GroupT::random_element();
el = base;
el.to_special();
result = base.mixed_add(el);
assert(result == base.dbl());
EXPECT_EQ(result, base.dbl());
}
template<typename GroupT>
@ -60,53 +59,53 @@ void test_group()
bigint<1> randsum = bigint<1>("121160274");
GroupT zero = GroupT::zero();
assert(zero == zero);
EXPECT_EQ(zero, zero);
GroupT one = GroupT::one();
assert(one == one);
EXPECT_EQ(one, one);
GroupT two = bigint<1>(2l) * GroupT::one();
assert(two == two);
EXPECT_EQ(two, two);
GroupT five = bigint<1>(5l) * GroupT::one();
GroupT three = bigint<1>(3l) * GroupT::one();
GroupT four = bigint<1>(4l) * GroupT::one();
assert(two+five == three+four);
EXPECT_EQ(two+five, three+four);
GroupT a = GroupT::random_element();
GroupT b = GroupT::random_element();
assert(one != zero);
assert(a != zero);
assert(a != one);
EXPECT_NE(one, zero);
EXPECT_NE(a, zero);
EXPECT_NE(a, one);
assert(b != zero);
assert(b != one);
EXPECT_NE(b, zero);
EXPECT_NE(b, one);
assert(a.dbl() == a + a);
assert(b.dbl() == b + b);
assert(one.add(two) == three);
assert(two.add(one) == three);
assert(a + b == b + a);
assert(a - a == zero);
assert(a - b == a + (-b));
assert(a - b == (-b) + a);
EXPECT_EQ(a.dbl(), a + a);
EXPECT_EQ(b.dbl(), b + b);
EXPECT_EQ(one.add(two), three);
EXPECT_EQ(two.add(one), three);
EXPECT_EQ(a + b, b + a);
EXPECT_EQ(a - a, zero);
EXPECT_EQ(a - b, a + (-b));
EXPECT_EQ(a - b, (-b) + a);
// handle special cases
assert(zero + (-a) == -a);
assert(zero - a == -a);
assert(a - zero == a);
assert(a + zero == a);
assert(zero + a == a);
EXPECT_EQ(zero + (-a), -a);
EXPECT_EQ(zero - a, -a);
EXPECT_EQ(a - zero, a);
EXPECT_EQ(a + zero, a);
EXPECT_EQ(zero + a, a);
assert((a + b).dbl() == (a + b) + (b + a));
assert(bigint<1>("2") * (a + b) == (a + b) + (b + a));
EXPECT_EQ((a + b).dbl(), (a + b) + (b + a));
EXPECT_EQ(bigint<1>("2") * (a + b), (a + b) + (b + a));
assert((rand1 * a) + (rand2 * a) == (randsum * a));
EXPECT_EQ((rand1 * a) + (rand2 * a), (randsum * a));
assert(GroupT::order() * a == zero);
assert(GroupT::order() * one == zero);
assert((GroupT::order() * a) - a != zero);
assert((GroupT::order() * one) - one != zero);
EXPECT_EQ(GroupT::order() * a, zero);
EXPECT_EQ(GroupT::order() * one, zero);
EXPECT_NE((GroupT::order() * a) - a, zero);
EXPECT_NE((GroupT::order() * one) - one, zero);
test_mixed_add<GroupT>();
}
@ -115,7 +114,7 @@ template<typename GroupT>
void test_mul_by_q()
{
GroupT a = GroupT::random_element();
assert((GroupT::base_field_char()*a) == a.mul_by_q());
EXPECT_EQ((GroupT::base_field_char()*a), a.mul_by_q());
}
template<typename GroupT>
@ -129,36 +128,14 @@ void test_output()
ss << g;
GroupT gg;
ss >> gg;
assert(g == gg);
EXPECT_EQ(g, gg);
/* use a random point in next iteration */
g = GroupT::random_element();
}
}
int main(void)
TEST(algebra, groups)
{
/*
edwards_pp::init_public_params();
test_group<G1<edwards_pp> >();
test_output<G1<edwards_pp> >();
test_group<G2<edwards_pp> >();
test_output<G2<edwards_pp> >();
test_mul_by_q<G2<edwards_pp> >();
mnt4_pp::init_public_params();
test_group<G1<mnt4_pp> >();
test_output<G1<mnt4_pp> >();
test_group<G2<mnt4_pp> >();
test_output<G2<mnt4_pp> >();
test_mul_by_q<G2<mnt4_pp> >();
mnt6_pp::init_public_params();
test_group<G1<mnt6_pp> >();
test_output<G1<mnt6_pp> >();
test_group<G2<mnt6_pp> >();
test_output<G2<mnt6_pp> >();
test_mul_by_q<G2<mnt6_pp> >();
*/
alt_bn128_pp::init_public_params();
test_group<G1<alt_bn128_pp> >();
test_output<G1<alt_bn128_pp> >();

10
src/snark/src/algebra/evaluation_domain/domains/basic_radix2_domain_aux.tcc

@ -74,11 +74,11 @@ void _basic_serial_radix2_FFT(std::vector<FieldT> &a, const FieldT &omega)
template<typename FieldT>
void _basic_parallel_radix2_FFT_inner(std::vector<FieldT> &a, const FieldT &omega, const size_t log_cpus)
{
const size_t num_cpus = UINT64_C(1)<<log_cpus;
const size_t num_cpus = 1ul<<log_cpus;
const size_t m = a.size();
const size_t log_m = log2(m);
assert(m == UINT64_C(1)<<log_m);
assert(m == 1ul<<log_m);
if (log_m < log_cpus)
{
@ -90,7 +90,7 @@ void _basic_parallel_radix2_FFT_inner(std::vector<FieldT> &a, const FieldT &omeg
std::vector<std::vector<FieldT> > tmp(num_cpus);
for (size_t j = 0; j < num_cpus; ++j)
{
tmp[j].resize(UINT64_C(1)<<(log_m-log_cpus), FieldT::zero());
tmp[j].resize(1ul<<(log_m-log_cpus), FieldT::zero());
}
#ifdef MULTICORE
@ -102,7 +102,7 @@ void _basic_parallel_radix2_FFT_inner(std::vector<FieldT> &a, const FieldT &omeg
const FieldT omega_step = omega^(j<<(log_m - log_cpus));
FieldT elt = FieldT::one();
for (size_t i = 0; i < UINT64_C(1)<<(log_m - log_cpus); ++i)
for (size_t i = 0; i < 1ul<<(log_m - log_cpus); ++i)
{
for (size_t s = 0; s < num_cpus; ++s)
{
@ -135,7 +135,7 @@ void _basic_parallel_radix2_FFT_inner(std::vector<FieldT> &a, const FieldT &omeg
#endif
for (size_t i = 0; i < num_cpus; ++i)
{
for (size_t j = 0; j < UINT64_C(1)<<(log_m - log_cpus); ++j)
for (size_t j = 0; j < 1ul<<(log_m - log_cpus); ++j)
{
// now: i = idx >> (log_m - log_cpus) and j = idx % (1u << (log_m - log_cpus)), for idx = ((i<<(log_m-log_cpus))+j) % (1u << log_m)
a[(j<<log_cpus) + i] = tmp[i][j];

48
src/snark/src/algebra/evaluation_domain/domains/extended_radix2_domain.hpp

@ -1,48 +0,0 @@
/** @file
*****************************************************************************
Declaration of interfaces for the "extended radix-2" evaluation domain.
Roughly, the domain has size m = 2^{k+1} and consists of
"the m-th roots of unity" union "a coset of these roots".
*****************************************************************************
* @author This file is part of libsnark, developed by SCIPR Lab
* and contributors (see AUTHORS).
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#ifndef EXTENDED_RADIX2_DOMAIN_HPP_
#define EXTENDED_RADIX2_DOMAIN_HPP_
#include "algebra/evaluation_domain/evaluation_domain.hpp"
namespace libsnark {
template<typename FieldT>
class extended_radix2_domain : public evaluation_domain<FieldT> {
public:
size_t small_m;
FieldT omega;
FieldT shift;
extended_radix2_domain(const size_t m);
void FFT(std::vector<FieldT> &a);
void iFFT(std::vector<FieldT> &a);
void cosetFFT(std::vector<FieldT> &a, const FieldT &g);
void icosetFFT(std::vector<FieldT> &a, const FieldT &g);
std::vector<FieldT> lagrange_coeffs(const FieldT &t);
FieldT get_element(const size_t idx);
FieldT compute_Z(const FieldT &t);
void add_poly_Z(const FieldT &coeff, std::vector<FieldT> &H);
void divide_by_Z_on_coset(std::vector<FieldT> &P);
};
} // libsnark
#include "algebra/evaluation_domain/domains/extended_radix2_domain.tcc"
#endif // EXTENDED_RADIX2_DOMAIN_HPP_

180
src/snark/src/algebra/evaluation_domain/domains/extended_radix2_domain.tcc

@ -1,180 +0,0 @@
/** @file
*****************************************************************************
Implementation of interfaces for the "extended radix-2" evaluation domain.
See extended_radix2_domain.hpp .
*****************************************************************************
* @author This file is part of libsnark, developed by SCIPR Lab
* and contributors (see AUTHORS).
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#ifndef EXTENDED_RADIX2_DOMAIN_TCC_
#include "algebra/evaluation_domain/domains/basic_radix2_domain_aux.hpp"
namespace libsnark {
template<typename FieldT>
extended_radix2_domain<FieldT>::extended_radix2_domain(const size_t m) : evaluation_domain<FieldT>(m)
{
assert(m > 1);
const size_t logm = log2(m);
assert(logm == FieldT::s + 1);
small_m = m/2;
omega = get_root_of_unity<FieldT>(small_m);
shift = coset_shift<FieldT>();
}
template<typename FieldT>
void extended_radix2_domain<FieldT>::FFT(std::vector<FieldT> &a)
{
assert(a.size() == this->m);
std::vector<FieldT> a0(small_m, FieldT::zero());
std::vector<FieldT> a1(small_m, FieldT::zero());
const FieldT shift_to_small_m = shift^bigint<1>(small_m);
FieldT shift_i = FieldT::one();
for (size_t i = 0; i < small_m; ++i)
{
a0[i] = a[i] + a[small_m + i];
a1[i] = shift_i * (a[i] + shift_to_small_m * a[small_m + i]);
shift_i *= shift;
}
_basic_radix2_FFT(a0, omega);
_basic_radix2_FFT(a1, omega);
for (size_t i = 0; i < small_m; ++i)
{
a[i] = a0[i];
a[i+small_m] = a1[i];
}
}
template<typename FieldT>
void extended_radix2_domain<FieldT>::iFFT(std::vector<FieldT> &a)
{
assert(a.size() == this->m);
// note: this is not in-place
std::vector<FieldT> a0(a.begin(), a.begin() + small_m);
std::vector<FieldT> a1(a.begin() + small_m, a.end());
const FieldT omega_inverse = omega.inverse();
_basic_radix2_FFT(a0, omega_inverse);
_basic_radix2_FFT(a1, omega_inverse);
const FieldT shift_to_small_m = shift^bigint<1>(small_m);
const FieldT sconst = (FieldT(small_m) * (FieldT::one()-shift_to_small_m)).inverse();
const FieldT shift_inverse = shift.inverse();
FieldT shift_inverse_i = FieldT::one();
for (size_t i = 0; i < small_m; ++i)
{
a[i] = sconst * (-shift_to_small_m * a0[i] + shift_inverse_i * a1[i]);
a[i+small_m] = sconst * (a0[i] - shift_inverse_i * a1[i]);
shift_inverse_i *= shift_inverse;
}
}
template<typename FieldT>
void extended_radix2_domain<FieldT>::cosetFFT(std::vector<FieldT> &a, const FieldT &g)
{
_multiply_by_coset(a, g);
FFT(a);
}
template<typename FieldT>
void extended_radix2_domain<FieldT>::icosetFFT(std::vector<FieldT> &a, const FieldT &g)
{
iFFT(a);
_multiply_by_coset(a, g.inverse());
}
template<typename FieldT>
std::vector<FieldT> extended_radix2_domain<FieldT>::lagrange_coeffs(const FieldT &t)
{
const std::vector<FieldT> T0 = _basic_radix2_lagrange_coeffs(small_m, t);
const std::vector<FieldT> T1 = _basic_radix2_lagrange_coeffs(small_m, t * shift.inverse());
std::vector<FieldT> result(this->m, FieldT::zero());
const FieldT t_to_small_m = t ^ bigint<1>(small_m);
const FieldT shift_to_small_m = shift ^ bigint<1>(small_m);
const FieldT one_over_denom = (shift_to_small_m - FieldT::one()).inverse();
const FieldT T0_coeff = (t_to_small_m - shift_to_small_m) * (-one_over_denom);
const FieldT T1_coeff = (t_to_small_m - FieldT::one()) * one_over_denom;
for (size_t i = 0; i < small_m; ++i)
{
result[i] = T0[i] * T0_coeff;
result[i+small_m] = T1[i] * T1_coeff;
}
return result;
}
template<typename FieldT>
FieldT extended_radix2_domain<FieldT>::get_element(const size_t idx)
{
if (idx < small_m)
{
return omega^idx;
}
else
{
return shift*(omega^(idx-small_m));
}
}
template<typename FieldT>
FieldT extended_radix2_domain<FieldT>::compute_Z(const FieldT &t)
{
return ((t^small_m) - FieldT::one()) * ((t^small_m) - (shift^small_m));
}
template<typename FieldT>
void extended_radix2_domain<FieldT>::add_poly_Z(const FieldT &coeff, std::vector<FieldT> &H)
{
assert(H.size() == this->m+1);
const FieldT shift_to_small_m = shift^small_m;
H[this->m] += coeff;
H[small_m] -= coeff * (shift_to_small_m + FieldT::one());
H[0] += coeff * shift_to_small_m;
}
template<typename FieldT>
void extended_radix2_domain<FieldT>::divide_by_Z_on_coset(std::vector<FieldT> &P)
{
const FieldT coset = FieldT::multiplicative_generator;
const FieldT coset_to_small_m = coset^small_m;
const FieldT shift_to_small_m = shift^small_m;
const FieldT Z0 = (coset_to_small_m - FieldT::one()) * (coset_to_small_m - shift_to_small_m);
const FieldT Z1 = (coset_to_small_m*shift_to_small_m - FieldT::one()) * (coset_to_small_m * shift_to_small_m - shift_to_small_m);
const FieldT Z0_inverse = Z0.inverse();
const FieldT Z1_inverse = Z1.inverse();
for (size_t i = 0; i < small_m; ++i)
{
P[i] *= Z0_inverse;
P[i+small_m] *= Z1_inverse;
}
}
} // libsnark
#endif // EXTENDED_RADIX2_DOMAIN_TCC_

50
src/snark/src/algebra/evaluation_domain/domains/step_radix2_domain.hpp

@ -1,50 +0,0 @@
/** @file
*****************************************************************************
Declaration of interfaces for the "step radix-2" evaluation domain.
Roughly, the domain has size m = 2^k + 2^r and consists of
"the 2^k-th roots of unity" union "a coset of 2^r-th roots of unity".
*****************************************************************************
* @author This file is part of libsnark, developed by SCIPR Lab
* and contributors (see AUTHORS).
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#ifndef STEP_RADIX2_DOMAIN_HPP_
#define STEP_RADIX2_DOMAIN_HPP_
#include "algebra/evaluation_domain/evaluation_domain.hpp"
namespace libsnark {
template<typename FieldT>
class step_radix2_domain : public evaluation_domain<FieldT> {
public:
size_t big_m;
size_t small_m;
FieldT omega;
FieldT big_omega;
FieldT small_omega;
step_radix2_domain(const size_t m);
void FFT(std::vector<FieldT> &a);
void iFFT(std::vector<FieldT> &a);
void cosetFFT(std::vector<FieldT> &a, const FieldT &g);
void icosetFFT(std::vector<FieldT> &a, const FieldT &g);
std::vector<FieldT> lagrange_coeffs(const FieldT &t);
FieldT get_element(const size_t idx);
FieldT compute_Z(const FieldT &t);
void add_poly_Z(const FieldT &coeff, std::vector<FieldT> &H);
void divide_by_Z_on_coset(std::vector<FieldT> &P);
};
} // libsnark
#include "algebra/evaluation_domain/domains/step_radix2_domain.tcc"
#endif // STEP_RADIX2_DOMAIN_HPP_

247
src/snark/src/algebra/evaluation_domain/domains/step_radix2_domain.tcc

@ -1,247 +0,0 @@
/** @file
*****************************************************************************
Implementation of interfaces for the "step radix-2" evaluation domain.
See step_radix2_domain.hpp .
*****************************************************************************
* @author This file is part of libsnark, developed by SCIPR Lab
* and contributors (see AUTHORS).
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#ifndef STEP_RADIX2_DOMAIN_TCC_
#include "algebra/evaluation_domain/domains/basic_radix2_domain_aux.hpp"
namespace libsnark {
template<typename FieldT>
step_radix2_domain<FieldT>::step_radix2_domain(const size_t m) : evaluation_domain<FieldT>(m)
{
assert(m > 1);
big_m = UINT64_C(1)<<(log2(m)-1);
small_m = m - big_m;
assert(small_m == UINT64_C(1)<<log2(small_m));
omega = get_root_of_unity<FieldT>(UINT64_C(1)<<log2(m)); // rounded!
big_omega = omega.squared();
small_omega = get_root_of_unity<FieldT>(small_m);
}
template<typename FieldT>
void step_radix2_domain<FieldT>::FFT(std::vector<FieldT> &a)
{
assert(a.size() == this->m);
std::vector<FieldT> c(big_m, FieldT::zero());
std::vector<FieldT> d(big_m, FieldT::zero());
FieldT omega_i = FieldT::one();
for (size_t i = 0; i < big_m; ++i)
{
c[i] = (i < small_m ? a[i] + a[i+big_m] : a[i]);
d[i] = omega_i * (i < small_m ? a[i] - a[i+big_m] : a[i]);
omega_i *= omega;
}
std::vector<FieldT> e(small_m, FieldT::zero());
const size_t compr = UINT64_C(1)<<(log2(big_m) - log2(small_m));
for (size_t i = 0; i < small_m; ++i)
{
for (size_t j = 0; j < compr; ++j)
{
e[i] += d[i + j * small_m];
}
}
_basic_radix2_FFT(c, omega.squared());
_basic_radix2_FFT(e, get_root_of_unity<FieldT>(small_m));
for (size_t i = 0; i < big_m; ++i)
{
a[i] = c[i];
}
for (size_t i = 0; i < small_m; ++i)
{
a[i+big_m] = e[i];
}
}
template<typename FieldT>
void step_radix2_domain<FieldT>::iFFT(std::vector<FieldT> &a)
{
assert(a.size() == this->m);
std::vector<FieldT> U0(a.begin(), a.begin() + big_m);
std::vector<FieldT> U1(a.begin() + big_m, a.end());
_basic_radix2_FFT(U0, omega.squared().inverse());
_basic_radix2_FFT(U1, get_root_of_unity<FieldT>(small_m).inverse());
const FieldT U0_size_inv = FieldT(big_m).inverse();
for (size_t i = 0; i < big_m; ++i)
{
U0[i] *= U0_size_inv;
}
const FieldT U1_size_inv = FieldT(small_m).inverse();
for (size_t i = 0; i < small_m; ++i)
{
U1[i] *= U1_size_inv;
}
std::vector<FieldT> tmp = U0;
FieldT omega_i = FieldT::one();
for (size_t i = 0; i < big_m; ++i)
{
tmp[i] *= omega_i;
omega_i *= omega;
}
// save A_suffix
for (size_t i = small_m; i < big_m; ++i)
{
a[i] = U0[i];
}
const size_t compr = UINT64_C(1)<<(log2(big_m) - log2(small_m));
for (size_t i = 0; i < small_m; ++i)
{
for (size_t j = 1; j < compr; ++j)
{
U1[i] -= tmp[i + j * small_m];
}
}
const FieldT omega_inv = omega.inverse();
FieldT omega_inv_i = FieldT::one();
for (size_t i = 0; i < small_m; ++i)
{
U1[i] *= omega_inv_i;
omega_inv_i *= omega_inv;
}
// compute A_prefix
const FieldT over_two = FieldT(2).inverse();
for (size_t i = 0; i < small_m; ++i)
{
a[i] = (U0[i]+U1[i]) * over_two;
}
// compute B2
for (size_t i = 0; i < small_m; ++i)
{
a[big_m + i] = (U0[i]-U1[i]) * over_two;
}
}
template<typename FieldT>
void step_radix2_domain<FieldT>::cosetFFT(std::vector<FieldT> &a, const FieldT &g)
{
_multiply_by_coset(a, g);
FFT(a);
}
template<typename FieldT>
void step_radix2_domain<FieldT>::icosetFFT(std::vector<FieldT> &a, const FieldT &g)
{
iFFT(a);
_multiply_by_coset(a, g.inverse());
}
template<typename FieldT>
std::vector<FieldT> step_radix2_domain<FieldT>::lagrange_coeffs(const FieldT &t)
{
std::vector<FieldT> inner_big = _basic_radix2_lagrange_coeffs(big_m, t);
std::vector<FieldT> inner_small = _basic_radix2_lagrange_coeffs(small_m, t * omega.inverse());
std::vector<FieldT> result(this->m, FieldT::zero());
const FieldT L0 = (t^small_m)-(omega^small_m);
const FieldT omega_to_small_m = omega^small_m;
const FieldT big_omega_to_small_m = big_omega ^ small_m;
FieldT elt = FieldT::one();
for (size_t i = 0; i < big_m; ++i)
{
result[i] = inner_big[i] * L0 * (elt - omega_to_small_m).inverse();
elt *= big_omega_to_small_m;
}
const FieldT L1 = ((t^big_m)-FieldT::one()) * ((omega^big_m) - FieldT::one()).inverse();
for (size_t i = 0; i < small_m; ++i)
{
result[big_m + i] = L1 * inner_small[i];
}
return result;
}
template<typename FieldT>
FieldT step_radix2_domain<FieldT>::get_element(const size_t idx)
{
if (idx < big_m)
{
return big_omega^idx;
}
else
{
return omega * (small_omega^(idx-big_m));
}
}
template<typename FieldT>
FieldT step_radix2_domain<FieldT>::compute_Z(const FieldT &t)
{
return ((t^big_m) - FieldT::one()) * ((t^small_m) - (omega^small_m));
}
template<typename FieldT>
void step_radix2_domain<FieldT>::add_poly_Z(const FieldT &coeff, std::vector<FieldT> &H)
{
assert(H.size() == this->m+1);
const FieldT omega_to_small_m = omega^small_m;
H[this->m] += coeff;
H[big_m] -= coeff * omega_to_small_m;
H[small_m] -= coeff;
H[0] += coeff * omega_to_small_m;
}
template<typename FieldT>
void step_radix2_domain<FieldT>::divide_by_Z_on_coset(std::vector<FieldT> &P)
{
// (c^{2^k}-1) * (c^{2^r} * w^{2^{r+1}*i) - w^{2^r})
const FieldT coset = FieldT::multiplicative_generator;
const FieldT Z0 = (coset^big_m) - FieldT::one();
const FieldT coset_to_small_m_times_Z0 = (coset^small_m) * Z0;
const FieldT omega_to_small_m_times_Z0 = (omega^small_m) * Z0;
const FieldT omega_to_2small_m = omega^(2*small_m);
FieldT elt = FieldT::one();
for (size_t i = 0; i < big_m; ++i)
{
P[i] *= (coset_to_small_m_times_Z0 * elt - omega_to_small_m_times_Z0).inverse();
elt *= omega_to_2small_m;
}
// (c^{2^k}*w^{2^k}-1) * (c^{2^k} * w^{2^r} - w^{2^r})
const FieldT Z1 = ((((coset*omega)^big_m) - FieldT::one()) * (((coset * omega)^small_m) - (omega^small_m)));
const FieldT Z1_inverse = Z1.inverse();
for (size_t i = 0; i < small_m; ++i)
{
P[big_m + i] *= Z1_inverse;
}
}
} // libsnark
#endif // STEP_RADIX2_DOMAIN_TCC_

12
src/snark/src/algebra/evaluation_domain/evaluation_domain.tcc

@ -22,8 +22,6 @@
#include <cassert>
#include "algebra/fields/field_utils.hpp"
#include "algebra/evaluation_domain/domains/basic_radix2_domain.hpp"
#include "algebra/evaluation_domain/domains/extended_radix2_domain.hpp"
#include "algebra/evaluation_domain/domains/step_radix2_domain.hpp"
namespace libsnark {
@ -43,7 +41,7 @@ std::shared_ptr<evaluation_domain<FieldT> > get_evaluation_domain(const size_t m
{
print_indent(); printf("* Selected domain: extended_radix2\n");
}
result.reset(new extended_radix2_domain<FieldT>(min_size));
assert(0);
}
else
{
@ -56,9 +54,9 @@ std::shared_ptr<evaluation_domain<FieldT> > get_evaluation_domain(const size_t m
}
else
{
const size_t big = UINT64_C(1)<<(log2(min_size)-1);
const size_t big = 1ul<<(log2(min_size)-1);
const size_t small = min_size - big;
const size_t rounded_small = (UINT64_C(1)<<log2(small));
const size_t rounded_small = (1ul<<log2(small));
if (big == rounded_small)
{
if (log2(big + rounded_small) < FieldT::s+1)
@ -75,7 +73,7 @@ std::shared_ptr<evaluation_domain<FieldT> > get_evaluation_domain(const size_t m
{
print_indent(); printf("* Selected domain: extended_radix2\n");
}
result.reset(new extended_radix2_domain<FieldT>(big + rounded_small));
assert(0);
}
}
else
@ -84,7 +82,7 @@ std::shared_ptr<evaluation_domain<FieldT> > get_evaluation_domain(const size_t m
{
print_indent(); printf("* Selected domain: step_radix2\n");
}
result.reset(new step_radix2_domain<FieldT>(big + rounded_small));
assert(0);
}
}

2
src/snark/src/algebra/exponentiation/exponentiation.hpp

@ -22,7 +22,7 @@ template<typename FieldT, mp_size_t m>
FieldT power(const FieldT &base, const bigint<m> &exponent);
template<typename FieldT>
FieldT power(const FieldT &base, const uint64_t exponent);
FieldT power(const FieldT &base, const unsigned long exponent);
} // libsnark

4
src/snark/src/algebra/exponentiation/exponentiation.tcc

@ -25,7 +25,7 @@ FieldT power(const FieldT &base, const bigint<m> &exponent)
bool found_one = false;
for (int64_t i = exponent.max_bits() - 1; i >= 0; --i)
for (long i = exponent.max_bits() - 1; i >= 0; --i)
{
if (found_one)
{
@ -43,7 +43,7 @@ FieldT power(const FieldT &base, const bigint<m> &exponent)
}
template<typename FieldT>
FieldT power(const FieldT &base, const uint64_t exponent)
FieldT power(const FieldT &base, const unsigned long exponent)
{
return power<FieldT>(base, bigint<1>(exponent));
}

4
src/snark/src/algebra/fields/bigint.hpp

@ -33,7 +33,7 @@ public:
mp_limb_t data[n] = {0};
bigint() = default;
bigint(const uint64_t x); /// Initalize from a small integer
bigint(const unsigned long x); /// Initalize from a small integer
bigint(const char* s); /// Initialize from a string containing an integer in decimal notation
bigint(const mpz_t r); /// Initialize from MPZ element
@ -46,7 +46,7 @@ public:
size_t max_bits() const { return n * GMP_NUMB_BITS; }
size_t num_bits() const;
uint64_t as_ulong() const; /* return the last limb of the integer */
unsigned long as_ulong() const; /* return the last limb of the integer */
void to_mpz(mpz_t r) const;
bool test_bit(const std::size_t bitno) const;

15
src/snark/src/algebra/fields/bigint.tcc

@ -9,7 +9,6 @@
#ifndef BIGINT_TCC_
#define BIGINT_TCC_
#include <iostream>
#include <cassert>
#include <climits>
#include <cstring>
@ -18,9 +17,9 @@
namespace libsnark {
template<mp_size_t n>
bigint<n>::bigint(const uint64_t x) /// Initalize from a small integer
bigint<n>::bigint(const unsigned long x) /// Initalize from a small integer
{
static_assert(UINT64_MAX <= GMP_NUMB_MAX, "uint64_t does not fit in a GMP limb");
static_assert(ULONG_MAX <= GMP_NUMB_MAX, "unsigned long does not fit in a GMP limb");
this->data[0] = x;
}
@ -106,7 +105,7 @@ template<mp_size_t n>
size_t bigint<n>::num_bits() const
{
/*
for (int64_t i = max_bits(); i >= 0; --i)
for (long i = max_bits(); i >= 0; --i)
{
if (this->test_bit(i))
{
@ -116,7 +115,7 @@ size_t bigint<n>::num_bits() const
return 0;
*/
for (int64_t i = n-1; i >= 0; --i)
for (long i = n-1; i >= 0; --i)
{
mp_limb_t x = this->data[i];
if (x == 0)
@ -125,14 +124,14 @@ size_t bigint<n>::num_bits() const
}
else
{
return (((i+1) * GMP_NUMB_BITS) - __builtin_clzl(x)) / 2;
return ((i+1) * GMP_NUMB_BITS) - __builtin_clzl(x);
}
}
return 0;
}
template<mp_size_t n>
uint64_t bigint<n>::as_ulong() const
unsigned long bigint<n>::as_ulong() const
{
return this->data[0];
}
@ -202,7 +201,7 @@ inline bigint<m> bigint<n>::shorten(const bigint<m>& q, const char *msg) const
}
}
bigint<m> res;
mpn_copyi(res.data, data, n);
mpn_copyi(res.data, data, m);
res.limit(q, msg);
return res;
}

8
src/snark/src/algebra/fields/field_utils.hpp

@ -16,13 +16,13 @@ namespace libsnark {
// returns root of unity of order n (for n a power of 2), if one exists
template<typename FieldT>
FieldT get_root_of_unity(const unsigned long long n);
FieldT get_root_of_unity(const size_t n);
template<typename FieldT>
std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<unsigned long long> &v, const unsigned long long w);
std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<size_t> &v, const size_t w);
template<typename FieldT>
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v, const unsigned long long chunk_bits);
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v, const size_t chunk_bits);
template<typename FieldT>
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v);
@ -37,7 +37,7 @@ template<typename FieldT>
bit_vector convert_field_element_to_bit_vector(const FieldT &el);
template<typename FieldT>
bit_vector convert_field_element_to_bit_vector(const FieldT &el, const unsigned long long bitcount);
bit_vector convert_field_element_to_bit_vector(const FieldT &el, const size_t bitcount);
template<typename FieldT>
FieldT convert_bit_vector_to_field_element(const bit_vector &v);

32
src/snark/src/algebra/fields/field_utils.tcc

@ -21,14 +21,14 @@ FieldT coset_shift()
}
template<typename FieldT>
FieldT get_root_of_unity(const unsigned long long n)
FieldT get_root_of_unity(const size_t n)
{
const unsigned long long logn = log2(n);
const size_t logn = log2(n);
assert(n == (1u << logn));
assert(logn <= FieldT::s);
FieldT omega = FieldT::root_of_unity;
for (unsigned long long i = FieldT::s; i > logn; --i)
for (size_t i = FieldT::s; i > logn; --i)
{
omega *= omega;
}
@ -37,21 +37,21 @@ FieldT get_root_of_unity(const unsigned long long n)
}
template<typename FieldT>
std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<unsigned long long> &v, const unsigned long long w)
std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<size_t> &v, const size_t w)
{
const unsigned long long chunk_bits = FieldT::capacity();
const unsigned long long repacked_size = div_ceil(v.size() * w, chunk_bits);
const size_t chunk_bits = FieldT::capacity();
const size_t repacked_size = div_ceil(v.size() * w, chunk_bits);
std::vector<FieldT> result(repacked_size);
for (unsigned long long i = 0; i < repacked_size; ++i)
for (size_t i = 0; i < repacked_size; ++i)
{
bigint<FieldT::num_limbs> b;
for (unsigned long long j = 0; j < chunk_bits; ++j)
for (size_t j = 0; j < chunk_bits; ++j)
{
const unsigned long long word_index = (i * chunk_bits + j) / w;
const unsigned long long pos_in_word = (i * chunk_bits + j) % w;
const unsigned long long word_or_0 = (word_index < v.size() ? v[word_index] : 0);
const unsigned long long bit = (word_or_0 >> pos_in_word) & 1;
const size_t word_index = (i * chunk_bits + j) / w;
const size_t pos_in_word = (i * chunk_bits + j) % w;
const size_t word_or_0 = (word_index < v.size() ? v[word_index] : 0);
const size_t bit = (word_or_0 >> pos_in_word) & 1;
b.data[j / GMP_NUMB_BITS] |= bit << (j % GMP_NUMB_BITS);
}
@ -62,11 +62,11 @@ std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<
}
template<typename FieldT>
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v, const unsigned long long chunk_bits)
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v, const size_t chunk_bits)
{
assert(chunk_bits <= FieldT::capacity());
const unsigned long long repacked_size = div_ceil(v.size(), chunk_bits);
const size_t repacked_size = div_ceil(v.size(), chunk_bits);
std::vector<FieldT> result(repacked_size);
for (size_t i = 0; i < repacked_size; ++i)
@ -131,7 +131,7 @@ bit_vector convert_field_element_to_bit_vector(const FieldT &el)
}
template<typename FieldT>
bit_vector convert_field_element_to_bit_vector(const FieldT &el, const unsigned long long bitcount)
bit_vector convert_field_element_to_bit_vector(const FieldT &el, const size_t bitcount)
{
bit_vector result = convert_field_element_to_bit_vector(el);
result.resize(bitcount);
@ -171,7 +171,7 @@ void batch_invert(std::vector<FieldT> &vec)
FieldT acc_inverse = acc.inverse();
for (int64_t i = vec.size()-1; i >= 0; --i)
for (long i = vec.size()-1; i >= 0; --i)
{
const FieldT old_el = vec[i];
vec[i] = acc_inverse * prod[i];

32
src/snark/src/algebra/fields/fp.hpp

@ -44,15 +44,15 @@ public:
static const mp_size_t num_limbs = n;
static const constexpr bigint<n>& mod = modulus;
#ifdef PROFILE_OP_COUNTS
static int64_t add_cnt;
static int64_t sub_cnt;
static int64_t mul_cnt;
static int64_t sqr_cnt;
static int64_t inv_cnt;
static long long add_cnt;
static long long sub_cnt;
static long long mul_cnt;
static long long sqr_cnt;
static long long inv_cnt;
#endif
static unsigned long long num_bits;
static size_t num_bits;
static bigint<n> euler; // (modulus-1)/2
static unsigned long long s; // modulus = 2^s * t + 1
static size_t s; // modulus = 2^s * t + 1
static bigint<n> t; // with t odd
static bigint<n> t_minus_1_over_2; // (t-1)/2
static Fp_model<n, modulus> nqr; // a quadratic nonresidue
@ -67,9 +67,9 @@ public:
Fp_model() {};
Fp_model(const bigint<n> &b);
Fp_model(const int64_t x, const bool is_unsigned=false);
Fp_model(const long x, const bool is_unsigned=false);
void set_ulong(const uint64_t x);
void set_ulong(const unsigned long x);
void mul_reduce(const bigint<n> &other);
@ -82,7 +82,7 @@ public:
/* Return the last limb of the standard representation of the
field element. E.g. on 64-bit architectures Fp(123).as_ulong()
and Fp(2^64+123).as_ulong() would both return 123. */
uint64_t as_ulong() const;
unsigned long as_ulong() const;
bool operator==(const Fp_model& other) const;
bool operator!=(const Fp_model& other) const;
@ -93,7 +93,7 @@ public:
Fp_model& operator+=(const Fp_model& other);
Fp_model& operator-=(const Fp_model& other);
Fp_model& operator*=(const Fp_model& other);
Fp_model& operator^=(const uint64_t pow);
Fp_model& operator^=(const unsigned long pow);
template<mp_size_t m>
Fp_model& operator^=(const bigint<m> &pow);
@ -107,12 +107,12 @@ public:
Fp_model inverse() const;
Fp_model sqrt() const; // HAS TO BE A SQUARE (else does not terminate)
Fp_model operator^(const uint64_t pow) const;
Fp_model operator^(const unsigned long pow) const;
template<mp_size_t m>
Fp_model operator^(const bigint<m> &pow) const;
static unsigned long long size_in_bits() { return num_bits; }
static unsigned long long capacity() { return num_bits - 1; }
static size_t size_in_bits() { return num_bits; }
static size_t capacity() { return num_bits - 1; }
static bigint<n> field_char() { return modulus; }
static Fp_model<n, modulus> zero();
@ -141,13 +141,13 @@ long long Fp_model<n, modulus>::inv_cnt = 0;
#endif
template<mp_size_t n, const bigint<n>& modulus>
unsigned long long Fp_model<n, modulus>::num_bits;
size_t Fp_model<n, modulus>::num_bits;
template<mp_size_t n, const bigint<n>& modulus>
bigint<n> Fp_model<n, modulus>::euler;
template<mp_size_t n, const bigint<n>& modulus>
unsigned long long Fp_model<n, modulus>::s;
size_t Fp_model<n, modulus>::s;
template<mp_size_t n, const bigint<n>& modulus>
bigint<n> Fp_model<n, modulus>::t;

22
src/snark/src/algebra/fields/fp.tcc

@ -194,7 +194,7 @@ Fp_model<n,modulus>::Fp_model(const bigint<n> &b)
}
template<mp_size_t n, const bigint<n>& modulus>
Fp_model<n,modulus>::Fp_model(const int64_t x, const bool is_unsigned)
Fp_model<n,modulus>::Fp_model(const long x, const bool is_unsigned)
{
if (is_unsigned || x >= 0)
{
@ -210,7 +210,7 @@ Fp_model<n,modulus>::Fp_model(const int64_t x, const bool is_unsigned)
}
template<mp_size_t n, const bigint<n>& modulus>
void Fp_model<n,modulus>::set_ulong(const uint64_t x)
void Fp_model<n,modulus>::set_ulong(const unsigned long x)
{
this->mont_repr.clear();
this->mont_repr.data[0] = x;
@ -237,7 +237,7 @@ bigint<n> Fp_model<n,modulus>::as_bigint() const
}
template<mp_size_t n, const bigint<n>& modulus>
uint64_t Fp_model<n,modulus>::as_ulong() const
unsigned long Fp_model<n,modulus>::as_ulong() const
{
return this->as_bigint().as_ulong();
}
@ -502,7 +502,7 @@ Fp_model<n,modulus>& Fp_model<n,modulus>::operator*=(const Fp_model<n,modulus>&
}
template<mp_size_t n, const bigint<n>& modulus>
Fp_model<n,modulus>& Fp_model<n,modulus>::operator^=(const uint64_t pow)
Fp_model<n,modulus>& Fp_model<n,modulus>::operator^=(const unsigned long pow)
{
(*this) = power<Fp_model<n, modulus> >(*this, pow);
return (*this);
@ -538,7 +538,7 @@ Fp_model<n,modulus> Fp_model<n,modulus>::operator*(const Fp_model<n,modulus>& ot
}
template<mp_size_t n, const bigint<n>& modulus>
Fp_model<n,modulus> Fp_model<n,modulus>::operator^(const uint64_t pow) const
Fp_model<n,modulus> Fp_model<n,modulus>::operator^(const unsigned long pow) const
{
Fp_model<n, modulus> r(*this);
return (r ^= pow);
@ -684,13 +684,13 @@ Fp_model<n, modulus> Fp_model<n,modulus>::random_element() /// returns random el
r.mont_repr.randomize();
/* clear all bits higher than MSB of modulus */
unsigned long long bitno = GMP_NUMB_BITS * n - 1;
size_t bitno = GMP_NUMB_BITS * n - 1;
while (modulus.test_bit(bitno) == false)
{
const unsigned long long part = bitno/GMP_NUMB_BITS;
const unsigned long long bit = bitno - (GMP_NUMB_BITS*part);
const std::size_t part = bitno/GMP_NUMB_BITS;
const std::size_t bit = bitno - (GMP_NUMB_BITS*part);
r.mont_repr.data[part] &= ~(1ull<<bit);
r.mont_repr.data[part] &= ~(1ul<<bit);
bitno--;
}
@ -710,7 +710,7 @@ Fp_model<n,modulus> Fp_model<n,modulus>::sqrt() const
Fp_model<n,modulus> one = Fp_model<n,modulus>::one();
unsigned long long v = Fp_model<n,modulus>::s;
size_t v = Fp_model<n,modulus>::s;
Fp_model<n,modulus> z = Fp_model<n,modulus>::nqr_to_t;
Fp_model<n,modulus> w = (*this)^Fp_model<n,modulus>::t_minus_1_over_2;
Fp_model<n,modulus> x = (*this) * w;
@ -734,7 +734,7 @@ Fp_model<n,modulus> Fp_model<n,modulus>::sqrt() const
while (b != one)
{
unsigned long long m = 0;
size_t m = 0;
Fp_model<n,modulus> b2m = b;
while (b2m != one)
{

4
src/snark/src/algebra/fields/fp12_2over3over2.hpp

@ -66,7 +66,7 @@ public:
Fp12_2over3over2_model squared_karatsuba() const;
Fp12_2over3over2_model squared_complex() const;
Fp12_2over3over2_model inverse() const;
Fp12_2over3over2_model Frobenius_map(uint64_t power) const;
Fp12_2over3over2_model Frobenius_map(unsigned long power) const;
Fp12_2over3over2_model unitary_inverse() const;
Fp12_2over3over2_model cyclotomic_squared() const;
@ -78,7 +78,7 @@ public:
Fp12_2over3over2_model cyclotomic_exp(const bigint<m> &exponent) const;
static bigint<n> base_field_char() { return modulus; }
static unsigned long long extension_degree() { return 12; }
static size_t extension_degree() { return 12; }
friend std::ostream& operator<< <n, modulus>(std::ostream &out, const Fp12_2over3over2_model<n, modulus> &el);
friend std::istream& operator>> <n, modulus>(std::istream &in, Fp12_2over3over2_model<n, modulus> &el);

10
src/snark/src/algebra/fields/fp12_2over3over2.tcc

@ -156,7 +156,7 @@ Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::inverse() c
}
template<mp_size_t n, const bigint<n>& modulus>
Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::Frobenius_map(uint64_t power) const
Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::Frobenius_map(unsigned long power) const
{
return Fp12_2over3over2_model<n,modulus>(c0.Frobenius_map(power),
Frobenius_coeffs_c1[power % 12] * c1.Frobenius_map(power));
@ -339,16 +339,16 @@ Fp12_2over3over2_model<n, modulus> Fp12_2over3over2_model<n,modulus>::cyclotomic
Fp12_2over3over2_model<n,modulus> res = Fp12_2over3over2_model<n,modulus>::one();
bool found_one = false;
for (int64_t i = m-1; i >= 0; --i)
for (long i = m-1; i >= 0; --i)
{
for (int64_t j = GMP_NUMB_BITS - 1; j >= 0; --j)
for (long j = GMP_NUMB_BITS - 1; j >= 0; --j)
{
if (found_one)
{
res = res.cyclotomic_squared();
}
if (exponent.data[i] & (UINT64_C(1)<<j))
if (exponent.data[i] & (1ul<<j))
{
found_one = true;
res = res * (*this);
@ -390,7 +390,7 @@ std::istream& operator>>(std::istream& in, std::vector<Fp12_2over3over2_model<n,
{
v.clear();
unsigned long long s;
size_t s;
in >> s;
char b;

8
src/snark/src/algebra/fields/fp2.hpp

@ -37,7 +37,7 @@ public:
typedef Fp_model<n, modulus> my_Fp;
static bigint<2*n> euler; // (modulus^2-1)/2
static unsigned long long s; // modulus^2 = 2^s * t + 1
static size_t s; // modulus^2 = 2^s * t + 1
static bigint<2*n> t; // with t odd
static bigint<2*n> t_minus_1_over_2; // (t-1)/2
static my_Fp non_residue; // X^4-non_residue irreducible over Fp; used for constructing Fp2 = Fp[X] / (X^2 - non_residue)
@ -66,7 +66,7 @@ public:
Fp2_model operator-() const;
Fp2_model squared() const; // default is squared_complex
Fp2_model inverse() const;
Fp2_model Frobenius_map(uint64_t power) const;
Fp2_model Frobenius_map(unsigned long power) const;
Fp2_model sqrt() const; // HAS TO BE A SQUARE (else does not terminate)
Fp2_model squared_karatsuba() const;
Fp2_model squared_complex() const;
@ -74,7 +74,7 @@ public:
template<mp_size_t m>
Fp2_model operator^(const bigint<m> &other) const;
static unsigned long long size_in_bits() { return 2*my_Fp::size_in_bits(); }
static size_t size_in_bits() { return 2*my_Fp::size_in_bits(); }
static bigint<n> base_field_char() { return modulus; }
friend std::ostream& operator<< <n, modulus>(std::ostream &out, const Fp2_model<n, modulus> &el);
@ -94,7 +94,7 @@ template<mp_size_t n, const bigint<n>& modulus>
bigint<2*n> Fp2_model<n, modulus>::euler;
template<mp_size_t n, const bigint<n>& modulus>
unsigned long long Fp2_model<n, modulus>::s;
size_t Fp2_model<n, modulus>::s;
template<mp_size_t n, const bigint<n>& modulus>
bigint<2*n> Fp2_model<n, modulus>::t;

8
src/snark/src/algebra/fields/fp2.tcc

@ -136,7 +136,7 @@ Fp2_model<n,modulus> Fp2_model<n,modulus>::inverse() const
}
template<mp_size_t n, const bigint<n>& modulus>
Fp2_model<n,modulus> Fp2_model<n,modulus>::Frobenius_map(uint64_t power) const
Fp2_model<n,modulus> Fp2_model<n,modulus>::Frobenius_map(unsigned long power) const
{
return Fp2_model<n,modulus>(c0,
Frobenius_coeffs_c1[power % 2] * c1);
@ -151,7 +151,7 @@ Fp2_model<n,modulus> Fp2_model<n,modulus>::sqrt() const
Fp2_model<n,modulus> one = Fp2_model<n,modulus>::one();
unsigned long long v = Fp2_model<n,modulus>::s;
size_t v = Fp2_model<n,modulus>::s;
Fp2_model<n,modulus> z = Fp2_model<n,modulus>::nqr_to_t;
Fp2_model<n,modulus> w = (*this)^Fp2_model<n,modulus>::t_minus_1_over_2;
Fp2_model<n,modulus> x = (*this) * w;
@ -175,7 +175,7 @@ Fp2_model<n,modulus> Fp2_model<n,modulus>::sqrt() const
while (b != one)
{
unsigned long long m = 0;
size_t m = 0;
Fp2_model<n,modulus> b2m = b;
while (b2m != one)
{
@ -239,7 +239,7 @@ std::istream& operator>>(std::istream& in, std::vector<Fp2_model<n, modulus> > &
{
v.clear();
unsigned long long s;
size_t s;
in >> s;
char b;

122
src/snark/src/algebra/fields/fp3.hpp

@ -1,122 +0,0 @@
/** @file
*****************************************************************************
Declaration of arithmetic in the finite field F[p^3].
*****************************************************************************
* @author This file is part of libsnark, developed by SCIPR Lab
* and contributors (see AUTHORS).
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#ifndef FP3_HPP_
#define FP3_HPP_
#include "algebra/fields/fp.hpp"
#include <vector>
namespace libsnark {
template<mp_size_t n, const bigint<n>& modulus>
class Fp3_model;
template<mp_size_t n, const bigint<n>& modulus>
std::ostream& operator<<(std::ostream &, const Fp3_model<n, modulus> &);
template<mp_size_t n, const bigint<n>& modulus>
std::istream& operator>>(std::istream &, Fp3_model<n, modulus> &);
/**
* Arithmetic in the field F[p^3].
*
* Let p := modulus. This interface provides arithmetic for the extension field
* Fp3 = Fp[U]/(U^3-non_residue), where non_residue is in Fp.
*
* ASSUMPTION: p = 1 (mod 6)
*/
template<mp_size_t n, const bigint<n>& modulus>
class Fp3_model {
public:
typedef Fp_model<n, modulus> my_Fp;
static bigint<3*n> euler; // (modulus^3-1)/2
static unsigned long long s; // modulus^3 = 2^s * t + 1
static bigint<3*n> t; // with t odd
static bigint<3*n> t_minus_1_over_2; // (t-1)/2
static my_Fp non_residue; // X^6-non_residue irreducible over Fp; used for constructing Fp3 = Fp[X] / (X^3 - non_residue)
static Fp3_model<n, modulus> nqr; // a quadratic nonresidue in Fp3
static Fp3_model<n, modulus> nqr_to_t; // nqr^t
static my_Fp Frobenius_coeffs_c1[3]; // non_residue^((modulus^i-1)/3) for i=0,1,2
static my_Fp Frobenius_coeffs_c2[3]; // non_residue^((2*modulus^i-2)/3) for i=0,1,2
my_Fp c0, c1, c2;
Fp3_model() {};
Fp3_model(const my_Fp& c0, const my_Fp& c1, const my_Fp& c2) : c0(c0), c1(c1), c2(c2) {};
void clear() { c0.clear(); c1.clear(); c2.clear(); }
void print() const { printf("c0/c1/c2:\n"); c0.print(); c1.print(); c2.print(); }
static Fp3_model<n, modulus> zero();
static Fp3_model<n, modulus> one();
static Fp3_model<n, modulus> random_element();
bool is_zero() const { return c0.is_zero() && c1.is_zero() && c2.is_zero(); }
bool operator==(const Fp3_model &other) const;
bool operator!=(const Fp3_model &other) const;
Fp3_model operator+(const Fp3_model &other) const;
Fp3_model operator-(const Fp3_model &other) const;
Fp3_model operator*(const Fp3_model &other) const;
Fp3_model operator-() const;
Fp3_model squared() const;
Fp3_model inverse() const;
Fp3_model Frobenius_map(unsigned long power) const;
Fp3_model sqrt() const; // HAS TO BE A SQUARE (else does not terminate)
template<mp_size_t m>
Fp3_model operator^(const bigint<m> &other) const;
static unsigned long long size_in_bits() { return 3*my_Fp::size_in_bits(); }
static bigint<n> base_field_char() { return modulus; }
friend std::ostream& operator<< <n, modulus>(std::ostream &out, const Fp3_model<n, modulus> &el);
friend std::istream& operator>> <n, modulus>(std::istream &in, Fp3_model<n, modulus> &el);
};
template<mp_size_t n, const bigint<n>& modulus>
std::ostream& operator<<(std::ostream& out, const std::vector<Fp3_model<n, modulus> > &v);
template<mp_size_t n, const bigint<n>& modulus>
std::istream& operator>>(std::istream& in, std::vector<Fp3_model<n, modulus> > &v);
template<mp_size_t n, const bigint<n>& modulus>
Fp3_model<n, modulus> operator*(const Fp_model<n, modulus> &lhs, const Fp3_model<n, modulus> &rhs);
template<mp_size_t n, const bigint<n>& modulus>
bigint<3*n> Fp3_model<n, modulus>::euler;
template<mp_size_t n, const bigint<n>& modulus>
unsigned long long Fp3_model<n, modulus>::s;
template<mp_size_t n, const bigint<n>& modulus>
bigint<3*n> Fp3_model<n, modulus>::t;
template<mp_size_t n, const bigint<n>& modulus>
bigint<3*n> Fp3_model<n, modulus>::t_minus_1_over_2;
template<mp_size_t n, const bigint<n>& modulus>
Fp_model<n, modulus> Fp3_model<n, modulus>::non_residue;
template<mp_size_t n, const bigint<n>& modulus>
Fp3_model<n, modulus> Fp3_model<n, modulus>::nqr;
template<mp_size_t n, const bigint<n>& modulus>
Fp3_model<n, modulus> Fp3_model<n, modulus>::nqr_to_t;
template<mp_size_t n, const bigint<n>& modulus>
Fp_model<n, modulus> Fp3_model<n, modulus>::Frobenius_coeffs_c1[3];
template<mp_size_t n, const bigint<n>& modulus>
Fp_model<n, modulus> Fp3_model<n, modulus>::Frobenius_coeffs_c2[3];
} // libsnark
#include "algebra/fields/fp3.tcc"
#endif // FP3_HPP_

259
src/snark/src/algebra/fields/fp3.tcc

@ -1,259 +0,0 @@
/** @file
*****************************************************************************
Implementation of arithmetic in the finite field F[p^3].
*****************************************************************************
* @author This file is part of libsnark, developed by SCIPR Lab
* and contributors (see AUTHORS).
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#ifndef FP3_TCC_
#define FP3_TCC_
#include "algebra/fields/field_utils.hpp"
namespace libsnark {
template<mp_size_t n, const bigint<n>& modulus>
Fp3_model<n,modulus> Fp3_model<n,modulus>::zero()
{
return Fp3_model<n, modulus>(my_Fp::zero(), my_Fp::zero(), my_Fp::zero());
}
template<mp_size_t n, const bigint<n>& modulus>
Fp3_model<n,modulus> Fp3_model<n,modulus>::one()
{
return Fp3_model<n, modulus>(my_Fp::one(), my_Fp::zero(), my_Fp::zero());
}
template<mp_size_t n, const bigint<n>& modulus>
Fp3_model<n,modulus> Fp3_model<n,modulus>::random_element()
{
Fp3_model<n, modulus> r;
r.c0 = my_Fp::random_element();
r.c1 = my_Fp::random_element();
r.c2 = my_Fp::random_element();
return r;
}
template<mp_size_t n, const bigint<n>& modulus>
bool Fp3_model<n,modulus>::operator==(const Fp3_model<n,modulus> &other) const
{
return (this->c0 == other.c0 && this->c1 == other.c1 && this->c2 == other.c2);
}
template<mp_size_t n, const bigint<n>& modulus>
bool Fp3_model<n,modulus>::operator!=(const Fp3_model<n,modulus> &other) const
{
return !(operator==(other));
}
template<mp_size_t n, const bigint<n>& modulus>
Fp3_model<n,modulus> Fp3_model<n,modulus>::operator+(const Fp3_model<n,modulus> &other) const
{
return Fp3_model<n,modulus>(this->c0 + other.c0,
this->c1 + other.c1,
this->c2 + other.c2);
}
template<mp_size_t n, const bigint<n>& modulus>
Fp3_model<n,modulus> Fp3_model<n,modulus>::operator-(const Fp3_model<n,modulus> &other) const
{
return Fp3_model<n,modulus>(this->c0 - other.c0,
this->c1 - other.c1,
this->c2 - other.c2);
}
template<mp_size_t n, const bigint<n>& modulus>
Fp3_model<n, modulus> operator*(const Fp_model<n, modulus> &lhs, const Fp3_model<n, modulus> &rhs)
{
return Fp3_model<n,modulus>(lhs*rhs.c0,
lhs*rhs.c1,
lhs*rhs.c2);
}
template<mp_size_t n, const bigint<n>& modulus>
Fp3_model<n,modulus> Fp3_model<n,modulus>::operator*(const Fp3_model<n,modulus> &other) const
{
/* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly Fields.pdf; Section 4 (Karatsuba) */
const my_Fp
&A = other.c0, &B = other.c1, &C = other.c2,
&a = this->c0, &b = this->c1, &c = this->c2;
const my_Fp aA = a*A;
const my_Fp bB = b*B;
const my_Fp cC = c*C;
return Fp3_model<n,modulus>(aA + non_residue*((b+c)*(B+C)-bB-cC),
(a+b)*(A+B)-aA-bB+non_residue*cC,
(a+c)*(A+C)-aA+bB-cC);
}
template<mp_size_t n, const bigint<n>& modulus>
Fp3_model<n,modulus> Fp3_model<n,modulus>::operator-() const
{
return Fp3_model<n,modulus>(-this->c0,
-this->c1,
-this->c2);
}
template<mp_size_t n, const bigint<n>& modulus>
Fp3_model<n,modulus> Fp3_model<n,modulus>::squared() const
{
/* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly Fields.pdf; Section 4 (CH-SQR2) */
const my_Fp
&a = this->c0, &b = this->c1, &c = this->c2;
const my_Fp s0 = a.squared();
const my_Fp ab = a*b;
const my_Fp s1 = ab + ab;
const my_Fp s2 = (a - b + c).squared();
const my_Fp bc = b*c;
const my_Fp s3 = bc + bc;
const my_Fp s4 = c.squared();
return Fp3_model<n,modulus>(s0 + non_residue * s3,
s1 + non_residue * s4,
s1 + s2 + s3 - s0 - s4);
}
template<mp_size_t n, const bigint<n>& modulus>
Fp3_model<n,modulus> Fp3_model<n,modulus>::inverse() const
{
const my_Fp
&a = this->c0, &b = this->c1, &c = this->c2;
/* From "High-Speed Software Implementation of the Optimal Ate Pairing over Barreto-Naehrig Curves"; Algorithm 17 */
const my_Fp t0 = a.squared();
const my_Fp t1 = b.squared();
const my_Fp t2 = c.squared();
const my_Fp t3 = a*b;
const my_Fp t4 = a*c;
const my_Fp t5 = b*c;
const my_Fp c0 = t0 - non_residue * t5;
const my_Fp c1 = non_residue * t2 - t3;
const my_Fp c2 = t1 - t4; // typo in paper referenced above. should be "-" as per Scott, but is "*"
const my_Fp t6 = (a * c0 + non_residue * (c * c1 + b * c2)).inverse();
return Fp3_model<n,modulus>(t6 * c0, t6 * c1, t6 * c2);
}
template<mp_size_t n, const bigint<n>& modulus>
Fp3_model<n,modulus> Fp3_model<n,modulus>::Frobenius_map(unsigned long power) const
{
return Fp3_model<n,modulus>(c0,
Frobenius_coeffs_c1[power % 3] * c1,
Frobenius_coeffs_c2[power % 3] * c2);
}
template<mp_size_t n, const bigint<n>& modulus>
Fp3_model<n,modulus> Fp3_model<n,modulus>::sqrt() const
{
Fp3_model<n,modulus> one = Fp3_model<n,modulus>::one();
unsigned long long v = Fp3_model<n,modulus>::s;
Fp3_model<n,modulus> z = Fp3_model<n,modulus>::nqr_to_t;
Fp3_model<n,modulus> w = (*this)^Fp3_model<n,modulus>::t_minus_1_over_2;
Fp3_model<n,modulus> x = (*this) * w;
Fp3_model<n,modulus> b = x * w; // b = (*this)^t
#if DEBUG
// check if square with euler's criterion
Fp3_model<n,modulus> check = b;
for (size_t i = 0; i < v-1; ++i)
{
check = check.squared();
}
if (check != one)
{
assert(0);
}
#endif
// compute square root with Tonelli--Shanks
// (does not terminate if not a square!)
while (b != one)
{
unsigned long long m = 0;
Fp3_model<n,modulus> b2m = b;
while (b2m != one)
{
/* invariant: b2m = b^(2^m) after entering this loop */
b2m = b2m.squared();
m += 1;
}
int j = v-m-1;
w = z;
while (j > 0)
{
w = w.squared();
--j;
} // w = z^2^(v-m-1)
z = w.squared();
b = b * z;
x = x * w;
v = m;
}
return x;
}
template<mp_size_t n, const bigint<n>& modulus>
template<mp_size_t m>
Fp3_model<n,modulus> Fp3_model<n,modulus>::operator^(const bigint<m> &pow) const
{
return power<Fp3_model<n, modulus> >(*this, pow);
}
template<mp_size_t n, const bigint<n>& modulus>
std::ostream& operator<<(std::ostream &out, const Fp3_model<n, modulus> &el)
{
out << el.c0 << OUTPUT_SEPARATOR << el.c1 << OUTPUT_SEPARATOR << el.c2;
return out;
}
template<mp_size_t n, const bigint<n>& modulus>
std::istream& operator>>(std::istream &in, Fp3_model<n, modulus> &el)
{
in >> el.c0 >> el.c1 >> el.c2;
return in;
}
template<mp_size_t n, const bigint<n>& modulus>
std::ostream& operator<<(std::ostream& out, const std::vector<Fp3_model<n, modulus> > &v)
{
out << v.size() << "\n";
for (const Fp3_model<n, modulus>& t : v)
{
out << t << OUTPUT_NEWLINE;
}
return out;
}
template<mp_size_t n, const bigint<n>& modulus>
std::istream& operator>>(std::istream& in, std::vector<Fp3_model<n, modulus> > &v)
{
v.clear();
unsigned long long s;
in >> s;
char b;
in.read(&b, 1);
v.reserve(s);
for (size_t i = 0; i < s; ++i)
{
Fp3_model<n, modulus> el;
in >> el;
v.emplace_back(el);
}
return in;
}
} // libsnark
#endif // FP3_TCC_

4
src/snark/src/algebra/fields/fp6_3over2.hpp

@ -63,7 +63,7 @@ public:
Fp6_3over2_model operator-() const;
Fp6_3over2_model squared() const;
Fp6_3over2_model inverse() const;
Fp6_3over2_model Frobenius_map(uint64_t power) const;
Fp6_3over2_model Frobenius_map(unsigned long power) const;
static my_Fp2 mul_by_non_residue(const my_Fp2 &elt);
@ -71,7 +71,7 @@ public:
Fp6_3over2_model operator^(const bigint<m> &other) const;
static bigint<n> base_field_char() { return modulus; }
static unsigned long long extension_degree() { return 6; }
static size_t extension_degree() { return 6; }
friend std::ostream& operator<< <n, modulus>(std::ostream &out, const Fp6_3over2_model<n, modulus> &el);
friend std::istream& operator>> <n, modulus>(std::istream &in, Fp6_3over2_model<n, modulus> &el);

4
src/snark/src/algebra/fields/fp6_3over2.tcc

@ -149,7 +149,7 @@ Fp6_3over2_model<n,modulus> Fp6_3over2_model<n,modulus>::inverse() const
}
template<mp_size_t n, const bigint<n>& modulus>
Fp6_3over2_model<n,modulus> Fp6_3over2_model<n,modulus>::Frobenius_map(uint64_t power) const
Fp6_3over2_model<n,modulus> Fp6_3over2_model<n,modulus>::Frobenius_map(unsigned long power) const
{
return Fp6_3over2_model<n,modulus>(c0.Frobenius_map(power),
Frobenius_coeffs_c1[power % 6] * c1.Frobenius_map(power),
@ -194,7 +194,7 @@ std::istream& operator>>(std::istream& in, std::vector<Fp6_3over2_model<n, modul
{
v.clear();
uint64_t s;
size_t s;
in >> s;
char b;

90
src/snark/src/algebra/fields/tests/test_bigint.cpp

@ -7,11 +7,13 @@
#include "algebra/fields/bigint.hpp"
#include <gtest/gtest.h>
using namespace libsnark;
void test_bigint()
TEST(algebra, bigint)
{
static_assert(UINT64_MAX == 0xFFFFFFFFFFFFFFFFul, "uint64_t not 64-bit");
static_assert(ULONG_MAX == 0xFFFFFFFFFFFFFFFFul, "unsigned long not 64-bit");
static_assert(GMP_NUMB_BITS == 64, "GMP limb not 64-bit");
const char *b1_decimal = "76749407";
@ -20,88 +22,76 @@ void test_bigint()
const char *b2_binary = "0000000000000000000000000000010101111101101000000110100001011010"
"1101101010001001000001101000101000100110011001110001111110100010";
bigint<1> b0 = bigint<1>(UINT64_C(0));
bigint<1> b0 = bigint<1>(0ul);
bigint<1> b1 = bigint<1>(b1_decimal);
bigint<2> b2 = bigint<2>(b2_decimal);
assert(b0.as_ulong() == UINT64_C(0));
assert(b0.is_zero());
assert(b1.as_ulong() == UINT64_C(76749407));
assert(!(b1.is_zero()));
assert(b2.as_ulong() == UINT64_C(15747124762497195938));
assert(!(b2.is_zero()));
assert(b0 != b1);
assert(!(b0 == b1));
assert(b2.max_bits() == 128);
assert(b2.num_bits() == 99);
EXPECT_EQ(b0.as_ulong(), 0ul);
EXPECT_TRUE(b0.is_zero());
EXPECT_EQ(b1.as_ulong(), 76749407ul);
EXPECT_FALSE(b1.is_zero());
EXPECT_EQ(b2.as_ulong(), 15747124762497195938ul);
EXPECT_FALSE(b2.is_zero());
EXPECT_NE(b0, b1);
EXPECT_FALSE(b0 == b1);
EXPECT_EQ(b2.max_bits(), 128);
EXPECT_EQ(b2.num_bits(), 99);
for (size_t i = 0; i < 128; i++) {
assert(b2.test_bit(i) == (b2_binary[127-i] == '1'));
EXPECT_EQ(b2.test_bit(i), (b2_binary[127-i] == '1'));
}
bigint<3> b3 = b2 * b1;
assert(b3 == bigint<3>(b3_decimal));
assert(!(b3.is_zero()));
EXPECT_EQ(b3, bigint<3>(b3_decimal));
EXPECT_FALSE(b3.is_zero());
bigint<3> b3a { b3 };
assert(b3a == bigint<3>(b3_decimal));
assert(b3a == b3);
assert(!(b3a.is_zero()));
EXPECT_EQ(b3a, bigint<3>(b3_decimal));
EXPECT_EQ(b3a, b3);
EXPECT_FALSE(b3a.is_zero());
mpz_t m3;
mpz_init(m3);
b3.to_mpz(m3);
bigint<3> b3b { m3 };
assert(b3b == b3);
EXPECT_EQ(b3b, b3);
bigint<2> quotient;
bigint<2> remainder;
bigint<3>::div_qr(quotient, remainder, b3, b2);
assert(quotient.num_bits() < GMP_NUMB_BITS);
assert(quotient.as_ulong() == b1.as_ulong());
EXPECT_LT(quotient.num_bits(), GMP_NUMB_BITS);
EXPECT_EQ(quotient.as_ulong(), b1.as_ulong());
bigint<1> b1inc = bigint<1>("76749408");
bigint<1> b1a = quotient.shorten(b1inc, "test");
assert(b1a == b1);
assert(remainder.is_zero());
EXPECT_EQ(b1a, b1);
EXPECT_TRUE(remainder.is_zero());
remainder.limit(b2, "test");
try {
(void)(quotient.shorten(b1, "test"));
assert(false);
} catch (std::domain_error) {}
try {
remainder.limit(remainder, "test");
assert(false);
} catch (std::domain_error) {}
EXPECT_THROW((void)(quotient.shorten(b1, "test")), std::domain_error);
EXPECT_THROW(remainder.limit(remainder, "test"), std::domain_error);
bigint<1> br = bigint<1>("42");
b3 += br;
assert(b3 != b3a);
assert(b3 > b3a);
assert(!(b3a > b3));
EXPECT_NE(b3, b3a);
EXPECT_GT(b3, b3a);
EXPECT_FALSE(b3a > b3);
bigint<3>::div_qr(quotient, remainder, b3, b2);
assert(quotient.num_bits() < GMP_NUMB_BITS);
assert(quotient.as_ulong() == b1.as_ulong());
assert(remainder.num_bits() < GMP_NUMB_BITS);
assert(remainder.as_ulong() == 42);
EXPECT_LT(quotient.num_bits(), GMP_NUMB_BITS);
EXPECT_EQ(quotient.as_ulong(), b1.as_ulong());
EXPECT_LT(remainder.num_bits(), GMP_NUMB_BITS);
EXPECT_EQ(remainder.as_ulong(), 42);
b3a.clear();
assert(b3a.is_zero());
assert(b3a.num_bits() == 0);
assert(!(b3.is_zero()));
EXPECT_TRUE(b3a.is_zero());
EXPECT_EQ(b3a.num_bits(), 0);
EXPECT_FALSE(b3.is_zero());
bigint<4> bx = bigint<4>().randomize();
bigint<4> by = bigint<4>().randomize();
assert(!(bx == by));
EXPECT_FALSE(bx == by);
// TODO: test serialization
}
int main(void)
{
test_bigint();
return 0;
}

108
src/snark/src/algebra/fields/tests/test_fields.cpp

@ -5,9 +5,6 @@
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#include "common/profiling.hpp"
#include "algebra/curves/edwards/edwards_pp.hpp"
#include "algebra/curves/mnt/mnt4/mnt4_pp.hpp"
#include "algebra/curves/mnt/mnt6/mnt6_pp.hpp"
#ifdef CURVE_BN128
#include "algebra/curves/bn128/bn128_pp.hpp"
#endif
@ -15,6 +12,8 @@
#include "algebra/fields/fp6_3over2.hpp"
#include "algebra/fields/fp12_2over3over2.hpp"
#include <gtest/gtest.h>
using namespace libsnark;
template<typename FieldT>
@ -29,25 +28,25 @@ void test_field()
FieldT a = FieldT::random_element();
FieldT a_ser;
a_ser = reserialize<FieldT>(a);
assert(a_ser == a);
EXPECT_EQ(a_ser, a);
FieldT b = FieldT::random_element();
FieldT c = FieldT::random_element();
FieldT d = FieldT::random_element();
assert(a != zero);
assert(a != one);
EXPECT_NE(a, zero);
EXPECT_NE(a, one);
assert(a * a == a.squared());
assert((a + b).squared() == a.squared() + a*b + b*a + b.squared());
assert((a + b)*(c + d) == a*c + a*d + b*c + b*d);
assert(a - b == a + (-b));
assert(a - b == (-b) + a);
EXPECT_EQ(a * a, a.squared());
EXPECT_EQ((a + b).squared(), a.squared() + a*b + b*a + b.squared());
EXPECT_EQ((a + b)*(c + d), a*c + a*d + b*c + b*d);
EXPECT_EQ(a - b, a + (-b));
EXPECT_EQ(a - b, (-b) + a);
assert((a ^ rand1) * (a ^ rand2) == (a^randsum));
EXPECT_EQ((a ^ rand1) * (a ^ rand2), (a^randsum));
assert(a * a.inverse() == one);
assert((a + b) * c.inverse() == a * c.inverse() + (b.inverse() * c).inverse());
EXPECT_EQ(a * a.inverse(), one);
EXPECT_EQ((a + b) * c.inverse(), a * c.inverse() + (b.inverse() * c).inverse());
}
@ -58,7 +57,7 @@ void test_sqrt()
{
FieldT a = FieldT::random_element();
FieldT asq = a.squared();
assert(asq.sqrt() == a || asq.sqrt() == -a);
EXPECT_TRUE(asq.sqrt() == a || asq.sqrt() == -a);
}
}
@ -66,21 +65,21 @@ template<typename FieldT>
void test_two_squarings()
{
FieldT a = FieldT::random_element();
assert(a.squared() == a * a);
assert(a.squared() == a.squared_complex());
assert(a.squared() == a.squared_karatsuba());
EXPECT_EQ(a.squared(), a * a);
EXPECT_EQ(a.squared(), a.squared_complex());
EXPECT_EQ(a.squared(), a.squared_karatsuba());
}
template<typename FieldT>
void test_Frobenius()
{
FieldT a = FieldT::random_element();
assert(a.Frobenius_map(0) == a);
EXPECT_EQ(a.Frobenius_map(0), a);
FieldT a_q = a ^ FieldT::base_field_char();
for (size_t power = 1; power < 10; ++power)
{
const FieldT a_qi = a.Frobenius_map(power);
assert(a_qi == a_q);
EXPECT_EQ(a_qi, a_q);
a_q = a_q ^ FieldT::base_field_char();
}
@ -89,49 +88,10 @@ void test_Frobenius()
template<typename FieldT>
void test_unitary_inverse()
{
assert(FieldT::extension_degree() % 2 == 0);
EXPECT_EQ(FieldT::extension_degree() % 2, 0);
FieldT a = FieldT::random_element();
FieldT aqcubed_minus1 = a.Frobenius_map(FieldT::extension_degree()/2) * a.inverse();
assert(aqcubed_minus1.inverse() == aqcubed_minus1.unitary_inverse());
}
template<typename FieldT>
void test_cyclotomic_squaring();
template<>
void test_cyclotomic_squaring<Fqk<edwards_pp> >()
{
typedef Fqk<edwards_pp> FieldT;
assert(FieldT::extension_degree() % 2 == 0);
FieldT a = FieldT::random_element();
FieldT a_unitary = a.Frobenius_map(FieldT::extension_degree()/2) * a.inverse();
// beta = a^((q^(k/2)-1)*(q+1))
FieldT beta = a_unitary.Frobenius_map(1) * a_unitary;
assert(beta.cyclotomic_squared() == beta.squared());
}
template<>
void test_cyclotomic_squaring<Fqk<mnt4_pp> >()
{
typedef Fqk<mnt4_pp> FieldT;
assert(FieldT::extension_degree() % 2 == 0);
FieldT a = FieldT::random_element();
FieldT a_unitary = a.Frobenius_map(FieldT::extension_degree()/2) * a.inverse();
// beta = a^(q^(k/2)-1)
FieldT beta = a_unitary;
assert(beta.cyclotomic_squared() == beta.squared());
}
template<>
void test_cyclotomic_squaring<Fqk<mnt6_pp> >()
{
typedef Fqk<mnt6_pp> FieldT;
assert(FieldT::extension_degree() % 2 == 0);
FieldT a = FieldT::random_element();
FieldT a_unitary = a.Frobenius_map(FieldT::extension_degree()/2) * a.inverse();
// beta = a^((q^(k/2)-1)*(q+1))
FieldT beta = a_unitary.Frobenius_map(1) * a_unitary;
assert(beta.cyclotomic_squared() == beta.squared());
EXPECT_EQ(aqcubed_minus1.inverse(), aqcubed_minus1.unitary_inverse());
}
template<typename ppT>
@ -197,16 +157,16 @@ void test_Fp4_tom_cook()
c2 = - (FieldT(5)*(FieldT(4).inverse()))* v0 + (FieldT(2)*(FieldT(3).inverse()))*(v1 + v2) - FieldT(24).inverse()*(v3 + v4) + FieldT(4)*v6 + beta*v6;
c3 = FieldT(12).inverse() * (FieldT(5)*v0 - FieldT(7)*v1) - FieldT(24).inverse()*(v2 - FieldT(7)*v3 + v4 + v5) + FieldT(15)*v6;
assert(res == correct_res);
EXPECT_EQ(res, correct_res);
// {v0, v3, v4, v5}
const FieldT u = (FieldT::one() - beta).inverse();
assert(v0 == u * c0 + beta * u * c2 - beta * u * FieldT(2).inverse() * v1 - beta * u * FieldT(2).inverse() * v2 + beta * v6);
assert(v3 == - FieldT(15) * u * c0 - FieldT(30) * u * c1 - FieldT(3) * (FieldT(4) + beta) * u * c2 - FieldT(6) * (FieldT(4) + beta) * u * c3 + (FieldT(24) - FieldT(3) * beta * FieldT(2).inverse()) * u * v1 + (-FieldT(8) + beta * FieldT(2).inverse()) * u * v2
EXPECT_EQ(v0, u * c0 + beta * u * c2 - beta * u * FieldT(2).inverse() * v1 - beta * u * FieldT(2).inverse() * v2 + beta * v6);
EXPECT_EQ(v3, - FieldT(15) * u * c0 - FieldT(30) * u * c1 - FieldT(3) * (FieldT(4) + beta) * u * c2 - FieldT(6) * (FieldT(4) + beta) * u * c3 + (FieldT(24) - FieldT(3) * beta * FieldT(2).inverse()) * u * v1 + (-FieldT(8) + beta * FieldT(2).inverse()) * u * v2
- FieldT(3) * (-FieldT(16) + beta) * v6);
assert(v4 == - FieldT(15) * u * c0 + FieldT(30) * u * c1 - FieldT(3) * (FieldT(4) + beta) * u * c2 + FieldT(6) * (FieldT(4) + beta) * u * c3 + (FieldT(24) - FieldT(3) * beta * FieldT(2).inverse()) * u * v2 + (-FieldT(8) + beta * FieldT(2).inverse()) * u * v1
EXPECT_EQ(v4, - FieldT(15) * u * c0 + FieldT(30) * u * c1 - FieldT(3) * (FieldT(4) + beta) * u * c2 + FieldT(6) * (FieldT(4) + beta) * u * c3 + (FieldT(24) - FieldT(3) * beta * FieldT(2).inverse()) * u * v2 + (-FieldT(8) + beta * FieldT(2).inverse()) * u * v1
- FieldT(3) * (-FieldT(16) + beta) * v6);
assert(v5 == - FieldT(80) * u * c0 - FieldT(240) * u * c1 - FieldT(8) * (FieldT(9) + beta) * u * c2 - FieldT(24) * (FieldT(9) + beta) * u * c3 - FieldT(2) * (-FieldT(81) + beta) * u * v1 + (-FieldT(81) + beta) * u * v2
EXPECT_EQ(v5, - FieldT(80) * u * c0 - FieldT(240) * u * c1 - FieldT(8) * (FieldT(9) + beta) * u * c2 - FieldT(24) * (FieldT(9) + beta) * u * c3 - FieldT(2) * (-FieldT(81) + beta) * u * v1 + (-FieldT(81) + beta) * u * v2
- FieldT(8) * (-FieldT(81) + beta) * v6);
// c0 + beta c2 - (beta v1)/2 - (beta v2)/ 2 - (-1 + beta) beta v6,
@ -216,22 +176,8 @@ void test_Fp4_tom_cook()
}
}
int main(void)
TEST(algebra, fields)
{
edwards_pp::init_public_params();
test_all_fields<edwards_pp>();
test_cyclotomic_squaring<Fqk<edwards_pp> >();
mnt4_pp::init_public_params();
test_all_fields<mnt4_pp>();
test_Fp4_tom_cook<mnt4_Fq4>();
test_two_squarings<Fqe<mnt4_pp> >();
test_cyclotomic_squaring<Fqk<mnt4_pp> >();
mnt6_pp::init_public_params();
test_all_fields<mnt6_pp>();
test_cyclotomic_squaring<Fqk<mnt6_pp> >();
alt_bn128_pp::init_public_params();
test_field<alt_bn128_Fq6>();
test_Frobenius<alt_bn128_Fq6>();

1
src/snark/src/algebra/scalar_multiplication/kc_multiexp.tcc

@ -8,7 +8,6 @@
#ifndef KC_MULTIEXP_TCC_
#define KC_MULTIEXP_TCC_
namespace libsnark {
template<typename T1, typename T2, mp_size_t n>

16
src/snark/src/algebra/scalar_multiplication/multiexp.tcc

@ -40,7 +40,7 @@ public:
#if defined(__x86_64__) && defined(USE_ASM)
if (n == 3)
{
int64_t res;
long res;
__asm__
("// check for overflow \n\t"
"mov $0, %[res] \n\t"
@ -58,7 +58,7 @@ public:
}
else if (n == 4)
{
int64_t res;
long res;
__asm__
("// check for overflow \n\t"
"mov $0, %[res] \n\t"
@ -77,7 +77,7 @@ public:
}
else if (n == 5)
{
int64_t res;
long res;
__asm__
("// check for overflow \n\t"
"mov $0, %[res] \n\t"
@ -190,7 +190,7 @@ T multi_exp_inner(typename std::vector<T>::const_iterator vec_start,
if (vec_len != odd_vec_len)
{
g.emplace_back(T::zero());
opt_q.emplace_back(ordered_exponent<n>(odd_vec_len - 1, bigint<n>(UINT64_C(0))));
opt_q.emplace_back(ordered_exponent<n>(odd_vec_len - 1, bigint<n>(0ul)));
}
assert(g.size() % 2 == 1);
assert(opt_q.size() == g.size());
@ -214,7 +214,7 @@ T multi_exp_inner(typename std::vector<T>::const_iterator vec_start,
const size_t bbits = b.r.num_bits();
const size_t limit = (abits-bbits >= 20 ? 20 : abits-bbits);
if (bbits < UINT64_C(1)<<limit)
if (bbits < 1ul<<limit)
{
/*
In this case, exponentiating to the power of a is cheaper than
@ -389,7 +389,7 @@ size_t get_exp_window_size(const size_t num_scalars)
#endif
}
size_t window = 1;
for (int64_t i = T::fixed_base_exp_window_table.size()-1; i >= 0; --i)
for (long i = T::fixed_base_exp_window_table.size()-1; i >= 0; --i)
{
#ifdef DEBUG
if (!inhibit_profiling_info)
@ -420,9 +420,9 @@ window_table<T> get_window_table(const size_t scalar_size,
const size_t window,
const T &g)
{
const size_t in_window = UINT64_C(1)<<window;
const size_t in_window = 1ul<<window;
const size_t outerc = (scalar_size+window-1)/window;
const size_t last_in_window = UINT64_C(1)<<(scalar_size - (outerc-1)*window);
const size_t last_in_window = 1ul<<(scalar_size - (outerc-1)*window);
#ifdef DEBUG
if (!inhibit_profiling_info)
{

2
src/snark/src/algebra/scalar_multiplication/wnaf.hpp

@ -18,7 +18,7 @@ namespace libsnark {
* Find the wNAF representation of the given scalar relative to the given window size.
*/
template<mp_size_t n>
std::vector<int64_t> find_wnaf(const size_t window_size, const bigint<n> &scalar);
std::vector<long> find_wnaf(const size_t window_size, const bigint<n> &scalar);
/**
* In additive notation, use wNAF exponentiation (with the given window size) to compute scalar * base.

18
src/snark/src/algebra/scalar_multiplication/wnaf.tcc

@ -17,15 +17,15 @@
namespace libsnark {
template<mp_size_t n>
std::vector<int64_t> find_wnaf(const size_t window_size, const bigint<n> &scalar)
std::vector<long> find_wnaf(const size_t window_size, const bigint<n> &scalar)
{
const size_t length = scalar.max_bits(); // upper bound
std::vector<int64_t> res(length+1);
std::vector<long> res(length+1);
bigint<n> c = scalar;
int64_t j = 0;
long j = 0;
while (!c.is_zero())
{
int64_t u;
long u;
if ((c.data[0] & 1) == 1)
{
u = c.data[0] % (1u << (window_size+1));
@ -59,11 +59,11 @@ std::vector<int64_t> find_wnaf(const size_t window_size, const bigint<n> &scalar
template<typename T, mp_size_t n>
T fixed_window_wnaf_exp(const size_t window_size, const T &base, const bigint<n> &scalar)
{
std::vector<int64_t> naf = find_wnaf(window_size, scalar);
std::vector<T> table(UINT64_C(1)<<(window_size-1));
std::vector<long> naf = find_wnaf(window_size, scalar);
std::vector<T> table(1ul<<(window_size-1));
T tmp = base;
T dbl = base.dbl();
for (size_t i = 0; i < UINT64_C(1)<<(window_size-1); ++i)
for (size_t i = 0; i < 1ul<<(window_size-1); ++i)
{
table[i] = tmp;
tmp = tmp + dbl;
@ -71,7 +71,7 @@ T fixed_window_wnaf_exp(const size_t window_size, const T &base, const bigint<n>
T res = T::zero();
bool found_nonzero = false;
for (int64_t i = naf.size()-1; i >= 0; --i)
for (long i = naf.size()-1; i >= 0; --i)
{
if (found_nonzero)
{
@ -99,7 +99,7 @@ template<typename T, mp_size_t n>
T opt_window_wnaf_exp(const T &base, const bigint<n> &scalar, const size_t scalar_bits)
{
size_t best = 0;
for (int64_t i = T::wnaf_window_table.size() - 1; i >= 0; --i)
for (long i = T::wnaf_window_table.size() - 1; i >= 0; --i)
{
if (scalar_bits >= T::wnaf_window_table[i])
{

8
src/snark/src/common/assert_except.hpp

@ -3,10 +3,10 @@
#include <exception>
inline void assert_except (bool condition) {
if (! condition) {
throw std :: runtime_error ("Assertion failed.");
}
inline void assert_except(bool condition) {
if (!condition) {
throw std::runtime_error("Assertion failed.");
}
}
#endif

18
src/snark/src/common/data_structures/merkle_tree.tcc

@ -66,14 +66,14 @@ merkle_tree<HashT>::merkle_tree(const size_t depth,
assert(log2(contents_as_vector.size()) <= depth);
for (size_t address = 0; address < contents_as_vector.size(); ++address)
{
const size_t idx = address + (UINT64_C(1)<<depth) - 1;
const size_t idx = address + (1ul<<depth) - 1;
values[idx] = contents_as_vector[address];
hashes[idx] = contents_as_vector[address];
hashes[idx].resize(digest_size);
}
size_t idx_begin = (UINT64_C(1)<<depth) - 1;
size_t idx_end = contents_as_vector.size() + ((UINT64_C(1)<<depth) - 1);
size_t idx_begin = (1ul<<depth) - 1;
size_t idx_end = contents_as_vector.size() + ((1ul<<depth) - 1);
for (int layer = depth; layer > 0; --layer)
{
@ -100,13 +100,13 @@ merkle_tree<HashT>::merkle_tree(const size_t depth,
if (!contents.empty())
{
assert(contents.rbegin()->first < UINT64_C(1)<<depth);
assert(contents.rbegin()->first < 1ul<<depth);
for (auto it = contents.begin(); it != contents.end(); ++it)
{
const size_t address = it->first;
const bit_vector value = it->second;
const size_t idx = address + (UINT64_C(1)<<depth) - 1;
const size_t idx = address + (1ul<<depth) - 1;
values[address] = value;
hashes[idx] = value;
@ -167,7 +167,7 @@ void merkle_tree<HashT>::set_value(const size_t address,
const bit_vector &value)
{
assert(log2(address) <= depth);
size_t idx = address + (UINT64_C(1)<<depth) - 1;
size_t idx = address + (1ul<<depth) - 1;
assert(value.size() == value_size);
values[address] = value;
@ -201,7 +201,7 @@ typename HashT::merkle_authentication_path_type merkle_tree<HashT>::get_path(con
{
typename HashT::merkle_authentication_path_type result(depth);
assert(log2(address) <= depth);
size_t idx = address + (UINT64_C(1)<<depth) - 1;
size_t idx = address + (1ul<<depth) - 1;
for (size_t layer = depth; layer > 0; --layer)
{
@ -209,7 +209,7 @@ typename HashT::merkle_authentication_path_type merkle_tree<HashT>::get_path(con
auto it = hashes.find(sibling_idx);
if (layer == depth)
{
auto it2 = values.find(sibling_idx - ((UINT64_C(1)<<depth) - 1));
auto it2 = values.find(sibling_idx - ((1ul<<depth) - 1));
result[layer-1] = (it2 == values.end() ? bit_vector(value_size, false) : it2->second);
result[layer-1].resize(digest_size);
}
@ -227,7 +227,7 @@ typename HashT::merkle_authentication_path_type merkle_tree<HashT>::get_path(con
template<typename HashT>
void merkle_tree<HashT>::dump() const
{
for (size_t i = 0; i < UINT64_C(1)<<depth; ++i)
for (size_t i = 0; i < 1ul<<depth; ++i)
{
auto it = values.find(i);
printf("[%zu] -> ", i);

14
src/snark/src/common/data_structures/sparse_vector.hpp

@ -32,9 +32,9 @@ std::istream& operator>>(std::istream &in, sparse_vector<T> &v);
template<typename T>
struct sparse_vector {
std::vector<unsigned long long> indices;
std::vector<size_t> indices;
std::vector<T> values;
unsigned long long domain_size_ = 0;
size_t domain_size_ = 0;
sparse_vector() = default;
sparse_vector(const sparse_vector<T> &other) = default;
@ -44,7 +44,7 @@ struct sparse_vector {
sparse_vector<T>& operator=(const sparse_vector<T> &other) = default;
sparse_vector<T>& operator=(sparse_vector<T> &&other) = default;
T operator[](const unsigned long long idx) const;
T operator[](const size_t idx) const;
bool operator==(const sparse_vector<T> &other) const;
bool operator==(const std::vector<T> &other) const;
@ -52,15 +52,15 @@ struct sparse_vector {
bool is_valid() const;
bool empty() const;
unsigned long long domain_size() const; // return domain_size_
unsigned long long size() const; // return the number of indices (representing the number of non-zero entries)
unsigned long long size_in_bits() const; // return the number bits needed to store the sparse vector
size_t domain_size() const; // return domain_size_
size_t size() const; // return the number of indices (representing the number of non-zero entries)
size_t size_in_bits() const; // return the number bits needed to store the sparse vector
/* return a pair consisting of the accumulated value and the sparse vector of non-accumuated values */
template<typename FieldT>
std::pair<T, sparse_vector<T> > accumulate(const typename std::vector<FieldT>::const_iterator &it_begin,
const typename std::vector<FieldT>::const_iterator &it_end,
const unsigned long long offset) const;
const size_t offset) const;
friend std::ostream& operator<< <T>(std::ostream &out, const sparse_vector<T> &v);
friend std::istream& operator>> <T>(std::istream &in, sparse_vector<T> &v);

36
src/snark/src/common/data_structures/sparse_vector.tcc

@ -29,7 +29,7 @@ sparse_vector<T>::sparse_vector(std::vector<T> &&v) :
}
template<typename T>
T sparse_vector<T>::operator[](const unsigned long long idx) const
T sparse_vector<T>::operator[](const size_t idx) const
{
auto it = std::lower_bound(indices.begin(), indices.end(), idx);
return (it != indices.end() && *it == idx) ? values[it - indices.begin()] : T();
@ -43,7 +43,7 @@ bool sparse_vector<T>::operator==(const sparse_vector<T> &other) const
return false;
}
unsigned long long this_pos = 0, other_pos = 0;
size_t this_pos = 0, other_pos = 0;
while (this_pos < this->indices.size() && other_pos < other.indices.size())
{
if (this->indices[this_pos] == other.indices[other_pos])
@ -103,8 +103,8 @@ bool sparse_vector<T>::operator==(const std::vector<T> &other) const
return false;
}
unsigned long long j = 0;
for (unsigned long long i = 0; i < other.size(); ++i)
size_t j = 0;
for (size_t i = 0; i < other.size(); ++i)
{
if (this->indices[j] == i)
{
@ -134,7 +134,7 @@ bool sparse_vector<T>::is_valid() const
return false;
}
for (unsigned long long i = 0; i + 1 < indices.size(); ++i)
for (size_t i = 0; i + 1 < indices.size(); ++i)
{
if (indices[i] >= indices[i+1])
{
@ -157,42 +157,42 @@ bool sparse_vector<T>::empty() const
}
template<typename T>
unsigned long long sparse_vector<T>::domain_size() const
size_t sparse_vector<T>::domain_size() const
{
return domain_size_;
}
template<typename T>
unsigned long long sparse_vector<T>::size() const
size_t sparse_vector<T>::size() const
{
return indices.size();
}
template<typename T>
unsigned long long sparse_vector<T>::size_in_bits() const
size_t sparse_vector<T>::size_in_bits() const
{
return indices.size() * (sizeof(unsigned long long) * 8 + T::size_in_bits());
return indices.size() * (sizeof(size_t) * 8 + T::size_in_bits());
}
template<typename T>
template<typename FieldT>
std::pair<T, sparse_vector<T> > sparse_vector<T>::accumulate(const typename std::vector<FieldT>::const_iterator &it_begin,
const typename std::vector<FieldT>::const_iterator &it_end,
const unsigned long long offset) const
const size_t offset) const
{
// TODO: does not really belong here.
const unsigned long long chunks = 1;
const size_t chunks = 1;
const bool use_multiexp = true;
T accumulated_value = T::zero();
sparse_vector<T> resulting_vector;
resulting_vector.domain_size_ = domain_size_;
const unsigned long long range_len = it_end - it_begin;
const size_t range_len = it_end - it_begin;
bool in_block = false;
unsigned long long first_pos = -1, last_pos = -1; // g++ -flto emits unitialized warning, even though in_block guards for such cases.
size_t first_pos = -1, last_pos = -1; // g++ -flto emits unitialized warning, even though in_block guards for such cases.
for (unsigned long long i = 0; i < indices.size(); ++i)
for (size_t i = 0; i < indices.size(); ++i)
{
const bool matching_pos = (offset <= indices[i] && indices[i] < offset + range_len);
// printf("i = %zu, pos[i] = %zu, offset = %zu, w_size = %zu\n", i, indices[i], offset, w_size);
@ -265,7 +265,7 @@ std::ostream& operator<<(std::ostream& out, const sparse_vector<T> &v)
{
out << v.domain_size_ << "\n";
out << v.indices.size() << "\n";
for (const unsigned long long& i : v.indices)
for (const size_t& i : v.indices)
{
out << i << "\n";
}
@ -285,11 +285,11 @@ std::istream& operator>>(std::istream& in, sparse_vector<T> &v)
in >> v.domain_size_;
consume_newline(in);
unsigned long long s;
size_t s;
in >> s;
consume_newline(in);
v.indices.resize(s);
for (unsigned long long i = 0; i < s; ++i)
for (size_t i = 0; i < s; ++i)
{
in >> v.indices[i];
consume_newline(in);
@ -300,7 +300,7 @@ std::istream& operator>>(std::istream& in, sparse_vector<T> &v)
consume_newline(in);
v.values.reserve(s);
for (unsigned long long i = 0; i < s; ++i)
for (size_t i = 0; i < s; ++i)
{
T t;
in >> t;

69
src/snark/src/common/profiling.cpp

@ -26,16 +26,9 @@
#include <proc/readproc.h>
#endif
#ifdef __MACH__ // required to build on MacOS
#include <time.h>
#include <sys/time.h>
#include <mach/clock.h>
#include <mach/mach.h>
#endif
namespace libsnark {
int64_t get_nsec_time()
long long get_nsec_time()
{
auto timepoint = std::chrono::high_resolution_clock::now();
return std::chrono::duration_cast<std::chrono::nanoseconds>(timepoint.time_since_epoch()).count();
@ -45,20 +38,10 @@ int64_t get_nsec_time()
long long get_nsec_cpu_time()
{
::timespec ts;
#ifdef __MACH__
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
ts.tv_sec = mts.tv_sec;
ts.tv_nsec = mts.tv_nsec;
#else
if ( ::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) )
throw ::std::runtime_error("clock_gettime(CLOCK_PROCESS_CPUTIME_ID) failed");
// If we expected this to work, don't silently ignore failures, because that would hide the problem and incur an unnecessarily system-call overhead. So if we ever observe this exception, we should probably add a suitable #ifdef .
//TODO: clock_gettime(CLOCK_PROCESS_CPUTIME_ID) is not supported by native Windows. What about Cygwin? Should we #ifdef on CLOCK_PROCESS_CPUTIME_ID or on __linux__?
#endif
return ts.tv_sec * 1000000000ll + ts.tv_nsec;
}
@ -74,20 +57,20 @@ void start_profiling()
}
std::map<std::string, size_t> invocation_counts;
std::map<std::string, int64_t> enter_times;
std::map<std::string, int64_t> last_times;
std::map<std::string, int64_t> cumulative_times;
std::map<std::string, long long> enter_times;
std::map<std::string, long long> last_times;
std::map<std::string, long long> cumulative_times;
//TODO: Instead of analogous maps for time and cpu_time, use a single struct-valued map
std::map<std::string, int64_t> enter_cpu_times;
std::map<std::string, int64_t> last_cpu_times;
std::map<std::pair<std::string, std::string>, int64_t> op_counts;
std::map<std::pair<std::string, std::string>, int64_t> cumulative_op_counts; // ((msg, data_point), value)
std::map<std::string, long long> enter_cpu_times;
std::map<std::string, long long> last_cpu_times;
std::map<std::pair<std::string, std::string>, long long> op_counts;
std::map<std::pair<std::string, std::string>, long long> cumulative_op_counts; // ((msg, data_point), value)
// TODO: Convert op_counts and cumulative_op_counts from pair to structs
size_t indentation = 0;
std::vector<std::string> block_names;
std::list<std::pair<std::string, int64_t*> > op_data_points = {
std::list<std::pair<std::string, long long*> > op_data_points = {
#ifdef PROFILE_OP_COUNTS
std::make_pair("Fradd", &Fr<default_ec_pp>::add_cnt),
std::make_pair("Frsub", &Fr<default_ec_pp>::sub_cnt),
@ -115,7 +98,7 @@ void clear_profiling_counters()
cumulative_times.clear();
}
void print_cumulative_time_entry(const std::string &key, const int64_t factor)
void print_cumulative_time_entry(const std::string &key, const long long factor)
{
const double total_ms = (cumulative_times.at(key) * 1e-6);
const size_t cnt = invocation_counts.at(key);
@ -123,7 +106,7 @@ void print_cumulative_time_entry(const std::string &key, const int64_t factor)
printf(" %-45s: %12.5fms = %lld * %0.5fms (%zu invocations, %0.5fms = %lld * %0.5fms per invocation)\n", key.c_str(), total_ms, factor, total_ms/factor, cnt, avg_ms, factor, avg_ms/factor);
}
void print_cumulative_times(const int64_t factor)
void print_cumulative_times(const long long factor)
{
printf("Dumping times:\n");
for (auto& kv : cumulative_times)
@ -172,7 +155,7 @@ void print_op_profiling(const std::string &msg)
printf("(opcounts) = (");
bool first = true;
for (std::pair<std::string, int64_t*> p : op_data_points)
for (std::pair<std::string, long long*> p : op_data_points)
{
if (!first)
{
@ -188,14 +171,14 @@ void print_op_profiling(const std::string &msg)
#endif
}
static void print_times_from_last_and_start(int64_t now, int64_t last,
int64_t cpu_now, int64_t cpu_last)
static void print_times_from_last_and_start(long long now, long long last,
long long cpu_now, long long cpu_last)
{
int64_t time_from_start = now - start_time;
int64_t time_from_last = now - last;
long long time_from_start = now - start_time;
long long time_from_last = now - last;
int64_t cpu_time_from_start = cpu_now - start_cpu_time;
int64_t cpu_time_from_last = cpu_now - cpu_last;
long long cpu_time_from_start = cpu_now - start_cpu_time;
long long cpu_time_from_last = cpu_now - cpu_last;
if (time_from_last != 0) {
double parallelism_from_last = 1.0 * cpu_time_from_last / time_from_last;
@ -216,8 +199,8 @@ void print_time(const char* msg)
return;
}
int64_t now = get_nsec_time();
int64_t cpu_now = get_nsec_cpu_time();
long long now = get_nsec_time();
long long cpu_now = get_nsec_cpu_time();
printf("%-35s\t", msg);
print_times_from_last_and_start(now, last_time, cpu_now, last_cpu_time);
@ -248,7 +231,7 @@ void print_indent()
void op_profiling_enter(const std::string &msg)
{
for (std::pair<std::string, int64_t*> p : op_data_points)
for (std::pair<std::string, long long*> p : op_data_points)
{
op_counts[std::make_pair(msg, p.first)] = *(p.second);
}
@ -262,9 +245,9 @@ void enter_block(const std::string &msg, const bool indent)
}
block_names.emplace_back(msg);
int64_t t = get_nsec_time();
long long t = get_nsec_time();
enter_times[msg] = t;
int64_t cpu_t = get_nsec_cpu_time();
long long cpu_t = get_nsec_cpu_time();
enter_cpu_times[msg] = cpu_t;
if (inhibit_profiling_info)
@ -305,15 +288,15 @@ void leave_block(const std::string &msg, const bool indent)
++invocation_counts[msg];
int64_t t = get_nsec_time();
long long t = get_nsec_time();
last_times[msg] = (t - enter_times[msg]);
cumulative_times[msg] += (t - enter_times[msg]);
int64_t cpu_t = get_nsec_cpu_time();
long long cpu_t = get_nsec_cpu_time();
last_cpu_times[msg] = (cpu_t - enter_cpu_times[msg]);
#ifdef PROFILE_OP_COUNTS
for (std::pair<std::string, int64_t*> p : op_data_points)
for (std::pair<std::string, long long*> p : op_data_points)
{
cumulative_op_counts[std::make_pair(msg, p.first)] += *(p.second)-op_counts[std::make_pair(msg, p.first)];
}

10
src/snark/src/common/profiling.hpp

@ -22,7 +22,7 @@
namespace libsnark {
void start_profiling();
int64_t get_nsec_time();
long long get_nsec_time();
void print_time(const char* msg);
void print_header(const char* msg);
@ -31,13 +31,13 @@ void print_indent();
extern bool inhibit_profiling_info;
extern bool inhibit_profiling_counters;
extern std::map<std::string, size_t> invocation_counts;
extern std::map<std::string, int64_t> last_times;
extern std::map<std::string, int64_t> cumulative_times;
extern std::map<std::string, long long> last_times;
extern std::map<std::string, long long> cumulative_times;
void clear_profiling_counters();
void print_cumulative_time_entry(const std::string &key, const int64_t factor=1);
void print_cumulative_times(const int64_t factor=1);
void print_cumulative_time_entry(const std::string &key, const long long factor=1);
void print_cumulative_times(const long long factor=1);
void print_cumulative_op_counts(const bool only_fq=false);
void enter_block(const std::string &msg, const bool indent=true);

28
src/snark/src/common/utils.cpp

@ -15,11 +15,11 @@
namespace libsnark {
unsigned long long log2(unsigned long long n)
size_t log2(size_t n)
/* returns ceil(log2(n)), so 1ul<<log2(n) is the smallest power of 2,
that is not less than n. */
{
unsigned long long r = ((n & (n-1)) == 0 ? 0 : 1); // add 1 if n is not power of 2
size_t r = ((n & (n-1)) == 0 ? 0 : 1); // add 1 if n is not power of 2
while (n > 1)
{
@ -30,10 +30,10 @@ unsigned long long log2(unsigned long long n)
return r;
}
unsigned long long bitreverse(unsigned long long n, const unsigned long long l)
size_t bitreverse(size_t n, const size_t l)
{
unsigned long long r = 0;
for (unsigned long long k = 0; k < l; ++k)
size_t r = 0;
for (size_t k = 0; k < l; ++k)
{
r = (r << 1) | (n & 1);
n >>= 1;
@ -41,20 +41,20 @@ unsigned long long bitreverse(unsigned long long n, const unsigned long long l)
return r;
}
bit_vector int_list_to_bits(const std::initializer_list<uint64_t> &l, const size_t wordsize)
bit_vector int_list_to_bits(const std::initializer_list<unsigned long> &l, const size_t wordsize)
{
bit_vector res(wordsize*l.size());
for (uint64_t i = 0; i < l.size(); ++i)
for (size_t i = 0; i < l.size(); ++i)
{
for (uint64_t j = 0; j < wordsize; ++j)
for (size_t j = 0; j < wordsize; ++j)
{
res[i*wordsize + j] = (*(l.begin()+i) & (UINT64_C(1)<<(wordsize-1-j)));
res[i*wordsize + j] = (*(l.begin()+i) & (1ul<<(wordsize-1-j)));
}
}
return res;
}
int64_t div_ceil(int64_t x, int64_t y)
long long div_ceil(long long x, long long y)
{
return (x + (y-1)) / y;
}
@ -68,7 +68,7 @@ bool is_little_endian()
std::string FORMAT(const std::string &prefix, const char* format, ...)
{
const static unsigned long long MAX_FMT = 256;
const static size_t MAX_FMT = 256;
char buf[MAX_FMT];
va_list args;
va_start(args, format);
@ -81,7 +81,7 @@ std::string FORMAT(const std::string &prefix, const char* format, ...)
void serialize_bit_vector(std::ostream &out, const bit_vector &v)
{
out << v.size() << "\n";
for (unsigned long long i = 0; i < v.size(); ++i)
for (size_t i = 0; i < v.size(); ++i)
{
out << v[i] << "\n";
}
@ -89,10 +89,10 @@ void serialize_bit_vector(std::ostream &out, const bit_vector &v)
void deserialize_bit_vector(std::istream &in, bit_vector &v)
{
unsigned long long size;
size_t size;
in >> size;
v.resize(size);
for (unsigned long long i = 0; i < size; ++i)
for (size_t i = 0; i < size; ++i)
{
bool b;
in >> b;

12
src/snark/src/common/utils.hpp

@ -21,13 +21,13 @@ namespace libsnark {
typedef std::vector<bool> bit_vector;
/// returns ceil(log2(n)), so 1ul<<log2(n) is the smallest power of 2, that is not less than n
unsigned long long log2(unsigned long long n);
size_t log2(size_t n);
inline unsigned long long exp2(unsigned long long k) { return 1ull << k; }
inline size_t exp2(size_t k) { return 1ul << k; }
unsigned long long bitreverse(unsigned long long n, const unsigned long long l);
bit_vector int_list_to_bits(const std::initializer_list<unsigned long long> &l, const unsigned long long wordsize);
int64_t div_ceil(int64_t x, int64_t y);
size_t bitreverse(size_t n, const size_t l);
bit_vector int_list_to_bits(const std::initializer_list<unsigned long> &l, const size_t wordsize);
long long div_ceil(long long x, long long y);
bool is_little_endian();
@ -47,7 +47,7 @@ void serialize_bit_vector(std::ostream &out, const bit_vector &v);
void deserialize_bit_vector(std::istream &in, bit_vector &v);
template<typename T>
unsigned long long size_in_bits(const std::vector<T> &v);
size_t size_in_bits(const std::vector<T> &v);
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))

2
src/snark/src/common/utils.tcc

@ -13,7 +13,7 @@
namespace libsnark {
template<typename T>
unsigned long long size_in_bits(const std::vector<T> &v)
size_t size_in_bits(const std::vector<T> &v)
{
return v.size() * T::size_in_bits();
}

40
src/snark/src/gadgetlib1/gadgets/basic_gadgets.tcc

@ -275,11 +275,11 @@ void test_disjunction_gadget(const size_t n)
disjunction_gadget<FieldT> d(pb, inputs, output, "d");
d.generate_r1cs_constraints();
for (size_t w = 0; w < UINT64_C(1)<<n; ++w)
for (size_t w = 0; w < 1ul<<n; ++w)
{
for (size_t j = 0; j < n; ++j)
{
pb.val(inputs[j]) = FieldT((w & (UINT64_C(1)<<j)) ? 1 : 0);
pb.val(inputs[j]) = FieldT((w & (1ul<<j)) ? 1 : 0);
}
d.generate_r1cs_witness();
@ -366,11 +366,11 @@ void test_conjunction_gadget(const size_t n)
conjunction_gadget<FieldT> c(pb, inputs, output, "c");
c.generate_r1cs_constraints();
for (size_t w = 0; w < UINT64_C(1)<<n; ++w)
for (size_t w = 0; w < 1ul<<n; ++w)
{
for (size_t j = 0; j < n; ++j)
{
pb.val(inputs[j]) = (w & (UINT64_C(1)<<j)) ? FieldT::one() : FieldT::zero();
pb.val(inputs[j]) = (w & (1ul<<j)) ? FieldT::one() : FieldT::zero();
}
c.generate_r1cs_witness();
@ -378,13 +378,13 @@ void test_conjunction_gadget(const size_t n)
#ifdef DEBUG
printf("positive test for %zu\n", w);
#endif
assert(pb.val(output) == (w == (UINT64_C(1)<<n) - 1 ? FieldT::one() : FieldT::zero()));
assert(pb.val(output) == (w == (1ul<<n) - 1 ? FieldT::one() : FieldT::zero()));
assert(pb.is_satisfied());
#ifdef DEBUG
printf("negative test for %zu\n", w);
#endif
pb.val(output) = (w == (UINT64_C(1)<<n) - 1 ? FieldT::zero() : FieldT::one());
pb.val(output) = (w == (1ul<<n) - 1 ? FieldT::zero() : FieldT::one());
assert(!pb.is_satisfied());
}
@ -454,9 +454,9 @@ void test_comparison_gadget(const size_t n)
comparison_gadget<FieldT> cmp(pb, n, A, B, less, less_or_eq, "cmp");
cmp.generate_r1cs_constraints();
for (size_t a = 0; a < UINT64_C(1)<<n; ++a)
for (size_t a = 0; a < 1ul<<n; ++a)
{
for (size_t b = 0; b < UINT64_C(1)<<n; ++b)
for (size_t b = 0; b < 1ul<<n; ++b)
{
pb.val(A) = FieldT(a);
pb.val(B) = FieldT(b);
@ -523,16 +523,16 @@ void test_inner_product_gadget(const size_t n)
inner_product_gadget<FieldT> g(pb, A, B, result, "g");
g.generate_r1cs_constraints();
for (size_t i = 0; i < UINT64_C(1)<<n; ++i)
for (size_t i = 0; i < 1ul<<n; ++i)
{
for (size_t j = 0; j < UINT64_C(1)<<n; ++j)
for (size_t j = 0; j < 1ul<<n; ++j)
{
size_t correct = 0;
for (size_t k = 0; k < n; ++k)
{
pb.val(A[k]) = (i & (UINT64_C(1)<<k) ? FieldT::one() : FieldT::zero());
pb.val(B[k]) = (j & (UINT64_C(1)<<k) ? FieldT::one() : FieldT::zero());
correct += ((i & (UINT64_C(1)<<k)) && (j & (UINT64_C(1)<<k)) ? 1 : 0);
pb.val(A[k]) = (i & (1ul<<k) ? FieldT::one() : FieldT::zero());
pb.val(B[k]) = (j & (1ul<<k) ? FieldT::one() : FieldT::zero());
correct += ((i & (1ul<<k)) && (j & (1ul<<k)) ? 1 : 0);
}
g.generate_r1cs_witness();
@ -587,7 +587,7 @@ void loose_multiplexing_gadget<FieldT>::generate_r1cs_witness()
{
/* assumes that idx can be fit in ulong; true for our purposes for now */
const bigint<FieldT::num_limbs> valint = this->pb.val(index).as_bigint();
uint64_t idx = valint.as_ulong();
unsigned long idx = valint.as_ulong();
const bigint<FieldT::num_limbs> arrsize(arr.size());
if (idx >= arr.size() || mpn_cmp(valint.data, arrsize.data, FieldT::num_limbs) >= 0)
@ -619,7 +619,7 @@ void test_loose_multiplexing_gadget(const size_t n)
protoboard<FieldT> pb;
pb_variable_array<FieldT> arr;
arr.allocate(pb, UINT64_C(1)<<n, "arr");
arr.allocate(pb, 1ul<<n, "arr");
pb_variable<FieldT> index, result, success_flag;
index.allocate(pb, "index");
result.allocate(pb, "result");
@ -628,20 +628,20 @@ void test_loose_multiplexing_gadget(const size_t n)
loose_multiplexing_gadget<FieldT> g(pb, arr, index, result, success_flag, "g");
g.generate_r1cs_constraints();
for (size_t i = 0; i < UINT64_C(1)<<n; ++i)
for (size_t i = 0; i < 1ul<<n; ++i)
{
pb.val(arr[i]) = FieldT((19*i) % (UINT64_C(1)<<n));
pb.val(arr[i]) = FieldT((19*i) % (1ul<<n));
}
for (int idx = -1; idx <= (int)(UINT64_C(1)<<n); ++idx)
for (int idx = -1; idx <= (int)(1ul<<n); ++idx)
{
pb.val(index) = FieldT(idx);
g.generate_r1cs_witness();
if (0 <= idx && idx <= (int)(UINT64_C(1)<<n) - 1)
if (0 <= idx && idx <= (int)(1ul<<n) - 1)
{
printf("demuxing element %d (in bounds)\n", idx);
assert(pb.val(result) == FieldT((19*idx) % (UINT64_C(1)<<n)));
assert(pb.val(result) == FieldT((19*idx) % (1ul<<n)));
assert(pb.val(success_flag) == FieldT::one());
assert(pb.is_satisfied());
pb.val(result) -= FieldT::one();

2
src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_aux.tcc

@ -285,7 +285,7 @@ void majority_gadget<FieldT>::generate_r1cs_witness()
{
for (size_t i = 0; i < 32; ++i)
{
const int64_t v = (this->pb.lc_val(X[i]) + this->pb.lc_val(Y[i]) + this->pb.lc_val(Z[i])).as_ulong();
const long v = (this->pb.lc_val(X[i]) + this->pb.lc_val(Y[i]) + this->pb.lc_val(Z[i])).as_ulong();
this->pb.val(result_bits[i]) = FieldT(v / 2);
}

4
src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_components.hpp

@ -78,7 +78,7 @@ public:
pb_linear_combination_array<FieldT> g;
pb_linear_combination_array<FieldT> h;
pb_variable<FieldT> W;
int64_t K;
long K;
pb_linear_combination_array<FieldT> new_a;
pb_linear_combination_array<FieldT> new_e;
@ -92,7 +92,7 @@ public:
const pb_linear_combination_array<FieldT> &g,
const pb_linear_combination_array<FieldT> &h,
const pb_variable<FieldT> &W,
const int64_t &K,
const long &K,
const pb_linear_combination_array<FieldT> &new_a,
const pb_linear_combination_array<FieldT> &new_e,
const std::string &annotation_prefix);

6
src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_components.tcc

@ -16,7 +16,7 @@
namespace libsnark {
const uint64_t SHA256_K[64] = {
const unsigned long SHA256_K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
@ -27,7 +27,7 @@ const uint64_t SHA256_K[64] = {
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
const uint64_t SHA256_H[8] = {
const unsigned long SHA256_H[8] = {
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
};
@ -149,7 +149,7 @@ sha256_round_function_gadget<FieldT>::sha256_round_function_gadget(protoboard<Fi
const pb_linear_combination_array<FieldT> &g,
const pb_linear_combination_array<FieldT> &h,
const pb_variable<FieldT> &W,
const int64_t &K,
const long &K,
const pb_linear_combination_array<FieldT> &new_a,
const pb_linear_combination_array<FieldT> &new_e,
const std::string &annotation_prefix) :

6
src/snark/src/gadgetlib1/gadgets/hashes/sha256/tests/test_sha256_gadget.cpp

@ -10,6 +10,8 @@
#include "common/profiling.hpp"
#include "gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp"
#include <gtest/gtest.h>
using namespace libsnark;
template<typename FieldT>
@ -35,10 +37,10 @@ void test_two_to_one()
f.generate_r1cs_witness();
output.generate_r1cs_witness(hash_bv);
assert(pb.is_satisfied());
EXPECT_TRUE(pb.is_satisfied());
}
int main(void)
TEST(gadgetlib1, sha256)
{
start_profiling();
default_ec_pp::init_public_params();

4
src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.tcc

@ -41,7 +41,7 @@ void merkle_authentication_path_variable<FieldT, HashT>::generate_r1cs_witness(c
for (size_t i = 0; i < tree_depth; ++i)
{
if (address & (UINT64_C(1) << (tree_depth-1-i)))
if (address & (1ul << (tree_depth-1-i)))
{
left_digests[i].generate_r1cs_witness(path[i]);
}
@ -58,7 +58,7 @@ merkle_authentication_path merkle_authentication_path_variable<FieldT, HashT>::g
merkle_authentication_path result;
for (size_t i = 0; i < tree_depth; ++i)
{
if (address & (UINT64_C(1) << (tree_depth-1-i)))
if (address & (1ul << (tree_depth-1-i)))
{
result.emplace_back(left_digests[i].get_digest());
}

4
src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.tcc

@ -144,10 +144,10 @@ void test_merkle_tree_check_read_gadget()
bit_vector address_bits;
size_t address = 0;
for (int64_t level = tree_depth-1; level >= 0; --level)
for (long level = tree_depth-1; level >= 0; --level)
{
const bool computed_is_right = (std::rand() % 2);
address |= (computed_is_right ? UINT64_C(1) << (tree_depth-1-level) : 0);
address |= (computed_is_right ? 1ul << (tree_depth-1-level) : 0);
address_bits.push_back(computed_is_right);
bit_vector other(digest_len);
std::generate(other.begin(), other.end(), [&]() { return std::rand() % 2; });

1
src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.hpp

@ -19,7 +19,6 @@
#include "common/data_structures/merkle_tree.hpp"
#include "gadgetlib1/gadget.hpp"
#include "gadgetlib1/gadgets/hashes/crh_gadget.hpp"
#include "gadgetlib1/gadgets/hashes/hash_io.hpp"
#include "gadgetlib1/gadgets/hashes/digest_selector_gadget.hpp"
#include "gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.hpp"

4
src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.tcc

@ -197,10 +197,10 @@ void test_merkle_tree_check_update_gadget()
bit_vector address_bits;
size_t address = 0;
for (int64_t level = tree_depth-1; level >= 0; --level)
for (long level = tree_depth-1; level >= 0; --level)
{
const bool computed_is_right = (std::rand() % 2);
address |= (computed_is_right ? UINT64_C(1) << (tree_depth-1-level) : 0);
address |= (computed_is_right ? 1ul << (tree_depth-1-level) : 0);
address_bits.push_back(computed_is_right);
bit_vector other(digest_len);
std::generate(other.begin(), other.end(), [&]() { return std::rand() % 2; });

22
src/snark/src/gadgetlib1/gadgets/merkle_tree/tests/test_merkle_tree_gadgets.cpp

@ -5,44 +5,36 @@
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp"
#ifdef CURVE_BN128
#include "algebra/curves/bn128/bn128_pp.hpp"
#endif
#include "algebra/curves/edwards/edwards_pp.hpp"
#include "algebra/curves/mnt/mnt4/mnt4_pp.hpp"
#include "algebra/curves/mnt/mnt6/mnt6_pp.hpp"
#include "gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp"
#include "gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.hpp"
#include "gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp"
#include <gtest/gtest.h>
using namespace libsnark;
template<typename ppT>
void test_all_merkle_tree_gadgets()
{
typedef Fr<ppT> FieldT;
test_merkle_tree_check_read_gadget<FieldT, CRH_with_bit_out_gadget<FieldT> >();
test_merkle_tree_check_read_gadget<FieldT, sha256_two_to_one_hash_gadget<FieldT> >();
test_merkle_tree_check_update_gadget<FieldT, CRH_with_bit_out_gadget<FieldT> >();
test_merkle_tree_check_update_gadget<FieldT, sha256_two_to_one_hash_gadget<FieldT> >();
}
int main(void)
TEST(gadgetlib1, merkle_tree)
{
start_profiling();
alt_bn128_pp::init_public_params();
test_all_merkle_tree_gadgets<alt_bn128_pp>();
#ifdef CURVE_BN128 // BN128 has fancy dependencies so it may be disabled
bn128_pp::init_public_params();
test_all_merkle_tree_gadgets<bn128_pp>();
#endif
edwards_pp::init_public_params();
test_all_merkle_tree_gadgets<edwards_pp>();
mnt4_pp::init_public_params();
test_all_merkle_tree_gadgets<mnt4_pp>();
mnt6_pp::init_public_params();
test_all_merkle_tree_gadgets<mnt6_pp>();
}

4
src/snark/src/gadgetlib1/pb_variable.hpp

@ -59,7 +59,7 @@ public:
void fill_with_field_elements(protoboard<FieldT> &pb, const std::vector<FieldT>& vals) const;
void fill_with_bits(protoboard<FieldT> &pb, const bit_vector& bits) const;
void fill_with_bits_of_ulong(protoboard<FieldT> &pb, const uint64_t i) const;
void fill_with_bits_of_ulong(protoboard<FieldT> &pb, const unsigned long i) const;
void fill_with_bits_of_field_element(protoboard<FieldT> &pb, const FieldT &r) const;
std::vector<FieldT> get_vals(const protoboard<FieldT> &pb) const;
@ -120,7 +120,7 @@ public:
void fill_with_field_elements(protoboard<FieldT> &pb, const std::vector<FieldT>& vals) const;
void fill_with_bits(protoboard<FieldT> &pb, const bit_vector& bits) const;
void fill_with_bits_of_ulong(protoboard<FieldT> &pb, const uint64_t i) const;
void fill_with_bits_of_ulong(protoboard<FieldT> &pb, const unsigned long i) const;
void fill_with_bits_of_field_element(protoboard<FieldT> &pb, const FieldT &r) const;
std::vector<FieldT> get_vals(const protoboard<FieldT> &pb) const;

4
src/snark/src/gadgetlib1/pb_variable.tcc

@ -65,7 +65,7 @@ void pb_variable_array<FieldT>::fill_with_bits_of_field_element(protoboard<Field
}
template<typename FieldT>
void pb_variable_array<FieldT>::fill_with_bits_of_ulong(protoboard<FieldT> &pb, const uint64_t i) const
void pb_variable_array<FieldT>::fill_with_bits_of_ulong(protoboard<FieldT> &pb, const unsigned long i) const
{
this->fill_with_bits_of_field_element(pb, FieldT(i, true));
}
@ -232,7 +232,7 @@ void pb_linear_combination_array<FieldT>::fill_with_bits_of_field_element(protob
}
template<typename FieldT>
void pb_linear_combination_array<FieldT>::fill_with_bits_of_ulong(protoboard<FieldT> &pb, const uint64_t i) const
void pb_linear_combination_array<FieldT>::fill_with_bits_of_ulong(protoboard<FieldT> &pb, const unsigned long i) const
{
this->fill_with_bits_of_field_element(pb, FieldT(i));
}

31
src/snark/src/relations/arithmetic_programs/qap/tests/test_qap.cpp

@ -10,13 +10,15 @@
#include <cstring>
#include <vector>
#include "algebra/curves/mnt/mnt6/mnt6_pp.hpp"
#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp"
#include "algebra/fields/field_utils.hpp"
#include "common/profiling.hpp"
#include "common/utils.hpp"
#include "reductions/r1cs_to_qap/r1cs_to_qap.hpp"
#include "relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.hpp"
#include <gtest/gtest.h>
using namespace libsnark;
template<typename FieldT>
@ -28,7 +30,7 @@ void test_qap(const size_t qap_degree, const size_t num_inputs, const bool binar
See the transformation from R1CS to QAP for why this is the case.
So we need that qap_degree >= num_inputs + 1.
*/
assert(num_inputs + 1 <= qap_degree);
ASSERT_LE(num_inputs + 1, qap_degree);
enter_block("Call to test_qap");
const size_t num_constraints = qap_degree - num_inputs - 1;
@ -51,7 +53,7 @@ void test_qap(const size_t qap_degree, const size_t num_inputs, const bool binar
leave_block("Generate constraint system and assignment");
enter_block("Check satisfiability of constraint system");
assert(example.constraint_system.is_satisfied(example.primary_input, example.auxiliary_input));
EXPECT_TRUE(example.constraint_system.is_satisfied(example.primary_input, example.auxiliary_input));
leave_block("Check satisfiability of constraint system");
const FieldT t = FieldT::random_element(),
@ -72,44 +74,31 @@ void test_qap(const size_t qap_degree, const size_t num_inputs, const bool binar
leave_block("Compute QAP witness");
enter_block("Check satisfiability of QAP instance 1");
assert(qap_inst_1.is_satisfied(qap_wit));
EXPECT_TRUE(qap_inst_1.is_satisfied(qap_wit));
leave_block("Check satisfiability of QAP instance 1");
enter_block("Check satisfiability of QAP instance 2");
assert(qap_inst_2.is_satisfied(qap_wit));
EXPECT_TRUE(qap_inst_2.is_satisfied(qap_wit));
leave_block("Check satisfiability of QAP instance 2");
leave_block("Call to test_qap");
}
int main()
TEST(relations, qap)
{
start_profiling();
mnt6_pp::init_public_params();
const size_t num_inputs = 10;
const size_t basic_domain_size = UINT64_C(1)<<mnt6_Fr::s;
const size_t step_domain_size = (UINT64_C(1)<<10) + (UINT64_C(1)<<8);
const size_t extended_domain_size = UINT64_C(1)<<(mnt6_Fr::s+1);
const size_t extended_domain_size_special = extended_domain_size-1;
enter_block("Test QAP with binary input");
test_qap<Fr<mnt6_pp> >(basic_domain_size, num_inputs, true);
test_qap<Fr<mnt6_pp> >(step_domain_size, num_inputs, true);
test_qap<Fr<mnt6_pp> >(extended_domain_size, num_inputs, true);
test_qap<Fr<mnt6_pp> >(extended_domain_size_special, num_inputs, true);
test_qap<Fr<alt_bn128_pp> >(1ul << 21, num_inputs, true);
leave_block("Test QAP with binary input");
enter_block("Test QAP with field input");
test_qap<Fr<mnt6_pp> >(basic_domain_size, num_inputs, false);
test_qap<Fr<mnt6_pp> >(step_domain_size, num_inputs, false);
test_qap<Fr<mnt6_pp> >(extended_domain_size, num_inputs, false);
test_qap<Fr<mnt6_pp> >(extended_domain_size_special, num_inputs, false);
test_qap<Fr<alt_bn128_pp> >(1ul << 21, num_inputs, false);
leave_block("Test QAP with field input");
}

2
src/snark/src/relations/variable.hpp

@ -26,7 +26,7 @@ namespace libsnark {
* Mnemonic typedefs.
*/
typedef size_t var_index_t;
typedef int64_t integer_coeff_t;
typedef long integer_coeff_t;
/**
* Forward declaration.

2
src/snark/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.tcc

@ -83,7 +83,7 @@ bool run_r1cs_ppzksnark(const r1cs_example<Fr<ppT> > &example,
}
print_header("R1CS ppzkSNARK Prover");
r1cs_ppzksnark_proof<ppT> proof = r1cs_ppzksnark_prover<ppT>(keypair.pk, example.primary_input, example.auxiliary_input);
r1cs_ppzksnark_proof<ppT> proof = r1cs_ppzksnark_prover<ppT>(keypair.pk, example.primary_input, example.auxiliary_input, example.constraint_system);
printf("\n"); print_indent(); print_mem("after prover");
if (test_serialization)

14
src/snark/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp

@ -11,14 +11,14 @@
#include <cassert>
#include <cstdio>
#include "zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark_params.hpp"
#include "common/default_types/ec_pp.hpp"
#include "common/default_types/r1cs_ppzksnark_pp.hpp"
#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp"
#include "common/profiling.hpp"
#include "common/utils.hpp"
#include "relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.hpp"
#include "zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.hpp"
#include <gtest/gtest.h>
using namespace libsnark;
template<typename ppT>
@ -29,16 +29,16 @@ void test_r1cs_ppzksnark(size_t num_constraints,
const bool test_serialization = true;
r1cs_example<Fr<ppT> > example = generate_r1cs_example_with_binary_input<Fr<ppT> >(num_constraints, input_size);
example.constraint_system.swap_AB_if_beneficial();
const bool bit = run_r1cs_ppzksnark<ppT>(example, test_serialization);
assert(bit);
EXPECT_TRUE(bit);
print_header("(leave) Test R1CS ppzkSNARK");
}
int main()
TEST(zk_proof_systems, r1cs_ppzksnark)
{
default_r1cs_ppzksnark_pp::init_public_params();
start_profiling();
test_r1cs_ppzksnark<default_r1cs_ppzksnark_pp>(1000, 100);
test_r1cs_ppzksnark<alt_bn128_pp>(1000, 20);
}

7
src/test/scheduler_tests.cpp

@ -30,14 +30,7 @@ static void microTask(CScheduler& s, boost::mutex& mutex, int& counter, int delt
static void MicroSleep(uint64_t n)
{
#if defined(HAVE_WORKING_BOOST_SLEEP_FOR)
boost::this_thread::sleep_for(boost::chrono::microseconds(n));
#elif defined(HAVE_WORKING_BOOST_SLEEP)
boost::this_thread::sleep(boost::posix_time::microseconds(n));
#else
//should never get here
#error missing boost sleep implementation
#endif
}
BOOST_AUTO_TEST_CASE(manythreads)

1
src/txdb.cpp

@ -518,6 +518,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
pindexNew->nSolution = diskindex.nSolution;
pindexNew->nStatus = diskindex.nStatus;
pindexNew->nTx = diskindex.nTx;
pindexNew->nSproutValue = diskindex.nSproutValue;
if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, Params().GetConsensus()))
return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString());

6
src/univalue/include/univalue.h

@ -3,8 +3,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef __UNIVALUE_H__
#define __UNIVALUE_H__
#ifndef UNIVALUE_H__
#define UNIVALUE_H__
#include <stdint.h>
@ -316,4 +316,4 @@ extern const UniValue NullUniValue;
const UniValue& find_value( const UniValue& obj, const std::string& name);
#endif // __UNIVALUE_H__
#endif // UNIVALUE_H__

4
src/util.cpp

@ -919,10 +919,6 @@ std::string LicenseInfo()
int GetNumCores()
{
#if BOOST_VERSION >= 105600
return boost::thread::physical_concurrency();
#else // Must fall back to hardware_concurrency, which unfortunately counts virtual cores
return boost::thread::hardware_concurrency();
#endif
}

2
src/utiltest.cpp

@ -63,7 +63,7 @@ CWalletTx GetValidReceive(ZCJoinSplit& params,
libzcash::Note GetNote(ZCJoinSplit& params,
const libzcash::SpendingKey& sk,
const CTransaction& tx, size_t js, size_t n) {
ZCNoteDecryption decryptor {sk.viewing_key()};
ZCNoteDecryption decryptor {sk.receiving_key()};
auto hSig = tx.vjoinsplit[js].h_sig(params, tx.joinSplitPubKey);
auto note_pt = libzcash::NotePlaintext::decrypt(
decryptor,

2
src/wallet/asyncrpcoperation_sendmany.cpp

@ -555,7 +555,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
intermediates.insert(std::make_pair(tree.root(), tree)); // chained js are interstitial (found in between block boundaries)
// Decrypt the change note's ciphertext to retrieve some data we need
ZCNoteDecryption decryptor(spendingkey_.viewing_key());
ZCNoteDecryption decryptor(spendingkey_.receiving_key());
auto hSig = prevJoinSplit.h_sig(*pzcashParams, tx_.joinSplitPubKey);
try {
NotePlaintext plaintext = NotePlaintext::decrypt(

8
src/wallet/crypter.cpp

@ -316,14 +316,14 @@ bool CCryptoKeyStore::AddSpendingKey(const libzcash::SpendingKey &sk)
if (!EncryptSecret(vMasterKey, vchSecret, address.GetHash(), vchCryptedSecret))
return false;
if (!AddCryptedSpendingKey(address, sk.viewing_key(), vchCryptedSecret))
if (!AddCryptedSpendingKey(address, sk.receiving_key(), vchCryptedSecret))
return false;
}
return true;
}
bool CCryptoKeyStore::AddCryptedSpendingKey(const libzcash::PaymentAddress &address,
const libzcash::ViewingKey &vk,
const libzcash::ReceivingKey &rk,
const std::vector<unsigned char> &vchCryptedSecret)
{
{
@ -332,7 +332,7 @@ bool CCryptoKeyStore::AddCryptedSpendingKey(const libzcash::PaymentAddress &addr
return false;
mapCryptedSpendingKeys[address] = vchCryptedSecret;
mapNoteDecryptors.insert(std::make_pair(address, ZCNoteDecryption(vk)));
mapNoteDecryptors.insert(std::make_pair(address, ZCNoteDecryption(rk)));
}
return true;
}
@ -384,7 +384,7 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
std::vector<unsigned char> vchCryptedSecret;
if (!EncryptSecret(vMasterKeyIn, vchSecret, address.GetHash(), vchCryptedSecret))
return false;
if (!AddCryptedSpendingKey(address, sk.viewing_key(), vchCryptedSecret))
if (!AddCryptedSpendingKey(address, sk.receiving_key(), vchCryptedSecret))
return false;
}
mapSpendingKeys.clear();

2
src/wallet/crypter.h

@ -201,7 +201,7 @@ public:
}
}
virtual bool AddCryptedSpendingKey(const libzcash::PaymentAddress &address,
const libzcash::ViewingKey &vk,
const libzcash::ReceivingKey &rk,
const std::vector<unsigned char> &vchCryptedSecret);
bool AddSpendingKey(const libzcash::SpendingKey &sk);
bool HaveSpendingKey(const libzcash::PaymentAddress &address) const

2
src/wallet/gtest/test_wallet.cpp

@ -328,7 +328,7 @@ TEST(wallet_tests, GetNoteNullifier) {
auto sk = libzcash::SpendingKey::random();
auto address = sk.address();
auto dec = ZCNoteDecryption(sk.viewing_key());
auto dec = ZCNoteDecryption(sk.receiving_key());
auto wtx = GetValidReceive(sk, 10, true);
auto note = GetNote(sk, wtx, 0, 1);

91
src/wallet/gtest/test_wallet_zkeys.cpp

@ -66,6 +66,53 @@ TEST(wallet_zkeys_tests, store_and_load_zkeys) {
ASSERT_EQ(m.nCreateTime, now);
}
/**
* This test covers methods on CWallet
* AddViewingKey()
* RemoveViewingKey()
* LoadViewingKey()
*/
TEST(wallet_zkeys_tests, StoreAndLoadViewingKeys) {
SelectParams(CBaseChainParams::MAIN);
CWallet wallet;
// wallet should be empty
std::set<libzcash::PaymentAddress> addrs;
wallet.GetPaymentAddresses(addrs);
ASSERT_EQ(0, addrs.size());
// manually add new viewing key to wallet
auto sk = libzcash::SpendingKey::random();
auto vk = sk.viewing_key();
ASSERT_TRUE(wallet.AddViewingKey(vk));
// verify wallet did add it
auto addr = sk.address();
ASSERT_TRUE(wallet.HaveViewingKey(addr));
// and that we don't have the corresponding spending key
ASSERT_FALSE(wallet.HaveSpendingKey(addr));
// verify viewing key stored correctly
libzcash::ViewingKey vkOut;
wallet.GetViewingKey(addr, vkOut);
ASSERT_EQ(vk, vkOut);
// Load a second viewing key into the wallet
auto sk2 = libzcash::SpendingKey::random();
ASSERT_TRUE(wallet.LoadViewingKey(sk2.viewing_key()));
// verify wallet did add it
auto addr2 = sk2.address();
ASSERT_TRUE(wallet.HaveViewingKey(addr2));
ASSERT_FALSE(wallet.HaveSpendingKey(addr2));
// Remove the first viewing key
ASSERT_TRUE(wallet.RemoveViewingKey(vk));
ASSERT_FALSE(wallet.HaveViewingKey(addr));
ASSERT_TRUE(wallet.HaveViewingKey(addr2));
}
/**
* This test covers methods on CWalletDB
* WriteZKey()
@ -138,6 +185,50 @@ TEST(wallet_zkeys_tests, write_zkey_direct_to_db) {
ASSERT_EQ(m.nCreateTime, now);
}
/**
* This test covers methods on CWalletDB
* WriteViewingKey()
*/
TEST(wallet_zkeys_tests, WriteViewingKeyDirectToDB) {
SelectParams(CBaseChainParams::TESTNET);
// Get temporary and unique path for file.
// Note: / operator to append paths
boost::filesystem::path pathTemp = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
boost::filesystem::create_directories(pathTemp);
mapArgs["-datadir"] = pathTemp.string();
bool fFirstRun;
CWallet wallet("wallet-vkey.dat");
ASSERT_EQ(DB_LOAD_OK, wallet.LoadWallet(fFirstRun));
// No default CPubKey set
ASSERT_TRUE(fFirstRun);
// create random viewing key and add it to database directly, bypassing wallet
auto sk = libzcash::SpendingKey::random();
auto vk = sk.viewing_key();
auto addr = sk.address();
int64_t now = GetTime();
CKeyMetadata meta(now);
CWalletDB db("wallet-vkey.dat");
db.WriteViewingKey(vk);
// wallet should not be aware of viewing key
ASSERT_FALSE(wallet.HaveViewingKey(addr));
// load the wallet again
ASSERT_EQ(DB_LOAD_OK, wallet.LoadWallet(fFirstRun));
// wallet can now see the viewing key
ASSERT_TRUE(wallet.HaveViewingKey(addr));
// check key is the same
libzcash::ViewingKey vkOut;
wallet.GetViewingKey(addr, vkOut);
ASSERT_EQ(vk, vkOut);
}
/**

18
src/wallet/rpcdisclosure.cpp

@ -59,7 +59,7 @@ UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp)
"3. \"output_index\" (string, required) \n"
"4. \"message\" (string, optional) \n"
"\nResult:\n"
"\"paymentblob\" (string) Hex string of payment blob\n"
"\"paymentdisclosure\" (string) Hex data string, with \"zpd:\" prefix.\n"
"\nExamples:\n"
+ HelpExampleCli("z_getpaymentdisclosure", "96f12882450429324d5f3b48630e3168220e49ab7b0f066e5c2935a6b88bb0f2 0 0 \"refund\"")
+ HelpExampleRpc("z_getpaymentdisclosure", "\"96f12882450429324d5f3b48630e3168220e49ab7b0f066e5c2935a6b88bb0f2\", 0, 0, \"refund\"")
@ -134,7 +134,7 @@ UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp)
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << pd;
string strHex = HexStr(ss.begin(), ss.end());
return strHex;
return PAYMENT_DISCLOSURE_BLOB_STRING_PREFIX + strHex;
}
@ -160,10 +160,10 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp)
"\nEXPERIMENTAL FEATURE\n"
+ strPaymentDisclosureDisabledMsg +
"\nArguments:\n"
"1. \"paymentdisclosure\" (string, required) Hex data string\n"
"1. \"paymentdisclosure\" (string, required) Hex data string, with \"zpd:\" prefix.\n"
"\nExamples:\n"
+ HelpExampleCli("z_validatepaymentdisclosure", "\"hexblob\"")
+ HelpExampleRpc("z_validatepaymentdisclosure", "\"hexblob\"")
+ HelpExampleCli("z_validatepaymentdisclosure", "\"zpd:706462ff004c561a0447ba2ec51184e6c204...\"")
+ HelpExampleRpc("z_validatepaymentdisclosure", "\"zpd:706462ff004c561a0447ba2ec51184e6c204...\"")
);
if (!fEnablePaymentDisclosure) {
@ -174,7 +174,13 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp)
EnsureWalletIsUnlocked();
string hexInput = params[0].get_str();
// Verify the payment disclosure input begins with "zpd:" prefix.
string strInput = params[0].get_str();
size_t pos = strInput.find(PAYMENT_DISCLOSURE_BLOB_STRING_PREFIX);
if (pos != 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, payment disclosure prefix not found.");
}
string hexInput = strInput.substr(strlen(PAYMENT_DISCLOSURE_BLOB_STRING_PREFIX));
if (!IsHex(hexInput))
{
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected payment disclosure data in hexadecimal format.");

136
src/wallet/rpcdump.cpp

@ -429,7 +429,7 @@ UniValue z_exportwallet(const UniValue& params, bool fHelp)
if (fHelp || params.size() != 1)
throw runtime_error(
"z_exportwallet \"filename\"\n"
"\nExports all wallet keys, for taddr and zaddr, in a human-readable format.\n"
"\nExports all wallet keys, for taddr and zaddr, in a human-readable format. Overwriting an existing file is not permitted.\n"
"\nArguments:\n"
"1. \"filename\" (string, required) The filename, saved in folder set by hushd -exportdir option\n"
"\nResult:\n"
@ -450,7 +450,7 @@ UniValue dumpwallet(const UniValue& params, bool fHelp)
if (fHelp || params.size() != 1)
throw runtime_error(
"dumpwallet \"filename\"\n"
"\nDumps taddr wallet keys in a human-readable format.\n"
"\nDumps taddr wallet keys in a human-readable format. Overwriting an existing file is not permitted.\n"
"\nArguments:\n"
"1. \"filename\" (string, required) The filename, saved in folder set by hushd -exportdir option\n"
"\nResult:\n"
@ -485,6 +485,10 @@ UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys)
}
boost::filesystem::path exportfilepath = exportdir / clean;
if (boost::filesystem::exists(exportfilepath)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot overwrite existing file " + exportfilepath.string());
}
ofstream file;
file.open(exportfilepath.string().c_str());
if (!file.is_open())
@ -645,6 +649,94 @@ UniValue z_importkey(const UniValue& params, bool fHelp)
return NullUniValue;
}
UniValue z_importviewingkey(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return NullUniValue;
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
"z_importviewingkey \"vkey\" ( rescan startHeight )\n"
"\nAdds a viewing key (as returned by z_exportviewingkey) to your wallet.\n"
"\nArguments:\n"
"1. \"vkey\" (string, required) The viewing key (see z_exportviewingkey)\n"
"2. rescan (string, optional, default=\"whenkeyisnew\") Rescan the wallet for transactions - can be \"yes\", \"no\" or \"whenkeyisnew\"\n"
"3. startHeight (numeric, optional, default=0) Block height to start rescan from\n"
"\nNote: This call can take minutes to complete if rescan is true.\n"
"\nExamples:\n"
"\nImport a viewing key\n"
+ HelpExampleCli("z_importviewingkey", "\"vkey\"") +
"\nImport the viewing key without rescan\n"
+ HelpExampleCli("z_importviewingkey", "\"vkey\", no") +
"\nImport the viewing key with partial rescan\n"
+ HelpExampleCli("z_importviewingkey", "\"vkey\" whenkeyisnew 30000") +
"\nRe-import the viewing key with longer partial rescan\n"
+ HelpExampleCli("z_importviewingkey", "\"vkey\" yes 20000") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("z_importviewingkey", "\"vkey\", \"no\"")
);
LOCK2(cs_main, pwalletMain->cs_wallet);
EnsureWalletIsUnlocked();
// Whether to perform rescan after import
bool fRescan = true;
bool fIgnoreExistingKey = true;
if (params.size() > 1) {
auto rescan = params[1].get_str();
if (rescan.compare("whenkeyisnew") != 0) {
fIgnoreExistingKey = false;
if (rescan.compare("no") == 0) {
fRescan = false;
} else if (rescan.compare("yes") != 0) {
throw JSONRPCError(
RPC_INVALID_PARAMETER,
"rescan must be \"yes\", \"no\" or \"whenkeyisnew\"");
}
}
}
// Height to rescan from
int nRescanHeight = 0;
if (params.size() > 2) {
nRescanHeight = params[2].get_int();
}
if (nRescanHeight < 0 || nRescanHeight > chainActive.Height()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
}
string strVKey = params[0].get_str();
CZCViewingKey viewingkey(strVKey);
auto vkey = viewingkey.Get();
auto addr = vkey.address();
{
if (pwalletMain->HaveSpendingKey(addr)) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this viewing key");
}
// Don't throw error in case a viewing key is already there
if (pwalletMain->HaveViewingKey(addr)) {
if (fIgnoreExistingKey) {
return NullUniValue;
}
} else {
pwalletMain->MarkDirty();
if (!pwalletMain->AddViewingKey(vkey)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding viewing key to wallet");
}
}
// We want to scan for transactions and notes
if (fRescan) {
pwalletMain->ScanForWalletTransactions(chainActive[nRescanHeight], true);
}
}
return NullUniValue;
}
UniValue z_exportkey(const UniValue& params, bool fHelp)
{
@ -683,3 +775,43 @@ UniValue z_exportkey(const UniValue& params, bool fHelp)
return spendingkey.ToString();
}
UniValue z_exportviewingkey(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return NullUniValue;
if (fHelp || params.size() != 1)
throw runtime_error(
"z_exportviewingkey \"zaddr\"\n"
"\nReveals the viewing key corresponding to 'zaddr'.\n"
"Then the z_importviewingkey can be used with this output\n"
"\nArguments:\n"
"1. \"zaddr\" (string, required) The zaddr for the viewing key\n"
"\nResult:\n"
"\"vkey\" (string) The viewing key\n"
"\nExamples:\n"
+ HelpExampleCli("z_exportviewingkey", "\"myaddress\"")
+ HelpExampleRpc("z_exportviewingkey", "\"myaddress\"")
);
LOCK2(cs_main, pwalletMain->cs_wallet);
EnsureWalletIsUnlocked();
string strAddress = params[0].get_str();
CZCPaymentAddress address(strAddress);
auto addr = address.Get();
libzcash::ViewingKey vk;
if (!pwalletMain->GetViewingKey(addr, vk)) {
libzcash::SpendingKey k;
if (!pwalletMain->GetSpendingKey(addr, k)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet does not hold private key or viewing key for this zaddr");
}
vk = k.viewing_key();
}
CZCViewingKey viewingkey(vk);
return viewingkey.ToString();
}

90
src/wallet/rpcwallet.cpp

@ -1065,7 +1065,7 @@ UniValue addmultisigaddress(const UniValue& params, bool fHelp)
"\nArguments:\n"
"1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
"2. \"keysobject\" (string, required) A json array of hush addresses or hex-encoded public keys\n"
"2. \"keysobject\" (string, required) A json array of Zcash addresses or hex-encoded public keys\n"
" [\n"
" \"address\" (string) hush address or hex-encoded public key\n"
" ...,\n"
@ -2669,7 +2669,7 @@ UniValue zc_raw_receive(const UniValue& params, bool fHelp)
}
}
ZCNoteDecryption decryptor(k.viewing_key());
ZCNoteDecryption decryptor(k.receiving_key());
NotePlaintext npt = NotePlaintext::decrypt(
decryptor,
@ -2904,6 +2904,7 @@ UniValue zc_raw_keygen(const UniValue& params, bool fHelp)
"Output: {\n"
" \"zcaddress\": zcaddr,\n"
" \"zcsecretkey\": zcsecretkey,\n"
" \"zcviewingkey\": zcviewingkey,\n"
"}\n"
);
}
@ -2912,18 +2913,14 @@ UniValue zc_raw_keygen(const UniValue& params, bool fHelp)
auto addr = k.address();
auto viewing_key = k.viewing_key();
CDataStream viewing(SER_NETWORK, PROTOCOL_VERSION);
viewing << viewing_key;
CZCPaymentAddress pubaddr(addr);
CZCSpendingKey spendingkey(k);
std::string viewing_hex = HexStr(viewing.begin(), viewing.end());
CZCViewingKey viewingkey(viewing_key);
UniValue result(UniValue::VOBJ);
result.push_back(Pair("zcaddress", pubaddr.ToString()));
result.push_back(Pair("zcsecretkey", spendingkey.ToString()));
result.push_back(Pair("zcviewingkey", viewing_hex));
result.push_back(Pair("zcviewingkey", viewingkey.ToString()));
return result;
}
@ -2962,9 +2959,10 @@ UniValue z_listaddresses(const UniValue& params, bool fHelp)
if (fHelp || params.size() > 1)
throw runtime_error(
"z_listaddresses\n"
"z_listaddresses ( includeWatchonly )\n"
"\nReturns the list of zaddr belonging to the wallet.\n"
"\nArguments:\n"
"1. includeWatchonly (bool, optional, default=false) Also include watchonly addresses (see 'z_importviewingkey')\n"
"\nResult:\n"
"[ (json array of string)\n"
" \"zaddr\" (string) a zaddr belonging to the wallet\n"
@ -2977,16 +2975,23 @@ UniValue z_listaddresses(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
bool fIncludeWatchonly = false;
if (params.size() > 0) {
fIncludeWatchonly = params[0].get_bool();
}
UniValue ret(UniValue::VARR);
std::set<libzcash::PaymentAddress> addresses;
pwalletMain->GetPaymentAddresses(addresses);
for (auto addr : addresses ) {
ret.push_back(CZCPaymentAddress(addr).ToString());
if (fIncludeWatchonly || pwalletMain->HaveSpendingKey(addr)) {
ret.push_back(CZCPaymentAddress(addr).ToString());
}
}
return ret;
}
CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1) {
CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ignoreUnspendable=true) {
set<CBitcoinAddress> setAddress;
vector<COutput> vecOutputs;
CAmount balance = 0;
@ -3008,6 +3013,10 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1) {
continue;
}
if (ignoreUnspendable && !out.fSpendable) {
continue;
}
if (setAddress.size()) {
CTxDestination address;
if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
@ -3025,11 +3034,11 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1) {
return balance;
}
CAmount getBalanceZaddr(std::string address, int minDepth = 1) {
CAmount getBalanceZaddr(std::string address, int minDepth = 1, bool ignoreUnspendable=true) {
CAmount balance = 0;
std::vector<CNotePlaintextEntry> entries;
LOCK2(cs_main, pwalletMain->cs_wallet);
pwalletMain->GetFilteredNotes(entries, address, minDepth);
pwalletMain->GetFilteredNotes(entries, address, minDepth, true, ignoreUnspendable);
for (auto & entry : entries) {
balance += CAmount(entry.plaintext.value);
}
@ -3055,6 +3064,9 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
" \"amount\": xxxxx, (numeric) the amount of value in the note\n"
" \"memo\": xxxxx, (string) hexademical string representation of memo field\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("z_listreceivedbyaddress", "\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
+ HelpExampleRpc("z_listreceivedbyaddress", "\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
);
LOCK2(cs_main, pwalletMain->cs_wallet);
@ -3078,14 +3090,14 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr.");
}
if (!pwalletMain->HaveSpendingKey(zaddr)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key not found.");
if (!(pwalletMain->HaveSpendingKey(zaddr) || pwalletMain->HaveViewingKey(zaddr))) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found.");
}
UniValue result(UniValue::VARR);
std::vector<CNotePlaintextEntry> entries;
pwalletMain->GetFilteredNotes(entries, fromaddress, nMinDepth, false);
pwalletMain->GetFilteredNotes(entries, fromaddress, nMinDepth, false, false);
for (CNotePlaintextEntry & entry : entries) {
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("txid",entry.jsop.hash.ToString()));
@ -3107,6 +3119,8 @@ UniValue z_getbalance(const UniValue& params, bool fHelp)
throw runtime_error(
"z_getbalance \"address\" ( minconf )\n"
"\nReturns the balance of a taddr or zaddr belonging to the node’s wallet.\n"
"\nCAUTION: If address is a watch-only zaddr, the returned balance may be larger than the actual balance,"
"\nbecause spends cannot be detected with incoming viewing keys.\n"
"\nArguments:\n"
"1. \"address\" (string) The selected address. It may be a transparent or private address.\n"
"2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
@ -3144,16 +3158,16 @@ UniValue z_getbalance(const UniValue& params, bool fHelp)
} catch (const std::runtime_error&) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
}
if (!pwalletMain->HaveSpendingKey(zaddr)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key not found.");
if (!(pwalletMain->HaveSpendingKey(zaddr) || pwalletMain->HaveViewingKey(zaddr))) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found.");
}
}
CAmount nBalance = 0;
if (fromTaddr) {
nBalance = getBalanceTaddr(fromaddress, nMinDepth);
nBalance = getBalanceTaddr(fromaddress, nMinDepth, false);
} else {
nBalance = getBalanceZaddr(fromaddress, nMinDepth);
nBalance = getBalanceZaddr(fromaddress, nMinDepth, false);
}
return ValueFromAmount(nBalance);
@ -3165,12 +3179,15 @@ UniValue z_gettotalbalance(const UniValue& params, bool fHelp)
if (!EnsureWalletIsAvailable(fHelp))
return NullUniValue;
if (fHelp || params.size() > 1)
if (fHelp || params.size() > 2)
throw runtime_error(
"z_gettotalbalance ( minconf )\n"
"z_gettotalbalance ( minconf includeWatchonly )\n"
"\nReturn the total value of funds stored in the node’s wallet.\n"
"\nCAUTION: If the wallet contains watch-only zaddrs, the returned private balance may be larger than the actual balance,"
"\nbecause spends cannot be detected with incoming viewing keys.\n"
"\nArguments:\n"
"1. minconf (numeric, optional, default=1) Only include private and transparent transactions confirmed at least this many times.\n"
"2. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress' and 'z_importviewingkey')\n"
"\nResult:\n"
"{\n"
" \"transparent\": xxxxx, (numeric) the total balance of transparent funds\n"
@ -3189,19 +3206,24 @@ UniValue z_gettotalbalance(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
int nMinDepth = 1;
if (params.size() == 1) {
if (params.size() > 0) {
nMinDepth = params[0].get_int();
}
if (nMinDepth < 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
}
bool fIncludeWatchonly = false;
if (params.size() > 1) {
fIncludeWatchonly = params[1].get_bool();
}
// getbalance and "getbalance * 1 true" should return the same number
// but they don't because wtx.GetAmounts() does not handle tx where there are no outputs
// pwalletMain->GetBalance() does not accept min depth parameter
// so we use our own method to get balance of utxos.
CAmount nBalance = getBalanceTaddr("", nMinDepth);
CAmount nPrivateBalance = getBalanceZaddr("", nMinDepth);
CAmount nBalance = getBalanceTaddr("", nMinDepth, !fIncludeWatchonly);
CAmount nPrivateBalance = getBalanceZaddr("", nMinDepth, !fIncludeWatchonly);
CAmount nTotalBalance = nBalance + nPrivateBalance;
UniValue result(UniValue::VOBJ);
result.push_back(Pair("transparent", FormatMoney(nBalance)));
@ -3224,6 +3246,9 @@ UniValue z_getoperationresult(const UniValue& params, bool fHelp)
"1. \"operationid\" (array, optional) A list of operation ids we are interested in. If not provided, examine all operations known to the node.\n"
"\nResult:\n"
"\" [object, ...]\" (array) A list of JSON objects\n"
"\nExamples:\n"
+ HelpExampleCli("z_getoperationresult", "'[\"operationid\", ... ]'")
+ HelpExampleRpc("z_getoperationresult", "'[\"operationid\", ... ]'")
);
// This call will remove finished operations
@ -3244,6 +3269,9 @@ UniValue z_getoperationstatus(const UniValue& params, bool fHelp)
"1. \"operationid\" (array, optional) A list of operation ids we are interested in. If not provided, examine all operations known to the node.\n"
"\nResult:\n"
"\" [object, ...]\" (array) A list of JSON objects\n"
"\nExamples:\n"
+ HelpExampleCli("z_getoperationstatus", "'[\"operationid\", ... ]'")
+ HelpExampleRpc("z_getoperationstatus", "'[\"operationid\", ... ]'")
);
// This call is idempotent so we don't want to remove finished operations
@ -3344,6 +3372,9 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
+ strprintf("%s", FormatMoney(ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
"\nResult:\n"
"\"operationid\" (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
"\nExamples:\n"
+ HelpExampleCli("z_sendmany", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" '[{\"address\": \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\" ,\"amount\": 5.0}]'")
+ HelpExampleRpc("z_sendmany", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", [{\"address\": \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\" ,\"amount\": 5.0}]")
);
LOCK2(cs_main, pwalletMain->cs_wallet);
@ -3544,12 +3575,15 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
+ strprintf("%d", SHIELD_COINBASE_DEFAULT_LIMIT) + ") Limit on the maximum number of utxos to shield. Set to 0 to use node option -mempooltxinputlimit.\n"
"\nResult:\n"
"{\n"
" \"operationid\": xxx (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
" \"shieldedUTXOs\": xxx (numeric) Number of coinbase utxos being shielded.\n"
" \"shieldedValue\": xxx (numeric) Value of coinbase utxos being shielded.\n"
" \"remainingUTXOs\": xxx (numeric) Number of coinbase utxos still available for shielding.\n"
" \"remainingValue\": xxx (numeric) Value of coinbase utxos still available for shielding.\n"
" \"shieldingUTXOs\": xxx (numeric) Number of coinbase utxos being shielded.\n"
" \"shieldingValue\": xxx (numeric) Value of coinbase utxos being shielded.\n"
" \"opid\": xxx (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("z_shieldcoinbase", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
+ HelpExampleRpc("z_shieldcoinbase", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
);
LOCK2(cs_main, pwalletMain->cs_wallet);

83
src/wallet/wallet.cpp

@ -107,6 +107,10 @@ bool CWallet::AddZKey(const libzcash::SpendingKey &key)
if (!CCryptoKeyStore::AddSpendingKey(key))
return false;
// check if we need to remove from viewing keys
if (HaveViewingKey(addr))
RemoveViewingKey(key.viewing_key());
if (!fFileBacked)
return true;
@ -190,10 +194,10 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
bool CWallet::AddCryptedSpendingKey(const libzcash::PaymentAddress &address,
const libzcash::ViewingKey &vk,
const libzcash::ReceivingKey &rk,
const std::vector<unsigned char> &vchCryptedSecret)
{
if (!CCryptoKeyStore::AddCryptedSpendingKey(address, vk, vchCryptedSecret))
if (!CCryptoKeyStore::AddCryptedSpendingKey(address, rk, vchCryptedSecret))
return false;
if (!fFileBacked)
return true;
@ -201,12 +205,12 @@ bool CWallet::AddCryptedSpendingKey(const libzcash::PaymentAddress &address,
LOCK(cs_wallet);
if (pwalletdbEncryption) {
return pwalletdbEncryption->WriteCryptedZKey(address,
vk,
rk,
vchCryptedSecret,
mapZKeyMetadata[address]);
} else {
return CWalletDB(strWalletFile).WriteCryptedZKey(address,
vk,
rk,
vchCryptedSecret,
mapZKeyMetadata[address]);
}
@ -236,9 +240,9 @@ bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigne
return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
}
bool CWallet::LoadCryptedZKey(const libzcash::PaymentAddress &addr, const libzcash::ViewingKey &vk, const std::vector<unsigned char> &vchCryptedSecret)
bool CWallet::LoadCryptedZKey(const libzcash::PaymentAddress &addr, const libzcash::ReceivingKey &rk, const std::vector<unsigned char> &vchCryptedSecret)
{
return CCryptoKeyStore::AddCryptedSpendingKey(addr, vk, vchCryptedSecret);
return CCryptoKeyStore::AddCryptedSpendingKey(addr, rk, vchCryptedSecret);
}
bool CWallet::LoadZKey(const libzcash::SpendingKey &key)
@ -246,6 +250,38 @@ bool CWallet::LoadZKey(const libzcash::SpendingKey &key)
return CCryptoKeyStore::AddSpendingKey(key);
}
bool CWallet::AddViewingKey(const libzcash::ViewingKey &vk)
{
if (!CCryptoKeyStore::AddViewingKey(vk)) {
return false;
}
nTimeFirstKey = 1; // No birthday information for viewing keys.
if (!fFileBacked) {
return true;
}
return CWalletDB(strWalletFile).WriteViewingKey(vk);
}
bool CWallet::RemoveViewingKey(const libzcash::ViewingKey &vk)
{
AssertLockHeld(cs_wallet);
if (!CCryptoKeyStore::RemoveViewingKey(vk)) {
return false;
}
if (fFileBacked) {
if (!CWalletDB(strWalletFile).EraseViewingKey(vk)) {
return false;
}
}
return true;
}
bool CWallet::LoadViewingKey(const libzcash::ViewingKey &vk)
{
return CCryptoKeyStore::AddViewingKey(vk);
}
bool CWallet::AddCScript(const CScript& redeemScript)
{
if (!CCryptoKeyStore::AddCScript(redeemScript))
@ -946,7 +982,8 @@ void CWallet::MarkDirty()
}
/**
* Ensure that every note in the wallet has a cached nullifier.
* Ensure that every note in the wallet (for which we possess a spending key)
* has a cached nullifier.
*/
bool CWallet::UpdateNullifierNoteMap()
{
@ -960,16 +997,17 @@ bool CWallet::UpdateNullifierNoteMap()
for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
for (mapNoteData_t::value_type& item : wtxItem.second.mapNoteData) {
if (!item.second.nullifier) {
auto i = item.first.js;
GetNoteDecryptor(item.second.address, dec);
auto hSig = wtxItem.second.vjoinsplit[i].h_sig(
*pzcashParams, wtxItem.second.joinSplitPubKey);
item.second.nullifier = GetNoteNullifier(
wtxItem.second.vjoinsplit[i],
item.second.address,
dec,
hSig,
item.first.n);
if (GetNoteDecryptor(item.second.address, dec)) {
auto i = item.first.js;
auto hSig = wtxItem.second.vjoinsplit[i].h_sig(
*pzcashParams, wtxItem.second.joinSplitPubKey);
item.second.nullifier = GetNoteNullifier(
wtxItem.second.vjoinsplit[i],
item.second.address,
dec,
hSig,
item.first.n);
}
}
}
UpdateNullifierNoteMapWithTx(wtxItem.second);
@ -1231,7 +1269,9 @@ boost::optional<uint256> CWallet::GetNoteNullifier(const JSDescription& jsdesc,
hSig,
(unsigned char) n);
auto note = note_pt.note(address);
// SpendingKeys are only available if the wallet is unlocked
// SpendingKeys are only available if:
// - We have them (this isn't a viewing key)
// - The wallet is unlocked
libzcash::SpendingKey key;
if (GetSpendingKey(address, key)) {
ret = note.nullifier(key);
@ -3608,7 +3648,7 @@ bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee)
* Find notes in the wallet filtered by payment address, min depth and ability to spend.
* These notes are decrypted and added to the output parameter vector, outEntries.
*/
void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, std::string address, int minDepth, bool ignoreSpent)
void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, std::string address, int minDepth, bool ignoreSpent, bool ignoreUnspendable)
{
bool fFilterAddress = false;
libzcash::PaymentAddress filterPaymentAddress;
@ -3646,6 +3686,11 @@ void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, st
continue;
}
// skip notes which cannot be spent
if (ignoreUnspendable && !HaveSpendingKey(pa)) {
continue;
}
int i = jsop.js; // Index into CTransaction.vjoinsplit
int j = jsop.n; // Index into JSDescription.ciphertexts

180
src/wallet/wallet.h

@ -60,7 +60,6 @@ static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000;
// unless there is some exceptional network disruption.
static const unsigned int WITNESS_CACHE_SIZE = COINBASE_MATURITY;
class CAccountingEntry;
class CBlockIndex;
class CCoinControl;
class COutput;
@ -570,6 +569,86 @@ public:
}
};
/**
* Internal transfers.
* Database key is acentry<account><counter>.
*/
class CAccountingEntry
{
public:
std::string strAccount;
CAmount nCreditDebit;
int64_t nTime;
std::string strOtherAccount;
std::string strComment;
mapValue_t mapValue;
int64_t nOrderPos; //! position in ordered transaction list
uint64_t nEntryNo;
CAccountingEntry()
{
SetNull();
}
void SetNull()
{
nCreditDebit = 0;
nTime = 0;
strAccount.clear();
strOtherAccount.clear();
strComment.clear();
nOrderPos = -1;
nEntryNo = 0;
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
if (!(nType & SER_GETHASH))
READWRITE(nVersion);
//! Note: strAccount is serialized as part of the key, not here.
READWRITE(nCreditDebit);
READWRITE(nTime);
READWRITE(LIMITED_STRING(strOtherAccount, 65536));
if (!ser_action.ForRead())
{
WriteOrderPos(nOrderPos, mapValue);
if (!(mapValue.empty() && _ssExtra.empty()))
{
CDataStream ss(nType, nVersion);
ss.insert(ss.begin(), '\0');
ss << mapValue;
ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end());
strComment.append(ss.str());
}
}
READWRITE(LIMITED_STRING(strComment, 65536));
size_t nSepPos = strComment.find("\0", 0, 1);
if (ser_action.ForRead())
{
mapValue.clear();
if (std::string::npos != nSepPos)
{
CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), nType, nVersion);
ss >> mapValue;
_ssExtra = std::vector<char>(ss.begin(), ss.end());
}
ReadOrderPos(nOrderPos, mapValue);
}
if (std::string::npos != nSepPos)
strComment.erase(nSepPos);
mapValue.erase("n");
}
private:
std::vector<char> _ssExtra;
};
/**
@ -871,9 +950,15 @@ public:
//! Load spending key metadata (used by LoadWallet)
bool LoadZKeyMetadata(const libzcash::PaymentAddress &addr, const CKeyMetadata &meta);
//! Adds an encrypted spending key to the store, without saving it to disk (used by LoadWallet)
bool LoadCryptedZKey(const libzcash::PaymentAddress &addr, const libzcash::ViewingKey &vk, const std::vector<unsigned char> &vchCryptedSecret);
bool LoadCryptedZKey(const libzcash::PaymentAddress &addr, const libzcash::ReceivingKey &rk, const std::vector<unsigned char> &vchCryptedSecret);
//! Adds an encrypted spending key to the store, and saves it to disk (virtual method, declared in crypter.h)
bool AddCryptedSpendingKey(const libzcash::PaymentAddress &address, const libzcash::ViewingKey &vk, const std::vector<unsigned char> &vchCryptedSecret);
bool AddCryptedSpendingKey(const libzcash::PaymentAddress &address, const libzcash::ReceivingKey &rk, const std::vector<unsigned char> &vchCryptedSecret);
//! Adds a viewing key to the store, and saves it to disk.
bool AddViewingKey(const libzcash::ViewingKey &vk);
bool RemoveViewingKey(const libzcash::ViewingKey &vk);
//! Adds a viewing key to the store, without saving it to disk (used by LoadWallet)
bool LoadViewingKey(const libzcash::ViewingKey &dest);
/**
* Increment the next transaction order id
@ -1036,7 +1121,11 @@ public:
void SetBroadcastTransactions(bool broadcast) { fBroadcastTransactions = broadcast; }
/* Find notes filtered by payment address, min depth, ability to spend */
void GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, std::string address, int minDepth=1, bool ignoreSpent=true);
void GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries,
std::string address,
int minDepth=1,
bool ignoreSpent=true,
bool ignoreUnspendable=true);
};
@ -1094,87 +1183,4 @@ public:
}
};
/**
* Internal transfers.
* Database key is acentry<account><counter>.
*/
class CAccountingEntry
{
public:
std::string strAccount;
CAmount nCreditDebit;
int64_t nTime;
std::string strOtherAccount;
std::string strComment;
mapValue_t mapValue;
int64_t nOrderPos; //! position in ordered transaction list
uint64_t nEntryNo;
CAccountingEntry()
{
SetNull();
}
void SetNull()
{
nCreditDebit = 0;
nTime = 0;
strAccount.clear();
strOtherAccount.clear();
strComment.clear();
nOrderPos = -1;
nEntryNo = 0;
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
if (!(nType & SER_GETHASH))
READWRITE(nVersion);
//! Note: strAccount is serialized as part of the key, not here.
READWRITE(nCreditDebit);
READWRITE(nTime);
READWRITE(LIMITED_STRING(strOtherAccount, 65536));
if (!ser_action.ForRead())
{
WriteOrderPos(nOrderPos, mapValue);
if (!(mapValue.empty() && _ssExtra.empty()))
{
CDataStream ss(nType, nVersion);
ss.insert(ss.begin(), '\0');
ss << mapValue;
ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end());
strComment.append(ss.str());
}
}
READWRITE(LIMITED_STRING(strComment, 65536));
size_t nSepPos = strComment.find("\0", 0, 1);
if (ser_action.ForRead())
{
mapValue.clear();
if (std::string::npos != nSepPos)
{
CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), nType, nVersion);
ss >> mapValue;
_ssExtra = std::vector<char>(ss.begin(), ss.end());
}
ReadOrderPos(nOrderPos, mapValue);
}
if (std::string::npos != nSepPos)
strComment.erase(nSepPos);
mapValue.erase("n");
}
private:
std::vector<char> _ssExtra;
};
#endif // BITCOIN_WALLET_WALLET_H

42
src/wallet/walletdb.cpp

@ -106,7 +106,7 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey,
}
bool CWalletDB::WriteCryptedZKey(const libzcash::PaymentAddress & addr,
const libzcash::ViewingKey &vk,
const libzcash::ReceivingKey &rk,
const std::vector<unsigned char>& vchCryptedSecret,
const CKeyMetadata &keyMeta)
{
@ -116,7 +116,7 @@ bool CWalletDB::WriteCryptedZKey(const libzcash::PaymentAddress & addr,
if (!Write(std::make_pair(std::string("zkeymeta"), addr), keyMeta))
return false;
if (!Write(std::make_pair(std::string("czkey"), addr), std::make_pair(vk, vchCryptedSecret), false))
if (!Write(std::make_pair(std::string("czkey"), addr), std::make_pair(rk, vchCryptedSecret), false))
return false;
if (fEraseUnencryptedKey)
{
@ -142,6 +142,18 @@ bool CWalletDB::WriteZKey(const libzcash::PaymentAddress& addr, const libzcash::
return Write(std::make_pair(std::string("zkey"), addr), key, false);
}
bool CWalletDB::WriteViewingKey(const libzcash::ViewingKey &vk)
{
nWalletDBUpdated++;
return Write(std::make_pair(std::string("vkey"), vk), '1');
}
bool CWalletDB::EraseViewingKey(const libzcash::ViewingKey &vk)
{
nWalletDBUpdated++;
return Erase(std::make_pair(std::string("vkey"), vk));
}
bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript)
{
nWalletDBUpdated++;
@ -471,6 +483,19 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
// so set the wallet birthday to the beginning of time.
pwallet->nTimeFirstKey = 1;
}
else if (strType == "vkey")
{
libzcash::ViewingKey vk;
ssKey >> vk;
char fYes;
ssValue >> fYes;
if (fYes == '1')
pwallet->LoadViewingKey(vk);
// Viewing keys have no birthday information for now,
// so set the wallet birthday to the beginning of time.
pwallet->nTimeFirstKey = 1;
}
else if (strType == "zkey")
{
libzcash::PaymentAddress addr;
@ -585,14 +610,14 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
libzcash::PaymentAddress addr;
ssKey >> addr;
// Deserialization of a pair is just one item after another
uint256 vkValue;
ssValue >> vkValue;
libzcash::ViewingKey vk(vkValue);
uint256 rkValue;
ssValue >> rkValue;
libzcash::ReceivingKey rk(rkValue);
vector<unsigned char> vchCryptedSecret;
ssValue >> vchCryptedSecret;
wss.nCKeys++;
if (!pwallet->LoadCryptedZKey(addr, vk, vchCryptedSecret))
if (!pwallet->LoadCryptedZKey(addr, rk, vchCryptedSecret))
{
strErr = "Error reading wallet database: LoadCryptedZKey failed";
return false;
@ -694,6 +719,7 @@ static bool IsKeyType(string strType)
{
return (strType== "key" || strType == "wkey" ||
strType == "zkey" || strType == "czkey" ||
strType == "vkey" ||
strType == "mkey" || strType == "ckey");
}
@ -968,11 +994,7 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
pathDest /= wallet.strWalletFile;
try {
#if BOOST_VERSION >= 104000
boost::filesystem::copy_file(pathSrc, pathDest, boost::filesystem::copy_option::overwrite_if_exists);
#else
boost::filesystem::copy_file(pathSrc, pathDest);
#endif
LogPrintf("copied wallet.dat to %s\n", pathDest.string());
return true;
} catch (const boost::filesystem::filesystem_error& e) {

5
src/wallet/walletdb.h

@ -136,10 +136,13 @@ public:
/// Write spending key to wallet database, where key is payment address and value is spending key.
bool WriteZKey(const libzcash::PaymentAddress& addr, const libzcash::SpendingKey& key, const CKeyMetadata &keyMeta);
bool WriteCryptedZKey(const libzcash::PaymentAddress & addr,
const libzcash::ViewingKey & vk,
const libzcash::ReceivingKey & rk,
const std::vector<unsigned char>& vchCryptedSecret,
const CKeyMetadata &keyMeta);
bool WriteViewingKey(const libzcash::ViewingKey &vk);
bool EraseViewingKey(const libzcash::ViewingKey &vk);
private:
CWalletDB(const CWalletDB&);
void operator=(const CWalletDB&);

14
src/zcash/Address.cpp

@ -12,12 +12,20 @@ uint256 PaymentAddress::GetHash() const {
return Hash(ss.begin(), ss.end());
}
uint256 ViewingKey::pk_enc() {
uint256 ReceivingKey::pk_enc() const {
return ZCNoteEncryption::generate_pubkey(*this);
}
PaymentAddress ViewingKey::address() const {
return PaymentAddress(a_pk, sk_enc.pk_enc());
}
ReceivingKey SpendingKey::receiving_key() const {
return ReceivingKey(ZCNoteEncryption::generate_privkey(*this));
}
ViewingKey SpendingKey::viewing_key() const {
return ViewingKey(ZCNoteEncryption::generate_privkey(*this));
return ViewingKey(PRF_addr_a_pk(*this), receiving_key());
}
SpendingKey SpendingKey::random() {
@ -25,7 +33,7 @@ SpendingKey SpendingKey::random() {
}
PaymentAddress SpendingKey::address() const {
return PaymentAddress(PRF_addr_a_pk(*this), viewing_key().pk_enc());
return viewing_key().address();
}
}

42
src/zcash/Address.hpp

@ -1,5 +1,5 @@
#ifndef _ZCADDRESS_H_
#define _ZCADDRESS_H_
#ifndef ZC_ADDRESS_H_
#define ZC_ADDRESS_H_
#include "uint256.h"
#include "uint252.h"
@ -8,6 +8,7 @@
namespace libzcash {
const size_t SerializedPaymentAddressSize = 64;
const size_t SerializedViewingKeySize = 64;
const size_t SerializedSpendingKeySize = 32;
class PaymentAddress {
@ -38,11 +39,39 @@ public:
}
};
class ViewingKey : public uint256 {
class ReceivingKey : public uint256 {
public:
ViewingKey(uint256 sk_enc) : uint256(sk_enc) { }
ReceivingKey() { }
ReceivingKey(uint256 sk_enc) : uint256(sk_enc) { }
uint256 pk_enc();
uint256 pk_enc() const;
};
class ViewingKey {
public:
uint256 a_pk;
ReceivingKey sk_enc;
ViewingKey() : a_pk(), sk_enc() { }
ViewingKey(uint256 a_pk, ReceivingKey sk_enc) : a_pk(a_pk), sk_enc(sk_enc) { }
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(a_pk);
READWRITE(sk_enc);
}
PaymentAddress address() const;
friend inline bool operator==(const ViewingKey& a, const ViewingKey& b) {
return a.a_pk == b.a_pk && a.sk_enc == b.sk_enc;
}
friend inline bool operator<(const ViewingKey& a, const ViewingKey& b) {
return (a.a_pk < b.a_pk ||
(a.a_pk == b.a_pk && a.sk_enc < b.sk_enc));
}
};
class SpendingKey : public uint252 {
@ -52,10 +81,11 @@ public:
static SpendingKey random();
ReceivingKey receiving_key() const;
ViewingKey viewing_key() const;
PaymentAddress address() const;
};
}
#endif // _ZCADDRESS_H_
#endif // ZC_ADDRESS_H_

7
src/zcash/IncrementalMerkleTree.hpp

@ -1,5 +1,5 @@
#ifndef ZCINCREMENTALMERKLETREE_H_
#define ZCINCREMENTALMERKLETREE_H_
#ifndef ZC_INCREMENTALMERKLETREE_H_
#define ZC_INCREMENTALMERKLETREE_H_
#include <deque>
#include <boost/optional.hpp>
@ -202,5 +202,4 @@ typedef libzcash::IncrementalMerkleTree<INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, l
typedef libzcash::IncrementalWitness<INCREMENTAL_MERKLE_TREE_DEPTH, libzcash::SHA256Compress> ZCIncrementalWitness;
typedef libzcash::IncrementalWitness<INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, libzcash::SHA256Compress> ZCTestingIncrementalWitness;
#endif /* ZCINCREMENTALMERKLETREE_H_ */
#endif /* ZC_INCREMENTALMERKLETREE_H_ */

1
src/zcash/JoinSplit.cpp

@ -387,4 +387,3 @@ template class JoinSplit<ZC_NUM_JS_INPUTS,
ZC_NUM_JS_OUTPUTS>;
}

7
src/zcash/JoinSplit.hpp

@ -1,5 +1,5 @@
#ifndef _ZCJOINSPLIT_H_
#define _ZCJOINSPLIT_H_
#ifndef ZC_JOINSPLIT_H_
#define ZC_JOINSPLIT_H_
#include "Zcash.h"
#include "Proof.hpp"
@ -102,5 +102,4 @@ protected:
typedef libzcash::JoinSplit<ZC_NUM_JS_INPUTS,
ZC_NUM_JS_OUTPUTS> ZCJoinSplit;
#endif // _ZCJOINSPLIT_H_
#endif // ZC_JOINSPLIT_H_

6
src/zcash/Note.hpp

@ -1,5 +1,5 @@
#ifndef _ZCNOTE_H_
#define _ZCNOTE_H_
#ifndef ZC_NOTE_H_
#define ZC_NOTE_H_
#include "uint256.h"
#include "Zcash.h"
@ -68,4 +68,4 @@ public:
}
#endif // _ZCNOTE_H_
#endif // ZC_NOTE_H_

1
src/zcash/NoteEncryption.cpp

@ -225,4 +225,3 @@ template class NoteDecryption<ZC_NOTEPLAINTEXT_SIZE>;
template class PaymentDisclosureNoteDecryption<ZC_NOTEPLAINTEXT_SIZE>;
}

1
src/zcash/NoteEncryption.hpp

@ -123,4 +123,3 @@ typedef libzcash::NoteDecryption<ZC_NOTEPLAINTEXT_SIZE> ZCNoteDecryption;
typedef libzcash::PaymentDisclosureNoteDecryption<ZC_NOTEPLAINTEXT_SIZE> ZCPaymentDisclosureNoteDecryption;
#endif /* ZC_NOTE_ENCRYPTION_H_ */

1
src/zcash/Proof.cpp

@ -249,4 +249,3 @@ bool ProofVerifier::check(
}
}

6
src/zcash/Proof.hpp

@ -1,5 +1,5 @@
#ifndef _ZCPROOF_H_
#define _ZCPROOF_H_
#ifndef ZC_PROOF_H_
#define ZC_PROOF_H_
#include "serialize.h"
#include "uint256.h"
@ -274,4 +274,4 @@ public:
}
#endif // _ZCPROOF_H_
#endif // ZC_PROOF_H_

6
src/zcash/Zcash.h

@ -1,5 +1,5 @@
#ifndef _ZCCONSTANTS_H_
#define _ZCCONSTANTS_H_
#ifndef ZC_ZCASH_H_
#define ZC_ZCASH_H_
#define ZC_NUM_JS_INPUTS 2
#define ZC_NUM_JS_OUTPUTS 2
@ -14,4 +14,4 @@
#define ZC_NOTEPLAINTEXT_SIZE (ZC_NOTEPLAINTEXT_LEADING + ZC_V_SIZE + ZC_RHO_SIZE + ZC_R_SIZE + ZC_MEMO_SIZE)
#endif // _ZCCONSTANTS_H_
#endif // ZC_ZCASH_H_

6
src/zcash/prf.h

@ -3,8 +3,8 @@ Zcash uses SHA256Compress as a PRF for various components
within the zkSNARK circuit.
*/
#ifndef _PRF_H_
#define _PRF_H_
#ifndef ZC_PRF_H_
#define ZC_PRF_H_
#include "uint256.h"
#include "uint252.h"
@ -15,4 +15,4 @@ uint256 PRF_nf(const uint252& a_sk, const uint256& rho);
uint256 PRF_pk(const uint252& a_sk, size_t i0, const uint256& h_sig);
uint256 PRF_rho(const uint252& phi, size_t i0, const uint256& h_sig);
#endif // _PRF_H_
#endif // ZC_PRF_H_

6
src/zcash/util.h

@ -1,5 +1,5 @@
#ifndef __ZCASH_UTIL_H
#define __ZCASH_UTIL_H
#ifndef ZC_UTIL_H_
#define ZC_UTIL_H_
#include <vector>
#include <cstdint>
@ -8,4 +8,4 @@ std::vector<unsigned char> convertIntToVectorLE(const uint64_t val_int);
std::vector<bool> convertBytesVectorToVector(const std::vector<unsigned char>& bytes);
uint64_t convertVectorToInt(const std::vector<bool>& v);
#endif // __ZCASH_UTIL_H
#endif // ZC_UTIL_H_

2
zcutil/build-debian-package.sh

@ -71,4 +71,4 @@ fakeroot dpkg-deb --build $BUILD_DIR
cp $BUILD_PATH/$PACKAGE_NAME-$PACKAGE_VERSION-amd64.deb $SRC_PATH
# Analyze with Lintian, reporting bugs and policy violations
lintian -i $SRC_PATH/$PACKAGE_NAME-$PACKAGE_VERSION-amd64.deb
exit 0
exit 0

2
zcutil/cleanup-tags.sh

@ -23,4 +23,4 @@ do
[ "$i" -ge "$MAXJOBS" ] && wait -n
done
wait
wait

2
zcutil/fetch-params.sh

@ -164,4 +164,4 @@ EOF
main
rm -f /tmp/fetch_params.lock
exit 0
exit 0

57
zcutil/make-release.py

@ -26,6 +26,7 @@ def main(args=sys.argv[1:]):
main_logged(
opts.RELEASE_VERSION,
opts.RELEASE_PREV,
opts.RELEASE_FROM,
opts.RELEASE_HEIGHT,
opts.HOTFIX,
)
@ -61,6 +62,11 @@ def parse_args(args):
type=Version.parse_arg,
help='The previously released version.',
)
p.add_argument(
'RELEASE_FROM',
type=Version.parse_arg,
help='The previously released non-beta non-RC version. May be the same as RELEASE_PREV.',
)
p.add_argument(
'RELEASE_HEIGHT',
type=int,
@ -70,8 +76,8 @@ def parse_args(args):
# Top-level flow:
def main_logged(release, releaseprev, releaseheight, hotfix):
verify_releaseprev_tag(releaseprev)
def main_logged(release, releaseprev, releasefrom, releaseheight, hotfix):
verify_tags(releaseprev, releasefrom)
verify_version(release, releaseprev, hotfix)
initialize_git(release, hotfix)
patch_version_in_files(release, releaseprev)
@ -82,7 +88,7 @@ def main_logged(release, releaseprev, releaseheight, hotfix):
gen_manpages()
commit('Updated manpages for {}.'.format(release.novtext))
gen_release_notes(release)
gen_release_notes(release, releasefrom)
update_debian_changelog(release)
commit(
'Updated release notes and changelog for {}.'.format(
@ -101,8 +107,8 @@ def phase(message):
return deco
@phase('Checking RELEASE_PREV tag.')
def verify_releaseprev_tag(releaseprev):
@phase('Checking tags.')
def verify_tags(releaseprev, releasefrom):
candidates = []
# Any tag beginning with a 'v' followed by [1-9] must be a version
@ -130,6 +136,31 @@ def verify_releaseprev_tag(releaseprev):
),
)
candidates.reverse()
prev_tags = []
for candidate in candidates:
if releasefrom == candidate:
break
else:
prev_tags.append(candidate)
else:
raise SystemExit(
'{} does not appear in `git tag --list`'
.format(
releasefrom.vtext,
),
)
for tag in prev_tags:
if not tag.betarc:
raise SystemExit(
'{} appears to be a more recent non-beta non-RC release than {}'
.format(
tag.vtext,
releasefrom.vtext,
),
)
@phase('Checking version.')
def verify_version(release, releaseprev, hotfix):
@ -238,8 +269,18 @@ def gen_manpages():
@phase('Generating release notes.')
def gen_release_notes(release):
sh_log('python', './zcutil/release-notes.py', '--version', release.novtext)
def gen_release_notes(release, releasefrom):
release_notes = [
'python',
'./zcutil/release-notes.py',
'--version',
release.novtext,
'--prev',
releasefrom.vtext,
]
if not release.betarc:
release_notes.append('--clear')
sh_log(*release_notes)
sh_log(
'git',
'add',
@ -625,4 +666,4 @@ if __name__ == '__main__':
sys.argv = actualargs
print '=== Running ==='
main()
main()

41
zcutil/release-notes.py

@ -70,6 +70,10 @@ def document_authors():
f.write('Zcash Contributors\n==================\n\n')
total_contrib = {}
for notes in os.listdir(os.path.join(doc_dir, 'release-notes')):
# Commits are duplicated across beta, RC and final release notes,
# except for the pre-launch release notes.
if ('-beta' in notes or '-rc' in notes) and '1.0.0-' not in notes:
continue
authors = authors_in_release_notes(notes)
for author in authors:
commits = int(authors[author])
@ -83,11 +87,15 @@ def document_authors():
f.write("{0} ({1})\n".format(n, c))
## Writes release note to ./doc/release-notes based on git shortlog when current version number is specified
def generate_release_note(version, filename):
def generate_release_note(version, prev, clear):
filename = 'release-notes-{0}.md'.format(version)
print "Automatically generating release notes for {0} from git shortlog. Should review {1} for accuracy.".format(version, filename)
# fetches latest tags, so that latest_tag will be correct
subprocess.Popen(['git fetch -t'], shell=True, stdout=subprocess.PIPE).communicate()[0]
latest_tag = subprocess.Popen(['git describe --abbrev=0'], shell=True, stdout=subprocess.PIPE).communicate()[0].strip()
if prev:
latest_tag = prev
else:
# fetches latest tags, so that latest_tag will be correct
subprocess.Popen(['git fetch -t'], shell=True, stdout=subprocess.PIPE).communicate()[0]
latest_tag = subprocess.Popen(['git describe --abbrev=0'], shell=True, stdout=subprocess.PIPE).communicate()[0].strip()
print "Previous release tag: ", latest_tag
notes = subprocess.Popen(['git shortlog --no-merges {0}..HEAD'.format(latest_tag)], shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE).communicate()[0]
lines = notes.split('\n')
@ -100,30 +108,35 @@ def generate_release_note(version, filename):
notable_changes = notable_changes[3:] + ['\n']
else:
notable_changes = []
release_note = os.path.join(doc_dir, 'release-notes', 'release-notes-{0}.md'.format(version))
release_note = os.path.join(doc_dir, 'release-notes', filename)
with open(release_note, 'w') as f:
f.writelines(notable_changes)
f.writelines(RELEASE_NOTES_CHANGELOG_HEADING)
f.writelines('\n'.join(lines))
# Clear temporary release notes file
with open(temp_release_note, 'w') as f:
f.writelines(TEMP_RELEASE_NOTES_HEADER)
if clear:
# Clear temporary release notes file
with open(temp_release_note, 'w') as f:
f.writelines(TEMP_RELEASE_NOTES_HEADER)
def main(version, filename):
def main(version, prev, clear):
if version != None:
generate_release_note(version, filename)
generate_release_note(version, prev, clear)
document_authors()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('--version')
parser.add_argument('--version', help='Upcoming version, without leading v')
parser.add_argument('--prev', help='Previous version, with leading v')
parser.add_argument('--clear', help='Wipe doc/release-notes.md', action='store_true')
args = parser.parse_args()
root_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
doc_dir = os.path.join(root_dir, 'doc')
version = None
filename = None
prev = None
clear = False
if args.version:
version = args.version
filename = 'release-notes-{0}.md'.format(version)
main(version, filename)
prev = args.prev
clear = args.clear
main(version, prev, clear)

Loading…
Cancel
Save