Browse Source

WIP: Merge zcash 1.0.15

pull/125/head
FireMartZ 6 years ago
parent
commit
649bd1a633
  1. 4
      .gitignore
  2. 101
      Makefile.am
  3. 2
      README.md
  4. 4
      configure.ac
  5. 20
      depends/packages/googlemock.mk
  6. 6
      depends/packages/libsodium.mk
  7. 8
      qa/pull-tester/rpc-tests.sh
  8. 91
      qa/rpc-tests/mempool_coinbase_spends.py
  9. 119
      qa/rpc-tests/mempool_nu_activation.py
  10. 187
      qa/rpc-tests/mempool_tx_expiry.py
  11. 117
      qa/rpc-tests/overwinter_peer_management.py
  12. 86
      qa/rpc-tests/reorg_limit.py
  13. 144
      qa/rpc-tests/wallet_overwintertx.py
  14. 2
      qa/rpc-tests/wallet_protectcoinbase.py
  15. 1
      qa/rpc-tests/wallet_shieldcoinbase.py
  16. 37
      share/certs/BitcoinFoundation_Apple_Cert.pem
  17. 37
      share/certs/BitcoinFoundation_Comodo_Cert.pem
  18. 46
      share/certs/PrivateKeyNotes.md
  19. BIN
      share/pixmaps/addressbook16.bmp
  20. BIN
      share/pixmaps/addressbook16mask.bmp
  21. BIN
      share/pixmaps/addressbook20.bmp
  22. BIN
      share/pixmaps/addressbook20mask.bmp
  23. BIN
      share/pixmaps/bitcoin-bc.ico
  24. BIN
      share/pixmaps/bitcoin.ico
  25. BIN
      share/pixmaps/bitcoin128.png
  26. 384
      share/pixmaps/bitcoin128.xpm
  27. BIN
      share/pixmaps/bitcoin16.png
  28. 181
      share/pixmaps/bitcoin16.xpm
  29. BIN
      share/pixmaps/bitcoin256.png
  30. 465
      share/pixmaps/bitcoin256.xpm
  31. BIN
      share/pixmaps/bitcoin32.png
  32. 140
      share/pixmaps/bitcoin32.xpm
  33. BIN
      share/pixmaps/bitcoin64.png
  34. 242
      share/pixmaps/bitcoin64.xpm
  35. BIN
      share/pixmaps/check.ico
  36. BIN
      share/pixmaps/favicon.ico
  37. BIN
      share/pixmaps/nsis-header.bmp
  38. BIN
      share/pixmaps/nsis-wizard.bmp
  39. BIN
      share/pixmaps/send16.bmp
  40. BIN
      share/pixmaps/send16mask.bmp
  41. BIN
      share/pixmaps/send16masknoshadow.bmp
  42. BIN
      share/pixmaps/send20.bmp
  43. BIN
      share/pixmaps/send20mask.bmp
  44. 179
      share/setup.nsi.in
  45. 15
      share/ui.rc
  46. 20
      src/Makefile.am
  47. 1
      src/Makefile.gtest.include
  48. 71
      src/bitcoin-tx.cpp
  49. 24
      src/chain.h
  50. 185
      src/chainparams.cpp
  51. 18
      src/chainparams.h
  52. 5
      src/chainparamsbase.cpp
  53. 9
      src/checkpoints.h
  54. 2
      src/clientversion.h
  55. 8
      src/consensus/consensus.h
  56. 49
      src/consensus/params.h
  57. 124
      src/consensus/upgrades.cpp
  58. 90
      src/consensus/upgrades.h
  59. 173
      src/gtest/test_upgrades.cpp
  60. 43
      src/hash.h
  61. 53
      src/init.cpp
  62. 25
      src/key.cpp
  63. 24
      src/key.h
  64. 595
      src/main.cpp
  65. 66
      src/main.h
  66. 21
      src/miner.cpp
  67. 29
      src/net.cpp
  68. 2
      src/net.h
  69. 50
      src/primitives/transaction.cpp
  70. 98
      src/primitives/transaction.h
  71. 4
      src/protocol.h
  72. 4
      src/pubkey.cpp
  73. 31
      src/pubkey.h
  74. 63
      src/rpcblockchain.cpp
  75. 4
      src/rpcclient.cpp
  76. 27
      src/rpcnet.cpp
  77. 56
      src/rpcrawtransaction.cpp
  78. 2
      src/rpcserver.cpp
  79. 2
      src/rpcserver.h
  80. 173
      src/script/interpreter.cpp
  81. 53
      src/script/interpreter.h
  82. 2
      src/script/sigcache.h
  83. 241
      src/script/sign.cpp
  84. 54
      src/script/sign.h
  85. 13
      src/script/zcashconsensus.cpp
  86. 2
      src/script/zcashconsensus.h
  87. 134
      src/snark/Makefile
  88. 0
      src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.cpp
  89. 0
      src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.hpp
  90. 0
      src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.cpp
  91. 0
      src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.hpp
  92. 0
      src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_init.cpp
  93. 0
      src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_init.hpp
  94. 0
      src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pairing.cpp
  95. 0
      src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pairing.hpp
  96. 0
      src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pp.cpp
  97. 0
      src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pp.hpp
  98. 0
      src/snark/libsnark/algebra/curves/curve_utils.hpp
  99. 0
      src/snark/libsnark/algebra/curves/curve_utils.tcc
  100. 0
      src/snark/libsnark/algebra/curves/public_params.hpp
  101. 0
      src/snark/libsnark/algebra/curves/tests/test_bilinearity.cpp
  102. 0
      src/snark/libsnark/algebra/curves/tests/test_groups.cpp
  103. 0
      src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain.hpp
  104. 0
      src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain.tcc
  105. 0
      src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain_aux.hpp
  106. 0
      src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain_aux.tcc
  107. 0
      src/snark/libsnark/algebra/evaluation_domain/evaluation_domain.hpp
  108. 0
      src/snark/libsnark/algebra/evaluation_domain/evaluation_domain.tcc
  109. 0
      src/snark/libsnark/algebra/exponentiation/exponentiation.hpp
  110. 0
      src/snark/libsnark/algebra/exponentiation/exponentiation.tcc
  111. 0
      src/snark/libsnark/algebra/fields/bigint.hpp
  112. 5
      src/snark/libsnark/algebra/fields/bigint.tcc
  113. 0
      src/snark/libsnark/algebra/fields/field_utils.hpp
  114. 0
      src/snark/libsnark/algebra/fields/field_utils.tcc
  115. 0
      src/snark/libsnark/algebra/fields/fp.hpp
  116. 0
      src/snark/libsnark/algebra/fields/fp.tcc
  117. 0
      src/snark/libsnark/algebra/fields/fp12_2over3over2.hpp
  118. 0
      src/snark/libsnark/algebra/fields/fp12_2over3over2.tcc
  119. 0
      src/snark/libsnark/algebra/fields/fp2.hpp
  120. 0
      src/snark/libsnark/algebra/fields/fp2.tcc
  121. 0
      src/snark/libsnark/algebra/fields/fp6_3over2.hpp
  122. 0
      src/snark/libsnark/algebra/fields/fp6_3over2.tcc
  123. 0
      src/snark/libsnark/algebra/fields/fp_aux.tcc
  124. 0
      src/snark/libsnark/algebra/fields/tests/test_bigint.cpp
  125. 0
      src/snark/libsnark/algebra/fields/tests/test_fields.cpp
  126. 0
      src/snark/libsnark/algebra/knowledge_commitment/knowledge_commitment.hpp
  127. 0
      src/snark/libsnark/algebra/knowledge_commitment/knowledge_commitment.tcc
  128. 0
      src/snark/libsnark/algebra/scalar_multiplication/kc_multiexp.hpp
  129. 0
      src/snark/libsnark/algebra/scalar_multiplication/kc_multiexp.tcc
  130. 0
      src/snark/libsnark/algebra/scalar_multiplication/multiexp.hpp
  131. 0
      src/snark/libsnark/algebra/scalar_multiplication/multiexp.tcc
  132. 0
      src/snark/libsnark/algebra/scalar_multiplication/wnaf.hpp
  133. 0
      src/snark/libsnark/algebra/scalar_multiplication/wnaf.tcc
  134. 0
      src/snark/libsnark/common/assert_except.hpp
  135. 0
      src/snark/libsnark/common/data_structures/accumulation_vector.hpp
  136. 0
      src/snark/libsnark/common/data_structures/accumulation_vector.tcc
  137. 0
      src/snark/libsnark/common/data_structures/merkle_tree.hpp
  138. 0
      src/snark/libsnark/common/data_structures/merkle_tree.tcc
  139. 0
      src/snark/libsnark/common/data_structures/sparse_vector.hpp
  140. 0
      src/snark/libsnark/common/data_structures/sparse_vector.tcc
  141. 0
      src/snark/libsnark/common/default_types/ec_pp.hpp
  142. 0
      src/snark/libsnark/common/default_types/r1cs_ppzksnark_pp.hpp
  143. 0
      src/snark/libsnark/common/profiling.cpp
  144. 0
      src/snark/libsnark/common/profiling.hpp
  145. 0
      src/snark/libsnark/common/serialization.hpp
  146. 0
      src/snark/libsnark/common/serialization.tcc
  147. 0
      src/snark/libsnark/common/template_utils.hpp
  148. 0
      src/snark/libsnark/common/utils.cpp
  149. 0
      src/snark/libsnark/common/utils.hpp
  150. 0
      src/snark/libsnark/common/utils.tcc
  151. 0
      src/snark/libsnark/gadgetlib1/constraint_profiling.cpp
  152. 0
      src/snark/libsnark/gadgetlib1/constraint_profiling.hpp
  153. 0
      src/snark/libsnark/gadgetlib1/examples/simple_example.hpp
  154. 0
      src/snark/libsnark/gadgetlib1/examples/simple_example.tcc
  155. 0
      src/snark/libsnark/gadgetlib1/gadget.hpp
  156. 0
      src/snark/libsnark/gadgetlib1/gadget.tcc
  157. 0
      src/snark/libsnark/gadgetlib1/gadgets/basic_gadgets.hpp
  158. 0
      src/snark/libsnark/gadgetlib1/gadgets/basic_gadgets.tcc
  159. 0
      src/snark/libsnark/gadgetlib1/gadgets/gadget_from_r1cs.hpp
  160. 0
      src/snark/libsnark/gadgetlib1/gadgets/gadget_from_r1cs.tcc
  161. 0
      src/snark/libsnark/gadgetlib1/gadgets/hashes/digest_selector_gadget.hpp
  162. 0
      src/snark/libsnark/gadgetlib1/gadgets/hashes/digest_selector_gadget.tcc
  163. 0
      src/snark/libsnark/gadgetlib1/gadgets/hashes/hash_io.hpp
  164. 0
      src/snark/libsnark/gadgetlib1/gadgets/hashes/hash_io.tcc
  165. 0
      src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_aux.hpp
  166. 0
      src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_aux.tcc
  167. 0
      src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_components.hpp
  168. 0
      src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_components.tcc
  169. 0
      src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp
  170. 0
      src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.tcc
  171. 0
      src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/generate_sha256_gadget_tests.py
  172. 0
      src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/pypy_sha256.py
  173. 0
      src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/test_sha256_gadget.cpp
  174. 0
      src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.hpp
  175. 0
      src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.tcc
  176. 0
      src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp
  177. 0
      src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.tcc
  178. 0
      src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.hpp
  179. 0
      src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.tcc
  180. 0
      src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/tests/test_merkle_tree_gadgets.cpp
  181. 0
      src/snark/libsnark/gadgetlib1/pb_variable.hpp
  182. 0
      src/snark/libsnark/gadgetlib1/pb_variable.tcc
  183. 0
      src/snark/libsnark/gadgetlib1/protoboard.hpp
  184. 0
      src/snark/libsnark/gadgetlib1/protoboard.tcc
  185. 0
      src/snark/libsnark/gtests.cpp
  186. 0
      src/snark/libsnark/reductions/r1cs_to_qap/r1cs_to_qap.hpp
  187. 0
      src/snark/libsnark/reductions/r1cs_to_qap/r1cs_to_qap.tcc
  188. 0
      src/snark/libsnark/relations/arithmetic_programs/qap/qap.hpp
  189. 0
      src/snark/libsnark/relations/arithmetic_programs/qap/qap.tcc
  190. 0
      src/snark/libsnark/relations/arithmetic_programs/qap/tests/test_qap.cpp
  191. 0
      src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.hpp
  192. 0
      src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.tcc
  193. 0
      src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/r1cs.hpp
  194. 0
      src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/r1cs.tcc
  195. 0
      src/snark/libsnark/relations/variable.hpp
  196. 0
      src/snark/libsnark/relations/variable.tcc
  197. 0
      src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.hpp
  198. 0
      src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.tcc
  199. 0
      src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/profiling/profile_r1cs_ppzksnark.cpp
  200. 0
      src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp
  201. 0
      src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.tcc
  202. 0
      src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark_params.hpp
  203. 0
      src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp
  204. 6
      src/txdb.cpp
  205. 4
      src/txdb.h
  206. 151
      src/txmempool.cpp
  207. 58
      src/txmempool.h
  208. 15
      src/utilstrencodings.cpp
  209. 2
      src/utilstrencodings.h
  210. 8
      src/utiltest.cpp
  211. 6
      src/version.h
  212. 13
      src/wallet/asyncrpcoperation_sendmany.cpp
  213. 3
      src/wallet/asyncrpcoperation_sendmany.h
  214. 12
      src/wallet/asyncrpcoperation_shieldcoinbase.cpp
  215. 2
      src/wallet/asyncrpcoperation_shieldcoinbase.h
  216. 33
      src/wallet/gtest/test_wallet.cpp
  217. 1
      src/wallet/rpcdisclosure.cpp
  218. 12
      src/wallet/rpcdump.cpp
  219. 381
      src/wallet/rpcwallet.cpp
  220. 64
      src/wallet/wallet.cpp
  221. 5
      src/wallet/wallet.h
  222. 1
      src/wallet/wallet_ismine.cpp
  223. 36
      src/zcbenchmarks.cpp
  224. 2
      src/zcbenchmarks.h

4
.gitignore

@ -8,9 +8,7 @@ src/hush-gtest
src/hush-tx
src/test/test_bitcoin
# Zcash utilities
src/zcash/GenerateParams
src/zcash/CreateJoinSplit
# Hush utilities
src/hush/GenerateParams
src/hush/CreateJoinSplit

101
Makefile.am

@ -15,33 +15,13 @@ endif
BITCOIND_BIN=$(top_builddir)/src/$(BITCOIN_DAEMON_NAME)$(EXEEXT)
BITCOIN_CLI_BIN=$(top_builddir)/src/$(BITCOIN_CLI_NAME)$(EXEEXT)
WALLET_UTILITY_BIN=$(top_builddir)/src/wallet-utility$(EXEEXT)
BITCOIN_WIN_INSTALLER=$(PACKAGE)-$(PACKAGE_VERSION)-win$(WINDOWS_BITS)-setup$(EXEEXT)
##OSX_APP=Bitcoin-Qt.app
##OSX_DMG=Bitcoin-Core.dmg
##OSX_BACKGROUND_IMAGE=background.tiff
##OSX_DEPLOY_SCRIPT=$(top_srcdir)/contrib/macdeploy/macdeployqtplus
##OSX_FANCY_PLIST=$(top_srcdir)/contrib/macdeploy/fancy.plist
##OSX_BASE_LPROJ_DIR=$(top_srcdir)/contrib/macdeploy/Base.lproj/InfoPlist.strings
##OSX_INSTALLER_ICONS=$(top_srcdir)/src/qt/res/icons/bitcoin.icns
##OSX_PLIST=$(top_srcdir)/share/qt/Info.plist #not installed
##OSX_QT_TRANSLATIONS = da,de,es,hu,ru,uk,zh_CN,zh_TW
DIST_DOCS = $(wildcard doc/*.md) $(wildcard doc/release-notes/*.md)
BIN_CHECKS=$(top_srcdir)/contrib/devtools/symbol-check.py \
$(top_srcdir)/contrib/devtools/security-check.py
WINDOWS_PACKAGING = $(top_srcdir)/share/pixmaps/bitcoin.ico \
$(top_srcdir)/share/pixmaps/nsis-header.bmp \
$(top_srcdir)/share/pixmaps/nsis-wizard.bmp
##OSX_PACKAGING = $(OSX_DEPLOY_SCRIPT) $(OSX_FANCY_PLIST) $(OSX_INSTALLER_ICONS) $(OSX_BASE_LPROJ_DIR) \
## $(top_srcdir)/contrib/macdeploy/$(OSX_BACKGROUND_IMAGE) \
## $(top_srcdir)/contrib/macdeploy/DS_Store \
## $(top_srcdir)/contrib/macdeploy/detached-sig-apply.sh \
## $(top_srcdir)/contrib/macdeploy/detached-sig-create.sh
COVERAGE_INFO = baseline_filtered_combined.info baseline.info \
leveldb_baseline.info test_bitcoin_filtered.info total_coverage.info \
baseline_filtered.info \
@ -61,85 +41,9 @@ distcheck-hook:
distcleancheck:
@:
$(BITCOIN_WIN_INSTALLER): all-recursive
$(MKDIR_P) $(top_builddir)/release
STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIND_BIN) $(top_builddir)/release
STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIN_CLI_BIN) $(top_builddir)/release
STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(WALLET_UTILITY_BIN) $(top_builddir)/release
@test -f $(MAKENSIS) && $(MAKENSIS) -V2 $(top_builddir)/share/setup.nsi || \
echo error: could not build $@
@echo built $@
$(if $(findstring src/,$(MAKECMDGOALS)),$(MAKECMDGOALS), none): FORCE
$(MAKE) -C src $(patsubst src/%,%,$@)
##$(OSX_APP)/Contents/PkgInfo:
## $(MKDIR_P) $(@D)
## @echo "APPL????" > $@
##
##$(OSX_APP)/Contents/Resources/empty.lproj:
## $(MKDIR_P) $(@D)
## @touch $@
##
##$(OSX_APP)/Contents/Info.plist: $(OSX_PLIST)
## $(MKDIR_P) $(@D)
## $(INSTALL_DATA) $< $@
##
##$(OSX_APP)/Contents/Resources/bitcoin.icns: $(OSX_INSTALLER_ICONS)
## $(MKDIR_P) $(@D)
## $(INSTALL_DATA) $< $@
##
##$(OSX_APP)/Contents/MacOS/Bitcoin-Qt: $(BITCOIN_QT_BIN)
## $(MKDIR_P) $(@D)
## STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $< $@
##
##$(OSX_APP)/Contents/Resources/Base.lproj/InfoPlist.strings: $(OSX_BASE_LPROJ_DIR)
## $(MKDIR_P) $(@D)
## $(INSTALL_DATA) $< $@
##
##OSX_APP_BUILT=$(OSX_APP)/Contents/PkgInfo $(OSX_APP)/Contents/Resources/empty.lproj \
## $(OSX_APP)/Contents/Resources/bitcoin.icns $(OSX_APP)/Contents/Info.plist \
## $(OSX_APP)/Contents/MacOS/Bitcoin-Qt $(OSX_APP)/Contents/Resources/Base.lproj/InfoPlist.strings
##
##if BUILD_DARWIN
##$(OSX_DMG): $(OSX_APP_BUILT) $(OSX_PACKAGING)
## $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -add-qt-tr $(OSX_QT_TRANSLATIONS) -translations-dir=$(QT_TRANSLATION_DIR) -dmg -fancy $(OSX_FANCY_PLIST) -verbose 2
##
##deploydir: $(OSX_DMG)
##else
##APP_DIST_DIR=$(top_builddir)/dist
##APP_DIST_EXTRAS=$(APP_DIST_DIR)/.background/$(OSX_BACKGROUND_IMAGE) $(APP_DIST_DIR)/.DS_Store $(APP_DIST_DIR)/Applications
##
##$(APP_DIST_DIR)/Applications:
## @rm -f $@
## @cd $(@D); $(LN_S) /Applications $(@F)
##
##$(APP_DIST_EXTRAS): $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt
##
##$(OSX_DMG): $(APP_DIST_EXTRAS)
## $(GENISOIMAGE) -no-cache-inodes -D -l -probe -V "Bitcoin-Core" -no-pad -r -apple -o $@ dist
##
##$(APP_DIST_DIR)/.background/$(OSX_BACKGROUND_IMAGE): contrib/macdeploy/$(OSX_BACKGROUND_IMAGE)
## $(MKDIR_P) $(@D)
## $(INSTALL) $< $@
##$(APP_DIST_DIR)/.DS_Store: contrib/macdeploy/DS_Store
## $(INSTALL) $< $@
##
##$(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt: $(OSX_APP_BUILT) $(OSX_PACKAGING)
## INSTALLNAMETOOL=$(INSTALLNAMETOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -translations-dir=$(QT_TRANSLATION_DIR) -add-qt-tr $(OSX_QT_TRANSLATIONS) -verbose 2
##
##deploydir: $(APP_DIST_EXTRAS)
##endif
##
##if TARGET_DARWIN
##appbundle: $(OSX_APP_BUILT)
##deploy: $(OSX_DMG)
##endif
if TARGET_WINDOWS
deploy: $(BITCOIN_WIN_INSTALLER)
endif
$(BITCOIND_BIN): FORCE
$(MAKE) -C src $(@F)
@ -255,11 +159,10 @@ EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.sh qa/pull
install-exec-hook:
mv $(DESTDIR)$(bindir)/fetch-params.sh $(DESTDIR)$(bindir)/hush-fetch-params
CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER)
.INTERMEDIATE: $(COVERAGE_INFO)
DISTCHECK_CONFIGURE_FLAGS = --enable-man
clean-local:
rm -rf test_bitcoin.coverage/ zcash-gtest.coverage/ total.coverage/ $(OSX_APP)
rm -rf test_bitcoin.coverage/ zcash-gtest.coverage/ total.coverage/

2
README.md

@ -1,4 +1,4 @@
# HUSH 1.0.14
# HUSH 1.0.15
## What is HUSH?

4
configure.ac

@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
AC_PREREQ([2.60])
define(_CLIENT_VERSION_MAJOR, 1)
define(_CLIENT_VERSION_MINOR, 0)
define(_CLIENT_VERSION_REVISION, 14)
define(_CLIENT_VERSION_REVISION, 15)
define(_CLIENT_VERSION_BUILD, 50)
define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50)))
define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1)))
@ -876,7 +876,7 @@ AC_SUBST(GMPXX_LIBS)
AC_SUBST(LIBSNARK_DEPINST)
AC_SUBST(LIBZCASH_LIBS)
AC_SUBST(PROTON_LIBS)
AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi src/test/buildenv.py])
AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile src/test/buildenv.py])
AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh])
AC_CONFIG_FILES([qa/pull-tester/tests-config.sh],[chmod +x qa/pull-tester/tests-config.sh])

20
depends/packages/googlemock.mk

@ -1,20 +0,0 @@
# url=https://github.com/google/googlemock/archive/release-1.7.0.tar.gz
package=googlemock
$(package)_version=1.7.0
$(package)_dependencies=googletest
$(package)_download_path=https://github.com/google/$(package)/archive/
$(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_download_file=release-$($(package)_version).tar.gz
$(package)_sha256_hash=3f20b6acb37e5a98e8c4518165711e3e35d47deb6cdb5a4dd4566563b5efd232
define $(package)_build_cmds
$(MAKE) -C make GTEST_DIR='$(host_prefix)' CXXFLAGS='-fPIC' gmock-all.o
endef
define $(package)_stage_cmds
install -D ./make/gmock-all.o $($(package)_staging_dir)$(host_prefix)/lib/libgmock.a && \
cp -a ./include $($(package)_staging_dir)$(host_prefix)/include
endef

6
depends/packages/libsodium.mk

@ -1,8 +1,8 @@
package=libsodium
$(package)_version=1.0.11
$(package)_version=1.0.15
$(package)_download_path=https://download.libsodium.org/libsodium/releases/
$(package)_file_name=libsodium-1.0.11.tar.gz
$(package)_sha256_hash=a14549db3c49f6ae2170cbbf4664bd48ace50681045e8dbea7c8d9fb96f9c765
$(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_sha256_hash=fb6a9e879a2f674592e4328c5d9f79f082405ee4bb05cb6e679b90afe9e178f4
$(package)_dependencies=
$(package)_config_opts=

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

@ -16,7 +16,9 @@ testScripts=(
'wallet_treestate.py'
'wallet_protectcoinbase.py'
'wallet_shieldcoinbase.py'
'wallet_mergetoaddress.py'
'wallet.py'
'wallet_overwintertx.py'
'wallet_nullifiers.py'
'wallet_1941.py'
'listtransactions.py'
@ -27,8 +29,10 @@ testScripts=(
'rawtransactions.py'
'rest.py'
'mempool_spendcoinbase.py'
'mempool_coinbase_spends.py'
'mempool_reorg.py'
'mempool_tx_input_limit.py'
'mempool_nu_activation.py'
'mempool_tx_expiry.py'
'httpbasics.py'
'zapwallettxes.py'
'proxy_test.py'
@ -47,9 +51,11 @@ testScripts=(
'zcjoinsplit.py'
'zcjoinsplitdoublespend.py'
'zkey_import_export.py'
'reorg_limit.py'
'getblocktemplate.py'
'bip65-cltv-p2p.py'
'bipdersig-p2p.py'
'overwinter_peer_management.py'
);
testScriptsExt=(
'getblocktemplate_longpoll.py'

91
qa/rpc-tests/mempool_coinbase_spends.py

@ -1,91 +0,0 @@
#!/usr/bin/env python2
# Copyright (c) 2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
# Test re-org scenarios with a mempool that contains transactions
# that spend (directly or indirectly) coinbase transactions.
#
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, start_node, connect_nodes
# Create one-input, one-output, no-fee transaction:
class MempoolCoinbaseTest(BitcoinTestFramework):
alert_filename = None # Set by setup_network
def setup_network(self):
args = ["-checkmempool", "-debug=mempool"]
self.nodes = []
self.nodes.append(start_node(0, self.options.tmpdir, args))
self.nodes.append(start_node(1, self.options.tmpdir, args))
connect_nodes(self.nodes[1], 0)
self.is_network_split = False
self.sync_all
def create_tx(self, from_txid, to_address, amount):
inputs = [{ "txid" : from_txid, "vout" : 0}]
outputs = { to_address : amount }
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
signresult = self.nodes[0].signrawtransaction(rawtx)
assert_equal(signresult["complete"], True)
return signresult["hex"]
def run_test(self):
# Mine three blocks. After this, nodes[0] blocks
# 101, 102, and 103 are spend-able.
new_blocks = self.nodes[1].generate(4)
self.sync_all()
node0_address = self.nodes[0].getnewaddress()
node1_address = self.nodes[1].getnewaddress()
# Three scenarios for re-orging coinbase spends in the memory pool:
# 1. Direct coinbase spend : spend_101
# 2. Indirect (coinbase spend in chain, child in mempool) : spend_102 and spend_102_1
# 3. Indirect (coinbase and child both in chain) : spend_103 and spend_103_1
# Use invalidatblock to make all of the above coinbase spends invalid (immature coinbase),
# and make sure the mempool code behaves correctly.
b = [ self.nodes[0].getblockhash(n) for n in range(102, 105) ]
coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ]
spend_101_raw = self.create_tx(coinbase_txids[0], node1_address, 10)
spend_102_raw = self.create_tx(coinbase_txids[1], node0_address, 10)
spend_103_raw = self.create_tx(coinbase_txids[2], node0_address, 10)
# Broadcast and mine spend_102 and 103:
spend_102_id = self.nodes[0].sendrawtransaction(spend_102_raw)
spend_103_id = self.nodes[0].sendrawtransaction(spend_103_raw)
self.nodes[0].generate(1)
# Create 102_1 and 103_1:
spend_102_1_raw = self.create_tx(spend_102_id, node1_address, 10)
spend_103_1_raw = self.create_tx(spend_103_id, node1_address, 10)
# Broadcast and mine 103_1:
spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw)
[spend_103_1_id] # hush pyflakes
self.nodes[0].generate(1)
# ... now put spend_101 and spend_102_1 in memory pools:
spend_101_id = self.nodes[0].sendrawtransaction(spend_101_raw)
spend_102_1_id = self.nodes[0].sendrawtransaction(spend_102_1_raw)
self.sync_all()
assert_equal(set(self.nodes[0].getrawmempool()), set([ spend_101_id, spend_102_1_id ]))
# Use invalidateblock to re-org back and make all those coinbase spends
# immature/invalid:
for node in self.nodes:
node.invalidateblock(new_blocks[0])
self.sync_all()
# mempool should be empty.
assert_equal(set(self.nodes[0].getrawmempool()), set())
if __name__ == '__main__':
MempoolCoinbaseTest().main()

119
qa/rpc-tests/mempool_nu_activation.py

@ -0,0 +1,119 @@
#!/usr/bin/env python2
# Copyright (c) 2018 The Zcash developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, initialize_chain_clean, \
start_node, connect_nodes, wait_and_assert_operationid_status
from decimal import Decimal
# Test mempool behaviour around network upgrade activation
class MempoolUpgradeActivationTest(BitcoinTestFramework):
alert_filename = None # Set by setup_network
def setup_network(self):
args = ["-checkmempool", "-debug=mempool", "-blockmaxsize=4000", "-nuparams=5ba81b19:200"]
self.nodes = []
self.nodes.append(start_node(0, self.options.tmpdir, args))
self.nodes.append(start_node(1, self.options.tmpdir, args))
connect_nodes(self.nodes[1], 0)
self.is_network_split = False
self.sync_all
def setup_chain(self):
print "Initializing test directory "+self.options.tmpdir
initialize_chain_clean(self.options.tmpdir, 2)
def run_test(self):
self.nodes[1].generate(100)
self.sync_all()
# Mine 97 blocks. After this, nodes[1] blocks
# 1 to 97 are spend-able.
self.nodes[0].generate(97)
self.sync_all()
# Shield some ZEC
node1_taddr = self.nodes[1].getnewaddress()
node0_zaddr = self.nodes[0].z_getnewaddress()
recipients = [{'address': node0_zaddr, 'amount': Decimal('10')}]
myopid = self.nodes[1].z_sendmany(node1_taddr, recipients, 1, Decimal('0'))
print wait_and_assert_operationid_status(self.nodes[1], myopid)
self.sync_all()
# Mine block 198. After this, the mempool expects
# block 199, which is the last Sprout block.
self.nodes[0].generate(1)
self.sync_all()
# Mempool should be empty.
assert_equal(set(self.nodes[0].getrawmempool()), set())
# Check node 0 shielded balance
assert_equal(self.nodes[0].z_getbalance(node0_zaddr), Decimal('10'))
# Fill the mempool with twice as many transactions as can fit into blocks
node0_taddr = self.nodes[0].getnewaddress()
sprout_txids = []
while self.nodes[1].getmempoolinfo()['bytes'] < 2 * 4000:
sprout_txids.append(self.nodes[1].sendtoaddress(node0_taddr, Decimal('0.001')))
self.sync_all()
# Spends should be in the mempool
sprout_mempool = set(self.nodes[0].getrawmempool())
assert_equal(sprout_mempool, set(sprout_txids))
# Mine block 199. After this, the mempool expects
# block 200, which is the first Overwinter block.
self.nodes[0].generate(1)
self.sync_all()
# mempool should be empty.
assert_equal(set(self.nodes[0].getrawmempool()), set())
# Block 199 should contain a subset of the original mempool
# (with all other transactions having been dropped)
block_txids = self.nodes[0].getblock(self.nodes[0].getbestblockhash())['tx']
assert(len(block_txids) < len(sprout_txids))
for txid in block_txids[1:]: # Exclude coinbase
assert(txid in sprout_txids)
# Create some transparent Overwinter transactions
overwinter_txids = [self.nodes[1].sendtoaddress(node0_taddr, Decimal('0.001')) for i in range(10)]
self.sync_all()
# Create a shielded Overwinter transaction
recipients = [{'address': node0_taddr, 'amount': Decimal('10')}]
myopid = self.nodes[0].z_sendmany(node0_zaddr, recipients, 1, Decimal('0'))
shielded = wait_and_assert_operationid_status(self.nodes[0], myopid)
assert(shielded != None)
overwinter_txids.append(shielded)
self.sync_all()
# Spends should be in the mempool
assert_equal(set(self.nodes[0].getrawmempool()), set(overwinter_txids))
# Node 0 note should be unspendable
assert_equal(self.nodes[0].z_getbalance(node0_zaddr), Decimal('0'))
# Invalidate block 199.
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
# BUG: Ideally, the mempool should now only contain the transactions
# that were in block 199, the Overwinter transactions having been dropped.
# However, because chainActive is not updated until after the transactions
# in the disconnected block have been re-added to the mempool, the height
# seen by AcceptToMemoryPool is one greater than it should be. This causes
# the block 199 transactions to be validated against the Overwinter rules,
# and rejected because they (obviously) fail.
#assert_equal(set(self.nodes[0].getrawmempool()), set(block_txids[1:]))
assert_equal(set(self.nodes[0].getrawmempool()), set())
# Node 0 note should be spendable again
assert_equal(self.nodes[0].z_getbalance(node0_zaddr), Decimal('10'))
if __name__ == '__main__':
MempoolUpgradeActivationTest().main()

187
qa/rpc-tests/mempool_tx_expiry.py

@ -0,0 +1,187 @@
#!/usr/bin/env python2
# Copyright (c) 2018 The Zcash developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
# Test proper expiry for transactions >= version 3
#
from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, connect_nodes, \
connect_nodes_bi, sync_blocks, start_nodes, sync_blocks, sync_mempools, \
wait_and_assert_operationid_status
from decimal import Decimal
import time
class MempoolTxExpiryTest(BitcoinTestFramework):
def setup_nodes(self):
return start_nodes(4, self.options.tmpdir, [["-nuparams=5ba81b19:205", "-txexpirydelta=4"]] * 4)
# Test before, at, and after expiry block
# TODO: Test case of dependent txs in reorgs
# chain is at block height 199 when run_test executes
def run_test(self):
alice = self.nodes[0].getnewaddress()
z_alice = self.nodes[0].z_getnewaddress()
bob = self.nodes[2].getnewaddress()
z_bob = self.nodes[2].z_getnewaddress()
# When Overwinter not yet activated, no expiryheight in tx
sapling_tx = self.nodes[0].sendtoaddress(bob, 0.01)
rawtx = self.nodes[0].getrawtransaction(sapling_tx, 1)
assert_equal(rawtx["overwintered"], False)
assert("expiryheight" not in rawtx)
self.nodes[0].generate(6)
self.sync_all()
## Shield one of Alice's coinbase funds to her zaddr
res = self.nodes[0].z_shieldcoinbase("*", z_alice, 0.0001, 1)
wait_and_assert_operationid_status(self.nodes[0], res['opid'])
self.nodes[0].generate(1)
self.sync_all()
# Get balance on node 0
bal = self.nodes[0].z_gettotalbalance()
print "Balance before zsend, after shielding 10: ", bal
assert_equal(Decimal(bal["private"]), Decimal("9.9999"))
print "Splitting network..."
self.split_network()
# Create transactions
zsendamount = Decimal('1.0') - Decimal('0.0001')
recipients = []
recipients.append({"address": z_bob, "amount": zsendamount})
myopid = self.nodes[0].z_sendmany(z_alice, recipients)
persist_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid)
persist_transparent = self.nodes[0].sendtoaddress(bob, 0.01)
# Verify transparent transaction is version 3 intended for Overwinter branch
rawtx = self.nodes[0].getrawtransaction(persist_transparent, 1)
assert_equal(rawtx["version"], 3)
assert_equal(rawtx["overwintered"], True)
assert_equal(rawtx["expiryheight"], 212)
print "Blockheight at persist_transparent & persist_shielded creation:", self.nodes[0].getblockchaininfo()['blocks']
print "Expiryheight of persist_transparent:", rawtx['expiryheight']
# Verify shielded transaction is version 3 intended for Overwinter branch
rawtx = self.nodes[0].getrawtransaction(persist_shielded, 1)
print "Expiryheight of persist_shielded", rawtx['expiryheight']
assert_equal(rawtx["version"], 3)
assert_equal(rawtx["overwintered"], True)
assert_equal(rawtx["expiryheight"], 212)
print "\n Blockheight advances to less than expiry block height. After reorg, txs should persist in mempool"
assert(persist_transparent in self.nodes[0].getrawmempool())
assert(persist_shielded in self.nodes[0].getrawmempool())
assert_equal(set(self.nodes[2].getrawmempool()), set())
print "mempool node 0:", self.nodes[0].getrawmempool()
print "mempool node 2:", self.nodes[2].getrawmempool()
bal = self.nodes[0].z_gettotalbalance()
print "Printing balance before persist_shielded & persist_transparent are initially mined from mempool", bal
# Txs are mined on node 0; will later be rolled back
self.nodes[0].generate(1)
print "Node 0 generated 1 block"
print "Node 0 height:", self.nodes[0].getblockchaininfo()['blocks']
print "Node 2 height:", self.nodes[2].getblockchaininfo()['blocks']
bal = self.nodes[0].z_gettotalbalance()
print "Printing balance after persist_shielded & persist_transparent are mined:", bal
assert_equal(set(self.nodes[0].getrawmempool()), set())
print "Mine 2 competing blocks on Node 2..."
blocks = self.nodes[2].generate(2)
for block in blocks:
blk = self.nodes[2].getblock(block)
print "Height: {0}, Mined block txs: {1}".format(blk["height"], blk["tx"])
print "Connect nodes to force a reorg"
connect_nodes_bi(self.nodes,0,2)
self.is_network_split = False
print "Syncing blocks"
sync_blocks(self.nodes)
print "Ensure that txs are back in mempool of node 0"
print "Blockheight node 0:", self.nodes[0].getblockchaininfo()['blocks']
print "Blockheight node 2:", self.nodes[2].getblockchaininfo()['blocks']
print "mempool node 0: ", self.nodes[0].getrawmempool()
print "mempool node 2: ", self.nodes[2].getrawmempool()
assert(persist_transparent in self.nodes[0].getrawmempool())
assert(persist_shielded in self.nodes[0].getrawmempool())
bal = self.nodes[0].z_gettotalbalance()
# Mine txs to get them out of the way of mempool sync in split_network()
print "Generating another block on node 0 to clear txs from mempool"
self.nodes[0].generate(1)
assert_equal(set(self.nodes[0].getrawmempool()), set())
sync_blocks(self.nodes)
print "Splitting network..."
self.split_network()
print "\n Blockheight advances to equal expiry block height. After reorg, txs should persist in mempool"
myopid = self.nodes[0].z_sendmany(z_alice, recipients)
persist_shielded_2 = wait_and_assert_operationid_status(self.nodes[0], myopid)
persist_transparent_2 = self.nodes[0].sendtoaddress(bob, 0.01)
rawtx_trans = self.nodes[0].getrawtransaction(persist_transparent_2, 1)
rawtx_shield = self.nodes[0].getrawtransaction(persist_shielded_2, 1)
print "Blockheight node 0 at persist_transparent_2 creation:", self.nodes[0].getblockchaininfo()['blocks']
print "Blockheight node 2 at persist_transparent_2 creation:", self.nodes[2].getblockchaininfo()['blocks']
print "Expiryheight of persist_transparent_2:", rawtx_trans['expiryheight']
print "Expiryheight of persist_shielded_2:", rawtx_shield['expiryheight']
blocks = self.nodes[2].generate(4)
for block in blocks:
blk = self.nodes[2].getblock(block)
print "Height: {0}, Mined block txs: {1}".format(blk["height"], blk["tx"])
print "Connect nodes to force a reorg"
connect_nodes_bi(self.nodes, 0, 2)
self.is_network_split = False
sync_blocks(self.nodes)
print "Ensure that persist_transparent_2 & persist_shielded_2 are in mempool at expiry block height"
print "Blockheight node 0:", self.nodes[0].getblockchaininfo()['blocks']
print "Blockheight node 2:", self.nodes[2].getblockchaininfo()['blocks']
print "mempool node 0: ", self.nodes[0].getrawmempool()
print "mempool node 2: ", self.nodes[2].getrawmempool()
assert(persist_transparent_2 in self.nodes[0].getrawmempool())
assert(persist_shielded_2 in self.nodes[0].getrawmempool())
# Mine persist txs to get them out of the way of mempool sync in split_network()
self.nodes[0].generate(1)
assert_equal(set(self.nodes[0].getrawmempool()), set())
sync_blocks(self.nodes)
print "Balance after persist_shielded_2 is mined to remove from mempool: ", self.nodes[0].z_gettotalbalance()
print "Splitting network..."
self.split_network()
print "\n Blockheight advances to greater than expiry block height. After reorg, txs should expire from mempool"
print "Balance before expire_shielded is sent: ", self.nodes[0].z_gettotalbalance()
myopid = self.nodes[0].z_sendmany(z_alice, recipients)
expire_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid)
expire_transparent = self.nodes[0].sendtoaddress(bob, 0.01)
print "Blockheight node 0 at expire_transparent creation:", self.nodes[0].getblockchaininfo()['blocks']
print "Blockheight node 2 at expire_shielded creation:", self.nodes[2].getblockchaininfo()['blocks']
print "Expiryheight of expire_transparent:", self.nodes[0].getrawtransaction(expire_transparent, 1)['expiryheight']
print "Expiryheight of expire_shielded:", self.nodes[0].getrawtransaction(expire_shielded, 1)['expiryheight']
assert(expire_transparent in self.nodes[0].getrawmempool())
assert(expire_shielded in self.nodes[0].getrawmempool())
blocks = self.nodes[2].generate(6)
for block in blocks:
blk = self.nodes[2].getblock(block)
print "Height: {0}, Mined block txs: {1}".format(blk["height"], blk["tx"])
print "Connect nodes to force a reorg"
connect_nodes_bi(self.nodes, 0, 2)
self.is_network_split = False
sync_blocks(self.nodes)
print "Ensure that expire_transparent & expire_shielded are in mempool at expiry block height"
print "mempool node 0: ", self.nodes[0].getrawmempool()
print "mempool node 2: ", self.nodes[2].getrawmempool()
assert_equal(set(self.nodes[0].getrawmempool()), set())
print "Ensure balance of node 0 is correct"
bal = self.nodes[0].z_gettotalbalance()
print "Balance after expire_shielded has expired: ", bal
assert_equal(Decimal(bal["private"]), Decimal("7.9999"))
if __name__ == '__main__':
MempoolTxExpiryTest().main()

117
qa/rpc-tests/overwinter_peer_management.py

@ -0,0 +1,117 @@
#!/usr/bin/env python2
# Copyright (c) 2018 The Zcash developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.mininode import NodeConn, NodeConnCB, NetworkThread, \
EarlyDisconnectError, msg_inv, mininode_lock, msg_ping, \
MY_VERSION, OVERWINTER_PROTO_VERSION
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import initialize_chain_clean, start_nodes, \
p2p_port, assert_equal
import time
#
# In this test we connect Sprout and Overwinter mininodes to a Zcashd node
# which will activate Overwinter at block 10.
#
# We test:
# 1. the mininodes stay connected to Zcash with Sprout consensus rules
# 2. when Overwinter activates, the Sprout mininodes are dropped
# 3. new Overwinter nodes can connect to Zcash
# 4. new Sprout nodes cannot connect to Zcash
#
# This test *does not* verify that prior to Overwinter activation, the Zcashd
# node will prefer connections with Overwinter nodes, with an eviction process
# that prioritizes Sprout connections.
#
class TestManager(NodeConnCB):
def __init__(self):
NodeConnCB.__init__(self)
self.create_callback_map()
def on_close(self, conn):
pass
def on_reject(self, conn, message):
conn.rejectMessage = message
class OverwinterPeerManagementTest(BitcoinTestFramework):
def setup_chain(self):
print "Initializing test directory "+self.options.tmpdir
initialize_chain_clean(self.options.tmpdir, 1)
def setup_network(self):
self.nodes = start_nodes(1, self.options.tmpdir,
extra_args=[['-nuparams=5ba81b19:10', '-debug', '-whitelist=127.0.0.1']])
def run_test(self):
test = TestManager()
# Launch 10 Sprout and 10 Overwinter mininodes
nodes = []
for x in xrange(10):
nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", False))
nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", True))
# Start up network handling in another thread
NetworkThread().start()
# Sprout consensus rules apply at block height 9
self.nodes[0].generate(9)
assert_equal(9, self.nodes[0].getblockcount())
# Verify mininodes are still connected to zcashd node
peerinfo = self.nodes[0].getpeerinfo()
versions = [x["version"] for x in peerinfo]
assert_equal(10, versions.count(MY_VERSION))
assert_equal(10, versions.count(OVERWINTER_PROTO_VERSION))
# Overwinter consensus rules activate at block height 10
self.nodes[0].generate(1)
assert_equal(10, self.nodes[0].getblockcount())
# Mininodes send ping message to zcashd node.
pingCounter = 1
for node in nodes:
node.send_message(msg_ping(pingCounter))
pingCounter = pingCounter + 1
time.sleep(3)
# Verify Sprout mininodes have been dropped and Overwinter mininodes are still connected.
peerinfo = self.nodes[0].getpeerinfo()
versions = [x["version"] for x in peerinfo]
assert_equal(0, versions.count(MY_VERSION))
assert_equal(10, versions.count(OVERWINTER_PROTO_VERSION))
# Extend the Overwinter chain with another block.
self.nodes[0].generate(1)
# Connect a new Overwinter mininode to the zcashd node, which is accepted.
nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", True))
time.sleep(3)
assert_equal(11, len(self.nodes[0].getpeerinfo()))
# Try to connect a new Sprout mininode to the zcashd node, which is rejected.
sprout = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", False)
nodes.append(sprout)
time.sleep(3)
assert("Version must be 170003 or greater" in str(sprout.rejectMessage))
# Verify that only Overwinter mininodes are connected.
peerinfo = self.nodes[0].getpeerinfo()
versions = [x["version"] for x in peerinfo]
assert_equal(0, versions.count(MY_VERSION))
assert_equal(11, versions.count(OVERWINTER_PROTO_VERSION))
for node in nodes:
node.disconnect_node()
if __name__ == '__main__':
OverwinterPeerManagementTest().main()

86
qa/rpc-tests/reorg_limit.py

@ -0,0 +1,86 @@
#!/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.
#
# Test reorg limit
#
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
check_node,
connect_nodes_bi,
initialize_chain_clean,
start_node,
sync_blocks,
)
from time import sleep
def check_stopped(i, timeout=10):
stopped = False
for x in xrange(1, timeout):
ret = check_node(i)
if ret is None:
sleep(1)
else:
stopped = True
break
return stopped
class ReorgLimitTest(BitcoinTestFramework):
def run_test(self):
assert(self.nodes[0].getblockcount() == 200)
assert(self.nodes[2].getblockcount() == 200)
self.split_network()
print "Test the maximum-allowed reorg:"
print "Mine 99 blocks on Node 0"
self.nodes[0].generate(99)
assert(self.nodes[0].getblockcount() == 299)
assert(self.nodes[2].getblockcount() == 200)
print "Mine competing 100 blocks on Node 2"
self.nodes[2].generate(100)
assert(self.nodes[0].getblockcount() == 299)
assert(self.nodes[2].getblockcount() == 300)
print "Connect nodes to force a reorg"
connect_nodes_bi(self.nodes, 0, 2)
self.is_network_split = False
sync_blocks(self.nodes)
print "Check Node 0 is still running and on the correct chain"
assert(self.nodes[0].getblockcount() == 300)
self.split_network()
print "Test the minimum-rejected reorg:"
print "Mine 100 blocks on Node 0"
self.nodes[0].generate(100)
assert(self.nodes[0].getblockcount() == 400)
assert(self.nodes[2].getblockcount() == 300)
print "Mine competing 101 blocks on Node 2"
self.nodes[2].generate(101)
assert(self.nodes[0].getblockcount() == 400)
assert(self.nodes[2].getblockcount() == 401)
print "Sync nodes to force a reorg"
connect_nodes_bi(self.nodes, 0, 2)
self.is_network_split = False
# sync_blocks uses RPC calls to wait for nodes to be synced, so don't
# call it here, because it will have a non-specific connection error
# when Node 0 stops. Instead, we explicitly check for the process itself
# to stop.
print "Check Node 0 is no longer running"
assert(check_stopped(0))
# Dummy stop to enable the test to tear down
self.nodes[0].stop = lambda: True
if __name__ == '__main__':
ReorgLimitTest().main()

144
qa/rpc-tests/wallet_overwintertx.py

@ -0,0 +1,144 @@
#!/usr/bin/env python2
# Copyright (c) 2018 The Zcash developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
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, sync_blocks, sync_mempools, \
wait_and_assert_operationid_status
from decimal import Decimal
class WalletOverwinterTxTest (BitcoinTestFramework):
def setup_chain(self):
print("Initializing test directory "+self.options.tmpdir)
initialize_chain_clean(self.options.tmpdir, 4)
def setup_network(self, split=False):
self.nodes = start_nodes(4, self.options.tmpdir, extra_args=[["-nuparams=5ba81b19:200", "-debug=zrpcunsafe", "-txindex"]] * 4 )
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)
self.is_network_split=False
self.sync_all()
def run_test (self):
self.nodes[0].generate(100)
self.sync_all()
self.nodes[1].generate(98)
self.sync_all()
# Node 0 has reward from blocks 1 to 98 which are spendable.
taddr0 = self.nodes[0].getnewaddress()
taddr1 = self.nodes[1].getnewaddress()
taddr2 = self.nodes[2].getnewaddress()
zaddr2 = self.nodes[2].z_getnewaddress()
taddr3 = self.nodes[3].getnewaddress()
zaddr3 = self.nodes[3].z_getnewaddress()
#
# Currently at block 198. The next block to be mined 199 is a Sprout block
#
bci = self.nodes[0].getblockchaininfo()
assert_equal(bci['consensus']['chaintip'], '00000000')
assert_equal(bci['consensus']['nextblock'], '00000000')
assert_equal(bci['upgrades']['5ba81b19']['status'], 'pending')
# Node 0 sends transparent funds to Node 2
tsendamount = Decimal('1.0')
txid_transparent = self.nodes[0].sendtoaddress(taddr2, tsendamount)
self.sync_all()
# Node 2 sends the zero-confirmation transparent funds to Node 1 using z_sendmany
recipients = []
recipients.append({"address":taddr1, "amount": Decimal('0.5')})
myopid = self.nodes[2].z_sendmany(taddr2, recipients, 0)
txid_zsendmany = wait_and_assert_operationid_status(self.nodes[2], myopid)
# Node 0 shields to Node 2, a coinbase utxo of value 10.0 less fee 0.00010000
zsendamount = Decimal('10.0') - Decimal('0.0001')
recipients = []
recipients.append({"address":zaddr2, "amount": zsendamount})
myopid = self.nodes[0].z_sendmany(taddr0, recipients)
txid_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid)
self.sync_all()
self.nodes[0].generate(1)
self.sync_all()
# Verify balance
assert_equal(self.nodes[1].z_getbalance(taddr1), Decimal('0.5'))
assert_equal(self.nodes[2].getbalance(), Decimal('0.4999'))
assert_equal(self.nodes[2].z_getbalance(zaddr2), zsendamount)
# Verify transaction versions are 1 or 2 (intended for Sprout)
result = self.nodes[0].getrawtransaction(txid_transparent, 1)
assert_equal(result["version"], 1)
assert_equal(result["overwintered"], False)
result = self.nodes[0].getrawtransaction(txid_zsendmany, 1)
assert_equal(result["version"], 1)
assert_equal(result["overwintered"], False)
result = self.nodes[0].getrawtransaction(txid_shielded, 1)
assert_equal(result["version"], 2)
assert_equal(result["overwintered"], False)
#
# Currently at block 199. The next block to be mined 200 is an Overwinter block
#
bci = self.nodes[0].getblockchaininfo()
assert_equal(bci['consensus']['chaintip'], '00000000')
assert_equal(bci['consensus']['nextblock'], '5ba81b19')
assert_equal(bci['upgrades']['5ba81b19']['status'], 'pending')
# Node 0 sends transparent funds to Node 3
tsendamount = Decimal('1.0')
txid_transparent = self.nodes[0].sendtoaddress(taddr3, tsendamount)
self.sync_all()
# Node 3 sends the zero-confirmation transparent funds to Node 1 using z_sendmany
recipients = []
recipients.append({"address":taddr1, "amount": Decimal('0.5')})
myopid = self.nodes[3].z_sendmany(taddr3, recipients, 0)
txid_zsendmany = wait_and_assert_operationid_status(self.nodes[3], myopid)
# Node 0 shields to Node 3, a coinbase utxo of value 10.0 less fee 0.00010000
zsendamount = Decimal('10.0') - Decimal('0.0001')
recipients = []
recipients.append({"address":zaddr3, "amount": zsendamount})
myopid = self.nodes[0].z_sendmany(taddr0, recipients)
txid_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid)
# Mine the first Overwinter block
self.sync_all()
self.nodes[0].generate(1)
self.sync_all()
bci = self.nodes[0].getblockchaininfo()
assert_equal(bci['consensus']['chaintip'], '5ba81b19')
assert_equal(bci['consensus']['nextblock'], '5ba81b19')
assert_equal(bci['upgrades']['5ba81b19']['status'], 'active')
# Verify balance
assert_equal(self.nodes[1].z_getbalance(taddr1), Decimal('1.0'))
assert_equal(self.nodes[3].getbalance(), Decimal('0.4999'))
assert_equal(self.nodes[3].z_getbalance(zaddr3), zsendamount)
# Verify transaction version is 3 (intended for Overwinter)
result = self.nodes[0].getrawtransaction(txid_transparent, 1)
assert_equal(result["version"], 3)
assert_equal(result["overwintered"], True)
assert_equal(result["versiongroupid"], "03c48270")
result = self.nodes[0].getrawtransaction(txid_zsendmany, 1)
assert_equal(result["version"], 3)
assert_equal(result["overwintered"], True)
assert_equal(result["versiongroupid"], "03c48270")
result = self.nodes[0].getrawtransaction(txid_shielded, 1)
assert_equal(result["version"], 3)
assert_equal(result["overwintered"], True)
assert_equal(result["versiongroupid"], "03c48270")
if __name__ == '__main__':
WalletOverwinterTxTest().main()

2
qa/rpc-tests/wallet_protectcoinbase.py

@ -6,6 +6,7 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.mininode import COIN
from test_framework.util import assert_equal, initialize_chain_clean, \
start_nodes, connect_nodes_bi, stop_node, wait_and_assert_operationid_status
@ -22,6 +23,7 @@ def check_value_pool(node, name, total):
found = True
assert_equal(pool['monitored'], True)
assert_equal(pool['chainValue'], total)
assert_equal(pool['chainValueZat'], total * COIN)
assert(found)
class WalletProtectCoinbaseTest (BitcoinTestFramework):

1
qa/rpc-tests/wallet_shieldcoinbase.py

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Copyright (c) 2017 The Zcash developers
# Distributed under the MIT software license, see the accompanying

37
share/certs/BitcoinFoundation_Apple_Cert.pem

@ -1,37 +0,0 @@
Bag Attributes
friendlyName: Developer ID Application: BITCOIN FOUNDATION, INC., THE
localKeyID: 6B 9C 6C A8 A5 73 70 70 E2 57 A3 49 D8 62 FB 97 C7 A5 5D 5E
subject=/UID=PBV4GLS9J4/CN=Developer ID Application: BITCOIN FOUNDATION, INC., THE/OU=PBV4GLS9J4/O=BITCOIN FOUNDATION, INC., THE/C=US
issuer=/CN=Developer ID Certification Authority/OU=Apple Certification Authority/O=Apple Inc./C=US
-----BEGIN CERTIFICATE-----
MIIFhzCCBG+gAwIBAgIIJ0r1rumyfZAwDQYJKoZIhvcNAQELBQAweTEtMCsGA1UE
AwwkRGV2ZWxvcGVyIElEIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSYwJAYDVQQL
DB1BcHBsZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTETMBEGA1UECgwKQXBwbGUg
SW5jLjELMAkGA1UEBhMCVVMwHhcNMTMwMTEwMjIzOTAxWhcNMTgwMTExMjIzOTAx
WjCBqDEaMBgGCgmSJomT8ixkAQEMClBCVjRHTFM5SjQxQDA+BgNVBAMMN0RldmVs
b3BlciBJRCBBcHBsaWNhdGlvbjogQklUQ09JTiBGT1VOREFUSU9OLCBJTkMuLCBU
SEUxEzARBgNVBAsMClBCVjRHTFM5SjQxJjAkBgNVBAoMHUJJVENPSU4gRk9VTkRB
VElPTiwgSU5DLiwgVEhFMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBALTd5zURuZVoJviusr119aktXksenb9IN9vq6kBbq38vxEk7
9wkKMES2XfBRh0HxcEizGzhMNy5OCXuTLMaNMihYdfwYSoBoR2foEU+6kjPUnyJ4
dQBFLJZJr5/QeQmALmYHEgZ6lwXFD2lU8t92340zeJ4y5LZw5pcEHtH9IummYDut
OGCkCGXDcjL+5nHhNScJiXHhswM+62o6XXsQiP6EWbM1CsgrGTNLtaa0U/UvVDwE
79YKklSC5Bog2LD0jBcTuveI66mFzqu++L9X9u+ZArtebwCl7BPNQ+uboYy5uV2d
zf8lpNNZLfXCFjoLe9bLICKfZ7ub9V5aC8+GhckCAwEAAaOCAeEwggHdMD4GCCsG
AQUFBwEBBDIwMDAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AuYXBwbGUuY29tL29j
c3AtZGV2aWQwMTAdBgNVHQ4EFgQUa5xsqKVzcHDiV6NJ2GL7l8elXV4wDAYDVR0T
AQH/BAIwADAfBgNVHSMEGDAWgBRXF+2iz9x8mKEQ4Py+hy0s8uMXVDCCAQ4GA1Ud
IASCAQUwggEBMIH+BgkqhkiG92NkBQEwgfAwKAYIKwYBBQUHAgEWHGh0dHA6Ly93
d3cuYXBwbGUuY29tL2FwcGxlY2EwgcMGCCsGAQUFBwICMIG2DIGzUmVsaWFuY2Ug
b24gdGhpcyBjZXJ0aWZpY2F0ZSBieSBhbnkgcGFydHkgYXNzdW1lcyBhY2NlcHRh
bmNlIG9mIHRoZSB0aGVuIGFwcGxpY2FibGUgc3RhbmRhcmQgdGVybXMgYW5kIGNv
bmRpdGlvbnMgb2YgdXNlLCBjZXJ0aWZpY2F0ZSBwb2xpY3kgYW5kIGNlcnRpZmlj
YXRpb24gcHJhY3RpY2Ugc3RhdGVtZW50cy4wDgYDVR0PAQH/BAQDAgeAMBYGA1Ud
JQEB/wQMMAoGCCsGAQUFBwMDMBMGCiqGSIb3Y2QGAQ0BAf8EAgUAMA0GCSqGSIb3
DQEBCwUAA4IBAQAfJ0BjID/1dS2aEeVyhAzPzCBjG8vm0gDf+/qfwRn3+yWeL9vS
nMdbilwM48IyQWTagjGGcojbsAd/vE4N7NhQyHInoCllNoeor1I5xx+blTaGRBK+
dDhJbbdlGCjsLnH/BczGZi5fyEJds9lUIrp1hJidRcUKO76qb/9gc6qNZpl1vH5k
lDUuJYt7YhAs+L6rTXDyqcK9maeQr0gaOPsRRAQLLwiQCorPeMTUNsbVMdMwZYJs
R+PxiAnk+nyi7rfiFvPoASAYUuI6OzYL/Fa6QU4/gYyPgic944QYVkaQBnc0vEP1
nXq6LGKwgVGcqJnkr/E2kui5gJoV5C3qll3e
-----END CERTIFICATE-----

37
share/certs/BitcoinFoundation_Comodo_Cert.pem

@ -1,37 +0,0 @@
Bag Attributes
friendlyName: The Bitcoin Foundation, Inc.'s COMODO CA Limited ID
localKeyID: 8C 94 64 E3 B5 B0 41 89 5B 89 B0 57 CC 74 B9 44 E5 B2 92 66
subject=/C=US/postalCode=98104-1444/ST=WA/L=Seattle/street=Suite 300/street=71 Columbia St/O=The Bitcoin Foundation, Inc./CN=The Bitcoin Foundation, Inc.
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO Code Signing CA 2
-----BEGIN CERTIFICATE-----
MIIFeDCCBGCgAwIBAgIRAJVYMd+waOER7lUqtiz3M2IwDQYJKoZIhvcNAQEFBQAw
ezELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxITAfBgNV
BAMTGENPTU9ETyBDb2RlIFNpZ25pbmcgQ0EgMjAeFw0xMzAxMTYwMDAwMDBaFw0x
NDAxMTYyMzU5NTlaMIG8MQswCQYDVQQGEwJVUzETMBEGA1UEEQwKOTgxMDQtMTQ0
NDELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxEjAQBgNVBAkMCVN1aXRl
IDMwMDEXMBUGA1UECQwONzEgQ29sdW1iaWEgU3QxJTAjBgNVBAoMHFRoZSBCaXRj
b2luIEZvdW5kYXRpb24sIEluYy4xJTAjBgNVBAMMHFRoZSBCaXRjb2luIEZvdW5k
YXRpb24sIEluYy4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQChUwLD
u/hu5aFZ/n11B27awONaaDrmHm0pamiWHb01yL4JmTBtaLCrSftF8RhCscQ8jpI0
UG1Cchmay0e3zH5o5XRs0H9C3x+SM5ozms0TWDmAYiB8aQEghsGovDk0D2nyTQeK
Q0xqyCh0m8ZPOnMnYrakHEmF6WvhLdJvI6Od4KIwbKxgN17cPFIfLVsZ7GrzmmbU
Gdi4wSQCHy5rxzvBxho8Qq/SfBl93uOMUrqOHjOUAPhNuTJG3t/MdhU8Zp24s29M
abHtYkT9W86hMjIiI8RTAR+WHKVglx9SB0cjDabXN8SZ3gME0+H++LyzlySHT8sI
ykepojZ7UBRgp9w3AgMBAAGjggGzMIIBrzAfBgNVHSMEGDAWgBQexbEsfYfaAmh8
JbwMB4Q/ts/e8TAdBgNVHQ4EFgQUfPf+ZyDWl/4LH0Y5BuJTelkRd/EwDgYDVR0P
AQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEQYJ
YIZIAYb4QgEBBAQDAgQQMEYGA1UdIAQ/MD0wOwYMKwYBBAGyMQECAQMCMCswKQYI
KwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5uZXQvQ1BTMEEGA1UdHwQ6
MDgwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0NPTU9ET0NvZGVTaWdu
aW5nQ0EyLmNybDByBggrBgEFBQcBAQRmMGQwPAYIKwYBBQUHMAKGMGh0dHA6Ly9j
cnQuY29tb2RvY2EuY29tL0NPTU9ET0NvZGVTaWduaW5nQ0EyLmNydDAkBggrBgEF
BQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMCgGA1UdEQQhMB+BHWxpbmRz
YXlAYml0Y29pbmZvdW5kYXRpb24ub3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAqibjo
D4HG5XSIIMCmYE5RgQBSEAJfI+EZERk1G9F83ZUWr0yNRZCw4O+RaM7xQhvJhEoD
G2kpk/q2bNOc71/VyZ6SrE1JRVUON41/Flhz4M6cP0BclTicXvh+efVwqZhIz+ws
UxF2hvC/1Xx6rqI7NYAlOYXk2MSUq3HREo+gWUPKM8em4MZZV/7XCH4QbsfxOl1J
xS6EOQmV8hfUN4KRXI5WfGUmedBxq7dM0RSJOSQl8fq2f+JjRLfjQwQucy7LDY+y
pRTsL2TdQV/DuDuI3s0NHRGznQNddoX5jqpXhSQFAAdgrhN1gGkWaaTPzr9IF2TG
qgr6PEp9tIYC+MbM
-----END CERTIFICATE-----

46
share/certs/PrivateKeyNotes.md

@ -1,46 +0,0 @@
Code-signing private key notes
==
The private keys for these certificates were generated on Gavin's main work machine,
following the certificate authoritys' recommendations for generating certificate
signing requests.
For OSX, the private key was generated by Keychain.app on Gavin's main work machine.
The key and certificate is in a separate, passphrase-protected keychain file that is
unlocked to sign the Bitcoin-Qt.app bundle.
For Windows, the private key was generated by Firefox running on Gavin's main work machine.
The key and certificate were exported into a separate, passphrase-protected PKCS#12 file, and
then deleted from Firefox's keystore. The exported file is used to sign the Windows setup.exe.
Threat analysis
--
Gavin is a single point of failure. He could be coerced to divulge the secret signing keys,
allowing somebody to distribute a Bitcoin-Qt.app or bitcoin-qt-setup.exe with a valid
signature but containing a malicious binary.
Or the machine Gavin uses to sign the binaries could be compromised, either remotely or
by breaking in to his office, allowing the attacker to get the private key files and then
install a keylogger to get the passphrase that protects them.
Threat Mitigation
--
"Air gapping" the machine used to do the signing will not work, because the signing
process needs to access a timestamp server over the network. And it would not
prevent the "rubber hose cryptography" threat (coercing Gavin to sign a bad binary
or divulge the private keys).
Windows binaries are reproducibly 'gitian-built', and the setup.exe file created
by the NSIS installer system is a 7zip archive, so you could check to make sure
that the bitcoin-qt.exe file inside the installer had not been tampered with.
However, an attacker could modify the installer's code, so when the setup.exe
was run it compromised users' systems. A volunteer to write an auditing tool
that checks the setup.exe for tampering, and checks the files in it against
the list of gitian signatures, is needed.
The long-term solution is something like the 'gitian downloader' system, which
uses signatures from multiple developers to determine whether or not a binary
should be trusted. However, that just pushes the problem to "how will
non-technical users securely get the gitian downloader code to start?"

BIN
share/pixmaps/addressbook16.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

BIN
share/pixmaps/addressbook16mask.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 B

BIN
share/pixmaps/addressbook20.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

BIN
share/pixmaps/addressbook20mask.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 B

BIN
share/pixmaps/bitcoin-bc.ico

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

BIN
share/pixmaps/bitcoin.ico

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

BIN
share/pixmaps/bitcoin128.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

384
share/pixmaps/bitcoin128.xpm

@ -1,384 +0,0 @@
/* XPM */
static char *bitcoin___[] = {
/* columns rows colors chars-per-pixel */
"128 128 250 2",
" c #845415",
". c #895616",
"X c #84581E",
"o c #8D5C18",
"O c #925A15",
"+ c #925E1C",
"@ c #98621C",
"# c #9E711C",
"$ c #A36E1A",
"% c #A96F1B",
"& c #A6711C",
"* c #AC741C",
"= c #B2741E",
"- c #B37C1E",
"; c #BB7C1E",
": c #835B21",
"> c #8F6125",
", c #956727",
"< c #916B2E",
"1 c #996B2C",
"2 c #B47B23",
"3 c #BD7C20",
"4 c #A17330",
"5 c #AB7D3B",
"6 c #C17F20",
"7 c #B9831F",
"8 c #BB842B",
"9 c #BD8533",
"0 c #B68F3D",
"q c #BE8C3B",
"w c #C4801F",
"e c #FE8C03",
"r c #F38A0F",
"t c #FD8E0A",
"y c #FF910C",
"u c #F78F13",
"i c #F98F10",
"p c #F79016",
"a c #FE9314",
"s c #F6931E",
"d c #FD961B",
"f c #FE991E",
"g c #C58421",
"h c #CD8621",
"j c #C78B21",
"k c #CC8B23",
"l c #C2852B",
"z c #C08B2D",
"x c #D28722",
"c c #D38B25",
"v c #DB8E22",
"b c #D28E2C",
"n c #D49323",
"m c #DC9224",
"M c #DC9B25",
"N c #D4922D",
"B c #DF972A",
"V c #DF982E",
"C c #C18D33",
"Z c #C58E38",
"A c #CB9332",
"S c #C2933C",
"D c #CD9339",
"F c #CC9938",
"G c #D19733",
"H c #DA9230",
"J c #D59935",
"K c #DC9C33",
"L c #DC9E3B",
"P c #E49124",
"I c #EA9426",
"U c #E09D26",
"Y c #EC972B",
"T c #F79625",
"R c #F99524",
"E c #F69A26",
"W c #F89825",
"Q c #F2972B",
"! c #F59A2C",
"~ c #F89B2B",
"^ c #E79D33",
"/ c #EF9D31",
"( c #E19F3A",
") c #EF9D3A",
"_ c #F49C33",
"` c #F99E32",
"' c #F49F39",
"] c #D6A13E",
"[ c #DAA33B",
"{ c #E3A127",
"} c #E7A328",
"| c #EDA32C",
" . c #EDA829",
".. c #FFA325",
"X. c #FFAB25",
"o. c #F3A42B",
"O. c #FFA429",
"+. c #F4A929",
"@. c #FFAC2A",
"#. c #FFB227",
"$. c #FFB32C",
"%. c #FFBA2D",
"&. c #EEA830",
"*. c #F7A334",
"=. c #FAA036",
"-. c #FCAB34",
";. c #F4A13C",
":. c #F9A33B",
">. c #F4A83B",
",. c #FFA83F",
"<. c #FDB432",
"1. c #FFBB33",
"2. c #FFB73A",
"3. c #FDB93E",
"4. c #FFC12F",
"5. c #FFC432",
"6. c #FFC338",
"7. c #D2A043",
"8. c #D8A140",
"9. c #EEA144",
"0. c #E2A840",
"q. c #EDA34B",
"w. c #F4A444",
"e. c #F9A642",
"r. c #FBA945",
"t. c #F3A64B",
"y. c #F4A84E",
"u. c #FBAB4B",
"i. c #EEB041",
"p. c #FABA44",
"a. c #ECA653",
"s. c #EEAC5D",
"d. c #F3AA53",
"f. c #FAAE53",
"g. c #F2AD5A",
"h. c #FBB056",
"j. c #F6B15E",
"k. c #FBB25B",
"l. c #DDAF79",
"z. c #E3A962",
"x. c #EBAE63",
"c. c #E4AC68",
"v. c #EAAF69",
"b. c #EEB065",
"n. c #E7B06C",
"m. c #EEB36B",
"M. c #F5B263",
"N. c #FBB461",
"B. c #E6B274",
"V. c #ECB574",
"C. c #E7B57B",
"Z. c #EAB77C",
"A. c #ECB97C",
"S. c #F2B770",
"D. c #F0BB7A",
"F. c #DBB485",
"G. c #DFB888",
"H. c #E4B984",
"J. c #EDBD82",
"K. c #E5BC8B",
"L. c #EABE8A",
"P. c #F0BE82",
"I. c #E0BF96",
"U. c #EDC089",
"Y. c #F0C28B",
"T. c #E5C194",
"R. c #E9C191",
"E. c #E4C39C",
"W. c #EBC699",
"Q. c #EBC99F",
"!. c #DFC3A0",
"~. c #DDCAAF",
"^. c #CFC7BD",
"/. c #D2CBB6",
"(. c #DBC8B1",
"). c #DBCDBB",
"_. c #E2C6A4",
"`. c #E6C8A5",
"'. c #EACBA5",
"]. c #E1C7A8",
"[. c #E3CBAD",
"{. c #EACCAA",
"}. c #EED1AC",
"|. c #E1CDB3",
" X c #E3CFB8",
".X c #E6D1B6",
"XX c #EBD2B3",
"oX c #E3D1BB",
"OX c #EAD6BB",
"+X c #EBD8BF",
"@X c #D3CDC2",
"#X c #D8CDC2",
"$X c #D0CECA",
"%X c #DDD3C4",
"&X c #D3D2CC",
"*X c #DDD5CB",
"=X c #CCD3D5",
"-X c #C9D7DF",
";X c #D2D4D6",
":X c #DEDAD4",
">X c #DDDCDB",
",X c #E2D4C2",
"<X c #ECDBC2",
"1X c #E2D7CA",
"2X c #E3D8CC",
"3X c #E2DCD6",
"4X c #E9DED2",
"5X c #E1DEDA",
"6X c #EEE0CE",
"7X c #EEE3D4",
"8X c #E7E2DA",
"9X c #EEE4D8",
"0X c #F3E6D1",
"qX c #C5D7ED",
"wX c #CDDBEB",
"eX c #DBDEE2",
"rX c #CBDCF1",
"tX c #C4DFFF",
"yX c #DEE1E4",
"uX c #DDE4EC",
"iX c #D3E1F2",
"pX c #DDE6F1",
"aX c #DEE9F4",
"sX c #D8E5F8",
"dX c #D6EEFF",
"fX c #DEECFB",
"gX c #D5F4FF",
"hX c #DDF3FF",
"jX c #DCF9FF",
"kX c #E3E4E6",
"lX c #EFEBE4",
"zX c #E1E5EB",
"xX c #E2E8ED",
"cX c #F1F1ED",
"vX c #E0E7F0",
"bX c #E2E9F2",
"nX c #EAEFF6",
"mX c #E1EEFD",
"MX c #E4F1F6",
"NX c #E3F4FF",
"BX c #EAF6FF",
"VX c #E5F9FF",
"CX c #EBFAFF",
"ZX c #F5F5F5",
"AX c #F9F7F5",
"SX c #FAF8F6",
"DX c #F3F7FB",
"FX c #F4FAFE",
"GX c #FEFEFE",
"HX c None",
/* pixels */
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX1 Z L >.N b b b b N >.( C > HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX4 L _ *.@.<.$.X.X...X.X.X.X.X.X...X.@.$.<.@.*./ G , HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX< L -.@.$.X...R R R T T T T W W W W W W T T T T R R W ..X.$.@.*.J HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXD -.%.X.W R T T W W W W W W W W W W W W W W W W W W W W W W T T R W X.%.+.A HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXS -.$.X.R T T W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W T T R X.$.-.C HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXF <.@.f R T W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W T R W #.<.A HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX[ <.X.f T W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W T R X.$.K HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX0.$...R T W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W E W W W W W W W T R ..%.G HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXS 1...R T W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W E ~ ~ E W W W W W W W W W T R X.1.A HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX3.X.d T W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ E W W W W W W W W W W T R @.2.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX7.5.f T W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W T W %.z HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX3.X.s T W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W T R $.<.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX1...R W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ E E W W W W W W W W W W W W W R ..1.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX0 5.f T W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W T W 5.8 HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX8.$.s W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ` ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W T R %.N HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXi.#.R W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ` ` ` ` ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W R $.&.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXp.X.R W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ` ` ` ` ` ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W R @.<.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXp.X.R W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ` ` ` ` ` ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W R @.<.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXi.X.R W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W E ~ E ~ W R ~ ~ ~ ~ ~ ~ ` ` ` ` ` ` ` ` ` ` ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W R @.| HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX] #.R W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ! s e t d ~ ` ` ` ` ` ` =.=.=.` ` ` ` ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W R %.N HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXq %.R W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W E W E ~ ~ ~ ~ y l.=XI.x.) p a =.` ` =.=.=.=.=.=.` ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W R %.2 HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX5 5.d W W W W W W W W W W W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ~ ~ t (.jXVXNXuX@XF.W ` =.:.` W =.:.=.=.` ` ` ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W T R 5.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX1.f T W W W W W W W W W W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ~ ~ R Q eXDXSXSXDXgX#Xa ` =.=.;.q.W a a R ` ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W T W %.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX3...T W W W W W W W W W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ~ ~ ~ ` a a.NXSXGXGXAXNXV.a :.:.f c.tX*XE.n.9.R ~ ` ` ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W T @.@.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXD #.R W W W W W W W W W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ` t H.VXSXGXGXDXmXy.f :.:.a I.hXBXCXNXiX^.' W ` ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W R %.g HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX5.d W W W W W W W W W W W W W W W W W W W W W W W W W E ~ W ~ ~ ~ ~ ~ ~ ~ ~ ~ ` ` ` i |.CXGXGXGXCX3X~ ` :.:.R %XCXSXGXAXNX>XW ~ ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W W R 5.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX2.W T W W W W W W W W W W W W W W W W W W W W W W W W ~ ~ ~ s t e a W ~ ` ` ` ` ` ` W ! eXFXGXGXSXVX[.d :.:.~ w.uXFXGXGXSXVXW.a ` ` ` ` ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W W T ..@.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHX9 $.R W W W W W W W W W W W W W W W W W W W W W W E W ~ ~ ~ y F./.B.9.T t t a ~ =.` =.a a.hXDXGXGXSXNXA.d :.e.R v.NXSXGXGXSXNXm.a =.` ` ` ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W R %.= HXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHX6.d W W W W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ W i &XjXNXfX:X].B.q.T t a d e K.VXSXGXGXDXaXd.W e.e.d E.VXSXGXGXDXvXw.W =.` ` ` ` ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W W W %.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXK X.T W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ~ a ) uXDXSXFXFXCXNXfX:X_.B.q.r .XFXGXGXGXCX3X=.=.e.,.~ %XCXGXGXGXCX1XW ` =.` ` ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W W T $.m HXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHX5.R W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ~ ~ t x.NXSXGXGXGXSXSXDXFXCXNXmX8XcXSXGXGXGXCXW.e :.e.=.t.uXFXGXGXSXVXE.d :.=.=.` ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W W W R %.HXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHX^ X.T W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ~ ~ ~ ` t T.VXSXGXGXGXGXGXGXGXSXSXFXGXGXGXGXGXGXFX}.9.' W e v.VXSXGXGXSXNXm.d :.=.=.=.` ` ` ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W W T @.P HXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHX1.R W W W W W W W W W W W W W W W W E E ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ s ;XNXAXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXSXFXNX>X|.V.XXFXGXGXGXFXbXy.~ :.:.=.=.` ` ` ` ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W W W R %.HXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXH X.T W W W W W W W W W W W W W W E E ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ` ` R ' $XsXNXVXFXSXSXGXGXGXGXGXGXGXGXGXGXGXGXGXGXSXFXCXCXFXSXGXGXGXCXOXa :.:.:.=.=.=.` ` ` ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W T $.c HXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHX1.R W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ` ` ` ` ` ` ~ t.V.`.5XVXFXSXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXFX<X_ d d =.:.=.=.` ` ` ` ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W W R $.HXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHX8 $.T W W W W W W W W W W W E E ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ` ` ` ` ` =.=.~ f a a W b.xXFXSXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXSXFXmX~.x.T a =.:.=.` ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W W T $.3 HXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHX-.W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ` ` ` ` ` ` =.=.=.=.=.:.:.:.` e y.MXFXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXSXFXCXhX*Xn.p a :.=.` ` ` ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W W ~ O.HXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHX1.R W W W W W W W W W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ` ` ` ` ` =.` =.=.=.:.:.:.:.:.:.:.a .XFXGXGXGXGXGXGXGXGXGXFXFXSXSXGXGXGXGXGXGXGXGXGXGXGXSXAXCXhX%Xq.t ~ =.` ` ` ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W R %.HXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXb @.T W W W W W W W W E ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ` ` ` ` ` ` =.=.=.=.=.:.:.:.:.:.:.:.e.d [.CXGXGXGXGXGXGXGXGXSXZXnXNXNXBXDXSXSXGXGXGXGXGXGXGXGXGXSXAXCXhXH.t W :.` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W T @.x HXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHX<.R W W W W W E E E ~ ~ ~ ~ ~ ~ ~ ~ ~ ` ~ ` ` ` ` ` =.=.=.=.=.:.:.:.:.:.:.:.:.e.=.' >XFXGXGXGXGXGXGXGXSXCX{.e.P.'.2XvXNXBXDXSXGXGXGXGXGXGXGXGXGXSXDXjX~.y W =.` ` ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W W W @.HXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHX: 1.R W W W W E ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ` ` ` ` ` ` =.=.=.=.=.:.:.:.:.:.:.:.:.e.e.e.~ s.fXDXGXGXGXGXGXGXGXSXNXD.f =.=.,.M.L.oXaXVXDXSXGXGXGXGXGXGXGXGXGXAXVX(.t ~ ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W R %. HXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXl #.T W W W E ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ` ` ` ` ` ` =.=.=.=.:.:.:.:.:.:.:.:.:.e.e.e.e.r.W H.NXSXGXGXGXGXGXGXGXDXzXg.r.f.f.f.r.=.=.g.`.fXBXAXGXGXGXGXGXGXGXGXGXAXjXH.t =.` ` ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W T $.6 HXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHX~ ..W W W W E ~ ~ ~ ~ ~ ~ ~ ~ ` ` ` ` ` ` =.=.=.=.=.:.:.:.:.:.:.:.e.e.e.e.e.e.e.r.W |.CXGXGXGXGXGXGXGXGXBX1X,.f.f.f.f.h.h.f.,.~ d.3XVXAXGXGXGXGXGXGXGXGXGXDXsX' f ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W ..~ HXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHX$.R W W W W W E ~ ~ ~ ~ ~ ` ` ` ` ` ` =.=.=.=.=.=.:.:.:.:.:.:.:.e.e.e.e.e.r.r.r.,.w.>XFXGXGXGXGXGXGXGXSXNX`.=.f.h.h.h.h.f.f.f.f.=.~ ,XVXSXGXGXGXGXGXGXGXGXSXVXT.y ` ` ` ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W R $.HXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXX %.T W W W W W E ~ ~ ~ ~ ~ ` ` ` ` =.=.=.=.=.:.:.:.:.:.:.:.:.e.e.e.e.e.e.r.r.r.u.=.x.fXDXGXGXGXGXGXGXGXSXmXA.,.h.h.h.k.k.h.f.f.f.f.:.~ 5XFXGXGXGXGXGXGXGXGXGXCX:XW ~ ` ` ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W T $.. HXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHX8 $.T W W W W W W E ~ ~ ~ ~ ~ ` ` ` =.=.=.:.:.:.:.:.:.:.:.e.e.e.e.e.r.r.r.r.r.u.u.~ K.NXSXGXGXGXGXGXGXGXDXzXj.r.k.k.k.k.k.h.f.f.f.f.f.W V.VXSXGXGXGXGXGXGXGXGXDXuXw.f ` ` ` ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W T $.3 HXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXY ..W W W W W W W E ~ ~ ~ ~ ~ ~ ` ` ` =.=.=.:.:.:.:.:.e.e.e.e.e.e.r.r.r.r.u.u.u.u.~ |.CXGXGXGXGXGXGXGXGXBX2Xr.f.k.k.k.k.k.k.h.f.f.f.f.,.d.bXFXGXGXGXGXGXGXGXGXDXfXd.d =.` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W O.P HXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXO.W W W W W W W W W ~ ~ ~ ~ ~ ~ ` ` ` ` =.=.:.:.:.:.e.e.e.e.r.r.r.r.r.r.u.u.u.u.r.w.>XFXGXGXGXGXGXGXGXSXNX'.,.k.k.k.k.k.k.k.h.h.f.f.f.e.y.kXFXGXGXGXGXGXGXGXGXDXfXg.d =.` ` ` ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W O.HXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHX$.R W W W W W W W W E ~ ~ ~ ~ ~ ` ` ` ` =.=.=.:.:.:.:.e.e.r.r.r.r.u.u.u.u.u.u.f.=.b.fXDXGXGXGXGXGXGXGXSXmXJ.r.k.k.k.k.k.k.k.h.h.f.f.f.:.s.mXFXGXGXGXGXGXGXGXGXDXpXy.R =.` ` ` ~ ~ ~ ~ ~ E E W W W W W W W W W W W W W W W W W $.HXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHX1.R W W W W W W W W W ~ ~ ~ ~ ~ ~ ` ` ` =.=.=.:.:.:.:.e.e.e.r.r.u.u.u.u.u.u.u.f.=.K.NXSXGXGXGXGXGXGXGXFXxXM.u.k.k.k.k.k.k.k.k.h.f.f.k.~ K.VXSXGXGXGXGXGXGXGXGXCX5X=.~ =.=.` ` ` ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W $.HXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHX+ $.T W W W W W W W W W W ~ ~ ~ ~ ~ ~ ` ` ` =.=.=.:.:.:.:.e.e.e.r.r.u.u.u.u.f.f.f.=.|.CXGXGXGXGXGXGXGXGXFX<X~ u.k.N.N.N.k.k.k.k.k.k.k.=.;.uXFXGXGXGXGXGXGXGXGXSXBXoXR =.=.=.` ` ` ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W T $.O HXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXl @.T W W W W W W W W W W ~ ~ ~ ~ ~ ~ ` ` ` =.=.=.:.:.:.:.e.e.e.r.r.u.u.u.u.f.f.u.t.>XFXGXGXGXGXGXGXGXGXFX9XA.b.u.r.r.u.u.h.h.h.u.r.O.w.:XCXSXGXGXGXGXGXGXGXGXSXhXL.a :.=.=.=.` ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W T $.* HXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXV X.T W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ` ` ` =.=.=.:.:.:.:.e.e.e.r.r.u.u.u.u.f.,.b.fXFXGXGXGXGXGXGXGXGXSXFXVXpX*X[.R.V.M.g.d.d.g.b.T.pXCXSXGXGXGXGXGXGXGXGXGXDXpXe.~ :.:.=.=.` ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W T $.; HXHXHXHXHXHXHX",
"HXHXHXHXHXHXHX| O.T W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ` ` ` ` =.=.:.:.:.:.:.e.e.r.r.u.u.u.u.f.=.K.NXSXGXGXGXGXGXGXGXGXGXGXSXFXFXBXNXmXuX>X3X3XyXmXVXFXSXGXGXGXGXGXGXGXGXGXAXhXE.d :.:.:.=.=.` ` ` ` ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W T @.h HXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXc @.T W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ` ` ` ` =.:.:.:.:.:.e.e.e.r.r.u.u.u.u.=.|.BXGXGXGXGXGXGXGXGXGXGXGXGXGXGXSXSXSXFXFXFXFXFXSXSXGXGXGXGXGXGXGXGXGXGXAXNX>X~ =.e.:.:.:.=.` ` ` ` ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W @.h HXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXk @.T W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ` ` ` =.=.:.:.:.:.e.e.e.r.r.r.u.u.r.w.>XFXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXSXZXNXeXe.~ e.:.:.:.:.=.=.=.` ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W @.h HXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXc @.T W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ` ` ` =.=.=.:.:.:.:.e.e.e.r.r.u.u.=.x.fXFXGXGXGXGXGXGXGXGXGXFXFXSXSXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXFXCXfXoX:.~ r.e.:.:.:.:.:.=.` ` ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W @.h HXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXc @.T W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ` ` ` ` =.=.:.:.:.:.:.e.e.r.r.r.u.~ K.NXSXGXGXGXGXGXGXGXSXZX6XkXmXNXBXDXAXSXGXGXGXGXGXGXGXGXGXGXGXGXGXGX0X'.S.~ =.u.e.e.e.:.:.:.:.=.=.` ` ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W @.h HXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXk @.T W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ` ` ` ` =.=.:.:.:.:.e.e.e.r.r.u.~ |.CXGXGXGXGXGXGXGXGXFX4X,.k.D.Q.,XkXmXNXDXSXSXGXGXGXGXGXGXGXGXGXGXGX<X_ y r.u.r.r.e.e.e.:.:.:.:.=.=.` ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W @.h HXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXc @.T W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ` ` ` ` =.=.=.:.:.:.e.e.e.r.r.e.;.>XFXGXGXGXGXGXGXGXSXVX{.,.f.u.r.u.N.J.{.5XNXBXAXSXGXGXGXGXGXGXGXGXGXFXMXH.W r.u.r.e.e.e.:.:.:.:.=.=.` ` ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W W T @.h HXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXo.O.T W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ` ` ` =.=.=.:.:.:.:.e.e.e.r.O.s.fXFXGXGXGXGXGXGXGXSXmXJ.r.N.N.N.N.h.r.r.f.J.1XhXBXAXGXGXGXGXGXGXGXGXSXDXjX!.W e.u.r.e.e.e.:.:.:.:.=.=.` ` ` ` ~ ~ ~ ~ ~ E W W W W W W W W W W T @.g HXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXB X.T W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ` ` ` =.=.:.:.:.:.:.e.e.r.W H.NXSXGXGXGXGXGXGXGXDXuXM.u.k.k.N.N.N.N.N.h.,.e.D.>XNXSXGXGXGXGXGXGXGXGXSXZXjXE.W r.r.e.e.e.:.:.:.:.=.=.=.` ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W W T $.- HXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXl @.T W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ` ` ` =.=.=.:.:.:.:.e.e.r.W |.CXGXGXGXGXGXGXGXGXBX2Xr.h.k.k.k.k.k.k.k.k.k.h.,.,.|.NXZXGXGXGXGXGXGXGXGXGXZXgXV.~ u.e.e.e.:.:.:.:.:.=.=.` ` ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W T $.% HXHXHXHXHXHXHX",
"HXHXHXHXHXHXHX@ $.T W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ` ` ` ` =.=.:.:.:.:.e.:.' >XFXGXGXGXGXGXGXGXSXNX{.,.k.k.k.k.k.k.k.k.k.k.k.k.u.~ `.NXSXGXGXGXGXGXGXGXGXSXCX>X=.e.r.r.e.e.:.:.:.:.:.=.=.` ` ` ~ ~ ~ ~ ~ ~ W W W W W W W W W T $.. HXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHX%.R W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ` ` ` ` =.=.:.:.:.:.e.~ s.fXFXGXGXGXGXGXGXGXSXNXJ.,.k.k.k.k.k.k.k.k.k.k.h.h.k.u.O.2XCXGXGXGXGXGXGXGXGXGXAXhXV.~ u.r.e.e.e.:.:.:.:.=.=.=.` ` ` ~ ~ ~ ~ ~ W W W W W W W W W W $.HXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHX$.R W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ` ` ` ` ~ :.:.:.:.e.f Z.VXSXGXGXGXGXGXGXGXDXzXM.r.k.k.k.k.k.k.k.h.h.h.h.f.f.k.=.V.NXSXGXGXGXGXGXGXGXGXSXVX`.W r.e.e.e.e.:.:.:.:.=.=.=.` ` ` ~ ~ ~ ~ ~ ~ E W W W W W W W W $.HXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXO.W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ` ` =.~ Q a a W =.=.t XCXGXGXGXGXGXGXGXGXBX2Xr.f.k.k.k.k.k.k.h.h.h.h.f.f.f.f.r.y.kXFXGXGXGXGXGXGXGXGXGXBX,X~ :.e.e.e.:.:.:.:.:.:.=.=.` ` ` ` ~ ~ ~ ~ ~ E W W W W W W W ~ ..HXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXI O.W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ` a z.-X_.B.q.! u C.NXSXGXGXGXGXGXGXGXSXNX'.=.h.h.k.k.k.h.h.f.f.f.f.f.f.f.f.r.w.5XFXGXGXGXGXGXGXGXGXGXCX2X=.:.e.:.:.:.:.:.:.:.:.=.=.=.` ` ` ` ~ ~ ~ ~ ~ E W W W W W W O.P HXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXk @.T W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ~ t ).jXVXNXaX2X1XBXDXSXGXGXGXGXGXGXGXSXmXA.:.h.h.h.h.h.f.f.f.f.f.f.f.f.f.f.,.d.vXFXGXGXGXGXGXGXGXGXGXCX1X` =.:.:.:.:.:.:.=.=.=.=.=.=.` ` ` ` ~ ~ ~ ~ ~ ~ W W W W W T $.; HXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXo %.T W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ` y q.fXZXSXSXFXFXFXSXSXGXGXGXGXGXGXGXGXFXxXj.r.f.h.h.h.f.f.f.f.f.f.f.f.u.u.f.W B.NXSXGXGXGXGXGXGXGXGXSXBXoXW :.:.:.:.:.:.=.=.=.=.=.` ` ` ` ` ` ~ ~ ~ ~ ~ ~ W W W W W W %. HXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHX$.R W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ` e !.CXSXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXFX+Xd ,.f.h.h.h.f.f.f.f.f.f.u.u.u.f.,.T :XFXGXGXGXGXGXGXGXGXGXSXNXE.f :.:.:.:.:.=.=.=.=.` ` ` ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W W R $.HXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHX~ ..W W W W W W W W W W W W W W W W W W W W E ~ ~ a _ aXFXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXFX7XV.s.:.=.:.,.u.f.f.f.f.u.u.u.r.~ s ~.VXSXGXGXGXGXGXGXGXGXGXAXhXV.d :.:.=.=.=.=.=.` ` ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W W O.E HXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXg $.T W W W W W W W W W W W W W W W W W W W E ~ ~ e G.hXAXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXSXFXVXpX*X_.Z.x.t.:.` ~ ~ ~ ~ ~ ' x.*XVXSXGXGXGXGXGXGXGXGXGXGXDXuXw.W :.=.=.=.=.` ` ` ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W W W W T $.; HXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHX %.R W W W W W W W W W W W W W W W W W W W W ~ d T qXgXBXFXSXSXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXSXFXFXBXNXaX>X,X[._.T.T.E.|.:XNXCXSXGXGXGXGXGXGXGXGXGXGXSXVX Xd =.=.=.=.` ` ` ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ E W W W W W W R %.HXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHX@.W W W W W W W W W W W W W W W W W W W W W ~ R ` s.H.oXkXNXNXCXFXSXSXGXGXGXGXGXGXGXGXGXGXGXGXGXGXSXSXDXFXCXCXBXVXVXBXCXFXSXSXGXGXGXGXGXGXGXGXGXGXGXAXhXm.a :.` =.` ` ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W W W W W W W W @.HXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXx @.T W W W W W W W W W W W W W W W W W W W W ~ ~ y t a _ g.L.oXkXhXVXCXFXSXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXSXGXSXSXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXSXBX:Xf ~ ` ` ` ` ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ E W W W W W W W W W T $.h HXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHX%.R W W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ d a t a ' s.R.oXnXDXSXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXZXhXg.y =.` ` ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ E ~ E W W W W W W W W W W R %.HXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXO.~ W W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ` ` ~ W a a d ! <XFXGXGXGXGXGXFXSXSXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXAXjX`.y ` ` ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ E E W W W W W W W W W W W W ..O.HXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHX; $.T W W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ` ` ` =.~ p 2XFXGXGXGXSXZXMXNXVXFXSXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXZXjX%Xa W =.` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W T %.= HXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHX%.R W W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ~ ` ` =.d a.mXSXGXGXSXCXY.:.U..XkXDXSXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXGXSXAXBXjX Xa d =.` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W R $.HXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXv $.T W W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ` ` ` a C.NXSXGXGXDXNXg.a ~ ~ ~ '.FXGXGXGXGXFXFXFXDXDXSXSXSXSXSXSXSXSXDXBXhXuXZ.y d ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W T $.x HXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHX%.R W W W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ` ` =.i ].CXGXGXGXCX5X:.:.r.r.d [.FXGXGXGXFXlXXX3XzXmXNXNXNXNXNXNXNXfXuX,XJ.~ t ~ ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W R %.HXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXP @.T W W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ` ~ E :XFXGXGXGXVX|.R e.r.:.w.yXFXGXGXSXCX'.e ` t.g.m.J.L.R.R.L.A.x.;.d t f ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W W T @.m HXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHX%.R W W W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ` a q.fXDXGXGXSXNXJ.f e.r.~ x.hXSXGXGXSXNXV.d ` W f d d a a a a a a d ~ ` ` ~ ~ ~ ~ ~ ~ ~ ~ E E W W W W W W W W W W W W W W W W W W W W W R %.HXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXP $.T W W W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ` t C.VXSXGXGXDXfXg.W e.r.f K.VXSXGXGXDXbXt.W :.:.:.=.=.=.` ` ` ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ E E W W W W W W W W W W W W W W W W W W W W W W T $.v HXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHX%.W W W W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ t ].CXSXGXGXFX3X` =.e.e.R ).CXGXGXGXCX2XW ` =.=.=.` ` ` ` ` ` ~ ` ~ ~ ~ ~ ~ ~ ~ ~ ~ E E W W W W W W W W W W W W W W W W W W W W W W W W %.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHX* %.R W W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ R Q wXNXAXSXSXVX[.d :.e.=.;.yXFXGXGXSXVX`.a =.=.=.` ` ` ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W W W W W W T %.* HXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX@.O.T W W W W W W W W W W W W W W W W W W W W E ~ ~ ~ d ' @XyXNXVXNXdXZ.d :.e.R s.NXSXGXGXSXNXV.a =.` ` ` ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W W W W W W W W W T O.@.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX5.R W W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ! ~ d ' b.W.%XrXd.R :.:.a K.NXSXGXGXFXbXw.f =.` ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ E E W W W W W W W W W W W W W W W W W W W W W W W W W W W R 5.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXg %.R W W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ d a y R w.:.=.:.=.R =XgXDXSXAXBX1XR ~ ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W W W W W W W W W W T %.w HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX+.@.T W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ` ` ` ~ R ` :.:.=.` K.%XzXNXNXgXE.y ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W W W W W W W W W W W T @.o.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX%.~ T W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ` ` ` ` =.=.:.:.:.d d ;.b.R.&Xv.a ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W T ~ %.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX4.R T W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ` ` ` ` =.=.=.=.=.` R a y R ~ ` ~ ~ ~ ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W T R 5.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX& %.R W W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ` ` ` =.=.` ` ` ` ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W R 4.$ HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXk %.R W W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ` ` ` ` ` ` ` ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ E E E W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W R %.g HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXM %.R W W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ` ` ` ` ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W R %.n HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX{ $.R W W W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ` ` ` ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W R $.U HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX{ $.R W W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ` ` ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ E E W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W R %.M HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXM %.R W W W W W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W R %.n HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXk %.R T W W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W T W %.g HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX* 4.~ T W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W T ..4.# HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX%.@.T W W W W W W W W W W W W W W W ~ ~ ~ ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W T @.%.HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX .%.R T W W W W W W W W W W W W W E ~ ~ ~ ~ ~ ~ ~ E W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W T R %.} HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX7 4.O.T W W W W W W W W W W W W W ~ ~ ~ ~ E E W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W T O.%.- HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX+.%.W T W W W W W W W W W W W E ~ E E W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W T W %. .HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX- %.@.R T W W W W W W W W W W ~ W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W T R $.%.* HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXk %.@.R T W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W T R @.%.j HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXn %.@.R T W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W T W @.%.n HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXk $.$.~ R T W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W T R ..$.$.j HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX- O.%.@.W T T W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W T T W @.%.O.* HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXk @.%.$.O.R T T W W W W W W W W W W W W W W W W W W W W W W T T R O.$.%.@.h HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX; E $.%.$.O.~ W W T T T T T T T T T T T T T T W W W O.$.$.$.E ; HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX ; P ..$.$.$.$.$.@.@.@.@.@.@.@.@.$.$.$.$.$.O.P ; . HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXO % ; g h h h h h h h ; % O HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX",
"HXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHXHX"
};

BIN
share/pixmaps/bitcoin16.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 827 B

181
share/pixmaps/bitcoin16.xpm

@ -1,181 +0,0 @@
/* XPM */
static char *bitcoin__[] = {
/* columns rows colors chars-per-pixel */
"16 16 159 2",
" c #CA7C1E",
". c #CB7D1E",
"X c #D1811E",
"o c #D0801F",
"O c #D1801F",
"+ c #D3821F",
"@ c #D7831F",
"# c #EE8D18",
"$ c #F4931F",
"% c #D78625",
"& c #D88520",
"* c #D98521",
"= c #D98620",
"- c #D78B2D",
"; c #DF8D2A",
": c #DF8F2F",
"> c #DF943B",
", c #D8913C",
"< c #D8923E",
"1 c #DF953E",
"2 c #E28B23",
"3 c #E38B23",
"4 c #EA9023",
"5 c #EB9023",
"6 c #ED9122",
"7 c #ED9123",
"8 c #EE9123",
"9 c #EE9223",
"0 c #F39421",
"q c #F19423",
"w c #F39523",
"e c #F79521",
"r c #F59422",
"t c #F49623",
"y c #F69622",
"u c #F79623",
"i c #F09324",
"p c #F19424",
"a c #F19525",
"s c #F49624",
"d c #F59625",
"f c #F49725",
"g c #F79624",
"h c #F79724",
"j c #F69725",
"k c #F79725",
"l c #F69726",
"z c #F79726",
"x c #F89621",
"c c #F89722",
"v c #F89723",
"b c #F89724",
"n c #F89824",
"m c #F89825",
"M c #F99825",
"N c #F89925",
"B c #F89926",
"V c #F89927",
"C c #F99927",
"Z c #F0972E",
"A c #F7992A",
"S c #F79A2B",
"D c #F79B2C",
"F c #F69A2D",
"G c #F79D2F",
"H c #F89929",
"J c #F89A28",
"K c #F89A29",
"L c #F99A29",
"P c #F99B29",
"I c #F89A2A",
"U c #F89A2B",
"Y c #F99B2B",
"T c #F89B2C",
"R c #F89C2C",
"E c #F99C2D",
"W c #F99C2E",
"Q c #F89D2E",
"! c #F99D2F",
"~ c #E29335",
"^ c #E49639",
"/ c #E2983F",
"( c #F79F35",
") c #F99E31",
"_ c #F89E32",
"` c #F99E32",
"' c #F9A033",
"] c #F9A035",
"[ c #F9A135",
"{ c #F9A036",
"} c #F9A136",
"| c #F9A137",
" . c #F3A03F",
".. c #F7A43F",
"X. c #F8A139",
"o. c #F9A23A",
"O. c #FAA33B",
"+. c #FAA43E",
"@. c #FAA43F",
"#. c #EF9F41",
"$. c #EEA244",
"%. c #ECA34B",
"&. c #F8A440",
"*. c #F9A541",
"=. c #F9A644",
"-. c #F9A947",
";. c #F0A349",
":. c #F5A648",
">. c #F1A74E",
",. c #F7AA4F",
"<. c #E4A458",
"1. c #E4A55B",
"2. c #E8A95E",
"3. c #F2A950",
"4. c #F4AA52",
"5. c #FBAF55",
"6. c #E4A860",
"7. c #EAAC63",
"8. c #EBAF68",
"9. c #F2AF61",
"0. c #EBB16C",
"q. c #F6B568",
"w. c #E3AF71",
"e. c #EBBE89",
"r. c #E0BC93",
"t. c #E3C199",
"y. c #E6C59D",
"u. c #EAC89E",
"i. c #E7C8A2",
"p. c #EACBA6",
"a. c #EBCFAF",
"s. c #F1CCA0",
"d. c #E7CEB1",
"f. c #ECD1B0",
"g. c #E5D2BB",
"h. c #E8D2B8",
"j. c #DFDFDF",
"k. c #E7D5C1",
"l. c #E7D7C4",
"z. c #E5D7C7",
"x. c #E7DACB",
"c. c #EADAC8",
"v. c #E9DCCC",
"b. c #EDDFCE",
"n. c #E5DDD3",
"m. c #E4DFD9",
"M. c #ECE0D1",
"N. c #E4E1DD",
"B. c #EDE3D8",
"V. c #EAE4DD",
"C. c #ECE5DC",
"Z. c #E2E2E2",
"A. c #E5E2E0",
"S. c #E4E4E4",
"D. c #E7E7E7",
"F. c #EAEAE9",
"G. c gray92",
"H. c #EEEEEE",
"J. c None",
/* pixels */
"J.J.J.J.J.J.J.1 > J.J.J.J.J.J.J.",
"J.J.J.J.J./ ..| ' ( ~ J.J.J.J.J.",
"J.J.J.< *.{ V $ r U W _ - J.J.J.",
"J.J., o.J 0 # <.w.$.F N H % J.J.",
"J.J.o.T e 1.r.k.x.t.S z B u J.J.",
"J.^ [ Y ! #.z.H.M.n.0.d n m 2 J.",
"J.X.) | =. .h.B.5.f.j.;.v B d J.",
": Q M ` &.>.A.V.p.c.l.4.E n d = ",
"; I b A Z 2.D.s.u.F.a.-.} C w & ",
"J.l g y 6.m.G.q.3.b.Z.,.] D 8 J.",
"J.3 k c %.d.C.v.N.S.y.@.L a * J.",
"J.J.j z x 8.i.g.e.9.+.W t 6 J.J.",
"J.J.+ s h G :.7.O.R B s 7 . J.J.",
"J.J.J.O i f P L K d p 5 J.J.J.",
"J.J.J.J.J.@ 9 q i 4 + J.J.J.J.J.",
"J.J.J.J.J.J.J.X o J.J.J.J.J.J.J."
};

BIN
share/pixmaps/bitcoin256.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

465
share/pixmaps/bitcoin256.xpm

@ -1,465 +0,0 @@
/* XPM */
static char *bitcoin___[] = {
/* columns rows colors chars-per-pixel */
"256 256 203 2",
" c #BE741B",
". c #C1761B",
"X c #C6791C",
"o c #CC7C1D",
"O c #D07F1D",
"+ c #C67B21",
"@ c #CC7E21",
"# c #D4821E",
"$ c #D9841F",
"% c #ED8E1D",
"& c #EF911F",
"* c #CF8022",
"= c #D48323",
"- c #DB8621",
"; c #DD8922",
": c #D58729",
"> c #D6882B",
", c #DE8C2A",
"< c #CE8C3C",
"1 c #D28934",
"2 c #D98E32",
"3 c #D28E3C",
"4 c #DF9132",
"5 c #D6903E",
"6 c #DD933B",
"7 c #E58C22",
"8 c #E98F23",
"9 c #E38F2B",
"0 c #E88F28",
"q c #ED9124",
"w c #E6922D",
"e c #EB942B",
"r c #EF982F",
"t c #F59624",
"y c #F89723",
"u c #F79826",
"i c #F89825",
"p c #F1972A",
"a c #F59A2C",
"s c #F89B2B",
"d c #E59534",
"f c #EA9632",
"g c #EE9933",
"h c #E3963B",
"j c #E6993D",
"k c #EC9C3B",
"l c #F49C33",
"z c #F99E32",
"x c #F29E3A",
"c c #F7A037",
"v c #F9A036",
"b c #F5A13C",
"n c #F9A33B",
"m c #CE9147",
"M c #D29245",
"N c #DC9641",
"B c #DD9846",
"V c #D2954B",
"C c #DC9A4B",
"Z c #E59C44",
"A c #EA9E43",
"S c #E39E4B",
"D c #E89F49",
"F c #F09F40",
"G c #EDA145",
"H c #E6A14D",
"J c #EBA34B",
"K c #F4A443",
"L c #F9A642",
"P c #F7A847",
"I c #FAA846",
"U c #F3A64A",
"Y c #F8A748",
"T c #F5A94D",
"R c #FAAA4B",
"E c #E6A454",
"W c #EBA552",
"Q c #EDA856",
"! c #E4A55B",
"~ c #E8A75B",
"^ c #E7A95E",
"/ c #EBA95B",
"( c #F0A751",
") c #F4AB53",
"_ c #FAAE53",
"` c #F4AE5A",
"' c #F8AF59",
"] c #FAB057",
"[ c #F6B15E",
"{ c #FAB25B",
"} c #DFAD6F",
"| c #DCAE77",
" . c #DFB27D",
".. c #E5AA64",
"X. c #E8AB61",
"o. c #E5AE6C",
"O. c #E6B06F",
"+. c #ECB16C",
"@. c #F5B365",
"#. c #FBB562",
"$. c #FBB867",
"%. c #F5B66B",
"&. c #FAB768",
"*. c #F4B86F",
"=. c #FBB96A",
"-. c #E1AE71",
";. c #E5B174",
":. c #EBB573",
">. c #EFB977",
",. c #E5B47A",
"<. c #EEBA7B",
"1. c #F3B770",
"2. c #F3B974",
"3. c #FBBC72",
"4. c #F3BC7B",
"5. c #F8BF7A",
"6. c #FAC079",
"7. c #DCB382",
"8. c #DFBB8F",
"9. c #DABB96",
"0. c #DBBD99",
"q. c #E2B682",
"w. c #E4B985",
"e. c #ECBD84",
"r. c #E3BB8B",
"t. c #EABF8C",
"y. c #F1BE83",
"u. c #E2BE92",
"i. c #D3BDA2",
"p. c #DEC09C",
"a. c #EEC28D",
"s. c #F4C286",
"d. c #F8C282",
"f. c #F3C48B",
"g. c #E7C297",
"h. c #ECC393",
"j. c #E2C29D",
"k. c #EAC69B",
"l. c #ECC89F",
"z. c #F1C694",
"x. c #F2C897",
"c. c #F1CA9B",
"v. c #DBC2A3",
"b. c #D6C2AB",
"n. c #DDC7AD",
"m. c #DEC9AF",
"M. c #D3C4B3",
"N. c #DDCAB3",
"B. c #D2C7B9",
"V. c #D6C9BA",
"C. c #DDCEBB",
"Z. c #DFD0BE",
"A. c #E2C5A2",
"S. c #E8C7A0",
"D. c #E6C9A5",
"F. c #EBCBA4",
"G. c #E2C7A8",
"H. c #E3CAAC",
"J. c #EBCDA9",
"K. c #EFD2AF",
"L. c #F3D1A7",
"P. c #F1D1A9",
"I. c #E4CEB3",
"U. c #E8CFB1",
"Y. c #E1CFBA",
"T. c #E6D0B6",
"R. c #E9D1B4",
"E. c #E4D2BC",
"W. c #EAD4BA",
"Q. c #F4D5B0",
"!. c #F4D9B9",
"~. c #CDCDCD",
"^. c #D5CCC3",
"/. c #D4CFCA",
"(. c #DED2C3",
"). c #D3D1CE",
"_. c #DED6CC",
"`. c #D5D5D5",
"'. c #DBD7D1",
"]. c #DEDAD4",
"[. c #DDDDDC",
"{. c #E3D5C3",
"}. c #E9D7C1",
"|. c #EBD9C4",
" X c #E1D6CA",
".X c #E3D9CD",
"XX c #EADDCD",
"oX c #E1DBD4",
"OX c #E8DFD4",
"+X c #E1DEDB",
"@X c #EDE3D7",
"#X c #E3E1DE",
"$X c #E8E3DC",
"%X c #F6E5D2",
"&X c #F4EBDF",
"*X c #E4E4E4",
"=X c #ECE7E2",
"-X c #EDE9E4",
";X c #ECECEC",
":X c #F0EBE7",
">X c #F4F4F4",
",X c #FEFEFE",
"<X c None",
/* pixels */
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XC C S H H J J J G J J J J J S S B M <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XV S J U T R Y I I L L n n n n n n n n n n n n n n n n L L I I U U J S M <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XC J T R Y L L n n v z z z z s s s s s s s s s s s s s s s s s s s z z z v v n n n L I U J B <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XV H T R I L n n v z z s s s u i i i i i i i i i i i i i i i i i i i i i i i i i i u u s s s z z v n n L I U Z <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XH T R I L n v z s s u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s s z v n n L K Z <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XV W R I L n v z s s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s z v n n L A < <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XV W R I n n z s s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s z z n L A <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XH R I n n z s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s z z n L Z <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XC T Y L n z s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s z v n K N <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XW R I n v s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s z n n A <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XW R L n z s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u i i i i i i i i i u s z z n k <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XV T Y n v s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u i i i i i i i i i i i u s s z n b 5 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XV ) I n v s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u i i i i i i i i i i i i i s s z v b 3 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XV ) I n v s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u i i i i i i i i i i i i i i u s z v b 3 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XT I n v s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u i u u u u u u u u i i i i i i i i i i i i i i i i i u s z v x <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XW R L v s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u u u u u i i i i i i i i i i i i i i i i i i u s z v k <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XS R L n s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u s s s s u u u u i i i i i i i i i i i i i i i i i i i s s z n h <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XT I n z u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s u s s s s u u u u u i i i i i i i i i i i i i i i i i i i u s s z c <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XH R n z s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i u s s z k <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XV T L n s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i u s z c 3 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XH I n z s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u i u u u u u u s s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i u s s z k <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XT L n s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i u s s c <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XS R n z s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i u s s z d <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XJ I n s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i u s s l <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XT L v s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s z <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XC Y n z u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s s 2 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XH I n s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s s s s s s s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s d <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XJ L n s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s g <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XT L v s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s l <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XR L z s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s s s s z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s z <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XR n z u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u s s s s s s s s s s s s s s s s s s s s s s z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i s s s <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XY n s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s s s z z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xm I n s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XM I n s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XI n s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XI n s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z z z z s s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XI n s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z z z z z z z s s s s s s s s s s s s u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XY n s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u i u u u u u u s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z z z v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u s s <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XR n s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s a t t a a s s s s s s s s z z z z z z z z z z z z z z z v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XY n z u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s a e f w 8 q t p a a a s s z z z z z z z z z z z z z v v v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u i p <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XU L z u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s p e M.B.9.o.Z e q q p p a l z z z z z z z z z z v v v v v v v v z z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u i e <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XJ L v u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s s t Z `.`.[.[.[.C.p.o.Z e q q a z z z z z z v v v v v v v v v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i s i w <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XB L v s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s s s a % ;.`.[.*X*X*X*X*X[.[.C.9.-.J z z z z z v v v v v v v v v v v v v z z z z z z z z s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u i : <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XI n s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s u s s s s s s s s s s s s s s a % v.[.*X-X;X;X;X;X*X*X[.`.`.v.s z z v v v v v c c c c n n v v v v v z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u i <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XI n s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u i u u u u u u s s s s s s s s s s s s s s s s s p e (.*X;X;X>X>X>X>X;X;X*X[.`.r.n n z v v v v c x l p l x x c c v v v v z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u i u <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XU n z u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u s s s s s s s s s s s s s s s s s s s t D [.*X;X>X>X>X>X>X>X;X*X[.`.@.n n v v v v v c g E | S k f r l l l z z z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u i e <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XS L z u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s s s s a q ;.*X;X>X>X,X,X,X,X>X>X;X*X_.R n v v v v v v x e 0.`.`.V.p.;.H f e e p l l z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u y , <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XI n s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s s s s z a q A.*X;X>X>X,X,X,X,X>X>X;X*XI.L n v v v v n n x g V.`.[.[.[.[.[.(.p.;.S f r l z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u y <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XY n s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s s s s s z z a e (.*X;X>X,X,X,X,X,X>X>X;X*Xa.n n v v v n n n l A `.[.*X*X-X-X*X*X*X[.`.V.9.K z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u i u <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XJ n z u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u u u s s s s s s s s s s s s s s s s s s s s s z z z p D [.-X;X>X,X,X,X,X,X>X>X-X[.%.n n n n n n n b p o.[.*X;X;X;X>X;X;X*X*X[.`.~.T z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u y 0 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XM L v u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u u s s s s s s s s s s s s s s s s s s s s z z z z z z q ;.*X;X>X>X,X,X,X,X,X>X;X*XoXR L n n n n n n b g u.*X-X;X>X>X>X>X>X;X*X*X[.N.L n z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u y <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XI n s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u u s s s s s s s s s s s s s s s s s s s s s z z z z z z l q A.*X;X>X>X,X,X,X,X>X>X;X*XI.L L n n n n n n b g C.*X;X>X>X,X,X,X>X>X;X*X[.g.L n z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u i u <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XG n z u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u u s s s u u a s s s s s s s s s s s s s s s z z z z z z z z a e _.*X;X>X,X,X,X,X,X>X>X;X*Xh.L L n n n n n n l G [.*X;X>X,X,X,X,X>X>X;X*X[.2.n n z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u y w <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XL v u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s a q q q & t p a a s s s s s s s s z z z z z z z z z z p D [.-X;X>X,X,X,X,X,X>X>X-X[.%.L n n n n n n b l o.*X;X>X>X,X,X,X,X,X>X;X*X]._ n v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i y <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XP n s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s t j i.7.! d q q q p a a a s s z z z z z z z z z z z z q ,.*X;X>X>X,X,X,X,X,X>X;X*XoXR L n n n n n n b g j.*X;X>X>X,X,X,X,X,X>X;X*XE.I n v z z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u y t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XZ n z u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u u s s s s s s s a % } `.`.`._.N.r.! d e q q p a a z z z z z z z z z z l e G.*X;X>X>X,X,X,X,X>X>X;X*XT.I L n n n n n n b k Z.*X;X>X,X,X,X,X,X>X>X;X*Xl.L n v v z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u y ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XL v s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s a % 0.`.[.*X*X*X*X*X'.m.w.! d e q q p l l z z z z z v l f X*X;X>X,X,X,X,X,X>X>X;X*Xh.L L n n n n L L x G [.*X;X>X,X,X,X,X,X>X>X;X*X4.n n v v v z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u i u <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XG n s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s p e C.[.*X*X;X;X;X;X*X*X*X*X'.N.r...j e e p a l l z z p H *X;X>X>X,X,X,X,X,X>X>X-X[.%.L L n n n L L L l ;.*X;X>X>X,X,X,X,X,X>X;X*X[._ L n v v v z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u y q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XL v u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u u s s s s s s s s s s s s t A [.*X;X;X>X>X>X>X;X;X;X;X*X*X*X*X].N.q.! d e e r p q ,.-X;X>X>X,X,X,X,X,X>X;X*XoX_ I L n L L L L K g j.*X;X>X>X,X,X,X,X,X>X;X*XE.Y L n v v v z z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XK n s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s a q -.[.*X;X>X>X>X>X>X>X>X>X>X;X;X;X;X*X*X*X*X_.I.r.o.Z w D.;X>X>X,X,X,X,X,X,X>X;X*XW.R I L L L L L L K k Y.*X;X>X,X,X,X,X,X>X>X;X*Xl.L L n v v v v v z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u y q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X3 n z u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s a q j.*X;X>X>X,X,X,X,X,X,X>X>X>X>X>X>X;X;X;X;X*X*X*X*X$X}.=X>X>X>X,X,X,X,X,X,X>X;X*Xx.I I L L L L L L x J [.*X;X>X,X,X,X,X,X>X>X;X*X4.L n n v v v v v z z z z z z s s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XL n s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s s p e (.*X;X>X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X>X>X;X;X;X;X;X>X>X>X>X,X,X,X,X,X,X,X>X>X;X&.L L L L L L L L x ;.*X;X>X>X,X,X,X,X,X>X;X*X[.' L n n n v v v v z z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u y t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X3 n z u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s s s s s s s s s a p A [.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X>X>X@Xb l x x K L L L L k j.*X;X>X>X,X,X,X,X,X>X;X*XE.R L n n n n v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XL n s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s s s s z q o.[.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X:XW.g.;.H k k k b F k {.;X>X>X,X,X,X,X,X>X>X;X*XS.I L n n n n v v v v v z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i y t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X5 n z u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s s s s s s s s s s s z a q 0.[.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X;X*X+XE.j.,.~ j A =X;X>X>X,X,X,X,X,X>X>X;X*X4.I L n n n n v v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XL n s i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s u s s s s s s s s s s s s s s s s s s s z z z a e V.[.*X-X;X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X;X;X*X*X*X*XXX}.;X>X>X,X,X,X,X,X,X>X>X;X#X{ I n n n n n n v v v v z z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i y t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xn z u i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s s s s s s s s s s s s z z z z u W ~.`.[.*X-X;X;X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X;X;X;X;X;X>X>X>X,X,X,X,X,X,X,X>X>X;X|.R I n n n n n n v v v v v z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XK n s i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s s s s s s z z z z z z s ( v.^.`.[.*X*X-X;X;X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X>X>X>X>X>X,X,X,X,X,X,X,X,X>X>X;XF.L L n n n n n n n v v v v z z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i y q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xn z u i i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z v c L _ %.t.D. X[.*X*X-X;X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X,X,X,X,X,X,X,X,X,X,X,X>X>X;X@.a x b b n n n n n v v v v z z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XG n s i i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z v n n L L R _ %.a.U.oX*X-X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X|.e.G g l c b n n n n v v v v z z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t 0 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XL v u i i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z z v v v v n L L L L R ' f..X*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X-X+XG...k g l b n n n v v v v z z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i y t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X6 n s i i i i i i i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z z v v v v v v v v n n n L L L L J.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X;X*X*X(.w.A g l c c v v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t = <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XK v s i i i i i i i i i i i i i i i i i i i i u u u u u u s s s s s s s s s s s s s s s s s s s s z s z z z z z z z z z z z z v v v v v v v v v v n n n n n L n z W.-X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X;X-X*X*X'.u.A r l x c v v v z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xn z u i i i i i i i i i i i i i i i i i u u u u u u s s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z v v v v v v v v v v n n n n n n n n n L z K *X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X;X;X*X*X].u.k r l c v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XA n s i i i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z z z v v v v v v v v n n n n n n n n n n n n n l U.;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X;X;X*X*X_.q.g p l z v z z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XL z u i i i i i i i i i i i i i u u u u u u u s s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z z v v v v v v v v v n n n n n n n n n n n n n n n l h.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X;X;X*X[.C.W p l c v z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i y t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xn s i i i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z z z v v v v v v v v v n n n n n n n n n n n n n n n b l e.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X;X;X;X;X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X;X*X*X[.w.r a l z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xk v s i i i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z z v v v v v v v v n n n n n n n n n n n n n n n n L L K g S.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X-X-X-X*X*X-X;X;X;X;X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X;X;X*X[.H.g a z z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t 0 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xn z u i i i i i i i i i u u u u u u u u s s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z z v v v v v v v n n n n n n n n n n n n n n n n L L L L b k {.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;Xf.3.x.R..X+X*X*X*X*X;X;X;X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X;X*X*X(.k p z z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i y t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X< n s i i i i i i i u u i u u u u u u s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z z z v v v v v v v v v n n n n n n n n n n n n n n L L L L L L L x H [.-X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X$.{ { { $.3.f.F.{.[.*X*X*X;X;X;X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X-X*X_.W p z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t @ <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xk v s i i i i i i i u u u u u u u s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z z v v v v v v v v v n n n n n n n n n n n n n n n L L L L L L L L x ;.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X-X|.{ ] _ ] { { { { $.3.h.R..X*X*X*X;X;X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X-X*X'.k p z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t 0 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xn z u i i i i u u u u u u u s s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z z z v v v v v v v v v n n n n n n n n n n n n n n L L L L L L L L L L k j.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XJ._ ] _ _ _ _ ] { { { #.$.$.f.T.oX*X*X;X;X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X-X*X_.l a z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xn s i i i i i u u u u u u s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z z z v z v v v v v v v v n n n n n n n n n n n n n n L L L L L L L L L L L K k (.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*Xs._ _ _ _ _ _ _ _ _ ] { { { { { =.l..X*X*X;X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X*XH.t z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xh v s i i i i i i u u u u s s s s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z z v v v v v v v v n n n n n n n n n n n n n n n L L L L L L L L L L L I I b W [.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X+X&.] _ _ _ _ _ _ _ _ _ _ _ _ ] { { { #.k.oX*X-X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X[.:.t z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xx z s i i i i i i i u u u s s s s s s s s s s s s s s s s s s z z z z z z z z z z z z z v v v v v v v v v n n n n n n n n n n n n n n n L L L L L L L L L L L I I I I x ,.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X{.{ { _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ] _ { J.*X*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X'.l s z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xn z u i i i i i i i u u u u s s s s s s s s s s s s s s s z z z z z z z z z z z z z v v v v v v v v v v n n n n n n n n n n n n n n n L L L L L L L L L L L I I I I P k A.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XF.{ { _ _ _ _ _ _ _ _ ] _ _ _ _ _ _ _ _ _ _ _ y.oX*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X[.t.u z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X1 n s i i i i i i i i u u u u u s s s s s s s s s s s s s s z z z z z z z z z z v z z v v v v v v v v n n n n n n n n n n n n n n n L L L L L L L L L L L I I I I I I K A (.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*Xs.{ ] _ _ _ _ _ ] ] ] ] ] _ _ _ _ _ _ _ _ _ _ _ ' .X*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X'.z z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xh v s i i i i i i i i i i u u u s s s s s s s s s s s z z z z z z z z z z z z z z v v v v v v v v n n n n n n n n n n n n n n n L L L L L L L L L L L I I I I I I I Y K W [.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X].&.{ ] _ _ _ ] ] ] ] ] ] ] _ _ _ _ _ _ _ _ _ _ _ R R oX*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X[.:.u z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xx z u i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z z z v v v z v v v v v v n n n n n n n n n n n n n n n n L L L L L L L L L L L I I I I I I I Y P x ,.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X{.#.{ _ _ _ _ ] ] ] ] ] ] ] ] _ _ _ _ _ _ _ _ _ _ _ I @.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XD.s z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xn z u i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z z v v v v v v v v v n n n n n n n n n n n n n n n L L L L L L L L L L L I I I I I I I Y I R R Y k j.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XF.{ { _ ' ] ] ] ] ] { { { ] ] ] _ _ _ _ _ _ _ _ R R _ n k.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X_.n z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xn s i i i i i i i i i i i u u u u u s s s s s s s s s s s z z z z z z v v v v v v v v v n n n n n n n n n n n n n n n L L L L L L L L L L I I I I I I I I I R R R R U G (.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*Xs.{ { ] ] ] ] { { { { { { ] ] ] _ _ _ _ _ _ _ _ R R R I T +X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X[.T z z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X6 v s i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v v n n n n n n n n n n n n n n n L L L L L L L L L L I I I I I I I I I R Y R R R R K W [.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X[.=.{ { ] ] ] { { { { { { { ] ] ] _ _ _ _ _ _ _ _ _ R R R K D.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X[.%.z z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t = <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xk z s i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n n n n n n L L L L L L L L L L L I I I I I I I I I R R R R R R R K ,.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X{.#.{ ] ] { { { { { { { { { { ] ] ] _ _ _ _ _ _ _ _ R R R K e.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X-X[.<.v v z z z z z z z s s s s s s s s s s s s u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xx z u i i i i i i i i i i i i i i u u u s s s s s s s s s s s s z z z z z z v v v v v n n n n n n n n n n L L L L L L L L L L L I I I I I I I I I I R R R R R R R R T G j.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XJ.{ { { { { { { { { { { { { { { ] ] ] _ _ _ _ _ _ _ _ R R K +.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X<.n v v z z z z z z s s s s s s s s s s s s u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xn s i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z z v v v v n n n n n n n n L L L L L L L L L L I I I I I I I I I I R R R R R R R R R R T G (.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*Xs.#.{ { { { { { { { { { { { { { ] ] ] ] _ _ _ _ _ _ _ _ R U / *X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*Xe.n n v v z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xv s i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z z v v v v n n n n n n n n n L L L L L L L L I I I I I I I I I R R R R R R R R R R R R K Q [.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X[.=.#.{ { { { { { { { { { { { { { ] ] ] ' _ _ _ _ _ _ _ _ R K +.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X<.n n v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X1 z s i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L L L L L I I I I I I I I R R R R R R R R R R R R R R R K ,.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X{.$.#.{ { { { { { { { { { { { { { { ] ] ] ] _ _ _ _ _ _ _ T K ,.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X-X[.>.n n v z z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t @ <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xd z s i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s s z z z z z z v v v v v n n n n n n n n n L L L L L I I I I I I I R R R R R R R R R R R R R R R T G A.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XJ.#.#.{ { { { { { { { { { { { { { { ] ] ] ] _ _ _ _ _ _ _ T G j.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X[.%.n n v v z z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t = <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xg z s i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L L L L L I I I I R R R R R R R R R R R R R R R _ _ T J (.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*Xf.#.{ { { { { { { { { { { { { { { { { ] ] ] _ _ _ _ _ _ _ T J X-X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X]._ L n v v v z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xx z u i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s s z z z z z z z v v v v n n n n n n n n n L L L L L L I I I I R R R R R R R R R R R R _ _ _ _ U Q [.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X#X3.#.{ { { { { { { { { { { { { { { { { { ] ] ] _ _ _ _ _ ) G ..*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X{.R L n v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xx z u i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L L L L L I I I I I R R R R R R R R _ R R _ _ _ _ U ,.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X|.=.#.{ { { { { { { { { { { { { { { { { { { ] ] ' _ _ _ _ T k E.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XH.L L n v v v v z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xv s i i i i i i i i i i i i i i i i i i i i u u u s s s s s s s s s s s s z z z z z z z v v v v n n n n n n n n n L L L L L I I I I I R R R R R R R R _ _ _ _ _ _ ) J j.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;Xc.] { { { { { { { { #.{ { { { { { { { { { { ] ] ] _ _ _ ( A w.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X-X[.a.L n n v v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xv s i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L L L L L I I I I I R R R R R R R R _ _ _ _ _ ) J Z.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;Xx.( Q ( ) ` [ [ { #.#.#.{ { { { { { { { { { { ] ] _ ) T D o.*X;X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X[.[ L n n n v v v v z z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xz s i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s s z z z z z z z v v v v n n n n n n n n n L L L L L L I I I I R R R R R R R R _ _ _ _ _ T / [.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;XOXI.u.O./ Q Q ` ` [ [ [ { { { { { { { { { ] ' ) ( J H r.*X-X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XE.R I n n n v v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xz s i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n n L L L L L I I I I I R R R R R R R R _ _ _ _ U ,.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X;X;X*X*X_.H.r.;.X./ Q Q ) ) ` ` ` ` ` ) ) ( J H W ,.{.*X;X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X[.y.I L n n n n v v v v z z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u t <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X1 z s i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L L L L L I I I I R R R R R R R R _ _ _ ) J j.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X;X;X;X*X*X*X*X].(.H.u.q.;.^ ^ ~ ~ E E ~ o.r.G. X*X*X;X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X_._ Y L n n n n n v v v z z z z z z z s s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i u t @ <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X2 z s i i i i i i i i i i i i i i i i i i i i i i i u u u s s s s s s s s s s s s z z z z z z z v v v v n n n n n n n n n L L L L L I I I I Y R R R R R R R R _ _ T J (.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X;X;X;X;X*X*X*X*X*X*X[.]..X X XoX+X*X*X*X-X;X;X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X[.f.R I n n n n n n v v v v z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t = <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X4 z s i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L L L L L I I I I R R R R R R R R _ _ U Q [.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X>X>X;X;X;X;X;X;X-X-X*X*X*X-X;X;X;X;X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X;X*X X_ R L n n n n n n v v v v z z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t = <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<Xd z s i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L L L L L I I I I I R R R R R R R R R K ,.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X>X>X>X>X>X>X>X;X;X;X>X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X[.%.R I L n n n n n n n v v v v z z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i t - <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<Xf z u i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z z v v v v n n n n n n n n L L L L L L I I I I R R R R R R R R T G j.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X>X>X>X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X;X*X[.k.R R L n n n n n n n n v v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i t ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<Xf s u i i i i i i i i i i i i i i i i i i i i i i i i i u u u s s s s s s s s s s s z z z z z z z z v v v v n n n n n n n n L L L L L L I I I I I R R R R R R R T G (.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X;X;X*X[.l.] _ I L L n n n n n n n n v v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i t ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<Xf s u i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L L L L L I I I I R Y R R R R R U W [.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X;X-X*X[.l.{ _ Y L L L n n n n n n n n v v v v v v z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i t ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<Xf s u i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s s z z z z z z z v v v v n n n n n n n n n L L L L L I I I I I R R R R R R K ,.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X;X*X*X].h.{ _ R L L L L L n n n n n n n n v v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i t ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<Xf s u i i i i i i i i i i i i i i i i i i i i i i i i i i u u u s s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L L L L L I I I Y I R R R R T G A.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X>X>X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X;X*X[.T.3.{ ] R I L L L L L n n n n n n n n n v v v z z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i t ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<Xf s u i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L L L L I I I I I Y R R R U G (.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X;X;X;X;X;X;X;X;X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X;X*XW.s.#.{ _ R I I L L L L L L n n n n n n n n v v v v z z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i t ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<Xf s u i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L L L L L I I I I R R R R K W [.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X-XQ.|.OX*X*X*X*X*X;X;X;X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X&X!.L.d.#.{ ] R R I I I L L L L L L n n n n n n n n n v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i i t ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<Xf s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z z v v v v n n n n n n n n L L L L L I I I I I Y R R K ,.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;XXX3.3.3.s.c.R..X[.*X*X*X-X;X;X;X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X%X{ L R _ _ R R R I I I I L L L L L L n n n n n n n n v v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i i t ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<Xf s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z z v v v v n n n n n n n n L L L L L L I I I I I R Y k j.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X-XK.&.=.=.&.=.3.3.d.c.R..X[.*X*X*X;X;X;X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;XJ.J K Y R R Y I I I I L L L L L L n n n n n n n n n v v v v z z z z z z z s s s s s s s s s s s s u u u i i i i i i i i i i i i i i i i i i i i i i i i t ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<Xw s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L L L L I I I I I R P A Z.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*Xf.$.#.#.#.#.&.&.=.=.3.3.f.F.}.+X*X*X*X;X;X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X;XOX:.K U R R I I I I I L L L L L L n n n n n n n n v v v v z z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i i i i t ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<Xw s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L L L L L I I I I Y K W [.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X-X+X3.$.#.{ { #.#.#.#.$.$.&.=.=.3.6.c.W.+X*X*X;X;X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X*Xj.K K R R I I I I I L L L L L n n n n n n n n v v v v v v z z z z z z s s s s s s s s s s s s u u u i i i i i i i i i i i i i i i i i i i i i i u t = <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<Xw s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L L L L L I I I P x ;.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X{.&.#.{ { { { #.#.#.#.#.#.#.#.$.$.=.=.5.J..X*X*X;X;X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X*XH.K K R R I I I I L L L L L L n n n n n n n n v v v v v z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i i i i i i i u t = <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X, s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s s z z z z z z z v v v v n n n n n n n n L L L L L L I I I P k j.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XJ.#.#.{ { { { #.#.#.#.#.#.#.#.{ #.#.$.$.$.=.z.{.*X*X;X;X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X;X*X*XC.U K R I I I I I L L L L L L n n n n n n n n v v v v v z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i i u q * <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X> s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L L L L L I I K A Z.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*Xf.#.#.{ { { { { #.#.#.#.{ { { { { { { #.#.#.#.$.z.{.*X*X;X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X*XC.b K Y I I I I L L L L L L n n n n n n n n n v v v v z z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i u q + <X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xs s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z z v v v v v n n n n n n n n L L L L L I I b J [.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X[.3.#.{ { { { { { #.#.#.{ { { { { { { { { { { #.#.#.$.F.+X*X;X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X[.H.b P I I I I I L L L L L n n n n n n n n n v v v v v z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xs s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L L L L I L x ;.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X{.$.#.{ { { { { { { { { { { { { { { { { { { { { { { #.{ 2.{.*X;X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X[.e.b Y I I I I L L L L L L n n n n n n n n v v v v z z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xs s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s s z z z z z z v v v v v n n n n n n n n L L L L L L K k j.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XJ.#.#.{ { { { { { { { { { { { { { { { { { { { { { { { { { { U.*X;X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X].T L Y I I I I L L L L L L n n n n n n n n v v v v v z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xs s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z z v v v v n n n n n n n n L L L L L K k Z.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*Xf.#.{ { { { { { { { { { { { { { { { { { { { { { { { { ] { { _ R.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X-X*XD.L R I I I I L L L L L L n n n n n n n n v v v v v z z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xa u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s s z z z z z z z v v v v n n n n n n n n n L L L L x J [.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X[.=.#.{ { { { { { { { { { { { { { { { { { { { { { ] ] ] ] ] { ' R T.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X[.` L I I I I I L L L L L L n n n n n n n n v v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i t 8 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xp s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L L L x ;.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X{.$.#.{ { { { { { { { { { { { { { { { { { { { ] ] ] ] ] ] ] _ ] _ R oX*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X-X[.g.n I Y I I I I L L L L L n n n n n n n n n v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i i i i t 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xe s i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s s z z z z z z v v v v v n n n n n n n n n L L K g j.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XJ.{ { { { { { { { { { { { { { { { { { { { { ] ] ] ] ] _ _ _ _ _ ] Y <.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X(.I I I I I I L L L L L L L n n n n n n n n v v v v v z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i u t ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X9 s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n n L L b k E.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*Xf.{ { { { { { { { { { { { { { { { { { { ] ] ] ] ] ] _ _ _ _ _ _ _ _ T .X-X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X[.[ L I I I L L L L L L L L n n n n n n n n n v v v v z z z z z z z s s s s s s s s s s s u u u u u i i i i i i i i i i i i i i u q = <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X: s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u s s s s s s s s s s s s z z z z z z z v v v v v n n n n n n n L L x G +X-X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X[.=.{ { ] { { { { { { { { { { { { { { ] ] ] ] ] ] _ _ _ _ _ _ _ _ _ _ P g.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X-X[.e.n I L L L L L L L L L L n n n n n n n n n v v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xs u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z l l l c c n n n n n n n n b g o.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X{.#.{ ] ] { { { { { { { { { { { ] ] ] ] ] ] ] ] _ _ _ _ _ _ _ _ _ _ _ Y +.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*Xg.L I L L L L L L L L L n n n n n n n n n n n v v v v z z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xs u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s s z z z z z l f j e r p l x n n n n n b b f H.-X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XJ.{ { ] ] ] { { { { { { { { { ] ] ] ] ] ' _ _ _ _ _ _ _ _ _ _ _ _ _ _ T Q #X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XD.I I L L L L L L L n n n n n n n n n n n n n v v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xp u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z l q 7.^.v. .E d f g l l x x k w ..*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*Xf.{ { ] ] ] ] { { { { { { { ] ] ] ] ] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ Y W +X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XI.I I L L L L L n n n n n n n n n n n n n n n v v v v v v z z z z z z z s s s s s s s s s s u u u u u i i i i i i i i i i i i t 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xe u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z p e /.`.[.[.[._.v.q.! j f w d ;.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X[.=.{ ] ] ] ] ] { { { { { ] ] ] ] ] ' _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ R R T W +X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XE.I L L L L n n n n n n n n n n n n n n v v v v v v v v v z z z z z z z s s s s s s s s s s s u u u u i i i i i i i i i i i u q ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X, s u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z l q -.[.[.*X*X*X*X*X*X*XoXE.E..X-X;X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X{.#.{ _ _ ] ] ] ] { ] ] ] ] ] ] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ R R R R K X.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XE.I L n n n n n n n n n n n n n n n n v v v v v v v v v z z z z z z z z s s s s s s s s s s s s u u u i i i i i i i i i i i t q @ <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xs u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s s z p e (.[.*X;X;X;X;X;X;X;X;X;X;X;X;X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XJ.{ { _ _ _ ] ] ] ] ] ] ] ] ' _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ R R R R R x q.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XD.R L n n n n n n n n n n n n n n n v v v v v v v v v z z z z z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xu u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s a q ! [.*X;X>X>X>X>X>X>X>X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*Xs.{ ] _ _ _ ] ] ] ] ] ] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ R R R R R R R T k G.*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XS.I L n n n n n n n n n n n n n v v v v v v v v v z z z z z z z z z z z z s s s s s s s s s s s s u u u u i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xp u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s a a 8 m.*X;X>X>X>X,X,X>X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X#X&.{ _ _ _ _ _ ] ] ] ] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ R R R R R R R R K A oX;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*Xh.L L n n n n n n n n n n v v v v v v v v v z z z z z z z z z z z z z s s s s s s s s s s s s s s s u u u i i i i i i i i i t 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X0 u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s a q j [.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X|.{ ] _ _ _ _ _ ] ] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ R R R R R R R R R U k u.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X-X[.2.L L n n n n n n n n n v v v v v v v v z z z z z z z z z z z z z s s s s s s s s s s s s s s s s s u u u u i i i i i i i u q = <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X= u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s a % u.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;Xc.R _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ R R R R R R R R R R T k D +X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X[.' L n n n n n n n n v v v v v v v z v v z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s u u u u i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xu u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s t w ].*X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;Xf.K G G U ) ) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ R R R R R R R R R R R U A j {.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X{.R L n n n n n n v v v v v v v v v z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s s u u u u i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xu i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s a % ;.[.-X;X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X-XXXH.w.X.J J J T ) ) ) _ _ _ _ _ _ _ _ R R R R R R R R R R R Y K k D Y.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XJ.L L n n n n v v v v v v v v z z z z z z z z z z z z z s z s s s s s s s s s s s s s s s s s s s s u u u u u u u i i i i u t 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X7 u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s p q (.*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X;X-X*X#X(.A.q...H J J U U T T T T R R R R R R R R R Y Y U K k A ;..X*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X-X[.4.L n n n v v v v v v v v z z z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i t q * <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xu u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s a % ! `.*X*X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X;X;X;X*X*X*X[.(.H.u.,.^ J D G A J K K U U U U K k k k A E w.Y.*X*X;X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X]._ L n v v v v v v v v v v z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xu i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u s s s s u q b.`.[.*X;X;X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X>X;X;X;X-X*X*X*X*X[._.N.A.u.;.;...E E E E ..;.q.j.I.+X*X*X;X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*XH.I L n v v v v v v v v z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s u u u u u u u u i i i i i i i i i t 8 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xq i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s t W ~.`.[.*X*X;X;X;X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X>X>X;X;X;X;X-X*X*X*X*X*X*X*X+X+X+X+X*X*X*X*X*X;X;X;X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X[.1.L n v v v v v v z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i u q ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X= i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s u K ,.j.C.[.[.*X*X*X;X;X;X;X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X>X>X>X>X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X XR L n v v v v v z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s u u u u u u u u i i i i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xi i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s z z L I [ e.J. X[.*X*X*X-X;X;X;X;X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X-X[.a.L n v v v z z z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i i i i i t 8 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xq i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s z c n n n Y @.a.D.{.[.*X*X*X-X;X;X;X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X>X>X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X]._ L n v z z z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s u u u u u u u i i i i i i i i i i i i i i i u q ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X@ i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s z c c n n I R @.e.J.{.[.*X*X*X-X;X;X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X;X*X[.a.L n v z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s s s u u u u u u u i i i i i i i i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xi i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s z z v n n L I R @.a.J. X*X*X*X;X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X_.R L n z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s s u u u u u u u i i i i i i i i i i i i i i i i i i t 8 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xq i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u s s s s s s s s s s s z z z v n n L L I _ %.a.R.OX;X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X[.2.L n z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s u s u u u u u u u u i i i i i i i i i i i i i i i i i i t q = <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xi i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z v n n L L I R _ @.P.>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X*X[.D.L L v z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s s z z z z z z z v v n L n u e.;X>X>X,X,X,X,X,X,X,X,X>X>X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X-X*X XR L n z z z z z z z z s s s s s s s s s s s s s s s s s s s s s s u u u u u u u i i i i i i i i i i i i i i i i i i i i i i u q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X- i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z z v v v l g {.;X>X>X,X,X,X,X,X,X,X>X>X>X>X;X;X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X;X-X*X'._ I n z z z z z z z s s s s s s s s s s s s s s s s s s s s s s u u u u u u i u u i i i i i i i i i i i i i i i i i i i i i i t q o <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xi i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s s z z z z z z z v v c l A #X;X>X>X,X,X,X,X,X,X>X>X>X=X;X-X-X-X;X;X;X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X;X-X*X].%.L L z z z z z z s s s s s s s s s s s s s s s s s s s s s s u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i t 8 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xq i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v l p o.*X;X>X>X,X,X,X,X,X>X>X;X=X=.5.c.W.oX*X*X-X;X>X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X;X*X*X_.%.I L z z z z z z s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i t q - <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xu i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s s z z z z z z z v l e u.*X;X>X>X,X,X,X,X,X>X>X;X|._ _ _ { #.4.l.}.$X;X>X>X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X;X;X*X[.E.{ I L v z z z z s s s s s s s s s s s s s s s s s s s s u u u u u u u u i u i i i i i i i i i i i i i i i i i i i i i i i i i i i t 8 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xq i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z z l r C.*X;X>X,X,X,X,X,X>X>X;X*XF.R R R R _ _ { { { 4.-X>X>X,X,X,X,X,X,X,X,X,X>X>X>X>X>X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X,X,X>X>X>X>X>X>X>X;X;X*X*X[.k._ I n z z z s s s s s s s s s s s s s s s s s s s s s s s u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xu i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z a k [.*X;X>X,X,X,X,X,X>X>X;X*X4.R I I I I R R R b U -X>X>X,X,X,X,X,X,X,X,X>X>X>X>X>X;X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X;X;X;X-X*X*X[.T.*.R L n z z z s s s s s s s s s s s s s s s s s s s s s u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s z z z z z z z p ..*X;X>X>X,X,X,X,X,X>X;X*X+X] R I L I I I I P x t.;X>X>X,X,X,X,X,X,X,X>X>X;X;X;X;X-X-X-X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X*X*X*X[.].U.4.R I L v z z z s s s s s s s s s s s s s s s s s s s s u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X@ u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s s z z z z z l q u.*X;X>X>X,X,X,X,X>X>X;X*XE.R Y L L I I I I K k I.-X;X>X,X,X,X,X,X,X>X>X;X|.f.J.W..X[.[.*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X*X[._.I.h.#.R L L n z z z s s s s s s s s s s s s s s s s s s s s u u u u u u u u i u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q . <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z l e C.*X;X>X,X,X,X,X,X>X>X;X*Xl.I I L L L I I P K A oX-X>X>X,X,X,X,X,X>X>X;X;Xs.R _ _ { #.4.y.S.l.T.{.{. XoXoXoXoX].oX{.{.E.k.a.2.{ _ I L n v z z s s s s s s s s s s s s s s s s s s s s s s u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X@ u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z a k [.*X;X>X,X,X,X,X,X>X>X;X[.2.I I L L L L I L x ^ *X;X>X>X,X,X,X,X,X>X>X;X*X#.I I I I Y I R I _ R _ ] { { [ { { { { ] _ R R I I L n n v z z z s s s s s s s s s s s s s s s s s s s s u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q . <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u s s s s s s s s s s s s z z z q ..*X;X>X>X,X,X,X,X,X>X;X*X]._ Y L L L L L I L k r.*X;X>X>X,X,X,X,X,X>X;X-X.XR L n n n n n n L L L L L L L n L n n n L n n n c v z z z z s s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u s s s s s s s s s s s s z z l q u.*X;X>X>X,X,X,X,X>X>X;X*XT.R I L L L L L L K k H.*X;X>X>X,X,X,X,X>X>X;X*XJ.L L n n n n n v v v v v v v v v z z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t 8 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xq u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s s z a e C.*X;X>X,X,X,X,X,X>X>X;X*Xk.I I n L L L L L b k ].*X;X>X,X,X,X,X,X>X>X;X*Xy.L n n n n v v v v v v v v v z z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s a p k ].*X;X>X,X,X,X,X,X>X>X-X[.2.L L n L L L L L l ^ [.-X>X>X,X,X,X,X,X>X;X*X[.[ L n n n v v v v v v v z z v z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t 8 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xq t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s a q ..[.*X;X>X,X,X,X,X,X>X;X*X]._ L L n L L L L K g r.*X;X>X>X,X,X,X,X,X>X;X*X{.R L n v v v v v v v z z z z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q - <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s a q 8.[.*X;X>X,X,X,X,X>X>X;X*XE.I L n n n L L L b g H.*X;X>X>X,X,X,X,X>X>X;X*XF.L L v v v v v v v z z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u q 8 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X; t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s a q N.[.*X;X>X>X>X,X>X>X>X;X*Xk.L L n n n n L L x k _.*X;X>X,X,X,X,X,X>X>X;X*Xy.n n v v v v v v z z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q # <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s a t k ).[.*X-X;X>X>X>X>X>X;X*X[.2.L L n n n n n b l ~ [.-X>X>X,X,X,X,X,X>X;X*X[.' L n v v v z z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s s s u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s t o.~.`.[.*X*X;X;X;X;X;X*X*X'.R L n n n n n n b g w.*X;X>X>X,X,X,X,X,X>X;X*X{.I n c v v z z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t 8 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X7 t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s U w.n._.[.[.*X*X*X*X*X*X[.Y.I L n n n n n n b g H.*X;X>X>X,X,X,X,X>X>X;X*XF.L n v z z z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q - <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s z z v I R *.h.I..X[.[.[.`.`.u.L n n n n n n n x k _.*X;X>X>X,X,X,X,X>X>X;X*X4.n n z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s s u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s z v c n n L I _ 2.h.N./.~.>.L n n n n n n b l E [.*X;X>X>X,X,X,X>X>X;X*X[.' n v z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t 8 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X7 t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s z z v n n n L R ' 2._ L n n n n n n b r 7.`.*X*X;X>X>X>X>X>X>X;X*X{.I n z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q - <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s s z z z v n n n n L n n n n n n n c l M.`.[.*X;X;X>X>X>X;X;X*X[.S.n n z z z z z z z z s s s s s s s s s s s s s s s s s s s s s u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s s z z z z z z z v v v v v n n n n z b M.`.`.[.*X*X;X;X;X;X*X*X[.<.n c z z z z z z s s s s s s s s s s s s s s s s s s s s s u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u q 8 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X; t u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s s z z z z z z z v v v v n n n n n n P %.a.H._.[.*X*X*X*X[.[.`._ n v z z z z s s s s s s s s s s s s s s s s s s s s u s u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t 8 # <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X8 t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z z v v v n n v v n n n L I R _ 1.a.I._.[.`.`.^.I n z z z s s s s s s s s s s s s s s s s s s s s u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v v v v v v n n n n n L I R 1.t.n.u.I v z s s s s s s s s s s s s s s s s s s s s s u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v v v v v v v v v z z z z n n n n L I I n z s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X# t t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s s z z z z z z z v v v v v v v z z z z z z z z z z z v v z z z s s s s s s s s s s s s s s s s s s s u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u t 8 X <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X; t u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s s z z z z z z z v v v v z z z z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s u s s u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t 8 - <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X8 t u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z v v v z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s s u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xq t u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z z z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s s s u u u u u i u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u s s s s s s s s s s s s z z z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z z z z z z z z s s s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XX t t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s s z z z z z z z z z s s s s s s s s s s s s s s s s s s s u u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XX t t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u s s s s s s s s s s s s z z z z z s s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xt t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s z z z s s s s s s s s s s s s s s s s s s s s s s u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xq t u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s s z s s s s s s s s s s s s s s s s s s s s s u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xq t u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xq t u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s s s s s s s s s s s s s s s s s s u s u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u t q 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X8 t t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s s s s s s s s s s s s s s s s u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u t 8 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X7 t t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u s s s s s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 8 - <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X; q t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s s s s s s s s s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 # <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X# q t u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s s s s s s s s u s u u u u u i u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 7 X <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xq t t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s s s s s s s u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u t 8 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X7 q t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s s s s u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 8 - <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X$ q t u i i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s s s s s s s s u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u t q 7 o <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xq t t i i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u u s s s s s s s s s s u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 8 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X; q t u i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u t q 7 # <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XX q q t i i i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s s u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 8 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X- q t t i i i i i i i i i i i i i i i i i i i i i i i i u u u u s s u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u t q 7 # <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X8 q t u i i i i i i i i i i i i i i i i i i i i i i u u u u s u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t q 8 7 <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X$ q q t u i i i i i i i i i i i i i i i i i i i i i u u u u u u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t t 8 7 o <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X- q t t i i i i i i i i i i i i i i i i i i i i i i u u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t t q 7 $ <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X7 q t t i i i i i i i i i i i i i i i i i i i u u u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t t q 7 ; <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XX 7 q t t i i i i i i i i i i i i i i i i i i u u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t t q 7 7 . <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XX 7 q t t u i i i i i i i i i i i i i i i u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t t q 7 7 . <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XX 7 q q t u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t t q 7 7 . <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X; q q t t i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u t q q 7 - <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X- 8 q t t u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t t q 8 7 $ <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xo 7 q q t t u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t t q q 7 7 o <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X$ 8 q q t t u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i t t q q 8 7 # <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X $ 8 q q t t u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u t t q q 8 7 $ <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X. $ 7 8 q t t t u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u t t t q 8 7 7 $ . <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XO ; 8 q q t t t t u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u t t t q q 8 7 7 # <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X # ; 8 8 q q t t t t t u i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i u t t t t q q 8 7 7 7 # <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<Xo $ 7 7 8 q q q q t t t t t t t t u u u u u u u u u u u t t t t t t t t q q q q 8 7 7 7 $ o <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X. O $ ; 7 7 8 8 8 q q q q q q q q q q q q q q q q q 8 8 8 7 7 7 ; $ O X <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<XX o o # $ $ $ $ $ - - $ $ # # # o X <X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X",
"<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X<X"
};

BIN
share/pixmaps/bitcoin32.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

140
share/pixmaps/bitcoin32.xpm

@ -1,140 +0,0 @@
/* XPM */
static char *bitcoin__[] = {
/* columns rows colors chars-per-pixel */
"32 32 102 2",
" c #CC7D1D",
". c #D5831F",
"X c #D48221",
"o c #D98621",
"O c #DC8820",
"+ c #DC8D2C",
"@ c #D98F36",
"# c #D68F39",
"$ c #DD943E",
"% c #E28B23",
"& c #E98F24",
"* c #E18F2D",
"= c #ED9124",
"- c #EC942A",
"; c #F59624",
": c #F89724",
"> c #F79827",
", c #F89825",
"< c #F0962B",
"1 c #F59A2D",
"2 c #F99B2B",
"3 c #EC9732",
"4 c #EC9A37",
"5 c #E2963B",
"6 c #E6983A",
"7 c #EC9C3B",
"8 c #F69D33",
"9 c #F99E32",
"0 c #F49E3A",
"q c #F9A036",
"w c #F6A13C",
"e c #F9A33B",
"r c #D79341",
"t c #DC9641",
"y c #E39A43",
"u c #EA9D42",
"i c #EFA041",
"p c #EDA34B",
"a c #F5A443",
"s c #F9A643",
"d c #FAA846",
"f c #F2A64C",
"g c #F9AA4B",
"h c #E5A251",
"j c #ECA756",
"k c #EBA758",
"l c #FAAF57",
"z c #FBB057",
"x c #FBB25B",
"c c #DFB179",
"v c #E4AA65",
"b c #EBAE64",
"n c #E9AF69",
"m c #FBB665",
"M c #F1B46A",
"N c #F8B96D",
"B c #E5B071",
"V c #EBB777",
"C c #EEB877",
"Z c #E7B478",
"A c #EBB97D",
"S c #F0B671",
"D c #F2B871",
"F c #EFBC80",
"G c #E6BD8D",
"H c #EDBF88",
"J c #E6BF90",
"K c #F1C187",
"L c #F1C288",
"P c #E5C093",
"I c #EEC493",
"U c #E1C19B",
"Y c #E9C69C",
"T c #ECC89D",
"R c #F1C897",
"E c #DFC5A4",
"W c #DBCBB8",
"Q c #E2C7A7",
"! c #EBCBA6",
"~ c #E6CBAB",
"^ c #E9D2B7",
"/ c #E5D1B9",
"( c #EBD6BD",
") c #EFD9BE",
"_ c #DDD0C2",
"` c #DCD7D2",
"' c #DEDEDE",
"] c #ECDAC5",
"[ c #EDDECB",
"{ c #E9E0D5",
"} c #E7E0D9",
"| c #E9E2DB",
" . c #EFE8DF",
".. c #E5E5E5",
"X. c #EBE7E2",
"o. c #EFEAE6",
"O. c #ECECEC",
"+. c #F2ECE6",
"@. c #F1F0EE",
"#. c #F4F4F4",
"$. c #FBFBFB",
"%. c None",
/* pixels */
"%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.",
"%.%.%.%.%.%.%.%.%.%.%.%.%.%.t 5 5 $ %.%.%.%.%.%.%.%.%.%.%.%.%.%.",
"%.%.%.%.%.%.%.%.%.%.%.r u w q 9 9 9 8 4 # %.%.%.%.%.%.%.%.%.%.%.",
"%.%.%.%.%.%.%.%.%.y s e 9 2 , , , : > 2 9 q 5 %.%.%.%.%.%.%.%.%.",
"%.%.%.%.%.%.%.%.s q 2 , , , , : , > 2 2 > > 2 9 %.%.%.%.%.%.%.%.",
"%.%.%.%.%.%.t e 1 , , , , : : ; > 2 9 9 2 , , > 2 + %.%.%.%.%.%.",
"%.%.%.%.%.$ e 2 , , , , , , ; u u 8 1 1 2 > , , > > + %.%.%.%.%.",
"%.%.%.%.%.e 2 , , : > ; ; > < ` ` 0 c n 1 2 , , , > , %.%.%.%.%.",
"%.%.%.%.e 1 , , , , ; h v - 3 ..! w ' _ 9 2 > , , , > : %.%.%.%.",
"%.%.%.6 q , : , > 2 > W ..| [ #.H V ..D 9 9 2 , , , , , % %.%.%.",
"%.%.%.e 2 , > 2 2 2 9 b ! #.$.$.#.#.#.Y i 1 2 > , , , > ; %.%.%.",
"%.%.@ q > 2 2 2 9 q e q 0 o.$.+.) { #.#.| b 2 2 , , , , : X %.%.",
"%.%.4 9 2 2 9 q e e s w b O.#.( m x I @.$...f > > , , , : & %.%.",
"%.%.8 > 2 2 9 e s d g a P #.#.L x l a [ $.#.A 2 2 , : , , ; %.%.",
"%.+ 1 , , 2 2 q e d g f / $.#.T n k Z o.$.O.M 9 2 > , , , ; X %.",
"%.* 2 , , , 2 9 q e s f X.$.#.O.O.O.#.$.+.Y g e 9 2 , , , ; o %.",
"%.* 2 , , , 2 2 q e w n O.$.[ R ( O.$.$.[ d s e 9 2 2 , , ; o %.",
"%.+ 2 , , , > 2 8 8 1 G #.#.T m m N ] #.#.~ s e e 9 2 > : ; X %.",
"%.%.> , , , , 2 < v B [ $.O.m z z s b #.$...g e e q 9 2 ; = %.%.",
"%.%.= : , , , : 7 ' O.#.$.@.C j p u ~ #.$.} g q 9 9 2 2 ; % %.%.",
"%.%.o , , , , : 0 G ^ .$.#.O.X.{ X.#.$.#.Y e 9 2 2 > , ; %.%.",
"%.%.%., : , , , 2 2 2 M O.) ] #.#.#.#.O./ d 9 2 > , , ; = %.%.%.",
"%.%.%.& ; , , , , 2 ; Q ..g F O.K A H S s 9 2 > , : , ; o %.%.%.",
"%.%.%.%.; ; , , , , 2 E _ d ' ..d q q 9 2 > , : , , ; = %.%.%.%.",
"%.%.%.%.%.; : , , , 2 q d g U J e 2 2 > , , , , , ; = %.%.%.%.%.",
"%.%.%.%.%.o ; : , , , 2 9 q 9 q 9 > , : , , , , ; = . %.%.%.%.%.",
"%.%.%.%.%.%.. ; ; , , > 2 2 2 > , , , , , , , ; = %.%.%.%.%.%.",
"%.%.%.%.%.%.%.%.= ; : > 2 2 , , : , , , , ; ; & %.%.%.%.%.%.%.%.",
"%.%.%.%.%.%.%.%.%.. = ; > : , , , , ; ; = = X %.%.%.%.%.%.%.%.%.",
"%.%.%.%.%.%.%.%.%.%.%. % = ; ; ; ; & O %.%.%.%.%.%.%.%.%.%.%.",
"%.%.%.%.%.%.%.%.%.%.%.%.%.%. X X %.%.%.%.%.%.%.%.%.%.%.%.%.%.",
"%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%."
};

BIN
share/pixmaps/bitcoin64.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

242
share/pixmaps/bitcoin64.xpm

@ -1,242 +0,0 @@
/* XPM */
static char *bitcoin__[] = {
/* columns rows colors chars-per-pixel */
"64 64 172 2",
" c #8F6319",
". c #8F6A1A",
"X c #90651A",
"o c #916C1A",
"O c #AF7C1E",
"+ c #B1781E",
"@ c #9A7026",
"# c #AC801F",
"$ c #B1811F",
"% c #A9812B",
"& c #B08320",
"* c #BB8621",
"= c #BD8E22",
"- c #A58132",
"; c #FC8400",
": c #FD8A03",
"> c #FD8E0C",
", c #FF910E",
"< c #F98F14",
"1 c #F79117",
"2 c #FD9314",
"3 c #FC951B",
"4 c #FE9A1D",
"5 c #CA8E22",
"6 c #CC8E2A",
"7 c #D48D23",
"8 c #C39223",
"9 c #CE9925",
"0 c #D19C25",
"q c #D19329",
"w c #D5992B",
"e c #DD9D33",
"r c #D69F3C",
"t c #E29425",
"y c #E79925",
"u c #EA9926",
"i c #E69A2C",
"p c #F79625",
"a c #F99524",
"s c #F79825",
"d c #F89825",
"f c #F3962A",
"g c #F69B2C",
"h c #F89B2B",
"j c #E19F30",
"k c #EE9B34",
"l c #F49D33",
"z c #F99E32",
"x c #F39F3B",
"c c #DFA731",
"v c #D7A43D",
"b c #DCA63C",
"n c #EEA328",
"m c #FFA225",
"M c #FFAB26",
"N c #F3A529",
"B c #FEA429",
"V c #F4AB2A",
"C c #FFAC2A",
"Z c #FFB325",
"A c #FFB42C",
"S c #FFBB2D",
"D c #E3A335",
"F c #E5A438",
"G c #EDA03D",
"H c #F7A037",
"J c #FAA135",
"K c #F3AB31",
"L c #FEAB31",
"P c #F4A13C",
"I c #F9A33B",
"U c #FDB432",
"Y c #FFBF37",
"T c #FFC12F",
"R c #FFC230",
"E c #FFC03E",
"W c #DFAF41",
"Q c #ECA34D",
"! c #EDA84E",
"~ c #F2A343",
"^ c #FAA642",
"/ c #FAA846",
"( c #F1A74C",
") c #F6A94F",
"_ c #FAAA4A",
"` c #E7A451",
"' c #ECA754",
"] c #EFAA56",
"[ c #ECAC5B",
"{ c #F3AA52",
"} c #FCAE52",
"| c #FBB056",
" . c #FBB25C",
".. c #E7AB61",
"X. c #ECB067",
"o. c #E7B36D",
"O. c #EBB36C",
"+. c #F2B163",
"@. c #FCB460",
"#. c #F0B56B",
"$. c #E3B274",
"%. c #EDB672",
"&. c #EDB877",
"*. c #E2B57C",
"=. c #ECB97B",
"-. c #E4BA83",
";. c #EBBD83",
":. c #E7BF8D",
">. c #EBBD88",
",. c #E9C08C",
"<. c #E7C496",
"1. c #EBC393",
"2. c #EBC997",
"3. c #E7C49A",
"4. c #E9C69A",
"5. c #E3CA9D",
"6. c #E9C89E",
"7. c #DCC9AE",
"8. c #DDCBB2",
"9. c #E3C7A2",
"0. c #E5CAA3",
"q. c #E9CBA3",
"w. c #E5CEAB",
"e. c #E8CEAA",
"r. c #E4D4AC",
"t. c #EBD2AF",
"y. c #E7CFB2",
"u. c #E1D4B4",
"i. c #E8D5B6",
"p. c #E5D7BB",
"a. c #E9D6BB",
"s. c #E5D8B9",
"d. c #EAD8BE",
"f. c #F0D6B4",
"g. c #DFDFC6",
"h. c #E3D6C1",
"j. c #E9D7C0",
"k. c #E6DAC5",
"l. c #EBDCC7",
"z. c #E5DCCA",
"x. c #EADEC9",
"c. c #E8DFD0",
"v. c #D7E2D9",
"b. c #E3E0C9",
"n. c #EEE2CB",
"m. c #E6E1D4",
"M. c #E9E2D3",
"N. c #E4E4DC",
"B. c #E9E5DE",
"V. c #F4EDDE",
"C. c #DFE8E6",
"Z. c #DEEEE8",
"A. c #DFF2F3",
"S. c #DDFFFF",
"D. c #E1E6E0",
"F. c #E8E6E2",
"G. c #E8E9E5",
"H. c #E5EFEC",
"J. c #E8E9EA",
"K. c #EAF3EE",
"L. c #F3F3EB",
"P. c #E7EDF2",
"I. c #E8EEF3",
"U. c #E7F4F7",
"Y. c #E9F0F7",
"T. c #EBF5FD",
"R. c #E4FEFF",
"E. c #ECFCFF",
"W. c #F4F5F4",
"Q. c #F4FFFF",
"!. c #FEFFFF",
"~. c None",
/* pixels */
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.F L h C C A A A A C C h L e ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.D N C m d d a a p a a p a a d m m C N j ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.- K M m a p s d d d d d d d d d d d d s p d m M V % ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.Y M d a d d d d d d d d d d d d d d d d h h d s a d M U ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.E m 4 a d d d d d d d d d d d d d d d d d d h h h d d d a d M U ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.C 4 a d d d d d d d d d d d d d d d d d h h h h h h d d d d d a m C ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.W S a p d d d d d d d d d d d d d d d d h h h h g g h h h d d d d d p a S c ~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.v M a s d d d d d d d d d d d d d d d h h h h h g z z g h h d d d d d d s a C w ~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.r Z a d d d d d d d d d d d d d d d g 4 : 2 h z z z z z h h h h d d d d d d d a S q ~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.b Z a d d d d d d d d d d d d d d h h 4 x $.l a z H h h H z h h h d d d d d d d d a A w ~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.T a s d d d d d d d d d d d d h h h g : $.R.T.7.a B x f > a H h h d d d d d d d d s a R ~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.U a s d d d d d d d d d d d d h h h h z : e.!.!.p.2 3 8.D.5.' a h h h d d d d d d d d p d A ~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.U M p d d d d d d d d d d h h 1 : : 2 h h p B.!.Q.%., l J.!.R.-.> z h h h d d d d d d d d p C N ~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.S a d d d d d d d d d d h d 3 7.r.O.G p ; k E.!.T.( , [ E.!.T.~ 4 z h h h d d d d d d d d d a S ~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.V d s d d d d d d d d h h h 2 l E.!.Q.T.m.:.q.!.!.l.: : -.Q.!.c.a z z z g h h d d d d d d d d s m A ~.~.~.~.~.~.~.",
"~.~.~.~.~.~.@ S a d d d d d d d h h h h z : *.R.!.!.!.!.Q.!.!.!.V.,.Q d.!.Q.1.2 I z z h h h d d d d d d d d d a S X ~.~.~.~.~.~.",
"~.~.~.~.~.~.U d s d d d d d h h h h h g z a [ 5.M.Q.!.!.!.!.!.!.!.Q.E.!.!.Q.&.; 3 J H z h h h d d d d d d d d s h C ~.~.~.~.~.~.",
"~.~.~.~.~.~.S a d d d d h h h h h h z z z I d > < %.W.!.!.!.!.!.!.!.!.!.!.!.W.s.[ > 4 H g h h d d d d d d d d d a S ~.~.~.~.~.~.",
"~.~.~.~.~.i M p d d d h h h h g z z z z J H I I J > x.!.!.!.!.Q.T.E.Q.!.!.!.!.!.E.u.f 2 H h h h d d d d d d d d p C 7 ~.~.~.~.~.",
"~.~.~.~.~.C a d h h h h h g g z z z J J I I I I J P J.!.!.!.!.d.P =.e.G.E.!.!.!.!.Q.Z.f 2 z h h d d d d d d d d d d A ~.~.~.~.~.",
"~.~.~.~.~.A a h h h h h g z z z J H I I I I ^ / d X.E.!.!.!.Q.1.4 I J I ;.U.!.!.!.!.!.N.1 h g h h d d d d d d d d a S ~.~.~.~.~.",
"~.~.~.~.6 C p d h h h z z J J J I I I I ^ ^ ^ _ a 3.Q.!.!.!.E.#.I . ._ 3 ] K.!.!.!.!.E.O., z h h h d d d d d d d p A + ~.~.~.~.",
"~.~.~.~.i B d d h h h g z J I I I I ^ ^ ^ / / _ h k.!.!.!.!.J.) } . .| .3 6.Q.!.!.!.Q.q.> z g h h d d d d d d d d B t ~.~.~.~.",
"~.~.~.~.B d d d d h h h z z J I I ^ / / / _ _ ^ ( I.!.!.!.Q.d.I . . .| .d 1.Q.!.!.!.Q.q.2 z h h h d d d d d d d d d B ~.~.~.~.",
"~.~.~.~.C a d d d d h h g z J H I ^ ^ / _ _ } J %.E.!.!.!.Q.;.4 _ } | } J f m.!.!.!.!.Q.;.2 J z g h h d d d d d d d a A ~.~.~.~.",
"~.~.~.~.C a d d d d h h h z z J I I ^ ^ / _ } z 6.Q.!.!.!.!.n.<.&.+.{ ) ] h.Q.!.!.!.!.R.~ d H z z h h h d d d d d d a A ~.~.~.~.",
"~.~.~.~.A a d d d d d h h g z z H I I ^ / _ _ z k.!.!.!.!.!.!.Q.E.I.F.F.T.Q.!.!.!.!.E.9.2 I J z z h h h d d d d d d d A ~.~.~.~.",
"~.~.~.~.S a d d d d d h h h z z J I I ^ ^ / I ( P.!.!.!.!.Q.Q.!.!.!.!.!.!.!.!.!.!.E.w.d J I I J z h h h d d d d d d d A ~.~.~.~.",
"~.~.~.~.A a d d d d d d h h h z J J I I ^ / h O.E.!.!.!.Q.f.1.z.Y.E.!.!.!.!.!.!.L.! , ^ / I I H z z h h h d d d d d d A ~.~.~.~.",
"~.~.~.~.S p d d d d d d h h h z z J I I ^ / d <.Q.!.!.!.E.+.d _ +.>.k.E.!.!.!.!.Q.s.P J _ ^ I I J z z h h h d d d d d A ~.~.~.~.",
"~.~.~.~.C a d d d d d d d h h g z z H I I ^ d k.!.!.!.!.J.{ | @.} I I O.H.!.!.!.!.Q.C.l I ^ I I H J z g h h d d d d a A ~.~.~.~.",
"~.~.~.~.B a d d d d d d d h h h h z z J I J x P.!.!.!.Q.j.I . . . . .B { K.!.!.!.!.Q.0.a / ^ I I J z z h h h d d d a A ~.~.~.~.",
"~.~.~.~.B d d d d d d d d d h h h J h f 2 ; [ E.!.!.!.Q.1.I . . .| | .d 4.Q.!.!.!.!.m.z I ^ I I I J z h h h h d d d B ~.~.~.~.",
"~.~.~.~.u B d d d d d d d d h h z , ' v.q.X.M.!.!.!.!.E.#.^ . .| } } } d >.Q.!.!.!.!.F.x J I I I J J z z h h h d d C t ~.~.~.~.",
"~.~.~.~.7 C p d d d d d d d d h h : y.Q.Q.Q.!.!.!.!.!.B.d B / _ } } } J 1 k.!.!.!.!.!.c.s J I H J J z z z h h h h s A + ~.~.~.~.",
"~.~.~.~.~.A a d d d d d d d d h > ` R.!.!.!.!.!.!.!.!.L.q.=.[ ~ z h h l 0.Q.!.!.!.!.Q.q.2 I J J z z h h h h h h h a S ~.~.~.~.~.",
"~.~.~.~.~.C d d d d d d d d d d > ..g.Y.E.Q.!.!.!.!.!.!.Q.E.T.B.k.a.d.P.Q.!.!.!.!.!.E.[ 2 J z z z g h h h h d d d d C ~.~.~.~.~.",
"~.~.~.~.~.y C p d d d d d d d d g 3 > l [ <.x.W.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.!.Q.z.> z z z h h h h h d d d d p C 7 ~.~.~.~.~.",
"~.~.~.~.~.~.S a d d d d d d d d d h h 3 , > ; =.Q.!.W.T.Q.!.!.!.!.!.!.!.!.!.!.!.Q.A.g 2 z h h h h h h d d d d d a S ~.~.~.~.~.~.",
"~.~.~.~.~.~.C h s d d d d d d d d d h g z H : <.!.!.t.l &.V.!.!.Q.Q.Q.Q.!.Q.Q.E.b.l > H h h h h h d d d d d d s m C ~.~.~.~.~.~.",
"~.~.~.~.~.~.X S a d d d d d d d d d h h h h p N.!.Q.=.: < c.!.Q.2.&.e.a.d.i.6.[ < 2 z h h h h d d d d d d d d a S ~.~.~.~.~.~.",
"~.~.~.~.~.~.~.A h s d d d d d d d d d h g 2 ~ E.!.E.{ 2 [ E.!.T.l : 2 1 3 2 > > h z h h h h d d d d d d d d s m A ~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.S a d d d d d d d d d h h : -.R.!.B.h 2 =.Q.!.M.p z z z h h z g h h h d d d d d d d d d d d a S ~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.N C p d d d d d d d d d h 3 ' 2.N.9.2 3 z.!.!.q.> J z h h h h h h d d d d d d d d d d d d p C n ~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.S h p d d d d d d d d d z 3 : p l J g 8.T.S.O.> z h h h h h d d d d d d d d d d d d d p h S ~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.S a s d d d d d d d d h h z d h I J a P o.P d g h h h d d d d d d d d d d d d d d s a S ~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.* S a s d d d d d d d d h h g z J J h 3 > d z h h h d d d d d d d d d d d d d d s a S * ~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.$ T a s d d d d d d d h h h z z z h g g h h d d d d d d d d d d d d d d d d s a T O ~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.& S a p d d d d d d h h h z g h h h h h d d d d d d d d d d d d d d d d p a S # ~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.8 S d p d d d d d d h h g h h h h d d d d d d d d d d d d d d d d d p h S = ~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.S A a s d d d d h h h h h d d d d d d d d d d d d d d d d d s a A S ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.0 T m p d d d d h h h d d d d d d d d d d d d d d d d d p B S 9 ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.V S m a p d h d d d d d d d d d d d d d d d d p a m S V ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.o V S C d p p d d d d d d d d d d d d p p d C S N . ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.5 C S A B d d a a d d a a a d B A S C 5 ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.O t B A A A A A A A A B t O ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.",
"~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~."
};

BIN
share/pixmaps/check.ico

Binary file not shown.

Before

Width:  |  Height:  |  Size: 766 B

BIN
share/pixmaps/favicon.ico

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

BIN
share/pixmaps/nsis-header.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

BIN
share/pixmaps/nsis-wizard.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

BIN
share/pixmaps/send16.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

BIN
share/pixmaps/send16mask.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 B

BIN
share/pixmaps/send16masknoshadow.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 B

BIN
share/pixmaps/send20.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

BIN
share/pixmaps/send20mask.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 B

179
share/setup.nsi.in

@ -1,179 +0,0 @@
Name "@PACKAGE_NAME@ (@WINDOWS_BITS@-bit)"
RequestExecutionLevel highest
SetCompressor /SOLID lzma
# General Symbol Definitions
!define REGKEY "SOFTWARE\$(^Name)"
!define VERSION @CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@
!define COMPANY "Bitcoin Core project"
!define URL http://www.bitcoin.org/
# MUI Symbol Definitions
!define MUI_ICON "@abs_top_srcdir@/share/pixmaps/bitcoin.ico"
!define MUI_WELCOMEFINISHPAGE_BITMAP "@abs_top_srcdir@/share/pixmaps/nsis-wizard.bmp"
!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_RIGHT
!define MUI_HEADERIMAGE_BITMAP "@abs_top_srcdir@/share/pixmaps/nsis-header.bmp"
!define MUI_FINISHPAGE_NOAUTOCLOSE
!define MUI_STARTMENUPAGE_REGISTRY_ROOT HKLM
!define MUI_STARTMENUPAGE_REGISTRY_KEY ${REGKEY}
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME StartMenuGroup
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "@PACKAGE_NAME@"
!define MUI_FINISHPAGE_RUN $INSTDIR\bitcoin-qt.exe
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "@abs_top_srcdir@/share/pixmaps/nsis-wizard.bmp"
!define MUI_UNFINISHPAGE_NOAUTOCLOSE
# Included files
!include Sections.nsh
!include MUI2.nsh
!if "@WINDOWS_BITS@" == "64"
!include x64.nsh
!endif
# Variables
Var StartMenuGroup
# Installer pages
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuGroup
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
# Installer languages
!insertmacro MUI_LANGUAGE English
# Installer attributes
OutFile @abs_top_srcdir@/bitcoin-${VERSION}-win@WINDOWS_BITS@-setup.exe
!if "@WINDOWS_BITS@" == "64"
InstallDir $PROGRAMFILES64\Bitcoin
!else
InstallDir $PROGRAMFILES\Bitcoin
!endif
CRCCheck on
XPStyle on
BrandingText " "
ShowInstDetails show
VIProductVersion ${VERSION}.@CLIENT_VERSION_BUILD@
VIAddVersionKey ProductName "Bitcoin Core"
VIAddVersionKey ProductVersion "${VERSION}"
VIAddVersionKey CompanyName "${COMPANY}"
VIAddVersionKey CompanyWebsite "${URL}"
VIAddVersionKey FileVersion "${VERSION}"
VIAddVersionKey FileDescription ""
VIAddVersionKey LegalCopyright ""
InstallDirRegKey HKCU "${REGKEY}" Path
ShowUninstDetails show
# Installer sections
Section -Main SEC0000
SetOutPath $INSTDIR
SetOverwrite on
File @abs_top_srcdir@/release/bitcoin-qt.exe
File /oname=COPYING.txt @abs_top_srcdir@/COPYING
File /oname=readme.txt @abs_top_srcdir@/doc/README_windows.txt
SetOutPath $INSTDIR\daemon
File @abs_top_srcdir@/release/bitcoind.exe
File @abs_top_srcdir@/release/bitcoin-cli.exe
SetOutPath $INSTDIR\doc
File /r @abs_top_srcdir@/doc\*.*
SetOutPath $INSTDIR
WriteRegStr HKCU "${REGKEY}\Components" Main 1
# Remove old wxwidgets-based-bitcoin executable and locales:
Delete /REBOOTOK $INSTDIR\bitcoin.exe
RMDir /r /REBOOTOK $INSTDIR\locale
SectionEnd
Section -post SEC0001
WriteRegStr HKCU "${REGKEY}" Path $INSTDIR
SetOutPath $INSTDIR
WriteUninstaller $INSTDIR\uninstall.exe
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
CreateDirectory $SMPROGRAMS\$StartMenuGroup
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk" $INSTDIR\bitcoin-qt.exe
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" $INSTDIR\uninstall.exe
!insertmacro MUI_STARTMENU_WRITE_END
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)"
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayVersion "${VERSION}"
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" Publisher "${COMPANY}"
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" URLInfoAbout "${URL}"
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayIcon $INSTDIR\uninstall.exe
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" UninstallString $INSTDIR\uninstall.exe
WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoModify 1
WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoRepair 1
WriteRegStr HKCR "bitcoin" "URL Protocol" ""
WriteRegStr HKCR "bitcoin" "" "URL:Bitcoin"
WriteRegStr HKCR "bitcoin\DefaultIcon" "" $INSTDIR\bitcoin-qt.exe
WriteRegStr HKCR "bitcoin\shell\open\command" "" '"$INSTDIR\bitcoin-qt.exe" "%1"'
SectionEnd
# Macro for selecting uninstaller sections
!macro SELECT_UNSECTION SECTION_NAME UNSECTION_ID
Push $R0
ReadRegStr $R0 HKCU "${REGKEY}\Components" "${SECTION_NAME}"
StrCmp $R0 1 0 next${UNSECTION_ID}
!insertmacro SelectSection "${UNSECTION_ID}"
GoTo done${UNSECTION_ID}
next${UNSECTION_ID}:
!insertmacro UnselectSection "${UNSECTION_ID}"
done${UNSECTION_ID}:
Pop $R0
!macroend
# Uninstaller sections
Section /o -un.Main UNSEC0000
Delete /REBOOTOK $INSTDIR\bitcoin-qt.exe
Delete /REBOOTOK $INSTDIR\COPYING.txt
Delete /REBOOTOK $INSTDIR\readme.txt
RMDir /r /REBOOTOK $INSTDIR\daemon
RMDir /r /REBOOTOK $INSTDIR\doc
DeleteRegValue HKCU "${REGKEY}\Components" Main
SectionEnd
Section -un.post UNSEC0001
DeleteRegKey HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)"
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk"
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk"
Delete /REBOOTOK "$SMSTARTUP\Bitcoin.lnk"
Delete /REBOOTOK $INSTDIR\uninstall.exe
Delete /REBOOTOK $INSTDIR\debug.log
Delete /REBOOTOK $INSTDIR\db.log
DeleteRegValue HKCU "${REGKEY}" StartMenuGroup
DeleteRegValue HKCU "${REGKEY}" Path
DeleteRegKey /IfEmpty HKCU "${REGKEY}\Components"
DeleteRegKey /IfEmpty HKCU "${REGKEY}"
DeleteRegKey HKCR "bitcoin"
RmDir /REBOOTOK $SMPROGRAMS\$StartMenuGroup
RmDir /REBOOTOK $INSTDIR
Push $R0
StrCpy $R0 $StartMenuGroup 1
StrCmp $R0 ">" no_smgroup
no_smgroup:
Pop $R0
SectionEnd
# Installer functions
Function .onInit
InitPluginsDir
!if "@WINDOWS_BITS@" == "64"
${If} ${RunningX64}
; disable registry redirection (enable access to 64-bit portion of registry)
SetRegView 64
${Else}
MessageBox MB_OK|MB_ICONSTOP "Cannot install 64-bit version on a 32-bit system."
Abort
${EndIf}
!endif
FunctionEnd
# Uninstaller functions
Function un.onInit
ReadRegStr $INSTDIR HKCU "${REGKEY}" Path
!insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuGroup
!insertmacro SELECT_UNSECTION Main ${UNSEC0000}
FunctionEnd

15
share/ui.rc

@ -1,15 +0,0 @@
bitcoin ICON "pixmaps/bitcoin.ico"
#include "wx/msw/wx.rc"
check ICON "pixmaps/check.ico"
send16 BITMAP "pixmaps/send16.bmp"
send16mask BITMAP "pixmaps/send16mask.bmp"
send16masknoshadow BITMAP "pixmaps/send16masknoshadow.bmp"
send20 BITMAP "pixmaps/send20.bmp"
send20mask BITMAP "pixmaps/send20mask.bmp"
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"

20
src/Makefile.am

@ -23,8 +23,8 @@ BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config
BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS)
BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include
BITCOIN_INCLUDES += -I$(srcdir)/snark/build/include
BITCOIN_INCLUDES += -I$(srcdir)/snark/build/include/libsnark
BITCOIN_INCLUDES += -I$(srcdir)/snark
BITCOIN_INCLUDES += -I$(srcdir)/snark/libsnark
BITCOIN_INCLUDES += -I$(srcdir)/univalue/include
LIBBITCOIN_SERVER=libbitcoin_server.a
@ -34,19 +34,13 @@ LIBBITCOIN_CLI=libbitcoin_cli.a
LIBBITCOIN_UTIL=libbitcoin_util.a
LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a
LIBSECP256K1=secp256k1/libsecp256k1.la
LIBSNARK=snark/build/lib/libsnark.a
LIBSNARK=snark/libsnark.a
LIBUNIVALUE=univalue/libunivalue.la
LIBZCASH=libzcash.a
$(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*)
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F)
# A phony target is included here to ensure libsnark is built first, so that its
# header files are collated for use in later build steps.
# See https://stackoverflow.com/a/10726725
-include collate-libsnark
collate-libsnark: $(LIBSNARK)
LIBSNARK_CXXFLAGS = -fPIC -DBINARY_OUTPUT -DNO_PT_COMPRESSION=1 -fstack-protector-all
LIBSNARK_CONFIG_FLAGS = CURVE=ALT_BN128 NO_PROCPS=1 NO_DOCS=1 STATIC=1 NO_SUPERCOP=1 FEATUREFLAGS=-DMONTGOMERY_OUTPUT NO_COPY_DEPINST=1 NO_COMPILE_LIBGTEST=1
if HAVE_OPENMP
@ -54,10 +48,10 @@ LIBSNARK_CONFIG_FLAGS += MULTICORE=1
endif
$(LIBSNARK): $(wildcard snark/src/*)
$(AM_V_at) CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ install PREFIX=$(srcdir)/build DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64"
$(AM_V_at) CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64"
libsnark-tests: $(wildcard snark/src/*)
$(AM_V_at) CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ check PREFIX=$(srcdir)/build DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64"
$(AM_V_at) CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ check DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64"
$(LIBUNIVALUE): $(wildcard univalue/lib/*)
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue/
@ -149,6 +143,7 @@ BITCOIN_CORE_H = \
compressor.h \
consensus/consensus.h \
consensus/params.h \
consensus/upgrades.h \
consensus/validation.h \
core_io.h \
core_memusage.h \
@ -215,6 +210,7 @@ BITCOIN_CORE_H = \
utiltls.h \
validationinterface.h \
version.h \
wallet/asyncrpcoperation_mergetoaddress.h \
wallet/asyncrpcoperation_sendmany.h \
wallet/asyncrpcoperation_shieldcoinbase.h \
wallet/crypter.h \
@ -309,6 +305,7 @@ libbitcoin_wallet_a_SOURCES = \
utiltest.h \
zcbenchmarks.cpp \
zcbenchmarks.h \
wallet/asyncrpcoperation_mergetoaddress.cpp \
wallet/asyncrpcoperation_sendmany.cpp \
wallet/asyncrpcoperation_shieldcoinbase.cpp \
wallet/crypter.cpp \
@ -367,6 +364,7 @@ libbitcoin_common_a_SOURCES = \
chainparams.cpp \
coins.cpp \
compressor.cpp \
consensus/upgrades.cpp \
core_read.cpp \
core_write.cpp \
hash.cpp \

1
src/Makefile.gtest.include

@ -25,6 +25,7 @@ zcash_gtest_SOURCES = \
gtest/test_random.cpp \
gtest/test_rpc.cpp \
gtest/test_transaction.cpp \
gtest/test_upgrades.cpp \
gtest/test_validation.cpp \
gtest/test_circuit.cpp \
gtest/test_txid.cpp \

71
src/bitcoin-tx.cpp

@ -7,6 +7,7 @@
#include "clientversion.h"
#include "coins.h"
#include "consensus/consensus.h"
#include "consensus/upgrades.h"
#include "core_io.h"
#include "keystore.h"
#include "primitives/transaction.h"
@ -71,7 +72,7 @@ static bool AppInitRawTx(int argc, char* argv[])
strUsage += HelpMessageOpt("nversion=N", _("Set TX version to N"));
strUsage += HelpMessageOpt("outaddr=VALUE:ADDRESS", _("Add address-based output to TX"));
strUsage += HelpMessageOpt("outscript=VALUE:SCRIPT", _("Add raw script output to TX"));
strUsage += HelpMessageOpt("sign=SIGHASH-FLAGS", _("Add zero or more signatures to transaction") + ". " +
strUsage += HelpMessageOpt("sign=HEIGHT:SIGHASH-FLAGS", _("Add zero or more signatures to transaction") + ". " +
_("This command requires JSON registers:") +
_("prevtxs=JSON object") + ", " +
_("privatekeys=JSON object") + ". " +
@ -158,12 +159,21 @@ static void RegisterLoad(const string& strInput)
static void MutateTxVersion(CMutableTransaction& tx, const string& cmdVal)
{
int64_t newVersion = atoi64(cmdVal);
if (newVersion < CTransaction::MIN_CURRENT_VERSION || newVersion > CTransaction::MAX_CURRENT_VERSION)
if (newVersion < CTransaction::SPROUT_MIN_CURRENT_VERSION || newVersion > CTransaction::SPROUT_MAX_CURRENT_VERSION)
throw runtime_error("Invalid TX version requested");
tx.nVersion = (int) newVersion;
}
static void MutateTxExpiry(CMutableTransaction& tx, const string& cmdVal)
{
int64_t newExpiry = atoi64(cmdVal);
if (newExpiry >= TX_EXPIRY_HEIGHT_THRESHOLD) {
throw runtime_error("Invalid TX expiry requested");
}
tx.nExpiryHeight = (int) newExpiry;
}
static void MutateTxLocktime(CMutableTransaction& tx, const string& cmdVal)
{
int64_t newLocktime = atoi64(cmdVal);
@ -323,10 +333,39 @@ vector<unsigned char> ParseHexUO(map<string,UniValue>& o, string strKey)
return ParseHexUV(o[strKey], strKey);
}
static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
static CAmount AmountFromValue(const UniValue& value)
{
int nHashType = SIGHASH_ALL;
if (!value.isNum() && !value.isStr())
throw runtime_error("Amount is not a number or string");
CAmount amount;
if (!ParseFixedPoint(value.getValStr(), 8, &amount))
throw runtime_error("Invalid amount");
if (!MoneyRange(amount))
throw runtime_error("Amount out of range");
return amount;
}
static void MutateTxSign(CMutableTransaction& tx, const string& strInput)
{
// separate HEIGHT:SIGHASH-FLAGS in string
size_t pos = strInput.find(':');
if ((pos == 0) ||
(pos == (strInput.size() - 1)))
throw runtime_error("Invalid sighash flag separator");
// extract and validate HEIGHT
string strHeight = strInput.substr(0, pos);
int nHeight = atoi(strHeight);
if (nHeight <= 0) {
throw runtime_error("invalid height");
}
// extract and validate SIGHASH-FLAGS
int nHashType = SIGHASH_ALL;
string flagStr;
if (pos != string::npos) {
flagStr = strInput.substr(pos + 1, string::npos);
}
if (flagStr.size() > 0)
if (!findSighashFlags(nHashType, flagStr))
throw runtime_error("unknown sighash flag/sign option");
@ -394,7 +433,10 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
if ((unsigned int)nOut >= coins->vout.size())
coins->vout.resize(nOut+1);
coins->vout[nOut].scriptPubKey = scriptPubKey;
coins->vout[nOut].nValue = 0; // we don't know the actual output value
coins->vout[nOut].nValue = 0;
if (prevOut.exists("amount")) {
coins->vout[nOut].nValue = AmountFromValue(prevOut["amount"]);
}
}
// if redeemScript given and private keys given,
@ -413,6 +455,9 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
// Grab the consensus branch ID for the given height
auto consensusBranchId = CurrentEpochBranchId(nHeight, Params().GetConsensus());
// Sign what we can:
for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
CTxIn& txin = mergedTx.vin[i];
@ -422,17 +467,19 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
continue;
}
const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
const CAmount& amount = coins->vout[txin.prevout.n].nValue;
txin.scriptSig.clear();
SignatureData sigdata;
// Only sign SIGHASH_SINGLE if there's a corresponding output:
if (!fHashSingle || (i < mergedTx.vout.size()))
SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType), prevPubKey, sigdata, consensusBranchId);
// ... and merge in other signatures:
BOOST_FOREACH(const CTransaction& txv, txVariants) {
txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
}
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i)))
BOOST_FOREACH(const CTransaction& txv, txVariants)
sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i), consensusBranchId);
UpdateTransaction(mergedTx, i, sigdata);
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount), consensusBranchId))
fComplete = false;
}
@ -466,6 +513,8 @@ static void MutateTx(CMutableTransaction& tx, const string& command,
MutateTxVersion(tx, commandVal);
else if (command == "locktime")
MutateTxLocktime(tx, commandVal);
else if (command == "expiry")
MutateTxExpiry(tx, commandVal);
else if (command == "delin")
MutateTxDelInput(tx, commandVal);

24
src/chain.h

@ -94,8 +94,14 @@ enum BlockStatus: uint32_t {
BLOCK_FAILED_VALID = 32, //! stage after last reached validness failed
BLOCK_FAILED_CHILD = 64, //! descends from failed block
BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD,
BLOCK_ACTIVATES_UPGRADE = 128, //! block activates a network upgrade
};
//! Short-hand for the highest consensus validity we implement.
//! Blocks with this validity are assumed to satisfy all consensus rules.
static const BlockStatus BLOCK_VALID_CONSENSUS = BLOCK_VALID_SCRIPTS;
/** The block chain is a tree shaped structure starting with the
* genesis block at the root, with each block potentially having multiple
* candidates to be the next block. A blockindex may have multiple pprev pointing
@ -140,6 +146,11 @@ public:
//! Verification status of this block. See enum BlockStatus
unsigned int nStatus;
//! Branch ID corresponding to the consensus rules used to validate this block.
//! Only cached if block validity is BLOCK_VALID_CONSENSUS.
//! Persisted at each activation height, memory-only for intervening blocks.
boost::optional<uint32_t> nCachedBranchId;
//! The anchor for the tree state up to the start of this block
uint256 hashAnchor;
@ -180,6 +191,7 @@ public:
nTx = 0;
nChainTx = 0;
nStatus = 0;
nCachedBranchId = boost::none;
hashAnchor = uint256();
hashAnchorEnd = uint256();
nSequenceId = 0;
@ -341,6 +353,18 @@ public:
READWRITE(VARINT(nDataPos));
if (nStatus & BLOCK_HAVE_UNDO)
READWRITE(VARINT(nUndoPos));
if (nStatus & BLOCK_ACTIVATES_UPGRADE) {
if (ser_action.ForRead()) {
uint32_t branchId;
READWRITE(branchId);
nCachedBranchId = branchId;
} else {
// nCachedBranchId must always be set if BLOCK_ACTIVATES_UPGRADE is set.
assert(nCachedBranchId);
uint32_t branchId = *nCachedBranchId;
READWRITE(branchId);
}
}
READWRITE(hashAnchor);
// block header

185
src/chainparams.cpp

@ -16,10 +16,56 @@
#include "base58.h"
using namespace std;
#include "chainparamsseeds.h"
static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, const uint256& nNonce, const std::vector<unsigned char>& nSolution, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward)
{
// To create a genesis block for a new chain which is Overwintered:
// txNew.nVersion = 3
// txNew.fOverwintered = true
// txNew.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID
// txNew.nExpiryHeight = <default value>
CMutableTransaction txNew;
txNew.nVersion = 1;
txNew.vin.resize(1);
txNew.vout.resize(1);
txNew.vin[0].scriptSig = CScript() << 520617983 << CScriptNum(4) << std::vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
txNew.vout[0].nValue = genesisReward;
txNew.vout[0].scriptPubKey = genesisOutputScript;
CBlock genesis;
genesis.nTime = nTime;
genesis.nBits = nBits;
genesis.nNonce = nNonce;
genesis.nSolution = nSolution;
genesis.nVersion = nVersion;
genesis.vtx.push_back(txNew);
genesis.hashPrevBlock.SetNull();
genesis.hashMerkleRoot = genesis.BuildMerkleTree();
return genesis;
}
/**
* Build the genesis block. Note that the output of its generation
* transaction cannot be spent since it did not originally exist in the
* database (and is in any case of zero value).
*
* >>> from pyblake2 import blake2s
* >>> 'Zcash' + blake2s(b'The Economist 2016-10-29 Known unknown: Another crypto-currency is born. BTC#436254 0000000000000000044f321997f336d2908cf8c8d6893e88dbf067e2d949487d ETH#2521903 483039a6b6bd8bd05f0584f9a078d075e454925eb71c1f13eaff59b405a721bb DJIA close on 27 Oct 2016: 18,169.68').hexdigest()
*
* CBlock(hash=00040fe8, ver=4, hashPrevBlock=00000000000000, hashMerkleRoot=c4eaa5, nTime=1477641360, nBits=1f07ffff, nNonce=4695, vtx=1)
* CTransaction(hash=c4eaa5, ver=1, vin.size=1, vout.size=1, nLockTime=0)
* CTxIn(COutPoint(000000, -1), coinbase 04ffff071f0104455a6361736830623963346565663862376363343137656535303031653335303039383462366665613335363833613763616331343161303433633432303634383335643334)
* CTxOut(nValue=0.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
* vMerkleTree: c4eaa5
*/
static CBlock CreateGenesisBlock(uint32_t nTime, const uint256& nNonce, const std::vector<unsigned char>& nSolution, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward)
{
const char* pszTimestamp = "Zdashe540ecf100001889836c7d491a2f44e6bc6076d59e5e317255946b71be3fc516";
const CScript genesisOutputScript = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nSolution, nBits, nVersion, genesisReward);
}
/**
* Main network
*/
@ -50,8 +96,18 @@ public:
consensus.nPowMaxAdjustDown = 32; // 32% adjustment down
consensus.nPowMaxAdjustUp = 16; // 16% adjustment up
consensus.nPowTargetSpacing = 2.5 * 60;
consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002;
consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight =
Consensus::NetworkUpgrade::ALWAYS_ACTIVE;
consensus.vUpgrades[Consensus::UPGRADE_TESTDUMMY].nProtocolVersion = 170002;
consensus.vUpgrades[Consensus::UPGRADE_TESTDUMMY].nActivationHeight =
Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT;
consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion = 170004;
consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight =
Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT;
/**
* The message start string should be awesome!
* The message start string should be awesome! â©â¤
*/
pchMessageStart[0] = 0x24;
pchMessageStart[1] = 0xe9;
@ -67,30 +123,11 @@ public:
nEquihashN = N;
nEquihashK = K;
/**
* Build the genesis block. Note that the output of its generation
* transaction cannot be spent since it did not originally exist in the
* database (and is in any case of zero value).
*
* >>> from pyblake2 import blake2s
* >>> 'Zcash' + blake2s(b'Reuters:... ').hexdigest()
*/
const char* pszTimestamp = "Zdashe540ecf100001889836c7d491a2f44e6bc6076d59e5e317255946b71be3fc516";
CMutableTransaction txNew;
txNew.vin.resize(1);
txNew.vout.resize(1);
txNew.vin[0].scriptSig = CScript() << 520617983 << CScriptNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
txNew.vout[0].nValue = 0;
txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
genesis.vtx.push_back(txNew);
genesis.hashPrevBlock.SetNull();
genesis.hashMerkleRoot = genesis.BuildMerkleTree();
genesis.nVersion = 4;
genesis.nTime = 1479401611;
genesis.nBits = 0x1f07ffff;
genesis.nNonce = uint256S("0x1205000000000000000000000000000000000000000000000000000000000000");
genesis.nSolution = ParseHex("0045f33727869d999e1d90de13eec508bb9eedf7c623ae0926922a749df12927967ce41f0363365e536a149ced0a25ce7258bcf4d36c9d69ea830ecafaac0a20576ee2405fa6e1ed91e5e5f3e72add8dae92175e05bb114100c654b90a0ea0e35e3ecee480d073b90c0d252963519492dce839f14bd3e54b017972fe05c30f61d73437d2ccb8a8dac1f33ba27c9d8a81bc02911a0f04f0af099ba8cc9114bd0de60fcd699673bc7a05d06baf544c5daa773991ff85c269c17f3a58618818f91d6ee9e4c393cd8d03428a2cc9be4243384caf197c77029b8c6c9387ab7a4966faac8efb13f7f9e259040fbbc1295551ad10084dba5ef0b732da7c90bd06026152acc74aad871aa3c2e46666d262129f07e128a0ea322b532851d649d2e0443954dafaaddfa6af28a70c786b94d904cb8ad3fda5364d9d5cccd1ce802f801dad25644a7dcab1c44191f24cdd8997f19c3602bc6e936aca34413a3270f837d94b211c5ad7533a070fe7b5651db5bf5d2aa13d503af5eef912fdcb5704a1bfc4c095d9b3da8f62261ed0dea089bf5b12db067ce1b4bee14f6515a180dedfeac9d794649da2b203e2a975db5c961daf788239ec722a7afbc63b8cb30c11e0ce1943f71981c3437530a4c0fcec0f9e7c6c1f5e85373ff132ddccb202916665c5559ddbcff20c743f15e2b7748a11d5de283f8cf190cb0c47feec730f6bde470ae172b9fdfc07e96362dd9238833876ff14b8028e811af7610b08842aac55f79f066e5df160104bd571f44fb16d7476e2626458c2992f6291781915d5ee927594c8a5966ba379ace56cf30a9c5f79e70fa6347e664796eea268d74862522ac275bf94ef2e406034ff121345351b92245ba834c752249d3506a111407bbd10e31b1167f9c3702fc54176e18ad8ca6211c892d4ba4598b3d834c2aa06392e21b4ff3d6d510132989a9828086bbbd1e03debe3fd44e34550c54103df97e25709e086efefc27013b9fc08bc777f96630876dfcba638d5f1f2fe10935d5fb950388ca485044535350e83267d0b5c75e5f570cd849d8567daecb90b011f72bccde31e8c6b13a630b82dc1fe68f7ef261013e2a91ed033c11fa201f4a32f7a05a58cbbce0a13f175c5e08a3ced164686a26277be7bbac9fed583276d12d67a12649b4f46e466bdc57bed60c3f8bd6e05f73d54686d36e97a6461cbda430abf9ec8df6699160822abbc947463338741c961fcaab0dbbd2a2b92084d0b372242e6103aa54479fc7b350f35c23eb1f3161352ec3e1ba178fd82147ff42ba02164405fe74606b6c525883dddc5fd8431bb49c889571c155974af19291e49f55fbfe7c823f526f77edc9bba773f9e370baf614175515eef3f7be1750ee2a3c915a0f8e3ea31bdd397668ebef7f0cf75ddecec887df2baf771e1013d2d4795c39ba8449c18d559eab9c2718f39531c0b632437506c9061ee9995e11173da85948b5b82e02e54977eb64db682af9a1993bbd16fcab3d55be7493a38ab9012d6c3f5834f3740fcc725aa70e0570b46073ad43c7b0a582af576f8e2afd4c6c75d933b0d8955a49c2b522d84a9fc9c75bbf2b5363667e5b42b420eddfa537ac5d15d7a4ea9c5dfd063cb03e81da219163fe7135d61db9d19f891e5784613a59df7ffefa2017f8d6edfde9ce19babd5963aae94ad7bfd52e736323c73f9765c9026f1b0a560dbdcc71563586f4ced072c0903bdf6362fe4f4c0cea265ad48a6639bccaa08b5593a9f0eeac5cfcc14ca6d2e7449ec029598b4061793745ba3e53dc289c16ee84c7c2575824e7a5e372d8c8e1bf0a2dfa90283a67bd305c684b39af1d109004522301344a9c346a0e227c45749aa24b11623211155bad78e1a137376738662a78619dceaf0c79f");
genesis = CreateGenesisBlock(
1479401611,
uint256S("0x1205000000000000000000000000000000000000000000000000000000000000"),
ParseHex("0045f33727869d999e1d90de13eec508bb9eedf7c623ae0926922a749df12927967ce41f0363365e536a149ced0a25ce7258bcf4d36c9d69ea830ecafaac0a20576ee2405fa6e1ed91e5e5f3e72add8dae92175e05bb114100c654b90a0ea0e35e3ecee480d073b90c0d252963519492dce839f14bd3e54b017972fe05c30f61d73437d2ccb8a8dac1f33ba27c9d8a81bc02911a0f04f0af099ba8cc9114bd0de60fcd699673bc7a05d06baf544c5daa773991ff85c269c17f3a58618818f91d6ee9e4c393cd8d03428a2cc9be4243384caf197c77029b8c6c9387ab7a4966faac8efb13f7f9e259040fbbc1295551ad10084dba5ef0b732da7c90bd06026152acc74aad871aa3c2e46666d262129f07e128a0ea322b532851d649d2e0443954dafaaddfa6af28a70c786b94d904cb8ad3fda5364d9d5cccd1ce802f801dad25644a7dcab1c44191f24cdd8997f19c3602bc6e936aca34413a3270f837d94b211c5ad7533a070fe7b5651db5bf5d2aa13d503af5eef912fdcb5704a1bfc4c095d9b3da8f62261ed0dea089bf5b12db067ce1b4bee14f6515a180dedfeac9d794649da2b203e2a975db5c961daf788239ec722a7afbc63b8cb30c11e0ce1943f71981c3437530a4c0fcec0f9e7c6c1f5e85373ff132ddccb202916665c5559ddbcff20c743f15e2b7748a11d5de283f8cf190cb0c47feec730f6bde470ae172b9fdfc07e96362dd9238833876ff14b8028e811af7610b08842aac55f79f066e5df160104bd571f44fb16d7476e2626458c2992f6291781915d5ee927594c8a5966ba379ace56cf30a9c5f79e70fa6347e664796eea268d74862522ac275bf94ef2e406034ff121345351b92245ba834c752249d3506a111407bbd10e31b1167f9c3702fc54176e18ad8ca6211c892d4ba4598b3d834c2aa06392e21b4ff3d6d510132989a9828086bbbd1e03debe3fd44e34550c54103df97e25709e086efefc27013b9fc08bc777f96630876dfcba638d5f1f2fe10935d5fb950388ca485044535350e83267d0b5c75e5f570cd849d8567daecb90b011f72bccde31e8c6b13a630b82dc1fe68f7ef261013e2a91ed033c11fa201f4a32f7a05a58cbbce0a13f175c5e08a3ced164686a26277be7bbac9fed583276d12d67a12649b4f46e466bdc57bed60c3f8bd6e05f73d54686d36e97a6461cbda430abf9ec8df6699160822abbc947463338741c961fcaab0dbbd2a2b92084d0b372242e6103aa54479fc7b350f35c23eb1f3161352ec3e1ba178fd82147ff42ba02164405fe74606b6c525883dddc5fd8431bb49c889571c155974af19291e49f55fbfe7c823f526f77edc9bba773f9e370baf614175515eef3f7be1750ee2a3c915a0f8e3ea31bdd397668ebef7f0cf75ddecec887df2baf771e1013d2d4795c39ba8449c18d559eab9c2718f39531c0b632437506c9061ee9995e11173da85948b5b82e02e54977eb64db682af9a1993bbd16fcab3d55be7493a38ab9012d6c3f5834f3740fcc725aa70e0570b46073ad43c7b0a582af576f8e2afd4c6c75d933b0d8955a49c2b522d84a9fc9c75bbf2b5363667e5b42b420eddfa537ac5d15d7a4ea9c5dfd063cb03e81da219163fe7135d61db9d19f891e5784613a59df7ffefa2017f8d6edfde9ce19babd5963aae94ad7bfd52e736323c73f9765c9026f1b0a560dbdcc71563586f4ced072c0903bdf6362fe4f4c0cea265ad48a6639bccaa08b5593a9f0eeac5cfcc14ca6d2e7449ec029598b4061793745ba3e53dc289c16ee84c7c2575824e7a5e372d8c8e1bf0a2dfa90283a67bd305c684b39af1d109004522301344a9c346a0e227c45749aa24b11623211155bad78e1a137376738662a78619dceaf0c79f"),
0x1f07ffff, 4, 0);
consensus.hashGenesisBlock = genesis.GetHash();
assert(consensus.hashGenesisBlock == uint256S("0x0003a67bc26fe564b75daf11186d360652eb435a35ba3d9d3e7e5d5f8e62dc17"));
assert(genesis.hashMerkleRoot == uint256S("0x830539f9ec196f36a2759638b674a51b668eba7bbf6af10c56fed4af666be177"));
@ -125,7 +162,7 @@ public:
fMineBlocksOnDemand = false;
fTestnetToBeDeprecatedFieldRPC = false;
checkpointData = (Checkpoints::CCheckpointData) {
checkpointData = (CCheckpointData) {
boost::assign::map_list_of
(0, consensus.hashGenesisBlock)
(120, uint256S("0x01e107af8605050c438e904a145e0e6479077bb2b4abbed8f9067adbeb37dd77")),
@ -201,32 +238,53 @@ static CMainParams mainParams;
/**
* Testnet (v3)
*/
class CTestNetParams : public CMainParams {
class CTestNetParams : public CChainParams {
public:
CTestNetParams() {
strNetworkID = "test";
strCurrencyUnits = "TUSH";
consensus.fCoinbaseMustBeProtected = true;
consensus.nSubsidySlowStartInterval = 20000;
consensus.nSubsidyHalvingInterval = 840000;
consensus.nMajorityEnforceBlockUpgrade = 51;
consensus.nMajorityRejectBlockOutdated = 75;
consensus.nMajorityWindow = 400;
consensus.powLimit = uint256S("07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
consensus.nPowAveragingWindow = 17;
assert(maxUint/UintToArith256(consensus.powLimit) >= consensus.nPowAveragingWindow);
consensus.nPowMaxAdjustDown = 32; // 32% adjustment down
consensus.nPowMaxAdjustUp = 16; // 16% adjustment up
consensus.nPowTargetSpacing = 2.5 * 60;
consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002;
consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight =
Consensus::NetworkUpgrade::ALWAYS_ACTIVE;
consensus.vUpgrades[Consensus::UPGRADE_TESTDUMMY].nProtocolVersion = 170002;
consensus.vUpgrades[Consensus::UPGRADE_TESTDUMMY].nActivationHeight =
Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT;
consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion = 170003;
consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = 207500;
pchMessageStart[0] = 0xfa;
pchMessageStart[1] = 0x1a;
pchMessageStart[2] = 0xf9;
pchMessageStart[3] = 0xbf;
vAlertPubKey = ParseHex("040c2275ef276b57c646edd5d4441b911c6b166596b0ee853e67842c580b9ed14dab42c7db0985afa1454f9480004e9597178ad4c51d54069bc1013909818a7b81");
nDefaultPort = 18888;
//nMinerThreads = 0; #Error on 1.0.12-rc Build to 1.0.9
nMaxTipAge = 24 * 60 * 60;
nPruneAfterHeight = 1000;
const size_t N = 200, K = 9;
BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K));
nEquihashN = N;
nEquihashK = K;
//! Modify the testnet genesis block so the timestamp is valid for a later start.
genesis.nTime = 1506883264;
genesis.nBits = 0x2007ffff;
genesis.nNonce = uint256S("0x0000000000000000000000000000000000000000000000000000000000000007");
genesis.nSolution = ParseHex("00e76338efc84e87b18b92ae132b31a6ff581ff89f1aeacf5c650f46ba9b6db78640fbb7f1ebf417ac890f747e4965f231ad966795d88eb3fab219fcb91d664b24e26d62e6572bc28289d058fcad472cc91ce83102560a46f8c2bef9f3865407beff0d3de381d0c0330f0e10fa1b052c495a9a2669edf9a385ab18359ed61953dc000c870899653ee2b391bd5930cc134e1bea41cb64bae2262cb186b12613df6098c9a062ff23690367c5698159c7aae04e03fcad58686e0cda1223da0cd4aeb761628f77999a52e1b1d58dee4c5f1d283c18d4264e5ebb73b5e8a241905ab2a38097157508902b9ede96e32ccf27bd5fa41cdaf65eed6ff54e26340726d8abdb207363e176c29798a9b5e94b0eab5a56076b95a24659daa7cbfd70897f06c891a5b673e98c29638ed5fcdecacfa4cf3b30a47413c71b1a5b57c240ae3cd001a9753b8e0af92cddeea7f28edffb3ae304e307e83ad7d4ed899972f1a4d8b98d8ec0bee6b40e594c15936b9d89c2e1c485087cae539d97bea3a14537daa89dabd5dfb45ea7266def7baafcbf5a6a3150f506d810333a2da6d8eb4f2e6de036dce45d95880612bfcbe9e446a954c133746f7cc5deebb27b21e8199603ec0eb0ee41d2c0a22f1363622ccfe672bfd00d566cdfdc4c4555ea3baa9662eae5ef399ebb345042ad4a607fd78c615484b66746eb2e56edf07b79c9077df6370fa17d91f8c4036fc3afb7b2065598a169142f12c75725986b3d7b33768fcb87de68ecfa924308cea135fb0feb5121d82538dd5378425beedcc36c21d8266e6c1c6147dd22c27f90a80f2cf8b5160f830785250422b51857cdf6b1d5851a08126dbebc957a0816a4f914a4a02b48e813f64745fcf1093a6cf9660f3d7e556c87fb55d98d420fe02497d11dbf5191310f7abe28d8c7ebb28f7ae702d0d34de236e11ecbcd028008c78821db534c8f36e6ff633d8eb73057967a0bf41b9b0dc3af5856e6325522513279924fba9d61035bce23c89d39151d4a907e0b9b407dc5c3daae4c0f3f4c996d4de800b696a285edc2d13d33616bc33d14fb15900f97b6f9b8c83326471f12c540829581f14e814ec121a922f9bf10e9f8ba7359d6be99fc8a3d2b65d3a691f22e45af9a84ce0332930944fe4ad535634e9c65af25c0a1ca965a3f9b77cf9f37195e5c8c04d19999d828706b6fad344f775ccdc17a60de507f3d4c866ea2d38e37ceae749038c56962e258f84683149948aded24e461c5b682c68efcfa263e631eca06453c926e39ed0443aa4de6b70dbb13061114b44d2f10f7e0b4be5f31559764f1f92175029164e19f595712bdbc51aad5d445537aa392d543e719fb167267d62d933e96286698f39ef7c370adfafd423f95fff9112eabde6eca5efb5b107fa3e8f9c7147628ccfedadb03b9e43712a88505dfe620f1eb6610fcdf4fcefcd20ec4f429d8f2dd17e8a6248b982ebc2ddf663ad7f90af22fb325534505995e555c53ae80e26240ff844a0f71050ef6b6ddb5b88c551f9759950622bc9a012006224f0d4e5cbdf118293190c74f4f9e5617d445e145a24cb19061c0bff7223b77bee96b7fbe89feef5b255ffda27df3a975cf57757974f591b5abadb0138e3d2fcc522beb9c2da51d94470e3f25a58b75d7ad01041bec72c021f6737741f1360ba0c2d269d35b0fb81b75a7cb855372a1f8e0494614db52cf04719ad78f0c427eb23ee3c8efe797364b94ea11c643db1aa3c01a2b16c46a888c6472b41648b74b829211e9f55d3c175e57906155a6174ac164345fed374dc4b1721732258f742dbd4ab0bee777c4f2b6781cda1ed0d90da21c9c11e85749833ad143c3c65231bb3e39325a7799342dea78e055383789d6136d12620caea3ecda8ed3");
genesis = CreateGenesisBlock(
1506883264,
uint256S("0x0000000000000000000000000000000000000000000000000000000000000007"),
ParseHex("00e76338efc84e87b18b92ae132b31a6ff581ff89f1aeacf5c650f46ba9b6db78640fbb7f1ebf417ac890f747e4965f231ad966795d88eb3fab219fcb91d664b24e26d62e6572bc28289d058fcad472cc91ce83102560a46f8c2bef9f3865407beff0d3de381d0c0330f0e10fa1b052c495a9a2669edf9a385ab18359ed61953dc000c870899653ee2b391bd5930cc134e1bea41cb64bae2262cb186b12613df6098c9a062ff23690367c5698159c7aae04e03fcad58686e0cda1223da0cd4aeb761628f77999a52e1b1d58dee4c5f1d283c18d4264e5ebb73b5e8a241905ab2a38097157508902b9ede96e32ccf27bd5fa41cdaf65eed6ff54e26340726d8abdb207363e176c29798a9b5e94b0eab5a56076b95a24659daa7cbfd70897f06c891a5b673e98c29638ed5fcdecacfa4cf3b30a47413c71b1a5b57c240ae3cd001a9753b8e0af92cddeea7f28edffb3ae304e307e83ad7d4ed899972f1a4d8b98d8ec0bee6b40e594c15936b9d89c2e1c485087cae539d97bea3a14537daa89dabd5dfb45ea7266def7baafcbf5a6a3150f506d810333a2da6d8eb4f2e6de036dce45d95880612bfcbe9e446a954c133746f7cc5deebb27b21e8199603ec0eb0ee41d2c0a22f1363622ccfe672bfd00d566cdfdc4c4555ea3baa9662eae5ef399ebb345042ad4a607fd78c615484b66746eb2e56edf07b79c9077df6370fa17d91f8c4036fc3afb7b2065598a169142f12c75725986b3d7b33768fcb87de68ecfa924308cea135fb0feb5121d82538dd5378425beedcc36c21d8266e6c1c6147dd22c27f90a80f2cf8b5160f830785250422b51857cdf6b1d5851a08126dbebc957a0816a4f914a4a02b48e813f64745fcf1093a6cf9660f3d7e556c87fb55d98d420fe02497d11dbf5191310f7abe28d8c7ebb28f7ae702d0d34de236e11ecbcd028008c78821db534c8f36e6ff633d8eb73057967a0bf41b9b0dc3af5856e6325522513279924fba9d61035bce23c89d39151d4a907e0b9b407dc5c3daae4c0f3f4c996d4de800b696a285edc2d13d33616bc33d14fb15900f97b6f9b8c83326471f12c540829581f14e814ec121a922f9bf10e9f8ba7359d6be99fc8a3d2b65d3a691f22e45af9a84ce0332930944fe4ad535634e9c65af25c0a1ca965a3f9b77cf9f37195e5c8c04d19999d828706b6fad344f775ccdc17a60de507f3d4c866ea2d38e37ceae749038c56962e258f84683149948aded24e461c5b682c68efcfa263e631eca06453c926e39ed0443aa4de6b70dbb13061114b44d2f10f7e0b4be5f31559764f1f92175029164e19f595712bdbc51aad5d445537aa392d543e719fb167267d62d933e96286698f39ef7c370adfafd423f95fff9112eabde6eca5efb5b107fa3e8f9c7147628ccfedadb03b9e43712a88505dfe620f1eb6610fcdf4fcefcd20ec4f429d8f2dd17e8a6248b982ebc2ddf663ad7f90af22fb325534505995e555c53ae80e26240ff844a0f71050ef6b6ddb5b88c551f9759950622bc9a012006224f0d4e5cbdf118293190c74f4f9e5617d445e145a24cb19061c0bff7223b77bee96b7fbe89feef5b255ffda27df3a975cf57757974f591b5abadb0138e3d2fcc522beb9c2da51d94470e3f25a58b75d7ad01041bec72c021f6737741f1360ba0c2d269d35b0fb81b75a7cb855372a1f8e0494614db52cf04719ad78f0c427eb23ee3c8efe797364b94ea11c643db1aa3c01a2b16c46a888c6472b41648b74b829211e9f55d3c175e57906155a6174ac164345fed374dc4b1721732258f742dbd4ab0bee777c4f2b6781cda1ed0d90da21c9c11e85749833ad143c3c65231bb3e39325a7799342dea78e055383789d6136d12620caea3ecda8ed3"),
0x2007ffff, 4, 0);
consensus.hashGenesisBlock = genesis.GetHash();
assert(consensus.hashGenesisBlock == uint256S("0x" + consensus.hashGenesisBlock.ToString()));
assert(genesis.hashMerkleRoot == uint256S("0x830539f9ec196f36a2759638b674a51b668eba7bbf6af10c56fed4af666be177"));
vFixedSeeds.clear();
vSeeds.clear();
@ -257,7 +315,7 @@ public:
fMineBlocksOnDemand = false;
fTestnetToBeDeprecatedFieldRPC = true;
checkpointData = (Checkpoints::CCheckpointData) {
checkpointData = (CCheckpointData) {
boost::assign::map_list_of
(0, consensus.hashGenesisBlock),
1506883264, // * UNIX timestamp of last checkpoint block
@ -289,7 +347,7 @@ static CTestNetParams testNetParams;
/**
* Regression test
*/
class CRegTestParams : public CTestNetParams {
class CRegTestParams : public CChainParams {
public:
CRegTestParams() {
strNetworkID = "regtest";
@ -301,27 +359,41 @@ public:
consensus.nMajorityRejectBlockOutdated = 950;
consensus.nMajorityWindow = 1000;
consensus.powLimit = uint256S("0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f");
consensus.nPowAveragingWindow = 17;
assert(maxUint/UintToArith256(consensus.powLimit) >= consensus.nPowAveragingWindow);
consensus.nPowMaxAdjustDown = 0; // Turn off adjustment down
consensus.nPowMaxAdjustUp = 0; // Turn off adjustment up
consensus.nPowTargetSpacing = 2.5 * 60;
consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002;
consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight =
Consensus::NetworkUpgrade::ALWAYS_ACTIVE;
consensus.vUpgrades[Consensus::UPGRADE_TESTDUMMY].nProtocolVersion = 170002;
consensus.vUpgrades[Consensus::UPGRADE_TESTDUMMY].nActivationHeight =
Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT;
consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion = 170003;
consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight =
Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT;
pchMessageStart[0] = 0xaa;
pchMessageStart[1] = 0xe8;
pchMessageStart[2] = 0x3f;
pchMessageStart[3] = 0x5f;
//nMinerThreads = 1;
nDefaultPort = 18444;
nMaxTipAge = 24 * 60 * 60;
nPruneAfterHeight = 1000;
const size_t N = 48, K = 5;
BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K));
nEquihashN = N;
nEquihashK = K;
genesis.nTime = 1519568466;
genesis.nBits = 0x200f0f0f;
genesis.nNonce = uint256S("0x0000000000000000000000000000000000000000000000000000000000000016");
genesis.nSolution = ParseHex("0d1d1ef025037da781252f695ff279c12d492c5ed53e565c8ecdc044ede53cea96cff5fc");
genesis = CreateGenesisBlock(
1519568466,
uint256S("0x0000000000000000000000000000000000000000000000000000000000000016"),
ParseHex("0d1d1ef025037da781252f695ff279c12d492c5ed53e565c8ecdc044ede53cea96cff5fc"),
0x200f0f0f, 4, 0);
consensus.hashGenesisBlock = genesis.GetHash();
nDefaultPort = 18444;
assert(consensus.hashGenesisBlock == uint256S("0x0379ff1530af893f2f2e61146db6e900dd828dc8254215b9de23df2dba06664f"));
nPruneAfterHeight = 1000;
assert(genesis.hashMerkleRoot == uint256S("0x830539f9ec196f36a2759638b674a51b668eba7bbf6af10c56fed4af666be177"));
vFixedSeeds.clear(); //! Regtest mode doesn't have any fixed seeds.
vSeeds.clear(); //! Regtest mode doesn't have any DNS seeds.
@ -332,18 +404,34 @@ public:
fMineBlocksOnDemand = true;
fTestnetToBeDeprecatedFieldRPC = false;
checkpointData = (Checkpoints::CCheckpointData){
checkpointData = (CCheckpointData){
boost::assign::map_list_of
( 0, uint256S("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")),
0,
0,
0
};
// These prefixes are the same as the testnet prefixes
base58Prefixes[PUBKEY_ADDRESS] = {0x1D,0x25};
base58Prefixes[SCRIPT_ADDRESS] = {0x1C,0xBA};
base58Prefixes[SECRET_KEY] = {0xEF};
// do not rely on these BIP32 prefixes; they are not specified and may change
base58Prefixes[EXT_PUBLIC_KEY] = {0x04,0x35,0x87,0xCF};
base58Prefixes[EXT_SECRET_KEY] = {0x04,0x35,0x83,0x94};
base58Prefixes[ZCPAYMENT_ADDRRESS] = {0x16,0xB6};
base58Prefixes[ZCVIEWING_KEY] = {0xA8,0xAC,0x0C};
base58Prefixes[ZCSPENDING_KEY] = {0xAC,0x08};
// Founders reward script expects a vector of 2-of-3 multisig addresses
vFoundersRewardAddress = { "t2FwcEhFdNXuFMv1tcYwaBJtYVtMj8b1uTg" };
assert(vFoundersRewardAddress.size() <= consensus.GetLastFoundersRewardBlockHeight());
}
void UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex idx, int nActivationHeight)
{
assert(idx > Consensus::BASE_SPROUT && idx < Consensus::MAX_NETWORK_UPGRADES);
consensus.vUpgrades[idx].nActivationHeight = nActivationHeight;
}
};
static CRegTestParams regTestParams;
@ -408,7 +496,7 @@ CScript CChainParams::GetFoundersRewardScriptAtHeight(int nHeight) const {
CBitcoinAddress address(GetFoundersRewardAddressAtHeight(nHeight).c_str());
assert(address.IsValid());
assert(address.IsScript());
CScriptID scriptID = get<CScriptID>(address.Get()); // Get() returns a boost variant
CScriptID scriptID = boost::get<CScriptID>(address.Get()); // Get() returns a boost variant
CScript script = CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
return script;
}
@ -417,3 +505,8 @@ std::string CChainParams::GetFoundersRewardAddressAtIndex(int i) const {
assert(i >= 0 && i < vFoundersRewardAddress.size());
return vFoundersRewardAddress[i];
}
void UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex idx, int nActivationHeight)
{
regTestParams.UpdateNetworkUpgradeParameters(idx, nActivationHeight);
}

18
src/chainparams.h

@ -7,7 +7,6 @@
#define BITCOIN_CHAINPARAMS_H
#include "chainparamsbase.h"
#include "checkpoints.h"
#include "consensus/params.h"
#include "primitives/block.h"
#include "protocol.h"
@ -24,6 +23,14 @@ struct SeedSpec6 {
uint16_t port;
};
typedef std::map<int, uint256> MapCheckpoints;
struct CCheckpointData {
MapCheckpoints mapCheckpoints;
int64_t nTimeLastCheckpoint;
int64_t nTransactionsLastCheckpoint;
double fTransactionsPerDay;
};
/**
* CChainParams defines various tweakable parameters of a given instance of the
@ -75,7 +82,7 @@ public:
const std::vector<CDNSSeedData>& DNSSeeds() const { return vSeeds; }
const std::vector<unsigned char>& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; }
const std::vector<SeedSpec6>& FixedSeeds() const { return vFixedSeeds; }
const Checkpoints::CCheckpointData& Checkpoints() const { return checkpointData; }
const CCheckpointData& Checkpoints() const { return checkpointData; }
/** Return the founder's reward address and script for a given block height */
std::string GetFoundersRewardAddressAtHeight(int height) const;
CScript GetFoundersRewardScriptAtHeight(int height) const;
@ -105,7 +112,7 @@ protected:
bool fRequireStandard = false;
bool fMineBlocksOnDemand = false;
bool fTestnetToBeDeprecatedFieldRPC = false;
Checkpoints::CCheckpointData checkpointData;
CCheckpointData checkpointData;
std::vector<std::string> vFoundersRewardAddress;
};
@ -127,4 +134,9 @@ void SelectParams(CBaseChainParams::Network network);
*/
bool SelectParamsFromCommandLine();
/**
* Allows modifying the network upgrade regtest parameters.
*/
void UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex idx, int nActivationHeight);
#endif // BITCOIN_CHAINPARAMS_H

5
src/chainparamsbase.cpp

@ -25,7 +25,7 @@ static CBaseMainParams mainParams;
/**
* Testnet (v4)
*/
class CBaseTestNetParams : public CBaseMainParams
class CBaseTestNetParams : public CBaseChainParams
{
public:
CBaseTestNetParams()
@ -39,11 +39,12 @@ static CBaseTestNetParams testNetParams;
/*
* Regression test
*/
class CBaseRegTestParams : public CBaseTestNetParams
class CBaseRegTestParams : public CBaseChainParams
{
public:
CBaseRegTestParams()
{
nRPCPort = 18822;
strDataDir = "regtest";
}
};

9
src/checkpoints.h

@ -10,6 +10,7 @@
#include <map>
class CBlockIndex;
struct CCheckpointData;
/**
* Block-chain checkpoints are compiled-in sanity checks.
@ -17,14 +18,6 @@ class CBlockIndex;
*/
namespace Checkpoints
{
typedef std::map<int, uint256> MapCheckpoints;
struct CCheckpointData {
MapCheckpoints mapCheckpoints;
int64_t nTimeLastCheckpoint;
int64_t nTransactionsLastCheckpoint;
double fTransactionsPerDay;
};
//! Return conservative estimate of total number of blocks, 0 if unknown
int GetTotalBlocksEstimate(const CCheckpointData& data);

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 14
#define CLIENT_VERSION_REVISION 15
#define CLIENT_VERSION_BUILD 50
//! Set to true for release, false for prerelease or test build

8
src/consensus/consensus.h

@ -9,7 +9,11 @@
/** The minimum allowed block version (network rule) */
static const int32_t MIN_BLOCK_VERSION = 4;
/** The minimum allowed transaction version (network rule) */
static const int32_t MIN_TX_VERSION = 1;
static const int32_t SPROUT_MIN_TX_VERSION = 1;
/** The minimum allowed transaction version (network rule) */
static const int32_t OVERWINTER_MIN_TX_VERSION = 3;
/** The maximum allowed transaction version (network rule) */
static const int32_t OVERWINTER_MAX_TX_VERSION = 3;
/** The maximum allowed size for a serialized block, in bytes (network rule) */
static const unsigned int MAX_BLOCK_SIZE = 2000000;
/** The maximum allowed number of signature check operations in a block (network rule) */
@ -18,6 +22,8 @@ static const unsigned int MAX_BLOCK_SIGOPS = 20000;
static const unsigned int MAX_TX_SIZE = 100000;
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
static const int COINBASE_MATURITY = 100;
/** The minimum value which is invalid for expiry height, used by CTransaction and CMutableTransaction */
static constexpr uint32_t TX_EXPIRY_HEIGHT_THRESHOLD = 500000000;
/** Flags for LockTime() */
enum {

49
src/consensus/params.h

@ -9,6 +9,54 @@
#include "uint256.h"
namespace Consensus {
/**
* Index into Params.vUpgrades and NetworkUpgradeInfo
*
* Being array indices, these MUST be numbered consecutively.
*
* The order of these indices MUST match the order of the upgrades on-chain, as
* several functions depends on the enum being sorted.
*/
enum UpgradeIndex {
// Sprout must be first
BASE_SPROUT,
UPGRADE_TESTDUMMY,
UPGRADE_OVERWINTER,
// NOTE: Also add new upgrades to NetworkUpgradeInfo in upgrades.cpp
MAX_NETWORK_UPGRADES
};
struct NetworkUpgrade {
/**
* The first protocol version which will understand the new consensus rules
*/
int nProtocolVersion;
/**
* Height of the first block for which the new consensus rules will be active
*/
int nActivationHeight;
/**
* Special value for nActivationHeight indicating that the upgrade is always active.
* This is useful for testing, as it means tests don't need to deal with the activation
* process (namely, faking a chain of somewhat-arbitrary length).
*
* New blockchains that want to enable upgrade rules from the beginning can also use
* this value. However, additional care must be taken to ensure the genesis block
* satisfies the enabled rules.
*/
static constexpr int ALWAYS_ACTIVE = 0;
/**
* Special value for nActivationHeight indicating that the upgrade will never activate.
* This is useful when adding upgrade code that has a testnet activation height, but
* should remain disabled on mainnet.
*/
static constexpr int NO_ACTIVATION_HEIGHT = -1;
};
/**
* Parameters that influence chain consensus.
*/
@ -39,6 +87,7 @@ struct Params {
int nMajorityEnforceBlockUpgrade;
int nMajorityRejectBlockOutdated;
int nMajorityWindow;
NetworkUpgrade vUpgrades[MAX_NETWORK_UPGRADES];
/** Proof of work parameters */
uint256 powLimit;
int64_t nPowAveragingWindow;

124
src/consensus/upgrades.cpp

@ -0,0 +1,124 @@
// Copyright (c) 2018 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "consensus/upgrades.h"
/**
* General information about each network upgrade.
* Ordered by Consensus::UpgradeIndex.
*/
const struct NUInfo NetworkUpgradeInfo[Consensus::MAX_NETWORK_UPGRADES] = {
{
/*.nBranchId =*/ 0,
/*.strName =*/ "Sprout",
/*.strInfo =*/ "The Zcash network at launch",
},
{
/*.nBranchId =*/ 0x74736554,
/*.strName =*/ "Test dummy",
/*.strInfo =*/ "Test dummy info",
},
{
/*.nBranchId =*/ 0x5ba81b19,
/*.strName =*/ "Overwinter",
/*.strInfo =*/ "TBD",
}
};
UpgradeState NetworkUpgradeState(
int nHeight,
const Consensus::Params& params,
Consensus::UpgradeIndex idx)
{
assert(nHeight >= 0);
assert(idx >= Consensus::BASE_SPROUT && idx < Consensus::MAX_NETWORK_UPGRADES);
auto nActivationHeight = params.vUpgrades[idx].nActivationHeight;
if (nActivationHeight == Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT) {
return UPGRADE_DISABLED;
} else if (nHeight >= nActivationHeight) {
// From ZIP 200:
//
// ACTIVATION_HEIGHT
// The non-zero block height at which the network upgrade rules will come
// into effect, and be enforced as part of the blockchain consensus.
//
// For removal of ambiguity, the block at height ACTIVATION_HEIGHT - 1 is
// subject to the pre-upgrade consensus rules, and would be the last common
// block in the event of a persistent pre-upgrade branch.
return UPGRADE_ACTIVE;
} else {
return UPGRADE_PENDING;
}
}
bool NetworkUpgradeActive(
int nHeight,
const Consensus::Params& params,
Consensus::UpgradeIndex idx)
{
return NetworkUpgradeState(nHeight, params, idx) == UPGRADE_ACTIVE;
}
int CurrentEpoch(int nHeight, const Consensus::Params& params) {
for (auto idxInt = Consensus::MAX_NETWORK_UPGRADES - 1; idxInt >= Consensus::BASE_SPROUT; idxInt--) {
if (NetworkUpgradeActive(nHeight, params, Consensus::UpgradeIndex(idxInt))) {
return idxInt;
}
}
}
uint32_t CurrentEpochBranchId(int nHeight, const Consensus::Params& params) {
return NetworkUpgradeInfo[CurrentEpoch(nHeight, params)].nBranchId;
}
bool IsActivationHeight(
int nHeight,
const Consensus::Params& params,
Consensus::UpgradeIndex idx)
{
assert(idx >= Consensus::BASE_SPROUT && idx < Consensus::MAX_NETWORK_UPGRADES);
// Don't count Sprout as an activation height
if (idx == Consensus::BASE_SPROUT) {
return false;
}
return nHeight >= 0 && nHeight == params.vUpgrades[idx].nActivationHeight;
}
bool IsActivationHeightForAnyUpgrade(
int nHeight,
const Consensus::Params& params)
{
if (nHeight < 0) {
return false;
}
// Don't count Sprout as an activation height
for (int idx = Consensus::BASE_SPROUT + 1; idx < Consensus::MAX_NETWORK_UPGRADES; idx++) {
if (nHeight == params.vUpgrades[idx].nActivationHeight)
return true;
}
return false;
}
boost::optional<int> NextActivationHeight(
int nHeight,
const Consensus::Params& params)
{
if (nHeight < 0) {
return boost::none;
}
// Don't count Sprout as an activation height
for (auto idx = Consensus::BASE_SPROUT + 1; idx < Consensus::MAX_NETWORK_UPGRADES; idx++) {
if (NetworkUpgradeState(nHeight, params, Consensus::UpgradeIndex(idx)) == UPGRADE_PENDING) {
return params.vUpgrades[idx].nActivationHeight;
}
}
return boost::none;
}

90
src/consensus/upgrades.h

@ -0,0 +1,90 @@
// Copyright (c) 2018 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef ZCASH_CONSENSUS_UPGRADES_H
#define ZCASH_CONSENSUS_UPGRADES_H
#include "consensus/params.h"
#include <boost/optional.hpp>
enum UpgradeState {
UPGRADE_DISABLED,
UPGRADE_PENDING,
UPGRADE_ACTIVE
};
struct NUInfo {
/** Branch ID (a random non-zero 32-bit value) */
uint32_t nBranchId;
/** User-facing name for the upgrade */
std::string strName;
/** User-facing information string about the upgrade */
std::string strInfo;
};
extern const struct NUInfo NetworkUpgradeInfo[];
// Consensus branch id to identify pre-overwinter (Sprout) consensus rules.
static const uint32_t SPROUT_BRANCH_ID = NetworkUpgradeInfo[Consensus::BASE_SPROUT].nBranchId;
/**
* Checks the state of a given network upgrade based on block height.
* Caller must check that the height is >= 0 (and handle unknown heights).
*/
UpgradeState NetworkUpgradeState(
int nHeight,
const Consensus::Params& params,
Consensus::UpgradeIndex idx);
/**
* Returns true if the given network upgrade is active as of the given block
* height. Caller must check that the height is >= 0 (and handle unknown
* heights).
*/
bool NetworkUpgradeActive(
int nHeight,
const Consensus::Params& params,
Consensus::UpgradeIndex idx);
/**
* Returns the index of the most recent upgrade as of the given block height
* (corresponding to the current "epoch"). Consensus::BASE_SPROUT is the
* default value if no upgrades are active. Caller must check that the height
* is >= 0 (and handle unknown heights).
*/
int CurrentEpoch(int nHeight, const Consensus::Params& params);
/**
* Returns the branch ID of the most recent upgrade as of the given block height
* (corresponding to the current "epoch"), or 0 if no upgrades are active.
* Caller must check that the height is >= 0 (and handle unknown heights).
*/
uint32_t CurrentEpochBranchId(int nHeight, const Consensus::Params& params);
/**
* Returns true if the given block height is the activation height for the given
* upgrade.
*/
bool IsActivationHeight(
int nHeight,
const Consensus::Params& params,
Consensus::UpgradeIndex upgrade);
/**
* Returns true if the given block height is the activation height for any upgrade.
*/
bool IsActivationHeightForAnyUpgrade(
int nHeight,
const Consensus::Params& params);
/**
* Returns the activation height for the next upgrade after the given block height,
* or boost::none if there are no more known upgrades.
*/
boost::optional<int> NextActivationHeight(
int nHeight,
const Consensus::Params& params);
#endif // ZCASH_CONSENSUS_UPGRADES_H

173
src/gtest/test_upgrades.cpp

@ -0,0 +1,173 @@
#include <gtest/gtest.h>
#include "chainparams.h"
#include "consensus/upgrades.h"
#include <boost/optional.hpp>
class UpgradesTest : public ::testing::Test {
protected:
virtual void SetUp() {
}
virtual void TearDown() {
// Revert to default
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT);
}
};
TEST_F(UpgradesTest, NetworkUpgradeState) {
SelectParams(CBaseChainParams::REGTEST);
const Consensus::Params& params = Params().GetConsensus();
// Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT
EXPECT_EQ(
NetworkUpgradeState(0, params, Consensus::UPGRADE_TESTDUMMY),
UPGRADE_DISABLED);
EXPECT_EQ(
NetworkUpgradeState(1000000, params, Consensus::UPGRADE_TESTDUMMY),
UPGRADE_DISABLED);
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, Consensus::NetworkUpgrade::ALWAYS_ACTIVE);
EXPECT_EQ(
NetworkUpgradeState(0, params, Consensus::UPGRADE_TESTDUMMY),
UPGRADE_ACTIVE);
EXPECT_EQ(
NetworkUpgradeState(1000000, params, Consensus::UPGRADE_TESTDUMMY),
UPGRADE_ACTIVE);
int nActivationHeight = 100;
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, nActivationHeight);
EXPECT_EQ(
NetworkUpgradeState(0, params, Consensus::UPGRADE_TESTDUMMY),
UPGRADE_PENDING);
EXPECT_EQ(
NetworkUpgradeState(nActivationHeight - 1, params, Consensus::UPGRADE_TESTDUMMY),
UPGRADE_PENDING);
EXPECT_EQ(
NetworkUpgradeState(nActivationHeight, params, Consensus::UPGRADE_TESTDUMMY),
UPGRADE_ACTIVE);
EXPECT_EQ(
NetworkUpgradeState(1000000, params, Consensus::UPGRADE_TESTDUMMY),
UPGRADE_ACTIVE);
}
TEST_F(UpgradesTest, CurrentEpoch) {
SelectParams(CBaseChainParams::REGTEST);
const Consensus::Params& params = Params().GetConsensus();
auto nBranchId = NetworkUpgradeInfo[Consensus::UPGRADE_TESTDUMMY].nBranchId;
// Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT
EXPECT_EQ(CurrentEpoch(0, params), Consensus::BASE_SPROUT);
EXPECT_EQ(CurrentEpochBranchId(0, params), 0);
EXPECT_EQ(CurrentEpoch(1000000, params), Consensus::BASE_SPROUT);
EXPECT_EQ(CurrentEpochBranchId(1000000, params), 0);
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, Consensus::NetworkUpgrade::ALWAYS_ACTIVE);
EXPECT_EQ(CurrentEpoch(0, params), Consensus::UPGRADE_TESTDUMMY);
EXPECT_EQ(CurrentEpochBranchId(0, params), nBranchId);
EXPECT_EQ(CurrentEpoch(1000000, params), Consensus::UPGRADE_TESTDUMMY);
EXPECT_EQ(CurrentEpochBranchId(1000000, params), nBranchId);
int nActivationHeight = 100;
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, nActivationHeight);
EXPECT_EQ(CurrentEpoch(0, params), Consensus::BASE_SPROUT);
EXPECT_EQ(CurrentEpochBranchId(0, params), 0);
EXPECT_EQ(CurrentEpoch(nActivationHeight - 1, params), Consensus::BASE_SPROUT);
EXPECT_EQ(CurrentEpochBranchId(nActivationHeight - 1, params), 0);
EXPECT_EQ(CurrentEpoch(nActivationHeight, params), Consensus::UPGRADE_TESTDUMMY);
EXPECT_EQ(CurrentEpochBranchId(nActivationHeight, params), nBranchId);
EXPECT_EQ(CurrentEpoch(1000000, params), Consensus::UPGRADE_TESTDUMMY);
EXPECT_EQ(CurrentEpochBranchId(1000000, params), nBranchId);
}
TEST_F(UpgradesTest, IsActivationHeight) {
SelectParams(CBaseChainParams::REGTEST);
const Consensus::Params& params = Params().GetConsensus();
// Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT
EXPECT_FALSE(IsActivationHeight(-1, params, Consensus::UPGRADE_TESTDUMMY));
EXPECT_FALSE(IsActivationHeight(0, params, Consensus::UPGRADE_TESTDUMMY));
EXPECT_FALSE(IsActivationHeight(1, params, Consensus::UPGRADE_TESTDUMMY));
EXPECT_FALSE(IsActivationHeight(1000000, params, Consensus::UPGRADE_TESTDUMMY));
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, Consensus::NetworkUpgrade::ALWAYS_ACTIVE);
EXPECT_FALSE(IsActivationHeight(-1, params, Consensus::UPGRADE_TESTDUMMY));
EXPECT_TRUE(IsActivationHeight(0, params, Consensus::UPGRADE_TESTDUMMY));
EXPECT_FALSE(IsActivationHeight(1, params, Consensus::UPGRADE_TESTDUMMY));
EXPECT_FALSE(IsActivationHeight(1000000, params, Consensus::UPGRADE_TESTDUMMY));
int nActivationHeight = 100;
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, nActivationHeight);
EXPECT_FALSE(IsActivationHeight(-1, params, Consensus::UPGRADE_TESTDUMMY));
EXPECT_FALSE(IsActivationHeight(0, params, Consensus::UPGRADE_TESTDUMMY));
EXPECT_FALSE(IsActivationHeight(1, params, Consensus::UPGRADE_TESTDUMMY));
EXPECT_FALSE(IsActivationHeight(nActivationHeight - 1, params, Consensus::UPGRADE_TESTDUMMY));
EXPECT_TRUE(IsActivationHeight(nActivationHeight, params, Consensus::UPGRADE_TESTDUMMY));
EXPECT_FALSE(IsActivationHeight(nActivationHeight + 1, params, Consensus::UPGRADE_TESTDUMMY));
EXPECT_FALSE(IsActivationHeight(1000000, params, Consensus::UPGRADE_TESTDUMMY));
}
TEST_F(UpgradesTest, IsActivationHeightForAnyUpgrade) {
SelectParams(CBaseChainParams::REGTEST);
const Consensus::Params& params = Params().GetConsensus();
// Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT
EXPECT_FALSE(IsActivationHeightForAnyUpgrade(-1, params));
EXPECT_FALSE(IsActivationHeightForAnyUpgrade(0, params));
EXPECT_FALSE(IsActivationHeightForAnyUpgrade(1, params));
EXPECT_FALSE(IsActivationHeightForAnyUpgrade(1000000, params));
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, Consensus::NetworkUpgrade::ALWAYS_ACTIVE);
EXPECT_FALSE(IsActivationHeightForAnyUpgrade(-1, params));
EXPECT_TRUE(IsActivationHeightForAnyUpgrade(0, params));
EXPECT_FALSE(IsActivationHeightForAnyUpgrade(1, params));
EXPECT_FALSE(IsActivationHeightForAnyUpgrade(1000000, params));
int nActivationHeight = 100;
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, nActivationHeight);
EXPECT_FALSE(IsActivationHeightForAnyUpgrade(-1, params));
EXPECT_FALSE(IsActivationHeightForAnyUpgrade(0, params));
EXPECT_FALSE(IsActivationHeightForAnyUpgrade(1, params));
EXPECT_FALSE(IsActivationHeightForAnyUpgrade(nActivationHeight - 1, params));
EXPECT_TRUE(IsActivationHeightForAnyUpgrade(nActivationHeight, params));
EXPECT_FALSE(IsActivationHeightForAnyUpgrade(nActivationHeight + 1, params));
EXPECT_FALSE(IsActivationHeightForAnyUpgrade(1000000, params));
}
TEST_F(UpgradesTest, NextActivationHeight) {
SelectParams(CBaseChainParams::REGTEST);
const Consensus::Params& params = Params().GetConsensus();
// Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT
EXPECT_EQ(NextActivationHeight(-1, params), boost::none);
EXPECT_EQ(NextActivationHeight(0, params), boost::none);
EXPECT_EQ(NextActivationHeight(1, params), boost::none);
EXPECT_EQ(NextActivationHeight(1000000, params), boost::none);
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, Consensus::NetworkUpgrade::ALWAYS_ACTIVE);
EXPECT_EQ(NextActivationHeight(-1, params), boost::none);
EXPECT_EQ(NextActivationHeight(0, params), boost::none);
EXPECT_EQ(NextActivationHeight(1, params), boost::none);
EXPECT_EQ(NextActivationHeight(1000000, params), boost::none);
int nActivationHeight = 100;
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, nActivationHeight);
EXPECT_EQ(NextActivationHeight(-1, params), boost::none);
EXPECT_EQ(NextActivationHeight(0, params), nActivationHeight);
EXPECT_EQ(NextActivationHeight(1, params), nActivationHeight);
EXPECT_EQ(NextActivationHeight(nActivationHeight - 1, params), nActivationHeight);
EXPECT_EQ(NextActivationHeight(nActivationHeight, params), boost::none);
EXPECT_EQ(NextActivationHeight(nActivationHeight + 1, params), boost::none);
EXPECT_EQ(NextActivationHeight(1000000, params), boost::none);
}

43
src/hash.h

@ -12,6 +12,8 @@
#include "uint256.h"
#include "version.h"
#include "sodium.h"
#include <vector>
typedef uint256 ChainCode;
@ -150,6 +152,47 @@ public:
}
};
/** A writer stream (for serialization) that computes a 256-bit BLAKE2b hash. */
class CBLAKE2bWriter
{
private:
crypto_generichash_blake2b_state state;
public:
int nType;
int nVersion;
CBLAKE2bWriter(int nTypeIn, int nVersionIn, const unsigned char* personal) : nType(nTypeIn), nVersion(nVersionIn) {
assert(crypto_generichash_blake2b_init_salt_personal(
&state,
NULL, 0, // No key.
32,
NULL, // No salt.
personal) == 0);
}
CBLAKE2bWriter& write(const char *pch, size_t size) {
crypto_generichash_blake2b_update(&state, (const unsigned char*)pch, size);
return (*this);
}
// invalidates the object
uint256 GetHash() {
uint256 result;
crypto_generichash_blake2b_final(&state, (unsigned char*)&result, 32);
return result;
}
template<typename T>
CBLAKE2bWriter& operator<<(const T& obj) {
// Serialize to this stream
::Serialize(*this, obj, nType, nVersion);
return (*this);
}
};
/** Compute the 256-bit hash of an object's serialization. */
template<typename T>
uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)

53
src/init.cpp

@ -17,6 +17,7 @@
#endif
#include "checkpoints.h"
#include "compat/sanity.h"
#include "consensus/upgrades.h"
#include "consensus/validation.h"
#include "httpserver.h"
#include "httprpc.h"
@ -47,8 +48,10 @@
#include <windows.h>
#endif
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/bind.hpp>
#include <boost/filesystem.hpp>
#include <boost/function.hpp>
@ -457,6 +460,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0));
strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1));
strUsage += HelpMessageOpt("-txconfirmtarget=<n>", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET));
strUsage += HelpMessageOpt("-txexpirydelta", strprintf(_("Set the number of blocks after which a transaction that has not been mined will become invalid (default: %u)"), DEFAULT_TX_EXPIRY_DELTA));
strUsage += HelpMessageOpt("-maxtxfee=<amt>", strprintf(_("Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s)"),
CURRENCY_UNIT, FormatMoney(maxTxFee)));
strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format") + " " + _("on startup"));
@ -494,6 +498,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-fuzzmessagestest=<n>", "Randomly fuzz 1 of every <n> network messages");
strUsage += HelpMessageOpt("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", 1));
strUsage += HelpMessageOpt("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", 0));
strUsage += HelpMessageOpt("-nuparams=hexBranchId:activationHeight", "Use given activation height for specified network upgrade (regtest-only)");
}
string debugCategories = "addrman, alert, bench, coindb, db, estimatefee, http, libevent, lock, mempool, net, partitioncheck, pow, proxy, prune, "
"rand, reindex, rpc, selectcoins, tor, zmq, zrpc, zrpcunsafe (implies zrpc)"; // Don't translate these
@ -840,6 +845,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
}
else if (mapArgs.count("-paymentdisclosure")) {
return InitError(_("Payment disclosure requires -experimentalfeatures."));
} else if (mapArgs.count("-zmergetoaddress")) {
return InitError(_("RPC method z_mergetoaddress requires -experimentalfeatures."));
}
}
@ -961,7 +968,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
InitWarning(_("Warning: Unsupported argument -benchmark ignored, use -debug=bench."));
// Checkmempool and checkblockindex default to true in regtest mode
mempool.setSanityCheck(GetBoolArg("-checkmempool", chainparams.DefaultConsistencyChecks()));
int ratio = std::min<int>(std::max<int>(GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
if (ratio != 0) {
mempool.setSanityCheck(1.0 / ratio);
}
fCheckBlockIndex = GetBoolArg("-checkblockindex", chainparams.DefaultConsistencyChecks());
fCheckpointsEnabled = GetBoolArg("-checkpoints", true);
@ -1051,6 +1061,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
}
}
nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
expiryDelta = GetArg("-txexpirydelta", DEFAULT_TX_EXPIRY_DELTA);
bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", true);
fSendFreeTransactions = GetBoolArg("-sendfreetransactions", false);
@ -1086,6 +1097,38 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
}
}
if (!mapMultiArgs["-nuparams"].empty()) {
// Allow overriding network upgrade parameters for testing
if (Params().NetworkIDString() != "regtest") {
return InitError("Network upgrade parameters may only be overridden on regtest.");
}
const vector<string>& deployments = mapMultiArgs["-nuparams"];
for (auto i : deployments) {
std::vector<std::string> vDeploymentParams;
boost::split(vDeploymentParams, i, boost::is_any_of(":"));
if (vDeploymentParams.size() != 2) {
return InitError("Network upgrade parameters malformed, expecting hexBranchId:activationHeight");
}
int nActivationHeight;
if (!ParseInt32(vDeploymentParams[1], &nActivationHeight)) {
return InitError(strprintf("Invalid nActivationHeight (%s)", vDeploymentParams[1]));
}
bool found = false;
// Exclude Sprout from upgrades
for (auto i = Consensus::BASE_SPROUT + 1; i < Consensus::MAX_NETWORK_UPGRADES; ++i)
{
if (vDeploymentParams[0].compare(HexInt(NetworkUpgradeInfo[i].nBranchId)) == 0) {
UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex(i), nActivationHeight);
found = true;
LogPrintf("Setting network upgrade activation parameters for %s to height=%d\n", vDeploymentParams[0], nActivationHeight);
break;
}
}
if (!found) {
return InitError(strprintf("Invalid network upgrade (%s)", vDeploymentParams[0]));
}
}
}
// ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log
@ -1470,6 +1513,14 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
break;
}
if (!fReindex) {
uiInterface.InitMessage(_("Rewinding blocks if needed..."));
if (!RewindBlockIndex(chainparams)) {
strLoadError = _("Unable to rewind the database to a pre-upgrade state. You will need to redownload the blockchain");
break;
}
}
uiInterface.InitMessage(_("Verifying blocks..."));
if (fHavePruned && GetArg("-checkblocks", 288) > MIN_BLOCKS_TO_KEEP) {
LogPrintf("Prune: pruned datadir may not have more than %d blocks; -checkblocks=%d may fail\n",

25
src/key.cpp

@ -85,16 +85,13 @@ static int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *ou
* <http://www.secg.org/sec1-v2.pdf>. The optional parameters and publicKey fields are
* included.
*
* privkey must point to an output buffer of length at least PRIVATE_KEY_SIZE bytes.
* privkey must point to an output buffer of length at least CKey::PRIVATE_KEY_SIZE bytes.
* privkeylen must initially be set to the size of the privkey buffer. Upon return it
* will be set to the number of bytes used in the buffer.
* key32 must point to a 32-byte raw private key.
*/
static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, int compressed) {
assert(*privkeylen >= PRIVATE_KEY_SIZE);
static_assert(
PRIVATE_KEY_SIZE >= COMPRESSED_PRIVATE_KEY_SIZE,
"COMPRESSED_PRIVATE_KEY_SIZE is larger than PRIVATE_KEY_SIZE");
assert(*privkeylen >= CKey::PRIVATE_KEY_SIZE);
secp256k1_pubkey pubkey;
size_t pubkeylen = 0;
if (!secp256k1_ec_pubkey_create(ctx, &pubkey, key32)) {
@ -120,11 +117,11 @@ static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *pr
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);
memcpy(ptr, key32, 32); ptr += 32;
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
pubkeylen = COMPRESSED_PUBLIC_KEY_SIZE;
pubkeylen = CPubKey::COMPRESSED_PUBLIC_KEY_SIZE;
secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED);
ptr += pubkeylen;
*privkeylen = ptr - privkey;
assert(*privkeylen == COMPRESSED_PRIVATE_KEY_SIZE);
assert(*privkeylen == CKey::COMPRESSED_PRIVATE_KEY_SIZE);
} else {
static const unsigned char begin[] = {
0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20
@ -146,11 +143,11 @@ static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *pr
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);
memcpy(ptr, key32, 32); ptr += 32;
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
pubkeylen = PUBLIC_KEY_SIZE;
pubkeylen = CPubKey::PUBLIC_KEY_SIZE;
secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_UNCOMPRESSED);
ptr += pubkeylen;
*privkeylen = ptr - privkey;
assert(*privkeylen == PRIVATE_KEY_SIZE);
assert(*privkeylen == CKey::PRIVATE_KEY_SIZE);
}
return 1;
}
@ -191,7 +188,7 @@ CPrivKey CKey::GetPrivKey() const {
CPubKey CKey::GetPubKey() const {
assert(fValid);
secp256k1_pubkey pubkey;
size_t clen = PUBLIC_KEY_SIZE;
size_t clen = CPubKey::PUBLIC_KEY_SIZE;
CPubKey result;
int ret = secp256k1_ec_pubkey_create(secp256k1_context_sign, &pubkey, begin());
assert(ret);
@ -204,8 +201,8 @@ CPubKey CKey::GetPubKey() const {
bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, uint32_t test_case) const {
if (!fValid)
return false;
vchSig.resize(SIGNATURE_SIZE);
size_t nSigLen = SIGNATURE_SIZE;
vchSig.resize(CPubKey::SIGNATURE_SIZE);
size_t nSigLen = CPubKey::SIGNATURE_SIZE;
unsigned char extra_entropy[32] = {0};
WriteLE32(extra_entropy, test_case);
secp256k1_ecdsa_signature sig;
@ -233,7 +230,7 @@ bool CKey::VerifyPubKey(const CPubKey& pubkey) const {
bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
if (!fValid)
return false;
vchSig.resize(COMPACT_SIGNATURE_SIZE);
vchSig.resize(CPubKey::COMPACT_SIGNATURE_SIZE);
int rec = -1;
secp256k1_ecdsa_recoverable_signature sig;
int ret = secp256k1_ecdsa_sign_recoverable(secp256k1_context_sign, &sig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, NULL);
@ -264,7 +261,7 @@ bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const
LockObject(out);
if ((nChild >> 31) == 0) {
CPubKey pubkey = GetPubKey();
assert(pubkey.size() == COMPRESSED_PUBLIC_KEY_SIZE);
assert(pubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE);
BIP32Hash(cc, nChild, *pubkey.begin(), pubkey.begin()+1, out);
} else {
assert(size() == 32);

24
src/key.h

@ -16,16 +16,6 @@
#include <vector>
/**
* secp256k1:
*/
const unsigned int PRIVATE_KEY_SIZE = 279;
const unsigned int COMPRESSED_PRIVATE_KEY_SIZE = 214;
/**
* see www.keylength.com
* script supports up to 75 for single byte push
*/
/**
* secure_allocator is defined in allocators.h
* CPrivKey is a serialized private key, with all parameters included
@ -36,6 +26,20 @@ typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
/** An encapsulated private key. */
class CKey
{
public:
/**
* secp256k1:
*/
static const unsigned int PRIVATE_KEY_SIZE = 279;
static const unsigned int COMPRESSED_PRIVATE_KEY_SIZE = 214;
/**
* see www.keylength.com
* script supports up to 75 for single byte push
*/
static_assert(
PRIVATE_KEY_SIZE >= COMPRESSED_PRIVATE_KEY_SIZE,
"COMPRESSED_PRIVATE_KEY_SIZE is larger than PRIVATE_KEY_SIZE");
private:
//! Whether this private key is valid. We check for correctness when modifying the key
//! data, so fValid should always correspond to the actual state.

595
src/main.cpp

@ -15,6 +15,7 @@
#include "chainparams.h"
#include "checkpoints.h"
#include "checkqueue.h"
#include "consensus/upgrades.h"
#include "consensus/validation.h"
#include "deprecation.h"
#include "init.h"
@ -78,6 +79,8 @@ size_t nCoinCacheUsage = 5000 * 300;
uint64_t nPruneTarget = 0;
bool fAlerts = DEFAULT_ALERTS;
unsigned int expiryDelta = DEFAULT_TX_EXPIRY_DELTA;
/** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
@ -549,6 +552,9 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc
CBlockIndex* pindex = (*mi).second;
if (chain.Contains(pindex))
return pindex;
if (pindex->GetAncestor(chain.Height()) == chain.Tip()) {
return chain.Tip();
}
}
}
return chain.Genesis();
@ -643,16 +649,22 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) EXCLUSIVE_LOCKS_REQUIRE
}
bool IsStandardTx(const CTransaction& tx, string& reason)
bool IsStandardTx(const CTransaction& tx, string& reason, const int nHeight)
{
if (tx.nVersion > CTransaction::MAX_CURRENT_VERSION || tx.nVersion < CTransaction::MIN_CURRENT_VERSION) {
reason = "version";
return false;
bool isOverwinter = NetworkUpgradeActive(nHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER);
if (isOverwinter) {
// Overwinter standard rules apply
if (tx.nVersion > CTransaction::OVERWINTER_MAX_CURRENT_VERSION || tx.nVersion < CTransaction::OVERWINTER_MIN_CURRENT_VERSION) {
reason = "overwinter-version";
return false;
}
} else {
// Sprout standard rules apply
if (tx.nVersion > CTransaction::SPROUT_MAX_CURRENT_VERSION || tx.nVersion < CTransaction::SPROUT_MIN_CURRENT_VERSION) {
reason = "version";
return false;
}
}
BOOST_FOREACH(const CTxIn& txin, tx.vin)
@ -714,6 +726,14 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
return true;
}
bool IsExpiredTx(const CTransaction &tx, int nBlockHeight)
{
if (tx.nExpiryHeight == 0 || tx.IsCoinBase()) {
return false;
}
return static_cast<uint32_t>(nBlockHeight) > tx.nExpiryHeight;
}
bool CheckFinalTx(const CTransaction &tx, int flags)
{
AssertLockHeld(cs_main);
@ -754,7 +774,7 @@ bool CheckFinalTx(const CTransaction &tx, int flags)
* 2. P2SH scripts with a crazy number of expensive
* CHECKSIG/CHECKMULTISIG operations
*/
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, uint32_t consensusBranchId)
{
if (tx.IsCoinBase())
return true; // Coinbases don't use vin normally
@ -780,7 +800,7 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
// IsStandardTx() will have already returned false
// and this method isn't called.
vector<vector<unsigned char> > stack;
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker()))
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), consensusBranchId))
return false;
if (whichType == TX_SCRIPTHASH)
@ -842,6 +862,79 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
return nSigOps;
}
/**
* Check a transaction contextually against a set of consensus rules valid at a given block height.
*
* Notes:
* 1. AcceptToMemoryPool calls CheckTransaction and this function.
* 2. ProcessNewBlock calls AcceptBlock, which calls CheckBlock (which calls CheckTransaction)
* and ContextualCheckBlock (which calls this function).
*/
bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state, const int nHeight, const int dosLevel)
{
bool isOverwinter = NetworkUpgradeActive(nHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER);
bool isSprout = !isOverwinter;
// If Sprout rules apply, reject transactions which are intended for Overwinter and beyond
if (isSprout && tx.fOverwintered) {
return state.DoS(dosLevel, error("ContextualCheckTransaction(): overwinter is not active yet"),
REJECT_INVALID, "tx-overwinter-not-active");
}
// If Overwinter rules apply:
if (isOverwinter) {
// Reject transactions with valid version but missing overwinter flag
if (tx.nVersion >= OVERWINTER_MIN_TX_VERSION && !tx.fOverwintered) {
return state.DoS(dosLevel, error("ContextualCheckTransaction(): overwinter flag must be set"),
REJECT_INVALID, "tx-overwinter-flag-not-set");
}
// Reject transactions with invalid version
if (tx.fOverwintered && tx.nVersion > OVERWINTER_MAX_TX_VERSION ) {
return state.DoS(100, error("CheckTransaction(): overwinter version too high"),
REJECT_INVALID, "bad-tx-overwinter-version-too-high");
}
// Reject transactions intended for Sprout
if (!tx.fOverwintered) {
return state.DoS(dosLevel, error("ContextualCheckTransaction: overwinter is active"),
REJECT_INVALID, "tx-overwinter-active");
}
// Check that all transactions are unexpired
if (IsExpiredTx(tx, nHeight)) {
return state.DoS(dosLevel, error("ContextualCheckTransaction(): transaction is expired"), REJECT_INVALID, "tx-overwinter-expired");
}
}
if (!(tx.IsCoinBase() || tx.vjoinsplit.empty())) {
auto consensusBranchId = CurrentEpochBranchId(nHeight, Params().GetConsensus());
// Empty output script.
CScript scriptCode;
uint256 dataToBeSigned;
try {
dataToBeSigned = SignatureHash(scriptCode, tx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
} catch (std::logic_error ex) {
return state.DoS(100, error("CheckTransaction(): error computing signature hash"),
REJECT_INVALID, "error-computing-signature-hash");
}
BOOST_STATIC_ASSERT(crypto_sign_PUBLICKEYBYTES == 32);
// We rely on libsodium to check that the signature is canonical.
// https://github.com/jedisct1/libsodium/commit/62911edb7ff2275cccd74bf1c8aefcc4d76924e0
if (crypto_sign_verify_detached(&tx.joinSplitSig[0],
dataToBeSigned.begin(), 32,
tx.joinSplitPubKey.begin()
) != 0) {
return state.DoS(100, error("CheckTransaction(): invalid joinsplit signature"),
REJECT_INVALID, "bad-txns-invalid-joinsplit-signature");
}
}
return true;
}
bool CheckTransaction(const CTransaction& tx, CValidationState &state,
libzcash::ProofVerifier& verifier)
{
@ -868,11 +961,46 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
{
// Basic checks that don't depend on any context
// Check transaction version
if (tx.nVersion < MIN_TX_VERSION) {
/**
* Previously:
* 1. The consensus rule below was:
* if (tx.nVersion < SPROUT_MIN_TX_VERSION) { ... }
* which checked if tx.nVersion fell within the range:
* INT32_MIN <= tx.nVersion < SPROUT_MIN_TX_VERSION
* 2. The parser allowed tx.nVersion to be negative
*
* Now:
* 1. The consensus rule checks to see if tx.Version falls within the range:
* 0 <= tx.nVersion < SPROUT_MIN_TX_VERSION
* 2. The previous consensus rule checked for negative values within the range:
* INT32_MIN <= tx.nVersion < 0
* This is unnecessary for Overwinter transactions since the parser now
* interprets the sign bit as fOverwintered, so tx.nVersion is always >=0,
* and when Overwinter is not active ContextualCheckTransaction rejects
* transactions with fOverwintered set. When fOverwintered is set,
* this function and ContextualCheckTransaction will together check to
* ensure tx.nVersion avoids the following ranges:
* 0 <= tx.nVersion < OVERWINTER_MIN_TX_VERSION
* OVERWINTER_MAX_TX_VERSION < tx.nVersion <= INT32_MAX
*/
if (!tx.fOverwintered && tx.nVersion < SPROUT_MIN_TX_VERSION) {
return state.DoS(100, error("CheckTransaction(): version too low"),
REJECT_INVALID, "bad-txns-version-too-low");
}
else if (tx.fOverwintered) {
if (tx.nVersion < OVERWINTER_MIN_TX_VERSION) {
return state.DoS(100, error("CheckTransaction(): overwinter version too low"),
REJECT_INVALID, "bad-tx-overwinter-version-too-low");
}
if (tx.nVersionGroupId != OVERWINTER_VERSION_GROUP_ID) {
return state.DoS(100, error("CheckTransaction(): unknown tx version group id"),
REJECT_INVALID, "bad-tx-version-group-id");
}
if (tx.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD) {
return state.DoS(100, error("CheckTransaction(): expiry height is too high"),
REJECT_INVALID, "bad-tx-expiry-height-too-high");
}
}
// Transactions can contain empty `vin` and `vout` so long as
// `vjoinsplit` is non-empty.
@ -999,30 +1127,6 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
if (txin.prevout.IsNull())
return state.DoS(10, error("CheckTransaction(): prevout is null"),
REJECT_INVALID, "bad-txns-prevout-null");
if (tx.vjoinsplit.size() > 0) {
// Empty output script.
CScript scriptCode;
uint256 dataToBeSigned;
try {
dataToBeSigned = SignatureHash(scriptCode, tx, NOT_AN_INPUT, SIGHASH_ALL);
} catch (std::logic_error ex) {
return state.DoS(100, error("CheckTransaction(): error computing signature hash"),
REJECT_INVALID, "error-computing-signature-hash");
}
BOOST_STATIC_ASSERT(crypto_sign_PUBLICKEYBYTES == 32);
// We rely on libsodium to check that the signature is canonical.
// https://github.com/jedisct1/libsodium/commit/62911edb7ff2275cccd74bf1c8aefcc4d76924e0
if (crypto_sign_verify_detached(&tx.joinSplitSig[0],
dataToBeSigned.begin(), 32,
tx.joinSplitPubKey.begin()
) != 0) {
return state.DoS(100, error("CheckTransaction(): invalid joinsplit signature"),
REJECT_INVALID, "bad-txns-invalid-joinsplit-signature");
}
}
}
return true;
@ -1065,6 +1169,9 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
if (pfMissingInputs)
*pfMissingInputs = false;
int nextBlockHeight = chainActive.Height() + 1;
auto consensusBranchId = CurrentEpochBranchId(nextBlockHeight, Params().GetConsensus());
// Node operator can choose to reject tx by number of transparent inputs
static_assert(std::numeric_limits<size_t>::max() >= std::numeric_limits<int64_t>::max(), "size_t too small");
size_t limit = (size_t) GetArg("-mempooltxinputlimit", 0);
@ -1080,6 +1187,12 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
if (!CheckTransaction(tx, state, verifier))
return error("AcceptToMemoryPool: CheckTransaction failed");
// DoS level set to 10 to be more forgiving.
// Check transaction contextually against the set of consensus rules which apply in the next block to be mined.
if (!ContextualCheckTransaction(tx, state, nextBlockHeight, 10)) {
return error("AcceptToMemoryPool: ContextualCheckTransaction failed");
}
// Coinbase is only valid in a block, not as a loose transaction
if (tx.IsCoinBase())
return state.DoS(100, error("AcceptToMemoryPool: coinbase as individual tx"),
@ -1087,7 +1200,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
string reason;
if (Params().RequireStandard() && !IsStandardTx(tx, reason))
if (Params().RequireStandard() && !IsStandardTx(tx, reason, nextBlockHeight))
return state.DoS(0,
error("AcceptToMemoryPool: nonstandard transaction: %s", reason),
REJECT_NONSTANDARD, reason);
@ -1170,7 +1283,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
}
// Check for non-standard pay-to-script-hash in inputs
if (Params().RequireStandard() && !AreInputsStandard(tx, view))
if (Params().RequireStandard() && !AreInputsStandard(tx, view, consensusBranchId))
return error("AcceptToMemoryPool: nonstandard transaction input");
// Check that the transaction doesn't have an excessive number of
@ -1190,7 +1303,23 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
CAmount nFees = nValueIn-nValueOut;
double dPriority = view.GetPriority(tx, chainActive.Height());
CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), mempool.HasNoInputsOf(tx));
// Keep track of transactions that spend a coinbase, which we re-scan
// during reorgs to ensure COINBASE_MATURITY is still met.
bool fSpendsCoinbase = false;
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
const CCoins *coins = view.AccessCoins(txin.prevout.hash);
if (coins->IsCoinBase()) {
fSpendsCoinbase = true;
break;
}
}
// Grab the branch ID we expect this transaction to commit to. We don't
// yet know if it does, but if the entry gets added to the mempool, then
// it has passed ContextualCheckInputs and therefore this is correct.
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), mempool.HasNoInputsOf(tx), fSpendsCoinbase, consensusBranchId);
unsigned int nSize = entry.GetTxSize();
// Accept a tx if it contains joinsplits and has at least the default fee specified by z_sendmany.
@ -1241,7 +1370,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, Params().GetConsensus()))
PrecomputedTransactionData txdata(tx);
if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
{
return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString());
}
@ -1255,7 +1385,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// There is a similar check in CreateNewBlock() to prevent creating
// invalid blocks, however allowing such transactions into the mempool
// can be exploited as a DoS attack.
if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, Params().GetConsensus()))
if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
{
return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s", hash.ToString());
}
@ -1642,7 +1772,7 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state
}
}
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight)
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txundo, int nHeight)
{
// mark inputs spent
if (!tx.IsCoinBase()) {
@ -1676,15 +1806,15 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight);
}
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, int nHeight)
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight)
{
CTxUndo txundo;
UpdateCoins(tx, state, inputs, txundo, nHeight);
UpdateCoins(tx, inputs, txundo, nHeight);
}
bool CScriptCheck::operator()() {
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, cacheStore), &error)) {
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), consensusBranchId, &error)) {
return ::error("CScriptCheck(): %s:%d VerifySignature failed: %s", ptxTo->GetHash().ToString(), nIn, ScriptErrorString(error));
}
return true;
@ -1767,7 +1897,17 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins
}
}// namespace Consensus
bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, const Consensus::Params& consensusParams, std::vector<CScriptCheck> *pvChecks)
bool ContextualCheckInputs(
const CTransaction& tx,
CValidationState &state,
const CCoinsViewCache &inputs,
bool fScriptChecks,
unsigned int flags,
bool cacheStore,
PrecomputedTransactionData& txdata,
const Consensus::Params& consensusParams,
uint32_t consensusBranchId,
std::vector<CScriptCheck> *pvChecks)
{
if (!tx.IsCoinBase())
{
@ -1792,7 +1932,7 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons
assert(coins);
// Verify signature
CScriptCheck check(*coins, tx, i, flags, cacheStore);
CScriptCheck check(*coins, tx, i, flags, cacheStore, consensusBranchId, &txdata);
if (pvChecks) {
pvChecks->push_back(CScriptCheck());
check.swap(pvChecks->back());
@ -1804,9 +1944,9 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons
// arguments; if so, don't trigger DoS protection to
// avoid splitting the network between upgraded and
// non-upgraded nodes.
CScriptCheck check(*coins, tx, i,
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore);
if (check())
CScriptCheck check2(*coins, tx, i,
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, consensusBranchId, &txdata);
if (check2())
return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));
}
// Failures of other flags indicate a transaction that is
@ -2275,6 +2415,11 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
assert(tree.root() == old_tree_root);
}
// Grab the consensus branch ID for the block's height
auto consensusBranchId = CurrentEpochBranchId(pindex->nHeight, Params().GetConsensus());
std::vector<PrecomputedTransactionData> txdata;
txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated
for (unsigned int i = 0; i < block.vtx.size(); i++)
{
const CTransaction &tx = block.vtx[i];
@ -2342,11 +2487,16 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (nSigOps > MAX_BLOCK_SIGOPS)
return state.DoS(100, error("ConnectBlock(): too many sigops"),
REJECT_INVALID, "bad-blk-sigops");
}
txdata.emplace_back(tx);
if (!tx.IsCoinBase())
{
nFees += view.GetValueIn(tx)-tx.GetValueOut();
std::vector<CScriptCheck> vChecks;
if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, false, chainparams.GetConsensus(), nScriptCheckThreads ? &vChecks : NULL))
if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, false, txdata[i], chainparams.GetConsensus(), consensusBranchId, nScriptCheckThreads ? &vChecks : NULL))
return false;
control.Add(vChecks);
}
@ -2384,7 +2534,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (i > 0) {
blockundo.vtxundo.push_back(CTxUndo());
}
UpdateCoins(tx, state, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight);
UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight);
BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
BOOST_FOREACH(const uint256 &note_commitment, joinsplit.commitments) {
@ -2437,6 +2587,17 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
pindex->nStatus |= BLOCK_HAVE_UNDO;
}
// Now that all consensus rules have been validated, set nCachedBranchId.
// Move this if BLOCK_VALID_CONSENSUS is ever altered.
static_assert(BLOCK_VALID_CONSENSUS == BLOCK_VALID_SCRIPTS,
"nCachedBranchId must be set after all consensus rules have been validated.");
if (IsActivationHeightForAnyUpgrade(pindex->nHeight, Params().GetConsensus())) {
pindex->nStatus |= BLOCK_ACTIVATES_UPGRADE;
pindex->nCachedBranchId = CurrentEpochBranchId(pindex->nHeight, chainparams.GetConsensus());
} else if (pindex->pprev) {
pindex->nCachedBranchId = pindex->pprev->nCachedBranchId;
}
pindex->RaiseValidity(BLOCK_VALID_SCRIPTS);
setDirtyBlockIndex.insert(pindex);
}
@ -2657,11 +2818,13 @@ void static UpdateTip(CBlockIndex *pindexNew) {
}
}
/** Disconnect chainActive's tip. */
bool static DisconnectTip(CValidationState &state) {
/**
* Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and
* mempool.removeWithoutBranchId after this, with cs_main held.
*/
bool static DisconnectTip(CValidationState &state, bool fBare = false) {
CBlockIndex *pindexDelete = chainActive.Tip();
assert(pindexDelete);
mempool.check(pcoinsTip);
// Read block from disk.
CBlock block;
if (!ReadBlockFromDisk(block, pindexDelete))
@ -2680,21 +2843,23 @@ bool static DisconnectTip(CValidationState &state) {
// Write the chain state to disk, if necessary.
if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED))
return false;
// Resurrect mempool transactions from the disconnected block.
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
// ignore validation errors in resurrected transactions
list<CTransaction> removed;
CValidationState stateDummy;
if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL))
mempool.remove(tx, removed, true);
}
if (anchorBeforeDisconnect != anchorAfterDisconnect) {
// The anchor may not change between block disconnects,
// in which case we don't want to evict from the mempool yet!
mempool.removeWithAnchor(anchorBeforeDisconnect);
}
mempool.removeCoinbaseSpends(pcoinsTip, pindexDelete->nHeight);
mempool.check(pcoinsTip);
if (!fBare) {
// Resurrect mempool transactions from the disconnected block.
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
// ignore validation errors in resurrected transactions
list<CTransaction> removed;
CValidationState stateDummy;
if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL))
mempool.remove(tx, removed, true);
}
if (anchorBeforeDisconnect != anchorAfterDisconnect) {
// The anchor may not change between block disconnects,
// in which case we don't want to evict from the mempool yet!
mempool.removeWithAnchor(anchorBeforeDisconnect);
}
}
// Update chainActive and related variables.
UpdateTip(pindexDelete->pprev);
// Get the current commitment tree
@ -2719,10 +2884,10 @@ static int64_t nTimePostConnect = 0;
/**
* Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock
* corresponding to pindexNew, to bypass loading it again from disk.
* You probably want to call mempool.removeWithoutBranchId after this, with cs_main held.
*/
bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) {
assert(pindexNew->pprev == chainActive.Tip());
mempool.check(pcoinsTip);
// Read block from disk.
int64_t nTime1 = GetTimeMicros();
CBlock block;
@ -2762,7 +2927,10 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
// Remove conflicting transactions from the mempool.
list<CTransaction> txConflicted;
mempool.removeForBlock(pblock->vtx, pindexNew->nHeight, txConflicted, !IsInitialBlockDownload());
mempool.check(pcoinsTip);
// Remove transactions that expire at new block height from mempool
mempool.removeExpired(pindexNew->nHeight);
// Update chainActive & related variables.
UpdateTip(pindexNew);
// Tell wallet about transactions that went from mempool
@ -2865,10 +3033,37 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
const CBlockIndex *pindexOldTip = chainActive.Tip();
const CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork);
// - On ChainDB initialization, pindexOldTip will be null, so there are no removable blocks.
// - If pindexMostWork is in a chain that doesn't have the same genesis block as our chain,
// then pindexFork will be null, and we would need to remove the entire chain including
// our genesis block. In practice this (probably) won't happen because of checks elsewhere.
auto reorgLength = pindexOldTip ? pindexOldTip->nHeight - (pindexFork ? pindexFork->nHeight : -1) : 0;
static_assert(MAX_REORG_LENGTH > 0, "We must be able to reorg some distance");
if (reorgLength > MAX_REORG_LENGTH) {
auto msg = strprintf(_(
"A block chain reorganization has been detected that would roll back %d blocks! "
"This is larger than the maximum of %d blocks, and so the node is shutting down for your safety."
), reorgLength, MAX_REORG_LENGTH) + "\n\n" +
_("Reorganization details") + ":\n" +
"- " + strprintf(_("Current tip: %s, height %d, work %s"),
pindexOldTip->phashBlock->GetHex(), pindexOldTip->nHeight, pindexOldTip->nChainWork.GetHex()) + "\n" +
"- " + strprintf(_("New tip: %s, height %d, work %s"),
pindexMostWork->phashBlock->GetHex(), pindexMostWork->nHeight, pindexMostWork->nChainWork.GetHex()) + "\n" +
"- " + strprintf(_("Fork point: %s, height %d"),
pindexFork->phashBlock->GetHex(), pindexFork->nHeight) + "\n\n" +
_("Please help, human!");
LogPrintf("*** %s\n", msg);
uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_ERROR);
StartShutdown();
return false;
}
// Disconnect active blocks which are no longer in the best chain.
bool fBlocksDisconnected = false;
while (chainActive.Tip() && chainActive.Tip() != pindexFork) {
if (!DisconnectTip(state))
return false;
fBlocksDisconnected = true;
}
// Build list of new blocks to connect.
@ -2876,43 +3071,50 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
bool fContinue = true;
int nHeight = pindexFork ? pindexFork->nHeight : -1;
while (fContinue && nHeight != pindexMostWork->nHeight) {
// Don't iterate the entire list of potential improvements toward the best tip, as we likely only need
// a few blocks along the way.
int nTargetHeight = std::min(nHeight + 32, pindexMostWork->nHeight);
vpindexToConnect.clear();
vpindexToConnect.reserve(nTargetHeight - nHeight);
CBlockIndex *pindexIter = pindexMostWork->GetAncestor(nTargetHeight);
while (pindexIter && pindexIter->nHeight != nHeight) {
vpindexToConnect.push_back(pindexIter);
pindexIter = pindexIter->pprev;
}
nHeight = nTargetHeight;
// Connect new blocks.
BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) {
if (!ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) {
if (state.IsInvalid()) {
// The block violates a consensus rule.
if (!state.CorruptionPossible())
InvalidChainFound(vpindexToConnect.back());
state = CValidationState();
fInvalidFound = true;
fContinue = false;
break;
// Don't iterate the entire list of potential improvements toward the best tip, as we likely only need
// a few blocks along the way.
int nTargetHeight = std::min(nHeight + 32, pindexMostWork->nHeight);
vpindexToConnect.clear();
vpindexToConnect.reserve(nTargetHeight - nHeight);
CBlockIndex *pindexIter = pindexMostWork->GetAncestor(nTargetHeight);
while (pindexIter && pindexIter->nHeight != nHeight) {
vpindexToConnect.push_back(pindexIter);
pindexIter = pindexIter->pprev;
}
nHeight = nTargetHeight;
// Connect new blocks.
BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) {
if (!ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) {
if (state.IsInvalid()) {
// The block violates a consensus rule.
if (!state.CorruptionPossible())
InvalidChainFound(vpindexToConnect.back());
state = CValidationState();
fInvalidFound = true;
fContinue = false;
break;
} else {
// A system error occurred (disk space, database error, ...).
return false;
}
} else {
// A system error occurred (disk space, database error, ...).
return false;
}
} else {
PruneBlockIndexCandidates();
if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) {
// We're in a better position than we were. Return temporarily to release the lock.
fContinue = false;
break;
PruneBlockIndexCandidates();
if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) {
// We're in a better position than we were. Return temporarily to release the lock.
fContinue = false;
break;
}
}
}
}
if (fBlocksDisconnected) {
mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
}
mempool.removeWithoutBranchId(
CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, Params().GetConsensus()));
mempool.check(pcoinsTip);
// Callbacks/notifications for a new best chain.
if (fInvalidFound)
@ -2998,6 +3200,9 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) {
// ActivateBestChain considers blocks already in chainActive
// unconditionally valid already, so force disconnect away from it.
if (!DisconnectTip(state)) {
mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
mempool.removeWithoutBranchId(
CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, Params().GetConsensus()));
return false;
}
}
@ -3013,6 +3218,9 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) {
}
InvalidChainFound(pindex);
mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
mempool.removeWithoutBranchId(
CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, Params().GetConsensus()));
return true;
}
@ -3367,6 +3575,12 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
// Check that all transactions are finalized
BOOST_FOREACH(const CTransaction& tx, block.vtx) {
// Check transaction contextually against consensus rules at block height
if (!ContextualCheckTransaction(tx, state, nHeight, 100)) {
return false; // Failure reason has been set in validation state object
}
int nLockTimeFlags = 0;
int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST)
? pindexPrev->GetMedianTimePast()
@ -3786,6 +4000,19 @@ bool static LoadBlockIndexDB()
pindex->nChainSproutValue = pindex->nSproutValue;
}
}
// Construct in-memory chain of branch IDs.
// Relies on invariant: a block that does not activate a network upgrade
// will always be valid under the same consensus rules as its parent.
// Genesis block has a branch ID of zero by definition, but has no
// validity status because it is side-loaded into a fresh chain.
// Activation blocks will have branch IDs set (read from disk).
if (pindex->pprev) {
if (pindex->IsValid(BLOCK_VALID_CONSENSUS) && !pindex->nCachedBranchId) {
pindex->nCachedBranchId = pindex->pprev->nCachedBranchId;
}
} else {
pindex->nCachedBranchId = SPROUT_BRANCH_ID;
}
if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && (pindex->nChainTx || pindex->pprev == NULL))
setBlockIndexCandidates.insert(pindex);
if (pindex->nStatus & BLOCK_FAILED_MASK && (!pindexBestInvalid || pindex->nChainWork > pindexBestInvalid->nChainWork))
@ -3981,6 +4208,135 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
return true;
}
bool RewindBlockIndex(const CChainParams& params)
{
LOCK(cs_main);
// RewindBlockIndex is called after LoadBlockIndex, so at this point every block
// index will have nCachedBranchId set based on the values previously persisted
// to disk. By definition, a set nCachedBranchId means that the block was
// fully-validated under the corresponding consensus rules. Thus we can quickly
// identify whether the current active chain matches our expected sequence of
// consensus rule changes, with two checks:
//
// - BLOCK_ACTIVATES_UPGRADE is set only on blocks that activate upgrades.
// - nCachedBranchId for each block matches what we expect.
auto sufficientlyValidated = [&params](const CBlockIndex* pindex) {
auto consensus = params.GetConsensus();
bool fFlagSet = pindex->nStatus & BLOCK_ACTIVATES_UPGRADE;
bool fFlagExpected = IsActivationHeightForAnyUpgrade(pindex->nHeight, consensus);
return fFlagSet == fFlagExpected &&
pindex->nCachedBranchId &&
*pindex->nCachedBranchId == CurrentEpochBranchId(pindex->nHeight, consensus);
};
int nHeight = 1;
while (nHeight <= chainActive.Height()) {
if (!sufficientlyValidated(chainActive[nHeight])) {
break;
}
nHeight++;
}
// nHeight is now the height of the first insufficiently-validated block, or tipheight + 1
auto rewindLength = chainActive.Height() - nHeight;
if (rewindLength > 0 && rewindLength > MAX_REORG_LENGTH) {
auto pindexOldTip = chainActive.Tip();
auto pindexRewind = chainActive[nHeight - 1];
auto msg = strprintf(_(
"A block chain rewind has been detected that would roll back %d blocks! "
"This is larger than the maximum of %d blocks, and so the node is shutting down for your safety."
), rewindLength, MAX_REORG_LENGTH) + "\n\n" +
_("Rewind details") + ":\n" +
"- " + strprintf(_("Current tip: %s, height %d"),
pindexOldTip->phashBlock->GetHex(), pindexOldTip->nHeight) + "\n" +
"- " + strprintf(_("Rewinding to: %s, height %d"),
pindexRewind->phashBlock->GetHex(), pindexRewind->nHeight) + "\n\n" +
_("Please help, human!");
LogPrintf("*** %s\n", msg);
uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_ERROR);
StartShutdown();
return false;
}
CValidationState state;
CBlockIndex* pindex = chainActive.Tip();
while (chainActive.Height() >= nHeight) {
if (fPruneMode && !(chainActive.Tip()->nStatus & BLOCK_HAVE_DATA)) {
// If pruning, don't try rewinding past the HAVE_DATA point;
// since older blocks can't be served anyway, there's
// no need to walk further, and trying to DisconnectTip()
// will fail (and require a needless reindex/redownload
// of the blockchain).
break;
}
if (!DisconnectTip(state, true)) {
return error("RewindBlockIndex: unable to disconnect block at height %i", pindex->nHeight);
}
// Occasionally flush state to disk.
if (!FlushStateToDisk(state, FLUSH_STATE_PERIODIC))
return false;
}
// Reduce validity flag and have-data flags.
// We do this after actual disconnecting, otherwise we'll end up writing the lack of data
// to disk before writing the chainstate, resulting in a failure to continue if interrupted.
for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); it++) {
CBlockIndex* pindexIter = it->second;
// Note: If we encounter an insufficiently validated block that
// is on chainActive, it must be because we are a pruning node, and
// this block or some successor doesn't HAVE_DATA, so we were unable to
// rewind all the way. Blocks remaining on chainActive at this point
// must not have their validity reduced.
if (!sufficientlyValidated(pindexIter) && !chainActive.Contains(pindexIter)) {
// Reduce validity
pindexIter->nStatus =
std::min<unsigned int>(pindexIter->nStatus & BLOCK_VALID_MASK, BLOCK_VALID_TREE) |
(pindexIter->nStatus & ~BLOCK_VALID_MASK);
// Remove have-data flags
pindexIter->nStatus &= ~(BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO);
// Remove branch ID
pindexIter->nStatus &= ~BLOCK_ACTIVATES_UPGRADE;
pindexIter->nCachedBranchId = boost::none;
// Remove storage location
pindexIter->nFile = 0;
pindexIter->nDataPos = 0;
pindexIter->nUndoPos = 0;
// Remove various other things
pindexIter->nTx = 0;
pindexIter->nChainTx = 0;
pindexIter->nSproutValue = boost::none;
pindexIter->nChainSproutValue = boost::none;
pindexIter->nSequenceId = 0;
// Make sure it gets written
setDirtyBlockIndex.insert(pindexIter);
// Update indices
setBlockIndexCandidates.erase(pindexIter);
auto ret = mapBlocksUnlinked.equal_range(pindexIter->pprev);
while (ret.first != ret.second) {
if (ret.first->second == pindexIter) {
mapBlocksUnlinked.erase(ret.first++);
} else {
++ret.first;
}
}
} else if (pindexIter->IsValid(BLOCK_VALID_TRANSACTIONS) && pindexIter->nChainTx) {
setBlockIndexCandidates.insert(pindexIter);
}
}
PruneBlockIndexCandidates();
CheckBlockIndex();
if (!FlushStateToDisk(state, FLUSH_STATE_ALWAYS)) {
return false;
}
return true;
}
void UnloadBlockIndex()
{
LOCK(cs_main);
@ -4639,6 +4995,19 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return false;
}
// When Overwinter is active, reject incoming connections from non-Overwinter nodes
const Consensus::Params& params = Params().GetConsensus();
if (NetworkUpgradeActive(GetHeight(), params, Consensus::UPGRADE_OVERWINTER)
&& pfrom->nVersion < params.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion)
{
LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion);
pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE,
strprintf("Version must be %d or greater",
params.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion));
pfrom->fDisconnect = true;
return false;
}
if (pfrom->nVersion == 10300)
pfrom->nVersion = 300;
if (!vRecv.empty())
@ -4757,6 +5126,22 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
// Disconnect existing peer connection when:
// 1. The version message has been received
// 2. Overwinter is active
// 3. Peer version is pre-Overwinter
else if (NetworkUpgradeActive(GetHeight(), chainparams.GetConsensus(), Consensus::UPGRADE_OVERWINTER)
&& (pfrom->nVersion < chainparams.GetConsensus().vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion))
{
LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion);
pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE,
strprintf("Version must be %d or greater",
chainparams.GetConsensus().vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion));
pfrom->fDisconnect = true;
return false;
}
else if (strCommand == "addr")
{
vector<CAddress> vAddr;

66
src/main.h

@ -15,6 +15,7 @@
#include "chainparams.h"
#include "coins.h"
#include "consensus/consensus.h"
#include "consensus/upgrades.h"
#include "net.h"
#include "primitives/block.h"
#include "primitives/transaction.h"
@ -46,6 +47,7 @@ class CInv;
class CScriptCheck;
class CValidationInterface;
class CValidationState;
class PrecomputedTransactionData;
struct CNodeStateStats;
@ -58,6 +60,8 @@ static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = DEFAULT_BLOCK_MAX_SIZE /
static const bool DEFAULT_ALERTS = true;
/** Minimum alert priority for enabling safe mode. */
static const int ALERT_PRIORITY_SAFE_MODE = 4000;
/** Maximum reorg length we will accept before we shut down and alert the user. */
static const unsigned int MAX_REORG_LENGTH = COINBASE_MATURITY - 1;
/** Maximum number of signature check operations in an IsStandard() P2SH script */
static const unsigned int MAX_P2SH_SIGOPS = 15;
/** The maximum number of sigops we're willing to relay/mine in a single tx */
@ -66,6 +70,8 @@ static const unsigned int MAX_STANDARD_TX_SIGOPS = MAX_BLOCK_SIGOPS/5;
static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 100;
/** Default for -maxorphantx, maximum number of orphan transactions kept in memory */
static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100;
/** Default for -txexpirydelta, in number of blocks */
static const unsigned int DEFAULT_TX_EXPIRY_DELTA = 20;
/** The maximum size of a blk?????.dat file (since 0.8) */
static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
@ -114,6 +120,7 @@ struct BlockHasher
size_t operator()(const uint256& hash) const { return hash.GetCheapHash(); }
};
extern unsigned int expiryDelta;
extern CScript COINBASE_FLAGS;
extern CCriticalSection cs_main;
extern CTxMemPool mempool;
@ -644,7 +651,7 @@ CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
* @return True if all inputs (scriptSigs) use only standard transaction forms
*/
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, uint32_t consensusBranchId);
/**
* Count ECDSA signature operations the old-fashioned (pre-0.6) way
@ -669,11 +676,17 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& ma
* instead of being performed inline.
*/
bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks,
unsigned int flags, bool cacheStore, const Consensus::Params& consensusParams,
unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata,
const Consensus::Params& consensusParams, uint32_t consensusBranchId,
std::vector<CScriptCheck> *pvChecks = NULL);
/** Check a transaction contextually against a set of consensus rules */
bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state, int nHeight, int dosLevel);
/** Apply the effects of this transaction on the UTXO set represented by view */
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, int nHeight);
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight);
/** Transaction validation functions */
/** Context-independent validity checks */
bool CheckTransaction(const CTransaction& tx, CValidationState& state, libzcash::ProofVerifier& verifier);
@ -682,7 +695,18 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
/** Check for standard transaction types
* @return True if all outputs (scriptPubKeys) use only standard transaction forms
*/
bool IsStandardTx(const CTransaction& tx, std::string& reason);
bool IsStandardTx(const CTransaction& tx, std::string& reason, int nHeight = 0);
namespace Consensus {
/**
* Check whether all inputs of this transaction are valid (no double spends and amounts)
* This does not modify the UTXO set. This does not check scripts and sigs.
* Preconditions: tx.IsCoinBase() is false.
*/
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, const Consensus::Params& consensusParams);
} // namespace Consensus
/**
* Check if transaction is final and can be included in a block with the
@ -690,6 +714,12 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason);
*/
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime);
/**
* Check if transaction is expired and can be included in a block with the
* specified height. Consensus critical.
*/
bool IsExpiredTx(const CTransaction &tx, int nBlockHeight);
/**
* Check if transaction will be final in the next block to be created.
*
@ -707,27 +737,33 @@ class CScriptCheck
{
private:
CScript scriptPubKey;
CAmount amount;
const CTransaction *ptxTo;
unsigned int nIn;
unsigned int nFlags;
bool cacheStore;
uint32_t consensusBranchId;
ScriptError error;
PrecomputedTransactionData *txdata;
public:
CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) :
scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey),
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) { }
CScriptCheck(): amount(0), ptxTo(0), nIn(0), nFlags(0), cacheStore(false), consensusBranchId(0), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, uint32_t consensusBranchIdIn, PrecomputedTransactionData* txdataIn) :
scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), amount(txFromIn.vout[txToIn.vin[nInIn].prevout.n].nValue),
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), consensusBranchId(consensusBranchIdIn), error(SCRIPT_ERR_UNKNOWN_ERROR), txdata(txdataIn) { }
bool operator()();
void swap(CScriptCheck &check) {
scriptPubKey.swap(check.scriptPubKey);
std::swap(ptxTo, check.ptxTo);
std::swap(amount, check.amount);
std::swap(nIn, check.nIn);
std::swap(nFlags, check.nFlags);
std::swap(cacheStore, check.cacheStore);
std::swap(consensusBranchId, check.consensusBranchId);
std::swap(error, check.error);
std::swap(txdata, check.txdata);
}
ScriptError GetScriptError() const { return error; }
@ -784,6 +820,13 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
/**
* When there are blocks in the active chain with missing data (e.g. if the
* activation height and branch ID of a particular upgrade have been altered),
* rewind the chainstate and remove them from the block index.
*/
bool RewindBlockIndex(const CChainParams& params);
class CBlockFileInfo
{
public:
@ -855,7 +898,7 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex);
/** Remove invalidity status from a block and its descendants. */
bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex);
/** The currently-connected chain of blocks. */
/** The currently-connected chain of blocks (protected by cs_main). */
extern CChain chainActive;
/** Global variable that points to the active CCoinsView (protected by cs_main) */
@ -871,8 +914,7 @@ extern CBlockTreeDB *pblocktree;
*/
int GetSpendHeight(const CCoinsViewCache& inputs);
namespace Consensus {
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, const Consensus::Params& consensusParams);
}
/** Return a CMutableTransaction with contextual default values based on set of consensus rules at height */
CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight);
#endif // BITCOIN_MAIN_H

21
src/miner.cpp

@ -13,6 +13,7 @@
#include "base58.h"
#include "chainparams.h"
#include "consensus/consensus.h"
#include "consensus/upgrades.h"
#include "consensus/validation.h"
#ifdef ENABLE_MINING
#include "crypto/equihash.h"
@ -144,6 +145,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
LOCK2(cs_main, mempool.cs);
CBlockIndex* pindexPrev = chainActive.Tip();
const int nHeight = pindexPrev->nHeight + 1;
uint32_t consensusBranchId = CurrentEpochBranchId(nHeight, chainparams.GetConsensus());
pblock->nTime = GetAdjustedTime();
const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
CCoinsViewCache view(pcoinsTip);
@ -156,16 +158,16 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
// This vector will be sorted into a priority queue:
vector<TxPriority> vecPriority;
vecPriority.reserve(mempool.mapTx.size());
for (map<uint256, CTxMemPoolEntry>::iterator mi = mempool.mapTx.begin();
for (CTxMemPool::indexed_transaction_set::iterator mi = mempool.mapTx.begin();
mi != mempool.mapTx.end(); ++mi)
{
const CTransaction& tx = mi->second.GetTx();
const CTransaction& tx = mi->GetTx();
int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST)
? nMedianTimePast
: pblock->GetBlockTime();
if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, nLockTimeCutoff))
if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, nLockTimeCutoff) || IsExpiredTx(tx, nHeight))
continue;
COrphan* porphan = NULL;
@ -199,7 +201,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
}
mapDependers[txin.prevout.hash].push_back(porphan);
porphan->setDependsOn.insert(txin.prevout.hash);
nTotalIn += mempool.mapTx[txin.prevout.hash].GetTx().vout[txin.prevout.n].nValue;
nTotalIn += mempool.mapTx.find(txin.prevout.hash)->GetTx().vout[txin.prevout.n].nValue;
continue;
}
const CCoins* coins = view.AccessCoins(txin.prevout.hash);
@ -231,7 +233,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
porphan->feeRate = feeRate;
}
else
vecPriority.push_back(TxPriority(dPriority, feeRate, &mi->second.GetTx()));
vecPriority.push_back(TxPriority(dPriority, feeRate, &(mi->GetTx())));
}
// Collect transactions into block
@ -294,10 +296,11 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
// policy here, but we still have to ensure that the block we
// create only contains transactions that are valid in new blocks.
CValidationState state;
if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, Params().GetConsensus()))
PrecomputedTransactionData txdata(tx);
if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
continue;
UpdateCoins(tx, state, view, nHeight);
UpdateCoins(tx, view, nHeight);
// Added
pblock->vtx.push_back(tx);
@ -337,12 +340,14 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize);
// Create coinbase tx
CMutableTransaction txNew;
CMutableTransaction txNew = CreateNewContextualCMutableTransaction(chainparams.GetConsensus(), nHeight);
txNew.vin.resize(1);
txNew.vin[0].prevout.SetNull();
txNew.vout.resize(1);
txNew.vout[0].scriptPubKey = scriptPubKeyIn;
txNew.vout[0].nValue = GetBlockSubsidy(nHeight, chainparams.GetConsensus());
// Set to 0 so expiry height does not apply to coinbase txs
txNew.nExpiryHeight = 0;
// Add fees
txNew.vout[0].nValue += nFees;

29
src/net.cpp

@ -7,6 +7,7 @@
#include "config/bitcoin-config.h"
#endif
#include "main.h"
#include "net.h"
#include "addrman.h"
@ -1098,6 +1099,34 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
// Protect connections with certain characteristics
// Check version of eviction candidates and prioritize nodes which do not support network upgrade.
std::vector<CNodeRef> vTmpEvictionCandidates;
int height;
{
LOCK(cs_main);
height = chainActive.Height();
}
const Consensus::Params& params = Params().GetConsensus();
int nActivationHeight = params.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight;
if (nActivationHeight > 0 &&
height < nActivationHeight &&
height >= nActivationHeight - NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD)
{
// Find any nodes which don't support Overwinter protocol version
BOOST_FOREACH(const CNodeRef &node, vEvictionCandidates) {
if (node->nVersion < params.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion) {
vTmpEvictionCandidates.push_back(node);
}
}
// Prioritize these nodes by replacing eviction set with them
if (vTmpEvictionCandidates.size() > 0) {
vEvictionCandidates = vTmpEvictionCandidates;
}
}
// Deterministically select 4 peers to protect by netgroup.
// An attacker cannot predict which netgroups will be protected.
static CompareNetGroupKeyed comparerNetGroupKeyed;

2
src/net.h

@ -61,6 +61,8 @@ static const size_t MAPASKFOR_MAX_SZ = MAX_INV_SZ;
static const size_t SETASKFOR_MAX_SZ = 2 * MAX_INV_SZ;
/** The maximum number of peer connections to maintain. */
static const unsigned int DEFAULT_MAX_PEER_CONNECTIONS = 125;
/** The period before a network upgrade activates, where connections to upgrading peers are preferred (in blocks). */
static const int NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD = 24 * 24 * 3;
unsigned int ReceiveFloodSize();
unsigned int SendBufferSize();

50
src/primitives/transaction.cpp

@ -146,8 +146,9 @@ std::string CTxOut::ToString() const
return strprintf("CTxOut(nValue=%d.%08d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30));
}
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::MIN_CURRENT_VERSION), nLockTime(0) {}
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime),
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::SPROUT_MIN_CURRENT_VERSION), fOverwintered(false), nVersionGroupId(0), nExpiryHeight(0), nLockTime(0) {}
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), fOverwintered(tx.fOverwintered), nVersionGroupId(tx.nVersionGroupId), nExpiryHeight(tx.nExpiryHeight),
vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime),
vjoinsplit(tx.vjoinsplit), joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig)
{
@ -163,19 +164,34 @@ void CTransaction::UpdateHash() const
*const_cast<uint256*>(&hash) = SerializeHash(*this);
}
CTransaction::CTransaction() : nVersion(CTransaction::MIN_CURRENT_VERSION), vin(), vout(), nLockTime(0), vjoinsplit(), joinSplitPubKey(), joinSplitSig() { }
CTransaction::CTransaction() : nVersion(CTransaction::SPROUT_MIN_CURRENT_VERSION), fOverwintered(false), nVersionGroupId(0), nExpiryHeight(0), vin(), vout(), nLockTime(0), vjoinsplit(), joinSplitPubKey(), joinSplitSig() { }
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), vjoinsplit(tx.vjoinsplit),
joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig)
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), fOverwintered(tx.fOverwintered), nVersionGroupId(tx.nVersionGroupId), nExpiryHeight(tx.nExpiryHeight),
vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime),
vjoinsplit(tx.vjoinsplit), joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig)
{
UpdateHash();
}
// Protected constructor which only derived classes can call.
// For developer testing only.
CTransaction::CTransaction(
const CMutableTransaction &tx,
bool evilDeveloperFlag) : nVersion(tx.nVersion), fOverwintered(tx.fOverwintered), nVersionGroupId(tx.nVersionGroupId), nExpiryHeight(tx.nExpiryHeight),
vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime),
vjoinsplit(tx.vjoinsplit), joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig)
{
assert(evilDeveloperFlag);
}
CTransaction& CTransaction::operator=(const CTransaction &tx) {
*const_cast<bool*>(&fOverwintered) = tx.fOverwintered;
*const_cast<int*>(&nVersion) = tx.nVersion;
*const_cast<uint32_t*>(&nVersionGroupId) = tx.nVersionGroupId;
*const_cast<std::vector<CTxIn>*>(&vin) = tx.vin;
*const_cast<std::vector<CTxOut>*>(&vout) = tx.vout;
*const_cast<unsigned int*>(&nLockTime) = tx.nLockTime;
*const_cast<uint32_t*>(&nExpiryHeight) = tx.nExpiryHeight;
*const_cast<std::vector<JSDescription>*>(&vjoinsplit) = tx.vjoinsplit;
*const_cast<uint256*>(&joinSplitPubKey) = tx.joinSplitPubKey;
*const_cast<joinsplit_sig_t*>(&joinSplitSig) = tx.joinSplitSig;
@ -248,12 +264,24 @@ unsigned int CTransaction::CalculateModifiedSize(unsigned int nTxSize) const
std::string CTransaction::ToString() const
{
std::string str;
str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%u, vout.size=%u, nLockTime=%u)\n",
GetHash().ToString().substr(0,10),
nVersion,
vin.size(),
vout.size(),
nLockTime);
if (!fOverwintered) {
str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%u, vout.size=%u, nLockTime=%u)\n",
GetHash().ToString().substr(0,10),
nVersion,
vin.size(),
vout.size(),
nLockTime);
} else if (nVersion >= 3) {
str += strprintf("CTransaction(hash=%s, ver=%d, fOverwintered=%d, nVersionGroupId=%08x, vin.size=%u, vout.size=%u, nLockTime=%u, nExpiryHeight=%u)\n",
GetHash().ToString().substr(0,10),
nVersion,
fOverwintered,
nVersionGroupId,
vin.size(),
vout.size(),
nLockTime,
nExpiryHeight);
}
for (unsigned int i = 0; i < vin.size(); i++)
str += " " + vin[i].ToString() + "\n";
for (unsigned int i = 0; i < vout.size(); i++)

98
src/primitives/transaction.h

@ -304,6 +304,10 @@ public:
std::string ToString() const;
};
// Overwinter version group id
static constexpr uint32_t OVERWINTER_VERSION_GROUP_ID = 0x03C48270;
static_assert(OVERWINTER_VERSION_GROUP_ID != 0, "version group id must be non-zero as specified in ZIP 202");
struct CMutableTransaction;
/** The basic transaction that is broadcasted on the network and contained in
@ -316,14 +320,29 @@ private:
const uint256 hash;
void UpdateHash() const;
protected:
/** Developer testing only. Set evilDeveloperFlag to true.
* Convert a CMutableTransaction into a CTransaction without invoking UpdateHash()
*/
CTransaction(const CMutableTransaction &tx, bool evilDeveloperFlag);
public:
typedef boost::array<unsigned char, 64> joinsplit_sig_t;
// Transactions that include a list of JoinSplits are version 2.
static const int32_t MIN_CURRENT_VERSION = 1;
static const int32_t MAX_CURRENT_VERSION = 2;
// Transactions that include a list of JoinSplits are >= version 2.
static const int32_t SPROUT_MIN_CURRENT_VERSION = 1;
static const int32_t SPROUT_MAX_CURRENT_VERSION = 2;
static const int32_t OVERWINTER_MIN_CURRENT_VERSION = 3;
static const int32_t OVERWINTER_MAX_CURRENT_VERSION = 3;
static_assert(SPROUT_MIN_CURRENT_VERSION >= SPROUT_MIN_TX_VERSION,
"standard rule for tx version should be consistent with network rule");
static_assert(OVERWINTER_MIN_CURRENT_VERSION >= OVERWINTER_MIN_TX_VERSION,
"standard rule for tx version should be consistent with network rule");
static_assert(MIN_CURRENT_VERSION >= MIN_TX_VERSION,
static_assert( (OVERWINTER_MAX_CURRENT_VERSION <= OVERWINTER_MAX_TX_VERSION &&
OVERWINTER_MAX_CURRENT_VERSION >= OVERWINTER_MIN_CURRENT_VERSION),
"standard rule for tx version should be consistent with network rule");
// The local variables are made const to prevent unintended modification
@ -331,10 +350,13 @@ public:
// actually immutable; deserialization and assignment are implemented,
// and bypass the constness. This is safe, as they update the entire
// structure, including the hash.
const bool fOverwintered;
const int32_t nVersion;
const uint32_t nVersionGroupId;
const std::vector<CTxIn> vin;
const std::vector<CTxOut> vout;
const uint32_t nLockTime;
const uint32_t nExpiryHeight;
const std::vector<JSDescription> vjoinsplit;
const uint256 joinSplitPubKey;
const joinsplit_sig_t joinSplitSig = {{0}};
@ -351,11 +373,34 @@ public:
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(*const_cast<int32_t*>(&this->nVersion));
if (ser_action.ForRead()) {
// When deserializing, unpack the 4 byte header to extract fOverwintered and nVersion.
uint32_t header;
READWRITE(header);
*const_cast<bool*>(&fOverwintered) = header >> 31;
*const_cast<int32_t*>(&this->nVersion) = header & 0x7FFFFFFF;
} else {
uint32_t header = GetHeader();
READWRITE(header);
}
nVersion = this->nVersion;
if (fOverwintered) {
READWRITE(*const_cast<uint32_t*>(&this->nVersionGroupId));
}
bool isOverwinterV3 = fOverwintered &&
nVersionGroupId == OVERWINTER_VERSION_GROUP_ID &&
nVersion == 3;
if (fOverwintered && !isOverwinterV3) {
throw std::ios_base::failure("Unknown transaction format");
}
READWRITE(*const_cast<std::vector<CTxIn>*>(&vin));
READWRITE(*const_cast<std::vector<CTxOut>*>(&vout));
READWRITE(*const_cast<uint32_t*>(&nLockTime));
if (isOverwinterV3) {
READWRITE(*const_cast<uint32_t*>(&nExpiryHeight));
}
if (nVersion >= 2) {
READWRITE(*const_cast<std::vector<JSDescription>*>(&vjoinsplit));
if (vjoinsplit.size() > 0) {
@ -375,6 +420,16 @@ public:
return hash;
}
uint32_t GetHeader() const {
// When serializing v1 and v2, the 4 byte header is nVersion
uint32_t header = this->nVersion;
// When serializing Overwintered tx, the 4 byte header is the combination of fOverwintered and nVersion
if (fOverwintered) {
header |= 1 << 31;
}
return header;
}
// Return sum of txouts.
CAmount GetValueOut() const;
// GetValueIn() is a method on CCoinsViewCache, because
@ -410,10 +465,13 @@ public:
/** A mutable version of CTransaction. */
struct CMutableTransaction
{
bool fOverwintered;
int32_t nVersion;
uint32_t nVersionGroupId;
std::vector<CTxIn> vin;
std::vector<CTxOut> vout;
uint32_t nLockTime;
uint32_t nExpiryHeight;
std::vector<JSDescription> vjoinsplit;
uint256 joinSplitPubKey;
CTransaction::joinsplit_sig_t joinSplitSig = {{0}};
@ -425,11 +483,39 @@ struct CMutableTransaction
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(this->nVersion);
if (ser_action.ForRead()) {
// When deserializing, unpack the 4 byte header to extract fOverwintered and nVersion.
uint32_t header;
READWRITE(header);
fOverwintered = header >> 31;
this->nVersion = header & 0x7FFFFFFF;
} else {
// When serializing v1 and v2, the 4 byte header is nVersion
uint32_t header = this->nVersion;
// When serializing Overwintered tx, the 4 byte header is the combination of fOverwintered and nVersion
if (fOverwintered) {
header |= 1 << 31;
}
READWRITE(header);
}
nVersion = this->nVersion;
if (fOverwintered) {
READWRITE(nVersionGroupId);
}
bool isOverwinterV3 = fOverwintered &&
nVersionGroupId == OVERWINTER_VERSION_GROUP_ID &&
nVersion == 3;
if (fOverwintered && !isOverwinterV3) {
throw std::ios_base::failure("Unknown transaction format");
}
READWRITE(vin);
READWRITE(vout);
READWRITE(nLockTime);
if (isOverwinterV3) {
READWRITE(nExpiryHeight);
}
if (nVersion >= 2) {
READWRITE(vjoinsplit);
if (vjoinsplit.size() > 0) {

4
src/protocol.h

@ -71,10 +71,6 @@ enum {
// set by all Bitcoin Core nodes, and is unset by SPV clients or other peers that just want
// network services but don't provide them.
NODE_NETWORK = (1 << 0),
// NODE_GETUTXO means the node is capable of responding to the getutxo protocol request.
// Bitcoin Core does not support this but a patch set called Bitcoin XT does.
// See BIP 64 for details on how this is implemented.
NODE_GETUTXO = (1 << 1),
// Bits 24-31 are reserved for temporary experiments. Just pick a bit that
// isn't getting used, or one not being used much, and notify the

4
src/pubkey.cpp

@ -104,8 +104,8 @@ void CExtPubKey::Encode(unsigned char code[74]) const {
code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF;
memcpy(code+9, chaincode.begin(), 32);
assert(pubkey.size() == COMPRESSED_PUBLIC_KEY_SIZE);
memcpy(code+41, pubkey.begin(), COMPRESSED_PUBLIC_KEY_SIZE);
assert(pubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE);
memcpy(code+41, pubkey.begin(), CPubKey::COMPRESSED_PUBLIC_KEY_SIZE);
}
void CExtPubKey::Decode(const unsigned char code[74]) {

31
src/pubkey.h

@ -14,18 +14,6 @@
#include <stdexcept>
#include <vector>
/**
* secp256k1:
*/
const unsigned int PUBLIC_KEY_SIZE = 65;
const unsigned int COMPRESSED_PUBLIC_KEY_SIZE = 33;
const unsigned int SIGNATURE_SIZE = 72;
const unsigned int COMPACT_SIGNATURE_SIZE = 65;
/**
* see www.keylength.com
* script supports up to 75 for single byte push
*/
/** A reference to a CKey: the Hash160 of its serialized public key */
class CKeyID : public uint160
{
@ -39,6 +27,22 @@ typedef uint256 ChainCode;
/** An encapsulated public key. */
class CPubKey
{
public:
/**
* secp256k1:
*/
static const unsigned int PUBLIC_KEY_SIZE = 65;
static const unsigned int COMPRESSED_PUBLIC_KEY_SIZE = 33;
static const unsigned int SIGNATURE_SIZE = 72;
static const unsigned int COMPACT_SIGNATURE_SIZE = 65;
/**
* see www.keylength.com
* script supports up to 75 for single byte push
*/
static_assert(
PUBLIC_KEY_SIZE >= COMPRESSED_PUBLIC_KEY_SIZE,
"COMPRESSED_PUBLIC_KEY_SIZE is larger than PUBLIC_KEY_SIZE");
private:
/**
@ -46,9 +50,6 @@ private:
* Its length can very cheaply be computed from the first byte.
*/
unsigned char vch[PUBLIC_KEY_SIZE];
static_assert(
PUBLIC_KEY_SIZE >= COMPRESSED_PUBLIC_KEY_SIZE,
"COMPRESSED_PUBLIC_KEY_SIZE is larger than PUBLIC_KEY_SIZE");
//! Compute the length of a pubkey with a given first byte.
unsigned int static GetLen(unsigned char chHeader)

63
src/rpcblockchain.cpp

@ -343,10 +343,9 @@ UniValue mempoolToJSON(bool fVerbose = false)
{
LOCK(mempool.cs);
UniValue o(UniValue::VOBJ);
BOOST_FOREACH(const PAIRTYPE(uint256, CTxMemPoolEntry)& entry, mempool.mapTx)
BOOST_FOREACH(const CTxMemPoolEntry& e, mempool.mapTx)
{
const uint256& hash = entry.first;
const CTxMemPoolEntry& e = entry.second;
const uint256& hash = e.GetTx().GetHash();
UniValue info(UniValue::VOBJ);
info.push_back(Pair("size", (int)e.GetTxSize()));
info.push_back(Pair("fee", ValueFromAmount(e.GetFee())));
@ -874,12 +873,45 @@ static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex*
return rv;
}
static UniValue NetworkUpgradeDesc(const Consensus::Params& consensusParams, Consensus::UpgradeIndex idx, int height)
{
UniValue rv(UniValue::VOBJ);
auto upgrade = NetworkUpgradeInfo[idx];
rv.push_back(Pair("name", upgrade.strName));
rv.push_back(Pair("activationheight", consensusParams.vUpgrades[idx].nActivationHeight));
switch (NetworkUpgradeState(height, consensusParams, idx)) {
case UPGRADE_DISABLED: rv.push_back(Pair("status", "disabled")); break;
case UPGRADE_PENDING: rv.push_back(Pair("status", "pending")); break;
case UPGRADE_ACTIVE: rv.push_back(Pair("status", "active")); break;
}
rv.push_back(Pair("info", upgrade.strInfo));
return rv;
}
void NetworkUpgradeDescPushBack(
UniValue& networkUpgrades,
const Consensus::Params& consensusParams,
Consensus::UpgradeIndex idx,
int height)
{
// Network upgrades with an activation height of NO_ACTIVATION_HEIGHT are
// hidden. This is used when network upgrade implementations are merged
// without specifying the activation height.
if (consensusParams.vUpgrades[idx].nActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT) {
networkUpgrades.push_back(Pair(
HexInt(NetworkUpgradeInfo[idx].nBranchId),
NetworkUpgradeDesc(consensusParams, idx, height)));
}
}
UniValue getblockchaininfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
"getblockchaininfo\n"
"Returns an object containing various state info regarding block chain processing.\n"
"\nNote that when the chain tip is at the last block before a network upgrade activation,\n"
"consensus.chaintip != consensus.nextblock.\n"
"\nResult:\n"
"{\n"
" \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
@ -902,7 +934,19 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
" },\n"
" \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n"
" }, ...\n"
" ]\n"
" ],\n"
" \"upgrades\": { (object) status of network upgrades\n"
" \"xxxx\" : { (string) branch ID of the upgrade\n"
" \"name\": \"xxxx\", (string) name of upgrade\n"
" \"activationheight\": xxxxxx, (numeric) block height of activation\n"
" \"status\": \"xxxx\", (string) status of upgrade\n"
" \"info\": \"xxxx\", (string) additional information about upgrade\n"
" }, ...\n"
" },\n"
" \"consensus\": { (object) branch IDs of the current and upcoming consensus rules\n"
" \"chaintip\": \"xxxxxxxx\", (string) branch ID used to validate the current chain tip\n"
" \"nextblock\": \"xxxxxxxx\" (string) branch ID that the next block will be validated under\n"
" }\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getblockchaininfo", "")
@ -937,6 +981,17 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
obj.push_back(Pair("softforks", softforks));
UniValue upgrades(UniValue::VOBJ);
for (int i = Consensus::UPGRADE_OVERWINTER; i < Consensus::MAX_NETWORK_UPGRADES; i++) {
NetworkUpgradeDescPushBack(upgrades, consensusParams, Consensus::UpgradeIndex(i), tip->nHeight);
}
obj.push_back(Pair("upgrades", upgrades));
UniValue consensus(UniValue::VOBJ);
consensus.push_back(Pair("chaintip", HexInt(CurrentEpochBranchId(tip->nHeight, consensusParams))));
consensus.push_back(Pair("nextblock", HexInt(CurrentEpochBranchId(tip->nHeight + 1, consensusParams))));
obj.push_back(Pair("consensus", consensus));
if (fPruneMode)
{
CBlockIndex *block = chainActive.Tip();

4
src/rpcclient.cpp

@ -123,6 +123,10 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "z_gettotalbalance", 0},
{ "z_gettotalbalance", 1},
{ "z_gettotalbalance", 2},
{ "z_mergetoaddress", 0},
{ "z_mergetoaddress", 2},
{ "z_mergetoaddress", 3},
{ "z_mergetoaddress", 4},
{ "z_sendmany", 1},
{ "z_sendmany", 2},
{ "z_sendmany", 3},

27
src/rpcnet.cpp

@ -403,6 +403,33 @@ static UniValue GetNetworksInfo()
return networks;
}
UniValue getdeprecationinfo(const UniValue& params, bool fHelp)
{
const CChainParams& chainparams = Params();
if (fHelp || params.size() != 0 || chainparams.NetworkIDString() != "main")
throw runtime_error(
"getdeprecationinfo\n"
"Returns an object containing current version and deprecation block height. Applicable only on mainnet.\n"
"\nResult:\n"
"{\n"
" \"version\": xxxxx, (numeric) the server version\n"
" \"subversion\": \"/MagicBean:x.y.z[-v]/\", (string) the server subversion string\n"
" \"deprecationheight\": xxxxx, (numeric) the block height at which this version will deprecate and shut down (unless -disabledeprecation is set)\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getdeprecationinfo", "")
+ HelpExampleRpc("getdeprecationinfo", "")
);
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("version", CLIENT_VERSION));
obj.push_back(Pair("subversion",
FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>())));
obj.push_back(Pair("deprecationheight", DEPRECATION_HEIGHT));
return obj;
}
UniValue getnetworkinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)

56
src/rpcrawtransaction.cpp

@ -4,6 +4,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "base58.h"
#include "consensus/upgrades.h"
#include "consensus/validation.h"
#include "core_io.h"
#include "init.h"
@ -118,8 +119,15 @@ void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue&
uint256 txid = tx.GetHash();
entry.push_back(Pair("txid", txid.GetHex()));
entry.push_back(Pair("overwintered", tx.fOverwintered));
entry.push_back(Pair("version", tx.nVersion));
if (tx.fOverwintered) {
entry.push_back(Pair("versiongroupid", HexInt(tx.nVersionGroupId)));
}
entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
if (tx.fOverwintered) {
entry.push_back(Pair("expiryheight", (int64_t)tx.nExpiryHeight));
}
UniValue vin(UniValue::VARR);
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
UniValue in(UniValue::VOBJ);
@ -199,9 +207,16 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
uint256 txid = tx.GetHash();
entry.push_back(Pair("txid", txid.GetHex()));
entry.push_back(Pair("overwintered", tx.fOverwintered));
entry.push_back(Pair("size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)));
entry.push_back(Pair("version", tx.nVersion));
if (tx.fOverwintered) {
entry.push_back(Pair("versiongroupid", HexInt(tx.nVersionGroupId)));
}
entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
if (tx.fOverwintered) {
entry.push_back(Pair("expiryheight", (int64_t)tx.nExpiryHeight));
}
UniValue vin(UniValue::VARR);
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
@ -278,6 +293,7 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp)
" \"txid\" : \"id\", (string) The transaction id (same as provided)\n"
" \"version\" : n, (numeric) The version\n"
" \"locktime\" : ttt, (numeric) The lock time\n"
" \"expiryheight\" : ttt, (numeric, optional) The block height after which the transaction expires\n"
" \"vin\" : [ (array of json objects)\n"
" {\n"
" \"txid\": \"id\", (string) The transaction id\n"
@ -544,7 +560,16 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp)
UniValue inputs = params[0].get_array();
UniValue sendTo = params[1].get_obj();
CMutableTransaction rawTx;
int nextBlockHeight = chainActive.Height() + 1;
CMutableTransaction rawTx = CreateNewContextualCMutableTransaction(
Params().GetConsensus(), nextBlockHeight);
if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
rawTx.nExpiryHeight = nextBlockHeight + expiryDelta;
if (rawTx.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD){
throw JSONRPCError(RPC_INVALID_PARAMETER, "nExpiryHeight must be less than TX_EXPIRY_HEIGHT_THRESHOLD.");
}
}
for (size_t idx = 0; idx < inputs.size(); idx++) {
const UniValue& input = inputs[idx];
@ -597,8 +622,11 @@ UniValue decoderawtransaction(const UniValue& params, bool fHelp)
"\nResult:\n"
"{\n"
" \"txid\" : \"id\", (string) The transaction id\n"
" \"overwintered\" : bool (boolean) The Overwintered flag\n"
" \"version\" : n, (numeric) The version\n"
" \"versiongroupid\": \"hex\" (string, optional) The version group id (Overwintered txs)\n"
" \"locktime\" : ttt, (numeric) The lock time\n"
" \"expiryheight\" : n, (numeric, optional) Last valid block height for mining transaction (Overwintered txs)\n"
" \"vin\" : [ (array of json objects)\n"
" {\n"
" \"txid\": \"id\", (string) The transaction id\n"
@ -752,7 +780,8 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
" \"txid\":\"id\", (string, required) The transaction id\n"
" \"vout\":n, (numeric, required) The output number\n"
" \"scriptPubKey\": \"hex\", (string, required) script key\n"
" \"redeemScript\": \"hex\" (string, required for P2SH) redeem script\n"
" \"redeemScript\": \"hex\", (string, required for P2SH) redeem script\n"
" \"amount\": value (numeric, required) The amount spent\n"
" }\n"
" ,...\n"
" ]\n"
@ -890,7 +919,10 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
if ((unsigned int)nOut >= coins->vout.size())
coins->vout.resize(nOut+1);
coins->vout[nOut].scriptPubKey = scriptPubKey;
coins->vout[nOut].nValue = 0; // we don't know the actual output value
coins->vout[nOut].nValue = 0;
if (prevOut.exists("amount")) {
coins->vout[nOut].nValue = AmountFromValue(find_value(prevOut, "amount"));
}
}
// if redeemScript given and not using the local wallet (private keys
@ -933,9 +965,15 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
// Grab the current consensus branch ID
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
// Script verification errors
UniValue vErrors(UniValue::VARR);
// Use CTransaction for the constant parts of the
// transaction to avoid rehashing.
const CTransaction txConst(mergedTx);
// Sign what we can:
for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
CTxIn& txin = mergedTx.vin[i];
@ -945,18 +983,22 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
continue;
}
const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
const CAmount& amount = coins->vout[txin.prevout.n].nValue;
txin.scriptSig.clear();
SignatureData sigdata;
// Only sign SIGHASH_SINGLE if there's a corresponding output:
if (!fHashSingle || (i < mergedTx.vout.size()))
SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType), prevPubKey, sigdata, consensusBranchId);
// ... and merge in other signatures:
BOOST_FOREACH(const CMutableTransaction& txv, txVariants) {
txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(txv, i), consensusBranchId);
}
UpdateTransaction(mergedTx, i, sigdata);
ScriptError serror = SCRIPT_ERR_OK;
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i), &serror)) {
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), consensusBranchId, &serror)) {
TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
}
}

2
src/rpcserver.cpp

@ -265,6 +265,7 @@ static const CRPCCommand vRPCCommands[] =
/* P2P networking */
{ "network", "getnetworkinfo", &getnetworkinfo, true },
{ "network", "getdeprecationinfo", &getdeprecationinfo, true },
{ "network", "addnode", &addnode, true },
{ "network", "disconnectnode", &disconnectnode, true },
{ "network", "getaddednodeinfo", &getaddednodeinfo, true },
@ -397,6 +398,7 @@ static const CRPCCommand vRPCCommands[] =
{ "wallet", "z_listunspent", &z_listunspent, false },
{ "wallet", "z_getbalance", &z_getbalance, false },
{ "wallet", "z_gettotalbalance", &z_gettotalbalance, false },
{ "wallet", "z_mergetoaddress", &z_mergetoaddress, false },
{ "wallet", "z_sendmany", &z_sendmany, false },
{ "wallet", "z_shieldcoinbase", &z_shieldcoinbase, false },
{ "wallet", "z_getoperationstatus", &z_getoperationstatus, true },

2
src/rpcserver.h

@ -245,6 +245,7 @@ extern UniValue getinfo(const UniValue& params, bool fHelp);
extern UniValue getwalletinfo(const UniValue& params, bool fHelp);
extern UniValue getblockchaininfo(const UniValue& params, bool fHelp);
extern UniValue getnetworkinfo(const UniValue& params, bool fHelp);
extern UniValue getdeprecationinfo(const UniValue& params, bool fHelp);
extern UniValue setmocktime(const UniValue& params, bool fHelp);
extern UniValue resendwallettransactions(const UniValue& params, bool fHelp);
extern UniValue zc_benchmark(const UniValue& params, bool fHelp);
@ -301,6 +302,7 @@ extern UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp); //
extern UniValue z_listunspent(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue z_getbalance(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue z_gettotalbalance(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue z_mergetoaddress(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue z_sendmany(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue z_shieldcoinbase(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue z_getoperationstatus(const UniValue& params, bool fHelp); // in rpcwallet.cpp

173
src/script/interpreter.cpp

@ -5,6 +5,7 @@
#include "interpreter.h"
#include "consensus/upgrades.h"
#include "primitives/transaction.h"
#include "crypto/ripemd160.h"
#include "crypto/sha1.h"
@ -232,7 +233,13 @@ bool static CheckMinimalPush(const valtype& data, opcodetype opcode) {
return true;
}
bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
bool EvalScript(
vector<vector<unsigned char> >& stack,
const CScript& script,
unsigned int flags,
const BaseSignatureChecker& checker,
uint32_t consensusBranchId,
ScriptError* serror)
{
static const CScriptNum bnZero(0);
static const CScriptNum bnOne(1);
@ -828,7 +835,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
//serror is set
return false;
}
bool fSuccess = checker.CheckSig(vchSig, vchPubKey, script);
bool fSuccess = checker.CheckSig(vchSig, vchPubKey, script, consensusBranchId);
popstack(stack);
popstack(stack);
@ -886,7 +893,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
}
// Check signature
bool fOk = checker.CheckSig(vchSig, vchPubKey, script);
bool fOk = checker.CheckSig(vchSig, vchPubKey, script, consensusBranchId);
if (fOk) {
isig++;
@ -1050,15 +1057,148 @@ public:
}
};
const unsigned char ZCASH_PREVOUTS_HASH_PERSONALIZATION[crypto_generichash_blake2b_PERSONALBYTES] =
{'Z','c','a','s','h','P','r','e','v','o','u','t','H','a','s','h'};
const unsigned char ZCASH_SEQUENCE_HASH_PERSONALIZATION[crypto_generichash_blake2b_PERSONALBYTES] =
{'Z','c','a','s','h','S','e','q','u','e','n','c','H','a','s','h'};
const unsigned char ZCASH_OUTPUTS_HASH_PERSONALIZATION[crypto_generichash_blake2b_PERSONALBYTES] =
{'Z','c','a','s','h','O','u','t','p','u','t','s','H','a','s','h'};
const unsigned char ZCASH_JOINSPLITS_HASH_PERSONALIZATION[crypto_generichash_blake2b_PERSONALBYTES] =
{'Z','c','a','s','h','J','S','p','l','i','t','s','H','a','s','h'};
uint256 GetPrevoutHash(const CTransaction& txTo) {
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_PREVOUTS_HASH_PERSONALIZATION);
for (unsigned int n = 0; n < txTo.vin.size(); n++) {
ss << txTo.vin[n].prevout;
}
return ss.GetHash();
}
uint256 GetSequenceHash(const CTransaction& txTo) {
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_SEQUENCE_HASH_PERSONALIZATION);
for (unsigned int n = 0; n < txTo.vin.size(); n++) {
ss << txTo.vin[n].nSequence;
}
return ss.GetHash();
}
uint256 GetOutputsHash(const CTransaction& txTo) {
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_OUTPUTS_HASH_PERSONALIZATION);
for (unsigned int n = 0; n < txTo.vout.size(); n++) {
ss << txTo.vout[n];
}
return ss.GetHash();
}
uint256 GetJoinSplitsHash(const CTransaction& txTo) {
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_JOINSPLITS_HASH_PERSONALIZATION);
for (unsigned int n = 0; n < txTo.vjoinsplit.size(); n++) {
ss << txTo.vjoinsplit[n];
}
ss << txTo.joinSplitPubKey;
return ss.GetHash();
}
} // anon namespace
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo)
{
hashPrevouts = GetPrevoutHash(txTo);
hashSequence = GetSequenceHash(txTo);
hashOutputs = GetOutputsHash(txTo);
hashJoinSplits = GetJoinSplitsHash(txTo);
}
SigVersion SignatureHashVersion(const CTransaction& txTo)
{
if (txTo.fOverwintered) {
return SIGVERSION_OVERWINTER;
} else {
return SIGVERSION_SPROUT;
}
}
uint256 SignatureHash(
const CScript& scriptCode,
const CTransaction& txTo,
unsigned int nIn,
int nHashType,
const CAmount& amount,
uint32_t consensusBranchId,
const PrecomputedTransactionData* cache)
{
if (nIn >= txTo.vin.size() && nIn != NOT_AN_INPUT) {
// nIn out of range
throw logic_error("input index is out of range");
}
auto sigversion = SignatureHashVersion(txTo);
if (sigversion == SIGVERSION_OVERWINTER) {
uint256 hashPrevouts;
uint256 hashSequence;
uint256 hashOutputs;
uint256 hashJoinSplits;
if (!(nHashType & SIGHASH_ANYONECANPAY)) {
hashPrevouts = cache ? cache->hashPrevouts : GetPrevoutHash(txTo);
}
if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
hashSequence = cache ? cache->hashSequence : GetSequenceHash(txTo);
}
if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
hashOutputs = cache ? cache->hashOutputs : GetOutputsHash(txTo);
} else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) {
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_OUTPUTS_HASH_PERSONALIZATION);
ss << txTo.vout[nIn];
hashOutputs = ss.GetHash();
}
if (!txTo.vjoinsplit.empty()) {
hashJoinSplits = cache ? cache->hashJoinSplits : GetJoinSplitsHash(txTo);
}
uint32_t leConsensusBranchId = htole32(consensusBranchId);
unsigned char personalization[16] = {};
memcpy(personalization, "ZcashSigHash", 12);
memcpy(personalization+12, &leConsensusBranchId, 4);
CBLAKE2bWriter ss(SER_GETHASH, 0, personalization);
// Header
ss << txTo.GetHeader();
// Version group ID
ss << txTo.nVersionGroupId;
// Input prevouts/nSequence (none/all, depending on flags)
ss << hashPrevouts;
ss << hashSequence;
// Outputs (none/one/all, depending on flags)
ss << hashOutputs;
// JoinSplits
ss << hashJoinSplits;
// Locktime
ss << txTo.nLockTime;
// Expiry height
ss << txTo.nExpiryHeight;
// Sighash type
ss << nHashType;
// If this hash is for a transparent input signature
// (i.e. not for txTo.joinSplitSig):
if (nIn != NOT_AN_INPUT){
// The input being signed (replacing the scriptSig with scriptCode + amount)
// The prevout may already be contained in hashPrevout, and the nSequence
// may already be contained in hashSequence.
ss << txTo.vin[nIn].prevout;
ss << scriptCode;
ss << amount;
ss << txTo.vin[nIn].nSequence;
}
return ss.GetHash();
}
// Check for invalid use of SIGHASH_SINGLE
if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
if (nIn >= txTo.vout.size()) {
@ -1076,12 +1216,17 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig
return ss.GetHash();
}
bool TransactionSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
bool TransactionSignatureChecker::VerifySignature(
const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
{
return pubkey.Verify(sighash, vchSig);
}
bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
bool TransactionSignatureChecker::CheckSig(
const vector<unsigned char>& vchSigIn,
const vector<unsigned char>& vchPubKey,
const CScript& scriptCode,
uint32_t consensusBranchId) const
{
CPubKey pubkey(vchPubKey);
if (!pubkey.IsValid())
@ -1096,7 +1241,7 @@ bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn
uint256 sighash;
try {
sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, consensusBranchId, this->txdata);
} catch (logic_error ex) {
return false;
}
@ -1144,7 +1289,13 @@ bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) con
}
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
bool VerifyScript(
const CScript& scriptSig,
const CScript& scriptPubKey,
unsigned int flags,
const BaseSignatureChecker& checker,
uint32_t consensusBranchId,
ScriptError* serror)
{
set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
@ -1153,12 +1304,12 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
}
vector<vector<unsigned char> > stack, stackCopy;
if (!EvalScript(stack, scriptSig, flags, checker, serror))
if (!EvalScript(stack, scriptSig, flags, checker, consensusBranchId, serror))
// serror is set
return false;
if (flags & SCRIPT_VERIFY_P2SH)
stackCopy = stack;
if (!EvalScript(stack, scriptPubKey, flags, checker, serror))
if (!EvalScript(stack, scriptPubKey, flags, checker, consensusBranchId, serror))
// serror is set
return false;
if (stack.empty())
@ -1185,7 +1336,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end());
popstack(stack);
if (!EvalScript(stack, pubKey2, flags, checker, serror))
if (!EvalScript(stack, pubKey2, flags, checker, consensusBranchId, serror))
// serror is set
return false;
if (stack.empty())

53
src/script/interpreter.h

@ -88,12 +88,36 @@ enum
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9),
};
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
struct PrecomputedTransactionData
{
uint256 hashPrevouts, hashSequence, hashOutputs, hashJoinSplits;
PrecomputedTransactionData(const CTransaction& tx);
};
enum SigVersion
{
SIGVERSION_SPROUT = 0,
SIGVERSION_OVERWINTER = 1,
};
uint256 SignatureHash(
const CScript &scriptCode,
const CTransaction& txTo,
unsigned int nIn,
int nHashType,
const CAmount& amount,
uint32_t consensusBranchId,
const PrecomputedTransactionData* cache = NULL);
class BaseSignatureChecker
{
public:
virtual bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
virtual bool CheckSig(
const std::vector<unsigned char>& scriptSig,
const std::vector<unsigned char>& vchPubKey,
const CScript& scriptCode,
uint32_t consensusBranchId) const
{
return false;
}
@ -111,13 +135,16 @@ class TransactionSignatureChecker : public BaseSignatureChecker
private:
const CTransaction* txTo;
unsigned int nIn;
const CAmount amount;
const PrecomputedTransactionData* txdata;
protected:
virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
public:
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn) {}
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const;
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(NULL) {}
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, const PrecomputedTransactionData& txdataIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {}
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, uint32_t consensusBranchId) const;
bool CheckLockTime(const CScriptNum& nLockTime) const;
};
@ -127,10 +154,22 @@ private:
const CTransaction txTo;
public:
MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn) : TransactionSignatureChecker(&txTo, nInIn), txTo(*txToIn) {}
MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount) : TransactionSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {}
};
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL);
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL);
bool EvalScript(
std::vector<std::vector<unsigned char> >& stack,
const CScript& script,
unsigned int flags,
const BaseSignatureChecker& checker,
uint32_t consensusBranchId,
ScriptError* error = NULL);
bool VerifyScript(
const CScript& scriptSig,
const CScript& scriptPubKey,
unsigned int flags,
const BaseSignatureChecker& checker,
uint32_t consensusBranchId,
ScriptError* serror = NULL);
#endif // BITCOIN_SCRIPT_INTERPRETER_H

2
src/script/sigcache.h

@ -18,7 +18,7 @@ private:
bool store;
public:
CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, bool storeIn=true) : TransactionSignatureChecker(txToIn, nInIn), store(storeIn) {}
CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn, PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nInIn, amount, txdataIn), store(storeIn) {}
bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
};

241
src/script/sign.cpp

@ -17,9 +17,9 @@ using namespace std;
typedef vector<unsigned char> valtype;
TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), checker(txTo, nIn) {}
TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {}
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode) const
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, uint32_t consensusBranchId) const
{
CKey key;
if (!keystore->GetKey(address, key))
@ -27,7 +27,7 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
uint256 hash;
try {
hash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, consensusBranchId);
} catch (logic_error ex) {
return false;
}
@ -38,16 +38,16 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
return true;
}
static bool Sign1(const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, CScript& scriptSigRet)
static bool Sign1(const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, uint32_t consensusBranchId)
{
vector<unsigned char> vchSig;
if (!creator.CreateSig(vchSig, address, scriptCode))
if (!creator.CreateSig(vchSig, address, scriptCode, consensusBranchId))
return false;
scriptSigRet << vchSig;
ret.push_back(vchSig);
return true;
}
static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, CScript& scriptSigRet)
static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, uint32_t consensusBranchId)
{
int nSigned = 0;
int nRequired = multisigdata.front()[0];
@ -55,7 +55,7 @@ static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreato
{
const valtype& pubkey = multisigdata[i];
CKeyID keyID = CPubKey(pubkey).GetID();
if (Sign1(keyID, creator, scriptCode, scriptSigRet))
if (Sign1(keyID, creator, scriptCode, ret, consensusBranchId))
++nSigned;
}
return nSigned==nRequired;
@ -68,9 +68,11 @@ static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreato
* Returns false if scriptPubKey could not be completely satisfied.
*/
static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptPubKey,
CScript& scriptSigRet, txnouttype& whichTypeRet)
std::vector<valtype>& ret, txnouttype& whichTypeRet, uint32_t consensusBranchId)
{
scriptSigRet.clear();
CScript scriptRet;
uint160 h160;
ret.clear();
vector<valtype> vSolutions;
if (!Solver(scriptPubKey, whichTypeRet, vSolutions))
@ -84,85 +86,127 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP
return false;
case TX_PUBKEY:
keyID = CPubKey(vSolutions[0]).GetID();
return Sign1(keyID, creator, scriptPubKey, scriptSigRet);
return Sign1(keyID, creator, scriptPubKey, ret, consensusBranchId);
case TX_PUBKEYHASH:
keyID = CKeyID(uint160(vSolutions[0]));
if (!Sign1(keyID, creator, scriptPubKey, scriptSigRet))
if (!Sign1(keyID, creator, scriptPubKey, ret, consensusBranchId))
return false;
else
{
CPubKey vch;
creator.KeyStore().GetPubKey(keyID, vch);
scriptSigRet << ToByteVector(vch);
ret.push_back(ToByteVector(vch));
}
return true;
case TX_SCRIPTHASH:
return creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptSigRet);
if (creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptRet)) {
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
return true;
}
return false;
case TX_MULTISIG:
scriptSigRet << OP_0; // workaround CHECKMULTISIG bug
return (SignN(vSolutions, creator, scriptPubKey, scriptSigRet));
ret.push_back(valtype()); // workaround CHECKMULTISIG bug
return (SignN(vSolutions, creator, scriptPubKey, ret, consensusBranchId));
default:
return false;
}
return false;
}
bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPubKey, CScript& scriptSig)
static CScript PushAll(const vector<valtype>& values)
{
CScript result;
BOOST_FOREACH(const valtype& v, values) {
if (v.size() == 0) {
result << OP_0;
} else if (v.size() == 1 && v[0] >= 1 && v[0] <= 16) {
result << CScript::EncodeOP_N(v[0]);
} else {
result << v;
}
}
return result;
}
bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPubKey, SignatureData& sigdata, uint32_t consensusBranchId)
{
CScript script = fromPubKey;
bool solved = true;
std::vector<valtype> result;
txnouttype whichType;
if (!SignStep(creator, fromPubKey, scriptSig, whichType))
return false;
solved = SignStep(creator, script, result, whichType, consensusBranchId);
CScript subscript;
if (whichType == TX_SCRIPTHASH)
if (solved && whichType == TX_SCRIPTHASH)
{
// Solver returns the subscript that need to be evaluated;
// Solver returns the subscript that needs to be evaluated;
// the final scriptSig is the signatures from that
// and then the serialized subscript:
CScript subscript = scriptSig;
txnouttype subType;
bool fSolved =
SignStep(creator, subscript, scriptSig, subType) && subType != TX_SCRIPTHASH;
// Append serialized subscript whether or not it is completely signed:
scriptSig << static_cast<valtype>(subscript);
if (!fSolved) return false;
script = subscript = CScript(result[0].begin(), result[0].end());
solved = solved && SignStep(creator, script, result, whichType, consensusBranchId) && whichType != TX_SCRIPTHASH;
result.push_back(std::vector<unsigned char>(subscript.begin(), subscript.end()));
}
sigdata.scriptSig = PushAll(result);
// Test solution
return VerifyScript(scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker());
return solved && VerifyScript(sigdata.scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker(), consensusBranchId);
}
SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn)
{
SignatureData data;
assert(tx.vin.size() > nIn);
data.scriptSig = tx.vin[nIn].scriptSig;
return data;
}
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const SignatureData& data)
{
assert(tx.vin.size() > nIn);
tx.vin[nIn].scriptSig = data.scriptSig;
}
bool SignSignature(
const CKeyStore &keystore,
const CScript& fromPubKey,
CMutableTransaction& txTo,
unsigned int nIn,
const CAmount& amount,
int nHashType,
uint32_t consensusBranchId)
{
assert(nIn < txTo.vin.size());
CTxIn& txin = txTo.vin[nIn];
CTransaction txToConst(txTo);
TransactionSignatureCreator creator(&keystore, &txToConst, nIn, nHashType);
TransactionSignatureCreator creator(&keystore, &txToConst, nIn, amount, nHashType);
return ProduceSignature(creator, fromPubKey, txin.scriptSig);
SignatureData sigdata;
bool ret = ProduceSignature(creator, fromPubKey, sigdata, consensusBranchId);
UpdateTransaction(txTo, nIn, sigdata);
return ret;
}
bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
bool SignSignature(
const CKeyStore &keystore,
const CTransaction& txFrom,
CMutableTransaction& txTo,
unsigned int nIn,
int nHashType,
uint32_t consensusBranchId)
{
assert(nIn < txTo.vin.size());
CTxIn& txin = txTo.vin[nIn];
assert(txin.prevout.n < txFrom.vout.size());
const CTxOut& txout = txFrom.vout[txin.prevout.n];
return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, nHashType);
return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType, consensusBranchId);
}
static CScript PushAll(const vector<valtype>& values)
{
CScript result;
BOOST_FOREACH(const valtype& v, values)
result << v;
return result;
}
static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
static vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
const vector<valtype>& vSolutions,
const vector<valtype>& sigs1, const vector<valtype>& sigs2)
const vector<valtype>& sigs1, const vector<valtype>& sigs2, uint32_t consensusBranchId)
{
// Combine all the signatures we've got:
set<valtype> allsigs;
@ -190,7 +234,7 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureC
if (sigs.count(pubkey))
continue; // Already got a sig for this pubkey
if (checker.CheckSig(sig, pubkey, scriptPubKey))
if (checker.CheckSig(sig, pubkey, scriptPubKey, consensusBranchId))
{
sigs[pubkey] = sig;
break;
@ -199,87 +243,100 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureC
}
// Now build a merged CScript:
unsigned int nSigsHave = 0;
CScript result; result << OP_0; // pop-one-too-many workaround
std::vector<valtype> result; result.push_back(valtype()); // pop-one-too-many workaround
for (unsigned int i = 0; i < nPubKeys && nSigsHave < nSigsRequired; i++)
{
if (sigs.count(vSolutions[i+1]))
{
result << sigs[vSolutions[i+1]];
result.push_back(sigs[vSolutions[i+1]]);
++nSigsHave;
}
}
// Fill any missing with OP_0:
for (unsigned int i = nSigsHave; i < nSigsRequired; i++)
result << OP_0;
result.push_back(valtype());
return result;
}
static CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
namespace
{
struct Stacks
{
std::vector<valtype> script;
Stacks() {}
explicit Stacks(const std::vector<valtype>& scriptSigStack_) : script(scriptSigStack_) {}
explicit Stacks(const SignatureData& data, uint32_t consensusBranchId) {
EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), consensusBranchId);
}
SignatureData Output() const {
SignatureData result;
result.scriptSig = PushAll(script);
return result;
}
};
}
static Stacks CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
const txnouttype txType, const vector<valtype>& vSolutions,
vector<valtype>& sigs1, vector<valtype>& sigs2)
Stacks sigs1, Stacks sigs2, uint32_t consensusBranchId)
{
switch (txType)
{
case TX_NONSTANDARD:
case TX_NULL_DATA:
// Don't know anything about this, assume bigger one is correct:
if (sigs1.size() >= sigs2.size())
return PushAll(sigs1);
return PushAll(sigs2);
if (sigs1.script.size() >= sigs2.script.size())
return sigs1;
return sigs2;
case TX_PUBKEY:
case TX_PUBKEYHASH:
// Signatures are bigger than placeholders or empty scripts:
if (sigs1.empty() || sigs1[0].empty())
return PushAll(sigs2);
return PushAll(sigs1);
if (sigs1.script.empty() || sigs1.script[0].empty())
return sigs2;
return sigs1;
case TX_SCRIPTHASH:
if (sigs1.empty() || sigs1.back().empty())
return PushAll(sigs2);
else if (sigs2.empty() || sigs2.back().empty())
return PushAll(sigs1);
if (sigs1.script.empty() || sigs1.script.back().empty())
return sigs2;
else if (sigs2.script.empty() || sigs2.script.back().empty())
return sigs1;
else
{
// Recur to combine:
valtype spk = sigs1.back();
valtype spk = sigs1.script.back();
CScript pubKey2(spk.begin(), spk.end());
txnouttype txType2;
vector<vector<unsigned char> > vSolutions2;
Solver(pubKey2, txType2, vSolutions2);
sigs1.pop_back();
sigs2.pop_back();
CScript result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2);
result << spk;
sigs1.script.pop_back();
sigs2.script.pop_back();
Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, consensusBranchId);
result.script.push_back(spk);
return result;
}
case TX_MULTISIG:
return CombineMultisig(scriptPubKey, checker, vSolutions, sigs1, sigs2);
return Stacks(CombineMultisig(scriptPubKey, checker, vSolutions, sigs1.script, sigs2.script, consensusBranchId));
default:
return Stacks();
}
return CScript();
}
CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
const CScript& scriptSig1, const CScript& scriptSig2)
{
TransactionSignatureChecker checker(&txTo, nIn);
return CombineSignatures(scriptPubKey, checker, scriptSig1, scriptSig2);
}
CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
const CScript& scriptSig1, const CScript& scriptSig2)
SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
const SignatureData& scriptSig1, const SignatureData& scriptSig2,
uint32_t consensusBranchId)
{
txnouttype txType;
vector<vector<unsigned char> > vSolutions;
Solver(scriptPubKey, txType, vSolutions);
vector<valtype> stack1;
EvalScript(stack1, scriptSig1, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker());
vector<valtype> stack2;
EvalScript(stack2, scriptSig2, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker());
return CombineSignatures(scriptPubKey, checker, txType, vSolutions, stack1, stack2);
return CombineSignatures(
scriptPubKey, checker, txType, vSolutions,
Stacks(scriptSig1, consensusBranchId),
Stacks(scriptSig2, consensusBranchId),
consensusBranchId).Output();
}
namespace {
@ -289,7 +346,11 @@ class DummySignatureChecker : public BaseSignatureChecker
public:
DummySignatureChecker() {}
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
bool CheckSig(
const std::vector<unsigned char>& scriptSig,
const std::vector<unsigned char>& vchPubKey,
const CScript& scriptCode,
uint32_t consensusBranchId) const
{
return true;
}
@ -302,7 +363,11 @@ const BaseSignatureChecker& DummySignatureCreator::Checker() const
return dummyChecker;
}
bool DummySignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode) const
bool DummySignatureCreator::CreateSig(
std::vector<unsigned char>& vchSig,
const CKeyID& keyid,
const CScript& scriptCode,
uint32_t consensusBranchId) const
{
// Create a dummy signature that is a valid DER-encoding
vchSig.assign(72, '\000');

54
src/script/sign.h

@ -27,7 +27,7 @@ public:
virtual const BaseSignatureChecker& Checker() const =0;
/** Create a singular (non-script) signature. */
virtual bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode) const =0;
virtual bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, uint32_t consensusBranchId) const =0;
};
/** A signature creator for transactions. */
@ -35,12 +35,20 @@ class TransactionSignatureCreator : public BaseSignatureCreator {
const CTransaction* txTo;
unsigned int nIn;
int nHashType;
CAmount amount;
const TransactionSignatureChecker checker;
public:
TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, int nHashTypeIn=SIGHASH_ALL);
TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn=SIGHASH_ALL);
const BaseSignatureChecker& Checker() const { return checker; }
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode) const;
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, uint32_t consensusBranchId) const;
};
class MutableTransactionSignatureCreator : public TransactionSignatureCreator {
CTransaction tx;
public:
MutableTransactionSignatureCreator(const CKeyStore* keystoreIn, const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount, int nHashTypeIn) : TransactionSignatureCreator(keystoreIn, &tx, nInIn, amount, nHashTypeIn), tx(*txToIn) {}
};
/** A signature creator that just produces 72-byte empty signatyres. */
@ -48,20 +56,46 @@ class DummySignatureCreator : public BaseSignatureCreator {
public:
DummySignatureCreator(const CKeyStore* keystoreIn) : BaseSignatureCreator(keystoreIn) {}
const BaseSignatureChecker& Checker() const;
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode) const;
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, uint32_t consensusBranchId) const;
};
struct SignatureData {
CScript scriptSig;
SignatureData() {}
explicit SignatureData(const CScript& script) : scriptSig(script) {}
};
/** Produce a script signature using a generic signature creator. */
bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& scriptPubKey, CScript& scriptSig);
bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& scriptPubKey, SignatureData& sigdata, uint32_t consensusBranchId);
/** Produce a script signature for a transaction. */
bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
bool SignSignature(
const CKeyStore &keystore,
const CScript& fromPubKey,
CMutableTransaction& txTo,
unsigned int nIn,
const CAmount& amount,
int nHashType,
uint32_t consensusBranchId);
bool SignSignature(
const CKeyStore& keystore,
const CTransaction& txFrom,
CMutableTransaction& txTo,
unsigned int nIn,
int nHashType,
uint32_t consensusBranchId);
/** Combine two script signatures using a generic signature checker, intelligently, possibly with OP_0 placeholders. */
CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, const CScript& scriptSig1, const CScript& scriptSig2);
SignatureData CombineSignatures(
const CScript& scriptPubKey,
const BaseSignatureChecker& checker,
const SignatureData& scriptSig1,
const SignatureData& scriptSig2,
uint32_t consensusBranchId);
/** Combine two script signatures on transactions. */
CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CScript& scriptSig1, const CScript& scriptSig2);
/** Extract signature data from a transaction, and insert it. */
SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn);
void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const SignatureData& data);
#endif // BITCOIN_SCRIPT_SIGN_H

13
src/script/zcashconsensus.cpp

@ -5,6 +5,7 @@
#include "zcashconsensus.h"
#include "consensus/upgrades.h"
#include "primitives/transaction.h"
#include "pubkey.h"
#include "script/interpreter.h"
@ -84,8 +85,16 @@ int zcashconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int
// Regardless of the verification result, the tx did not error.
set_error(err, zcashconsensus_ERR_OK);
return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), flags, TransactionSignatureChecker(&tx, nIn), NULL);
PrecomputedTransactionData txdata(tx);
CAmount am(0);
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
return VerifyScript(
tx.vin[nIn].scriptSig,
CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen),
flags,
TransactionSignatureChecker(&tx, nIn, am, txdata),
consensusBranchId,
NULL);
} catch (const std::exception&) {
return set_error(err, zcashconsensus_ERR_TX_DESERIALIZE); // Error deserializing
}

2
src/script/zcashconsensus.h

@ -6,6 +6,8 @@
#ifndef BITCOIN_ZCASHCONSENSUS_H
#define BITCOIN_ZCASHCONSENSUS_H
#include <stdint.h>
#if defined(BUILD_BITCOIN_INTERNAL) && defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#if defined(_WIN32)

134
src/snark/Makefile

@ -17,7 +17,7 @@ CXXFLAGS += -std=c++11 -Wall -Wextra -Wno-unused-parameter -Wno-comment -Wfatal-
DEPSRC = depsrc
DEPINST = depinst
CXXFLAGS += -I$(DEPINST)/include -Isrc
CXXFLAGS += -I$(DEPINST)/include -Ilibsnark
LDFLAGS += -L$(DEPINST)/lib -Wl,-rpath,$(DEPINST)/lib
LDLIBS += -lgmpxx -lgmp -lboost_program_options-mt -lsodium
# List of .a files to include within libsnark.a and libsnark.so:
@ -44,23 +44,23 @@ ifneq ($(NO_SUPERCOP),1)
endif
LIB_SRCS = \
src/algebra/curves/alt_bn128/alt_bn128_g1.cpp \
src/algebra/curves/alt_bn128/alt_bn128_g2.cpp \
src/algebra/curves/alt_bn128/alt_bn128_init.cpp \
src/algebra/curves/alt_bn128/alt_bn128_pairing.cpp \
src/algebra/curves/alt_bn128/alt_bn128_pp.cpp \
src/common/profiling.cpp \
src/common/utils.cpp \
src/gadgetlib1/constraint_profiling.cpp \
libsnark/algebra/curves/alt_bn128/alt_bn128_g1.cpp \
libsnark/algebra/curves/alt_bn128/alt_bn128_g2.cpp \
libsnark/algebra/curves/alt_bn128/alt_bn128_init.cpp \
libsnark/algebra/curves/alt_bn128/alt_bn128_pairing.cpp \
libsnark/algebra/curves/alt_bn128/alt_bn128_pp.cpp \
libsnark/common/profiling.cpp \
libsnark/common/utils.cpp \
libsnark/gadgetlib1/constraint_profiling.cpp \
ifeq ($(CURVE),BN128)
LIB_SRCS += \
src/algebra/curves/bn128/bn128_g1.cpp \
src/algebra/curves/bn128/bn128_g2.cpp \
src/algebra/curves/bn128/bn128_gt.cpp \
src/algebra/curves/bn128/bn128_init.cpp \
src/algebra/curves/bn128/bn128_pairing.cpp \
src/algebra/curves/bn128/bn128_pp.cpp
libsnark/algebra/curves/bn128/bn128_g1.cpp \
libsnark/algebra/curves/bn128/bn128_g2.cpp \
libsnark/algebra/curves/bn128/bn128_gt.cpp \
libsnark/algebra/curves/bn128/bn128_init.cpp \
libsnark/algebra/curves/bn128/bn128_pairing.cpp \
libsnark/algebra/curves/bn128/bn128_pp.cpp
CXXFLAGS += -DBN_SUPPORT_SNARK
AR_LIBS += $(DEPINST)/lib/libzm.a
@ -68,56 +68,56 @@ endif
# FIXME: most of these are broken due to removed code.
DISABLED_EXECUTABLES = \
src/common/routing_algorithms/profiling/profile_routing_algorithms \
src/common/routing_algorithms/tests/test_routing_algorithms \
src/gadgetlib1/gadgets/cpu_checkers/fooram/examples/test_fooram \
src/gadgetlib1/gadgets/hashes/knapsack/tests/test_knapsack_gadget \
src/gadgetlib1/gadgets/routing/profiling/profile_routing_gadgets \
src/gadgetlib1/gadgets/set_commitment/tests/test_set_commitment_gadget \
src/gadgetlib1/gadgets/verifiers/tests/test_r1cs_ppzksnark_verifier_gadget \
src/reductions/ram_to_r1cs/examples/demo_arithmetization \
src/relations/arithmetic_programs/ssp/tests/test_ssp \
src/zk_proof_systems/pcd/r1cs_pcd/r1cs_mp_ppzkpcd/profiling/profile_r1cs_mp_ppzkpcd \
src/zk_proof_systems/pcd/r1cs_pcd/r1cs_mp_ppzkpcd/tests/test_r1cs_mp_ppzkpcd \
src/zk_proof_systems/pcd/r1cs_pcd/r1cs_sp_ppzkpcd/profiling/profile_r1cs_sp_ppzkpcd \
src/zk_proof_systems/pcd/r1cs_pcd/r1cs_sp_ppzkpcd/tests/test_r1cs_sp_ppzkpcd \
src/zk_proof_systems/ppzksnark/bacs_ppzksnark/profiling/profile_bacs_ppzksnark \
src/zk_proof_systems/ppzksnark/bacs_ppzksnark/tests/test_bacs_ppzksnark \
src/zk_proof_systems/ppzksnark/r1cs_gg_ppzksnark/profiling/profile_r1cs_gg_ppzksnark \
src/zk_proof_systems/ppzksnark/r1cs_gg_ppzksnark/tests/test_r1cs_gg_ppzksnark \
src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/profiling/profile_r1cs_ppzksnark \
src/zk_proof_systems/ppzksnark/ram_ppzksnark/examples/demo_ram_ppzksnark \
src/zk_proof_systems/ppzksnark/ram_ppzksnark/examples/demo_ram_ppzksnark_generator \
src/zk_proof_systems/ppzksnark/ram_ppzksnark/examples/demo_ram_ppzksnark_prover \
src/zk_proof_systems/ppzksnark/ram_ppzksnark/examples/demo_ram_ppzksnark_verifier \
src/zk_proof_systems/ppzksnark/ram_ppzksnark/profiling/profile_ram_ppzksnark \
src/zk_proof_systems/ppzksnark/ram_ppzksnark/tests/test_ram_ppzksnark \
src/zk_proof_systems/ppzksnark/tbcs_ppzksnark/profiling/profile_tbcs_ppzksnark \
src/zk_proof_systems/ppzksnark/tbcs_ppzksnark/tests/test_tbcs_ppzksnark \
src/zk_proof_systems/ppzksnark/uscs_ppzksnark/profiling/profile_uscs_ppzksnark \
src/zk_proof_systems/ppzksnark/uscs_ppzksnark/tests/test_uscs_ppzksnark \
src/zk_proof_systems/zksnark/ram_zksnark/profiling/profile_ram_zksnark \
src/zk_proof_systems/zksnark/ram_zksnark/tests/test_ram_zksnark
libsnark/common/routing_algorithms/profiling/profile_routing_algorithms \
libsnark/common/routing_algorithms/tests/test_routing_algorithms \
libsnark/gadgetlib1/gadgets/cpu_checkers/fooram/examples/test_fooram \
libsnark/gadgetlib1/gadgets/hashes/knapsack/tests/test_knapsack_gadget \
libsnark/gadgetlib1/gadgets/routing/profiling/profile_routing_gadgets \
libsnark/gadgetlib1/gadgets/set_commitment/tests/test_set_commitment_gadget \
libsnark/gadgetlib1/gadgets/verifiers/tests/test_r1cs_ppzksnark_verifier_gadget \
libsnark/reductions/ram_to_r1cs/examples/demo_arithmetization \
libsnark/relations/arithmetic_programs/ssp/tests/test_ssp \
libsnark/zk_proof_systems/pcd/r1cs_pcd/r1cs_mp_ppzkpcd/profiling/profile_r1cs_mp_ppzkpcd \
libsnark/zk_proof_systems/pcd/r1cs_pcd/r1cs_mp_ppzkpcd/tests/test_r1cs_mp_ppzkpcd \
libsnark/zk_proof_systems/pcd/r1cs_pcd/r1cs_sp_ppzkpcd/profiling/profile_r1cs_sp_ppzkpcd \
libsnark/zk_proof_systems/pcd/r1cs_pcd/r1cs_sp_ppzkpcd/tests/test_r1cs_sp_ppzkpcd \
libsnark/zk_proof_systems/ppzksnark/bacs_ppzksnark/profiling/profile_bacs_ppzksnark \
libsnark/zk_proof_systems/ppzksnark/bacs_ppzksnark/tests/test_bacs_ppzksnark \
libsnark/zk_proof_systems/ppzksnark/r1cs_gg_ppzksnark/profiling/profile_r1cs_gg_ppzksnark \
libsnark/zk_proof_systems/ppzksnark/r1cs_gg_ppzksnark/tests/test_r1cs_gg_ppzksnark \
libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/profiling/profile_r1cs_ppzksnark \
libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/examples/demo_ram_ppzksnark \
libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/examples/demo_ram_ppzksnark_generator \
libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/examples/demo_ram_ppzksnark_prover \
libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/examples/demo_ram_ppzksnark_verifier \
libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/profiling/profile_ram_ppzksnark \
libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/tests/test_ram_ppzksnark \
libsnark/zk_proof_systems/ppzksnark/tbcs_ppzksnark/profiling/profile_tbcs_ppzksnark \
libsnark/zk_proof_systems/ppzksnark/tbcs_ppzksnark/tests/test_tbcs_ppzksnark \
libsnark/zk_proof_systems/ppzksnark/uscs_ppzksnark/profiling/profile_uscs_ppzksnark \
libsnark/zk_proof_systems/ppzksnark/uscs_ppzksnark/tests/test_uscs_ppzksnark \
libsnark/zk_proof_systems/zksnark/ram_zksnark/profiling/profile_ram_zksnark \
libsnark/zk_proof_systems/zksnark/ram_zksnark/tests/test_ram_zksnark
EXECUTABLES =
EXECUTABLES_WITH_GTEST =
EXECUTABLES_WITH_SUPERCOP = \
src/zk_proof_systems/ppzkadsnark/r1cs_ppzkadsnark/examples/demo_r1cs_ppzkadsnark
libsnark/zk_proof_systems/ppzkadsnark/r1cs_ppzkadsnark/examples/demo_r1cs_ppzkadsnark
GTEST_TESTS = src/gtests
GTEST_TESTS = libsnark/gtests
GTEST_SRCS = \
src/algebra/curves/tests/test_bilinearity.cpp \
src/algebra/curves/tests/test_groups.cpp \
src/algebra/fields/tests/test_bigint.cpp \
src/algebra/fields/tests/test_fields.cpp \
src/gadgetlib1/gadgets/hashes/sha256/tests/test_sha256_gadget.cpp \
src/gadgetlib1/gadgets/merkle_tree/tests/test_merkle_tree_gadgets.cpp \
src/relations/arithmetic_programs/qap/tests/test_qap.cpp \
src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp \
src/gtests.cpp
libsnark/algebra/curves/tests/test_bilinearity.cpp \
libsnark/algebra/curves/tests/test_groups.cpp \
libsnark/algebra/fields/tests/test_bigint.cpp \
libsnark/algebra/fields/tests/test_fields.cpp \
libsnark/gadgetlib1/gadgets/hashes/sha256/tests/test_sha256_gadget.cpp \
libsnark/gadgetlib1/gadgets/merkle_tree/tests/test_merkle_tree_gadgets.cpp \
libsnark/relations/arithmetic_programs/qap/tests/test_qap.cpp \
libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp \
libsnark/gtests.cpp
DOCS = README.html
@ -192,7 +192,7 @@ $(LIB_OBJS) $(if $(NO_GTEST),,$(GTEST_OBJS)) $(EXEC_OBJS): %.o: %.cpp
LIBGTEST_A = $(DEPINST)/lib/libgtest.a
$(LIBGTEST_A): $(GTESTDIR)/src/gtest-all.cc $(DEPINST_EXISTS)
$(LIBGTEST_A): $(GTESTDIR)/libsnark/gtest-all.cc $(DEPINST_EXISTS)
$(CXX) -o $(DEPINST)/lib/gtest-all.o -I $(GTESTDIR) -c -isystem $(GTESTDIR)/include $< $(CXXFLAGS)
$(AR) -rv $(LIBGTEST_A) $(DEPINST)/lib/gtest-all.o
@ -205,13 +205,13 @@ $(LIBSNARK_A): $(LIB_OBJS) $(AR_LIBS)
libsnark.so: $(LIBSNARK_A) $(DEPINST_EXISTS)
$(CXX) -o $@ --shared -Wl,--whole-archive $(LIBSNARK_A) $(CXXFLAGS) $(LDFLAGS) -Wl,--no-whole-archive $(LDLIBS)
src/gadgetlib2/tests/gadgetlib2_test: \
src/gadgetlib2/tests/adapters_UTEST.cpp \
src/gadgetlib2/tests/constraint_UTEST.cpp \
src/gadgetlib2/tests/gadget_UTEST.cpp \
src/gadgetlib2/tests/integration_UTEST.cpp \
src/gadgetlib2/tests/protoboard_UTEST.cpp \
src/gadgetlib2/tests/variable_UTEST.cpp
libsnark/gadgetlib2/tests/gadgetlib2_test: \
libsnark/gadgetlib2/tests/adapters_UTEST.cpp \
libsnark/gadgetlib2/tests/constraint_UTEST.cpp \
libsnark/gadgetlib2/tests/gadget_UTEST.cpp \
libsnark/gadgetlib2/tests/integration_UTEST.cpp \
libsnark/gadgetlib2/tests/protoboard_UTEST.cpp \
libsnark/gadgetlib2/tests/variable_UTEST.cpp
$(EXECUTABLES): %: %.o $(LIBSNARK_A) $(DEPINST_EXISTS)
$(CXX) -o $@ $@.o $(LIBSNARK_A) $(CXXFLAGS) $(LDFLAGS) $(LDLIBS)
@ -243,10 +243,10 @@ ifeq ($(PREFIX),)
install:
$(error Please provide PREFIX. E.g. make install PREFIX=/usr)
else
HEADERS_SRC=$(shell find src -name '*.hpp' -o -name '*.tcc')
HEADERS_DEST=$(patsubst src/%,$(PREFIX)/include/libsnark/%,$(HEADERS_SRC))
HEADERS_SRC=$(shell find libsnark -name '*.hpp' -o -name '*.tcc')
HEADERS_DEST=$(patsubst libsnark/%,$(PREFIX)/include/libsnark/%,$(HEADERS_SRC))
$(HEADERS_DEST): $(PREFIX)/include/libsnark/%: src/%
$(HEADERS_DEST): $(PREFIX)/include/libsnark/%: libsnark/%
mkdir -p $(shell dirname $@)
cp $< $@

0
src/snark/src/algebra/curves/alt_bn128/alt_bn128_g1.cpp → src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.cpp

0
src/snark/src/algebra/curves/alt_bn128/alt_bn128_g1.hpp → src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.hpp

0
src/snark/src/algebra/curves/alt_bn128/alt_bn128_g2.cpp → src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.cpp

0
src/snark/src/algebra/curves/alt_bn128/alt_bn128_g2.hpp → src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.hpp

0
src/snark/src/algebra/curves/alt_bn128/alt_bn128_init.cpp → src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_init.cpp

0
src/snark/src/algebra/curves/alt_bn128/alt_bn128_init.hpp → src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_init.hpp

0
src/snark/src/algebra/curves/alt_bn128/alt_bn128_pairing.cpp → src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pairing.cpp

0
src/snark/src/algebra/curves/alt_bn128/alt_bn128_pairing.hpp → src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pairing.hpp

0
src/snark/src/algebra/curves/alt_bn128/alt_bn128_pp.cpp → src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pp.cpp

0
src/snark/src/algebra/curves/alt_bn128/alt_bn128_pp.hpp → src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pp.hpp

0
src/snark/src/algebra/curves/curve_utils.hpp → src/snark/libsnark/algebra/curves/curve_utils.hpp

0
src/snark/src/algebra/curves/curve_utils.tcc → src/snark/libsnark/algebra/curves/curve_utils.tcc

0
src/snark/src/algebra/curves/public_params.hpp → src/snark/libsnark/algebra/curves/public_params.hpp

0
src/snark/src/algebra/curves/tests/test_bilinearity.cpp → src/snark/libsnark/algebra/curves/tests/test_bilinearity.cpp

0
src/snark/src/algebra/curves/tests/test_groups.cpp → src/snark/libsnark/algebra/curves/tests/test_groups.cpp

0
src/snark/src/algebra/evaluation_domain/domains/basic_radix2_domain.hpp → src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain.hpp

0
src/snark/src/algebra/evaluation_domain/domains/basic_radix2_domain.tcc → src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain.tcc

0
src/snark/src/algebra/evaluation_domain/domains/basic_radix2_domain_aux.hpp → src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain_aux.hpp

0
src/snark/src/algebra/evaluation_domain/domains/basic_radix2_domain_aux.tcc → src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain_aux.tcc

0
src/snark/src/algebra/evaluation_domain/evaluation_domain.hpp → src/snark/libsnark/algebra/evaluation_domain/evaluation_domain.hpp

0
src/snark/src/algebra/evaluation_domain/evaluation_domain.tcc → src/snark/libsnark/algebra/evaluation_domain/evaluation_domain.tcc

0
src/snark/src/algebra/exponentiation/exponentiation.hpp → src/snark/libsnark/algebra/exponentiation/exponentiation.hpp

0
src/snark/src/algebra/exponentiation/exponentiation.tcc → src/snark/libsnark/algebra/exponentiation/exponentiation.tcc

0
src/snark/src/algebra/fields/bigint.hpp → src/snark/libsnark/algebra/fields/bigint.hpp

5
src/snark/src/algebra/fields/bigint.tcc → src/snark/libsnark/algebra/fields/bigint.tcc

@ -104,7 +104,7 @@ bool bigint<n>::is_zero() const
template<mp_size_t n>
size_t bigint<n>::num_bits() const
{
/*
for (long long i = max_bits(); i >= 0; --i)
{
if (this->test_bit(i))
@ -114,7 +114,7 @@ size_t bigint<n>::num_bits() const
}
return 0;
/*
*/
for (long long i = n-1; i >= 0; --i)
{
mp_limb_t x = this->data[i];
@ -128,7 +128,6 @@ size_t bigint<n>::num_bits() const
}
}
return 0;
*/
}
template<mp_size_t n>

0
src/snark/src/algebra/fields/field_utils.hpp → src/snark/libsnark/algebra/fields/field_utils.hpp

0
src/snark/src/algebra/fields/field_utils.tcc → src/snark/libsnark/algebra/fields/field_utils.tcc

0
src/snark/src/algebra/fields/fp.hpp → src/snark/libsnark/algebra/fields/fp.hpp

0
src/snark/src/algebra/fields/fp.tcc → src/snark/libsnark/algebra/fields/fp.tcc

0
src/snark/src/algebra/fields/fp12_2over3over2.hpp → src/snark/libsnark/algebra/fields/fp12_2over3over2.hpp

0
src/snark/src/algebra/fields/fp12_2over3over2.tcc → src/snark/libsnark/algebra/fields/fp12_2over3over2.tcc

0
src/snark/src/algebra/fields/fp2.hpp → src/snark/libsnark/algebra/fields/fp2.hpp

0
src/snark/src/algebra/fields/fp2.tcc → src/snark/libsnark/algebra/fields/fp2.tcc

0
src/snark/src/algebra/fields/fp6_3over2.hpp → src/snark/libsnark/algebra/fields/fp6_3over2.hpp

0
src/snark/src/algebra/fields/fp6_3over2.tcc → src/snark/libsnark/algebra/fields/fp6_3over2.tcc

0
src/snark/src/algebra/fields/fp_aux.tcc → src/snark/libsnark/algebra/fields/fp_aux.tcc

0
src/snark/src/algebra/fields/tests/test_bigint.cpp → src/snark/libsnark/algebra/fields/tests/test_bigint.cpp

0
src/snark/src/algebra/fields/tests/test_fields.cpp → src/snark/libsnark/algebra/fields/tests/test_fields.cpp

0
src/snark/src/algebra/knowledge_commitment/knowledge_commitment.hpp → src/snark/libsnark/algebra/knowledge_commitment/knowledge_commitment.hpp

0
src/snark/src/algebra/knowledge_commitment/knowledge_commitment.tcc → src/snark/libsnark/algebra/knowledge_commitment/knowledge_commitment.tcc

0
src/snark/src/algebra/scalar_multiplication/kc_multiexp.hpp → src/snark/libsnark/algebra/scalar_multiplication/kc_multiexp.hpp

0
src/snark/src/algebra/scalar_multiplication/kc_multiexp.tcc → src/snark/libsnark/algebra/scalar_multiplication/kc_multiexp.tcc

0
src/snark/src/algebra/scalar_multiplication/multiexp.hpp → src/snark/libsnark/algebra/scalar_multiplication/multiexp.hpp

0
src/snark/src/algebra/scalar_multiplication/multiexp.tcc → src/snark/libsnark/algebra/scalar_multiplication/multiexp.tcc

0
src/snark/src/algebra/scalar_multiplication/wnaf.hpp → src/snark/libsnark/algebra/scalar_multiplication/wnaf.hpp

0
src/snark/src/algebra/scalar_multiplication/wnaf.tcc → src/snark/libsnark/algebra/scalar_multiplication/wnaf.tcc

0
src/snark/src/common/assert_except.hpp → src/snark/libsnark/common/assert_except.hpp

0
src/snark/src/common/data_structures/accumulation_vector.hpp → src/snark/libsnark/common/data_structures/accumulation_vector.hpp

0
src/snark/src/common/data_structures/accumulation_vector.tcc → src/snark/libsnark/common/data_structures/accumulation_vector.tcc

0
src/snark/src/common/data_structures/merkle_tree.hpp → src/snark/libsnark/common/data_structures/merkle_tree.hpp

0
src/snark/src/common/data_structures/merkle_tree.tcc → src/snark/libsnark/common/data_structures/merkle_tree.tcc

0
src/snark/src/common/data_structures/sparse_vector.hpp → src/snark/libsnark/common/data_structures/sparse_vector.hpp

0
src/snark/src/common/data_structures/sparse_vector.tcc → src/snark/libsnark/common/data_structures/sparse_vector.tcc

0
src/snark/src/common/default_types/ec_pp.hpp → src/snark/libsnark/common/default_types/ec_pp.hpp

0
src/snark/src/common/default_types/r1cs_ppzksnark_pp.hpp → src/snark/libsnark/common/default_types/r1cs_ppzksnark_pp.hpp

0
src/snark/src/common/profiling.cpp → src/snark/libsnark/common/profiling.cpp

0
src/snark/src/common/profiling.hpp → src/snark/libsnark/common/profiling.hpp

0
src/snark/src/common/serialization.hpp → src/snark/libsnark/common/serialization.hpp

0
src/snark/src/common/serialization.tcc → src/snark/libsnark/common/serialization.tcc

0
src/snark/src/common/template_utils.hpp → src/snark/libsnark/common/template_utils.hpp

0
src/snark/src/common/utils.cpp → src/snark/libsnark/common/utils.cpp

0
src/snark/src/common/utils.hpp → src/snark/libsnark/common/utils.hpp

0
src/snark/src/common/utils.tcc → src/snark/libsnark/common/utils.tcc

0
src/snark/src/gadgetlib1/constraint_profiling.cpp → src/snark/libsnark/gadgetlib1/constraint_profiling.cpp

0
src/snark/src/gadgetlib1/constraint_profiling.hpp → src/snark/libsnark/gadgetlib1/constraint_profiling.hpp

0
src/snark/src/gadgetlib1/examples/simple_example.hpp → src/snark/libsnark/gadgetlib1/examples/simple_example.hpp

0
src/snark/src/gadgetlib1/examples/simple_example.tcc → src/snark/libsnark/gadgetlib1/examples/simple_example.tcc

0
src/snark/src/gadgetlib1/gadget.hpp → src/snark/libsnark/gadgetlib1/gadget.hpp

0
src/snark/src/gadgetlib1/gadget.tcc → src/snark/libsnark/gadgetlib1/gadget.tcc

0
src/snark/src/gadgetlib1/gadgets/basic_gadgets.hpp → src/snark/libsnark/gadgetlib1/gadgets/basic_gadgets.hpp

0
src/snark/src/gadgetlib1/gadgets/basic_gadgets.tcc → src/snark/libsnark/gadgetlib1/gadgets/basic_gadgets.tcc

0
src/snark/src/gadgetlib1/gadgets/gadget_from_r1cs.hpp → src/snark/libsnark/gadgetlib1/gadgets/gadget_from_r1cs.hpp

0
src/snark/src/gadgetlib1/gadgets/gadget_from_r1cs.tcc → src/snark/libsnark/gadgetlib1/gadgets/gadget_from_r1cs.tcc

0
src/snark/src/gadgetlib1/gadgets/hashes/digest_selector_gadget.hpp → src/snark/libsnark/gadgetlib1/gadgets/hashes/digest_selector_gadget.hpp

0
src/snark/src/gadgetlib1/gadgets/hashes/digest_selector_gadget.tcc → src/snark/libsnark/gadgetlib1/gadgets/hashes/digest_selector_gadget.tcc

0
src/snark/src/gadgetlib1/gadgets/hashes/hash_io.hpp → src/snark/libsnark/gadgetlib1/gadgets/hashes/hash_io.hpp

0
src/snark/src/gadgetlib1/gadgets/hashes/hash_io.tcc → src/snark/libsnark/gadgetlib1/gadgets/hashes/hash_io.tcc

0
src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_aux.hpp → src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_aux.hpp

0
src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_aux.tcc → src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_aux.tcc

0
src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_components.hpp → src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_components.hpp

0
src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_components.tcc → src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_components.tcc

0
src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp → src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp

0
src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.tcc → src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.tcc

0
src/snark/src/gadgetlib1/gadgets/hashes/sha256/tests/generate_sha256_gadget_tests.py → src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/generate_sha256_gadget_tests.py

0
src/snark/src/gadgetlib1/gadgets/hashes/sha256/tests/pypy_sha256.py → src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/pypy_sha256.py

0
src/snark/src/gadgetlib1/gadgets/hashes/sha256/tests/test_sha256_gadget.cpp → src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/test_sha256_gadget.cpp

0
src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.hpp → src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.hpp

0
src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.tcc → src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.tcc

0
src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp → src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp

0
src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.tcc → src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.tcc

0
src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.hpp → src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.hpp

0
src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.tcc → src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.tcc

0
src/snark/src/gadgetlib1/gadgets/merkle_tree/tests/test_merkle_tree_gadgets.cpp → src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/tests/test_merkle_tree_gadgets.cpp

0
src/snark/src/gadgetlib1/pb_variable.hpp → src/snark/libsnark/gadgetlib1/pb_variable.hpp

0
src/snark/src/gadgetlib1/pb_variable.tcc → src/snark/libsnark/gadgetlib1/pb_variable.tcc

0
src/snark/src/gadgetlib1/protoboard.hpp → src/snark/libsnark/gadgetlib1/protoboard.hpp

0
src/snark/src/gadgetlib1/protoboard.tcc → src/snark/libsnark/gadgetlib1/protoboard.tcc

0
src/snark/src/gtests.cpp → src/snark/libsnark/gtests.cpp

0
src/snark/src/reductions/r1cs_to_qap/r1cs_to_qap.hpp → src/snark/libsnark/reductions/r1cs_to_qap/r1cs_to_qap.hpp

0
src/snark/src/reductions/r1cs_to_qap/r1cs_to_qap.tcc → src/snark/libsnark/reductions/r1cs_to_qap/r1cs_to_qap.tcc

0
src/snark/src/relations/arithmetic_programs/qap/qap.hpp → src/snark/libsnark/relations/arithmetic_programs/qap/qap.hpp

0
src/snark/src/relations/arithmetic_programs/qap/qap.tcc → src/snark/libsnark/relations/arithmetic_programs/qap/qap.tcc

0
src/snark/src/relations/arithmetic_programs/qap/tests/test_qap.cpp → src/snark/libsnark/relations/arithmetic_programs/qap/tests/test_qap.cpp

0
src/snark/src/relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.hpp → src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.hpp

0
src/snark/src/relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.tcc → src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.tcc

0
src/snark/src/relations/constraint_satisfaction_problems/r1cs/r1cs.hpp → src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/r1cs.hpp

0
src/snark/src/relations/constraint_satisfaction_problems/r1cs/r1cs.tcc → src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/r1cs.tcc

0
src/snark/src/relations/variable.hpp → src/snark/libsnark/relations/variable.hpp

0
src/snark/src/relations/variable.tcc → src/snark/libsnark/relations/variable.tcc

0
src/snark/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.hpp → src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.hpp

0
src/snark/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.tcc → src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.tcc

0
src/snark/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/profiling/profile_r1cs_ppzksnark.cpp → src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/profiling/profile_r1cs_ppzksnark.cpp

0
src/snark/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp → src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp

0
src/snark/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.tcc → src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.tcc

0
src/snark/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark_params.hpp → src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark_params.hpp

0
src/snark/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp → src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp

6
src/txdb.cpp

@ -517,9 +517,15 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
pindexNew->nNonce = diskindex.nNonce;
pindexNew->nSolution = diskindex.nSolution;
pindexNew->nStatus = diskindex.nStatus;
pindexNew->nCachedBranchId = diskindex.nCachedBranchId;
pindexNew->nTx = diskindex.nTx;
pindexNew->nSproutValue = diskindex.nSproutValue;
// Consistency checks
auto header = pindexNew->GetBlockHeader();
if (header.GetHash() != pindexNew->GetBlockHash())
return error("LoadBlockIndex(): block header inconsistency detected: on-disk = %s, in-memory = %s",
diskindex.ToString(), pindexNew->ToString());
if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, Params().GetConsensus()))
return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString());

4
src/txdb.h

@ -32,8 +32,8 @@ struct CSpentIndexValue;
class uint256;
//! -dbcache default (MiB)
static const int64_t nDefaultDbCache = 100;
//! max. -dbcache in (MiB)
static const int64_t nDefaultDbCache = 450;
//! max. -dbcache (MiB)
static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 16384 : 1024;
//! min. -dbcache in (MiB)
static const int64_t nMinDbCache = 4;

151
src/txmempool.cpp

@ -11,6 +11,7 @@
#include "main.h"
#include "policy/fees.h"
#include "streams.h"
#include "timedata.h"
#include "util.h"
#include "utilmoneystr.h"
#include "version.h"
@ -18,20 +19,24 @@
using namespace std;
CTxMemPoolEntry::CTxMemPoolEntry():
nFee(0), nTxSize(0), nModSize(0), nUsageSize(0), nTime(0), dPriority(0.0), hadNoDependencies(false)
nFee(0), nTxSize(0), nModSize(0), nUsageSize(0), nTime(0), dPriority(0.0),
hadNoDependencies(false), spendsCoinbase(false)
{
nHeight = MEMPOOL_HEIGHT;
}
CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
int64_t _nTime, double _dPriority,
unsigned int _nHeight, bool poolHasNoInputsOf):
unsigned int _nHeight, bool poolHasNoInputsOf,
bool _spendsCoinbase, uint32_t _nBranchId):
tx(_tx), nFee(_nFee), nTime(_nTime), dPriority(_dPriority), nHeight(_nHeight),
hadNoDependencies(poolHasNoInputsOf)
hadNoDependencies(poolHasNoInputsOf),
spendsCoinbase(_spendsCoinbase), nBranchId(_nBranchId)
{
nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
nModSize = tx.CalculateModifiedSize(nTxSize);
nUsageSize = RecursiveDynamicUsage(tx);
feeRate = CFeeRate(nFee, nTxSize);
}
CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other)
@ -54,7 +59,7 @@ CTxMemPool::CTxMemPool(const CFeeRate& _minRelayFee) :
// Sanity checks off by default for performance, because otherwise
// accepting transactions becomes O(N^2) where N is the number
// of transactions in the pool
fSanityCheck = false;
nCheckFrequency = 0;
minerPolicyEstimator = new CBlockPolicyEstimator(_minRelayFee);
}
@ -96,8 +101,8 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
// Used by main.cpp AcceptToMemoryPool(), which DOES do
// all the appropriate checks.
LOCK(cs);
mapTx[hash] = entry;
const CTransaction& tx = mapTx[hash].GetTx();
mapTx.insert(entry);
const CTransaction& tx = mapTx.find(hash)->GetTx();
for (unsigned int i = 0; i < tx.vin.size(); i++)
mapNextTx[tx.vin[i].prevout] = CInPoint(&tx, i);
BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
@ -277,7 +282,7 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list<CTransaction>& rem
txToRemove.pop_front();
if (!mapTx.count(hash))
continue;
const CTransaction& tx = mapTx[hash].GetTx();
const CTransaction& tx = mapTx.find(hash)->GetTx();
if (fRecursive) {
for (unsigned int i = 0; i < tx.vout.size(); i++) {
std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(COutPoint(hash, i));
@ -295,8 +300,8 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list<CTransaction>& rem
}
removed.push_back(tx);
totalTxSize -= mapTx[hash].GetTxSize();
cachedInnerUsage -= mapTx[hash].DynamicMemoryUsage();
totalTxSize -= mapTx.find(hash)->GetTxSize();
cachedInnerUsage -= mapTx.find(hash)->DynamicMemoryUsage();
mapTx.erase(hash);
nTransactionsUpdated++;
minerPolicyEstimator->removeTx(hash);
@ -306,22 +311,26 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list<CTransaction>& rem
}
}
void CTxMemPool::removeCoinbaseSpends(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight)
void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags)
{
// Remove transactions spending a coinbase which are now immature
// Remove transactions spending a coinbase which are now immature and no-longer-final transactions
LOCK(cs);
list<CTransaction> transactionsToRemove;
for (std::map<uint256, CTxMemPoolEntry>::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
const CTransaction& tx = it->second.GetTx();
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
std::map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(txin.prevout.hash);
if (it2 != mapTx.end())
continue;
const CCoins *coins = pcoins->AccessCoins(txin.prevout.hash);
if (fSanityCheck) assert(coins);
if (!coins || (coins->IsCoinBase() && ((signed long)nMemPoolHeight) - coins->nHeight < COINBASE_MATURITY)) {
transactionsToRemove.push_back(tx);
break;
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
const CTransaction& tx = it->GetTx();
if (!CheckFinalTx(tx, flags)) {
transactionsToRemove.push_back(tx);
} else if (it->GetSpendsCoinbase()) {
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash);
if (it2 != mapTx.end())
continue;
const CCoins *coins = pcoins->AccessCoins(txin.prevout.hash);
if (nCheckFrequency != 0) assert(coins);
if (!coins || (coins->IsCoinBase() && ((signed long)nMemPoolHeight) - coins->nHeight < COINBASE_MATURITY)) {
transactionsToRemove.push_back(tx);
break;
}
}
}
}
@ -341,8 +350,8 @@ void CTxMemPool::removeWithAnchor(const uint256 &invalidRoot)
LOCK(cs);
list<CTransaction> transactionsToRemove;
for (std::map<uint256, CTxMemPoolEntry>::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
const CTransaction& tx = it->second.GetTx();
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
const CTransaction& tx = it->GetTx();
BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit) {
if (joinsplit.anchor == invalidRoot) {
transactionsToRemove.push_back(tx);
@ -387,6 +396,24 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>
}
}
void CTxMemPool::removeExpired(unsigned int nBlockHeight)
{
// Remove expired txs from the mempool
LOCK(cs);
list<CTransaction> transactionsToRemove;
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++)
{
const CTransaction& tx = it->GetTx();
if (IsExpiredTx(tx, nBlockHeight)) {
transactionsToRemove.push_back(tx);
}
}
for (const CTransaction& tx : transactionsToRemove) {
list<CTransaction> removed;
remove(tx, removed, true);
}
}
/**
* Called when a block is connected. Removes from mempool and updates the miner fee estimator.
*/
@ -398,8 +425,10 @@ void CTxMemPool::removeForBlock(const std::vector<CTransaction>& vtx, unsigned i
BOOST_FOREACH(const CTransaction& tx, vtx)
{
uint256 hash = tx.GetHash();
if (mapTx.count(hash))
entries.push_back(mapTx[hash]);
indexed_transaction_set::iterator i = mapTx.find(hash);
if (i != mapTx.end())
entries.push_back(*i);
}
BOOST_FOREACH(const CTransaction& tx, vtx)
{
@ -412,6 +441,28 @@ void CTxMemPool::removeForBlock(const std::vector<CTransaction>& vtx, unsigned i
minerPolicyEstimator->processBlock(nBlockHeight, entries, fCurrentEstimate);
}
/**
* Called whenever the tip changes. Removes transactions which don't commit to
* the given branch ID from the mempool.
*/
void CTxMemPool::removeWithoutBranchId(uint32_t nMemPoolBranchId)
{
LOCK(cs);
std::list<CTransaction> transactionsToRemove;
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
const CTransaction& tx = it->GetTx();
if (it->GetValidatedBranchId() != nMemPoolBranchId) {
transactionsToRemove.push_back(tx);
}
}
for (const CTransaction& tx : transactionsToRemove) {
std::list<CTransaction> removed;
remove(tx, removed, true);
}
}
void CTxMemPool::clear()
{
LOCK(cs);
@ -424,7 +475,10 @@ void CTxMemPool::clear()
void CTxMemPool::check(const CCoinsViewCache *pcoins) const
{
if (!fSanityCheck)
if (nCheckFrequency == 0)
return;
if (insecure_rand() >= nCheckFrequency)
return;
LogPrint("mempool", "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
@ -433,20 +487,21 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
uint64_t innerUsage = 0;
CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins));
const int64_t nSpendHeight = GetSpendHeight(mempoolDuplicate);
LOCK(cs);
list<const CTxMemPoolEntry*> waitingOnDependants;
for (std::map<uint256, CTxMemPoolEntry>::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
unsigned int i = 0;
checkTotal += it->second.GetTxSize();
innerUsage += it->second.DynamicMemoryUsage();
const CTransaction& tx = it->second.GetTx();
checkTotal += it->GetTxSize();
innerUsage += it->DynamicMemoryUsage();
const CTransaction& tx = it->GetTx();
bool fDependsWait = false;
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
// Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
std::map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(txin.prevout.hash);
indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash);
if (it2 != mapTx.end()) {
const CTransaction& tx2 = it2->second.GetTx();
const CTransaction& tx2 = it2->GetTx();
assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
fDependsWait = true;
} else {
@ -484,11 +539,13 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
intermediates.insert(std::make_pair(tree.root(), tree));
}
if (fDependsWait)
waitingOnDependants.push_back(&it->second);
waitingOnDependants.push_back(&(*it));
else {
CValidationState state;
assert(ContextualCheckInputs(tx, state, mempoolDuplicate, false, 0, false, Params().GetConsensus(), NULL));
UpdateCoins(tx, state, mempoolDuplicate, 1000000);
bool fCheckResult = tx.IsCoinBase() ||
Consensus::CheckTxInputs(tx, state, mempoolDuplicate, nSpendHeight, Params().GetConsensus());
assert(fCheckResult);
UpdateCoins(tx, mempoolDuplicate, 1000000);
}
}
unsigned int stepsSinceLastRemove = 0;
@ -501,15 +558,17 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
stepsSinceLastRemove++;
assert(stepsSinceLastRemove < waitingOnDependants.size());
} else {
assert(ContextualCheckInputs(entry->GetTx(), state, mempoolDuplicate, false, 0, false, Params().GetConsensus(), NULL));
UpdateCoins(entry->GetTx(), state, mempoolDuplicate, 1000000);
bool fCheckResult = entry->GetTx().IsCoinBase() ||
Consensus::CheckTxInputs(entry->GetTx(), state, mempoolDuplicate, nSpendHeight, Params().GetConsensus());
assert(fCheckResult);
UpdateCoins(entry->GetTx(), mempoolDuplicate, 1000000);
stepsSinceLastRemove = 0;
}
}
for (std::map<COutPoint, CInPoint>::const_iterator it = mapNextTx.begin(); it != mapNextTx.end(); it++) {
uint256 hash = it->second.ptx->GetHash();
map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(hash);
const CTransaction& tx = it2->second.GetTx();
indexed_transaction_set::const_iterator it2 = mapTx.find(hash);
const CTransaction& tx = it2->GetTx();
assert(it2 != mapTx.end());
assert(&tx == it->second.ptx);
assert(tx.vin.size() > it->second.n);
@ -518,8 +577,8 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
for (std::map<uint256, const CTransaction*>::const_iterator it = mapNullifiers.begin(); it != mapNullifiers.end(); it++) {
uint256 hash = it->second->GetHash();
map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(hash);
const CTransaction& tx = it2->second.GetTx();
indexed_transaction_set::const_iterator it2 = mapTx.find(hash);
const CTransaction& tx = it2->GetTx();
assert(it2 != mapTx.end());
assert(&tx == it->second);
}
@ -534,16 +593,16 @@ void CTxMemPool::queryHashes(vector<uint256>& vtxid)
LOCK(cs);
vtxid.reserve(mapTx.size());
for (map<uint256, CTxMemPoolEntry>::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi)
vtxid.push_back((*mi).first);
for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi)
vtxid.push_back(mi->GetTx().GetHash());
}
bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const
{
LOCK(cs);
map<uint256, CTxMemPoolEntry>::const_iterator i = mapTx.find(hash);
indexed_transaction_set::const_iterator i = mapTx.find(hash);
if (i == mapTx.end()) return false;
result = i->second.GetTx();
result = i->GetTx();
return true;
}

58
src/txmempool.h

@ -15,6 +15,10 @@
#include "primitives/transaction.h"
#include "sync.h"
#undef foreach
#include "boost/multi_index_container.hpp"
#include "boost/multi_index/ordered_index.hpp"
class CAutoFile;
inline double AllowFreeThreshold()
@ -43,25 +47,54 @@ private:
size_t nTxSize; //! ... and avoid recomputing tx size
size_t nModSize; //! ... and modified size for priority
size_t nUsageSize; //! ... and total memory usage
CFeeRate feeRate; //! ... and fee per kB
int64_t nTime; //! Local time when entering the mempool
double dPriority; //! Priority when entering the mempool
unsigned int nHeight; //! Chain height when entering the mempool
bool hadNoDependencies; //! Not dependent on any other txs when it entered the mempool
bool spendsCoinbase; //! keep track of transactions that spend a coinbase
uint32_t nBranchId; //! Branch ID this transaction is known to commit to, cached for efficiency
public:
CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
int64_t _nTime, double _dPriority, unsigned int _nHeight, bool poolHasNoInputsOf = false);
int64_t _nTime, double _dPriority, unsigned int _nHeight,
bool poolHasNoInputsOf, bool spendsCoinbase, uint32_t nBranchId);
CTxMemPoolEntry();
CTxMemPoolEntry(const CTxMemPoolEntry& other);
const CTransaction& GetTx() const { return this->tx; }
double GetPriority(unsigned int currentHeight) const;
CAmount GetFee() const { return nFee; }
CFeeRate GetFeeRate() const { return feeRate; }
size_t GetTxSize() const { return nTxSize; }
int64_t GetTime() const { return nTime; }
unsigned int GetHeight() const { return nHeight; }
bool WasClearAtEntry() const { return hadNoDependencies; }
size_t DynamicMemoryUsage() const { return nUsageSize; }
bool GetSpendsCoinbase() const { return spendsCoinbase; }
uint32_t GetValidatedBranchId() const { return nBranchId; }
};
// extracts a TxMemPoolEntry's transaction hash
struct mempoolentry_txid
{
typedef uint256 result_type;
result_type operator() (const CTxMemPoolEntry &entry) const
{
return entry.GetTx().GetHash();
}
};
class CompareTxMemPoolEntryByFee
{
public:
bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b)
{
if (a.GetFeeRate() == b.GetFeeRate())
return a.GetTime() < b.GetTime();
return a.GetFeeRate() > b.GetFeeRate();
}
};
class CBlockPolicyEstimator;
@ -93,7 +126,7 @@ public:
class CTxMemPool
{
private:
bool fSanityCheck; //! Normally false, true if -checkmempool or -regtest
uint32_t nCheckFrequency; //! Value n means that n times in 2^32 we check.
unsigned int nTransactionsUpdated;
CBlockPolicyEstimator* minerPolicyEstimator;
@ -101,8 +134,21 @@ private:
uint64_t cachedInnerUsage; //! sum of dynamic memory usage of all the map elements (NOT the maps themselves)
public:
typedef boost::multi_index_container<
CTxMemPoolEntry,
boost::multi_index::indexed_by<
// sorted by txid
boost::multi_index::ordered_unique<mempoolentry_txid>,
// sorted by fee rate
boost::multi_index::ordered_non_unique<
boost::multi_index::identity<CTxMemPoolEntry>,
CompareTxMemPoolEntryByFee
>
>
> indexed_transaction_set;
mutable CCriticalSection cs;
std::map<uint256, CTxMemPoolEntry> mapTx;
indexed_transaction_set mapTx;
private:
typedef std::map<CMempoolAddressDeltaKey, CMempoolAddressDelta, CMempoolAddressDeltaKeyCompare> addressDeltaMap;
@ -132,7 +178,7 @@ public:
* check does nothing.
*/
void check(const CCoinsViewCache *pcoins) const;
void setSanityCheck(bool _fSanityCheck) { fSanityCheck = _fSanityCheck; }
void setSanityCheck(double dFrequency = 1.0) { nCheckFrequency = dFrequency * 4294967296.0; }
bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, bool fCurrentEstimate = true);
@ -147,10 +193,12 @@ public:
void remove(const CTransaction &tx, std::list<CTransaction>& removed, bool fRecursive = false);
void removeWithAnchor(const uint256 &invalidRoot);
void removeCoinbaseSpends(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight);
void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags);
void removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed);
void removeExpired(unsigned int nBlockHeight);
void removeForBlock(const std::vector<CTransaction>& vtx, unsigned int nBlockHeight,
std::list<CTransaction>& conflicts, bool fCurrentEstimate = true);
void removeWithoutBranchId(uint32_t nMemPoolBranchId);
void clear();
void queryHashes(std::vector<uint256>& vtxid);
void pruneSpent(const uint256& hash, CCoins &coins);

15
src/utilstrencodings.cpp

@ -10,6 +10,7 @@
#include <cstdlib>
#include <cstring>
#include <errno.h>
#include <iomanip>
#include <limits>
using namespace std;
@ -46,6 +47,20 @@ string SanitizeFilename(const string& str)
return strResult;
}
std::string HexInt(uint32_t val)
{
std::stringstream ss;
ss << std::setfill('0') << std::setw(sizeof(uint32_t) * 2) << std::hex << val;
return ss.str();
}
uint32_t ParseHexToUInt32(const std::string& str) {
std::istringstream converter(str);
uint32_t value;
converter >> std::hex >> value;
return value;
}
const signed char p_util_hexdigit[256] =
{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,

2
src/utilstrencodings.h

@ -24,6 +24,8 @@
std::string SanitizeFilename(const std::string& str);
std::string SanitizeString(const std::string& str);
std::string HexInt(uint32_t val);
uint32_t ParseHexToUInt32(const std::string& str);
std::vector<unsigned char> ParseHex(const char* psz);
std::vector<unsigned char> ParseHex(const std::string& str);
signed char HexDigit(char c);

8
src/utiltest.cpp

@ -4,6 +4,8 @@
#include "utiltest.h"
#include "consensus/upgrades.h"
CWalletTx GetValidReceive(ZCJoinSplit& params,
const libzcash::SpendingKey& sk, CAmount value,
bool randomInputs) {
@ -45,9 +47,10 @@ CWalletTx GetValidReceive(ZCJoinSplit& params,
mtx.vjoinsplit.push_back(jsdesc);
// Empty output script.
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
// Add the signature
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
@ -129,9 +132,10 @@ CWalletTx GetValidSpend(ZCJoinSplit& params,
mtx.vjoinsplit.push_back(jsdesc);
// Empty output script.
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
// Add the signature
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,

6
src/version.h

@ -9,7 +9,7 @@
* network protocol versioning
*/
static const int PROTOCOL_VERSION = 170002;
static const int PROTOCOL_VERSION = 170003;
//! initial proto version, to be increased after version/verack negotiation
static const int INIT_PROTO_VERSION = 209;
@ -24,10 +24,6 @@ static const int MIN_PEER_PROTO_VERSION = 170002;
//! if possible, avoid requesting addresses nodes older than this
static const int CADDR_TIME_VERSION = 31402;
//! only request blocks from nodes outside this range of versions
static const int NOBLKS_VERSION_START = 32000;
static const int NOBLKS_VERSION_END = 32400;
//! BIP 0031, pong message, is enabled for all versions AFTER this one
static const int BIP0031_VERSION = 60000;

13
src/wallet/asyncrpcoperation_sendmany.cpp

@ -5,6 +5,7 @@
#include "asyncrpcoperation_sendmany.h"
#include "asyncrpcqueue.h"
#include "amount.h"
#include "consensus/upgrades.h"
#include "core_io.h"
#include "init.h"
#include "main.h"
@ -50,13 +51,14 @@ int find_output(UniValue obj, int n) {
}
AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
CMutableTransaction contextualTx,
std::string fromAddress,
std::vector<SendManyRecipient> tOutputs,
std::vector<SendManyRecipient> zOutputs,
int minDepth,
CAmount fee,
UniValue contextInfo) :
fromaddress_(fromAddress), t_outputs_(tOutputs), z_outputs_(zOutputs), mindepth_(minDepth), fee_(fee), contextinfo_(contextInfo)
tx_(contextualTx), fromaddress_(fromAddress), t_outputs_(tOutputs), z_outputs_(zOutputs), mindepth_(minDepth), fee_(fee), contextinfo_(contextInfo)
{
assert(fee_ >= 0);
@ -335,6 +337,12 @@ bool AsyncRPCOperation_sendmany::main_impl() {
LogPrint("zrpcunsafe", "%s: private output: %s\n", getId(), FormatMoney(z_outputs_total));
LogPrint("zrpc", "%s: fee: %s\n", getId(), FormatMoney(minersFee));
// Grab the current consensus branch ID
{
LOCK(cs_main);
consensusBranchId_ = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
}
/**
* SCENARIO #1
*
@ -370,7 +378,6 @@ bool AsyncRPCOperation_sendmany::main_impl() {
// Prepare raw transaction to handle JoinSplits
CMutableTransaction mtx(tx_);
mtx.nVersion = 2;
crypto_sign_keypair(joinSplitPubKey_.begin(), joinSplitPrivKey_);
mtx.joinSplitPubKey = joinSplitPubKey_;
tx_ = CTransaction(mtx);
@ -993,7 +1000,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit(
// Empty output script.
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId_);
// Add the signature
if (!(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,

3
src/wallet/asyncrpcoperation_sendmany.h

@ -51,7 +51,7 @@ struct WitnessAnchorData {
class AsyncRPCOperation_sendmany : public AsyncRPCOperation {
public:
AsyncRPCOperation_sendmany(std::string fromAddress, std::vector<SendManyRecipient> tOutputs, std::vector<SendManyRecipient> zOutputs, int minDepth, CAmount fee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE, UniValue contextInfo = NullUniValue);
AsyncRPCOperation_sendmany(CMutableTransaction contextualTx, std::string fromAddress, std::vector<SendManyRecipient> tOutputs, std::vector<SendManyRecipient> zOutputs, int minDepth, CAmount fee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE, UniValue contextInfo = NullUniValue);
virtual ~AsyncRPCOperation_sendmany();
// We don't want to be copied or moved around
@ -73,6 +73,7 @@ private:
UniValue contextinfo_; // optional data to include in return value from getStatus()
uint32_t consensusBranchId_;
CAmount fee_;
int mindepth_;
std::string fromaddress_;

12
src/wallet/asyncrpcoperation_shieldcoinbase.cpp

@ -4,6 +4,7 @@
#include "asyncrpcqueue.h"
#include "amount.h"
#include "consensus/upgrades.h"
#include "core_io.h"
#include "init.h"
#include "main.h"
@ -52,12 +53,15 @@ static int find_output(UniValue obj, int n) {
}
AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase(
CMutableTransaction contextualTx,
std::vector<ShieldCoinbaseUTXO> inputs,
std::string toAddress,
CAmount fee,
UniValue contextInfo) :
inputs_(inputs), fee_(fee), contextinfo_(contextInfo)
tx_(contextualTx), inputs_(inputs), fee_(fee), contextinfo_(contextInfo)
{
assert(contextualTx.nVersion >= 2); // transaction format version must support vjoinsplit
if (fee < 0 || fee > MAX_MONEY) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Fee is out of range");
}
@ -213,7 +217,6 @@ bool AsyncRPCOperation_shieldcoinbase::main_impl() {
// Prepare raw transaction to handle JoinSplits
CMutableTransaction mtx(tx_);
mtx.nVersion = 2;
crypto_sign_keypair(joinSplitPubKey_.begin(), joinSplitPrivKey_);
mtx.joinSplitPubKey = joinSplitPubKey_;
tx_ = CTransaction(mtx);
@ -300,12 +303,15 @@ void AsyncRPCOperation_shieldcoinbase::sign_send_raw_transaction(UniValue obj)
UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInfo & info) {
uint32_t consensusBranchId;
uint256 anchor;
{
LOCK(cs_main);
consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
anchor = pcoinsTip->GetBestAnchor();
}
if (anchor.IsNull()) {
throw std::runtime_error("anchor is null");
}
@ -367,7 +373,7 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf
// Empty output script.
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
// Add the signature
if (!(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,

2
src/wallet/asyncrpcoperation_shieldcoinbase.h

@ -42,7 +42,7 @@ struct ShieldCoinbaseJSInfo
class AsyncRPCOperation_shieldcoinbase : public AsyncRPCOperation {
public:
AsyncRPCOperation_shieldcoinbase(std::vector<ShieldCoinbaseUTXO> inputs, std::string toAddress, CAmount fee = SHIELD_COINBASE_DEFAULT_MINERS_FEE, UniValue contextInfo = NullUniValue);
AsyncRPCOperation_shieldcoinbase(CMutableTransaction contextualTx, std::vector<ShieldCoinbaseUTXO> inputs, std::string toAddress, CAmount fee = SHIELD_COINBASE_DEFAULT_MINERS_FEE, UniValue contextInfo = NullUniValue);
virtual ~AsyncRPCOperation_shieldcoinbase();
// We don't want to be copied or moved around

33
src/wallet/gtest/test_wallet.cpp

@ -1046,36 +1046,3 @@ TEST(wallet_tests, MarkAffectedTransactionsDirty) {
wallet.MarkAffectedTransactionsDirty(wtx2);
EXPECT_FALSE(wallet.mapWallet[hash].fDebitCached);
}
TEST(wallet_tests, NoteLocking) {
TestWallet wallet;
auto sk = libzcash::SpendingKey::random();
wallet.AddSpendingKey(sk);
auto wtx = GetValidReceive(sk, 10, true);
auto wtx2 = GetValidReceive(sk, 10, true);
JSOutPoint jsoutpt {wtx.GetHash(), 0, 0};
JSOutPoint jsoutpt2 {wtx2.GetHash(),0, 0};
// Test selective locking
wallet.LockNote(jsoutpt);
EXPECT_TRUE(wallet.IsLockedNote(jsoutpt.hash, jsoutpt.js, jsoutpt.n));
EXPECT_FALSE(wallet.IsLockedNote(jsoutpt2.hash, jsoutpt2.js, jsoutpt2.n));
// Test selective unlocking
wallet.UnlockNote(jsoutpt);
EXPECT_FALSE(wallet.IsLockedNote(jsoutpt.hash, jsoutpt.js, jsoutpt.n));
// Test multiple locking
wallet.LockNote(jsoutpt);
wallet.LockNote(jsoutpt2);
EXPECT_TRUE(wallet.IsLockedNote(jsoutpt.hash, jsoutpt.js, jsoutpt.n));
EXPECT_TRUE(wallet.IsLockedNote(jsoutpt2.hash, jsoutpt2.js, jsoutpt2.n));
// Test unlock all
wallet.UnlockAllNotes();
EXPECT_FALSE(wallet.IsLockedNote(jsoutpt.hash, jsoutpt.js, jsoutpt.n));
EXPECT_FALSE(wallet.IsLockedNote(jsoutpt2.hash, jsoutpt2.js, jsoutpt2.n));
}

1
src/wallet/rpcdisclosure.cpp

@ -303,4 +303,3 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp)
return o;
}

12
src/wallet/rpcdump.cpp

@ -235,11 +235,11 @@ UniValue z_importwallet(const UniValue& params, bool fHelp)
"1. \"filename\" (string, required) The wallet file\n"
"\nExamples:\n"
"\nDump the wallet\n"
+ HelpExampleCli("z_exportwallet", "\"test\"") +
+ HelpExampleCli("z_exportwallet", "\"nameofbackup\"") +
"\nImport the wallet\n"
+ HelpExampleCli("z_importwallet", "\"test\"") +
+ HelpExampleCli("z_importwallet", "\"path/to/exportdir/nameofbackup\"") +
"\nImport using the json rpc call\n"
+ HelpExampleRpc("z_importwallet", "\"test\"")
+ HelpExampleRpc("z_importwallet", "\"path/to/exportdir/nameofbackup\"")
);
return importwallet_impl(params, fHelp, true);
@ -258,11 +258,11 @@ UniValue importwallet(const UniValue& params, bool fHelp)
"1. \"filename\" (string, required) The wallet file\n"
"\nExamples:\n"
"\nDump the wallet\n"
+ HelpExampleCli("dumpwallet", "\"test\"") +
+ HelpExampleCli("dumpwallet", "\"nameofbackup\"") +
"\nImport the wallet\n"
+ HelpExampleCli("importwallet", "\"test\"") +
+ HelpExampleCli("importwallet", "\"path/to/exportdir/nameofbackup\"") +
"\nImport using the json rpc call\n"
+ HelpExampleRpc("importwallet", "\"test\"")
+ HelpExampleRpc("importwallet", "\"path/to/exportdir/nameofbackup\"")
);
return importwallet_impl(params, fHelp, false);

381
src/wallet/rpcwallet.cpp

@ -6,6 +6,7 @@
#include "amount.h"
#include "base58.h"
#include "consensus/upgrades.h"
#include "core_io.h"
#include "init.h"
#include "main.h"
@ -24,6 +25,7 @@
#include "utiltime.h"
#include "asyncrpcoperation.h"
#include "asyncrpcqueue.h"
#include "wallet/asyncrpcoperation_mergetoaddress.h"
#include "wallet/asyncrpcoperation_sendmany.h"
#include "wallet/asyncrpcoperation_shieldcoinbase.h"
@ -85,6 +87,7 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
entry.push_back(Pair("blockindex", wtx.nIndex));
entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
entry.push_back(Pair("expiryheight", (int64_t)wtx.nExpiryHeight));
}
uint256 hash = wtx.GetHash();
entry.push_back(Pair("txid", hash.GetHex()));
@ -2719,7 +2722,12 @@ UniValue zc_benchmark(const UniValue& params, bool fHelp)
} else if (benchmarktype == "verifyequihash") {
sample_times.push_back(benchmark_verify_equihash());
} else if (benchmarktype == "validatelargetx") {
sample_times.push_back(benchmark_large_tx());
// Number of inputs in the spending transaction that we will simulate
int nInputs = 555;
if (params.size() >= 3) {
nInputs = params[2].get_int();
}
sample_times.push_back(benchmark_large_tx(nInputs));
} else if (benchmarktype == "trydecryptnotes") {
int nAddrs = params[2].get_int();
sample_times.push_back(benchmark_try_decrypt_notes(nAddrs));
@ -2979,7 +2987,8 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
// Empty output script.
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
// Add the signature
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
@ -3657,9 +3666,20 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
o.push_back(Pair("fee", std::stod(FormatMoney(nFee))));
UniValue contextInfo = o;
// Contextual transaction we will build on
int nextBlockHeight = chainActive.Height() + 1;
CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextBlockHeight);
bool isShielded = !fromTaddr || zaddrRecipients.size() > 0;
if (contextualTx.nVersion == 1 && isShielded) {
contextualTx.nVersion = 2; // Tx format should support vjoinsplits
}
if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
contextualTx.nExpiryHeight = nextBlockHeight + expiryDelta;
}
// Create operation and add to global queue
std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(fromaddress, taddrRecipients, zaddrRecipients, nMinDepth, nFee, contextInfo) );
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(contextualTx, fromaddress, taddrRecipients, zaddrRecipients, nMinDepth, nFee, contextInfo) );
q->addOperation(operation);
AsyncRPCOperationId operationId = operation->getId();
return operationId;
@ -3841,9 +3861,20 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
contextInfo.push_back(Pair("toaddress", params[1]));
contextInfo.push_back(Pair("fee", ValueFromAmount(nFee)));
// Contextual transaction we will build on
int nextBlockHeight = chainActive.Height() + 1;
CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(
Params().GetConsensus(), nextBlockHeight);
if (contextualTx.nVersion == 1) {
contextualTx.nVersion = 2; // Tx format should support vjoinsplits
}
if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
contextualTx.nExpiryHeight = nextBlockHeight + expiryDelta;
}
// Create operation and add to global queue
std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(inputs, destaddress, nFee, contextInfo) );
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(contextualTx, inputs, destaddress, nFee, contextInfo) );
q->addOperation(operation);
AsyncRPCOperationId operationId = operation->getId();
@ -3858,6 +3889,348 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
}
#define MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT 50
#define MERGE_TO_ADDRESS_DEFAULT_SHIELDED_LIMIT 10
#define JOINSPLIT_SIZE JSDescription().GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION)
UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return NullUniValue;
auto fEnableMergeToAddress = fExperimentalMode && GetBoolArg("-zmergetoaddress", false);
std::string strDisabledMsg = "";
if (!fEnableMergeToAddress) {
strDisabledMsg = "\nWARNING: z_mergetoaddress is DISABLED but can be enabled as an experimental feature.\n";
}
if (fHelp || params.size() < 2 || params.size() > 6)
throw runtime_error(
"z_mergetoaddress [\"fromaddress\", ... ] \"toaddress\" ( fee ) ( transparent_limit ) ( shielded_limit ) ( memo )\n"
+ strDisabledMsg +
"\nMerge multiple UTXOs and notes into a single UTXO or note. Coinbase UTXOs are ignored; use `z_shieldcoinbase`"
"\nto combine those into a single note."
"\n\nThis is an asynchronous operation, and UTXOs selected for merging will be locked. If there is an error, they"
"\nare unlocked. The RPC call `listlockunspent` can be used to return a list of locked UTXOs."
"\n\nThe number of UTXOs and notes selected for merging can be limited by the caller. If the transparent limit"
"\nparameter is set to zero, the -mempooltxinputlimit option will determine the number of UTXOs. Any limit is"
"\nconstrained by the consensus rule defining a maximum transaction size of "
+ strprintf("%d bytes.", MAX_TX_SIZE)
+ HelpRequiringPassphrase() + "\n"
"\nArguments:\n"
"1. fromaddresses (string, required) A JSON array with addresses.\n"
" The following special strings are accepted inside the array:\n"
" - \"*\": Merge both UTXOs and notes from all addresses belonging to the wallet.\n"
" - \"ANY_TADDR\": Merge UTXOs from all t-addrs belonging to the wallet.\n"
" - \"ANY_ZADDR\": Merge notes from all z-addrs belonging to the wallet.\n"
" If a special string is given, any given addresses of that type will be ignored.\n"
" [\n"
" \"address\" (string) Can be a t-addr or a z-addr\n"
" ,...\n"
" ]\n"
"2. \"toaddress\" (string, required) The t-addr or z-addr to send the funds to.\n"
"3. fee (numeric, optional, default="
+ strprintf("%s", FormatMoney(MERGE_TO_ADDRESS_OPERATION_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
"4. transparent_limit (numeric, optional, default="
+ strprintf("%d", MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT) + ") Limit on the maximum number of UTXOs to merge. Set to 0 to use node option -mempooltxinputlimit.\n"
"4. shielded_limit (numeric, optional, default="
+ strprintf("%d", MERGE_TO_ADDRESS_DEFAULT_SHIELDED_LIMIT) + ") Limit on the maximum number of notes to merge. Set to 0 to merge as many as will fit in the transaction.\n"
"5. \"memo\" (string, optional) Encoded as hex. When toaddress is a z-addr, this will be stored in the memo field of the new note.\n"
"\nResult:\n"
"{\n"
" \"remainingUTXOs\": xxx (numeric) Number of UTXOs still available for merging.\n"
" \"remainingTransparentValue\": xxx (numeric) Value of UTXOs still available for merging.\n"
" \"remainingNotes\": xxx (numeric) Number of notes still available for merging.\n"
" \"remainingShieldedValue\": xxx (numeric) Value of notes still available for merging.\n"
" \"mergingUTXOs\": xxx (numeric) Number of UTXOs being merged.\n"
" \"mergingTransparentValue\": xxx (numeric) Value of UTXOs being merged.\n"
" \"mergingNotes\": xxx (numeric) Number of notes being merged.\n"
" \"mergingShieldedValue\": xxx (numeric) Value of notes being merged.\n"
" \"opid\": xxx (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("z_mergetoaddress", "'[\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\"]' ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf")
+ HelpExampleRpc("z_mergetoaddress", "[\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\"], \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
);
if (!fEnableMergeToAddress) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error: z_mergetoaddress is disabled.");
}
LOCK2(cs_main, pwalletMain->cs_wallet);
bool useAny = false;
bool useAnyUTXO = false;
bool useAnyNote = false;
std::set<CBitcoinAddress> taddrs = {};
std::set<libzcash::PaymentAddress> zaddrs = {};
UniValue addresses = params[0].get_array();
if (addresses.size()==0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, fromaddresses array is empty.");
// Keep track of addresses to spot duplicates
std::set<std::string> setAddress;
// Sources
for (const UniValue& o : addresses.getValues()) {
if (!o.isStr())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected string");
std::string address = o.get_str();
if (address == "*") {
useAny = true;
} else if (address == "ANY_TADDR") {
useAnyUTXO = true;
} else if (address == "ANY_ZADDR") {
useAnyNote = true;
} else {
CBitcoinAddress taddr(address);
if (taddr.IsValid()) {
// Ignore any listed t-addrs if we are using all of them
if (!(useAny || useAnyUTXO)) {
taddrs.insert(taddr);
}
} else {
try {
CZCPaymentAddress zaddr(address);
// Ignore listed z-addrs if we are using all of them
if (!(useAny || useAnyNote)) {
zaddrs.insert(zaddr.Get());
}
} catch (const std::runtime_error&) {
throw JSONRPCError(
RPC_INVALID_PARAMETER,
string("Invalid parameter, unknown address format: ") + address);
}
}
}
if (setAddress.count(address))
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ") + address);
setAddress.insert(address);
}
// Validate the destination address
auto destaddress = params[1].get_str();
bool isToZaddr = false;
CBitcoinAddress taddr(destaddress);
if (!taddr.IsValid()) {
try {
CZCPaymentAddress zaddr(destaddress);
zaddr.Get();
isToZaddr = true;
} catch (const std::runtime_error&) {
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
}
}
// Convert fee from currency format to zatoshis
CAmount nFee = SHIELD_COINBASE_DEFAULT_MINERS_FEE;
if (params.size() > 2) {
if (params[2].get_real() == 0.0) {
nFee = 0;
} else {
nFee = AmountFromValue( params[2] );
}
}
int nUTXOLimit = MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT;
if (params.size() > 3) {
nUTXOLimit = params[3].get_int();
if (nUTXOLimit < 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of UTXOs cannot be negative");
}
}
int nNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SHIELDED_LIMIT;
if (params.size() > 4) {
nNoteLimit = params[4].get_int();
if (nNoteLimit < 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of notes cannot be negative");
}
}
std::string memo;
if (params.size() > 5) {
memo = params[5].get_str();
if (!isToZaddr) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Memo can not be used with a taddr. It can only be used with a zaddr.");
} else if (!IsHex(memo)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected memo data in hexadecimal format.");
}
if (memo.length() > ZC_MEMO_SIZE*2) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, size of memo is larger than maximum allowed %d", ZC_MEMO_SIZE ));
}
}
MergeToAddressRecipient recipient(destaddress, memo);
// Prepare to get UTXOs and notes
std::vector<MergeToAddressInputUTXO> utxoInputs;
std::vector<MergeToAddressInputNote> noteInputs;
CAmount mergedUTXOValue = 0;
CAmount mergedNoteValue = 0;
CAmount remainingUTXOValue = 0;
CAmount remainingNoteValue = 0;
size_t utxoCounter = 0;
size_t noteCounter = 0;
bool maxedOutUTXOsFlag = false;
bool maxedOutNotesFlag = false;
size_t mempoolLimit = (nUTXOLimit != 0) ? nUTXOLimit : (size_t)GetArg("-mempooltxinputlimit", 0);
size_t estimatedTxSize = 200; // tx overhead + wiggle room
if (isToZaddr) {
estimatedTxSize += JOINSPLIT_SIZE;
}
if (useAny || useAnyUTXO || taddrs.size() > 0) {
// Get available utxos
vector<COutput> vecOutputs;
pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, false);
// Find unspent utxos and update estimated size
for (const COutput& out : vecOutputs) {
if (!out.fSpendable) {
continue;
}
CTxDestination address;
if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
continue;
}
// If taddr is not wildcard "*", filter utxos
if (taddrs.size() > 0 && !taddrs.count(address)) {
continue;
}
utxoCounter++;
CAmount nValue = out.tx->vout[out.i].nValue;
if (!maxedOutUTXOsFlag) {
CBitcoinAddress ba(address);
size_t increase = (ba.IsScript()) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE;
if (estimatedTxSize + increase >= MAX_TX_SIZE ||
(mempoolLimit > 0 && utxoCounter > mempoolLimit))
{
maxedOutUTXOsFlag = true;
} else {
estimatedTxSize += increase;
COutPoint utxo(out.tx->GetHash(), out.i);
utxoInputs.emplace_back(utxo, nValue);
mergedUTXOValue += nValue;
}
}
if (maxedOutUTXOsFlag) {
remainingUTXOValue += nValue;
}
}
}
if (useAny || useAnyNote || zaddrs.size() > 0) {
// Get available notes
std::vector<CNotePlaintextEntry> entries;
pwalletMain->GetFilteredNotes(entries, zaddrs);
// Find unspent notes and update estimated size
for (CNotePlaintextEntry& entry : entries) {
noteCounter++;
CAmount nValue = entry.plaintext.value;
if (!maxedOutNotesFlag) {
// If we haven't added any notes yet and the merge is to a
// z-address, we have already accounted for the first JoinSplit.
size_t increase = (noteInputs.empty() && !isToZaddr) || (noteInputs.size() % 2 == 0) ? JOINSPLIT_SIZE : 0;
if (estimatedTxSize + increase >= MAX_TX_SIZE ||
(nNoteLimit > 0 && noteCounter > nNoteLimit))
{
maxedOutNotesFlag = true;
} else {
estimatedTxSize += increase;
SpendingKey zkey;
pwalletMain->GetSpendingKey(entry.address, zkey);
noteInputs.emplace_back(entry.jsop, entry.plaintext.note(entry.address), nValue, zkey);
mergedNoteValue += nValue;
}
}
if (maxedOutNotesFlag) {
remainingNoteValue += nValue;
}
}
}
size_t numUtxos = utxoInputs.size();
size_t numNotes = noteInputs.size();
if (numUtxos == 0 && numNotes == 0) {
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any funds to merge.");
}
// Sanity check: Don't do anything if:
// - We only have one from address
// - It's equal to toaddress
// - The address only contains a single UTXO or note
if (setAddress.size() == 1 && setAddress.count(destaddress) && (numUtxos + numNotes) == 1) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Destination address is also the only source address, and all its funds are already merged.");
}
CAmount mergedValue = mergedUTXOValue + mergedNoteValue;
if (mergedValue < nFee) {
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS,
strprintf("Insufficient funds, have %s, which is less than miners fee %s",
FormatMoney(mergedValue), FormatMoney(nFee)));
}
// Check that the user specified fee is sane (if too high, it can result in error -25 absurd fee)
CAmount netAmount = mergedValue - nFee;
if (nFee > netAmount) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the net amount to be shielded %s", FormatMoney(nFee), FormatMoney(netAmount)));
}
// Keep record of parameters in context object
UniValue contextInfo(UniValue::VOBJ);
contextInfo.push_back(Pair("fromaddresses", params[0]));
contextInfo.push_back(Pair("toaddress", params[1]));
contextInfo.push_back(Pair("fee", ValueFromAmount(nFee)));
// Contextual transaction we will build on
int nextBlockHeight = chainActive.Height() + 1;
CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(
Params().GetConsensus(),
nextBlockHeight);
bool isShielded = numNotes > 0 || isToZaddr;
if (contextualTx.nVersion == 1 && isShielded) {
contextualTx.nVersion = 2; // Tx format should support vjoinsplit
}
if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
contextualTx.nExpiryHeight = nextBlockHeight + expiryDelta;
}
// Create operation and add to global queue
std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
std::shared_ptr<AsyncRPCOperation> operation(
new AsyncRPCOperation_mergetoaddress(contextualTx, utxoInputs, noteInputs, recipient, nFee, contextInfo) );
q->addOperation(operation);
AsyncRPCOperationId operationId = operation->getId();
// Return continuation information
UniValue o(UniValue::VOBJ);
o.push_back(Pair("remainingUTXOs", utxoCounter - numUtxos));
o.push_back(Pair("remainingTransparentValue", ValueFromAmount(remainingUTXOValue)));
o.push_back(Pair("remainingNotes", noteCounter - numNotes));
o.push_back(Pair("remainingShieldedValue", ValueFromAmount(remainingNoteValue)));
o.push_back(Pair("mergingUTXOs", numUtxos));
o.push_back(Pair("mergingTransparentValue", ValueFromAmount(mergedUTXOValue)));
o.push_back(Pair("mergingNotes", numNotes));
o.push_back(Pair("mergingShieldedValue", ValueFromAmount(mergedNoteValue)));
o.push_back(Pair("opid", operationId));
return o;
}
UniValue z_listoperationids(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))

64
src/wallet/wallet.cpp

@ -8,7 +8,9 @@
#include "base58.h"
#include "checkpoints.h"
#include "coincontrol.h"
#include "consensus/upgrades.h"
#include "consensus/validation.h"
#include "consensus/consensus.h"
#include "init.h"
#include "main.h"
#include "net.h"
@ -2522,6 +2524,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nC
CReserveKey reservekey(this);
CWalletTx wtx;
if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosRet, strFailReason, &coinControl, false))
return false;
@ -2572,8 +2575,21 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
wtxNew.fTimeReceivedIsTxTime = true;
wtxNew.BindWallet(this);
CMutableTransaction txNew;
int nextBlockHeight = chainActive.Height() + 1;
CMutableTransaction txNew = CreateNewContextualCMutableTransaction(
Params().GetConsensus(), nextBlockHeight);
// Activates after Overwinter network upgrade
// Set nExpiryHeight to expiryDelta (default 20) blocks past current block height
if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
if (nextBlockHeight + expiryDelta >= TX_EXPIRY_HEIGHT_THRESHOLD){
strFailReason = _("nExpiryHeight must be less than TX_EXPIRY_HEIGHT_THRESHOLD.");
return false;
} else {
txNew.nExpiryHeight = nextBlockHeight + expiryDelta;
}
}
// Discourage fee sniping.
//
// However because of a off-by-one-error in previous versions we need to
@ -2767,6 +2783,9 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
}
}
// Grab the current consensus branch ID
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
// Sign
int nIn = 0;
CTransaction txNewConst(txNew);
@ -2774,17 +2793,20 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
{
bool signSuccess;
const CScript& scriptPubKey = coin.first->vout[coin.second].scriptPubKey;
CScript& scriptSigRes = txNew.vin[nIn].scriptSig;
SignatureData sigdata;
if (sign)
signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, SIGHASH_ALL), scriptPubKey, scriptSigRes);
signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, coin.first->vout[coin.second].nValue, SIGHASH_ALL), scriptPubKey, sigdata, consensusBranchId);
else
signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, scriptSigRes);
signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata, consensusBranchId);
if (!signSuccess)
{
strFailReason = _("Signing transaction failed");
return false;
} else {
UpdateTransaction(txNew, nIn, sigdata);
}
nIn++;
}
@ -3686,13 +3708,26 @@ bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee)
*/
void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, std::string address, int minDepth, bool ignoreSpent, bool ignoreUnspendable)
{
bool fFilterAddress = false;
libzcash::PaymentAddress filterPaymentAddress;
std::set<PaymentAddress> filterAddresses;
if (address.length() > 0) {
filterPaymentAddress = CZCPaymentAddress(address).Get();
fFilterAddress = true;
filterAddresses.insert(CZCPaymentAddress(address).Get());
}
GetFilteredNotes(outEntries, filterAddresses, minDepth, ignoreSpent, ignoreUnspendable);
}
/**
* Find notes in the wallet filtered by payment addresses, 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::set<PaymentAddress>& filterAddresses,
int minDepth,
bool ignoreSpent,
bool ignoreUnspendable)
{
LOCK2(cs_main, cs_wallet);
for (auto & p : mapWallet) {
@ -3713,7 +3748,7 @@ void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, st
PaymentAddress pa = nd.address;
// skip notes which belong to a different payment address in the wallet
if (fFilterAddress && !(pa == filterPaymentAddress)) {
if (!(filterAddresses.empty() || filterAddresses.count(pa))) {
continue;
}
@ -3726,11 +3761,6 @@ void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, st
if (ignoreUnspendable && !HaveSpendingKey(pa)) {
continue;
}
// skip locked notes
if (IsLockedNote(jsop.hash, jsop.js, jsop.n)) {
continue;
}
int i = jsop.js; // Index into CTransaction.vjoinsplit
int j = jsop.n; // Index into JSDescription.ciphertexts
@ -3752,7 +3782,7 @@ void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, st
hSig,
(unsigned char) j);
outEntries.push_back(CNotePlaintextEntry{jsop, plaintext});
outEntries.push_back(CNotePlaintextEntry{jsop, pa, plaintext});
} catch (const note_decryption_failed &err) {
// Couldn't decrypt with this spending key
@ -3838,4 +3868,4 @@ void CWallet::GetUnspentFilteredNotes(
}
}
}
}
}

5
src/wallet/wallet.h

@ -8,9 +8,9 @@
#include "amount.h"
#include "coins.h"
#include "consensus/consensus.h"
#include "key.h"
#include "keystore.h"
#include "main.h"
#include "primitives/block.h"
#include "primitives/transaction.h"
#include "tinyformat.h"
@ -58,7 +58,7 @@ static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000;
//! Size of witness cache
// Should be large enough that we can expect not to reorg beyond our cache
// unless there is some exceptional network disruption.
static const unsigned int WITNESS_CACHE_SIZE = COINBASE_MATURITY;
static const unsigned int WITNESS_CACHE_SIZE = MAX_REORG_LENGTH + 1;
class CBlockIndex;
class CCoinControl;
@ -267,6 +267,7 @@ typedef std::map<JSOutPoint, CNoteData> mapNoteData_t;
struct CNotePlaintextEntry
{
JSOutPoint jsop;
libzcash::PaymentAddress address;
libzcash::NotePlaintext plaintext;
};

1
src/wallet/wallet_ismine.cpp

@ -71,6 +71,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
}
break;
}
case TX_MULTISIG:
{
// Only consider transactions "mine" if we own ALL the

36
src/zcbenchmarks.cpp

@ -13,6 +13,7 @@
#include "crypto/equihash.h"
#include "chain.h"
#include "chainparams.h"
#include "consensus/upgrades.h"
#include "consensus/validation.h"
#include "main.h"
#include "miner.h"
@ -221,11 +222,8 @@ double benchmark_verify_equihash()
return timer_stop(tv_start);
}
double benchmark_large_tx()
double benchmark_large_tx(size_t nInputs)
{
// Number of inputs in the spending transaction that we will simulate
const size_t NUM_INPUTS = 555;
// Create priv/pub key
CKey priv;
priv.MakeNewKey(false);
@ -244,26 +242,20 @@ double benchmark_large_tx()
auto orig_tx = CTransaction(m_orig_tx);
CMutableTransaction spending_tx;
spending_tx.fOverwintered = true;
spending_tx.nVersion = 3;
spending_tx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID;
auto input_hash = orig_tx.GetHash();
// Add NUM_INPUTS inputs
for (size_t i = 0; i < NUM_INPUTS; i++) {
// Add nInputs inputs
for (size_t i = 0; i < nInputs; i++) {
spending_tx.vin.emplace_back(input_hash, 0);
}
// Sign for all the inputs
for (size_t i = 0; i < NUM_INPUTS; i++) {
SignSignature(tempKeystore, prevPubKey, spending_tx, i, SIGHASH_ALL);
}
// Serialize:
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << spending_tx;
//std::cout << "SIZE OF SPENDING TX: " << ss.size() << std::endl;
auto error = MAX_TX_SIZE / 20; // 5% error
assert(ss.size() < MAX_TX_SIZE + error);
assert(ss.size() > MAX_TX_SIZE - error);
auto consensusBranchId = NetworkUpgradeInfo[Consensus::UPGRADE_OVERWINTER].nBranchId;
for (size_t i = 0; i < nInputs; i++) {
SignSignature(tempKeystore, prevPubKey, spending_tx, i, 1000000, SIGHASH_ALL, consensusBranchId);
}
// Spending tx has all its inputs signed and does not need to be mutated anymore
@ -272,12 +264,14 @@ double benchmark_large_tx()
// Benchmark signature verification costs:
struct timeval tv_start;
timer_start(tv_start);
for (size_t i = 0; i < NUM_INPUTS; i++) {
PrecomputedTransactionData txdata(final_spending_tx);
for (size_t i = 0; i < nInputs; i++) {
ScriptError serror = SCRIPT_ERR_OK;
assert(VerifyScript(final_spending_tx.vin[i].scriptSig,
prevPubKey,
STANDARD_SCRIPT_VERIFY_FLAGS,
TransactionSignatureChecker(&final_spending_tx, i),
TransactionSignatureChecker(&final_spending_tx, i, 1000000, txdata),
consensusBranchId,
&serror));
}
return timer_stop(tv_start);

2
src/zcbenchmarks.h

@ -12,7 +12,7 @@ extern double benchmark_solve_equihash();
extern std::vector<double> benchmark_solve_equihash_threaded(int nThreads);
extern double benchmark_verify_joinsplit(const JSDescription &joinsplit);
extern double benchmark_verify_equihash();
extern double benchmark_large_tx();
extern double benchmark_large_tx(size_t nInputs);
extern double benchmark_try_decrypt_notes(size_t nAddrs);
extern double benchmark_increment_note_witnesses(size_t nTxs);
extern double benchmark_connectblock_slow();

Loading…
Cancel
Save