mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-19 13:27:35 +02:00
Squashed 'src/secp256k1/' changes from 22f60a6..71ed475
71ed475 Pedersen commitments, borromean ring signatures, and ZK range proofs. afd1379 Add 64-bit integer utilities 9d96e36 Merge pull request #280 432e1ce Merge pull request #283 14727fd Use correct name in gitignore 356b0e9 Actually test static precomputation in Travis ff3a5df Merge pull request #284 2587208 Merge pull request #212 a5a66c7 Add support for custom EC-Schnorr-SHA256 signatures d84a378 Merge pull request #252 72ae443 Improve perf. of cmov-based table lookup 92e53fc Implement endomorphism optimization for secp256k1_ecmult_const ed35d43 Make `secp256k1_scalar_add_bit` conditional; make `secp256k1_scalar_split_lambda_var` constant time 91c0ce9 Add benchmarks for ECDH and const-time multiplication 0739bbb Add ECDH module which works by hashing the output of ecmult_const 4401500 Add constant-time multiply `secp256k1_ecmult_const` for ECDH e4ce393 build: fix hard-coded usage of "gen_context" b8e39ac build: don't use BUILT_SOURCES for the static context header baa75da tests: add a couple tests ae4f0c6 Merge pull request #278 995c548 Introduce callback functions for dealing with errors. c333074 Merge pull request #282 18c329c Remove the internal secp256k1_ecdsa_sig_t type 74a2acd Add a secp256k1_ecdsa_signature_t type 23cfa91 Introduce secp256k1_pubkey_t type 4c63780 Merge pull request #269 3e6f1e2 Change rfc6979 implementation to be a generic PRNG ed5334a Update configure.ac to make it build on OpenBSD 1b68366 Merge pull request #274 a83bb48 Make ecmult static precomputation default 166b32f Merge pull request #276 c37812f Add gen_context src/ecmult_static_context.h to CLEANFILES to fix distclean. 125c15d Merge pull request #275 76f6769 Fix build with static ecmult altroot and make dist. 5133f78 Merge pull request #254 b0a60e6 Merge pull request #258 733c1e6 Add travis build to test the static context. fbecc38 Add ability to use a statically generated ecmult context. 4fb174d Merge pull request #263 4ab8990 Merge pull request #270 bdf0e0c Merge pull request #271 31d0c1f Merge pull request #273 eb2c8ff Add missing casts to SECP256K1_FE_CONST_INNER 55399c2 Further performance improvements to _ecmult_wnaf 99fd963 Add secp256k1_ec_pubkey_compress(), with test similar to the related decompress() function. 145cc6e Improve performance of _ecmult_wnaf 36b305a Verify the result of GMP modular inverse using non-GMP code 0cbc860 Merge pull request #266 06ff7fe Merge pull request #267 5a43124 Save 1 _fe_negate since s1 == -s2 a5d796e Update code comments 3f3964e Add specific VERIFY tests for _fe_cmov 7d054cd Refactor to save a _fe_negate b28d02a Refactor to remove a local var 55e7fc3 Perf. improvement in _gej_add_ge a0601cd Fix VERIFY calculations in _fe_cmov methods 17f7148 Merge pull request #261 7657420 Add tests for adding P+Q with P.x!=Q.x and P.y=-Q.y 8c5d5f7 tests: Add failing unit test for #257 (bad addition formula) 5de4c5d gej_add_ge: fix degenerate case when computing P + (-lambda)P bcf2fcf gej_add_ge: rearrange algebra e2a07c7 Fix compilation with C++ 873a453 Merge pull request #250 91eb0da Merge pull request #247 210ffed Use separate in and out pointers in `secp256k1_ec_pubkey_decompress` a1d5ae1 Tiny optimization 729badf Merge pull request #210 2d5a186 Apply effective-affine trick to precomp 4f9791a Effective affine addition in EC multiplication git-subtree-dir: src/secp256k1 git-subtree-split: 71ed475ea53ff4576b7344762584b752a824c60f
This commit is contained in:
parent
582b2934e6
commit
a671356e1f
1140 changed files with 4941 additions and 305782 deletions
|
|
@ -1,51 +0,0 @@
|
|||
AccessModifierOffset: -4
|
||||
AlignEscapedNewlinesLeft: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
BinPackParameters: false
|
||||
BreakBeforeBinaryOperators: false
|
||||
BreakBeforeBraces: Linux
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
ColumnLimit: 0
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH, BOOST_REVERSE_FOREACH ]
|
||||
IndentCaseLabels: false
|
||||
IndentFunctionDeclarationAfterType: false
|
||||
IndentWidth: 4
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
Language: Cpp
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: None
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: false
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerAlignment: Left
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
Standard: Cpp03
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
422
src/Makefile.am
422
src/Makefile.am
|
|
@ -1,422 +0,0 @@
|
|||
DIST_SUBDIRS = secp256k1
|
||||
AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS)
|
||||
|
||||
|
||||
if EMBEDDED_LEVELDB
|
||||
LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include
|
||||
LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/helpers/memenv
|
||||
LIBLEVELDB += $(builddir)/leveldb/libleveldb.a
|
||||
LIBMEMENV += $(builddir)/leveldb/libmemenv.a
|
||||
|
||||
# NOTE: This dependency is not strictly necessary, but without it make may try to build both in parallel, which breaks the LevelDB build system in a race
|
||||
$(LIBLEVELDB): $(LIBMEMENV)
|
||||
|
||||
$(LIBLEVELDB) $(LIBMEMENV):
|
||||
@echo "Building LevelDB ..." && $(MAKE) -C $(@D) $(@F) CXX="$(CXX)" \
|
||||
CC="$(CC)" PLATFORM=$(TARGET_OS) AR="$(AR)" $(LEVELDB_TARGET_FLAGS) \
|
||||
OPT="$(CXXFLAGS) $(CPPFLAGS)"
|
||||
endif
|
||||
|
||||
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
|
||||
|
||||
LIBBITCOIN_SERVER=libbitcoin_server.a
|
||||
LIBBITCOIN_WALLET=libbitcoin_wallet.a
|
||||
LIBBITCOIN_COMMON=libbitcoin_common.a
|
||||
LIBBITCOIN_CLI=libbitcoin_cli.a
|
||||
LIBBITCOIN_UTIL=libbitcoin_util.a
|
||||
LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a
|
||||
LIBBITCOIN_UNIVALUE=univalue/libbitcoin_univalue.a
|
||||
LIBBITCOINQT=qt/libbitcoinqt.a
|
||||
LIBSECP256K1=secp256k1/libsecp256k1.la
|
||||
|
||||
$(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*)
|
||||
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F)
|
||||
|
||||
# Make is not made aware of per-object dependencies to avoid limiting building parallelization
|
||||
# But to build the less dependent modules first, we manually select their order here:
|
||||
EXTRA_LIBRARIES = \
|
||||
crypto/libbitcoin_crypto.a \
|
||||
libbitcoin_util.a \
|
||||
libbitcoin_common.a \
|
||||
univalue/libbitcoin_univalue.a \
|
||||
libbitcoin_server.a \
|
||||
libbitcoin_cli.a
|
||||
if ENABLE_WALLET
|
||||
BITCOIN_INCLUDES += $(BDB_CPPFLAGS)
|
||||
EXTRA_LIBRARIES += libbitcoin_wallet.a
|
||||
endif
|
||||
|
||||
if BUILD_BITCOIN_LIBS
|
||||
lib_LTLIBRARIES = libbitcoinconsensus.la
|
||||
LIBBITCOIN_CONSENSUS=libbitcoinconsensus.la
|
||||
else
|
||||
LIBBITCOIN_CONSENSUS=
|
||||
endif
|
||||
|
||||
bin_PROGRAMS =
|
||||
TESTS =
|
||||
|
||||
if BUILD_BITCOIND
|
||||
bin_PROGRAMS += bitcoind
|
||||
endif
|
||||
|
||||
if BUILD_BITCOIN_UTILS
|
||||
bin_PROGRAMS += bitcoin-cli bitcoin-tx
|
||||
endif
|
||||
|
||||
.PHONY: FORCE
|
||||
# bitcoin core #
|
||||
BITCOIN_CORE_H = \
|
||||
addrman.h \
|
||||
alert.h \
|
||||
allocators.h \
|
||||
amount.h \
|
||||
base58.h \
|
||||
bloom.h \
|
||||
callrpc.h \
|
||||
chain.h \
|
||||
chainparams.h \
|
||||
chainparamsbase.h \
|
||||
chainparamsseeds.h \
|
||||
checkpoints.h \
|
||||
checkqueue.h \
|
||||
clientversion.h \
|
||||
coincontrol.h \
|
||||
coins.h \
|
||||
compat.h \
|
||||
compressor.h \
|
||||
primitives/block.h \
|
||||
primitives/transaction.h \
|
||||
core_io.h \
|
||||
crypter.h \
|
||||
db.h \
|
||||
eccryptoverify.h \
|
||||
ecwrapper.h \
|
||||
hash.h \
|
||||
init.h \
|
||||
key.h \
|
||||
keystore.h \
|
||||
leveldbwrapper.h \
|
||||
limitedmap.h \
|
||||
main.h \
|
||||
merkleblock.h \
|
||||
miner.h \
|
||||
mruset.h \
|
||||
netbase.h \
|
||||
net.h \
|
||||
noui.h \
|
||||
pow.h \
|
||||
protocol.h \
|
||||
pubkey.h \
|
||||
random.h \
|
||||
rpcclient.h \
|
||||
rpcprotocol.h \
|
||||
rpcserver.h \
|
||||
script/generic.hpp \
|
||||
script/interpreter.h \
|
||||
script/script.h \
|
||||
script/sigcache.h \
|
||||
script/sign.h \
|
||||
script/standard.h \
|
||||
script/script_error.h \
|
||||
serialize.h \
|
||||
streams.h \
|
||||
sync.h \
|
||||
threadsafety.h \
|
||||
timedata.h \
|
||||
tinyformat.h \
|
||||
txdb.h \
|
||||
txmempool.h \
|
||||
ui_interface.h \
|
||||
uint256.h \
|
||||
undo.h \
|
||||
util.h \
|
||||
utilstrencodings.h \
|
||||
utilmoneystr.h \
|
||||
utiltime.h \
|
||||
version.h \
|
||||
wallet.h \
|
||||
wallet_ismine.h \
|
||||
walletdb.h \
|
||||
compat/sanity.h
|
||||
|
||||
JSON_H = \
|
||||
json/json_spirit.h \
|
||||
json/json_spirit_error_position.h \
|
||||
json/json_spirit_reader.h \
|
||||
json/json_spirit_reader_template.h \
|
||||
json/json_spirit_stream_reader.h \
|
||||
json/json_spirit_utils.h \
|
||||
json/json_spirit_value.h \
|
||||
json/json_spirit_writer.h \
|
||||
json/json_spirit_writer_template.h
|
||||
|
||||
obj/build.h: FORCE
|
||||
@$(MKDIR_P) $(builddir)/obj
|
||||
@$(top_srcdir)/share/genbuild.sh $(abs_top_builddir)/src/obj/build.h \
|
||||
$(abs_top_srcdir)
|
||||
libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h
|
||||
|
||||
# server: shared between bitcoind and bitcoin-qt
|
||||
libbitcoin_server_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS)
|
||||
libbitcoin_server_a_SOURCES = \
|
||||
addrman.cpp \
|
||||
alert.cpp \
|
||||
chain.cpp \
|
||||
checkpoints.cpp \
|
||||
init.cpp \
|
||||
leveldbwrapper.cpp \
|
||||
main.cpp \
|
||||
miner.cpp \
|
||||
net.cpp \
|
||||
noui.cpp \
|
||||
rest.cpp \
|
||||
rpcblockchain.cpp \
|
||||
rpcmining.cpp \
|
||||
rpcmisc.cpp \
|
||||
rpcnet.cpp \
|
||||
rpcrawtransaction.cpp \
|
||||
rpcserver.cpp \
|
||||
script/sigcache.cpp \
|
||||
timedata.cpp \
|
||||
txdb.cpp \
|
||||
txmempool.cpp \
|
||||
$(JSON_H) \
|
||||
$(BITCOIN_CORE_H)
|
||||
|
||||
# wallet: shared between bitcoind and bitcoin-qt, but only linked
|
||||
# when wallet enabled
|
||||
libbitcoin_wallet_a_CPPFLAGS = $(BITCOIN_INCLUDES)
|
||||
libbitcoin_wallet_a_SOURCES = \
|
||||
db.cpp \
|
||||
crypter.cpp \
|
||||
rpcdump.cpp \
|
||||
rpcwallet.cpp \
|
||||
wallet.cpp \
|
||||
wallet_ismine.cpp \
|
||||
walletdb.cpp \
|
||||
$(BITCOIN_CORE_H)
|
||||
|
||||
# crypto primitives library
|
||||
crypto_libbitcoin_crypto_a_CPPFLAGS = $(BITCOIN_CONFIG_INCLUDES)
|
||||
crypto_libbitcoin_crypto_a_SOURCES = \
|
||||
crypto/sha1.cpp \
|
||||
crypto/sha256.cpp \
|
||||
crypto/sha512.cpp \
|
||||
crypto/hmac_sha256.cpp \
|
||||
crypto/rfc6979_hmac_sha256.cpp \
|
||||
crypto/hmac_sha512.cpp \
|
||||
crypto/ripemd160.cpp \
|
||||
crypto/common.h \
|
||||
crypto/sha256.h \
|
||||
crypto/sha512.h \
|
||||
crypto/hmac_sha256.h \
|
||||
crypto/rfc6979_hmac_sha256.h \
|
||||
crypto/hmac_sha512.h \
|
||||
crypto/sha1.h \
|
||||
crypto/ripemd160.h
|
||||
|
||||
# univalue JSON library
|
||||
univalue_libbitcoin_univalue_a_SOURCES = \
|
||||
univalue/univalue.cpp \
|
||||
univalue/univalue_read.cpp \
|
||||
univalue/univalue_write.cpp \
|
||||
univalue/univalue_escapes.h \
|
||||
univalue/univalue.h
|
||||
|
||||
# common: shared between bitcoind, and bitcoin-qt and non-server tools
|
||||
libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES)
|
||||
libbitcoin_common_a_SOURCES = \
|
||||
allocators.cpp \
|
||||
amount.cpp \
|
||||
base58.cpp \
|
||||
bloom.cpp \
|
||||
chainparams.cpp \
|
||||
coins.cpp \
|
||||
compressor.cpp \
|
||||
primitives/block.cpp \
|
||||
primitives/transaction.cpp \
|
||||
core_read.cpp \
|
||||
core_write.cpp \
|
||||
eccryptoverify.cpp \
|
||||
ecwrapper.cpp \
|
||||
hash.cpp \
|
||||
key.cpp \
|
||||
keystore.cpp \
|
||||
merkleblock.cpp \
|
||||
netbase.cpp \
|
||||
pow.cpp \
|
||||
protocol.cpp \
|
||||
pubkey.cpp \
|
||||
script/interpreter.cpp \
|
||||
script/script.cpp \
|
||||
script/sign.cpp \
|
||||
script/standard.cpp \
|
||||
script/script_error.cpp \
|
||||
$(BITCOIN_CORE_H)
|
||||
|
||||
# util: shared between all executables.
|
||||
# This library *must* be included to make sure that the glibc
|
||||
# backward-compatibility objects and their sanity checks are linked.
|
||||
libbitcoin_util_a_CPPFLAGS = $(BITCOIN_INCLUDES)
|
||||
libbitcoin_util_a_SOURCES = \
|
||||
callrpc.cpp \
|
||||
compat/strnlen.cpp \
|
||||
compat/glibc_sanity.cpp \
|
||||
compat/glibcxx_sanity.cpp \
|
||||
chainparamsbase.cpp \
|
||||
clientversion.cpp \
|
||||
random.cpp \
|
||||
rpcprotocol.cpp \
|
||||
sync.cpp \
|
||||
uint256.cpp \
|
||||
util.cpp \
|
||||
utilstrencodings.cpp \
|
||||
utilmoneystr.cpp \
|
||||
utiltime.cpp \
|
||||
$(BITCOIN_CORE_H)
|
||||
|
||||
if GLIBC_BACK_COMPAT
|
||||
libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp
|
||||
libbitcoin_util_a_SOURCES += compat/glibcxx_compat.cpp
|
||||
endif
|
||||
|
||||
# cli: shared between bitcoin-cli and bitcoin-qt
|
||||
libbitcoin_cli_a_CPPFLAGS = $(BITCOIN_INCLUDES)
|
||||
libbitcoin_cli_a_SOURCES = \
|
||||
rpcclient.cpp \
|
||||
$(BITCOIN_CORE_H)
|
||||
|
||||
nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h
|
||||
#
|
||||
|
||||
# bitcoind binary #
|
||||
bitcoind_LDADD = \
|
||||
$(LIBBITCOIN_SERVER) \
|
||||
$(LIBBITCOIN_COMMON) \
|
||||
$(LIBBITCOIN_UNIVALUE) \
|
||||
$(LIBBITCOIN_UTIL) \
|
||||
$(LIBBITCOIN_CRYPTO) \
|
||||
$(LIBLEVELDB) \
|
||||
$(LIBMEMENV) \
|
||||
$(LIBSECP256K1)
|
||||
|
||||
if ENABLE_WALLET
|
||||
bitcoind_LDADD += libbitcoin_wallet.a
|
||||
endif
|
||||
bitcoind_SOURCES = bitcoind.cpp
|
||||
#
|
||||
|
||||
if TARGET_WINDOWS
|
||||
bitcoind_SOURCES += bitcoind-res.rc
|
||||
endif
|
||||
|
||||
bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
|
||||
bitcoind_CPPFLAGS = $(BITCOIN_INCLUDES)
|
||||
bitcoind_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
|
||||
# bitcoin-cli binary #
|
||||
bitcoin_cli_LDADD = \
|
||||
$(LIBBITCOIN_CLI) \
|
||||
$(LIBBITCOIN_UTIL) \
|
||||
$(BOOST_LIBS) \
|
||||
$(SSL_LIBS) \
|
||||
$(CRYPTO_LIBS)
|
||||
|
||||
bitcoin_cli_SOURCES = \
|
||||
bitcoin-cli.cpp
|
||||
|
||||
bitcoin_cli_CPPFLAGS = $(BITCOIN_INCLUDES)
|
||||
#
|
||||
|
||||
# bitcoin-tx binary #
|
||||
bitcoin_tx_LDADD = \
|
||||
$(LIBBITCOIN_UNIVALUE) \
|
||||
$(LIBBITCOIN_COMMON) \
|
||||
$(LIBBITCOIN_UTIL) \
|
||||
$(LIBBITCOIN_CRYPTO) \
|
||||
$(LIBSECP256K1) \
|
||||
$(BOOST_LIBS) \
|
||||
$(CRYPTO_LIBS) \
|
||||
$(SSL_LIBS)
|
||||
|
||||
bitcoin_tx_SOURCES = bitcoin-tx.cpp
|
||||
bitcoin_tx_CPPFLAGS = $(BITCOIN_INCLUDES)
|
||||
#
|
||||
bitcoin_tx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
|
||||
if TARGET_WINDOWS
|
||||
bitcoin_cli_SOURCES += bitcoin-cli-res.rc
|
||||
endif
|
||||
bitcoin_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
|
||||
if BUILD_BITCOIN_LIBS
|
||||
include_HEADERS = script/bitcoinconsensus.h
|
||||
libbitcoinconsensus_la_SOURCES = \
|
||||
primitives/transaction.cpp \
|
||||
crypto/hmac_sha512.cpp \
|
||||
crypto/sha1.cpp \
|
||||
crypto/sha256.cpp \
|
||||
crypto/sha512.cpp \
|
||||
crypto/ripemd160.cpp \
|
||||
eccryptoverify.cpp \
|
||||
ecwrapper.cpp \
|
||||
hash.cpp \
|
||||
pubkey.cpp \
|
||||
script/script.cpp \
|
||||
script/interpreter.cpp \
|
||||
script/bitcoinconsensus.cpp \
|
||||
uint256.cpp \
|
||||
utilstrencodings.cpp
|
||||
|
||||
if GLIBC_BACK_COMPAT
|
||||
libbitcoinconsensus_la_SOURCES += compat/glibc_compat.cpp
|
||||
libbitcoinconsensus_la_SOURCES += compat/glibcxx_compat.cpp
|
||||
endif
|
||||
|
||||
libbitcoinconsensus_la_LDFLAGS = -no-undefined -version-info 1:0:0 $(RELDFLAGS)
|
||||
libbitcoinconsensus_la_LIBADD = $(CRYPTO_LIBS) $(SSL_LIBS)
|
||||
libbitcoinconsensus_la_CPPFLAGS = $(CRYPTO_CFLAGS) -I$(builddir)/obj -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL
|
||||
if USE_LIBSECP256K1
|
||||
libbitcoinconsensus_la_LIBADD += secp256k1/libsecp256k1.la
|
||||
endif
|
||||
endif
|
||||
|
||||
CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a *.gcda *.gcno
|
||||
|
||||
DISTCLEANFILES = obj/build.h
|
||||
|
||||
EXTRA_DIST = leveldb
|
||||
|
||||
clean-local:
|
||||
-$(MAKE) -C leveldb clean
|
||||
-$(MAKE) -C secp256k1 clean
|
||||
rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno
|
||||
-rm -f config.h
|
||||
|
||||
.rc.o:
|
||||
@test -f $(WINDRES)
|
||||
$(AM_V_GEN) $(WINDRES) -DWINDRES_PREPROC -i $< -o $@
|
||||
|
||||
.mm.o:
|
||||
$(AM_V_CXX) $(OBJCXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CXXFLAGS) $(QT_INCLUDES) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
%.pb.cc %.pb.h: %.proto
|
||||
@test -f $(PROTOC)
|
||||
$(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $(<D) $<)
|
||||
|
||||
if ENABLE_TESTS
|
||||
include Makefile.test.include
|
||||
endif
|
||||
|
||||
if ENABLE_QT
|
||||
include Makefile.qt.include
|
||||
endif
|
||||
|
||||
if ENABLE_QT_TESTS
|
||||
include Makefile.qttest.include
|
||||
endif
|
||||
|
|
@ -1,416 +0,0 @@
|
|||
bin_PROGRAMS += qt/bitcoin-qt
|
||||
EXTRA_LIBRARIES += qt/libbitcoinqt.a
|
||||
|
||||
# bitcoin qt core #
|
||||
QT_TS = \
|
||||
qt/locale/bitcoin_ach.ts \
|
||||
qt/locale/bitcoin_af_ZA.ts \
|
||||
qt/locale/bitcoin_ar.ts \
|
||||
qt/locale/bitcoin_be_BY.ts \
|
||||
qt/locale/bitcoin_bg.ts \
|
||||
qt/locale/bitcoin_bs.ts \
|
||||
qt/locale/bitcoin_ca_ES.ts \
|
||||
qt/locale/bitcoin_ca.ts \
|
||||
qt/locale/bitcoin_ca@valencia.ts \
|
||||
qt/locale/bitcoin_cmn.ts \
|
||||
qt/locale/bitcoin_cs.ts \
|
||||
qt/locale/bitcoin_cy.ts \
|
||||
qt/locale/bitcoin_da.ts \
|
||||
qt/locale/bitcoin_de.ts \
|
||||
qt/locale/bitcoin_el_GR.ts \
|
||||
qt/locale/bitcoin_en.ts \
|
||||
qt/locale/bitcoin_eo.ts \
|
||||
qt/locale/bitcoin_es_CL.ts \
|
||||
qt/locale/bitcoin_es_DO.ts \
|
||||
qt/locale/bitcoin_es_MX.ts \
|
||||
qt/locale/bitcoin_es.ts \
|
||||
qt/locale/bitcoin_es_UY.ts \
|
||||
qt/locale/bitcoin_et.ts \
|
||||
qt/locale/bitcoin_eu_ES.ts \
|
||||
qt/locale/bitcoin_fa_IR.ts \
|
||||
qt/locale/bitcoin_fa.ts \
|
||||
qt/locale/bitcoin_fi.ts \
|
||||
qt/locale/bitcoin_fr_CA.ts \
|
||||
qt/locale/bitcoin_fr.ts \
|
||||
qt/locale/bitcoin_gl.ts \
|
||||
qt/locale/bitcoin_gu_IN.ts \
|
||||
qt/locale/bitcoin_he.ts \
|
||||
qt/locale/bitcoin_hi_IN.ts \
|
||||
qt/locale/bitcoin_hr.ts \
|
||||
qt/locale/bitcoin_hu.ts \
|
||||
qt/locale/bitcoin_id_ID.ts \
|
||||
qt/locale/bitcoin_it.ts \
|
||||
qt/locale/bitcoin_ja.ts \
|
||||
qt/locale/bitcoin_ka.ts \
|
||||
qt/locale/bitcoin_kk_KZ.ts \
|
||||
qt/locale/bitcoin_ko_KR.ts \
|
||||
qt/locale/bitcoin_ky.ts \
|
||||
qt/locale/bitcoin_la.ts \
|
||||
qt/locale/bitcoin_lt.ts \
|
||||
qt/locale/bitcoin_lv_LV.ts \
|
||||
qt/locale/bitcoin_mn.ts \
|
||||
qt/locale/bitcoin_ms_MY.ts \
|
||||
qt/locale/bitcoin_nb.ts \
|
||||
qt/locale/bitcoin_nl.ts \
|
||||
qt/locale/bitcoin_pam.ts \
|
||||
qt/locale/bitcoin_pl.ts \
|
||||
qt/locale/bitcoin_pt_BR.ts \
|
||||
qt/locale/bitcoin_pt_PT.ts \
|
||||
qt/locale/bitcoin_ro_RO.ts \
|
||||
qt/locale/bitcoin_ru.ts \
|
||||
qt/locale/bitcoin_sah.ts \
|
||||
qt/locale/bitcoin_sk.ts \
|
||||
qt/locale/bitcoin_sl_SI.ts \
|
||||
qt/locale/bitcoin_sq.ts \
|
||||
qt/locale/bitcoin_sr.ts \
|
||||
qt/locale/bitcoin_sv.ts \
|
||||
qt/locale/bitcoin_th_TH.ts \
|
||||
qt/locale/bitcoin_tr.ts \
|
||||
qt/locale/bitcoin_uk.ts \
|
||||
qt/locale/bitcoin_ur_PK.ts \
|
||||
qt/locale/bitcoin_uz@Cyrl.ts \
|
||||
qt/locale/bitcoin_vi.ts \
|
||||
qt/locale/bitcoin_vi_VN.ts \
|
||||
qt/locale/bitcoin_zh_CN.ts \
|
||||
qt/locale/bitcoin_zh_HK.ts \
|
||||
qt/locale/bitcoin_zh_TW.ts
|
||||
|
||||
QT_FORMS_UI = \
|
||||
qt/forms/addressbookpage.ui \
|
||||
qt/forms/askpassphrasedialog.ui \
|
||||
qt/forms/coincontroldialog.ui \
|
||||
qt/forms/editaddressdialog.ui \
|
||||
qt/forms/helpmessagedialog.ui \
|
||||
qt/forms/intro.ui \
|
||||
qt/forms/openuridialog.ui \
|
||||
qt/forms/optionsdialog.ui \
|
||||
qt/forms/overviewpage.ui \
|
||||
qt/forms/receivecoinsdialog.ui \
|
||||
qt/forms/receiverequestdialog.ui \
|
||||
qt/forms/rpcconsole.ui \
|
||||
qt/forms/sendcoinsdialog.ui \
|
||||
qt/forms/sendcoinsentry.ui \
|
||||
qt/forms/signverifymessagedialog.ui \
|
||||
qt/forms/transactiondescdialog.ui
|
||||
|
||||
QT_MOC_CPP = \
|
||||
qt/moc_addressbookpage.cpp \
|
||||
qt/moc_addresstablemodel.cpp \
|
||||
qt/moc_askpassphrasedialog.cpp \
|
||||
qt/moc_bitcoinaddressvalidator.cpp \
|
||||
qt/moc_bitcoinamountfield.cpp \
|
||||
qt/moc_bitcoingui.cpp \
|
||||
qt/moc_bitcoinunits.cpp \
|
||||
qt/moc_clientmodel.cpp \
|
||||
qt/moc_coincontroldialog.cpp \
|
||||
qt/moc_coincontroltreewidget.cpp \
|
||||
qt/moc_csvmodelwriter.cpp \
|
||||
qt/moc_editaddressdialog.cpp \
|
||||
qt/moc_guiutil.cpp \
|
||||
qt/moc_intro.cpp \
|
||||
qt/moc_macdockiconhandler.cpp \
|
||||
qt/moc_macnotificationhandler.cpp \
|
||||
qt/moc_notificator.cpp \
|
||||
qt/moc_openuridialog.cpp \
|
||||
qt/moc_optionsdialog.cpp \
|
||||
qt/moc_optionsmodel.cpp \
|
||||
qt/moc_overviewpage.cpp \
|
||||
qt/moc_peertablemodel.cpp \
|
||||
qt/moc_paymentserver.cpp \
|
||||
qt/moc_qvalidatedlineedit.cpp \
|
||||
qt/moc_qvaluecombobox.cpp \
|
||||
qt/moc_receivecoinsdialog.cpp \
|
||||
qt/moc_receiverequestdialog.cpp \
|
||||
qt/moc_recentrequeststablemodel.cpp \
|
||||
qt/moc_rpcconsole.cpp \
|
||||
qt/moc_sendcoinsdialog.cpp \
|
||||
qt/moc_sendcoinsentry.cpp \
|
||||
qt/moc_signverifymessagedialog.cpp \
|
||||
qt/moc_splashscreen.cpp \
|
||||
qt/moc_trafficgraphwidget.cpp \
|
||||
qt/moc_transactiondesc.cpp \
|
||||
qt/moc_transactiondescdialog.cpp \
|
||||
qt/moc_transactionfilterproxy.cpp \
|
||||
qt/moc_transactiontablemodel.cpp \
|
||||
qt/moc_transactionview.cpp \
|
||||
qt/moc_utilitydialog.cpp \
|
||||
qt/moc_walletframe.cpp \
|
||||
qt/moc_walletmodel.cpp \
|
||||
qt/moc_walletview.cpp
|
||||
|
||||
BITCOIN_MM = \
|
||||
qt/macdockiconhandler.mm \
|
||||
qt/macnotificationhandler.mm
|
||||
|
||||
QT_MOC = \
|
||||
qt/bitcoin.moc \
|
||||
qt/bitcoinamountfield.moc \
|
||||
qt/intro.moc \
|
||||
qt/overviewpage.moc \
|
||||
qt/rpcconsole.moc
|
||||
|
||||
QT_QRC_CPP = qt/qrc_bitcoin.cpp
|
||||
QT_QRC = qt/bitcoin.qrc
|
||||
QT_QRC_LOCALE_CPP = qt/qrc_bitcoin_locale.cpp
|
||||
QT_QRC_LOCALE = qt/bitcoin_locale.qrc
|
||||
|
||||
PROTOBUF_CC = qt/paymentrequest.pb.cc
|
||||
PROTOBUF_H = qt/paymentrequest.pb.h
|
||||
PROTOBUF_PROTO = qt/paymentrequest.proto
|
||||
|
||||
BITCOIN_QT_H = \
|
||||
qt/addressbookpage.h \
|
||||
qt/addresstablemodel.h \
|
||||
qt/askpassphrasedialog.h \
|
||||
qt/bitcoinaddressvalidator.h \
|
||||
qt/bitcoinamountfield.h \
|
||||
qt/bitcoingui.h \
|
||||
qt/bitcoinunits.h \
|
||||
qt/clientmodel.h \
|
||||
qt/coincontroldialog.h \
|
||||
qt/coincontroltreewidget.h \
|
||||
qt/csvmodelwriter.h \
|
||||
qt/editaddressdialog.h \
|
||||
qt/guiconstants.h \
|
||||
qt/guiutil.h \
|
||||
qt/intro.h \
|
||||
qt/macdockiconhandler.h \
|
||||
qt/macnotificationhandler.h \
|
||||
qt/networkstyle.h \
|
||||
qt/notificator.h \
|
||||
qt/openuridialog.h \
|
||||
qt/optionsdialog.h \
|
||||
qt/optionsmodel.h \
|
||||
qt/overviewpage.h \
|
||||
qt/paymentrequestplus.h \
|
||||
qt/paymentserver.h \
|
||||
qt/peertablemodel.h \
|
||||
qt/qvalidatedlineedit.h \
|
||||
qt/qvaluecombobox.h \
|
||||
qt/receivecoinsdialog.h \
|
||||
qt/receiverequestdialog.h \
|
||||
qt/recentrequeststablemodel.h \
|
||||
qt/rpcconsole.h \
|
||||
qt/sendcoinsdialog.h \
|
||||
qt/sendcoinsentry.h \
|
||||
qt/signverifymessagedialog.h \
|
||||
qt/splashscreen.h \
|
||||
qt/trafficgraphwidget.h \
|
||||
qt/transactiondesc.h \
|
||||
qt/transactiondescdialog.h \
|
||||
qt/transactionfilterproxy.h \
|
||||
qt/transactionrecord.h \
|
||||
qt/transactiontablemodel.h \
|
||||
qt/transactionview.h \
|
||||
qt/utilitydialog.h \
|
||||
qt/walletframe.h \
|
||||
qt/walletmodel.h \
|
||||
qt/walletmodeltransaction.h \
|
||||
qt/walletview.h \
|
||||
qt/winshutdownmonitor.h
|
||||
|
||||
RES_ICONS = \
|
||||
qt/res/icons/add.png \
|
||||
qt/res/icons/address-book.png \
|
||||
qt/res/icons/bitcoin.ico \
|
||||
qt/res/icons/bitcoin.png \
|
||||
qt/res/icons/bitcoin_testnet.ico \
|
||||
qt/res/icons/bitcoin_testnet.png \
|
||||
qt/res/icons/clock1.png \
|
||||
qt/res/icons/clock2.png \
|
||||
qt/res/icons/clock3.png \
|
||||
qt/res/icons/clock4.png \
|
||||
qt/res/icons/clock5.png \
|
||||
qt/res/icons/configure.png \
|
||||
qt/res/icons/connect0_16.png \
|
||||
qt/res/icons/connect1_16.png \
|
||||
qt/res/icons/connect2_16.png \
|
||||
qt/res/icons/connect3_16.png \
|
||||
qt/res/icons/connect4_16.png \
|
||||
qt/res/icons/debugwindow.png \
|
||||
qt/res/icons/edit.png \
|
||||
qt/res/icons/editcopy.png \
|
||||
qt/res/icons/editpaste.png \
|
||||
qt/res/icons/export.png \
|
||||
qt/res/icons/eye.png \
|
||||
qt/res/icons/eye_minus.png \
|
||||
qt/res/icons/eye_plus.png \
|
||||
qt/res/icons/filesave.png \
|
||||
qt/res/icons/history.png \
|
||||
qt/res/icons/key.png \
|
||||
qt/res/icons/lock_closed.png \
|
||||
qt/res/icons/lock_open.png \
|
||||
qt/res/icons/overview.png \
|
||||
qt/res/icons/qrcode.png \
|
||||
qt/res/icons/quit.png \
|
||||
qt/res/icons/receive.png \
|
||||
qt/res/icons/remove.png \
|
||||
qt/res/icons/send.png \
|
||||
qt/res/icons/synced.png \
|
||||
qt/res/icons/transaction0.png \
|
||||
qt/res/icons/transaction2.png \
|
||||
qt/res/icons/transaction_conflicted.png \
|
||||
qt/res/icons/tx_inout.png \
|
||||
qt/res/icons/tx_input.png \
|
||||
qt/res/icons/tx_output.png \
|
||||
qt/res/icons/tx_mined.png \
|
||||
qt/res/icons/unit_btc.png \
|
||||
qt/res/icons/unit_mbtc.png \
|
||||
qt/res/icons/unit_ubtc.png
|
||||
|
||||
BITCOIN_QT_CPP = \
|
||||
qt/bitcoinaddressvalidator.cpp \
|
||||
qt/bitcoinamountfield.cpp \
|
||||
qt/bitcoingui.cpp \
|
||||
qt/bitcoinunits.cpp \
|
||||
qt/clientmodel.cpp \
|
||||
qt/csvmodelwriter.cpp \
|
||||
qt/guiutil.cpp \
|
||||
qt/intro.cpp \
|
||||
qt/networkstyle.cpp \
|
||||
qt/notificator.cpp \
|
||||
qt/optionsdialog.cpp \
|
||||
qt/optionsmodel.cpp \
|
||||
qt/peertablemodel.cpp \
|
||||
qt/qvalidatedlineedit.cpp \
|
||||
qt/qvaluecombobox.cpp \
|
||||
qt/rpcconsole.cpp \
|
||||
qt/splashscreen.cpp \
|
||||
qt/trafficgraphwidget.cpp \
|
||||
qt/utilitydialog.cpp \
|
||||
qt/winshutdownmonitor.cpp
|
||||
|
||||
if ENABLE_WALLET
|
||||
BITCOIN_QT_CPP += \
|
||||
qt/addressbookpage.cpp \
|
||||
qt/addresstablemodel.cpp \
|
||||
qt/askpassphrasedialog.cpp \
|
||||
qt/coincontroldialog.cpp \
|
||||
qt/coincontroltreewidget.cpp \
|
||||
qt/editaddressdialog.cpp \
|
||||
qt/openuridialog.cpp \
|
||||
qt/overviewpage.cpp \
|
||||
qt/paymentrequestplus.cpp \
|
||||
qt/paymentserver.cpp \
|
||||
qt/receivecoinsdialog.cpp \
|
||||
qt/receiverequestdialog.cpp \
|
||||
qt/recentrequeststablemodel.cpp \
|
||||
qt/sendcoinsdialog.cpp \
|
||||
qt/sendcoinsentry.cpp \
|
||||
qt/signverifymessagedialog.cpp \
|
||||
qt/transactiondesc.cpp \
|
||||
qt/transactiondescdialog.cpp \
|
||||
qt/transactionfilterproxy.cpp \
|
||||
qt/transactionrecord.cpp \
|
||||
qt/transactiontablemodel.cpp \
|
||||
qt/transactionview.cpp \
|
||||
qt/walletframe.cpp \
|
||||
qt/walletmodel.cpp \
|
||||
qt/walletmodeltransaction.cpp \
|
||||
qt/walletview.cpp
|
||||
endif
|
||||
|
||||
RES_IMAGES = \
|
||||
qt/res/images/about.png \
|
||||
qt/res/images/splash.png \
|
||||
qt/res/images/splash_testnet.png
|
||||
|
||||
RES_MOVIES = $(wildcard qt/res/movies/spinner-*.png)
|
||||
|
||||
BITCOIN_RC = qt/res/bitcoin-qt-res.rc
|
||||
|
||||
BITCOIN_QT_INCLUDES = -I$(builddir)/qt -I$(srcdir)/qt -I$(srcdir)/qt/forms \
|
||||
-I$(builddir)/qt/forms
|
||||
|
||||
qt_libbitcoinqt_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
|
||||
$(QT_INCLUDES) $(QT_DBUS_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS)
|
||||
|
||||
qt_libbitcoinqt_a_SOURCES = $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(QT_FORMS_UI) \
|
||||
$(QT_QRC) $(QT_QRC_LOCALE) $(QT_TS) $(PROTOBUF_PROTO) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES)
|
||||
|
||||
nodist_qt_libbitcoinqt_a_SOURCES = $(QT_MOC_CPP) $(QT_MOC) $(PROTOBUF_CC) \
|
||||
$(PROTOBUF_H) $(QT_QRC_CPP) $(QT_QRC_LOCALE_CPP)
|
||||
|
||||
# forms/foo.h -> forms/ui_foo.h
|
||||
QT_FORMS_H=$(join $(dir $(QT_FORMS_UI)),$(addprefix ui_, $(notdir $(QT_FORMS_UI:.ui=.h))))
|
||||
|
||||
# Most files will depend on the forms and moc files as includes. Generate them
|
||||
# before anything else.
|
||||
$(QT_MOC): $(QT_FORMS_H)
|
||||
$(qt_libbitcoinqt_a_OBJECTS) $(qt_bitcoin_qt_OBJECTS) : | $(QT_MOC)
|
||||
|
||||
#Generating these with a half-written protobuf header leads to wacky results.
|
||||
#This makes sure it's done.
|
||||
$(QT_MOC): $(PROTOBUF_H)
|
||||
$(QT_MOC_CPP): $(PROTOBUF_H)
|
||||
|
||||
# bitcoin-qt binary #
|
||||
qt_bitcoin_qt_CPPFLAGS = $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
|
||||
$(QT_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS)
|
||||
|
||||
qt_bitcoin_qt_SOURCES = qt/bitcoin.cpp
|
||||
if TARGET_DARWIN
|
||||
qt_bitcoin_qt_SOURCES += $(BITCOIN_MM)
|
||||
endif
|
||||
if TARGET_WINDOWS
|
||||
qt_bitcoin_qt_SOURCES += $(BITCOIN_RC)
|
||||
endif
|
||||
qt_bitcoin_qt_LDADD = qt/libbitcoinqt.a $(LIBBITCOIN_SERVER)
|
||||
if ENABLE_WALLET
|
||||
qt_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET)
|
||||
endif
|
||||
qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_UNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \
|
||||
$(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1)
|
||||
qt_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
qt_bitcoin_qt_LIBTOOLFLAGS = --tag CXX
|
||||
|
||||
#locale/foo.ts -> locale/foo.qm
|
||||
QT_QM=$(QT_TS:.ts=.qm)
|
||||
|
||||
.SECONDARY: $(QT_QM)
|
||||
|
||||
qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_wallet_a_SOURCES)
|
||||
@test -n $(XGETTEXT) || echo "xgettext is required for updating translations"
|
||||
$(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) ../share/qt/extract_strings_qt.py $^
|
||||
|
||||
translate: qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM)
|
||||
@test -n $(LUPDATE) || echo "lupdate is required for updating translations"
|
||||
$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(LUPDATE) $^ -locations relative -no-obsolete -ts qt/locale/bitcoin_en.ts
|
||||
|
||||
$(QT_QRC_LOCALE_CPP): $(QT_QRC_LOCALE) $(QT_QM)
|
||||
@test -f $(RCC)
|
||||
@test -f $(@D)/$(<F) || cp -f $< $(@D)
|
||||
$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(RCC) -name bitcoin_locale $(@D)/$(<F) | \
|
||||
$(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@
|
||||
|
||||
$(QT_QRC_CPP): $(QT_QRC) $(QT_FORMS_H) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) $(PROTOBUF_H)
|
||||
@test -f $(RCC)
|
||||
$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(RCC) -name bitcoin $< | \
|
||||
$(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@
|
||||
|
||||
CLEAN_QT = $(nodist_qt_libbitcoinqt_a_SOURCES) $(QT_QM) $(QT_FORMS_H) qt/*.gcda qt/*.gcno
|
||||
|
||||
CLEANFILES += $(CLEAN_QT)
|
||||
|
||||
bitcoin_qt_clean: FORCE
|
||||
rm -f $(CLEAN_QT) $(qt_libbitcoinqt_a_OBJECTS) $(qt_bitcoin_qt_OBJECTS) qt/bitcoin-qt$(EXEEXT) $(LIBBITCOINQT)
|
||||
|
||||
bitcoin_qt : qt/bitcoin-qt$(EXEEXT)
|
||||
|
||||
ui_%.h: %.ui
|
||||
@test -f $(UIC)
|
||||
@$(MKDIR_P) $(@D)
|
||||
$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(UIC) -o $@ $< || (echo "Error creating $@"; false)
|
||||
|
||||
%.moc: %.cpp
|
||||
$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) $< | \
|
||||
$(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@
|
||||
|
||||
moc_%.cpp: %.h
|
||||
$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) $< | \
|
||||
$(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@
|
||||
|
||||
%.qm: %.ts
|
||||
@test -f $(LRELEASE)
|
||||
@$(MKDIR_P) $(@D)
|
||||
$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(LRELEASE) -silent $< -qm $@
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
bin_PROGRAMS += qt/test/test_bitcoin-qt
|
||||
TESTS += qt/test/test_bitcoin-qt
|
||||
|
||||
TEST_QT_MOC_CPP = qt/test/moc_uritests.cpp
|
||||
|
||||
if ENABLE_WALLET
|
||||
TEST_QT_MOC_CPP += qt/test/moc_paymentservertests.cpp
|
||||
endif
|
||||
|
||||
TEST_QT_H = \
|
||||
qt/test/uritests.h \
|
||||
qt/test/paymentrequestdata.h \
|
||||
qt/test/paymentservertests.h
|
||||
|
||||
qt_test_test_bitcoin_qt_CPPFLAGS = $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
|
||||
$(QT_INCLUDES) $(QT_TEST_INCLUDES) $(PROTOBUF_CFLAGS)
|
||||
|
||||
qt_test_test_bitcoin_qt_SOURCES = \
|
||||
qt/test/test_main.cpp \
|
||||
qt/test/uritests.cpp \
|
||||
$(TEST_QT_H)
|
||||
if ENABLE_WALLET
|
||||
qt_test_test_bitcoin_qt_SOURCES += \
|
||||
qt/test/paymentservertests.cpp
|
||||
endif
|
||||
|
||||
nodist_qt_test_test_bitcoin_qt_SOURCES = $(TEST_QT_MOC_CPP)
|
||||
|
||||
qt_test_test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER)
|
||||
if ENABLE_WALLET
|
||||
qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET)
|
||||
endif
|
||||
qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_UNIVALUE) $(LIBLEVELDB) \
|
||||
$(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \
|
||||
$(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1)
|
||||
qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
|
||||
CLEAN_BITCOIN_QT_TEST = $(TEST_QT_MOC_CPP) qt/test/*.gcda qt/test/*.gcno
|
||||
|
||||
CLEANFILES += $(CLEAN_BITCOIN_QT_TEST)
|
||||
|
||||
test_bitcoin_qt : qt/test/test_bitcoin-qt$(EXEEXT)
|
||||
|
||||
test_bitcoin_qt_check : qt/test/test_bitcoin-qt$(EXEEXT) FORCE
|
||||
$(MAKE) check-TESTS TESTS=$^
|
||||
|
||||
test_bitcoin_qt_clean: FORCE
|
||||
rm -f $(CLEAN_BITCOIN_QT_TEST) $(qt_test_test_bitcoin_qt_OBJECTS)
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
TESTS += test/test_bitcoin test/bitcoin-util-test.py
|
||||
bin_PROGRAMS += test/test_bitcoin
|
||||
TEST_SRCDIR = test
|
||||
TEST_BINARY=test/test_bitcoin$(EXEEXT)
|
||||
|
||||
|
||||
EXTRA_DIST += \
|
||||
test/bctest.py \
|
||||
test/bitcoin-util-test.py \
|
||||
test/data/bitcoin-util-test.json \
|
||||
test/data/blanktx.hex \
|
||||
test/data/tt-delin1-out.hex \
|
||||
test/data/tt-delout1-out.hex \
|
||||
test/data/tt-locktime317000-out.hex \
|
||||
test/data/tx394b54bb.hex \
|
||||
test/data/txcreate1.hex \
|
||||
test/data/txcreate2.hex \
|
||||
test/data/txcreatesign.hex
|
||||
|
||||
JSON_TEST_FILES = \
|
||||
test/data/script_valid.json \
|
||||
test/data/base58_keys_valid.json \
|
||||
test/data/sig_canonical.json \
|
||||
test/data/sig_noncanonical.json \
|
||||
test/data/base58_encode_decode.json \
|
||||
test/data/base58_keys_invalid.json \
|
||||
test/data/script_invalid.json \
|
||||
test/data/tx_invalid.json \
|
||||
test/data/tx_valid.json \
|
||||
test/data/sighash.json
|
||||
|
||||
RAW_TEST_FILES = test/data/alertTests.raw
|
||||
|
||||
GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h)
|
||||
|
||||
BITCOIN_TESTS =\
|
||||
test/bignum.h \
|
||||
test/alert_tests.cpp \
|
||||
test/allocator_tests.cpp \
|
||||
test/base32_tests.cpp \
|
||||
test/base58_tests.cpp \
|
||||
test/base64_tests.cpp \
|
||||
test/bloom_tests.cpp \
|
||||
test/checkblock_tests.cpp \
|
||||
test/Checkpoints_tests.cpp \
|
||||
test/coins_tests.cpp \
|
||||
test/compress_tests.cpp \
|
||||
test/crypto_tests.cpp \
|
||||
test/DoS_tests.cpp \
|
||||
test/getarg_tests.cpp \
|
||||
test/hash_tests.cpp \
|
||||
test/key_tests.cpp \
|
||||
test/main_tests.cpp \
|
||||
test/mempool_tests.cpp \
|
||||
test/miner_tests.cpp \
|
||||
test/mruset_tests.cpp \
|
||||
test/multisig_tests.cpp \
|
||||
test/netbase_tests.cpp \
|
||||
test/pmt_tests.cpp \
|
||||
test/rpc_tests.cpp \
|
||||
test/sanity_tests.cpp \
|
||||
test/script_P2SH_tests.cpp \
|
||||
test/script_tests.cpp \
|
||||
test/scriptnum_tests.cpp \
|
||||
test/serialize_tests.cpp \
|
||||
test/sighash_tests.cpp \
|
||||
test/sigopcount_tests.cpp \
|
||||
test/skiplist_tests.cpp \
|
||||
test/test_bitcoin.cpp \
|
||||
test/timedata_tests.cpp \
|
||||
test/transaction_tests.cpp \
|
||||
test/uint256_tests.cpp \
|
||||
test/univalue_tests.cpp \
|
||||
test/util_tests.cpp
|
||||
|
||||
if ENABLE_WALLET
|
||||
BITCOIN_TESTS += \
|
||||
test/accounting_tests.cpp \
|
||||
test/wallet_tests.cpp \
|
||||
test/rpc_wallet_tests.cpp
|
||||
endif
|
||||
|
||||
test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
|
||||
test_test_bitcoin_CPPFLAGS = $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS)
|
||||
test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_UNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \
|
||||
$(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1)
|
||||
if ENABLE_WALLET
|
||||
test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
|
||||
endif
|
||||
|
||||
test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
|
||||
test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static
|
||||
|
||||
nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES)
|
||||
|
||||
$(BITCOIN_TESTS): $(GENERATED_TEST_FILES)
|
||||
|
||||
CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno $(GENERATED_TEST_FILES)
|
||||
|
||||
CLEANFILES += $(CLEAN_BITCOIN_TEST)
|
||||
|
||||
bitcoin_test: $(TEST_BINARY)
|
||||
|
||||
bitcoin_test_check: $(TEST_BINARY) FORCE
|
||||
$(MAKE) check-TESTS TESTS=$^
|
||||
|
||||
bitcoin_test_clean : FORCE
|
||||
rm -f $(CLEAN_BITCOIN_TEST) $(test_test_bitcoin_OBJECTS) $(TEST_BINARY)
|
||||
|
||||
check-local:
|
||||
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check
|
||||
|
||||
%.json.h: %.json
|
||||
@$(MKDIR_P) $(@D)
|
||||
@echo "namespace json_tests{" > $@
|
||||
@echo "static unsigned const char $(*F)[] = {" >> $@
|
||||
@$(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' >> $@
|
||||
@echo "};};" >> $@
|
||||
@echo "Generated $@"
|
||||
|
||||
%.raw.h: %.raw
|
||||
@$(MKDIR_P) $(@D)
|
||||
@echo "namespace alert_tests{" > $@
|
||||
@echo "static unsigned const char $(*F)[] = {" >> $@
|
||||
@$(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' >> $@
|
||||
@echo "};};" >> $@
|
||||
@echo "Generated $@"
|
||||
490
src/addrman.cpp
490
src/addrman.cpp
|
|
@ -1,490 +0,0 @@
|
|||
// Copyright (c) 2012 Pieter Wuille
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "addrman.h"
|
||||
|
||||
#include "hash.h"
|
||||
#include "serialize.h"
|
||||
#include "streams.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int CAddrInfo::GetTriedBucket(const uint256& nKey) const
|
||||
{
|
||||
uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << GetKey()).GetHash().GetLow64();
|
||||
uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << GetGroup() << (hash1 % ADDRMAN_TRIED_BUCKETS_PER_GROUP)).GetHash().GetLow64();
|
||||
return hash2 % ADDRMAN_TRIED_BUCKET_COUNT;
|
||||
}
|
||||
|
||||
int CAddrInfo::GetNewBucket(const uint256& nKey, const CNetAddr& src) const
|
||||
{
|
||||
std::vector<unsigned char> vchSourceGroupKey = src.GetGroup();
|
||||
uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << GetGroup() << vchSourceGroupKey).GetHash().GetLow64();
|
||||
uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP)).GetHash().GetLow64();
|
||||
return hash2 % ADDRMAN_NEW_BUCKET_COUNT;
|
||||
}
|
||||
|
||||
int CAddrInfo::GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const
|
||||
{
|
||||
uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << (fNew ? 'N' : 'K') << nBucket << GetKey()).GetHash().GetLow64();
|
||||
return hash1 % ADDRMAN_BUCKET_SIZE;
|
||||
}
|
||||
|
||||
bool CAddrInfo::IsTerrible(int64_t nNow) const
|
||||
{
|
||||
if (nLastTry && nLastTry >= nNow - 60) // never remove things tried in the last minute
|
||||
return false;
|
||||
|
||||
if (nTime > nNow + 10 * 60) // came in a flying DeLorean
|
||||
return true;
|
||||
|
||||
if (nTime == 0 || nNow - nTime > ADDRMAN_HORIZON_DAYS * 24 * 60 * 60) // not seen in recent history
|
||||
return true;
|
||||
|
||||
if (nLastSuccess == 0 && nAttempts >= ADDRMAN_RETRIES) // tried N times and never a success
|
||||
return true;
|
||||
|
||||
if (nNow - nLastSuccess > ADDRMAN_MIN_FAIL_DAYS * 24 * 60 * 60 && nAttempts >= ADDRMAN_MAX_FAILURES) // N successive failures in the last week
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
double CAddrInfo::GetChance(int64_t nNow) const
|
||||
{
|
||||
double fChance = 1.0;
|
||||
|
||||
int64_t nSinceLastSeen = nNow - nTime;
|
||||
int64_t nSinceLastTry = nNow - nLastTry;
|
||||
|
||||
if (nSinceLastSeen < 0)
|
||||
nSinceLastSeen = 0;
|
||||
if (nSinceLastTry < 0)
|
||||
nSinceLastTry = 0;
|
||||
|
||||
// deprioritize very recent attempts away
|
||||
if (nSinceLastTry < 60 * 10)
|
||||
fChance *= 0.01;
|
||||
|
||||
// deprioritize 66% after each failed attempt, but at most 1/28th to avoid the search taking forever or overly penalizing outages.
|
||||
fChance *= pow(0.66, min(nAttempts, 8));
|
||||
|
||||
return fChance;
|
||||
}
|
||||
|
||||
CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int* pnId)
|
||||
{
|
||||
std::map<CNetAddr, int>::iterator it = mapAddr.find(addr);
|
||||
if (it == mapAddr.end())
|
||||
return NULL;
|
||||
if (pnId)
|
||||
*pnId = (*it).second;
|
||||
std::map<int, CAddrInfo>::iterator it2 = mapInfo.find((*it).second);
|
||||
if (it2 != mapInfo.end())
|
||||
return &(*it2).second;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CAddrInfo* CAddrMan::Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId)
|
||||
{
|
||||
int nId = nIdCount++;
|
||||
mapInfo[nId] = CAddrInfo(addr, addrSource);
|
||||
mapAddr[addr] = nId;
|
||||
mapInfo[nId].nRandomPos = vRandom.size();
|
||||
vRandom.push_back(nId);
|
||||
if (pnId)
|
||||
*pnId = nId;
|
||||
return &mapInfo[nId];
|
||||
}
|
||||
|
||||
void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2)
|
||||
{
|
||||
if (nRndPos1 == nRndPos2)
|
||||
return;
|
||||
|
||||
assert(nRndPos1 < vRandom.size() && nRndPos2 < vRandom.size());
|
||||
|
||||
int nId1 = vRandom[nRndPos1];
|
||||
int nId2 = vRandom[nRndPos2];
|
||||
|
||||
assert(mapInfo.count(nId1) == 1);
|
||||
assert(mapInfo.count(nId2) == 1);
|
||||
|
||||
mapInfo[nId1].nRandomPos = nRndPos2;
|
||||
mapInfo[nId2].nRandomPos = nRndPos1;
|
||||
|
||||
vRandom[nRndPos1] = nId2;
|
||||
vRandom[nRndPos2] = nId1;
|
||||
}
|
||||
|
||||
void CAddrMan::Delete(int nId)
|
||||
{
|
||||
assert(mapInfo.count(nId) != 0);
|
||||
CAddrInfo& info = mapInfo[nId];
|
||||
assert(!info.fInTried);
|
||||
assert(info.nRefCount == 0);
|
||||
|
||||
SwapRandom(info.nRandomPos, vRandom.size() - 1);
|
||||
vRandom.pop_back();
|
||||
mapAddr.erase(info);
|
||||
mapInfo.erase(nId);
|
||||
nNew--;
|
||||
}
|
||||
|
||||
void CAddrMan::ClearNew(int nUBucket, int nUBucketPos)
|
||||
{
|
||||
// if there is an entry in the specified bucket, delete it.
|
||||
if (vvNew[nUBucket][nUBucketPos] != -1) {
|
||||
int nIdDelete = vvNew[nUBucket][nUBucketPos];
|
||||
CAddrInfo& infoDelete = mapInfo[nIdDelete];
|
||||
assert(infoDelete.nRefCount > 0);
|
||||
infoDelete.nRefCount--;
|
||||
vvNew[nUBucket][nUBucketPos] = -1;
|
||||
if (infoDelete.nRefCount == 0) {
|
||||
Delete(nIdDelete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CAddrMan::MakeTried(CAddrInfo& info, int nId)
|
||||
{
|
||||
// remove the entry from all new buckets
|
||||
for (int bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) {
|
||||
int pos = info.GetBucketPosition(nKey, true, bucket);
|
||||
if (vvNew[bucket][pos] == nId) {
|
||||
vvNew[bucket][pos] = -1;
|
||||
info.nRefCount--;
|
||||
}
|
||||
}
|
||||
nNew--;
|
||||
|
||||
assert(info.nRefCount == 0);
|
||||
|
||||
// which tried bucket to move the entry to
|
||||
int nKBucket = info.GetTriedBucket(nKey);
|
||||
int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);
|
||||
|
||||
// first make space to add it (the existing tried entry there is moved to new, deleting whatever is there).
|
||||
if (vvTried[nKBucket][nKBucketPos] != -1) {
|
||||
// find an item to evict
|
||||
int nIdEvict = vvTried[nKBucket][nKBucketPos];
|
||||
assert(mapInfo.count(nIdEvict) == 1);
|
||||
CAddrInfo& infoOld = mapInfo[nIdEvict];
|
||||
|
||||
// Remove the to-be-evicted item from the tried set.
|
||||
infoOld.fInTried = false;
|
||||
vvTried[nKBucket][nKBucketPos] = -1;
|
||||
nTried--;
|
||||
|
||||
// find which new bucket it belongs to
|
||||
int nUBucket = infoOld.GetNewBucket(nKey);
|
||||
int nUBucketPos = infoOld.GetBucketPosition(nKey, true, nUBucket);
|
||||
ClearNew(nUBucket, nUBucketPos);
|
||||
assert(vvNew[nUBucket][nUBucketPos] == -1);
|
||||
|
||||
// Enter it into the new set again.
|
||||
infoOld.nRefCount = 1;
|
||||
vvNew[nUBucket][nUBucketPos] = nIdEvict;
|
||||
nNew++;
|
||||
}
|
||||
assert(vvTried[nKBucket][nKBucketPos] == -1);
|
||||
|
||||
vvTried[nKBucket][nKBucketPos] = nId;
|
||||
nTried++;
|
||||
info.fInTried = true;
|
||||
}
|
||||
|
||||
void CAddrMan::Good_(const CService& addr, int64_t nTime)
|
||||
{
|
||||
int nId;
|
||||
CAddrInfo* pinfo = Find(addr, &nId);
|
||||
|
||||
// if not found, bail out
|
||||
if (!pinfo)
|
||||
return;
|
||||
|
||||
CAddrInfo& info = *pinfo;
|
||||
|
||||
// check whether we are talking about the exact same CService (including same port)
|
||||
if (info != addr)
|
||||
return;
|
||||
|
||||
// update info
|
||||
info.nLastSuccess = nTime;
|
||||
info.nLastTry = nTime;
|
||||
info.nAttempts = 0;
|
||||
// nTime is not updated here, to avoid leaking information about
|
||||
// currently-connected peers.
|
||||
|
||||
// if it is already in the tried set, don't do anything else
|
||||
if (info.fInTried)
|
||||
return;
|
||||
|
||||
// find a bucket it is in now
|
||||
int nRnd = GetRandInt(ADDRMAN_NEW_BUCKET_COUNT);
|
||||
int nUBucket = -1;
|
||||
for (unsigned int n = 0; n < ADDRMAN_NEW_BUCKET_COUNT; n++) {
|
||||
int nB = (n + nRnd) % ADDRMAN_NEW_BUCKET_COUNT;
|
||||
int nBpos = info.GetBucketPosition(nKey, true, nB);
|
||||
if (vvNew[nB][nBpos] == nId) {
|
||||
nUBucket = nB;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if no bucket is found, something bad happened;
|
||||
// TODO: maybe re-add the node, but for now, just bail out
|
||||
if (nUBucket == -1)
|
||||
return;
|
||||
|
||||
LogPrint("addrman", "Moving %s to tried\n", addr.ToString());
|
||||
|
||||
// move nId to the tried tables
|
||||
MakeTried(info, nId);
|
||||
}
|
||||
|
||||
bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty)
|
||||
{
|
||||
if (!addr.IsRoutable())
|
||||
return false;
|
||||
|
||||
bool fNew = false;
|
||||
int nId;
|
||||
CAddrInfo* pinfo = Find(addr, &nId);
|
||||
|
||||
if (pinfo) {
|
||||
// periodically update nTime
|
||||
bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
|
||||
int64_t nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
|
||||
if (addr.nTime && (!pinfo->nTime || pinfo->nTime < addr.nTime - nUpdateInterval - nTimePenalty))
|
||||
pinfo->nTime = max((int64_t)0, addr.nTime - nTimePenalty);
|
||||
|
||||
// add services
|
||||
pinfo->nServices |= addr.nServices;
|
||||
|
||||
// do not update if no new information is present
|
||||
if (!addr.nTime || (pinfo->nTime && addr.nTime <= pinfo->nTime))
|
||||
return false;
|
||||
|
||||
// do not update if the entry was already in the "tried" table
|
||||
if (pinfo->fInTried)
|
||||
return false;
|
||||
|
||||
// do not update if the max reference count is reached
|
||||
if (pinfo->nRefCount == ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
|
||||
return false;
|
||||
|
||||
// stochastic test: previous nRefCount == N: 2^N times harder to increase it
|
||||
int nFactor = 1;
|
||||
for (int n = 0; n < pinfo->nRefCount; n++)
|
||||
nFactor *= 2;
|
||||
if (nFactor > 1 && (GetRandInt(nFactor) != 0))
|
||||
return false;
|
||||
} else {
|
||||
pinfo = Create(addr, source, &nId);
|
||||
pinfo->nTime = max((int64_t)0, (int64_t)pinfo->nTime - nTimePenalty);
|
||||
nNew++;
|
||||
fNew = true;
|
||||
}
|
||||
|
||||
int nUBucket = pinfo->GetNewBucket(nKey, source);
|
||||
int nUBucketPos = pinfo->GetBucketPosition(nKey, true, nUBucket);
|
||||
if (vvNew[nUBucket][nUBucketPos] != nId) {
|
||||
bool fInsert = vvNew[nUBucket][nUBucketPos] == -1;
|
||||
if (!fInsert) {
|
||||
CAddrInfo& infoExisting = mapInfo[vvNew[nUBucket][nUBucketPos]];
|
||||
if (infoExisting.IsTerrible() || (infoExisting.nRefCount > 1 && pinfo->nRefCount == 0)) {
|
||||
// Overwrite the existing new table entry.
|
||||
fInsert = true;
|
||||
}
|
||||
}
|
||||
if (fInsert) {
|
||||
ClearNew(nUBucket, nUBucketPos);
|
||||
pinfo->nRefCount++;
|
||||
vvNew[nUBucket][nUBucketPos] = nId;
|
||||
} else {
|
||||
if (pinfo->nRefCount == 0) {
|
||||
Delete(nId);
|
||||
}
|
||||
}
|
||||
}
|
||||
return fNew;
|
||||
}
|
||||
|
||||
void CAddrMan::Attempt_(const CService& addr, int64_t nTime)
|
||||
{
|
||||
CAddrInfo* pinfo = Find(addr);
|
||||
|
||||
// if not found, bail out
|
||||
if (!pinfo)
|
||||
return;
|
||||
|
||||
CAddrInfo& info = *pinfo;
|
||||
|
||||
// check whether we are talking about the exact same CService (including same port)
|
||||
if (info != addr)
|
||||
return;
|
||||
|
||||
// update info
|
||||
info.nLastTry = nTime;
|
||||
info.nAttempts++;
|
||||
}
|
||||
|
||||
CAddress CAddrMan::Select_()
|
||||
{
|
||||
if (size() == 0)
|
||||
return CAddress();
|
||||
|
||||
// Use a 50% chance for choosing between tried and new table entries.
|
||||
if (nTried > 0 && (nNew == 0 || GetRandInt(2) == 0)) {
|
||||
// use a tried node
|
||||
double fChanceFactor = 1.0;
|
||||
while (1) {
|
||||
int nKBucket = GetRandInt(ADDRMAN_TRIED_BUCKET_COUNT);
|
||||
int nKBucketPos = GetRandInt(ADDRMAN_BUCKET_SIZE);
|
||||
if (vvTried[nKBucket][nKBucketPos] == -1)
|
||||
continue;
|
||||
int nId = vvTried[nKBucket][nKBucketPos];
|
||||
assert(mapInfo.count(nId) == 1);
|
||||
CAddrInfo& info = mapInfo[nId];
|
||||
if (GetRandInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30))
|
||||
return info;
|
||||
fChanceFactor *= 1.2;
|
||||
}
|
||||
} else {
|
||||
// use a new node
|
||||
double fChanceFactor = 1.0;
|
||||
while (1) {
|
||||
int nUBucket = GetRandInt(ADDRMAN_NEW_BUCKET_COUNT);
|
||||
int nUBucketPos = GetRandInt(ADDRMAN_BUCKET_SIZE);
|
||||
if (vvNew[nUBucket][nUBucketPos] == -1)
|
||||
continue;
|
||||
int nId = vvNew[nUBucket][nUBucketPos];
|
||||
assert(mapInfo.count(nId) == 1);
|
||||
CAddrInfo& info = mapInfo[nId];
|
||||
if (GetRandInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30))
|
||||
return info;
|
||||
fChanceFactor *= 1.2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ADDRMAN
|
||||
int CAddrMan::Check_()
|
||||
{
|
||||
std::set<int> setTried;
|
||||
std::map<int, int> mapNew;
|
||||
|
||||
if (vRandom.size() != nTried + nNew)
|
||||
return -7;
|
||||
|
||||
for (std::map<int, CAddrInfo>::iterator it = mapInfo.begin(); it != mapInfo.end(); it++) {
|
||||
int n = (*it).first;
|
||||
CAddrInfo& info = (*it).second;
|
||||
if (info.fInTried) {
|
||||
if (!info.nLastSuccess)
|
||||
return -1;
|
||||
if (info.nRefCount)
|
||||
return -2;
|
||||
setTried.insert(n);
|
||||
} else {
|
||||
if (info.nRefCount < 0 || info.nRefCount > ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
|
||||
return -3;
|
||||
if (!info.nRefCount)
|
||||
return -4;
|
||||
mapNew[n] = info.nRefCount;
|
||||
}
|
||||
if (mapAddr[info] != n)
|
||||
return -5;
|
||||
if (info.nRandomPos < 0 || info.nRandomPos >= vRandom.size() || vRandom[info.nRandomPos] != n)
|
||||
return -14;
|
||||
if (info.nLastTry < 0)
|
||||
return -6;
|
||||
if (info.nLastSuccess < 0)
|
||||
return -8;
|
||||
}
|
||||
|
||||
if (setTried.size() != nTried)
|
||||
return -9;
|
||||
if (mapNew.size() != nNew)
|
||||
return -10;
|
||||
|
||||
for (int n = 0; n < ADDRMAN_TRIED_BUCKET_COUNT; n++) {
|
||||
for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
|
||||
if (vvTried[n][i] != -1) {
|
||||
if (!setTried.count(vvTried[n][i]))
|
||||
return -11;
|
||||
if (mapInfo[vvTried[n][i]].GetTriedBucket(nKey) != n)
|
||||
return -17;
|
||||
if (mapInfo[vvTried[n][i]].GetBucketPosition(nKey, false, n) != i)
|
||||
return -18;
|
||||
setTried.erase(vvTried[n][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int n = 0; n < ADDRMAN_NEW_BUCKET_COUNT; n++) {
|
||||
for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
|
||||
if (vvNew[n][i] != -1) {
|
||||
if (!mapNew.count(vvNew[n][i]))
|
||||
return -12;
|
||||
if (mapInfo[vvNew[n][i]].GetBucketPosition(nKey, true, n) != i)
|
||||
return -19;
|
||||
if (--mapNew[vvNew[n][i]] == 0)
|
||||
mapNew.erase(vvNew[n][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (setTried.size())
|
||||
return -13;
|
||||
if (mapNew.size())
|
||||
return -15;
|
||||
if (nKey.IsNull())
|
||||
return -16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void CAddrMan::GetAddr_(std::vector<CAddress>& vAddr)
|
||||
{
|
||||
unsigned int nNodes = ADDRMAN_GETADDR_MAX_PCT * vRandom.size() / 100;
|
||||
if (nNodes > ADDRMAN_GETADDR_MAX)
|
||||
nNodes = ADDRMAN_GETADDR_MAX;
|
||||
|
||||
// gather a list of random nodes, skipping those of low quality
|
||||
for (unsigned int n = 0; n < vRandom.size(); n++) {
|
||||
if (vAddr.size() >= nNodes)
|
||||
break;
|
||||
|
||||
int nRndPos = GetRandInt(vRandom.size() - n) + n;
|
||||
SwapRandom(n, nRndPos);
|
||||
assert(mapInfo.count(vRandom[n]) == 1);
|
||||
|
||||
const CAddrInfo& ai = mapInfo[vRandom[n]];
|
||||
if (!ai.IsTerrible())
|
||||
vAddr.push_back(ai);
|
||||
}
|
||||
}
|
||||
|
||||
void CAddrMan::Connected_(const CService& addr, int64_t nTime)
|
||||
{
|
||||
CAddrInfo* pinfo = Find(addr);
|
||||
|
||||
// if not found, bail out
|
||||
if (!pinfo)
|
||||
return;
|
||||
|
||||
CAddrInfo& info = *pinfo;
|
||||
|
||||
// check whether we are talking about the exact same CService (including same port)
|
||||
if (info != addr)
|
||||
return;
|
||||
|
||||
// update info
|
||||
int64_t nUpdateInterval = 20 * 60;
|
||||
if (nTime - info.nTime > nUpdateInterval)
|
||||
info.nTime = nTime;
|
||||
}
|
||||
573
src/addrman.h
573
src/addrman.h
|
|
@ -1,573 +0,0 @@
|
|||
// Copyright (c) 2012 Pieter Wuille
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_ADDRMAN_H
|
||||
#define BITCOIN_ADDRMAN_H
|
||||
|
||||
#include "netbase.h"
|
||||
#include "protocol.h"
|
||||
#include "random.h"
|
||||
#include "sync.h"
|
||||
#include "timedata.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* Extended statistics about a CAddress
|
||||
*/
|
||||
class CAddrInfo : public CAddress
|
||||
{
|
||||
private:
|
||||
//! where knowledge about this address first came from
|
||||
CNetAddr source;
|
||||
|
||||
//! last successful connection by us
|
||||
int64_t nLastSuccess;
|
||||
|
||||
//! last try whatsoever by us:
|
||||
// int64_t CAddress::nLastTry
|
||||
|
||||
//! connection attempts since last successful attempt
|
||||
int nAttempts;
|
||||
|
||||
//! reference count in new sets (memory only)
|
||||
int nRefCount;
|
||||
|
||||
//! in tried set? (memory only)
|
||||
bool fInTried;
|
||||
|
||||
//! position in vRandom
|
||||
int nRandomPos;
|
||||
|
||||
friend class CAddrMan;
|
||||
|
||||
public:
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(*(CAddress*)this);
|
||||
READWRITE(source);
|
||||
READWRITE(nLastSuccess);
|
||||
READWRITE(nAttempts);
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
nLastSuccess = 0;
|
||||
nLastTry = 0;
|
||||
nAttempts = 0;
|
||||
nRefCount = 0;
|
||||
fInTried = false;
|
||||
nRandomPos = -1;
|
||||
}
|
||||
|
||||
CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CAddrInfo() : CAddress(), source()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
//! Calculate in which "tried" bucket this entry belongs
|
||||
int GetTriedBucket(const uint256 &nKey) const;
|
||||
|
||||
//! Calculate in which "new" bucket this entry belongs, given a certain source
|
||||
int GetNewBucket(const uint256 &nKey, const CNetAddr& src) const;
|
||||
|
||||
//! Calculate in which "new" bucket this entry belongs, using its default source
|
||||
int GetNewBucket(const uint256 &nKey) const
|
||||
{
|
||||
return GetNewBucket(nKey, source);
|
||||
}
|
||||
|
||||
//! Calculate in which position of a bucket to store this entry.
|
||||
int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const;
|
||||
|
||||
//! Determine whether the statistics about this entry are bad enough so that it can just be deleted
|
||||
bool IsTerrible(int64_t nNow = GetAdjustedTime()) const;
|
||||
|
||||
//! Calculate the relative chance this entry should be given when selecting nodes to connect to
|
||||
double GetChance(int64_t nNow = GetAdjustedTime()) const;
|
||||
|
||||
};
|
||||
|
||||
/** Stochastic address manager
|
||||
*
|
||||
* Design goals:
|
||||
* * Keep the address tables in-memory, and asynchronously dump the entire to able in peers.dat.
|
||||
* * Make sure no (localized) attacker can fill the entire table with his nodes/addresses.
|
||||
*
|
||||
* To that end:
|
||||
* * Addresses are organized into buckets.
|
||||
* * Address that have not yet been tried go into 1024 "new" buckets.
|
||||
* * Based on the address range (/16 for IPv4) of source of the information, 64 buckets are selected at random
|
||||
* * The actual bucket is chosen from one of these, based on the range the address itself is located.
|
||||
* * One single address can occur in up to 8 different buckets, to increase selection chances for addresses that
|
||||
* are seen frequently. The chance for increasing this multiplicity decreases exponentially.
|
||||
* * When adding a new address to a full bucket, a randomly chosen entry (with a bias favoring less recently seen
|
||||
* ones) is removed from it first.
|
||||
* * Addresses of nodes that are known to be accessible go into 256 "tried" buckets.
|
||||
* * Each address range selects at random 8 of these buckets.
|
||||
* * The actual bucket is chosen from one of these, based on the full address.
|
||||
* * When adding a new good address to a full bucket, a randomly chosen entry (with a bias favoring less recently
|
||||
* tried ones) is evicted from it, back to the "new" buckets.
|
||||
* * Bucket selection is based on cryptographic hashing, using a randomly-generated 256-bit key, which should not
|
||||
* be observable by adversaries.
|
||||
* * Several indexes are kept for high performance. Defining DEBUG_ADDRMAN will introduce frequent (and expensive)
|
||||
* consistency checks for the entire data structure.
|
||||
*/
|
||||
|
||||
//! total number of buckets for tried addresses
|
||||
#define ADDRMAN_TRIED_BUCKET_COUNT 256
|
||||
|
||||
//! total number of buckets for new addresses
|
||||
#define ADDRMAN_NEW_BUCKET_COUNT 1024
|
||||
|
||||
//! maximum allowed number of entries in buckets for new and tried addresses
|
||||
#define ADDRMAN_BUCKET_SIZE 64
|
||||
|
||||
//! over how many buckets entries with tried addresses from a single group (/16 for IPv4) are spread
|
||||
#define ADDRMAN_TRIED_BUCKETS_PER_GROUP 8
|
||||
|
||||
//! over how many buckets entries with new addresses originating from a single group are spread
|
||||
#define ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP 64
|
||||
|
||||
//! in how many buckets for entries with new addresses a single address may occur
|
||||
#define ADDRMAN_NEW_BUCKETS_PER_ADDRESS 8
|
||||
|
||||
//! how old addresses can maximally be
|
||||
#define ADDRMAN_HORIZON_DAYS 30
|
||||
|
||||
//! after how many failed attempts we give up on a new node
|
||||
#define ADDRMAN_RETRIES 3
|
||||
|
||||
//! how many successive failures are allowed ...
|
||||
#define ADDRMAN_MAX_FAILURES 10
|
||||
|
||||
//! ... in at least this many days
|
||||
#define ADDRMAN_MIN_FAIL_DAYS 7
|
||||
|
||||
//! the maximum percentage of nodes to return in a getaddr call
|
||||
#define ADDRMAN_GETADDR_MAX_PCT 23
|
||||
|
||||
//! the maximum number of nodes to return in a getaddr call
|
||||
#define ADDRMAN_GETADDR_MAX 2500
|
||||
|
||||
/**
|
||||
* Stochastical (IP) address manager
|
||||
*/
|
||||
class CAddrMan
|
||||
{
|
||||
private:
|
||||
//! critical section to protect the inner data structures
|
||||
mutable CCriticalSection cs;
|
||||
|
||||
//! secret key to randomize bucket select with
|
||||
uint256 nKey;
|
||||
|
||||
//! last used nId
|
||||
int nIdCount;
|
||||
|
||||
//! table with information about all nIds
|
||||
std::map<int, CAddrInfo> mapInfo;
|
||||
|
||||
//! find an nId based on its network address
|
||||
std::map<CNetAddr, int> mapAddr;
|
||||
|
||||
//! randomly-ordered vector of all nIds
|
||||
std::vector<int> vRandom;
|
||||
|
||||
// number of "tried" entries
|
||||
int nTried;
|
||||
|
||||
//! list of "tried" buckets
|
||||
int vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE];
|
||||
|
||||
//! number of (unique) "new" entries
|
||||
int nNew;
|
||||
|
||||
//! list of "new" buckets
|
||||
int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE];
|
||||
|
||||
protected:
|
||||
|
||||
//! Find an entry.
|
||||
CAddrInfo* Find(const CNetAddr& addr, int *pnId = NULL);
|
||||
|
||||
//! find an entry, creating it if necessary.
|
||||
//! nTime and nServices of the found node are updated, if necessary.
|
||||
CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId = NULL);
|
||||
|
||||
//! Swap two elements in vRandom.
|
||||
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2);
|
||||
|
||||
//! Move an entry from the "new" table(s) to the "tried" table
|
||||
void MakeTried(CAddrInfo& info, int nId);
|
||||
|
||||
//! Delete an entry. It must not be in tried, and have refcount 0.
|
||||
void Delete(int nId);
|
||||
|
||||
//! Clear a position in a "new" table. This is the only place where entries are actually deleted.
|
||||
void ClearNew(int nUBucket, int nUBucketPos);
|
||||
|
||||
//! Mark an entry "good", possibly moving it from "new" to "tried".
|
||||
void Good_(const CService &addr, int64_t nTime);
|
||||
|
||||
//! Add an entry to the "new" table.
|
||||
bool Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty);
|
||||
|
||||
//! Mark an entry as attempted to connect.
|
||||
void Attempt_(const CService &addr, int64_t nTime);
|
||||
|
||||
//! Select an address to connect to.
|
||||
//! nUnkBias determines how much to favor new addresses over tried ones (min=0, max=100)
|
||||
CAddress Select_();
|
||||
|
||||
#ifdef DEBUG_ADDRMAN
|
||||
//! Perform consistency check. Returns an error code or zero.
|
||||
int Check_();
|
||||
#endif
|
||||
|
||||
//! Select several addresses at once.
|
||||
void GetAddr_(std::vector<CAddress> &vAddr);
|
||||
|
||||
//! Mark an entry as currently-connected-to.
|
||||
void Connected_(const CService &addr, int64_t nTime);
|
||||
|
||||
public:
|
||||
/**
|
||||
* serialized format:
|
||||
* * version byte (currently 1)
|
||||
* * 0x20 + nKey (serialized as if it were a vector, for backward compatibility)
|
||||
* * nNew
|
||||
* * nTried
|
||||
* * number of "new" buckets XOR 2**30
|
||||
* * all nNew addrinfos in vvNew
|
||||
* * all nTried addrinfos in vvTried
|
||||
* * for each bucket:
|
||||
* * number of elements
|
||||
* * for each element: index
|
||||
*
|
||||
* 2**30 is xorred with the number of buckets to make addrman deserializer v0 detect it
|
||||
* as incompatible. This is necessary because it did not check the version number on
|
||||
* deserialization.
|
||||
*
|
||||
* Notice that vvTried, mapAddr and vVector are never encoded explicitly;
|
||||
* they are instead reconstructed from the other information.
|
||||
*
|
||||
* vvNew is serialized, but only used if ADDRMAN_UNKOWN_BUCKET_COUNT didn't change,
|
||||
* otherwise it is reconstructed as well.
|
||||
*
|
||||
* This format is more complex, but significantly smaller (at most 1.5 MiB), and supports
|
||||
* changes to the ADDRMAN_ parameters without breaking the on-disk structure.
|
||||
*
|
||||
* We don't use ADD_SERIALIZE_METHODS since the serialization and deserialization code has
|
||||
* very little in common.
|
||||
*/
|
||||
template<typename Stream>
|
||||
void Serialize(Stream &s, int nType, int nVersionDummy) const
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
unsigned char nVersion = 1;
|
||||
s << nVersion;
|
||||
s << ((unsigned char)32);
|
||||
s << nKey;
|
||||
s << nNew;
|
||||
s << nTried;
|
||||
|
||||
int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
|
||||
s << nUBuckets;
|
||||
std::map<int, int> mapUnkIds;
|
||||
int nIds = 0;
|
||||
for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end(); it++) {
|
||||
mapUnkIds[(*it).first] = nIds;
|
||||
const CAddrInfo &info = (*it).second;
|
||||
if (info.nRefCount) {
|
||||
assert(nIds != nNew); // this means nNew was wrong, oh ow
|
||||
s << info;
|
||||
nIds++;
|
||||
}
|
||||
}
|
||||
nIds = 0;
|
||||
for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end(); it++) {
|
||||
const CAddrInfo &info = (*it).second;
|
||||
if (info.fInTried) {
|
||||
assert(nIds != nTried); // this means nTried was wrong, oh ow
|
||||
s << info;
|
||||
nIds++;
|
||||
}
|
||||
}
|
||||
for (int bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) {
|
||||
int nSize = 0;
|
||||
for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
|
||||
if (vvNew[bucket][i] != -1)
|
||||
nSize++;
|
||||
}
|
||||
s << nSize;
|
||||
for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
|
||||
if (vvNew[bucket][i] != -1) {
|
||||
int nIndex = mapUnkIds[vvNew[bucket][i]];
|
||||
s << nIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s, int nType, int nVersionDummy)
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
Clear();
|
||||
|
||||
unsigned char nVersion;
|
||||
s >> nVersion;
|
||||
unsigned char nKeySize;
|
||||
s >> nKeySize;
|
||||
if (nKeySize != 32) throw std::ios_base::failure("Incorrect keysize in addrman deserialization");
|
||||
s >> nKey;
|
||||
s >> nNew;
|
||||
s >> nTried;
|
||||
int nUBuckets = 0;
|
||||
s >> nUBuckets;
|
||||
if (nVersion != 0) {
|
||||
nUBuckets ^= (1 << 30);
|
||||
}
|
||||
|
||||
// Deserialize entries from the new table.
|
||||
for (int n = 0; n < nNew; n++) {
|
||||
CAddrInfo &info = mapInfo[n];
|
||||
s >> info;
|
||||
mapAddr[info] = n;
|
||||
info.nRandomPos = vRandom.size();
|
||||
vRandom.push_back(n);
|
||||
if (nVersion != 1 || nUBuckets != ADDRMAN_NEW_BUCKET_COUNT) {
|
||||
// In case the new table data cannot be used (nVersion unknown, or bucket count wrong),
|
||||
// immediately try to give them a reference based on their primary source address.
|
||||
int nUBucket = info.GetNewBucket(nKey);
|
||||
int nUBucketPos = info.GetBucketPosition(nKey, true, nUBucket);
|
||||
if (vvNew[nUBucket][nUBucketPos] == -1) {
|
||||
vvNew[nUBucket][nUBucketPos] = n;
|
||||
info.nRefCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
nIdCount = nNew;
|
||||
|
||||
// Deserialize entries from the tried table.
|
||||
int nLost = 0;
|
||||
for (int n = 0; n < nTried; n++) {
|
||||
CAddrInfo info;
|
||||
s >> info;
|
||||
int nKBucket = info.GetTriedBucket(nKey);
|
||||
int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);
|
||||
if (vvTried[nKBucket][nKBucketPos] == -1) {
|
||||
info.nRandomPos = vRandom.size();
|
||||
info.fInTried = true;
|
||||
vRandom.push_back(nIdCount);
|
||||
mapInfo[nIdCount] = info;
|
||||
mapAddr[info] = nIdCount;
|
||||
vvTried[nKBucket][nKBucketPos] = nIdCount;
|
||||
nIdCount++;
|
||||
} else {
|
||||
nLost++;
|
||||
}
|
||||
}
|
||||
nTried -= nLost;
|
||||
|
||||
// Deserialize positions in the new table (if possible).
|
||||
for (int bucket = 0; bucket < nUBuckets; bucket++) {
|
||||
int nSize = 0;
|
||||
s >> nSize;
|
||||
for (int n = 0; n < nSize; n++) {
|
||||
int nIndex = 0;
|
||||
s >> nIndex;
|
||||
if (nIndex >= 0 && nIndex < nNew) {
|
||||
CAddrInfo &info = mapInfo[nIndex];
|
||||
int nUBucketPos = info.GetBucketPosition(nKey, true, bucket);
|
||||
if (nVersion == 1 && nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && vvNew[bucket][nUBucketPos] == -1 && info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS) {
|
||||
info.nRefCount++;
|
||||
vvNew[bucket][nUBucketPos] = nIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prune new entries with refcount 0 (as a result of collisions).
|
||||
int nLostUnk = 0;
|
||||
for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end(); ) {
|
||||
if (it->second.fInTried == false && it->second.nRefCount == 0) {
|
||||
std::map<int, CAddrInfo>::const_iterator itCopy = it++;
|
||||
Delete(itCopy->first);
|
||||
nLostUnk++;
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
if (nLost + nLostUnk > 0) {
|
||||
LogPrint("addrman", "addrman lost %i new and %i tried addresses due to collisions\n", nLostUnk, nLost);
|
||||
}
|
||||
|
||||
Check();
|
||||
}
|
||||
|
||||
unsigned int GetSerializeSize(int nType, int nVersion) const
|
||||
{
|
||||
return (CSizeComputer(nType, nVersion) << *this).size();
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
std::vector<int>().swap(vRandom);
|
||||
nKey = GetRandHash();
|
||||
for (size_t bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) {
|
||||
for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) {
|
||||
vvNew[bucket][entry] = -1;
|
||||
}
|
||||
}
|
||||
for (size_t bucket = 0; bucket < ADDRMAN_TRIED_BUCKET_COUNT; bucket++) {
|
||||
for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) {
|
||||
vvTried[bucket][entry] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
nIdCount = 0;
|
||||
nTried = 0;
|
||||
nNew = 0;
|
||||
}
|
||||
|
||||
CAddrMan()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
~CAddrMan()
|
||||
{
|
||||
nKey = uint256(0);
|
||||
}
|
||||
|
||||
//! Return the number of (unique) addresses in all tables.
|
||||
int size()
|
||||
{
|
||||
return vRandom.size();
|
||||
}
|
||||
|
||||
//! Consistency check
|
||||
void Check()
|
||||
{
|
||||
#ifdef DEBUG_ADDRMAN
|
||||
{
|
||||
LOCK(cs);
|
||||
int err;
|
||||
if ((err=Check_()))
|
||||
LogPrintf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//! Add a single address.
|
||||
bool Add(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty = 0)
|
||||
{
|
||||
bool fRet = false;
|
||||
{
|
||||
LOCK(cs);
|
||||
Check();
|
||||
fRet |= Add_(addr, source, nTimePenalty);
|
||||
Check();
|
||||
}
|
||||
if (fRet)
|
||||
LogPrint("addrman", "Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort(), source.ToString(), nTried, nNew);
|
||||
return fRet;
|
||||
}
|
||||
|
||||
//! Add multiple addresses.
|
||||
bool Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty = 0)
|
||||
{
|
||||
int nAdd = 0;
|
||||
{
|
||||
LOCK(cs);
|
||||
Check();
|
||||
for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++)
|
||||
nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0;
|
||||
Check();
|
||||
}
|
||||
if (nAdd)
|
||||
LogPrint("addrman", "Added %i addresses from %s: %i tried, %i new\n", nAdd, source.ToString(), nTried, nNew);
|
||||
return nAdd > 0;
|
||||
}
|
||||
|
||||
//! Mark an entry as accessible.
|
||||
void Good(const CService &addr, int64_t nTime = GetAdjustedTime())
|
||||
{
|
||||
{
|
||||
LOCK(cs);
|
||||
Check();
|
||||
Good_(addr, nTime);
|
||||
Check();
|
||||
}
|
||||
}
|
||||
|
||||
//! Mark an entry as connection attempted to.
|
||||
void Attempt(const CService &addr, int64_t nTime = GetAdjustedTime())
|
||||
{
|
||||
{
|
||||
LOCK(cs);
|
||||
Check();
|
||||
Attempt_(addr, nTime);
|
||||
Check();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose an address to connect to.
|
||||
* nUnkBias determines how much "new" entries are favored over "tried" ones (0-100).
|
||||
*/
|
||||
CAddress Select()
|
||||
{
|
||||
CAddress addrRet;
|
||||
{
|
||||
LOCK(cs);
|
||||
Check();
|
||||
addrRet = Select_();
|
||||
Check();
|
||||
}
|
||||
return addrRet;
|
||||
}
|
||||
|
||||
//! Return a bunch of addresses, selected at random.
|
||||
std::vector<CAddress> GetAddr()
|
||||
{
|
||||
Check();
|
||||
std::vector<CAddress> vAddr;
|
||||
{
|
||||
LOCK(cs);
|
||||
GetAddr_(vAddr);
|
||||
}
|
||||
Check();
|
||||
return vAddr;
|
||||
}
|
||||
|
||||
//! Mark an entry as currently-connected-to.
|
||||
void Connected(const CService &addr, int64_t nTime = GetAdjustedTime())
|
||||
{
|
||||
{
|
||||
LOCK(cs);
|
||||
Check();
|
||||
Connected_(addr, nTime);
|
||||
Check();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BITCOIN_ADDRMAN_H
|
||||
266
src/alert.cpp
266
src/alert.cpp
|
|
@ -1,266 +0,0 @@
|
|||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "alert.h"
|
||||
|
||||
#include "chainparams.h"
|
||||
#include "clientversion.h"
|
||||
#include "net.h"
|
||||
#include "pubkey.h"
|
||||
#include "timedata.h"
|
||||
#include "ui_interface.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
map<uint256, CAlert> mapAlerts;
|
||||
CCriticalSection cs_mapAlerts;
|
||||
|
||||
void CUnsignedAlert::SetNull()
|
||||
{
|
||||
nVersion = 1;
|
||||
nRelayUntil = 0;
|
||||
nExpiration = 0;
|
||||
nID = 0;
|
||||
nCancel = 0;
|
||||
setCancel.clear();
|
||||
nMinVer = 0;
|
||||
nMaxVer = 0;
|
||||
setSubVer.clear();
|
||||
nPriority = 0;
|
||||
|
||||
strComment.clear();
|
||||
strStatusBar.clear();
|
||||
strReserved.clear();
|
||||
}
|
||||
|
||||
std::string CUnsignedAlert::ToString() const
|
||||
{
|
||||
std::string strSetCancel;
|
||||
BOOST_FOREACH(int n, setCancel)
|
||||
strSetCancel += strprintf("%d ", n);
|
||||
std::string strSetSubVer;
|
||||
BOOST_FOREACH(std::string str, setSubVer)
|
||||
strSetSubVer += "\"" + str + "\" ";
|
||||
return strprintf(
|
||||
"CAlert(\n"
|
||||
" nVersion = %d\n"
|
||||
" nRelayUntil = %d\n"
|
||||
" nExpiration = %d\n"
|
||||
" nID = %d\n"
|
||||
" nCancel = %d\n"
|
||||
" setCancel = %s\n"
|
||||
" nMinVer = %d\n"
|
||||
" nMaxVer = %d\n"
|
||||
" setSubVer = %s\n"
|
||||
" nPriority = %d\n"
|
||||
" strComment = \"%s\"\n"
|
||||
" strStatusBar = \"%s\"\n"
|
||||
")\n",
|
||||
nVersion,
|
||||
nRelayUntil,
|
||||
nExpiration,
|
||||
nID,
|
||||
nCancel,
|
||||
strSetCancel,
|
||||
nMinVer,
|
||||
nMaxVer,
|
||||
strSetSubVer,
|
||||
nPriority,
|
||||
strComment,
|
||||
strStatusBar);
|
||||
}
|
||||
|
||||
void CAlert::SetNull()
|
||||
{
|
||||
CUnsignedAlert::SetNull();
|
||||
vchMsg.clear();
|
||||
vchSig.clear();
|
||||
}
|
||||
|
||||
bool CAlert::IsNull() const
|
||||
{
|
||||
return (nExpiration == 0);
|
||||
}
|
||||
|
||||
uint256 CAlert::GetHash() const
|
||||
{
|
||||
return Hash(this->vchMsg.begin(), this->vchMsg.end());
|
||||
}
|
||||
|
||||
bool CAlert::IsInEffect() const
|
||||
{
|
||||
return (GetAdjustedTime() < nExpiration);
|
||||
}
|
||||
|
||||
bool CAlert::Cancels(const CAlert& alert) const
|
||||
{
|
||||
if (!IsInEffect())
|
||||
return false; // this was a no-op before 31403
|
||||
return (alert.nID <= nCancel || setCancel.count(alert.nID));
|
||||
}
|
||||
|
||||
bool CAlert::AppliesTo(int nVersion, std::string strSubVerIn) const
|
||||
{
|
||||
// TODO: rework for client-version-embedded-in-strSubVer ?
|
||||
return (IsInEffect() &&
|
||||
nMinVer <= nVersion && nVersion <= nMaxVer &&
|
||||
(setSubVer.empty() || setSubVer.count(strSubVerIn)));
|
||||
}
|
||||
|
||||
bool CAlert::AppliesToMe() const
|
||||
{
|
||||
return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<std::string>()));
|
||||
}
|
||||
|
||||
bool CAlert::RelayTo(CNode* pnode) const
|
||||
{
|
||||
if (!IsInEffect())
|
||||
return false;
|
||||
// don't relay to nodes which haven't sent their version message
|
||||
if (pnode->nVersion == 0)
|
||||
return false;
|
||||
// returns true if wasn't already contained in the set
|
||||
if (pnode->setKnown.insert(GetHash()).second)
|
||||
{
|
||||
if (AppliesTo(pnode->nVersion, pnode->strSubVer) ||
|
||||
AppliesToMe() ||
|
||||
GetAdjustedTime() < nRelayUntil)
|
||||
{
|
||||
pnode->PushMessage("alert", *this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CAlert::CheckSignature() const
|
||||
{
|
||||
CPubKey key(Params().AlertKey());
|
||||
if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
|
||||
return error("CAlert::CheckSignature() : verify signature failed");
|
||||
|
||||
// Now unserialize the data
|
||||
CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
|
||||
sMsg >> *(CUnsignedAlert*)this;
|
||||
return true;
|
||||
}
|
||||
|
||||
CAlert CAlert::getAlertByHash(const uint256 &hash)
|
||||
{
|
||||
CAlert retval;
|
||||
{
|
||||
LOCK(cs_mapAlerts);
|
||||
map<uint256, CAlert>::iterator mi = mapAlerts.find(hash);
|
||||
if(mi != mapAlerts.end())
|
||||
retval = mi->second;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool CAlert::ProcessAlert(bool fThread)
|
||||
{
|
||||
if (!CheckSignature())
|
||||
return false;
|
||||
if (!IsInEffect())
|
||||
return false;
|
||||
|
||||
// alert.nID=max is reserved for if the alert key is
|
||||
// compromised. It must have a pre-defined message,
|
||||
// must never expire, must apply to all versions,
|
||||
// and must cancel all previous
|
||||
// alerts or it will be ignored (so an attacker can't
|
||||
// send an "everything is OK, don't panic" version that
|
||||
// cannot be overridden):
|
||||
int maxInt = std::numeric_limits<int>::max();
|
||||
if (nID == maxInt)
|
||||
{
|
||||
if (!(
|
||||
nExpiration == maxInt &&
|
||||
nCancel == (maxInt-1) &&
|
||||
nMinVer == 0 &&
|
||||
nMaxVer == maxInt &&
|
||||
setSubVer.empty() &&
|
||||
nPriority == maxInt &&
|
||||
strStatusBar == "URGENT: Alert key compromised, upgrade required"
|
||||
))
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
LOCK(cs_mapAlerts);
|
||||
// Cancel previous alerts
|
||||
for (map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();)
|
||||
{
|
||||
const CAlert& alert = (*mi).second;
|
||||
if (Cancels(alert))
|
||||
{
|
||||
LogPrint("alert", "cancelling alert %d\n", alert.nID);
|
||||
uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
|
||||
mapAlerts.erase(mi++);
|
||||
}
|
||||
else if (!alert.IsInEffect())
|
||||
{
|
||||
LogPrint("alert", "expiring alert %d\n", alert.nID);
|
||||
uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
|
||||
mapAlerts.erase(mi++);
|
||||
}
|
||||
else
|
||||
mi++;
|
||||
}
|
||||
|
||||
// Check if this alert has been cancelled
|
||||
BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
|
||||
{
|
||||
const CAlert& alert = item.second;
|
||||
if (alert.Cancels(*this))
|
||||
{
|
||||
LogPrint("alert", "alert already cancelled by %d\n", alert.nID);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Add to mapAlerts
|
||||
mapAlerts.insert(make_pair(GetHash(), *this));
|
||||
// Notify UI and -alertnotify if it applies to me
|
||||
if(AppliesToMe())
|
||||
{
|
||||
uiInterface.NotifyAlertChanged(GetHash(), CT_NEW);
|
||||
Notify(strStatusBar, fThread);
|
||||
}
|
||||
}
|
||||
|
||||
LogPrint("alert", "accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe());
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CAlert::Notify(const std::string& strMessage, bool fThread)
|
||||
{
|
||||
std::string strCmd = GetArg("-alertnotify", "");
|
||||
if (strCmd.empty()) return;
|
||||
|
||||
// Alert text should be plain ascii coming from a trusted source, but to
|
||||
// be safe we first strip anything not in safeChars, then add single quotes around
|
||||
// the whole string before passing it to the shell:
|
||||
std::string singleQuote("'");
|
||||
std::string safeStatus = SanitizeString(strMessage);
|
||||
safeStatus = singleQuote+safeStatus+singleQuote;
|
||||
boost::replace_all(strCmd, "%s", safeStatus);
|
||||
|
||||
if (fThread)
|
||||
boost::thread t(runCommand, strCmd); // thread runs free
|
||||
else
|
||||
runCommand(strCmd);
|
||||
}
|
||||
113
src/alert.h
113
src/alert.h
|
|
@ -1,113 +0,0 @@
|
|||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2013 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_ALERT_H
|
||||
#define BITCOIN_ALERT_H
|
||||
|
||||
#include "serialize.h"
|
||||
#include "sync.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
class CAlert;
|
||||
class CNode;
|
||||
class uint256;
|
||||
|
||||
extern std::map<uint256, CAlert> mapAlerts;
|
||||
extern CCriticalSection cs_mapAlerts;
|
||||
|
||||
/** Alerts are for notifying old versions if they become too obsolete and
|
||||
* need to upgrade. The message is displayed in the status bar.
|
||||
* Alert messages are broadcast as a vector of signed data. Unserializing may
|
||||
* not read the entire buffer if the alert is for a newer version, but older
|
||||
* versions can still relay the original data.
|
||||
*/
|
||||
class CUnsignedAlert
|
||||
{
|
||||
public:
|
||||
int nVersion;
|
||||
int64_t nRelayUntil; // when newer nodes stop relaying to newer nodes
|
||||
int64_t nExpiration;
|
||||
int nID;
|
||||
int nCancel;
|
||||
std::set<int> setCancel;
|
||||
int nMinVer; // lowest version inclusive
|
||||
int nMaxVer; // highest version inclusive
|
||||
std::set<std::string> setSubVer; // empty matches all
|
||||
int nPriority;
|
||||
|
||||
// Actions
|
||||
std::string strComment;
|
||||
std::string strStatusBar;
|
||||
std::string strReserved;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(this->nVersion);
|
||||
nVersion = this->nVersion;
|
||||
READWRITE(nRelayUntil);
|
||||
READWRITE(nExpiration);
|
||||
READWRITE(nID);
|
||||
READWRITE(nCancel);
|
||||
READWRITE(setCancel);
|
||||
READWRITE(nMinVer);
|
||||
READWRITE(nMaxVer);
|
||||
READWRITE(setSubVer);
|
||||
READWRITE(nPriority);
|
||||
|
||||
READWRITE(LIMITED_STRING(strComment, 65536));
|
||||
READWRITE(LIMITED_STRING(strStatusBar, 256));
|
||||
READWRITE(LIMITED_STRING(strReserved, 256));
|
||||
}
|
||||
|
||||
void SetNull();
|
||||
|
||||
std::string ToString() const;
|
||||
};
|
||||
|
||||
/** An alert is a combination of a serialized CUnsignedAlert and a signature. */
|
||||
class CAlert : public CUnsignedAlert
|
||||
{
|
||||
public:
|
||||
std::vector<unsigned char> vchMsg;
|
||||
std::vector<unsigned char> vchSig;
|
||||
|
||||
CAlert()
|
||||
{
|
||||
SetNull();
|
||||
}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(vchMsg);
|
||||
READWRITE(vchSig);
|
||||
}
|
||||
|
||||
void SetNull();
|
||||
bool IsNull() const;
|
||||
uint256 GetHash() const;
|
||||
bool IsInEffect() const;
|
||||
bool Cancels(const CAlert& alert) const;
|
||||
bool AppliesTo(int nVersion, std::string strSubVerIn) const;
|
||||
bool AppliesToMe() const;
|
||||
bool RelayTo(CNode* pnode) const;
|
||||
bool CheckSignature() const;
|
||||
bool ProcessAlert(bool fThread = true); // fThread means run -alertnotify in a free-running thread
|
||||
static void Notify(const std::string& strMessage, bool fThread);
|
||||
|
||||
/*
|
||||
* Get copy of (active) alert object by hash. Returns a null alert if it is not found.
|
||||
*/
|
||||
static CAlert getAlertByHash(const uint256 &hash);
|
||||
};
|
||||
|
||||
#endif // BITCOIN_ALERT_H
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
// Copyright (c) 2009-2013 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "allocators.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
#endif
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <windows.h>
|
||||
// This is used to attempt to keep keying material out of swap
|
||||
// Note that VirtualLock does not provide this as a guarantee on Windows,
|
||||
// but, in practice, memory that has been VirtualLock'd almost never gets written to
|
||||
// the pagefile except in rare circumstances where memory is extremely low.
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#include <limits.h> // for PAGESIZE
|
||||
#include <unistd.h> // for sysconf
|
||||
#endif
|
||||
|
||||
LockedPageManager* LockedPageManager::_instance = NULL;
|
||||
boost::once_flag LockedPageManager::init_flag = BOOST_ONCE_INIT;
|
||||
|
||||
/** Determine system page size in bytes */
|
||||
static inline size_t GetSystemPageSize()
|
||||
{
|
||||
size_t page_size;
|
||||
#if defined(WIN32)
|
||||
SYSTEM_INFO sSysInfo;
|
||||
GetSystemInfo(&sSysInfo);
|
||||
page_size = sSysInfo.dwPageSize;
|
||||
#elif defined(PAGESIZE) // defined in limits.h
|
||||
page_size = PAGESIZE;
|
||||
#else // assume some POSIX OS
|
||||
page_size = sysconf(_SC_PAGESIZE);
|
||||
#endif
|
||||
return page_size;
|
||||
}
|
||||
|
||||
bool MemoryPageLocker::Lock(const void* addr, size_t len)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return VirtualLock(const_cast<void*>(addr), len) != 0;
|
||||
#else
|
||||
return mlock(addr, len) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool MemoryPageLocker::Unlock(const void* addr, size_t len)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return VirtualUnlock(const_cast<void*>(addr), len) != 0;
|
||||
#else
|
||||
return munlock(addr, len) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
LockedPageManager::LockedPageManager() : LockedPageManagerBase<MemoryPageLocker>(GetSystemPageSize())
|
||||
{
|
||||
}
|
||||
268
src/allocators.h
268
src/allocators.h
|
|
@ -1,268 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2013 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_ALLOCATORS_H
|
||||
#define BITCOIN_ALLOCATORS_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/once.hpp>
|
||||
|
||||
#include <openssl/crypto.h> // for OPENSSL_cleanse()
|
||||
|
||||
/**
|
||||
* Thread-safe class to keep track of locked (ie, non-swappable) memory pages.
|
||||
*
|
||||
* Memory locks do not stack, that is, pages which have been locked several times by calls to mlock()
|
||||
* will be unlocked by a single call to munlock(). This can result in keying material ending up in swap when
|
||||
* those functions are used naively. This class simulates stacking memory locks by keeping a counter per page.
|
||||
*
|
||||
* @note By using a map from each page base address to lock count, this class is optimized for
|
||||
* small objects that span up to a few pages, mostly smaller than a page. To support large allocations,
|
||||
* something like an interval tree would be the preferred data structure.
|
||||
*/
|
||||
template <class Locker>
|
||||
class LockedPageManagerBase
|
||||
{
|
||||
public:
|
||||
LockedPageManagerBase(size_t page_size) : page_size(page_size)
|
||||
{
|
||||
// Determine bitmask for extracting page from address
|
||||
assert(!(page_size & (page_size - 1))); // size must be power of two
|
||||
page_mask = ~(page_size - 1);
|
||||
}
|
||||
|
||||
~LockedPageManagerBase()
|
||||
{
|
||||
assert(this->GetLockedPageCount() == 0);
|
||||
}
|
||||
|
||||
|
||||
// For all pages in affected range, increase lock count
|
||||
void LockRange(void* p, size_t size)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(mutex);
|
||||
if (!size)
|
||||
return;
|
||||
const size_t base_addr = reinterpret_cast<size_t>(p);
|
||||
const size_t start_page = base_addr & page_mask;
|
||||
const size_t end_page = (base_addr + size - 1) & page_mask;
|
||||
for (size_t page = start_page; page <= end_page; page += page_size) {
|
||||
Histogram::iterator it = histogram.find(page);
|
||||
if (it == histogram.end()) // Newly locked page
|
||||
{
|
||||
locker.Lock(reinterpret_cast<void*>(page), page_size);
|
||||
histogram.insert(std::make_pair(page, 1));
|
||||
} else // Page was already locked; increase counter
|
||||
{
|
||||
it->second += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For all pages in affected range, decrease lock count
|
||||
void UnlockRange(void* p, size_t size)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(mutex);
|
||||
if (!size)
|
||||
return;
|
||||
const size_t base_addr = reinterpret_cast<size_t>(p);
|
||||
const size_t start_page = base_addr & page_mask;
|
||||
const size_t end_page = (base_addr + size - 1) & page_mask;
|
||||
for (size_t page = start_page; page <= end_page; page += page_size) {
|
||||
Histogram::iterator it = histogram.find(page);
|
||||
assert(it != histogram.end()); // Cannot unlock an area that was not locked
|
||||
// Decrease counter for page, when it is zero, the page will be unlocked
|
||||
it->second -= 1;
|
||||
if (it->second == 0) // Nothing on the page anymore that keeps it locked
|
||||
{
|
||||
// Unlock page and remove the count from histogram
|
||||
locker.Unlock(reinterpret_cast<void*>(page), page_size);
|
||||
histogram.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get number of locked pages for diagnostics
|
||||
int GetLockedPageCount()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(mutex);
|
||||
return histogram.size();
|
||||
}
|
||||
|
||||
private:
|
||||
Locker locker;
|
||||
boost::mutex mutex;
|
||||
size_t page_size, page_mask;
|
||||
// map of page base address to lock count
|
||||
typedef std::map<size_t, int> Histogram;
|
||||
Histogram histogram;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* OS-dependent memory page locking/unlocking.
|
||||
* Defined as policy class to make stubbing for test possible.
|
||||
*/
|
||||
class MemoryPageLocker
|
||||
{
|
||||
public:
|
||||
/** Lock memory pages.
|
||||
* addr and len must be a multiple of the system page size
|
||||
*/
|
||||
bool Lock(const void* addr, size_t len);
|
||||
/** Unlock memory pages.
|
||||
* addr and len must be a multiple of the system page size
|
||||
*/
|
||||
bool Unlock(const void* addr, size_t len);
|
||||
};
|
||||
|
||||
/**
|
||||
* Singleton class to keep track of locked (ie, non-swappable) memory pages, for use in
|
||||
* std::allocator templates.
|
||||
*
|
||||
* Some implementations of the STL allocate memory in some constructors (i.e., see
|
||||
* MSVC's vector<T> implementation where it allocates 1 byte of memory in the allocator.)
|
||||
* Due to the unpredictable order of static initializers, we have to make sure the
|
||||
* LockedPageManager instance exists before any other STL-based objects that use
|
||||
* secure_allocator are created. So instead of having LockedPageManager also be
|
||||
* static-initialized, it is created on demand.
|
||||
*/
|
||||
class LockedPageManager : public LockedPageManagerBase<MemoryPageLocker>
|
||||
{
|
||||
public:
|
||||
static LockedPageManager& Instance()
|
||||
{
|
||||
boost::call_once(LockedPageManager::CreateInstance, LockedPageManager::init_flag);
|
||||
return *LockedPageManager::_instance;
|
||||
}
|
||||
|
||||
private:
|
||||
LockedPageManager();
|
||||
|
||||
static void CreateInstance()
|
||||
{
|
||||
// Using a local static instance guarantees that the object is initialized
|
||||
// when it's first needed and also deinitialized after all objects that use
|
||||
// it are done with it. I can think of one unlikely scenario where we may
|
||||
// have a static deinitialization order/problem, but the check in
|
||||
// LockedPageManagerBase's destructor helps us detect if that ever happens.
|
||||
static LockedPageManager instance;
|
||||
LockedPageManager::_instance = &instance;
|
||||
}
|
||||
|
||||
static LockedPageManager* _instance;
|
||||
static boost::once_flag init_flag;
|
||||
};
|
||||
|
||||
//
|
||||
// Functions for directly locking/unlocking memory objects.
|
||||
// Intended for non-dynamically allocated structures.
|
||||
//
|
||||
template <typename T>
|
||||
void LockObject(const T& t)
|
||||
{
|
||||
LockedPageManager::Instance().LockRange((void*)(&t), sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void UnlockObject(const T& t)
|
||||
{
|
||||
OPENSSL_cleanse((void*)(&t), sizeof(T));
|
||||
LockedPageManager::Instance().UnlockRange((void*)(&t), sizeof(T));
|
||||
}
|
||||
|
||||
//
|
||||
// Allocator that locks its contents from being paged
|
||||
// out of memory and clears its contents before deletion.
|
||||
//
|
||||
template <typename T>
|
||||
struct secure_allocator : public std::allocator<T> {
|
||||
// MSVC8 default copy constructor is broken
|
||||
typedef std::allocator<T> base;
|
||||
typedef typename base::size_type size_type;
|
||||
typedef typename base::difference_type difference_type;
|
||||
typedef typename base::pointer pointer;
|
||||
typedef typename base::const_pointer const_pointer;
|
||||
typedef typename base::reference reference;
|
||||
typedef typename base::const_reference const_reference;
|
||||
typedef typename base::value_type value_type;
|
||||
secure_allocator() throw() {}
|
||||
secure_allocator(const secure_allocator& a) throw() : base(a) {}
|
||||
template <typename U>
|
||||
secure_allocator(const secure_allocator<U>& a) throw() : base(a)
|
||||
{
|
||||
}
|
||||
~secure_allocator() throw() {}
|
||||
template <typename _Other>
|
||||
struct rebind {
|
||||
typedef secure_allocator<_Other> other;
|
||||
};
|
||||
|
||||
T* allocate(std::size_t n, const void* hint = 0)
|
||||
{
|
||||
T* p;
|
||||
p = std::allocator<T>::allocate(n, hint);
|
||||
if (p != NULL)
|
||||
LockedPageManager::Instance().LockRange(p, sizeof(T) * n);
|
||||
return p;
|
||||
}
|
||||
|
||||
void deallocate(T* p, std::size_t n)
|
||||
{
|
||||
if (p != NULL) {
|
||||
OPENSSL_cleanse(p, sizeof(T) * n);
|
||||
LockedPageManager::Instance().UnlockRange(p, sizeof(T) * n);
|
||||
}
|
||||
std::allocator<T>::deallocate(p, n);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Allocator that clears its contents before deletion.
|
||||
//
|
||||
template <typename T>
|
||||
struct zero_after_free_allocator : public std::allocator<T> {
|
||||
// MSVC8 default copy constructor is broken
|
||||
typedef std::allocator<T> base;
|
||||
typedef typename base::size_type size_type;
|
||||
typedef typename base::difference_type difference_type;
|
||||
typedef typename base::pointer pointer;
|
||||
typedef typename base::const_pointer const_pointer;
|
||||
typedef typename base::reference reference;
|
||||
typedef typename base::const_reference const_reference;
|
||||
typedef typename base::value_type value_type;
|
||||
zero_after_free_allocator() throw() {}
|
||||
zero_after_free_allocator(const zero_after_free_allocator& a) throw() : base(a) {}
|
||||
template <typename U>
|
||||
zero_after_free_allocator(const zero_after_free_allocator<U>& a) throw() : base(a)
|
||||
{
|
||||
}
|
||||
~zero_after_free_allocator() throw() {}
|
||||
template <typename _Other>
|
||||
struct rebind {
|
||||
typedef zero_after_free_allocator<_Other> other;
|
||||
};
|
||||
|
||||
void deallocate(T* p, std::size_t n)
|
||||
{
|
||||
if (p != NULL)
|
||||
OPENSSL_cleanse(p, sizeof(T) * n);
|
||||
std::allocator<T>::deallocate(p, n);
|
||||
}
|
||||
};
|
||||
|
||||
// This is exactly like std::string, but with a custom allocator.
|
||||
typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString;
|
||||
|
||||
// Byte-vector that clears its contents before deletion.
|
||||
typedef std::vector<char, zero_after_free_allocator<char> > CSerializeData;
|
||||
|
||||
#endif // BITCOIN_ALLOCATORS_H
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "amount.h"
|
||||
|
||||
#include "tinyformat.h"
|
||||
|
||||
CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nSize)
|
||||
{
|
||||
if (nSize > 0)
|
||||
nSatoshisPerK = nFeePaid*1000/nSize;
|
||||
else
|
||||
nSatoshisPerK = 0;
|
||||
}
|
||||
|
||||
CAmount CFeeRate::GetFee(size_t nSize) const
|
||||
{
|
||||
CAmount nFee = nSatoshisPerK*nSize / 1000;
|
||||
|
||||
if (nFee == 0 && nSatoshisPerK > 0)
|
||||
nFee = nSatoshisPerK;
|
||||
|
||||
return nFee;
|
||||
}
|
||||
|
||||
std::string CFeeRate::ToString() const
|
||||
{
|
||||
return strprintf("%d.%08d BTC/kB", nSatoshisPerK / COIN, nSatoshisPerK % COIN);
|
||||
}
|
||||
54
src/amount.h
54
src/amount.h
|
|
@ -1,54 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_AMOUNT_H
|
||||
#define BITCOIN_AMOUNT_H
|
||||
|
||||
#include "serialize.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
|
||||
typedef int64_t CAmount;
|
||||
|
||||
static const CAmount COIN = 100000000;
|
||||
static const CAmount CENT = 1000000;
|
||||
|
||||
/** No amount larger than this (in satoshi) is valid */
|
||||
static const CAmount MAX_MONEY = 21000000 * COIN;
|
||||
inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
|
||||
|
||||
/** Type-safe wrapper class to for fee rates
|
||||
* (how much to pay based on transaction size)
|
||||
*/
|
||||
class CFeeRate
|
||||
{
|
||||
private:
|
||||
CAmount nSatoshisPerK; // unit is satoshis-per-1,000-bytes
|
||||
public:
|
||||
CFeeRate() : nSatoshisPerK(0) { }
|
||||
explicit CFeeRate(const CAmount& _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { }
|
||||
CFeeRate(const CAmount& nFeePaid, size_t nSize);
|
||||
CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; }
|
||||
|
||||
CAmount GetFee(size_t size) const; // unit returned is satoshis
|
||||
CAmount GetFeePerK() const { return GetFee(1000); } // satoshis-per-1000-bytes
|
||||
|
||||
friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; }
|
||||
friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; }
|
||||
friend bool operator==(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK == b.nSatoshisPerK; }
|
||||
friend bool operator<=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK <= b.nSatoshisPerK; }
|
||||
friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; }
|
||||
std::string ToString() const;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(nSatoshisPerK);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BITCOIN_AMOUNT_H
|
||||
311
src/base58.cpp
311
src/base58.cpp
|
|
@ -1,311 +0,0 @@
|
|||
// Copyright (c) 2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "base58.h"
|
||||
|
||||
#include "hash.h"
|
||||
#include "uint256.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
|
||||
/** All alphanumeric characters except for "0", "I", "O", and "l" */
|
||||
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||
|
||||
bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
|
||||
{
|
||||
// Skip leading spaces.
|
||||
while (*psz && isspace(*psz))
|
||||
psz++;
|
||||
// Skip and count leading '1's.
|
||||
int zeroes = 0;
|
||||
while (*psz == '1') {
|
||||
zeroes++;
|
||||
psz++;
|
||||
}
|
||||
// Allocate enough space in big-endian base256 representation.
|
||||
std::vector<unsigned char> b256(strlen(psz) * 733 / 1000 + 1); // log(58) / log(256), rounded up.
|
||||
// Process the characters.
|
||||
while (*psz && !isspace(*psz)) {
|
||||
// Decode base58 character
|
||||
const char* ch = strchr(pszBase58, *psz);
|
||||
if (ch == NULL)
|
||||
return false;
|
||||
// Apply "b256 = b256 * 58 + ch".
|
||||
int carry = ch - pszBase58;
|
||||
for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); it != b256.rend(); it++) {
|
||||
carry += 58 * (*it);
|
||||
*it = carry % 256;
|
||||
carry /= 256;
|
||||
}
|
||||
assert(carry == 0);
|
||||
psz++;
|
||||
}
|
||||
// Skip trailing spaces.
|
||||
while (isspace(*psz))
|
||||
psz++;
|
||||
if (*psz != 0)
|
||||
return false;
|
||||
// Skip leading zeroes in b256.
|
||||
std::vector<unsigned char>::iterator it = b256.begin();
|
||||
while (it != b256.end() && *it == 0)
|
||||
it++;
|
||||
// Copy result into output vector.
|
||||
vch.reserve(zeroes + (b256.end() - it));
|
||||
vch.assign(zeroes, 0x00);
|
||||
while (it != b256.end())
|
||||
vch.push_back(*(it++));
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
|
||||
{
|
||||
// Skip & count leading zeroes.
|
||||
int zeroes = 0;
|
||||
while (pbegin != pend && *pbegin == 0) {
|
||||
pbegin++;
|
||||
zeroes++;
|
||||
}
|
||||
// Allocate enough space in big-endian base58 representation.
|
||||
std::vector<unsigned char> b58((pend - pbegin) * 138 / 100 + 1); // log(256) / log(58), rounded up.
|
||||
// Process the bytes.
|
||||
while (pbegin != pend) {
|
||||
int carry = *pbegin;
|
||||
// Apply "b58 = b58 * 256 + ch".
|
||||
for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); it != b58.rend(); it++) {
|
||||
carry += 256 * (*it);
|
||||
*it = carry % 58;
|
||||
carry /= 58;
|
||||
}
|
||||
assert(carry == 0);
|
||||
pbegin++;
|
||||
}
|
||||
// Skip leading zeroes in base58 result.
|
||||
std::vector<unsigned char>::iterator it = b58.begin();
|
||||
while (it != b58.end() && *it == 0)
|
||||
it++;
|
||||
// Translate the result into a string.
|
||||
std::string str;
|
||||
str.reserve(zeroes + (b58.end() - it));
|
||||
str.assign(zeroes, '1');
|
||||
while (it != b58.end())
|
||||
str += pszBase58[*(it++)];
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string EncodeBase58(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
return EncodeBase58(&vch[0], &vch[0] + vch.size());
|
||||
}
|
||||
|
||||
bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
|
||||
{
|
||||
return DecodeBase58(str.c_str(), vchRet);
|
||||
}
|
||||
|
||||
std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
|
||||
{
|
||||
// add 4-byte hash check to the end
|
||||
std::vector<unsigned char> vch(vchIn);
|
||||
uint256 hash = Hash(vch.begin(), vch.end());
|
||||
vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
|
||||
return EncodeBase58(vch);
|
||||
}
|
||||
|
||||
bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
|
||||
{
|
||||
if (!DecodeBase58(psz, vchRet) ||
|
||||
(vchRet.size() < 4)) {
|
||||
vchRet.clear();
|
||||
return false;
|
||||
}
|
||||
// re-calculate the checksum, insure it matches the included 4-byte checksum
|
||||
uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4);
|
||||
if (memcmp(&hash, &vchRet.end()[-4], 4) != 0) {
|
||||
vchRet.clear();
|
||||
return false;
|
||||
}
|
||||
vchRet.resize(vchRet.size() - 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
|
||||
{
|
||||
return DecodeBase58Check(str.c_str(), vchRet);
|
||||
}
|
||||
|
||||
CBase58Data::CBase58Data()
|
||||
{
|
||||
vchVersion.clear();
|
||||
vchData.clear();
|
||||
}
|
||||
|
||||
void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const void* pdata, size_t nSize)
|
||||
{
|
||||
vchVersion = vchVersionIn;
|
||||
vchData.resize(nSize);
|
||||
if (!vchData.empty())
|
||||
memcpy(&vchData[0], pdata, nSize);
|
||||
}
|
||||
|
||||
void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend)
|
||||
{
|
||||
SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
|
||||
}
|
||||
|
||||
bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes)
|
||||
{
|
||||
std::vector<unsigned char> vchTemp;
|
||||
bool rc58 = DecodeBase58Check(psz, vchTemp);
|
||||
if ((!rc58) || (vchTemp.size() < nVersionBytes)) {
|
||||
vchData.clear();
|
||||
vchVersion.clear();
|
||||
return false;
|
||||
}
|
||||
vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
|
||||
vchData.resize(vchTemp.size() - nVersionBytes);
|
||||
if (!vchData.empty())
|
||||
memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size());
|
||||
OPENSSL_cleanse(&vchTemp[0], vchData.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBase58Data::SetString(const std::string& str)
|
||||
{
|
||||
return SetString(str.c_str());
|
||||
}
|
||||
|
||||
std::string CBase58Data::ToString() const
|
||||
{
|
||||
std::vector<unsigned char> vch = vchVersion;
|
||||
vch.insert(vch.end(), vchData.begin(), vchData.end());
|
||||
return EncodeBase58Check(vch);
|
||||
}
|
||||
|
||||
int CBase58Data::CompareTo(const CBase58Data& b58) const
|
||||
{
|
||||
if (vchVersion < b58.vchVersion)
|
||||
return -1;
|
||||
if (vchVersion > b58.vchVersion)
|
||||
return 1;
|
||||
if (vchData < b58.vchData)
|
||||
return -1;
|
||||
if (vchData > b58.vchData)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class CBitcoinAddressVisitor : public boost::static_visitor<bool>
|
||||
{
|
||||
private:
|
||||
CBitcoinAddress* addr;
|
||||
|
||||
public:
|
||||
CBitcoinAddressVisitor(CBitcoinAddress* addrIn) : addr(addrIn) {}
|
||||
|
||||
bool operator()(const CKeyID& id) const { return addr->Set(id); }
|
||||
bool operator()(const CScriptID& id) const { return addr->Set(id); }
|
||||
bool operator()(const CNoDestination& no) const { return false; }
|
||||
};
|
||||
|
||||
} // anon namespace
|
||||
|
||||
bool CBitcoinAddress::Set(const CKeyID& id)
|
||||
{
|
||||
SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBitcoinAddress::Set(const CScriptID& id)
|
||||
{
|
||||
SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBitcoinAddress::Set(const CTxDestination& dest)
|
||||
{
|
||||
return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
|
||||
}
|
||||
|
||||
bool CBitcoinAddress::IsValid() const
|
||||
{
|
||||
return IsValid(Params());
|
||||
}
|
||||
|
||||
bool CBitcoinAddress::IsValid(const CChainParams& params) const
|
||||
{
|
||||
bool fCorrectSize = vchData.size() == 20;
|
||||
bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
|
||||
vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
|
||||
return fCorrectSize && fKnownVersion;
|
||||
}
|
||||
|
||||
CTxDestination CBitcoinAddress::Get() const
|
||||
{
|
||||
if (!IsValid())
|
||||
return CNoDestination();
|
||||
uint160 id;
|
||||
memcpy(&id, &vchData[0], 20);
|
||||
if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
|
||||
return CKeyID(id);
|
||||
else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
|
||||
return CScriptID(id);
|
||||
else
|
||||
return CNoDestination();
|
||||
}
|
||||
|
||||
bool CBitcoinAddress::GetKeyID(CKeyID& keyID) const
|
||||
{
|
||||
if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
|
||||
return false;
|
||||
uint160 id;
|
||||
memcpy(&id, &vchData[0], 20);
|
||||
keyID = CKeyID(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBitcoinAddress::IsScript() const
|
||||
{
|
||||
return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
|
||||
}
|
||||
|
||||
void CBitcoinSecret::SetKey(const CKey& vchSecret)
|
||||
{
|
||||
assert(vchSecret.IsValid());
|
||||
SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
|
||||
if (vchSecret.IsCompressed())
|
||||
vchData.push_back(1);
|
||||
}
|
||||
|
||||
CKey CBitcoinSecret::GetKey()
|
||||
{
|
||||
CKey ret;
|
||||
assert(vchData.size() >= 32);
|
||||
ret.Set(vchData.begin(), vchData.begin() + 32, vchData.size() > 32 && vchData[32] == 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CBitcoinSecret::IsValid() const
|
||||
{
|
||||
bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
|
||||
bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
|
||||
return fExpectedFormat && fCorrectVersion;
|
||||
}
|
||||
|
||||
bool CBitcoinSecret::SetString(const char* pszSecret)
|
||||
{
|
||||
return CBase58Data::SetString(pszSecret) && IsValid();
|
||||
}
|
||||
|
||||
bool CBitcoinSecret::SetString(const std::string& strSecret)
|
||||
{
|
||||
return SetString(strSecret.c_str());
|
||||
}
|
||||
162
src/base58.h
162
src/base58.h
|
|
@ -1,162 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
/**
|
||||
* Why base-58 instead of standard base-64 encoding?
|
||||
* - Don't want 0OIl characters that look the same in some fonts and
|
||||
* could be used to create visually identical looking account numbers.
|
||||
* - A string with non-alphanumeric characters is not as easily accepted as an account number.
|
||||
* - E-mail usually won't line-break if there's no punctuation to break at.
|
||||
* - Double-clicking selects the whole number as one word if it's all alphanumeric.
|
||||
*/
|
||||
#ifndef BITCOIN_BASE58_H
|
||||
#define BITCOIN_BASE58_H
|
||||
|
||||
#include "chainparams.h"
|
||||
#include "key.h"
|
||||
#include "pubkey.h"
|
||||
#include "script/script.h"
|
||||
#include "script/standard.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* Encode a byte sequence as a base58-encoded string.
|
||||
* pbegin and pend cannot be NULL, unless both are.
|
||||
*/
|
||||
std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend);
|
||||
|
||||
/**
|
||||
* Encode a byte vector as a base58-encoded string
|
||||
*/
|
||||
std::string EncodeBase58(const std::vector<unsigned char>& vch);
|
||||
|
||||
/**
|
||||
* Decode a base58-encoded string (psz) into a byte vector (vchRet).
|
||||
* return true if decoding is successful.
|
||||
* psz cannot be NULL.
|
||||
*/
|
||||
bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet);
|
||||
|
||||
/**
|
||||
* Decode a base58-encoded string (str) into a byte vector (vchRet).
|
||||
* return true if decoding is successful.
|
||||
*/
|
||||
bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet);
|
||||
|
||||
/**
|
||||
* Encode a byte vector into a base58-encoded string, including checksum
|
||||
*/
|
||||
std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn);
|
||||
|
||||
/**
|
||||
* Decode a base58-encoded string (psz) that includes a checksum into a byte
|
||||
* vector (vchRet), return true if decoding is successful
|
||||
*/
|
||||
inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet);
|
||||
|
||||
/**
|
||||
* Decode a base58-encoded string (str) that includes a checksum into a byte
|
||||
* vector (vchRet), return true if decoding is successful
|
||||
*/
|
||||
inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet);
|
||||
|
||||
/**
|
||||
* Base class for all base58-encoded data
|
||||
*/
|
||||
class CBase58Data
|
||||
{
|
||||
protected:
|
||||
//! the version byte(s)
|
||||
std::vector<unsigned char> vchVersion;
|
||||
|
||||
//! the actually encoded data
|
||||
typedef std::vector<unsigned char, zero_after_free_allocator<unsigned char> > vector_uchar;
|
||||
vector_uchar vchData;
|
||||
|
||||
CBase58Data();
|
||||
void SetData(const std::vector<unsigned char> &vchVersionIn, const void* pdata, size_t nSize);
|
||||
void SetData(const std::vector<unsigned char> &vchVersionIn, const unsigned char *pbegin, const unsigned char *pend);
|
||||
|
||||
public:
|
||||
bool SetString(const char* psz, unsigned int nVersionBytes = 1);
|
||||
bool SetString(const std::string& str);
|
||||
std::string ToString() const;
|
||||
int CompareTo(const CBase58Data& b58) const;
|
||||
|
||||
bool operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; }
|
||||
bool operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; }
|
||||
bool operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; }
|
||||
bool operator< (const CBase58Data& b58) const { return CompareTo(b58) < 0; }
|
||||
bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; }
|
||||
};
|
||||
|
||||
/** base58-encoded Bitcoin addresses.
|
||||
* Public-key-hash-addresses have version 0 (or 111 testnet).
|
||||
* The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
|
||||
* Script-hash-addresses have version 5 (or 196 testnet).
|
||||
* The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
|
||||
*/
|
||||
class CBitcoinAddress : public CBase58Data {
|
||||
public:
|
||||
bool Set(const CKeyID &id);
|
||||
bool Set(const CScriptID &id);
|
||||
bool Set(const CTxDestination &dest);
|
||||
bool IsValid() const;
|
||||
bool IsValid(const CChainParams ¶ms) const;
|
||||
|
||||
CBitcoinAddress() {}
|
||||
CBitcoinAddress(const CTxDestination &dest) { Set(dest); }
|
||||
CBitcoinAddress(const std::string& strAddress) { SetString(strAddress); }
|
||||
CBitcoinAddress(const char* pszAddress) { SetString(pszAddress); }
|
||||
|
||||
CTxDestination Get() const;
|
||||
bool GetKeyID(CKeyID &keyID) const;
|
||||
bool IsScript() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* A base58-encoded secret key
|
||||
*/
|
||||
class CBitcoinSecret : public CBase58Data
|
||||
{
|
||||
public:
|
||||
void SetKey(const CKey& vchSecret);
|
||||
CKey GetKey();
|
||||
bool IsValid() const;
|
||||
bool SetString(const char* pszSecret);
|
||||
bool SetString(const std::string& strSecret);
|
||||
|
||||
CBitcoinSecret(const CKey& vchSecret) { SetKey(vchSecret); }
|
||||
CBitcoinSecret() {}
|
||||
};
|
||||
|
||||
template<typename K, int Size, CChainParams::Base58Type Type> class CBitcoinExtKeyBase : public CBase58Data
|
||||
{
|
||||
public:
|
||||
void SetKey(const K &key) {
|
||||
unsigned char vch[Size];
|
||||
key.Encode(vch);
|
||||
SetData(Params().Base58Prefix(Type), vch, vch+Size);
|
||||
}
|
||||
|
||||
K GetKey() {
|
||||
K ret;
|
||||
ret.Decode(&vchData[0], &vchData[Size]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
CBitcoinExtKeyBase(const K &key) {
|
||||
SetKey(key);
|
||||
}
|
||||
|
||||
CBitcoinExtKeyBase() {}
|
||||
};
|
||||
|
||||
typedef CBitcoinExtKeyBase<CExtKey, 74, CChainParams::EXT_SECRET_KEY> CBitcoinExtKey;
|
||||
typedef CBitcoinExtKeyBase<CExtPubKey, 74, CChainParams::EXT_PUBLIC_KEY> CBitcoinExtPubKey;
|
||||
|
||||
#endif // BITCOIN_BASE58_H
|
||||
32
src/basic-config.h
Normal file
32
src/basic-config.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_BASIC_CONFIG_
|
||||
#define _SECP256K1_BASIC_CONFIG_
|
||||
|
||||
#ifdef USE_BASIC_CONFIG
|
||||
|
||||
#undef USE_ASM_X86_64
|
||||
#undef USE_ENDOMORPHISM
|
||||
#undef USE_FIELD_10X26
|
||||
#undef USE_FIELD_5X52
|
||||
#undef USE_FIELD_INV_BUILTIN
|
||||
#undef USE_FIELD_INV_NUM
|
||||
#undef USE_NUM_GMP
|
||||
#undef USE_NUM_NONE
|
||||
#undef USE_SCALAR_4X64
|
||||
#undef USE_SCALAR_8X32
|
||||
#undef USE_SCALAR_INV_BUILTIN
|
||||
#undef USE_SCALAR_INV_NUM
|
||||
|
||||
#define USE_NUM_NONE 1
|
||||
#define USE_FIELD_INV_BUILTIN 1
|
||||
#define USE_SCALAR_INV_BUILTIN 1
|
||||
#define USE_FIELD_10X26 1
|
||||
#define USE_SCALAR_8X32 1
|
||||
|
||||
#endif // USE_BASIC_CONFIG
|
||||
#endif // _SECP256K1_BASIC_CONFIG_
|
||||
|
|
@ -7,18 +7,19 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "include/secp256k1.h"
|
||||
#include "include/secp256k1_ecdh.h"
|
||||
#include "util.h"
|
||||
#include "bench.h"
|
||||
|
||||
typedef struct {
|
||||
unsigned char point[33];
|
||||
int pointlen;
|
||||
secp256k1_context_t *ctx;
|
||||
secp256k1_pubkey_t point;
|
||||
unsigned char scalar[32];
|
||||
} bench_multiply_t;
|
||||
} bench_ecdh_t;
|
||||
|
||||
static void bench_multiply_setup(void* arg) {
|
||||
static void bench_ecdh_setup(void* arg) {
|
||||
int i;
|
||||
bench_multiply_t *data = (bench_multiply_t*)arg;
|
||||
bench_ecdh_t *data = (bench_ecdh_t*)arg;
|
||||
const unsigned char point[] = {
|
||||
0x03,
|
||||
0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06,
|
||||
|
|
@ -27,23 +28,24 @@ static void bench_multiply_setup(void* arg) {
|
|||
0xa2, 0xba, 0xd1, 0x84, 0xf8, 0x83, 0xc6, 0x9f
|
||||
};
|
||||
|
||||
data->ctx = secp256k1_context_create(0);
|
||||
for (i = 0; i < 32; i++) data->scalar[i] = i + 1;
|
||||
data->pointlen = sizeof(point);
|
||||
memcpy(data->point, point, data->pointlen);
|
||||
CHECK(secp256k1_ec_pubkey_parse(data->ctx, &data->point, point, sizeof(point)) == 1);
|
||||
}
|
||||
|
||||
static void bench_multiply(void* arg) {
|
||||
static void bench_ecdh(void* arg) {
|
||||
int i;
|
||||
bench_multiply_t *data = (bench_multiply_t*)arg;
|
||||
unsigned char res[32];
|
||||
bench_ecdh_t *data = (bench_ecdh_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
CHECK(secp256k1_point_multiply(data->point, &data->pointlen, data->scalar) == 1);
|
||||
CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar) == 1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
bench_multiply_t data;
|
||||
bench_ecdh_t data;
|
||||
|
||||
run_benchmark("ecdh_mult", bench_multiply, bench_multiply_setup, NULL, &data, 10, 20000);
|
||||
run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, 20000);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
#include "field_impl.h"
|
||||
#include "group_impl.h"
|
||||
#include "scalar_impl.h"
|
||||
#include "ecmult_const_impl.h"
|
||||
#include "ecmult_impl.h"
|
||||
#include "bench.h"
|
||||
|
||||
|
|
@ -21,7 +22,7 @@ typedef struct {
|
|||
secp256k1_fe_t fe_x, fe_y;
|
||||
secp256k1_ge_t ge_x, ge_y;
|
||||
secp256k1_gej_t gej_x, gej_y;
|
||||
unsigned char data[32];
|
||||
unsigned char data[64];
|
||||
int wnaf[256];
|
||||
} bench_inv_t;
|
||||
|
||||
|
|
@ -51,6 +52,7 @@ void bench_setup(void* arg) {
|
|||
secp256k1_gej_set_ge(&data->gej_x, &data->ge_x);
|
||||
secp256k1_gej_set_ge(&data->gej_y, &data->ge_y);
|
||||
memcpy(data->data, init_x, 32);
|
||||
memcpy(data->data + 32, init_y, 32);
|
||||
}
|
||||
|
||||
void bench_scalar_add(void* arg) {
|
||||
|
|
@ -96,7 +98,7 @@ void bench_scalar_split(void* arg) {
|
|||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_scalar_t l, r;
|
||||
secp256k1_scalar_split_lambda_var(&l, &r, &data->scalar_x);
|
||||
secp256k1_scalar_split_lambda(&l, &r, &data->scalar_x);
|
||||
secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
|
||||
}
|
||||
}
|
||||
|
|
@ -229,7 +231,17 @@ void bench_ecmult_wnaf(void* arg) {
|
|||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_ecmult_wnaf(data->wnaf, &data->scalar_x, WINDOW_A);
|
||||
secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar_x, WINDOW_A);
|
||||
secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_wnaf_const(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_wnaf_const(data->wnaf, data->scalar_x, WINDOW_A);
|
||||
secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
|
||||
}
|
||||
}
|
||||
|
|
@ -265,7 +277,7 @@ void bench_rfc6979_hmac_sha256(void* arg) {
|
|||
secp256k1_rfc6979_hmac_sha256_t rng;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 32, data->data, 32, NULL, 0);
|
||||
secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64);
|
||||
secp256k1_rfc6979_hmac_sha256_generate(&rng, data->data, 32);
|
||||
}
|
||||
}
|
||||
|
|
@ -309,6 +321,7 @@ int main(int argc, char **argv) {
|
|||
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, 200000);
|
||||
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, 200000);
|
||||
|
||||
if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("wnaf_const", bench_wnaf_const, bench_setup, NULL, &data, 10, 20000);
|
||||
if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, 20000);
|
||||
|
||||
if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "sha256")) run_benchmark("hash_sha256", bench_sha256, bench_setup, NULL, &data, 10, 20000);
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "include/secp256k1.h"
|
||||
#include "include/secp256k1_rangeproof.h"
|
||||
#include "util.h"
|
||||
#include "bench.h"
|
||||
|
||||
|
|
@ -52,11 +52,13 @@ static void bench_rangeproof(void* arg) {
|
|||
int main(void) {
|
||||
bench_rangeproof_t data;
|
||||
|
||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_COMMIT | SECP256K1_CONTEXT_RANGEPROOF);
|
||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
secp256k1_pedersen_context_initialize(data.ctx);
|
||||
secp256k1_rangeproof_context_initialize(data.ctx);
|
||||
|
||||
data.min_bits = 32;
|
||||
|
||||
run_benchmark("rangeproof_verif_bit", bench_rangeproof, bench_rangeproof_setup, NULL, &data, 10, 1000 * data.min_bits);
|
||||
run_benchmark("rangeproof_verify_bit", bench_rangeproof, bench_rangeproof_setup, NULL, &data, 10, 1000 * data.min_bits);
|
||||
|
||||
secp256k1_context_destroy(data.ctx);
|
||||
return 0;
|
||||
|
|
@ -17,16 +17,20 @@ typedef struct {
|
|||
void bench_recover(void* arg) {
|
||||
int i;
|
||||
bench_recover_t *data = (bench_recover_t*)arg;
|
||||
unsigned char pubkey[33];
|
||||
secp256k1_pubkey_t pubkey;
|
||||
unsigned char pubkeyc[33];
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
int j;
|
||||
int pubkeylen = 33;
|
||||
CHECK(secp256k1_ecdsa_recover_compact(data->ctx, data->msg, data->sig, pubkey, &pubkeylen, 1, i % 2));
|
||||
secp256k1_ecdsa_signature_t sig;
|
||||
CHECK(secp256k1_ecdsa_signature_parse_compact(data->ctx, &sig, data->sig, i % 2));
|
||||
CHECK(secp256k1_ecdsa_recover(data->ctx, data->msg, &sig, &pubkey));
|
||||
CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, 1));
|
||||
for (j = 0; j < 32; j++) {
|
||||
data->sig[j + 32] = data->msg[j]; /* Move former message to S. */
|
||||
data->msg[j] = data->sig[j]; /* Move former R to message. */
|
||||
data->sig[j] = pubkey[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */
|
||||
data->sig[j] = pubkeyc[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */
|
||||
}
|
||||
}
|
||||
}
|
||||
69
src/bench_schnorr_verify.c
Normal file
69
src/bench_schnorr_verify.c
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "include/secp256k1.h"
|
||||
#include "include/secp256k1_schnorr.h"
|
||||
#include "util.h"
|
||||
#include "bench.h"
|
||||
|
||||
typedef struct {
|
||||
unsigned char key[32];
|
||||
unsigned char sig[64];
|
||||
unsigned char pubkey[33];
|
||||
int pubkeylen;
|
||||
} benchmark_schnorr_sig_t;
|
||||
|
||||
typedef struct {
|
||||
secp256k1_context_t *ctx;
|
||||
unsigned char msg[32];
|
||||
benchmark_schnorr_sig_t sigs[64];
|
||||
int numsigs;
|
||||
} benchmark_schnorr_verify_t;
|
||||
|
||||
static void benchmark_schnorr_init(void* arg) {
|
||||
int i, k;
|
||||
benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg;
|
||||
|
||||
for (i = 0; i < 32; i++) data->msg[i] = 1 + i;
|
||||
for (k = 0; k < data->numsigs; k++) {
|
||||
secp256k1_pubkey_t pubkey;
|
||||
for (i = 0; i < 32; i++) data->sigs[k].key[i] = 33 + i + k;
|
||||
secp256k1_schnorr_sign(data->ctx, data->msg, data->sigs[k].sig, data->sigs[k].key, NULL, NULL);
|
||||
data->sigs[k].pubkeylen = 33;
|
||||
CHECK(secp256k1_ec_pubkey_create(data->ctx, &pubkey, data->sigs[k].key));
|
||||
CHECK(secp256k1_ec_pubkey_serialize(data->ctx, data->sigs[k].pubkey, &data->sigs[k].pubkeylen, &pubkey, 1));
|
||||
}
|
||||
}
|
||||
|
||||
static void benchmark_schnorr_verify(void* arg) {
|
||||
int i;
|
||||
benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000 / data->numsigs; i++) {
|
||||
secp256k1_pubkey_t pubkey;
|
||||
data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF);
|
||||
CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->sigs[0].pubkey, data->sigs[0].pubkeylen));
|
||||
CHECK(secp256k1_schnorr_verify(data->ctx, data->msg, data->sigs[0].sig, &pubkey) == ((i & 0xFF) == 0));
|
||||
data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(void) {
|
||||
benchmark_schnorr_verify_t data;
|
||||
|
||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
|
||||
data.numsigs = 1;
|
||||
run_benchmark("schnorr_verify", benchmark_schnorr_verify, benchmark_schnorr_init, NULL, &data, 10, 20000);
|
||||
|
||||
secp256k1_context_destroy(data.ctx);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -30,7 +30,9 @@ static void bench_sign(void* arg) {
|
|||
for (i = 0; i < 20000; i++) {
|
||||
int j;
|
||||
int recid = 0;
|
||||
CHECK(secp256k1_ecdsa_sign_compact(data->ctx, data->msg, sig, data->key, NULL, NULL, &recid));
|
||||
secp256k1_ecdsa_signature_t signature;
|
||||
CHECK(secp256k1_ecdsa_sign(data->ctx, data->msg, &signature, data->key, NULL, NULL));
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_compact(data->ctx, sig, &recid, &signature));
|
||||
for (j = 0; j < 32; j++) {
|
||||
data->msg[j] = sig[j]; /* Move former R to message. */
|
||||
data->key[j] = sig[j + 32]; /* Move former S to key. */
|
||||
|
|
@ -26,10 +26,14 @@ static void benchmark_verify(void* arg) {
|
|||
benchmark_verify_t* data = (benchmark_verify_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_pubkey_t pubkey;
|
||||
secp256k1_ecdsa_signature_t sig;
|
||||
data->sig[data->siglen - 1] ^= (i & 0xFF);
|
||||
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
|
||||
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
|
||||
CHECK(secp256k1_ecdsa_verify(data->ctx, data->msg, data->sig, data->siglen, data->pubkey, data->pubkeylen) == (i == 0));
|
||||
CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(data->ctx, data->msg, &sig, &pubkey) == (i == 0));
|
||||
data->sig[data->siglen - 1] ^= (i & 0xFF);
|
||||
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
|
||||
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
|
||||
|
|
@ -38,6 +42,8 @@ static void benchmark_verify(void* arg) {
|
|||
|
||||
int main(void) {
|
||||
int i;
|
||||
secp256k1_pubkey_t pubkey;
|
||||
secp256k1_ecdsa_signature_t sig;
|
||||
benchmark_verify_t data;
|
||||
|
||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
|
|
@ -45,9 +51,10 @@ int main(void) {
|
|||
for (i = 0; i < 32; i++) data.msg[i] = 1 + i;
|
||||
for (i = 0; i < 32; i++) data.key[i] = 33 + i;
|
||||
data.siglen = 72;
|
||||
secp256k1_ecdsa_sign(data.ctx, data.msg, data.sig, &data.siglen, data.key, NULL, NULL);
|
||||
data.pubkeylen = 33;
|
||||
CHECK(secp256k1_ec_pubkey_create(data.ctx, data.pubkey, &data.pubkeylen, data.key, 1));
|
||||
CHECK(secp256k1_ecdsa_sign(data.ctx, data.msg, &sig, data.key, NULL, NULL));
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig));
|
||||
CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key));
|
||||
CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, 1) == 1);
|
||||
|
||||
run_benchmark("ecdsa_verify", benchmark_verify, NULL, NULL, &data, 10, 20000);
|
||||
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
#include <windows.h> // needed for VERSIONINFO
|
||||
#include "clientversion.h" // holds the needed client version information
|
||||
|
||||
#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD
|
||||
#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD)
|
||||
#define VER_FILEVERSION VER_PRODUCTVERSION
|
||||
#define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VER_FILEVERSION
|
||||
PRODUCTVERSION VER_PRODUCTVERSION
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904E4" // U.S. English - multilingual (hex)
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Bitcoin"
|
||||
VALUE "FileDescription", "Bitcoin-cli (OSS RPC client for Bitcoin)"
|
||||
VALUE "FileVersion", VER_FILEVERSION_STR
|
||||
VALUE "InternalName", "bitcoin-cli"
|
||||
VALUE "LegalCopyright", COPYRIGHT_STR
|
||||
VALUE "LegalTrademarks1", "Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php."
|
||||
VALUE "OriginalFilename", "bitcoin-cli.exe"
|
||||
VALUE "ProductName", "Bitcoin-cli"
|
||||
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
|
||||
END
|
||||
END
|
||||
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0, 1252 // language neutral - multilingual (decimal)
|
||||
END
|
||||
END
|
||||
|
|
@ -1,188 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2013 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "callrpc.h"
|
||||
#include "chainparamsbase.h"
|
||||
#include "clientversion.h"
|
||||
#include "util.h"
|
||||
#include "utilstrencodings.h"
|
||||
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
|
||||
#define _(x) std::string(x) /* Keep the _() around in case gettext or such will be used later to translate non-UI */
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
using namespace boost::asio;
|
||||
using namespace json_spirit;
|
||||
|
||||
std::string HelpMessageCli()
|
||||
{
|
||||
string strUsage;
|
||||
strUsage += _("Options:") + "\n";
|
||||
strUsage += " -? " + _("This help message") + "\n";
|
||||
strUsage += " -conf=<file> " + strprintf(_("Specify configuration file (default: %s)"), "bitcoin.conf") + "\n";
|
||||
strUsage += " -datadir=<dir> " + _("Specify data directory") + "\n";
|
||||
strUsage += " -testnet " + _("Use the test network") + "\n";
|
||||
strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be "
|
||||
"solved instantly. This is intended for regression testing tools and app development.") + "\n";
|
||||
strUsage += " -rpcconnect=<ip> " + strprintf(_("Send commands to node running on <ip> (default: %s)"), "127.0.0.1") + "\n";
|
||||
strUsage += " -rpcport=<port> " + strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), 8332, 18332) + "\n";
|
||||
strUsage += " -rpcwait " + _("Wait for RPC server to start") + "\n";
|
||||
strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n";
|
||||
strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n";
|
||||
|
||||
strUsage += "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n";
|
||||
strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n";
|
||||
|
||||
return strUsage;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Start
|
||||
//
|
||||
|
||||
static bool AppInitRPC(int argc, char* argv[])
|
||||
{
|
||||
//
|
||||
// Parameters
|
||||
//
|
||||
ParseParameters(argc, argv);
|
||||
if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version")) {
|
||||
std::string strUsage = _("Bitcoin Core RPC client version") + " " + FormatFullVersion() + "\n";
|
||||
if (!mapArgs.count("-version")) {
|
||||
strUsage += "\n" + _("Usage:") + "\n" +
|
||||
" bitcoin-cli [options] <command> [params] " + _("Send command to Bitcoin Core") + "\n" +
|
||||
" bitcoin-cli [options] help " + _("List commands") + "\n" +
|
||||
" bitcoin-cli [options] help <command> " + _("Get help for a command") + "\n";
|
||||
|
||||
strUsage += "\n" + HelpMessageCli();
|
||||
}
|
||||
|
||||
fprintf(stdout, "%s", strUsage.c_str());
|
||||
return false;
|
||||
}
|
||||
if (!boost::filesystem::is_directory(GetDataDir(false))) {
|
||||
fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str());
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
ReadConfigFile(mapArgs, mapMultiArgs);
|
||||
} catch(std::exception &e) {
|
||||
fprintf(stderr,"Error reading configuration file: %s\n", e.what());
|
||||
return false;
|
||||
}
|
||||
// Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause)
|
||||
if (!SelectBaseParamsFromCommandLine()) {
|
||||
fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int CommandLineRPC(int argc, char *argv[])
|
||||
{
|
||||
string strPrint;
|
||||
int nRet = 0;
|
||||
try {
|
||||
// Skip switches
|
||||
while (argc > 1 && IsSwitchChar(argv[1][0])) {
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
// Method
|
||||
if (argc < 2)
|
||||
throw runtime_error("too few parameters");
|
||||
string strMethod = argv[1];
|
||||
|
||||
// Parameters default to strings
|
||||
std::vector<std::string> strParams(&argv[2], &argv[argc]);
|
||||
Array params = RPCConvertValues(strMethod, strParams);
|
||||
|
||||
// Execute and handle connection failures with -rpcwait
|
||||
const bool fWait = GetBoolArg("-rpcwait", false);
|
||||
do {
|
||||
try {
|
||||
const Object reply = CallRPC(strMethod, params);
|
||||
|
||||
// Parse reply
|
||||
const Value& result = find_value(reply, "result");
|
||||
const Value& error = find_value(reply, "error");
|
||||
|
||||
if (error.type() != null_type) {
|
||||
// Error
|
||||
const int code = find_value(error.get_obj(), "code").get_int();
|
||||
if (fWait && code == RPC_IN_WARMUP)
|
||||
throw CConnectionFailed("server in warmup");
|
||||
strPrint = "error: " + write_string(error, false);
|
||||
nRet = abs(code);
|
||||
} else {
|
||||
// Result
|
||||
if (result.type() == null_type)
|
||||
strPrint = "";
|
||||
else if (result.type() == str_type)
|
||||
strPrint = result.get_str();
|
||||
else
|
||||
strPrint = write_string(result, true);
|
||||
}
|
||||
|
||||
// Connection succeeded, no need to retry.
|
||||
break;
|
||||
}
|
||||
catch (const CConnectionFailed& e) {
|
||||
if (fWait)
|
||||
MilliSleep(1000);
|
||||
else
|
||||
throw;
|
||||
}
|
||||
} while (fWait);
|
||||
}
|
||||
catch (boost::thread_interrupted) {
|
||||
throw;
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
strPrint = string("error: ") + e.what();
|
||||
nRet = EXIT_FAILURE;
|
||||
}
|
||||
catch (...) {
|
||||
PrintExceptionContinue(NULL, "CommandLineRPC()");
|
||||
throw;
|
||||
}
|
||||
|
||||
if (strPrint != "") {
|
||||
fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
|
||||
}
|
||||
return nRet;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
SetupEnvironment();
|
||||
|
||||
try {
|
||||
if(!AppInitRPC(argc, argv))
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
PrintExceptionContinue(&e, "AppInitRPC()");
|
||||
return EXIT_FAILURE;
|
||||
} catch (...) {
|
||||
PrintExceptionContinue(NULL, "AppInitRPC()");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int ret = EXIT_FAILURE;
|
||||
try {
|
||||
ret = CommandLineRPC(argc, argv);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
PrintExceptionContinue(&e, "CommandLineRPC()");
|
||||
} catch (...) {
|
||||
PrintExceptionContinue(NULL, "CommandLineRPC()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1,736 +0,0 @@
|
|||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "base58.h"
|
||||
#include "clientversion.h"
|
||||
#include "primitives/block.h" // for MAX_BLOCK_SIZE
|
||||
#include "primitives/transaction.h"
|
||||
#include "core_io.h"
|
||||
#include "coins.h"
|
||||
#include "keystore.h"
|
||||
#include "merkleblock.h"
|
||||
#include "script/script.h"
|
||||
#include "script/sign.h"
|
||||
#include "streams.h"
|
||||
#include "ui_interface.h" // for _(...)
|
||||
#include "univalue/univalue.h"
|
||||
#include "util.h"
|
||||
#include "utilstrencodings.h"
|
||||
#include "utilmoneystr.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/assign/list_of.hpp>
|
||||
|
||||
using namespace boost::assign;
|
||||
using namespace std;
|
||||
|
||||
static bool fCreateBlank;
|
||||
static map<string,UniValue> registers;
|
||||
CClientUIInterface uiInterface;
|
||||
|
||||
static bool AppInitRawTx(int argc, char* argv[])
|
||||
{
|
||||
//
|
||||
// Parameters
|
||||
//
|
||||
ParseParameters(argc, argv);
|
||||
|
||||
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
|
||||
if (!SelectParamsFromCommandLine()) {
|
||||
fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
fCreateBlank = GetBoolArg("-create", false);
|
||||
|
||||
if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help"))
|
||||
{
|
||||
// First part of help message is specific to this utility
|
||||
std::string strUsage = _("Bitcoin Core bitcoin-tx utility version") + " " + FormatFullVersion() + "\n\n" +
|
||||
_("Usage:") + "\n" +
|
||||
" bitcoin-tx [options] <hex-tx> [commands] " + _("Update hex-encoded bitcoin transaction") + "\n" +
|
||||
" bitcoin-tx [options] -create [commands] " + _("Create hex-encoded bitcoin transaction") + "\n" +
|
||||
"\n";
|
||||
|
||||
fprintf(stdout, "%s", strUsage.c_str());
|
||||
|
||||
strUsage = _("Options:") + "\n";
|
||||
strUsage += " -? " + _("This help message") + "\n";
|
||||
strUsage += " -create " + _("Create new, empty TX.") + "\n";
|
||||
strUsage += " -json " + _("Select JSON output") + "\n";
|
||||
strUsage += " -txid " + _("Output only the hex-encoded transaction id of the resultant transaction.") + "\n";
|
||||
strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n";
|
||||
strUsage += " -testnet " + _("Use the test network") + "\n";
|
||||
strUsage += "\n";
|
||||
|
||||
fprintf(stdout, "%s", strUsage.c_str());
|
||||
|
||||
|
||||
strUsage = _("Commands:") + "\n";
|
||||
strUsage += " delin=N " + _("Delete input N from TX") + "\n";
|
||||
strUsage += " delout=N " + _("Delete output N from TX") + "\n";
|
||||
strUsage += " in=TXID:VOUT[:SEQ] " + _("Add input to TX") + "\n";
|
||||
strUsage += " locktime=N " + _("Set TX lock time to N") + "\n";
|
||||
strUsage += " nversion=N " + _("Set TX version to N") + "\n";
|
||||
strUsage += " outaddr=VALUE:ADDRESS " + _("Add address-based output to TX") + "\n";
|
||||
strUsage += " outscript=VALUE:SCRIPT " + _("Add raw script output to TX") + "\n";
|
||||
strUsage += " sign=SIGHASH-FLAGS " + _("Add zero or more signatures to transaction") + "\n";
|
||||
strUsage += " This command requires JSON registers:\n";
|
||||
strUsage += " prevtxs=JSON object\n";
|
||||
strUsage += " privatekeys=JSON object\n";
|
||||
strUsage += " See signrawtransaction docs for format of sighash flags, JSON objects.\n";
|
||||
strUsage += "\n";
|
||||
fprintf(stdout, "%s", strUsage.c_str());
|
||||
|
||||
strUsage = _("Register Commands:") + "\n";
|
||||
strUsage += " load=NAME:FILENAME " + _("Load JSON file FILENAME into register NAME") + "\n";
|
||||
strUsage += " set=NAME:JSON-STRING " + _("Set register NAME to given JSON-STRING") + "\n";
|
||||
strUsage += "\n";
|
||||
fprintf(stdout, "%s", strUsage.c_str());
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void RegisterSetJson(const string& key, const string& rawJson)
|
||||
{
|
||||
UniValue val;
|
||||
if (!val.read(rawJson)) {
|
||||
string strErr = "Cannot parse JSON for key " + key;
|
||||
throw runtime_error(strErr);
|
||||
}
|
||||
|
||||
registers[key] = val;
|
||||
}
|
||||
|
||||
static void RegisterSet(const string& strInput)
|
||||
{
|
||||
// separate NAME:VALUE in string
|
||||
size_t pos = strInput.find(':');
|
||||
if ((pos == string::npos) ||
|
||||
(pos == 0) ||
|
||||
(pos == (strInput.size() - 1)))
|
||||
throw runtime_error("Register input requires NAME:VALUE");
|
||||
|
||||
string key = strInput.substr(0, pos);
|
||||
string valStr = strInput.substr(pos + 1, string::npos);
|
||||
|
||||
RegisterSetJson(key, valStr);
|
||||
}
|
||||
|
||||
static void RegisterLoad(const string& strInput)
|
||||
{
|
||||
// separate NAME:FILENAME in string
|
||||
size_t pos = strInput.find(':');
|
||||
if ((pos == string::npos) ||
|
||||
(pos == 0) ||
|
||||
(pos == (strInput.size() - 1)))
|
||||
throw runtime_error("Register load requires NAME:FILENAME");
|
||||
|
||||
string key = strInput.substr(0, pos);
|
||||
string filename = strInput.substr(pos + 1, string::npos);
|
||||
|
||||
FILE *f = fopen(filename.c_str(), "r");
|
||||
if (!f) {
|
||||
string strErr = "Cannot open file " + filename;
|
||||
throw runtime_error(strErr);
|
||||
}
|
||||
|
||||
// load file chunks into one big buffer
|
||||
string valStr;
|
||||
while ((!feof(f)) && (!ferror(f))) {
|
||||
char buf[4096];
|
||||
int bread = fread(buf, 1, sizeof(buf), f);
|
||||
if (bread <= 0)
|
||||
break;
|
||||
|
||||
valStr.insert(valStr.size(), buf, bread);
|
||||
}
|
||||
|
||||
if (ferror(f)) {
|
||||
string strErr = "Error reading file " + filename;
|
||||
throw runtime_error(strErr);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
// evaluate as JSON buffer register
|
||||
RegisterSetJson(key, valStr);
|
||||
}
|
||||
|
||||
static void MutateTxVersion(CMutableTransaction& tx, const string& cmdVal)
|
||||
{
|
||||
int64_t newVersion = atoi64(cmdVal);
|
||||
if (newVersion < 1 || newVersion > CTransaction::CURRENT_VERSION)
|
||||
throw runtime_error("Invalid TX version requested");
|
||||
|
||||
tx.nVersion = (int) newVersion;
|
||||
}
|
||||
|
||||
static void MutateTxLocktime(CMutableTransaction& tx, const string& cmdVal)
|
||||
{
|
||||
int64_t newLocktime = atoi64(cmdVal);
|
||||
if (newLocktime < 0LL || newLocktime > 0xffffffffLL)
|
||||
throw runtime_error("Invalid TX locktime requested");
|
||||
|
||||
tx.nLockTime = (unsigned int) newLocktime;
|
||||
}
|
||||
|
||||
static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput)
|
||||
{
|
||||
// separate TXID:VOUT in string
|
||||
size_t pos = strInput.find(':');
|
||||
if ((pos == string::npos) ||
|
||||
(pos == 0) ||
|
||||
(pos == (strInput.size() - 1)))
|
||||
throw runtime_error("TX input missing separator");
|
||||
|
||||
// extract and validate TXID
|
||||
string strTxid = strInput.substr(0, pos);
|
||||
if ((strTxid.size() != 64) || !IsHex(strTxid))
|
||||
throw runtime_error("invalid TX input txid");
|
||||
uint256 txid(strTxid);
|
||||
|
||||
static const unsigned int minTxOutSz = 9;
|
||||
static const unsigned int maxVout = MAX_BLOCK_SIZE / minTxOutSz;
|
||||
|
||||
// Remove txid
|
||||
string strVout = strInput.substr(pos + 1, string::npos);
|
||||
|
||||
// extract and validate sequence number
|
||||
uint32_t nSequence = ~(uint32_t)0;
|
||||
pos = strVout.find(':');
|
||||
if (pos != string::npos) {
|
||||
if ((pos == 0) || (pos == (strVout.size() - 1)))
|
||||
throw runtime_error("empty TX input field");
|
||||
|
||||
string strSeq = strVout.substr(pos + 1, string::npos);
|
||||
strVout.resize(pos);
|
||||
int64_t nSeq = atoi64(strSeq);
|
||||
|
||||
// Allow e.g. -1 to be used for 0xffffffff
|
||||
if (nSeq < 0)
|
||||
nSeq += ((int64_t)std::numeric_limits<uint32_t>::max()) + 1;
|
||||
|
||||
// Range check
|
||||
if (nSeq < std::numeric_limits<uint32_t>::min() ||
|
||||
nSeq > std::numeric_limits<uint32_t>::max())
|
||||
{
|
||||
throw runtime_error("invalid TX input sequence");
|
||||
}
|
||||
|
||||
nSequence = (uint32_t)nSeq;
|
||||
}
|
||||
|
||||
// extract and validate vout
|
||||
int vout = atoi(strVout);
|
||||
if ((vout < 0) || (vout > (int)maxVout))
|
||||
throw runtime_error("invalid TX input vout");
|
||||
|
||||
// append to transaction input list
|
||||
CTxIn txin(txid, vout, CScript(), nSequence);
|
||||
tx.vin.push_back(txin);
|
||||
}
|
||||
|
||||
static void MutateTxAddOutAddr(CMutableTransaction& tx, const string& strInput)
|
||||
{
|
||||
// separate VALUE:ADDRESS in string
|
||||
size_t pos = strInput.find(':');
|
||||
if ((pos == string::npos) ||
|
||||
(pos == 0) ||
|
||||
(pos == (strInput.size() - 1)))
|
||||
throw runtime_error("TX output missing separator");
|
||||
|
||||
// extract and validate VALUE
|
||||
string strValue = strInput.substr(0, pos);
|
||||
CAmount value;
|
||||
if (!ParseMoney(strValue, value))
|
||||
throw runtime_error("invalid TX output value");
|
||||
|
||||
// extract and validate ADDRESS
|
||||
string strAddr = strInput.substr(pos + 1, string::npos);
|
||||
CBitcoinAddress addr(strAddr);
|
||||
if (!addr.IsValid())
|
||||
throw runtime_error("invalid TX output address");
|
||||
|
||||
// build standard output script via GetScriptForDestination()
|
||||
CScript scriptPubKey = GetScriptForDestination(addr.Get());
|
||||
|
||||
// construct TxOut, append to transaction output list
|
||||
CTxOut txout(value, scriptPubKey);
|
||||
tx.vout.push_back(txout);
|
||||
}
|
||||
|
||||
static void MutateTxAddOutScript(CMutableTransaction& tx, const string& strInput)
|
||||
{
|
||||
// separate VALUE:SCRIPT in string
|
||||
size_t pos = strInput.find(':');
|
||||
if ((pos == string::npos) ||
|
||||
(pos == 0))
|
||||
throw runtime_error("TX output missing separator");
|
||||
|
||||
// extract and validate VALUE
|
||||
string strValue = strInput.substr(0, pos);
|
||||
CAmount value;
|
||||
if (!ParseMoney(strValue, value))
|
||||
throw runtime_error("invalid TX output value");
|
||||
|
||||
// extract and validate script
|
||||
string strScript = strInput.substr(pos + 1, string::npos);
|
||||
CScript scriptPubKey = ParseScript(strScript); // throws on err
|
||||
|
||||
// construct TxOut, append to transaction output list
|
||||
CTxOut txout(value, scriptPubKey);
|
||||
tx.vout.push_back(txout);
|
||||
}
|
||||
|
||||
static void MutateTxDelInput(CMutableTransaction& tx, const string& strInIdx)
|
||||
{
|
||||
// parse requested deletion index
|
||||
int inIdx = atoi(strInIdx);
|
||||
if (inIdx < 0 || inIdx >= (int)tx.vin.size()) {
|
||||
string strErr = "Invalid TX input index '" + strInIdx + "'";
|
||||
throw runtime_error(strErr.c_str());
|
||||
}
|
||||
|
||||
// delete input from transaction
|
||||
tx.vin.erase(tx.vin.begin() + inIdx);
|
||||
}
|
||||
|
||||
static void MutateTxDelOutput(CMutableTransaction& tx, const string& strOutIdx)
|
||||
{
|
||||
// parse requested deletion index
|
||||
int outIdx = atoi(strOutIdx);
|
||||
if (outIdx < 0 || outIdx >= (int)tx.vout.size()) {
|
||||
string strErr = "Invalid TX output index '" + strOutIdx + "'";
|
||||
throw runtime_error(strErr.c_str());
|
||||
}
|
||||
|
||||
// delete output from transaction
|
||||
tx.vout.erase(tx.vout.begin() + outIdx);
|
||||
}
|
||||
|
||||
static const unsigned int N_SIGHASH_OPTS = 6;
|
||||
static const struct {
|
||||
const char *flagStr;
|
||||
int flags;
|
||||
} sighashOptions[N_SIGHASH_OPTS] = {
|
||||
{"ALL", SIGHASH_ALL},
|
||||
{"NONE", SIGHASH_NONE},
|
||||
{"SINGLE", SIGHASH_SINGLE},
|
||||
{"ALL|ANYONECANPAY", SIGHASH_ALL|SIGHASH_ANYONECANPAY},
|
||||
{"NONE|ANYONECANPAY", SIGHASH_NONE|SIGHASH_ANYONECANPAY},
|
||||
{"SINGLE|ANYONECANPAY", SIGHASH_SINGLE|SIGHASH_ANYONECANPAY},
|
||||
};
|
||||
|
||||
static bool findSighashFlags(int& flags, const string& flagStr)
|
||||
{
|
||||
flags = 0;
|
||||
|
||||
for (unsigned int i = 0; i < N_SIGHASH_OPTS; i++) {
|
||||
if (flagStr == sighashOptions[i].flagStr) {
|
||||
flags = sighashOptions[i].flags;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint256 ParseHashUO(map<string,UniValue>& o, string strKey)
|
||||
{
|
||||
if (!o.count(strKey))
|
||||
return 0;
|
||||
return ParseHashUV(o[strKey], strKey);
|
||||
}
|
||||
|
||||
vector<unsigned char> ParseHexUO(map<string,UniValue>& o, string strKey)
|
||||
{
|
||||
if (!o.count(strKey)) {
|
||||
vector<unsigned char> emptyVec;
|
||||
return emptyVec;
|
||||
}
|
||||
return ParseHexUV(o[strKey], strKey);
|
||||
}
|
||||
|
||||
static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
|
||||
{
|
||||
int nHashType = SIGHASH_ALL;
|
||||
|
||||
if (flagStr.size() > 0)
|
||||
if (!findSighashFlags(nHashType, flagStr))
|
||||
throw runtime_error("unknown sighash flag/sign option");
|
||||
|
||||
vector<CTransaction> txVariants;
|
||||
txVariants.push_back(tx);
|
||||
|
||||
// mergedTx will end up with all the signatures; it
|
||||
// starts as a clone of the raw tx:
|
||||
CMutableTransaction mergedTx(txVariants[0]);
|
||||
bool fComplete = true;
|
||||
CCoinsView viewDummy;
|
||||
CCoinsViewCache view(&viewDummy);
|
||||
|
||||
if (!registers.count("privatekeys"))
|
||||
throw runtime_error("privatekeys register variable must be set.");
|
||||
bool fGivenKeys = false;
|
||||
CBasicKeyStore tempKeystore;
|
||||
UniValue keysObj = registers["privatekeys"];
|
||||
fGivenKeys = true;
|
||||
|
||||
for (unsigned int kidx = 0; kidx < keysObj.count(); kidx++) {
|
||||
if (!keysObj[kidx].isStr())
|
||||
throw runtime_error("privatekey not a string");
|
||||
CBitcoinSecret vchSecret;
|
||||
bool fGood = vchSecret.SetString(keysObj[kidx].getValStr());
|
||||
if (!fGood)
|
||||
throw runtime_error("privatekey not valid");
|
||||
|
||||
CKey key = vchSecret.GetKey();
|
||||
tempKeystore.AddKey(key);
|
||||
}
|
||||
|
||||
// Add previous txouts given in the RPC call:
|
||||
if (!registers.count("prevtxs"))
|
||||
throw runtime_error("prevtxs register variable must be set.");
|
||||
UniValue prevtxsObj = registers["prevtxs"];
|
||||
{
|
||||
for (unsigned int previdx = 0; previdx < prevtxsObj.count(); previdx++) {
|
||||
UniValue prevOut = prevtxsObj[previdx];
|
||||
if (!prevOut.isObject())
|
||||
throw runtime_error("expected prevtxs internal object");
|
||||
|
||||
map<string,UniValue::VType> types = map_list_of("txid", UniValue::VSTR)("vout",UniValue::VNUM)("scriptPubKey",UniValue::VSTR);
|
||||
if (!prevOut.checkObject(types))
|
||||
throw runtime_error("prevtxs internal object typecheck fail");
|
||||
|
||||
uint256 txid = ParseHashUV(prevOut["txid"], "txid");
|
||||
|
||||
int nOut = atoi(prevOut["vout"].getValStr());
|
||||
if (nOut < 0)
|
||||
throw runtime_error("vout must be positive");
|
||||
|
||||
vector<unsigned char> pkData(ParseHexUV(prevOut["scriptPubKey"], "scriptPubKey"));
|
||||
CScript scriptPubKey(pkData.begin(), pkData.end());
|
||||
|
||||
{
|
||||
CCoinsModifier coins = view.ModifyCoins(txid);
|
||||
if (coins->IsAvailable(nOut) && coins->vout[nOut].scriptPubKey != scriptPubKey) {
|
||||
string err("Previous output scriptPubKey mismatch:\n");
|
||||
err = err + coins->vout[nOut].scriptPubKey.ToString() + "\nvs:\n"+
|
||||
scriptPubKey.ToString();
|
||||
throw runtime_error(err);
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
// if redeemScript given and private keys given,
|
||||
// add redeemScript to the tempKeystore so it can be signed:
|
||||
if (fGivenKeys && scriptPubKey.IsPayToScriptHash() &&
|
||||
prevOut.exists("redeemScript")) {
|
||||
UniValue v = prevOut["redeemScript"];
|
||||
vector<unsigned char> rsData(ParseHexUV(v, "redeemScript"));
|
||||
CScript redeemScript(rsData.begin(), rsData.end());
|
||||
tempKeystore.AddCScript(redeemScript);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const CKeyStore& keystore = tempKeystore;
|
||||
|
||||
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
|
||||
|
||||
// Sign what we can:
|
||||
for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
|
||||
CTxIn& txin = mergedTx.vin[i];
|
||||
const CCoins* coins = view.AccessCoins(txin.prevout.hash);
|
||||
if (!coins || !coins->IsAvailable(txin.prevout.n)) {
|
||||
fComplete = false;
|
||||
continue;
|
||||
}
|
||||
const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
|
||||
|
||||
txin.scriptSig.clear();
|
||||
// Only sign SIGHASH_SINGLE if there's a corresponding output:
|
||||
if (!fHashSingle || (i < mergedTx.vout.size()))
|
||||
SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
|
||||
|
||||
// ... 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, MutableTransactionNoWithdrawsSignatureChecker(&mergedTx, i)))
|
||||
fComplete = false;
|
||||
}
|
||||
|
||||
if (fComplete) {
|
||||
// do nothing... for now
|
||||
// perhaps store this for later optional JSON output
|
||||
}
|
||||
|
||||
tx = mergedTx;
|
||||
}
|
||||
|
||||
static CScript GetScriptFromValue(const UniValue& v, const string& name)
|
||||
{
|
||||
if (v.isObject() && v[name].isStr()) {
|
||||
string str = v[name].getValStr();
|
||||
try {
|
||||
return ParseScript(str);
|
||||
} catch (std::exception& e) {}
|
||||
}
|
||||
throw runtime_error(name+" must be a script");
|
||||
}
|
||||
|
||||
static void MutateTxWithdrawSign(CMutableTransaction& tx, const string& flagStr)
|
||||
{
|
||||
if (!registers.count("withdrawkeys"))
|
||||
throw runtime_error("withdrawkeys register variable must be set.");
|
||||
UniValue keysObj = registers["withdrawkeys"];
|
||||
|
||||
if (!keysObj.isObject())
|
||||
throw runtime_error("withdrawkeysObjs must be an object");
|
||||
map<string,UniValue::VType> types = map_list_of("contract",UniValue::VSTR)("txoutproof",UniValue::VSTR)("tx",UniValue::VSTR)("nout",UniValue::VNUM)
|
||||
("secondScriptSig",UniValue::VSTR)("secondScriptPubKey",UniValue::VSTR)("coinbase",UniValue::VSTR);
|
||||
if (!keysObj.checkObject(types))
|
||||
throw runtime_error("withdrawkeysObjs internal object typecheck fail");
|
||||
|
||||
vector<unsigned char> contractData(ParseHexUV(keysObj["contract"], "contract"));
|
||||
vector<unsigned char> txoutproofData(ParseHexUV(keysObj["txoutproof"], "txoutproof"));
|
||||
vector<unsigned char> txData(ParseHexUV(keysObj["tx"], "tx"));
|
||||
vector<unsigned char> coinbaseTxData(ParseHexUV(keysObj["coinbase"], "coinbase"));
|
||||
CScript secondScriptSig(GetScriptFromValue(keysObj, "secondScriptSig"));
|
||||
CScript secondScriptPubKey(GetScriptFromValue(keysObj, "secondScriptPubKey"));
|
||||
int nOut = atoi(keysObj["nout"].getValStr());
|
||||
|
||||
if (contractData.size() != 40)
|
||||
throw runtime_error("contract must be 40 bytes");
|
||||
|
||||
CDataStream ssProof(txoutproofData, SER_NETWORK, PROTOCOL_VERSION);
|
||||
CMerkleBlock merkleBlock;
|
||||
merkleBlock.header.SetBitcoinBlock();
|
||||
ssProof >> merkleBlock;
|
||||
|
||||
CDataStream ssTx(txData, SER_NETWORK, PROTOCOL_VERSION);
|
||||
CTransaction txBTC;
|
||||
ssTx >> txBTC;
|
||||
|
||||
CDataStream ssCoinbaseTx(coinbaseTxData, SER_NETWORK, PROTOCOL_VERSION);
|
||||
CTransaction coinbaseTxBTC;
|
||||
ssCoinbaseTx >> coinbaseTxBTC;
|
||||
|
||||
vector<uint256> transactionHashes;
|
||||
if (merkleBlock.txn.ExtractMatches(transactionHashes) != merkleBlock.header.hashMerkleRoot ||
|
||||
transactionHashes.size() != 2 ||
|
||||
transactionHashes[0] != coinbaseTxBTC.GetHash() ||
|
||||
transactionHashes[1] != txBTC.GetHash())
|
||||
throw runtime_error("txoutproof is invalid or did not match tx");
|
||||
|
||||
if (nOut < 0 || (unsigned int) nOut >= txBTC.vout.size())
|
||||
throw runtime_error("nout must be >= 0, < txout count");
|
||||
|
||||
CScript scriptSig;
|
||||
scriptSig << vector<unsigned char>(secondScriptPubKey.begin(), secondScriptPubKey.end()) << vector<unsigned char>(secondScriptSig.begin(), secondScriptSig.end()) << contractData;
|
||||
scriptSig.PushWithdraw(txoutproofData);
|
||||
scriptSig.PushWithdraw(txData);
|
||||
scriptSig << nOut;
|
||||
scriptSig.PushWithdraw(coinbaseTxData);
|
||||
|
||||
//TODO: Verify the withdraw proof
|
||||
for (unsigned int i = 0; i < tx.vin.size(); i++) {
|
||||
tx.vin[i].scriptSig = scriptSig;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void MutateTx(CMutableTransaction& tx, const string& command,
|
||||
const string& commandVal)
|
||||
{
|
||||
if (command == "nversion")
|
||||
MutateTxVersion(tx, commandVal);
|
||||
else if (command == "locktime")
|
||||
MutateTxLocktime(tx, commandVal);
|
||||
|
||||
else if (command == "delin")
|
||||
MutateTxDelInput(tx, commandVal);
|
||||
else if (command == "in")
|
||||
MutateTxAddInput(tx, commandVal);
|
||||
|
||||
else if (command == "delout")
|
||||
MutateTxDelOutput(tx, commandVal);
|
||||
else if (command == "outaddr")
|
||||
MutateTxAddOutAddr(tx, commandVal);
|
||||
else if (command == "outscript")
|
||||
MutateTxAddOutScript(tx, commandVal);
|
||||
|
||||
else if (command == "sign")
|
||||
MutateTxSign(tx, commandVal);
|
||||
else if (command == "withdrawsign")
|
||||
MutateTxWithdrawSign(tx, commandVal);
|
||||
|
||||
else if (command == "load")
|
||||
RegisterLoad(commandVal);
|
||||
|
||||
else if (command == "set")
|
||||
RegisterSet(commandVal);
|
||||
|
||||
else
|
||||
throw runtime_error("unknown command");
|
||||
}
|
||||
|
||||
static void OutputTxJSON(const CTransaction& tx)
|
||||
{
|
||||
UniValue entry(UniValue::VOBJ);
|
||||
TxToUniv(tx, 0, entry);
|
||||
|
||||
string jsonOutput = entry.write(4);
|
||||
fprintf(stdout, "%s\n", jsonOutput.c_str());
|
||||
}
|
||||
|
||||
static void OutputTxHash(const CTransaction& tx)
|
||||
{
|
||||
string strHexHash = tx.GetHash().GetHex(); // the hex-encoded transaction hash (aka the transaction id)
|
||||
|
||||
fprintf(stdout, "%s\n", strHexHash.c_str());
|
||||
}
|
||||
|
||||
static void OutputTxHex(const CTransaction& tx)
|
||||
{
|
||||
string strHex = EncodeHexTx(tx);
|
||||
|
||||
fprintf(stdout, "%s\n", strHex.c_str());
|
||||
}
|
||||
|
||||
static void OutputTx(const CTransaction& tx)
|
||||
{
|
||||
if (GetBoolArg("-json", false))
|
||||
OutputTxJSON(tx);
|
||||
else if (GetBoolArg("-txid", false))
|
||||
OutputTxHash(tx);
|
||||
else
|
||||
OutputTxHex(tx);
|
||||
}
|
||||
|
||||
static string readStdin()
|
||||
{
|
||||
char buf[4096];
|
||||
string ret;
|
||||
|
||||
while (!feof(stdin)) {
|
||||
size_t bread = fread(buf, 1, sizeof(buf), stdin);
|
||||
ret.append(buf, bread);
|
||||
if (bread < sizeof(buf))
|
||||
break;
|
||||
}
|
||||
|
||||
if (ferror(stdin))
|
||||
throw runtime_error("error reading stdin");
|
||||
|
||||
boost::algorithm::trim_right(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int CommandLineRawTx(int argc, char* argv[])
|
||||
{
|
||||
string strPrint;
|
||||
int nRet = 0;
|
||||
try {
|
||||
// Skip switches; Permit common stdin convention "-"
|
||||
while (argc > 1 && IsSwitchChar(argv[1][0]) &&
|
||||
(argv[1][1] != 0)) {
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
CTransaction txDecodeTmp;
|
||||
int startArg;
|
||||
|
||||
if (!fCreateBlank) {
|
||||
// require at least one param
|
||||
if (argc < 2)
|
||||
throw runtime_error("too few parameters");
|
||||
|
||||
// param: hex-encoded bitcoin transaction
|
||||
string strHexTx(argv[1]);
|
||||
if (strHexTx == "-") // "-" implies standard input
|
||||
strHexTx = readStdin();
|
||||
|
||||
if (!DecodeHexTx(txDecodeTmp, strHexTx))
|
||||
throw runtime_error("invalid transaction encoding");
|
||||
|
||||
startArg = 2;
|
||||
} else
|
||||
startArg = 1;
|
||||
|
||||
CMutableTransaction tx(txDecodeTmp);
|
||||
|
||||
for (int i = startArg; i < argc; i++) {
|
||||
string arg = argv[i];
|
||||
string key, value;
|
||||
size_t eqpos = arg.find('=');
|
||||
if (eqpos == string::npos)
|
||||
key = arg;
|
||||
else {
|
||||
key = arg.substr(0, eqpos);
|
||||
value = arg.substr(eqpos + 1);
|
||||
}
|
||||
|
||||
MutateTx(tx, key, value);
|
||||
}
|
||||
|
||||
OutputTx(tx);
|
||||
}
|
||||
|
||||
catch (boost::thread_interrupted) {
|
||||
throw;
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
strPrint = string("error: ") + e.what();
|
||||
nRet = EXIT_FAILURE;
|
||||
}
|
||||
catch (...) {
|
||||
PrintExceptionContinue(NULL, "CommandLineRawTx()");
|
||||
throw;
|
||||
}
|
||||
|
||||
if (strPrint != "") {
|
||||
fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
|
||||
}
|
||||
return nRet;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
SetupEnvironment();
|
||||
|
||||
try {
|
||||
if(!AppInitRawTx(argc, argv))
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
PrintExceptionContinue(&e, "AppInitRawTx()");
|
||||
return EXIT_FAILURE;
|
||||
} catch (...) {
|
||||
PrintExceptionContinue(NULL, "AppInitRawTx()");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int ret = EXIT_FAILURE;
|
||||
try {
|
||||
ret = CommandLineRawTx(argc, argv);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
PrintExceptionContinue(&e, "CommandLineRawTx()");
|
||||
} catch (...) {
|
||||
PrintExceptionContinue(NULL, "CommandLineRawTx()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
#include <windows.h> // needed for VERSIONINFO
|
||||
#include "clientversion.h" // holds the needed client version information
|
||||
|
||||
#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD
|
||||
#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD)
|
||||
#define VER_FILEVERSION VER_PRODUCTVERSION
|
||||
#define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VER_FILEVERSION
|
||||
PRODUCTVERSION VER_PRODUCTVERSION
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904E4" // U.S. English - multilingual (hex)
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Bitcoin"
|
||||
VALUE "FileDescription", "Bitcoind (OSS daemon/client for Bitcoin)"
|
||||
VALUE "FileVersion", VER_FILEVERSION_STR
|
||||
VALUE "InternalName", "bitcoind"
|
||||
VALUE "LegalCopyright", COPYRIGHT_STR
|
||||
VALUE "LegalTrademarks1", "Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php."
|
||||
VALUE "OriginalFilename", "bitcoind.exe"
|
||||
VALUE "ProductName", "Bitcoind"
|
||||
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
|
||||
END
|
||||
END
|
||||
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0, 1252 // language neutral - multilingual (decimal)
|
||||
END
|
||||
END
|
||||
186
src/bitcoind.cpp
186
src/bitcoind.cpp
|
|
@ -1,186 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2013 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "clientversion.h"
|
||||
#include "rpcserver.h"
|
||||
#include "init.h"
|
||||
#include "main.h"
|
||||
#include "noui.h"
|
||||
#include "ui_interface.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
/* Introduction text for doxygen: */
|
||||
|
||||
/*! \mainpage Developer documentation
|
||||
*
|
||||
* \section intro_sec Introduction
|
||||
*
|
||||
* This is the developer documentation of the reference client for an experimental new digital currency called Bitcoin (http://www.bitcoin.org/),
|
||||
* which enables instant payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer technology to operate
|
||||
* with no central authority: managing transactions and issuing money are carried out collectively by the network.
|
||||
*
|
||||
* The software is a community-driven open source project, released under the MIT license.
|
||||
*
|
||||
* \section Navigation
|
||||
* Use the buttons <code>Namespaces</code>, <code>Classes</code> or <code>Files</code> at the top of the page to start navigating the code.
|
||||
*/
|
||||
|
||||
static bool fDaemon;
|
||||
|
||||
void DetectShutdownThread(boost::thread_group* threadGroup)
|
||||
{
|
||||
bool fShutdown = ShutdownRequested();
|
||||
// Tell the main threads to shutdown.
|
||||
while (!fShutdown)
|
||||
{
|
||||
MilliSleep(200);
|
||||
fShutdown = ShutdownRequested();
|
||||
}
|
||||
if (threadGroup)
|
||||
{
|
||||
threadGroup->interrupt_all();
|
||||
threadGroup->join_all();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Start
|
||||
//
|
||||
bool AppInit(int argc, char* argv[])
|
||||
{
|
||||
boost::thread_group threadGroup;
|
||||
boost::thread* detectShutdownThread = NULL;
|
||||
|
||||
bool fRet = false;
|
||||
|
||||
//
|
||||
// Parameters
|
||||
//
|
||||
// If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
|
||||
ParseParameters(argc, argv);
|
||||
|
||||
// Process help and version before taking care about datadir
|
||||
if (mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version"))
|
||||
{
|
||||
std::string strUsage = _("Bitcoin Core Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n";
|
||||
|
||||
if (mapArgs.count("-version"))
|
||||
{
|
||||
strUsage += LicenseInfo();
|
||||
}
|
||||
else
|
||||
{
|
||||
strUsage += "\n" + _("Usage:") + "\n" +
|
||||
" bitcoind [options] " + _("Start Bitcoin Core Daemon") + "\n";
|
||||
|
||||
strUsage += "\n" + HelpMessage(HMM_BITCOIND);
|
||||
}
|
||||
|
||||
fprintf(stdout, "%s", strUsage.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!boost::filesystem::is_directory(GetDataDir(false)))
|
||||
{
|
||||
fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str());
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
ReadConfigFile(mapArgs, mapMultiArgs);
|
||||
} catch(std::exception &e) {
|
||||
fprintf(stderr,"Error reading configuration file: %s\n", e.what());
|
||||
return false;
|
||||
}
|
||||
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
|
||||
if (!SelectParamsFromCommandLine()) {
|
||||
fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Command-line RPC
|
||||
bool fCommandLine = false;
|
||||
for (int i = 1; i < argc; i++)
|
||||
if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "bitcoin:"))
|
||||
fCommandLine = true;
|
||||
|
||||
if (fCommandLine)
|
||||
{
|
||||
fprintf(stderr, "Error: There is no RPC client functionality in bitcoind anymore. Use the bitcoin-cli utility instead.\n");
|
||||
exit(1);
|
||||
}
|
||||
#ifndef WIN32
|
||||
fDaemon = GetBoolArg("-daemon", false);
|
||||
if (fDaemon)
|
||||
{
|
||||
fprintf(stdout, "Bitcoin server starting\n");
|
||||
|
||||
// Daemonize
|
||||
pid_t pid = fork();
|
||||
if (pid < 0)
|
||||
{
|
||||
fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno);
|
||||
return false;
|
||||
}
|
||||
if (pid > 0) // Parent process, pid is child process id
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Child process falls through to rest of initialization
|
||||
|
||||
pid_t sid = setsid();
|
||||
if (sid < 0)
|
||||
fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno);
|
||||
}
|
||||
#endif
|
||||
SoftSetBoolArg("-server", true);
|
||||
|
||||
detectShutdownThread = new boost::thread(boost::bind(&DetectShutdownThread, &threadGroup));
|
||||
fRet = AppInit2(threadGroup);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
PrintExceptionContinue(&e, "AppInit()");
|
||||
} catch (...) {
|
||||
PrintExceptionContinue(NULL, "AppInit()");
|
||||
}
|
||||
|
||||
if (!fRet)
|
||||
{
|
||||
if (detectShutdownThread)
|
||||
detectShutdownThread->interrupt();
|
||||
|
||||
threadGroup.interrupt_all();
|
||||
// threadGroup.join_all(); was left out intentionally here, because we didn't re-test all of
|
||||
// the startup-failure cases to make sure they don't result in a hang due to some
|
||||
// thread-blocking-waiting-for-another-thread-during-startup case
|
||||
}
|
||||
|
||||
if (detectShutdownThread)
|
||||
{
|
||||
detectShutdownThread->join();
|
||||
delete detectShutdownThread;
|
||||
detectShutdownThread = NULL;
|
||||
}
|
||||
Shutdown();
|
||||
|
||||
return fRet;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
SetupEnvironment();
|
||||
|
||||
// Connect bitcoind signal handlers
|
||||
noui_connect();
|
||||
|
||||
return (AppInit(argc, argv) ? 0 : 1);
|
||||
}
|
||||
199
src/bloom.cpp
199
src/bloom.cpp
|
|
@ -1,199 +0,0 @@
|
|||
// Copyright (c) 2012-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "bloom.h"
|
||||
|
||||
#include "primitives/transaction.h"
|
||||
#include "hash.h"
|
||||
#include "script/script.h"
|
||||
#include "script/standard.h"
|
||||
#include "streams.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#define LN2SQUARED 0.4804530139182014246671025263266649717305529515945455
|
||||
#define LN2 0.6931471805599453094172321214581765680755001343602552
|
||||
|
||||
using namespace std;
|
||||
|
||||
CBloomFilter::CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweakIn, unsigned char nFlagsIn) :
|
||||
/**
|
||||
* The ideal size for a bloom filter with a given number of elements and false positive rate is:
|
||||
* - nElements * log(fp rate) / ln(2)^2
|
||||
* We ignore filter parameters which will create a bloom filter larger than the protocol limits
|
||||
*/
|
||||
vData(min((unsigned int)(-1 / LN2SQUARED * nElements * log(nFPRate)), MAX_BLOOM_FILTER_SIZE * 8) / 8),
|
||||
/**
|
||||
* The ideal number of hash functions is filter size * ln(2) / number of elements
|
||||
* Again, we ignore filter parameters which will create a bloom filter with more hash functions than the protocol limits
|
||||
* See https://en.wikipedia.org/wiki/Bloom_filter for an explanation of these formulas
|
||||
*/
|
||||
isFull(false),
|
||||
isEmpty(false),
|
||||
nHashFuncs(min((unsigned int)(vData.size() * 8 / nElements * LN2), MAX_HASH_FUNCS)),
|
||||
nTweak(nTweakIn),
|
||||
nFlags(nFlagsIn)
|
||||
{
|
||||
}
|
||||
|
||||
inline unsigned int CBloomFilter::Hash(unsigned int nHashNum, const std::vector<unsigned char>& vDataToHash) const
|
||||
{
|
||||
// 0xFBA4C795 chosen as it guarantees a reasonable bit difference between nHashNum values.
|
||||
return MurmurHash3(nHashNum * 0xFBA4C795 + nTweak, vDataToHash) % (vData.size() * 8);
|
||||
}
|
||||
|
||||
void CBloomFilter::insert(const vector<unsigned char>& vKey)
|
||||
{
|
||||
if (isFull)
|
||||
return;
|
||||
for (unsigned int i = 0; i < nHashFuncs; i++)
|
||||
{
|
||||
unsigned int nIndex = Hash(i, vKey);
|
||||
// Sets bit nIndex of vData
|
||||
vData[nIndex >> 3] |= (1 << (7 & nIndex));
|
||||
}
|
||||
isEmpty = false;
|
||||
}
|
||||
|
||||
void CBloomFilter::insert(const COutPoint& outpoint)
|
||||
{
|
||||
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
||||
stream << outpoint;
|
||||
vector<unsigned char> data(stream.begin(), stream.end());
|
||||
insert(data);
|
||||
}
|
||||
|
||||
void CBloomFilter::insert(const uint256& hash)
|
||||
{
|
||||
vector<unsigned char> data(hash.begin(), hash.end());
|
||||
insert(data);
|
||||
}
|
||||
|
||||
bool CBloomFilter::contains(const vector<unsigned char>& vKey) const
|
||||
{
|
||||
if (isFull)
|
||||
return true;
|
||||
if (isEmpty)
|
||||
return false;
|
||||
for (unsigned int i = 0; i < nHashFuncs; i++)
|
||||
{
|
||||
unsigned int nIndex = Hash(i, vKey);
|
||||
// Checks bit nIndex of vData
|
||||
if (!(vData[nIndex >> 3] & (1 << (7 & nIndex))))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBloomFilter::contains(const COutPoint& outpoint) const
|
||||
{
|
||||
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
||||
stream << outpoint;
|
||||
vector<unsigned char> data(stream.begin(), stream.end());
|
||||
return contains(data);
|
||||
}
|
||||
|
||||
bool CBloomFilter::contains(const uint256& hash) const
|
||||
{
|
||||
vector<unsigned char> data(hash.begin(), hash.end());
|
||||
return contains(data);
|
||||
}
|
||||
|
||||
void CBloomFilter::clear()
|
||||
{
|
||||
vData.assign(vData.size(),0);
|
||||
isFull = false;
|
||||
isEmpty = true;
|
||||
}
|
||||
|
||||
bool CBloomFilter::IsWithinSizeConstraints() const
|
||||
{
|
||||
return vData.size() <= MAX_BLOOM_FILTER_SIZE && nHashFuncs <= MAX_HASH_FUNCS;
|
||||
}
|
||||
|
||||
bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx)
|
||||
{
|
||||
bool fFound = false;
|
||||
// Match if the filter contains the hash of tx
|
||||
// for finding tx when they appear in a block
|
||||
if (isFull)
|
||||
return true;
|
||||
if (isEmpty)
|
||||
return false;
|
||||
const uint256& hash = tx.GetHash();
|
||||
if (contains(hash))
|
||||
fFound = true;
|
||||
|
||||
for (unsigned int i = 0; i < tx.vout.size(); i++)
|
||||
{
|
||||
const CTxOut& txout = tx.vout[i];
|
||||
// Match if the filter contains any arbitrary script data element in any scriptPubKey in tx
|
||||
// If this matches, also add the specific output that was matched.
|
||||
// This means clients don't have to update the filter themselves when a new relevant tx
|
||||
// is discovered in order to find spending transactions, which avoids round-tripping and race conditions.
|
||||
CScript::const_iterator pc = txout.scriptPubKey.begin();
|
||||
vector<unsigned char> data;
|
||||
while (pc < txout.scriptPubKey.end())
|
||||
{
|
||||
opcodetype opcode;
|
||||
if (!txout.scriptPubKey.GetOp(pc, opcode, data))
|
||||
break;
|
||||
if (data.size() != 0 && contains(data))
|
||||
{
|
||||
fFound = true;
|
||||
if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_ALL)
|
||||
insert(COutPoint(hash, i));
|
||||
else if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_P2PUBKEY_ONLY)
|
||||
{
|
||||
txnouttype type;
|
||||
vector<vector<unsigned char> > vSolutions;
|
||||
if (Solver(txout.scriptPubKey, type, vSolutions) &&
|
||||
(type == TX_PUBKEY || type == TX_MULTISIG))
|
||||
insert(COutPoint(hash, i));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fFound)
|
||||
return true;
|
||||
|
||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
||||
{
|
||||
// Match if the filter contains an outpoint tx spends
|
||||
if (contains(txin.prevout))
|
||||
return true;
|
||||
|
||||
// Match if the filter contains any arbitrary script data element in any scriptSig in tx
|
||||
CScript::const_iterator pc = txin.scriptSig.begin();
|
||||
vector<unsigned char> data;
|
||||
while (pc < txin.scriptSig.end())
|
||||
{
|
||||
opcodetype opcode;
|
||||
if (!txin.scriptSig.GetOp(pc, opcode, data))
|
||||
break;
|
||||
if (data.size() != 0 && contains(data))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CBloomFilter::UpdateEmptyFull()
|
||||
{
|
||||
bool full = true;
|
||||
bool empty = true;
|
||||
for (unsigned int i = 0; i < vData.size(); i++)
|
||||
{
|
||||
full &= vData[i] == 0xff;
|
||||
empty &= vData[i] == 0;
|
||||
}
|
||||
isFull = full;
|
||||
isEmpty = empty;
|
||||
}
|
||||
100
src/bloom.h
100
src/bloom.h
|
|
@ -1,100 +0,0 @@
|
|||
// Copyright (c) 2012-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_BLOOM_H
|
||||
#define BITCOIN_BLOOM_H
|
||||
|
||||
#include "serialize.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class COutPoint;
|
||||
class CTransaction;
|
||||
class uint256;
|
||||
|
||||
//! 20,000 items with fp rate < 0.1% or 10,000 items and <0.0001%
|
||||
static const unsigned int MAX_BLOOM_FILTER_SIZE = 36000; // bytes
|
||||
static const unsigned int MAX_HASH_FUNCS = 50;
|
||||
|
||||
/**
|
||||
* First two bits of nFlags control how much IsRelevantAndUpdate actually updates
|
||||
* The remaining bits are reserved
|
||||
*/
|
||||
enum bloomflags
|
||||
{
|
||||
BLOOM_UPDATE_NONE = 0,
|
||||
BLOOM_UPDATE_ALL = 1,
|
||||
// Only adds outpoints to the filter if the output is a pay-to-pubkey/pay-to-multisig script
|
||||
BLOOM_UPDATE_P2PUBKEY_ONLY = 2,
|
||||
BLOOM_UPDATE_MASK = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* BloomFilter is a probabilistic filter which SPV clients provide
|
||||
* so that we can filter the transactions we sends them.
|
||||
*
|
||||
* This allows for significantly more efficient transaction and block downloads.
|
||||
*
|
||||
* Because bloom filters are probabilistic, an SPV node can increase the false-
|
||||
* positive rate, making us send them transactions which aren't actually theirs,
|
||||
* allowing clients to trade more bandwidth for more privacy by obfuscating which
|
||||
* keys are owned by them.
|
||||
*/
|
||||
class CBloomFilter
|
||||
{
|
||||
private:
|
||||
std::vector<unsigned char> vData;
|
||||
bool isFull;
|
||||
bool isEmpty;
|
||||
unsigned int nHashFuncs;
|
||||
unsigned int nTweak;
|
||||
unsigned char nFlags;
|
||||
|
||||
unsigned int Hash(unsigned int nHashNum, const std::vector<unsigned char>& vDataToHash) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new bloom filter which will provide the given fp rate when filled with the given number of elements
|
||||
* Note that if the given parameters will result in a filter outside the bounds of the protocol limits,
|
||||
* the filter created will be as close to the given parameters as possible within the protocol limits.
|
||||
* This will apply if nFPRate is very low or nElements is unreasonably high.
|
||||
* nTweak is a constant which is added to the seed value passed to the hash function
|
||||
* It should generally always be a random value (and is largely only exposed for unit testing)
|
||||
* nFlags should be one of the BLOOM_UPDATE_* enums (not _MASK)
|
||||
*/
|
||||
CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweak, unsigned char nFlagsIn);
|
||||
CBloomFilter() : isFull(true), isEmpty(false), nHashFuncs(0), nTweak(0), nFlags(0) {}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(vData);
|
||||
READWRITE(nHashFuncs);
|
||||
READWRITE(nTweak);
|
||||
READWRITE(nFlags);
|
||||
}
|
||||
|
||||
void insert(const std::vector<unsigned char>& vKey);
|
||||
void insert(const COutPoint& outpoint);
|
||||
void insert(const uint256& hash);
|
||||
|
||||
bool contains(const std::vector<unsigned char>& vKey) const;
|
||||
bool contains(const COutPoint& outpoint) const;
|
||||
bool contains(const uint256& hash) const;
|
||||
|
||||
void clear();
|
||||
|
||||
//! True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS
|
||||
//! (catch a filter which was just deserialized which was too big)
|
||||
bool IsWithinSizeConstraints() const;
|
||||
|
||||
//! Also adds any outputs which match the filter to the filter (to match their spending txes)
|
||||
bool IsRelevantAndUpdate(const CTransaction& tx);
|
||||
|
||||
//! Checks for empty and full filters to avoid wasting cpu
|
||||
void UpdateEmptyFull();
|
||||
};
|
||||
|
||||
#endif // BITCOIN_BLOOM_H
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
#include "callrpc.h"
|
||||
#include "chainparamsbase.h"
|
||||
#include "util.h"
|
||||
#include "utilstrencodings.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
using namespace boost::asio;
|
||||
using namespace json_spirit;
|
||||
|
||||
#define _(x) std::string(x) /* Keep the _() around in case gettext or such will be used later to translate non-UI */
|
||||
|
||||
Object CallRPC(const string& strMethod, const Array& params, string port)
|
||||
{
|
||||
if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
|
||||
throw runtime_error(strprintf(
|
||||
_("You must set rpcpassword=<password> in the configuration file:\n%s\n"
|
||||
"If the file does not exist, create it with owner-readable-only file permissions."),
|
||||
GetConfigFile().string().c_str()));
|
||||
|
||||
// Connect to localhost
|
||||
bool fUseSSL = GetBoolArg("-rpcssl", false);
|
||||
asio::io_service io_service;
|
||||
ssl::context context(io_service, ssl::context::sslv23);
|
||||
context.set_options(ssl::context::no_sslv2 | ssl::context::no_sslv3);
|
||||
asio::ssl::stream<asio::ip::tcp::socket> sslStream(io_service, context);
|
||||
SSLIOStreamDevice<asio::ip::tcp> d(sslStream, fUseSSL);
|
||||
iostreams::stream< SSLIOStreamDevice<asio::ip::tcp> > stream(d);
|
||||
|
||||
if (port == "")
|
||||
port = GetArg("-rpcport", itostr(BaseParams().RPCPort()));
|
||||
const bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), port);
|
||||
if (!fConnected)
|
||||
throw CConnectionFailed("couldn't connect to server");
|
||||
|
||||
// HTTP basic authentication
|
||||
string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
|
||||
map<string, string> mapRequestHeaders;
|
||||
mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
|
||||
|
||||
// Send request
|
||||
string strRequest = JSONRPCRequest(strMethod, params, 1);
|
||||
string strPost = HTTPPost(strRequest, mapRequestHeaders);
|
||||
stream << strPost << std::flush;
|
||||
|
||||
// Receive HTTP reply status
|
||||
int nProto = 0;
|
||||
int nStatus = ReadHTTPStatus(stream, nProto);
|
||||
|
||||
// Receive HTTP reply message headers and body
|
||||
map<string, string> mapHeaders;
|
||||
string strReply;
|
||||
ReadHTTPMessage(stream, mapHeaders, strReply, nProto, std::numeric_limits<size_t>::max());
|
||||
|
||||
if (nStatus == HTTP_UNAUTHORIZED)
|
||||
throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
|
||||
else if (nStatus >= 400 && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR)
|
||||
throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
|
||||
else if (strReply.empty())
|
||||
throw runtime_error("no response from server");
|
||||
|
||||
// Parse reply
|
||||
Value valReply;
|
||||
if (!read_string(strReply, valReply))
|
||||
throw runtime_error("couldn't parse reply from server");
|
||||
const Object& reply = valReply.get_obj();
|
||||
if (reply.empty())
|
||||
throw runtime_error("expected reply to have result, error and id properties");
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
bool IsConfirmedBitcoinBlock(const uint256& hash, int nMinConfirmationDepth)
|
||||
{
|
||||
try {
|
||||
Array params;
|
||||
params.push_back(hash.GetHex());
|
||||
Object reply = CallRPC("getblock", params, GetArg("-rpcconnectport", "18332"));
|
||||
if (find_value(reply, "error").type() != null_type)
|
||||
return false;
|
||||
Value result = find_value(reply, "result");
|
||||
if (result.type() != obj_type)
|
||||
return false;
|
||||
result = find_value(result.get_obj(), "confirmations");
|
||||
return result.type() == int_type && result.get_int64() >= nMinConfirmationDepth;
|
||||
} catch (CConnectionFailed& e) {
|
||||
LogPrintf("ERROR: Lost connection to bitcoind RPC, you will want to restart after fixing this!\n");
|
||||
return false;
|
||||
} catch (...) {
|
||||
LogPrintf("ERROR: Failure connecting to bitcoind RPC, you will want to restart after fixing this!\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_CALLRPC_H
|
||||
#define BITCOIN_CALLRPC_H
|
||||
|
||||
#include "rpcclient.h"
|
||||
#include "rpcprotocol.h"
|
||||
#include "uint256.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
//
|
||||
// Exception thrown on connection error. This error is used to determine
|
||||
// when to wait if -rpcwait is given.
|
||||
//
|
||||
class CConnectionFailed : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
|
||||
explicit inline CConnectionFailed(const std::string& msg) :
|
||||
std::runtime_error(msg)
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
json_spirit::Object CallRPC(const std::string& strMethod, const json_spirit::Array& params, std::string port="");
|
||||
bool IsConfirmedBitcoinBlock(const uint256& hash, int nMinConfirmationDepth);
|
||||
|
||||
#endif // BITCOIN_CALLRPC_H
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "chain.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* CChain implementation
|
||||
*/
|
||||
void CChain::SetTip(CBlockIndex *pindex) {
|
||||
if (pindex == NULL) {
|
||||
vChain.clear();
|
||||
return;
|
||||
}
|
||||
vChain.resize(pindex->nHeight + 1);
|
||||
while (pindex && vChain[pindex->nHeight] != pindex) {
|
||||
vChain[pindex->nHeight] = pindex;
|
||||
pindex = pindex->pprev;
|
||||
}
|
||||
}
|
||||
|
||||
CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
|
||||
int nStep = 1;
|
||||
std::vector<uint256> vHave;
|
||||
vHave.reserve(32);
|
||||
|
||||
if (!pindex)
|
||||
pindex = Tip();
|
||||
while (pindex) {
|
||||
vHave.push_back(pindex->GetBlockHash());
|
||||
// Stop when we have added the genesis block.
|
||||
if (pindex->nHeight == 0)
|
||||
break;
|
||||
// Exponentially larger steps back, plus the genesis block.
|
||||
int nHeight = std::max(pindex->nHeight - nStep, 0);
|
||||
if (Contains(pindex)) {
|
||||
// Use O(1) CChain index if possible.
|
||||
pindex = (*this)[nHeight];
|
||||
} else {
|
||||
// Otherwise, use O(log n) skiplist.
|
||||
pindex = pindex->GetAncestor(nHeight);
|
||||
}
|
||||
if (vHave.size() > 10)
|
||||
nStep *= 2;
|
||||
}
|
||||
|
||||
return CBlockLocator(vHave);
|
||||
}
|
||||
|
||||
const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
|
||||
if (pindex->nHeight > Height())
|
||||
pindex = pindex->GetAncestor(Height());
|
||||
while (pindex && !Contains(pindex))
|
||||
pindex = pindex->pprev;
|
||||
return pindex;
|
||||
}
|
||||
401
src/chain.h
401
src/chain.h
|
|
@ -1,401 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_CHAIN_H
|
||||
#define BITCOIN_CHAIN_H
|
||||
|
||||
#include "primitives/block.h"
|
||||
#include "pow.h"
|
||||
#include "tinyformat.h"
|
||||
#include "uint256.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
struct CDiskBlockPos
|
||||
{
|
||||
int nFile;
|
||||
unsigned int nPos;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(VARINT(nFile));
|
||||
READWRITE(VARINT(nPos));
|
||||
}
|
||||
|
||||
CDiskBlockPos() {
|
||||
SetNull();
|
||||
}
|
||||
|
||||
CDiskBlockPos(int nFileIn, unsigned int nPosIn) {
|
||||
nFile = nFileIn;
|
||||
nPos = nPosIn;
|
||||
}
|
||||
|
||||
friend bool operator==(const CDiskBlockPos &a, const CDiskBlockPos &b) {
|
||||
return (a.nFile == b.nFile && a.nPos == b.nPos);
|
||||
}
|
||||
|
||||
friend bool operator!=(const CDiskBlockPos &a, const CDiskBlockPos &b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
void SetNull() { nFile = -1; nPos = 0; }
|
||||
bool IsNull() const { return (nFile == -1); }
|
||||
};
|
||||
|
||||
enum BlockStatus {
|
||||
//! Unused.
|
||||
BLOCK_VALID_UNKNOWN = 0,
|
||||
|
||||
//! Parsed, version ok, hash satisfies claimed PoW, 1 <= vtx count <= max, timestamp not in future
|
||||
BLOCK_VALID_HEADER = 1,
|
||||
|
||||
//! All parent headers found, difficulty matches, timestamp >= median previous, checkpoint. Implies all parents
|
||||
//! are also at least TREE.
|
||||
BLOCK_VALID_TREE = 2,
|
||||
|
||||
/**
|
||||
* Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid, no duplicate txids,
|
||||
* sigops, size, merkle root. Implies all parents are at least TREE but not necessarily TRANSACTIONS. When all
|
||||
* parent blocks also have TRANSACTIONS, CBlockIndex::nChainTx will be set.
|
||||
*/
|
||||
BLOCK_VALID_TRANSACTIONS = 3,
|
||||
|
||||
//! Outputs do not overspend inputs, no double spends, coinbase output ok, immature coinbase spends, BIP30.
|
||||
//! Implies all parents are also at least CHAIN.
|
||||
BLOCK_VALID_CHAIN = 4,
|
||||
|
||||
//! Scripts & signatures ok. Implies all parents are also at least SCRIPTS.
|
||||
BLOCK_VALID_SCRIPTS = 5,
|
||||
|
||||
//! All validity bits.
|
||||
BLOCK_VALID_MASK = BLOCK_VALID_HEADER | BLOCK_VALID_TREE | BLOCK_VALID_TRANSACTIONS |
|
||||
BLOCK_VALID_CHAIN | BLOCK_VALID_SCRIPTS,
|
||||
|
||||
BLOCK_HAVE_DATA = 8, //! full block available in blk*.dat
|
||||
BLOCK_HAVE_UNDO = 16, //! undo data available in rev*.dat
|
||||
BLOCK_HAVE_MASK = BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO,
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
/** 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
|
||||
* to it, but at most one of them can be part of the currently active branch.
|
||||
*/
|
||||
class CBlockIndex
|
||||
{
|
||||
public:
|
||||
//! pointer to the hash of the block, if any. memory is owned by this CBlockIndex
|
||||
const uint256* phashBlock;
|
||||
|
||||
//! pointer to the index of the predecessor of this block
|
||||
CBlockIndex* pprev;
|
||||
|
||||
//! pointer to the index of some further predecessor of this block
|
||||
CBlockIndex* pskip;
|
||||
|
||||
//! height of the entry in the chain. The genesis block has height 0
|
||||
int nHeight;
|
||||
|
||||
//! Which # file this block is stored in (blk?????.dat)
|
||||
int nFile;
|
||||
|
||||
//! Byte offset within blk?????.dat where this block's data is stored
|
||||
unsigned int nDataPos;
|
||||
|
||||
//! Byte offset within rev?????.dat where this block's undo data is stored
|
||||
unsigned int nUndoPos;
|
||||
|
||||
//! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block
|
||||
uint256 nChainWork;
|
||||
|
||||
//! Number of transactions in this block.
|
||||
//! Note: in a potential headers-first mode, this number cannot be relied upon
|
||||
unsigned int nTx;
|
||||
|
||||
//! (memory only) Number of transactions in the chain up to and including this block.
|
||||
//! This value will be non-zero only if and only if transactions for this block and all its parents are available.
|
||||
//! Change to 64-bit type when necessary; won't happen before 2030
|
||||
unsigned int nChainTx;
|
||||
|
||||
//! Verification status of this block. See enum BlockStatus
|
||||
unsigned int nStatus;
|
||||
|
||||
//! block header
|
||||
int nVersion;
|
||||
uint256 hashMerkleRoot;
|
||||
unsigned int nTime;
|
||||
CProof proof;
|
||||
|
||||
//! (memory only) Sequential id assigned to distinguish order in which blocks are received.
|
||||
uint32_t nSequenceId;
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
phashBlock = NULL;
|
||||
pprev = NULL;
|
||||
pskip = NULL;
|
||||
nHeight = 0;
|
||||
nFile = 0;
|
||||
nDataPos = 0;
|
||||
nUndoPos = 0;
|
||||
nChainWork = 0;
|
||||
nTx = 0;
|
||||
nChainTx = 0;
|
||||
nStatus = 0;
|
||||
nSequenceId = 0;
|
||||
|
||||
nVersion = 0;
|
||||
hashMerkleRoot = 0;
|
||||
nTime = 0;
|
||||
proof.SetNull();
|
||||
}
|
||||
|
||||
CBlockIndex()
|
||||
{
|
||||
SetNull();
|
||||
}
|
||||
|
||||
CBlockIndex(const CBlockHeader& block)
|
||||
{
|
||||
SetNull();
|
||||
|
||||
nVersion = block.nVersion;
|
||||
hashMerkleRoot = block.hashMerkleRoot;
|
||||
nTime = block.nTime;
|
||||
proof = block.proof;
|
||||
}
|
||||
|
||||
CDiskBlockPos GetBlockPos() const {
|
||||
CDiskBlockPos ret;
|
||||
if (nStatus & BLOCK_HAVE_DATA) {
|
||||
ret.nFile = nFile;
|
||||
ret.nPos = nDataPos;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
CDiskBlockPos GetUndoPos() const {
|
||||
CDiskBlockPos ret;
|
||||
if (nStatus & BLOCK_HAVE_UNDO) {
|
||||
ret.nFile = nFile;
|
||||
ret.nPos = nUndoPos;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
CBlockHeader GetBlockHeader() const
|
||||
{
|
||||
CBlockHeader block;
|
||||
block.nVersion = nVersion;
|
||||
if (pprev)
|
||||
block.hashPrevBlock = pprev->GetBlockHash();
|
||||
block.hashMerkleRoot = hashMerkleRoot;
|
||||
block.nTime = nTime;
|
||||
block.proof = proof;
|
||||
return block;
|
||||
}
|
||||
|
||||
uint256 GetBlockHash() const
|
||||
{
|
||||
return *phashBlock;
|
||||
}
|
||||
|
||||
int64_t GetBlockTime() const
|
||||
{
|
||||
return (int64_t)nTime;
|
||||
}
|
||||
|
||||
enum { nMedianTimeSpan=11 };
|
||||
|
||||
int64_t GetMedianTimePast() const
|
||||
{
|
||||
int64_t pmedian[nMedianTimeSpan];
|
||||
int64_t* pbegin = &pmedian[nMedianTimeSpan];
|
||||
int64_t* pend = &pmedian[nMedianTimeSpan];
|
||||
|
||||
const CBlockIndex* pindex = this;
|
||||
for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
|
||||
*(--pbegin) = pindex->GetBlockTime();
|
||||
|
||||
std::sort(pbegin, pend);
|
||||
return pbegin[(pend - pbegin)/2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there are nRequired or more blocks of minVersion or above
|
||||
* in the last Params().ToCheckBlockUpgradeMajority() blocks, starting at pstart
|
||||
* and going backwards.
|
||||
*/
|
||||
static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart,
|
||||
unsigned int nRequired);
|
||||
|
||||
std::string ToString() const
|
||||
{
|
||||
return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
|
||||
pprev, nHeight,
|
||||
hashMerkleRoot.ToString(),
|
||||
GetBlockHash().ToString());
|
||||
}
|
||||
|
||||
//! Check whether this block index entry is valid up to the passed validity level.
|
||||
bool IsValid(enum BlockStatus nUpTo = BLOCK_VALID_TRANSACTIONS) const
|
||||
{
|
||||
assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
|
||||
if (nStatus & BLOCK_FAILED_MASK)
|
||||
return false;
|
||||
return ((nStatus & BLOCK_VALID_MASK) >= nUpTo);
|
||||
}
|
||||
|
||||
//! Raise the validity level of this block index entry.
|
||||
//! Returns true if the validity was changed.
|
||||
bool RaiseValidity(enum BlockStatus nUpTo)
|
||||
{
|
||||
assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
|
||||
if (nStatus & BLOCK_FAILED_MASK)
|
||||
return false;
|
||||
if ((nStatus & BLOCK_VALID_MASK) < nUpTo) {
|
||||
nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Build the skiplist pointer for this entry.
|
||||
void BuildSkip();
|
||||
|
||||
//! Efficiently find an ancestor of this block.
|
||||
CBlockIndex* GetAncestor(int height);
|
||||
const CBlockIndex* GetAncestor(int height) const;
|
||||
};
|
||||
|
||||
/** Used to marshal pointers into hashes for db storage. */
|
||||
class CDiskBlockIndex : public CBlockIndex
|
||||
{
|
||||
public:
|
||||
uint256 hashPrev;
|
||||
|
||||
CDiskBlockIndex() {
|
||||
hashPrev = 0;
|
||||
}
|
||||
|
||||
explicit CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex) {
|
||||
hashPrev = (pprev ? pprev->GetBlockHash() : 0);
|
||||
}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
if (!(nType & SER_GETHASH))
|
||||
READWRITE(VARINT(nVersion));
|
||||
|
||||
READWRITE(VARINT(nHeight));
|
||||
READWRITE(VARINT(nStatus));
|
||||
READWRITE(VARINT(nTx));
|
||||
if (nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO))
|
||||
READWRITE(VARINT(nFile));
|
||||
if (nStatus & BLOCK_HAVE_DATA)
|
||||
READWRITE(VARINT(nDataPos));
|
||||
if (nStatus & BLOCK_HAVE_UNDO)
|
||||
READWRITE(VARINT(nUndoPos));
|
||||
|
||||
// block header
|
||||
READWRITE(this->nVersion);
|
||||
READWRITE(hashPrev);
|
||||
READWRITE(hashMerkleRoot);
|
||||
READWRITE(nTime);
|
||||
READWRITE(proof);
|
||||
}
|
||||
|
||||
uint256 GetBlockHash() const
|
||||
{
|
||||
CBlockHeader block;
|
||||
block.nVersion = nVersion;
|
||||
block.hashPrevBlock = hashPrev;
|
||||
block.hashMerkleRoot = hashMerkleRoot;
|
||||
block.nTime = nTime;
|
||||
block.proof = proof;
|
||||
return block.GetHash();
|
||||
}
|
||||
|
||||
|
||||
std::string ToString() const
|
||||
{
|
||||
std::string str = "CDiskBlockIndex(";
|
||||
str += CBlockIndex::ToString();
|
||||
str += strprintf("\n hashBlock=%s, hashPrev=%s)",
|
||||
GetBlockHash().ToString(),
|
||||
hashPrev.ToString());
|
||||
return str;
|
||||
}
|
||||
};
|
||||
|
||||
/** An in-memory indexed chain of blocks. */
|
||||
class CChain {
|
||||
private:
|
||||
std::vector<CBlockIndex*> vChain;
|
||||
|
||||
public:
|
||||
/** Returns the index entry for the genesis block of this chain, or NULL if none. */
|
||||
CBlockIndex *Genesis() const {
|
||||
return vChain.size() > 0 ? vChain[0] : NULL;
|
||||
}
|
||||
|
||||
/** Returns the index entry for the tip of this chain, or NULL if none. */
|
||||
CBlockIndex *Tip() const {
|
||||
return vChain.size() > 0 ? vChain[vChain.size() - 1] : NULL;
|
||||
}
|
||||
|
||||
/** Returns the index entry at a particular height in this chain, or NULL if no such height exists. */
|
||||
CBlockIndex *operator[](int nHeight) const {
|
||||
if (nHeight < 0 || nHeight >= (int)vChain.size())
|
||||
return NULL;
|
||||
return vChain[nHeight];
|
||||
}
|
||||
|
||||
/** Compare two chains efficiently. */
|
||||
friend bool operator==(const CChain &a, const CChain &b) {
|
||||
return a.vChain.size() == b.vChain.size() &&
|
||||
a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1];
|
||||
}
|
||||
|
||||
/** Efficiently check whether a block is present in this chain. */
|
||||
bool Contains(const CBlockIndex *pindex) const {
|
||||
return (*this)[pindex->nHeight] == pindex;
|
||||
}
|
||||
|
||||
/** Find the successor of a block in this chain, or NULL if the given index is not found or is the tip. */
|
||||
CBlockIndex *Next(const CBlockIndex *pindex) const {
|
||||
if (Contains(pindex))
|
||||
return (*this)[pindex->nHeight + 1];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */
|
||||
int Height() const {
|
||||
return vChain.size() - 1;
|
||||
}
|
||||
|
||||
/** Set/initialize a chain with a given tip. */
|
||||
void SetTip(CBlockIndex *pindex);
|
||||
|
||||
/** Return a CBlockLocator that refers to a block in this chain (by default the tip). */
|
||||
CBlockLocator GetLocator(const CBlockIndex *pindex = NULL) const;
|
||||
|
||||
/** Find the last common block between this chain and a block index entry. */
|
||||
const CBlockIndex *FindFork(const CBlockIndex *pindex) const;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_CHAIN_H
|
||||
|
|
@ -1,349 +0,0 @@
|
|||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "chainparams.h"
|
||||
|
||||
#include "hash.h"
|
||||
#include "random.h"
|
||||
#include "util.h"
|
||||
#include "utilstrencodings.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <boost/assign/list_of.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost::assign;
|
||||
|
||||
struct SeedSpec6 {
|
||||
uint8_t addr[16];
|
||||
uint16_t port;
|
||||
};
|
||||
|
||||
#include "chainparamsseeds.h"
|
||||
|
||||
/**
|
||||
* Main network
|
||||
*/
|
||||
|
||||
//! Convert the pnSeeds6 array into usable address objects.
|
||||
static void convertSeed6(std::vector<CAddress> &vSeedsOut, const SeedSpec6 *data, unsigned int count)
|
||||
{
|
||||
// It'll only connect to one or two seed nodes because once it connects,
|
||||
// it'll get a pile of addresses with newer timestamps.
|
||||
// Seed nodes are given a random 'last seen time' of between one and two
|
||||
// weeks ago.
|
||||
const int64_t nOneWeek = 7*24*60*60;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
struct in6_addr ip;
|
||||
memcpy(&ip, data[i].addr, sizeof(ip));
|
||||
CAddress addr(CService(ip, data[i].port));
|
||||
addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek;
|
||||
vSeedsOut.push_back(addr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* What makes a good checkpoint block?
|
||||
* + Is surrounded by blocks with reasonable timestamps
|
||||
* (no blocks before with a timestamp after, none after with
|
||||
* timestamp before)
|
||||
* + Contains no strange transactions
|
||||
*/
|
||||
static Checkpoints::MapCheckpoints mapCheckpoints;
|
||||
static const Checkpoints::CCheckpointData data = {
|
||||
&mapCheckpoints,
|
||||
0, // * UNIX timestamp of last checkpoint block
|
||||
0, // * total number of transactions between genesis and last checkpoint
|
||||
// (the tx=... number in the SetBestChain debug.log lines)
|
||||
0 // * estimated number of transactions per day after checkpoint
|
||||
};
|
||||
|
||||
static Checkpoints::MapCheckpoints mapCheckpointsTestnet;
|
||||
static const Checkpoints::CCheckpointData dataTestnet = {
|
||||
&mapCheckpointsTestnet,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
static Checkpoints::MapCheckpoints mapCheckpointsRegtest;
|
||||
static const Checkpoints::CCheckpointData dataRegtest = {
|
||||
&mapCheckpointsRegtest,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
class CMainParams : public CChainParams {
|
||||
public:
|
||||
CMainParams() {
|
||||
networkID = CBaseChainParams::MAIN;
|
||||
strNetworkID = "main";
|
||||
/**
|
||||
* The message start string is designed to be unlikely to occur in normal data.
|
||||
* The characters are rarely used upper ASCII, not valid as UTF-8, and produce
|
||||
* a large 4-byte int at any alignment.
|
||||
*/
|
||||
pchMessageStart[0] = 0xf9;
|
||||
pchMessageStart[1] = 0xbe;
|
||||
pchMessageStart[2] = 0xb4;
|
||||
pchMessageStart[3] = 0xd9;
|
||||
vAlertPubKey = ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284");
|
||||
nDefaultPort = 8333;
|
||||
bnProofOfWorkLimit = ~uint256(0) >> 32;
|
||||
nSubsidyHalvingInterval = 210000;
|
||||
nEnforceBlockUpgradeMajority = 750;
|
||||
nRejectBlockOutdatedMajority = 950;
|
||||
nToCheckBlockUpgradeMajority = 1000;
|
||||
nMinerThreads = 0;
|
||||
nTargetTimespan = 14 * 24 * 60 * 60; // two weeks
|
||||
nTargetSpacing = 10 * 60;
|
||||
|
||||
/**
|
||||
* Build the genesis block.
|
||||
*
|
||||
* CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
|
||||
* CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)
|
||||
* CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
|
||||
* CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
|
||||
* vMerkleTree: 4a5e1e
|
||||
*/
|
||||
const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
|
||||
CMutableTransaction txNew;
|
||||
txNew.nVersion = 1;
|
||||
txNew.vin.resize(1);
|
||||
txNew.vout.resize(1);
|
||||
txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
|
||||
txNew.vout[0].nValue = MAX_MONEY;
|
||||
uint256 bitcoinGenesisHash = uint256("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
|
||||
uint160 bitcoinSecondSPKHash = Hash160(CScript() << OP_DROP << CScriptNum(144) << OP_LESSTHANOREQUAL);
|
||||
txNew.vout[0].scriptPubKey = CScript() << std::vector<unsigned char>(bitcoinGenesisHash.begin(), bitcoinGenesisHash.end()) << std::vector<unsigned char>(bitcoinSecondSPKHash.begin(), bitcoinSecondSPKHash.end()) << OP_WITHDRAWPROOFVERIFY;
|
||||
genesis.vtx.push_back(txNew);
|
||||
genesis.hashPrevBlock = 0;
|
||||
genesis.hashMerkleRoot = genesis.BuildMerkleTree();
|
||||
genesis.nVersion = 1;
|
||||
genesis.nTime = 1231006505;
|
||||
genesis.proof = CProof(0x1d00ffff, 2083236893);
|
||||
|
||||
hashGenesisBlock = genesis.GetHash();
|
||||
mapCheckpoints[0] = hashGenesisBlock;
|
||||
|
||||
vSeeds.push_back(CDNSSeedData("bitcoin.sipa.be", "seed.bitcoin.sipa.be"));
|
||||
vSeeds.push_back(CDNSSeedData("bluematt.me", "dnsseed.bluematt.me"));
|
||||
vSeeds.push_back(CDNSSeedData("dashjr.org", "dnsseed.bitcoin.dashjr.org"));
|
||||
vSeeds.push_back(CDNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com"));
|
||||
vSeeds.push_back(CDNSSeedData("xf2.org", "bitseed.xf2.org"));
|
||||
|
||||
base58Prefixes[PUBKEY_ADDRESS] = list_of(0);
|
||||
base58Prefixes[SCRIPT_ADDRESS] = list_of(5);
|
||||
base58Prefixes[SECRET_KEY] = list_of(128);
|
||||
base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x88)(0xB2)(0x1E);
|
||||
base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x88)(0xAD)(0xE4);
|
||||
|
||||
convertSeed6(vFixedSeeds, pnSeed6_main, ARRAYLEN(pnSeed6_main));
|
||||
|
||||
fRequireRPCPassword = true;
|
||||
fMiningRequiresPeers = true;
|
||||
fAllowMinDifficultyBlocks = false;
|
||||
fDefaultConsistencyChecks = false;
|
||||
fRequireStandard = true;
|
||||
fMineBlocksOnDemand = false;
|
||||
fSkipProofOfWorkCheck = false;
|
||||
fTestnetToBeDeprecatedFieldRPC = false;
|
||||
}
|
||||
|
||||
const Checkpoints::CCheckpointData& Checkpoints() const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
};
|
||||
static CMainParams mainParams;
|
||||
|
||||
/**
|
||||
* Testnet (v3)
|
||||
*/
|
||||
class CTestNetParams : public CMainParams {
|
||||
public:
|
||||
CTestNetParams() {
|
||||
networkID = CBaseChainParams::TESTNET;
|
||||
strNetworkID = "test";
|
||||
pchMessageStart[0] = 0x0b;
|
||||
pchMessageStart[1] = 0x11;
|
||||
pchMessageStart[2] = 0x09;
|
||||
pchMessageStart[3] = 0x07;
|
||||
vAlertPubKey = ParseHex("04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a");
|
||||
nDefaultPort = 18333;
|
||||
nEnforceBlockUpgradeMajority = 51;
|
||||
nRejectBlockOutdatedMajority = 75;
|
||||
nToCheckBlockUpgradeMajority = 100;
|
||||
nMinerThreads = 0;
|
||||
nTargetTimespan = 14 * 24 * 60 * 60; //! two weeks
|
||||
nTargetSpacing = 10 * 60;
|
||||
|
||||
//! Modify the testnet genesis block so the timestamp is valid for a later start.
|
||||
genesis.nTime = 1296688602;
|
||||
genesis.proof = CProof(0x1d00ffff, 414098458);
|
||||
|
||||
hashGenesisBlock = genesis.GetHash();
|
||||
mapCheckpointsTestnet[0] = hashGenesisBlock;
|
||||
|
||||
vFixedSeeds.clear();
|
||||
vSeeds.clear();
|
||||
vSeeds.push_back(CDNSSeedData("alexykot.me", "testnet-seed.alexykot.me"));
|
||||
vSeeds.push_back(CDNSSeedData("bitcoin.petertodd.org", "testnet-seed.bitcoin.petertodd.org"));
|
||||
vSeeds.push_back(CDNSSeedData("bluematt.me", "testnet-seed.bluematt.me"));
|
||||
vSeeds.push_back(CDNSSeedData("bitcoin.schildbach.de", "testnet-seed.bitcoin.schildbach.de"));
|
||||
|
||||
base58Prefixes[PUBKEY_ADDRESS] = list_of(111);
|
||||
base58Prefixes[SCRIPT_ADDRESS] = list_of(196);
|
||||
base58Prefixes[SECRET_KEY] = list_of(239);
|
||||
base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x35)(0x87)(0xCF);
|
||||
base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x35)(0x83)(0x94);
|
||||
|
||||
convertSeed6(vFixedSeeds, pnSeed6_test, ARRAYLEN(pnSeed6_test));
|
||||
|
||||
fRequireRPCPassword = true;
|
||||
fMiningRequiresPeers = true;
|
||||
fAllowMinDifficultyBlocks = true;
|
||||
fDefaultConsistencyChecks = false;
|
||||
fRequireStandard = false;
|
||||
fMineBlocksOnDemand = false;
|
||||
fTestnetToBeDeprecatedFieldRPC = true;
|
||||
}
|
||||
const Checkpoints::CCheckpointData& Checkpoints() const
|
||||
{
|
||||
return dataTestnet;
|
||||
}
|
||||
};
|
||||
static CTestNetParams testNetParams;
|
||||
|
||||
/**
|
||||
* Regression test
|
||||
*/
|
||||
class CRegTestParams : public CTestNetParams {
|
||||
public:
|
||||
CRegTestParams() {
|
||||
networkID = CBaseChainParams::REGTEST;
|
||||
strNetworkID = "regtest";
|
||||
pchMessageStart[0] = 0xfa;
|
||||
pchMessageStart[1] = 0xbf;
|
||||
pchMessageStart[2] = 0xb5;
|
||||
pchMessageStart[3] = 0xda;
|
||||
nSubsidyHalvingInterval = 150;
|
||||
nEnforceBlockUpgradeMajority = 750;
|
||||
nRejectBlockOutdatedMajority = 950;
|
||||
nToCheckBlockUpgradeMajority = 1000;
|
||||
nMinerThreads = 1;
|
||||
nTargetTimespan = 14 * 24 * 60 * 60; //! two weeks
|
||||
nTargetSpacing = 10 * 60;
|
||||
bnProofOfWorkLimit = ~uint256(0) >> 1;
|
||||
genesis.nTime = 1296688602;
|
||||
genesis.proof = CProof(0x207fffff, 2);
|
||||
nDefaultPort = 18444;
|
||||
|
||||
hashGenesisBlock = genesis.GetHash();
|
||||
mapCheckpointsRegtest[0] = hashGenesisBlock;
|
||||
|
||||
vFixedSeeds.clear(); //! Regtest mode doesn't have any fixed seeds.
|
||||
vSeeds.clear(); //! Regtest mode doesn't have any DNS seeds.
|
||||
|
||||
fRequireRPCPassword = false;
|
||||
fMiningRequiresPeers = false;
|
||||
fAllowMinDifficultyBlocks = true;
|
||||
fDefaultConsistencyChecks = true;
|
||||
fRequireStandard = false;
|
||||
fMineBlocksOnDemand = true;
|
||||
fTestnetToBeDeprecatedFieldRPC = false;
|
||||
}
|
||||
const Checkpoints::CCheckpointData& Checkpoints() const
|
||||
{
|
||||
return dataRegtest;
|
||||
}
|
||||
};
|
||||
static CRegTestParams regTestParams;
|
||||
|
||||
/**
|
||||
* Unit test
|
||||
*/
|
||||
class CUnitTestParams : public CMainParams, public CModifiableParams {
|
||||
public:
|
||||
CUnitTestParams() {
|
||||
networkID = CBaseChainParams::UNITTEST;
|
||||
strNetworkID = "unittest";
|
||||
nDefaultPort = 18445;
|
||||
vFixedSeeds.clear(); //! Unit test mode doesn't have any fixed seeds.
|
||||
vSeeds.clear(); //! Unit test mode doesn't have any DNS seeds.
|
||||
|
||||
fRequireRPCPassword = false;
|
||||
fMiningRequiresPeers = false;
|
||||
fDefaultConsistencyChecks = true;
|
||||
fAllowMinDifficultyBlocks = false;
|
||||
fMineBlocksOnDemand = true;
|
||||
}
|
||||
|
||||
const Checkpoints::CCheckpointData& Checkpoints() const
|
||||
{
|
||||
// UnitTest share the same checkpoints as MAIN
|
||||
return data;
|
||||
}
|
||||
|
||||
//! Published setters to allow changing values in unit test cases
|
||||
virtual void setSubsidyHalvingInterval(int anSubsidyHalvingInterval) { nSubsidyHalvingInterval=anSubsidyHalvingInterval; }
|
||||
virtual void setEnforceBlockUpgradeMajority(int anEnforceBlockUpgradeMajority) { nEnforceBlockUpgradeMajority=anEnforceBlockUpgradeMajority; }
|
||||
virtual void setRejectBlockOutdatedMajority(int anRejectBlockOutdatedMajority) { nRejectBlockOutdatedMajority=anRejectBlockOutdatedMajority; }
|
||||
virtual void setToCheckBlockUpgradeMajority(int anToCheckBlockUpgradeMajority) { nToCheckBlockUpgradeMajority=anToCheckBlockUpgradeMajority; }
|
||||
virtual void setDefaultConsistencyChecks(bool afDefaultConsistencyChecks) { fDefaultConsistencyChecks=afDefaultConsistencyChecks; }
|
||||
virtual void setAllowMinDifficultyBlocks(bool afAllowMinDifficultyBlocks) { fAllowMinDifficultyBlocks=afAllowMinDifficultyBlocks; }
|
||||
virtual void setSkipProofOfWorkCheck(bool afSkipProofOfWorkCheck) { fSkipProofOfWorkCheck = afSkipProofOfWorkCheck; }
|
||||
};
|
||||
static CUnitTestParams unitTestParams;
|
||||
|
||||
|
||||
static CChainParams *pCurrentParams = 0;
|
||||
|
||||
CModifiableParams *ModifiableParams()
|
||||
{
|
||||
assert(pCurrentParams);
|
||||
assert(pCurrentParams==&unitTestParams);
|
||||
return (CModifiableParams*)&unitTestParams;
|
||||
}
|
||||
|
||||
const CChainParams &Params() {
|
||||
assert(pCurrentParams);
|
||||
return *pCurrentParams;
|
||||
}
|
||||
|
||||
CChainParams &Params(CBaseChainParams::Network network) {
|
||||
switch (network) {
|
||||
case CBaseChainParams::MAIN:
|
||||
return mainParams;
|
||||
case CBaseChainParams::TESTNET:
|
||||
return testNetParams;
|
||||
case CBaseChainParams::REGTEST:
|
||||
return regTestParams;
|
||||
case CBaseChainParams::UNITTEST:
|
||||
return unitTestParams;
|
||||
default:
|
||||
assert(false && "Unimplemented network");
|
||||
return mainParams;
|
||||
}
|
||||
}
|
||||
|
||||
void SelectParams(CBaseChainParams::Network network) {
|
||||
SelectBaseParams(network);
|
||||
pCurrentParams = &Params(network);
|
||||
}
|
||||
|
||||
bool SelectParamsFromCommandLine()
|
||||
{
|
||||
CBaseChainParams::Network network = NetworkIdFromCommandLine();
|
||||
if (network == CBaseChainParams::MAX_NETWORK_TYPES)
|
||||
return false;
|
||||
|
||||
SelectParams(network);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,154 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_CHAINPARAMS_H
|
||||
#define BITCOIN_CHAINPARAMS_H
|
||||
|
||||
#include "chainparamsbase.h"
|
||||
#include "checkpoints.h"
|
||||
#include "primitives/block.h"
|
||||
#include "protocol.h"
|
||||
#include "uint256.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
typedef unsigned char MessageStartChars[MESSAGE_START_SIZE];
|
||||
|
||||
struct CDNSSeedData {
|
||||
std::string name, host;
|
||||
CDNSSeedData(const std::string &strName, const std::string &strHost) : name(strName), host(strHost) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* CChainParams defines various tweakable parameters of a given instance of the
|
||||
* Bitcoin system. There are three: the main network on which people trade goods
|
||||
* and services, the public test network which gets reset from time to time and
|
||||
* a regression test mode which is intended for private networks only. It has
|
||||
* minimal difficulty to ensure that blocks can be found instantly.
|
||||
*/
|
||||
class CChainParams
|
||||
{
|
||||
public:
|
||||
enum Base58Type {
|
||||
PUBKEY_ADDRESS,
|
||||
SCRIPT_ADDRESS,
|
||||
SECRET_KEY,
|
||||
EXT_PUBLIC_KEY,
|
||||
EXT_SECRET_KEY,
|
||||
|
||||
MAX_BASE58_TYPES
|
||||
};
|
||||
|
||||
const uint256& HashGenesisBlock() const { return hashGenesisBlock; }
|
||||
const MessageStartChars& MessageStart() const { return pchMessageStart; }
|
||||
const std::vector<unsigned char>& AlertKey() const { return vAlertPubKey; }
|
||||
int GetDefaultPort() const { return nDefaultPort; }
|
||||
const uint256& ProofOfWorkLimit() const { return bnProofOfWorkLimit; }
|
||||
int SubsidyHalvingInterval() const { return nSubsidyHalvingInterval; }
|
||||
/** Used to check majorities for block version upgrade */
|
||||
int EnforceBlockUpgradeMajority() const { return nEnforceBlockUpgradeMajority; }
|
||||
int RejectBlockOutdatedMajority() const { return nRejectBlockOutdatedMajority; }
|
||||
int ToCheckBlockUpgradeMajority() const { return nToCheckBlockUpgradeMajority; }
|
||||
|
||||
/** Used if GenerateBitcoins is called with a negative number of threads */
|
||||
int DefaultMinerThreads() const { return nMinerThreads; }
|
||||
const CBlock& GenesisBlock() const { return genesis; }
|
||||
bool RequireRPCPassword() const { return fRequireRPCPassword; }
|
||||
/** Make miner wait to have peers to avoid wasting work */
|
||||
bool MiningRequiresPeers() const { return fMiningRequiresPeers; }
|
||||
/** Default value for -checkmempool and -checkblockindex argument */
|
||||
bool DefaultConsistencyChecks() const { return fDefaultConsistencyChecks; }
|
||||
/** Allow mining of a min-difficulty block */
|
||||
bool AllowMinDifficultyBlocks() const { return fAllowMinDifficultyBlocks; }
|
||||
/** Skip proof-of-work check: allow mining of any difficulty block */
|
||||
bool SkipProofOfWorkCheck() const { return fSkipProofOfWorkCheck; }
|
||||
/** Make standard checks */
|
||||
bool RequireStandard() const { return fRequireStandard; }
|
||||
int64_t TargetTimespan() const { return nTargetTimespan; }
|
||||
int64_t TargetSpacing() const { return nTargetSpacing; }
|
||||
int64_t Interval() const { return nTargetTimespan / nTargetSpacing; }
|
||||
/** Make miner stop after a block is found. In RPC, don't return until nGenProcLimit blocks are generated */
|
||||
bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; }
|
||||
/** In the future use NetworkIDString() for RPC fields */
|
||||
bool TestnetToBeDeprecatedFieldRPC() const { return fTestnetToBeDeprecatedFieldRPC; }
|
||||
/** Return the BIP70 network string (main, test or regtest) */
|
||||
std::string NetworkIDString() const { return strNetworkID; }
|
||||
const std::vector<CDNSSeedData>& DNSSeeds() const { return vSeeds; }
|
||||
const std::vector<unsigned char>& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; }
|
||||
const std::vector<CAddress>& FixedSeeds() const { return vFixedSeeds; }
|
||||
virtual const Checkpoints::CCheckpointData& Checkpoints() const = 0;
|
||||
protected:
|
||||
CChainParams() {}
|
||||
|
||||
uint256 hashGenesisBlock;
|
||||
MessageStartChars pchMessageStart;
|
||||
//! Raw pub key bytes for the broadcast alert signing key.
|
||||
std::vector<unsigned char> vAlertPubKey;
|
||||
int nDefaultPort;
|
||||
uint256 bnProofOfWorkLimit;
|
||||
int nSubsidyHalvingInterval;
|
||||
int nEnforceBlockUpgradeMajority;
|
||||
int nRejectBlockOutdatedMajority;
|
||||
int nToCheckBlockUpgradeMajority;
|
||||
int64_t nTargetTimespan;
|
||||
int64_t nTargetSpacing;
|
||||
int nMinerThreads;
|
||||
std::vector<CDNSSeedData> vSeeds;
|
||||
std::vector<unsigned char> base58Prefixes[MAX_BASE58_TYPES];
|
||||
CBaseChainParams::Network networkID;
|
||||
std::string strNetworkID;
|
||||
CBlock genesis;
|
||||
std::vector<CAddress> vFixedSeeds;
|
||||
bool fRequireRPCPassword;
|
||||
bool fMiningRequiresPeers;
|
||||
bool fAllowMinDifficultyBlocks;
|
||||
bool fDefaultConsistencyChecks;
|
||||
bool fRequireStandard;
|
||||
bool fMineBlocksOnDemand;
|
||||
bool fSkipProofOfWorkCheck;
|
||||
bool fTestnetToBeDeprecatedFieldRPC;
|
||||
};
|
||||
|
||||
/**
|
||||
* Modifiable parameters interface is used by test cases to adapt the parameters in order
|
||||
* to test specific features more easily. Test cases should always restore the previous
|
||||
* values after finalization.
|
||||
*/
|
||||
|
||||
class CModifiableParams {
|
||||
public:
|
||||
//! Published setters to allow changing values in unit test cases
|
||||
virtual void setSubsidyHalvingInterval(int anSubsidyHalvingInterval) =0;
|
||||
virtual void setEnforceBlockUpgradeMajority(int anEnforceBlockUpgradeMajority)=0;
|
||||
virtual void setRejectBlockOutdatedMajority(int anRejectBlockOutdatedMajority)=0;
|
||||
virtual void setToCheckBlockUpgradeMajority(int anToCheckBlockUpgradeMajority)=0;
|
||||
virtual void setDefaultConsistencyChecks(bool aDefaultConsistencyChecks)=0;
|
||||
virtual void setAllowMinDifficultyBlocks(bool aAllowMinDifficultyBlocks)=0;
|
||||
virtual void setSkipProofOfWorkCheck(bool aSkipProofOfWorkCheck)=0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the currently selected parameters. This won't change after app startup
|
||||
* outside of the unit tests.
|
||||
*/
|
||||
const CChainParams &Params();
|
||||
|
||||
/** Return parameters for the given network. */
|
||||
CChainParams &Params(CBaseChainParams::Network network);
|
||||
|
||||
/** Get modifiable network parameters (UNITTEST only) */
|
||||
CModifiableParams *ModifiableParams();
|
||||
|
||||
/** Sets the params returned by Params() to those for the given network. */
|
||||
void SelectParams(CBaseChainParams::Network network);
|
||||
|
||||
/**
|
||||
* Looks for -regtest or -testnet and then calls SelectParams as appropriate.
|
||||
* Returns false if an invalid combination is given.
|
||||
*/
|
||||
bool SelectParamsFromCommandLine();
|
||||
|
||||
#endif // BITCOIN_CHAINPARAMS_H
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "chainparamsbase.h"
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <boost/assign/list_of.hpp>
|
||||
|
||||
using namespace boost::assign;
|
||||
|
||||
/**
|
||||
* Main network
|
||||
*/
|
||||
class CBaseMainParams : public CBaseChainParams
|
||||
{
|
||||
public:
|
||||
CBaseMainParams()
|
||||
{
|
||||
networkID = CBaseChainParams::MAIN;
|
||||
nRPCPort = 8332;
|
||||
}
|
||||
};
|
||||
static CBaseMainParams mainParams;
|
||||
|
||||
/**
|
||||
* Testnet (v3)
|
||||
*/
|
||||
class CBaseTestNetParams : public CBaseMainParams
|
||||
{
|
||||
public:
|
||||
CBaseTestNetParams()
|
||||
{
|
||||
networkID = CBaseChainParams::TESTNET;
|
||||
nRPCPort = 18332;
|
||||
strDataDir = "testnet3";
|
||||
}
|
||||
};
|
||||
static CBaseTestNetParams testNetParams;
|
||||
|
||||
/*
|
||||
* Regression test
|
||||
*/
|
||||
class CBaseRegTestParams : public CBaseTestNetParams
|
||||
{
|
||||
public:
|
||||
CBaseRegTestParams()
|
||||
{
|
||||
networkID = CBaseChainParams::REGTEST;
|
||||
strDataDir = "regtest";
|
||||
}
|
||||
};
|
||||
static CBaseRegTestParams regTestParams;
|
||||
|
||||
/*
|
||||
* Unit test
|
||||
*/
|
||||
class CBaseUnitTestParams : public CBaseMainParams
|
||||
{
|
||||
public:
|
||||
CBaseUnitTestParams()
|
||||
{
|
||||
networkID = CBaseChainParams::UNITTEST;
|
||||
strDataDir = "unittest";
|
||||
}
|
||||
};
|
||||
static CBaseUnitTestParams unitTestParams;
|
||||
|
||||
static CBaseChainParams* pCurrentBaseParams = 0;
|
||||
|
||||
const CBaseChainParams& BaseParams()
|
||||
{
|
||||
assert(pCurrentBaseParams);
|
||||
return *pCurrentBaseParams;
|
||||
}
|
||||
|
||||
void SelectBaseParams(CBaseChainParams::Network network)
|
||||
{
|
||||
switch (network) {
|
||||
case CBaseChainParams::MAIN:
|
||||
pCurrentBaseParams = &mainParams;
|
||||
break;
|
||||
case CBaseChainParams::TESTNET:
|
||||
pCurrentBaseParams = &testNetParams;
|
||||
break;
|
||||
case CBaseChainParams::REGTEST:
|
||||
pCurrentBaseParams = ®TestParams;
|
||||
break;
|
||||
case CBaseChainParams::UNITTEST:
|
||||
pCurrentBaseParams = &unitTestParams;
|
||||
break;
|
||||
default:
|
||||
assert(false && "Unimplemented network");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CBaseChainParams::Network NetworkIdFromCommandLine()
|
||||
{
|
||||
bool fRegTest = GetBoolArg("-regtest", false);
|
||||
bool fTestNet = GetBoolArg("-testnet", false);
|
||||
|
||||
if (fTestNet && fRegTest)
|
||||
return CBaseChainParams::MAX_NETWORK_TYPES;
|
||||
if (fRegTest)
|
||||
return CBaseChainParams::REGTEST;
|
||||
if (fTestNet)
|
||||
return CBaseChainParams::TESTNET;
|
||||
return CBaseChainParams::MAIN;
|
||||
}
|
||||
|
||||
bool SelectBaseParamsFromCommandLine()
|
||||
{
|
||||
CBaseChainParams::Network network = NetworkIdFromCommandLine();
|
||||
if (network == CBaseChainParams::MAX_NETWORK_TYPES)
|
||||
return false;
|
||||
|
||||
SelectBaseParams(network);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AreBaseParamsConfigured()
|
||||
{
|
||||
return pCurrentBaseParams != NULL;
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
// Copyright (c) 2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_CHAINPARAMSBASE_H
|
||||
#define BITCOIN_CHAINPARAMSBASE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* CBaseChainParams defines the base parameters (shared between bitcoin-cli and bitcoind)
|
||||
* of a given instance of the Bitcoin system.
|
||||
*/
|
||||
class CBaseChainParams
|
||||
{
|
||||
public:
|
||||
enum Network {
|
||||
MAIN,
|
||||
TESTNET,
|
||||
REGTEST,
|
||||
UNITTEST,
|
||||
|
||||
MAX_NETWORK_TYPES
|
||||
};
|
||||
|
||||
const std::string& DataDir() const { return strDataDir; }
|
||||
int RPCPort() const { return nRPCPort; }
|
||||
|
||||
protected:
|
||||
CBaseChainParams() {}
|
||||
|
||||
int nRPCPort;
|
||||
std::string strDataDir;
|
||||
Network networkID;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the currently selected parameters. This won't change after app startup
|
||||
* outside of the unit tests.
|
||||
*/
|
||||
const CBaseChainParams& BaseParams();
|
||||
|
||||
/** Sets the params returned by Params() to those for the given network. */
|
||||
void SelectBaseParams(CBaseChainParams::Network network);
|
||||
|
||||
/**
|
||||
* Looks for -regtest or -testnet and returns the appropriate Network ID.
|
||||
* Returns MAX_NETWORK_TYPES if an invalid combination is given.
|
||||
*/
|
||||
CBaseChainParams::Network NetworkIdFromCommandLine();
|
||||
|
||||
/**
|
||||
* Calls NetworkIdFromCommandLine() and then calls SelectParams as appropriate.
|
||||
* Returns false if an invalid combination is given.
|
||||
*/
|
||||
bool SelectBaseParamsFromCommandLine();
|
||||
|
||||
/**
|
||||
* Return true if SelectBaseParamsFromCommandLine() has been called to select
|
||||
* a network.
|
||||
*/
|
||||
bool AreBaseParamsConfigured();
|
||||
|
||||
#endif // BITCOIN_CHAINPARAMSBASE_H
|
||||
|
|
@ -1,552 +0,0 @@
|
|||
#ifndef BITCOIN_CHAINPARAMSSEEDS_H
|
||||
#define BITCOIN_CHAINPARAMSSEEDS_H
|
||||
/**
|
||||
* List of fixed seed nodes for the bitcoin network
|
||||
* AUTOGENERATED by share/seeds/generate-seeds.py
|
||||
*
|
||||
* Each line contains a 16-byte IPv6 address and a port.
|
||||
* IPv4 as well as onion addresses are wrapped inside a IPv6 address accordingly.
|
||||
*/
|
||||
static SeedSpec6 pnSeed6_main[] = {
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x01,0x21,0xc5,0x6e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x01,0x22,0xb4,0xf5}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x01,0xca,0x80,0xda}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x23,0xc3,0x19}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x64,0x7b,0x13}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xaf,0x91,0xa9}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xc7,0x85,0xc1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xc7,0x97,0x0a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xe4,0x01,0xe6}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0e,0xc8,0xc8,0x91}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x12,0xe4,0x00,0xbc}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x12,0xe4,0x00,0xc8}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x1e,0xf3,0x99}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x58,0xe8,0x31}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x63,0x69,0x09}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe2,0x89,0xd0}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe3,0xb1,0xa1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe3,0xbf,0x32}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe5,0x2d,0x20}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xec,0x90,0x45}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xfd,0x94,0x71}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xfd,0xf1,0x16}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xff,0xe3,0xe7}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x14,0xcd,0xde}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x17,0x78,0xfc}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x5e,0x62,0x60}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x62,0x5f,0xc9}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x6f,0x5a,0x37}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x77,0x77,0x69}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x8a,0x19,0x95}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x03,0xd6,0x2d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xba,0x57,0x2e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xba,0x65,0x62}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xba,0xfa,0xba}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xcc,0x99,0x6b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x2c,0x10,0xe7}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x2c,0x2c,0x0b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x78,0xa8,0xcc}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x8f,0x56,0x1a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xbb,0x4b,0x18}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xbc,0x44,0xa9}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xc0,0x5f,0x96}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xc9,0xf6,0x74}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xcd,0x0a,0x8c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x0a,0xd2,0x11}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x13,0x8a,0x9a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0xcc,0x7b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0xcd,0x43}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x26,0xeb,0xe5}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa3,0x4c,0xe6}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa6,0xa2,0x5b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xad,0xbe,0x32}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe3,0x42,0x84}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe5,0xee,0xbb}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xec,0x74,0xd1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x37,0x0e,0x41}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x07,0xfc,0xe5}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x2e,0x9f,0x5b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x4e,0x31,0xb5}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x4e,0xe7,0x39}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x4f,0x99,0x41}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x74,0x22,0x2c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x7e,0x56,0xfd}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x8e,0x29,0x17}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0xc7,0x71,0xc1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0xc8,0x4e,0x6b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0xce,0x8a,0xb1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0xfc,0x34,0x31}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xa5,0x19,0x4b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xa9,0x6b,0x28}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xb3,0xbe,0x38}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xbb,0x52,0x79}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xf6,0x55,0xf6}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3a,0x4a,0x07,0xcd}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3a,0x60,0xb7,0x79}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0x3e,0x3a,0x26}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0x3f,0x5b,0x48}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0x3f,0x5b,0x70}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0x48,0xd3,0xe4}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x2b,0x28,0x9a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x2b,0x82,0xb2}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x50,0xb9,0xd5}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x6d,0x31,0x1a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xad,0x8b,0x3a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xb5,0xee,0xba}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xd2,0x72,0x7f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0x8d,0xe4,0x8a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0x99,0xd5,0x4e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0xdf,0x54,0x91}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0xfb,0x58,0x70}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x1f,0x6e,0x32}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x22,0x79,0x2d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x72,0x06,0x2a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x8c,0x7d,0x62}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x9c,0xc1,0x64}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0x1e,0x2f,0x74}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0x23,0x84,0xb1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0x60,0xc1,0xa5}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0x6f,0xbd,0x1a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x44,0x0a,0x1e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x72,0x21,0xfa}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x82,0x2e,0x3f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xaf,0xd7,0x87}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xbe,0xfd,0xa5}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xc2,0x26,0xfe}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xf4,0x62,0x6f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xa2,0xee,0x1e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xa9,0xff,0x11}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xb7,0xad,0x19}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xdb,0xe9,0x8c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xe3,0xf0,0x73}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xf7,0xde,0x47}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x2b,0x72,0x42}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x34,0x21,0x24}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0xc6,0xf5,0xf1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x0c,0xe2,0xa5}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x0d,0xc6,0xbc}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x0f,0xb3,0x3e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x27,0xef,0x2f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x2f,0x2d,0x57}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x3e,0xd9,0xce}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x40,0x2a,0x1f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x40,0x51,0x3d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x43,0xdb,0xc8}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x5a,0x84,0x9d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x5e,0x1e,0xb1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x88,0xaf,0xf1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x3d,0x61,0xe4}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x7b,0x76,0x84}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x3b,0x98,0xb6}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xc6,0xf8,0x97}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xc8,0xf2,0x59}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xe1,0xb3,0x9d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x0e,0xbb,0x33}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x26,0x22,0xb4}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x34,0x48,0xbb}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x5b,0x90,0xb6}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xa7,0x31,0xd9}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xc9,0xf3,0x37}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xdf,0x3c,0xf9}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xe4,0x99,0x66}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0x1a,0x65,0xe4}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0x32,0x9e,0xc8}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0xb5,0xcc,0xaa}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x39,0xc7,0xb4}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x3f,0xde,0xe2}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x51,0xe7,0x15}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0xc1,0x7e,0x52}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0xcf,0xeb,0xa4}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x53,0xc5,0x72}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x90,0x72,0x09}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x70,0x05,0xf7}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0xae,0x14,0xf7}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x25,0xf0,0x8e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x39,0xca,0x6b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xac,0x7b,0x35}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xdd,0x5b,0xfd}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xeb,0x30,0x30}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xf5,0x4e,0x02}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x08,0x3a,0xf9}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x1b,0xbf,0xb6}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x81,0xec,0x8d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x83,0x58,0x2f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x9d,0xcd,0x06}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x84,0xe6,0x90}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x8f,0xbc,0x9b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xa0,0xdd,0x8c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xa1,0x6f,0x72}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x64,0xbd,0x03}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x93,0x8c,0x79}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xcb,0x4b,0x85}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xdc,0x63,0xe3}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xde,0x14,0xa9}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xf1,0x01,0x07}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x17,0xbf,0xf3}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x26,0x0b,0xca}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x50,0x09,0x47}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x6e,0xd5,0xa5}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x85,0x9b,0xed}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xab,0x22,0x25}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xb5,0x9b,0xb4}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x27,0x9c,0x89}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x49,0xa1,0x5f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x82,0x2d,0x28}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xa5,0x99,0x2f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xa8,0x80,0x85}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xb3,0xe1,0x76}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc2,0xf5,0x9e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc7,0x66,0x0a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xd3,0x1e,0xf3}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xd9,0x85,0x91}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x80,0x23}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x83,0xb1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xe9,0xe1,0xcd}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x00,0xf9,0x92}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x59,0x1f,0xf9}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x80,0x1d,0xe7}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x80,0xfd,0x8e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x8f,0x82,0x38}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x96,0x02,0x63}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x96,0x09,0xc4}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xa1,0x40,0x2d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xd4,0x67,0xd4}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xd4,0x6f,0x72}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xf6,0x4b,0x08}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xfe,0x51,0x1f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xfe,0x96,0x36}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x02,0x22,0x68}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x0f,0x3d,0x3c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x11,0x19,0x87}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x2a,0x90,0x13}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd4,0xd2,0x87}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd7,0xa5,0xe7}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xee,0x8c,0xb0}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xf0,0x1f,0xb8}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x19,0xd6,0x89}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x8b,0xa3,0x84}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xc7,0x04,0xe4}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0x3d,0xd1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0x6c,0x4d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x7b,0x10,0x11}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x30,0x2a,0xc7}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x68,0xa8,0x68}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xe5,0x49,0xab}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xec,0xc4,0x4d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x61,0x38,0x62}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x86,0xb2,0x59}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x96,0xe9,0x13}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xa8,0x85,0x03}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xd0,0x12,0xf6}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xd0,0x21,0xca}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x12,0x1c,0x15}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x55,0xdc,0x54}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xa3,0xe3,0x1c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xb8,0x53,0x3c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xe7,0x60,0x53}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xec,0x31,0x75}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x5a,0x42,0xd1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x6a,0xc2,0x61}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x86,0x4b,0x73}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x98,0xc1,0x24}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x98,0xdb,0x23}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xc5,0x0a,0xea}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xd1,0x4d,0x65}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xd2,0x6a,0x93}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xd6,0xc8,0xcd}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xdf,0x73,0x26}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xea,0x30,0xe8}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xfa,0x56,0x12}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x1b,0x07,0xd1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0xff,0xcf,0x49}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x4a,0xa3,0xea}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x54,0x72,0x6a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x98,0xa6,0x1d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xab,0xd8,0xdd}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xb9,0xb1,0x47}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x13,0x0c,0xf4}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x2a,0x73,0x32}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x4f,0xb1,0xce}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x88,0x93,0x77}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x8f,0xf5,0x05}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xbc,0x32,0x27}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xbe,0xe3,0x70}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xc6,0x87,0x1d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xe2,0x6b,0x56}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xf2,0xdb,0x5a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xf2,0xe5,0xa8}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xf4,0xa0,0x54}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x1f,0x0a,0xd1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x55,0x19,0x29}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x69,0xa1,0x88}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x9a,0xa5,0x2d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x9a,0xc8,0xd8}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xa7,0x6d,0x7d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd3,0x7d,0xe7}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd3,0xd8,0xeb}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x21,0x19,0x11}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x2b,0x82,0xb2}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x61,0x76,0x08,0xec}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x66,0x06,0x7d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xca,0x14,0x2d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xd9,0x7d,0xe1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xea,0xd2,0x6f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xed,0x14,0x7b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xff,0x90,0xb0}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x63,0x71,0x40,0x2b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x63,0xe5,0x16,0x08}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x01,0xd4,0x13}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x1e,0x2a,0xbd}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xe0,0xa5,0x30}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xf3,0x5e,0x8c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x83,0x6b,0x6b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x83,0x74,0xb8}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x8f,0x00,0x9c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xdb,0xb8,0x09}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6a,0xb9,0x26,0xae}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0x06,0x04,0x91}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0x96,0x08,0x1b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0x96,0x21,0x14}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0xaa,0xe4,0x81}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0xaa,0xf0,0xad}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x33,0x14,0x56}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x3d,0x95,0xde}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x3d,0x97,0xac}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0xa1,0x81,0xf7}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0xaa,0x8c,0x15}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x3c,0xd3,0xd8}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x49,0x2a,0x24}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x49,0xac,0x8a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xa3,0xeb,0xef}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xbe,0xc4,0xdc}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xc9,0x87,0xd8}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xe4,0x98,0x02}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xe4,0x9a,0x51}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xe6,0xdc,0x7d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xea,0x9c,0xda}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xeb,0x31,0x1b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xeb,0x45,0x54}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x70,0x7c,0x47,0x00}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x71,0x92,0x44,0xfb}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x73,0x1d,0x11,0x52}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x73,0x46,0xb0,0x11}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x75,0x29,0xa2,0xb8}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x76,0x1b,0x08,0xaa}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x77,0xe6,0x07,0xd3}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x77,0xf6,0x47,0x34}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0xac,0x08,0x64}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7a,0x80,0x6d,0x94}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7b,0xe7,0xe0,0x3f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xaf,0xc3,0x1f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xc7,0xa4,0x60}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xc7,0xfe,0xf4}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x81,0x61,0x45,0x4c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x81,0x7b,0x07,0x07}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x81,0x7b,0x07,0x27}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x81,0xba,0x11,0x11}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0xf7,0xa9,0xbe}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x85,0xf2,0xd1,0x3f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x86,0x66,0x5e,0x26}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x86,0x77,0x11,0x91}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x89,0x74,0xa0,0xb0}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x89,0xe2,0x22,0x2a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8a,0xd2,0xd9,0xaa}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8d,0xff,0xa6,0xc2}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8f,0xd7,0x81,0x7e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x4c,0xf4,0x13}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0x94,0x34,0xa2}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0x94,0x50,0x39}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0xb9,0x13,0x1e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0xb9,0x8e,0x56}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0xb9,0xfd,0x33}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x94,0xfb,0x06,0xd6}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x95,0x9a,0x9b,0xeb}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x95,0xd2,0x85,0xf4}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x97,0xe0,0xf8,0xfc}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x99,0x79,0x4b,0xe5}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x99,0x7f,0xfb,0x43}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9a,0x14,0x02,0x8b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9d,0x0d,0x3d,0x05}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0x3a,0xad,0x30}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0xfd,0x17,0x84}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xd1,0x6e,0xda}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xd5,0xfe,0xcd}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xef,0xfe,0x64}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf2,0x96,0x27}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf3,0x51,0x8a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf3,0xeb,0x38}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf4,0x4f,0x10}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf5,0xd9,0x77}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf8,0x66,0x75}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xfb,0x6c,0x35}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xfe,0x95,0x8b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xff,0x74,0x4e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa6,0x46,0x5e,0x6a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa7,0x58,0x2d,0x7c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa7,0x58,0x78,0xd2}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x1a,0x31,0x2b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x1e,0x0e,0x06}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x50,0x72,0xc5}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xa7,0xd6,0xf3}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xd0,0xdb,0x6c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xdc,0x43,0x9c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xec,0x65,0x22}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xf6,0x6b,0x22}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xff,0xed,0xf1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x02,0xd5,0xd1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x33,0x17,0xe0}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x33,0x7b,0x9f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x39,0xd4,0x79}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x6d,0x21,0x1c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xaf,0x7e,0x7c,0x5b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xaf,0x7e,0x7c,0x5c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x0a,0x74,0xf2}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x24,0x23,0x7e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x24,0x63,0xde}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x7c,0x6e,0x2f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0xc2,0x21,0x2c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0xdf,0xc9,0xc6}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x3e,0x1a,0x53}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x3e,0x24,0x30}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x3e,0xd4,0x8d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x3e,0xfe,0x3b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x4e,0xfa,0x03}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x9b,0x56,0xe2}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xaf,0x86,0x23}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xf8,0x6f,0x04}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xfe,0x01,0xaa}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xfe,0x22,0xa1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb3,0x2b,0x72,0x0e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb6,0xd5,0xd0,0x1c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x44,0x02,0x2e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x48,0xee,0x2a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x5e,0xe2,0x22}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x5e,0xe3,0x3a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x6b,0x8b,0x3a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x6b,0xce,0x2d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x0a,0x30,0x75}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x15,0xd8,0x9c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x26,0x2f,0xe0}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x2d,0xc0,0x81}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x35,0x81,0xe6}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x35,0x83,0x72}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x37,0x35,0x3d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x37,0x35,0x3f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x3d,0x77,0x02}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x3d,0x94,0xcb}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xba,0x02,0xa7,0x17}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x5c,0x4b,0xb2}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x7a,0x5c,0x86}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x8a,0x09,0xd0}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xa5,0xd1,0x94}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xe2,0xce,0xef}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0x0a,0x08,0x7c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0x0a,0x0a,0x93}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x00,0x82,0x8e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x03,0x59,0x9f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x49,0xea,0x8a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x4b,0x5f,0x6b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x5f,0x64,0x66}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x9b,0x54,0xb5}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xa9,0xe9,0xce}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xc6,0x5d,0x56}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xe3,0x87,0xd8}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x00,0x6d,0x03}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x4d,0x32,0xd0}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x6d,0x44,0x3e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x96,0x79,0x25}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0xe0,0x45,0x62}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x4f,0x08,0x25}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x8d,0x56,0x0a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x0c,0xb4,0x5e}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x38,0x3f,0x0a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x74,0x5d,0x5d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x9a,0xae,0xe2}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x9f,0x6f,0x62}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xa9,0x8a,0x02}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xbd,0x7e,0x23}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xc5,0xaf,0xbe}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc5,0xf2,0x5d,0x52}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x0b,0xd6,0x93}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x31,0x29,0x15}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0x21,0x7c,0xba}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xcc,0xba,0x92}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xe9,0xee,0x73}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xf1,0xbd,0x42}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x3c,0x44,0xf2}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x3c,0x45,0xe8}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0xb7,0x97,0x27}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0xdb,0x0e,0xcc}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x2c,0x7b,0x6d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x2c,0x7b,0xa2}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x2d,0x78,0xb2}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0xbe,0x86,0x2c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0xf8,0xb8,0x7f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcf,0xf4,0x49,0x08}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x42,0x1e,0x1b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x51,0x09,0xdf}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x69,0xf3,0xe5}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x7e,0x46,0x9f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x8c,0x1e,0xa9}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xa5,0x80,0xeb}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xbe,0x02,0xf2}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd2,0x42,0xfe,0xec}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd2,0x49,0x1b,0x21}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd3,0x48,0x42,0xe5}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x19,0x25,0x7c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x47,0xeb,0x72}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x47,0xfc,0x6d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x72,0x30,0x1f}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0xae,0x97,0x76}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x42,0xcd,0xc2}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x81,0xf8,0x8b}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x88,0x57,0x22}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xa5,0x52,0x85}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xa7,0x11,0x06}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xb3,0x9e,0xfd}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xbd,0x35,0x7d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xde,0xd0,0x5d}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x31,0x9e,0xa1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x37,0x8f,0x9a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x83,0x5b,0x64}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xf5,0xce,0xb5}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xfa,0x8a,0xe6}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x0b,0xe1,0xbd}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x17,0x06,0x85}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x4b,0x58,0xb2}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xac,0x8f,0x8c}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xc3,0xa9,0xd1}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xc4,0xf8,0x6a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdb,0x8a,0xa1,0xa2}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xde,0xa7,0xf8,0x5a}, 8333},
|
||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdf,0x12,0xfe,0x37}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0a,0x26,0x27,0x21,0xae,0x94,0xd5,0xc2,0x72,0x24}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xea,0xb9,0x5b,0x63,0x1d,0x94,0xe2,0xed,0xec,0xa1}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xce,0x36,0xa1,0xc1,0xd6,0x64,0x43,0xfb,0xb3,0xe7}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x26,0xe6,0xdf,0xeb,0xe5,0xc5,0x9a,0x87,0x5e,0x22}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x52,0x71,0xa2,0x43,0x2a,0xe6,0x6c,0x8e,0xe4,0x7b}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7c,0xf4,0x0b,0x4c,0x52,0xd5,0x16,0xcf,0xf5,0x06}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x98,0xff,0x33,0x38,0xbb,0x43,0x08,0x8d,0x95,0x9e}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x16,0x64,0x1b,0x1f,0x8f,0x87,0x18,0x7d,0xa3,0x2b}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb8,0xda,0x83,0x67,0x90,0x6f,0x46,0x10,0xdb,0x53}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc3,0x1b,0x22,0x8c,0x89,0x60,0xbf,0xca,0x88,0xa1}, 7033},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4d,0xe3,0x5b,0x75,0x10,0x46,0x5e,0xf0,0x99,0x8b}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0a,0xba,0x44,0x94,0x9d,0xf5,0xc0,0xaa,0xcd,0x4a}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x96,0x64,0xce,0x6d,0xd4,0xfb,0xa7,0x6b,0x60,0xb5}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe9,0x8f,0x0b,0x72,0xc9,0xf1,0xde,0x62,0xd4,0x66}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x25,0x5c,0xbc,0x34,0xe8,0x9f,0xe4,0x7c,0x90,0x93}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe0,0xa2,0x72,0xef,0xfa,0x7b,0x88,0x95,0x8b,0x9c}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x99,0x69,0xc5,0x40,0xa7,0x95,0xbb,0x25,0xc1,0xfa}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x46,0xa3,0xd9,0x84,0x08,0xc8,0x7f,0xd3,0xeb,0xc5}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0c,0xc4,0xd2,0x4f,0x74,0x99,0xb3,0x8c,0xe8,0x25}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xac,0x9d,0xb8,0xf8,0x4c,0x4b,0x9c,0xc3,0x9c,0xc6}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7c,0x1d,0x28,0x9f,0xd6,0x28,0x28,0x22,0x4f,0x7a}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xce,0x36,0xa1,0xc1,0xd6,0x64,0x43,0xfb,0xb3,0xe7}, 8333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8f,0x06,0x4e,0x64,0xbc,0x5e,0x1a,0x8a,0x71,0x97}, 8444}
|
||||
};
|
||||
|
||||
static SeedSpec6 pnSeed6_test[] = {
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x99,0xcb,0x26,0x31,0xba,0x48,0x51,0x31,0x39,0x0d}, 18333},
|
||||
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x44,0xf4,0xf4,0xf0,0xbf,0xf7,0x7e,0x6d,0xc4,0xe8}, 18333}
|
||||
};
|
||||
#endif // BITCOIN_CHAINPARAMSSEEDS_H
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "checkpoints.h"
|
||||
|
||||
#include "chainparams.h"
|
||||
#include "main.h"
|
||||
#include "uint256.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
namespace Checkpoints {
|
||||
|
||||
/**
|
||||
* How many times we expect transactions after the last checkpoint to
|
||||
* be slower. This number is a compromise, as it can't be accurate for
|
||||
* every system. When reindexing from a fast disk with a slow CPU, it
|
||||
* can be up to 20, while when downloading from a slow network with a
|
||||
* fast multicore CPU, it won't be much higher than 1.
|
||||
*/
|
||||
static const double SIGCHECK_VERIFICATION_FACTOR = 5.0;
|
||||
|
||||
bool fEnabled = true;
|
||||
|
||||
bool CheckBlock(int nHeight, const uint256& hash)
|
||||
{
|
||||
if (!fEnabled)
|
||||
return true;
|
||||
|
||||
const MapCheckpoints& checkpoints = *Params().Checkpoints().mapCheckpoints;
|
||||
|
||||
MapCheckpoints::const_iterator i = checkpoints.find(nHeight);
|
||||
if (i == checkpoints.end()) return true;
|
||||
return hash == i->second;
|
||||
}
|
||||
|
||||
//! Guess how far we are in the verification process at the given block index
|
||||
double GuessVerificationProgress(CBlockIndex *pindex, bool fSigchecks) {
|
||||
if (pindex==NULL)
|
||||
return 0.0;
|
||||
|
||||
int64_t nNow = time(NULL);
|
||||
|
||||
double fSigcheckVerificationFactor = fSigchecks ? SIGCHECK_VERIFICATION_FACTOR : 1.0;
|
||||
double fWorkBefore = 0.0; // Amount of work done before pindex
|
||||
double fWorkAfter = 0.0; // Amount of work left after pindex (estimated)
|
||||
// Work is defined as: 1.0 per transaction before the last checkpoint, and
|
||||
// fSigcheckVerificationFactor per transaction after.
|
||||
|
||||
const CCheckpointData &data = Params().Checkpoints();
|
||||
|
||||
if (pindex->nChainTx <= data.nTransactionsLastCheckpoint) {
|
||||
double nCheapBefore = pindex->nChainTx;
|
||||
double nCheapAfter = data.nTransactionsLastCheckpoint - pindex->nChainTx;
|
||||
double nExpensiveAfter = (nNow - data.nTimeLastCheckpoint)/86400.0*data.fTransactionsPerDay;
|
||||
fWorkBefore = nCheapBefore;
|
||||
fWorkAfter = nCheapAfter + nExpensiveAfter*fSigcheckVerificationFactor;
|
||||
} else {
|
||||
double nCheapBefore = data.nTransactionsLastCheckpoint;
|
||||
double nExpensiveBefore = pindex->nChainTx - data.nTransactionsLastCheckpoint;
|
||||
double nExpensiveAfter = (nNow - pindex->GetBlockTime())/86400.0*data.fTransactionsPerDay;
|
||||
fWorkBefore = nCheapBefore + nExpensiveBefore*fSigcheckVerificationFactor;
|
||||
fWorkAfter = nExpensiveAfter*fSigcheckVerificationFactor;
|
||||
}
|
||||
|
||||
return fWorkBefore / (fWorkBefore + fWorkAfter);
|
||||
}
|
||||
|
||||
int GetTotalBlocksEstimate()
|
||||
{
|
||||
if (!fEnabled)
|
||||
return 0;
|
||||
|
||||
const MapCheckpoints& checkpoints = *Params().Checkpoints().mapCheckpoints;
|
||||
|
||||
return checkpoints.rbegin()->first;
|
||||
}
|
||||
|
||||
CBlockIndex* GetLastCheckpoint()
|
||||
{
|
||||
if (!fEnabled)
|
||||
return NULL;
|
||||
|
||||
const MapCheckpoints& checkpoints = *Params().Checkpoints().mapCheckpoints;
|
||||
|
||||
BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, checkpoints)
|
||||
{
|
||||
const uint256& hash = i.second;
|
||||
BlockMap::const_iterator t = mapBlockIndex.find(hash);
|
||||
if (t != mapBlockIndex.end())
|
||||
return t->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace Checkpoints
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_CHECKPOINTS_H
|
||||
#define BITCOIN_CHECKPOINTS_H
|
||||
|
||||
#include "uint256.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
class CBlockIndex;
|
||||
|
||||
/**
|
||||
* Block-chain checkpoints are compiled-in sanity checks.
|
||||
* They are updated every release or three.
|
||||
*/
|
||||
namespace Checkpoints
|
||||
{
|
||||
typedef std::map<int, uint256> MapCheckpoints;
|
||||
|
||||
struct CCheckpointData {
|
||||
const MapCheckpoints *mapCheckpoints;
|
||||
int64_t nTimeLastCheckpoint;
|
||||
int64_t nTransactionsLastCheckpoint;
|
||||
double fTransactionsPerDay;
|
||||
};
|
||||
|
||||
//! Returns true if block passes checkpoint checks
|
||||
bool CheckBlock(int nHeight, const uint256& hash);
|
||||
|
||||
//! Return conservative estimate of total number of blocks, 0 if unknown
|
||||
int GetTotalBlocksEstimate();
|
||||
|
||||
//! Returns last CBlockIndex* in mapBlockIndex that is a checkpoint
|
||||
CBlockIndex* GetLastCheckpoint();
|
||||
|
||||
double GuessVerificationProgress(CBlockIndex* pindex, bool fSigchecks = true);
|
||||
|
||||
extern bool fEnabled;
|
||||
|
||||
} //namespace Checkpoints
|
||||
|
||||
#endif // BITCOIN_CHECKPOINTS_H
|
||||
215
src/checkqueue.h
215
src/checkqueue.h
|
|
@ -1,215 +0,0 @@
|
|||
// Copyright (c) 2012-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_CHECKQUEUE_H
|
||||
#define BITCOIN_CHECKQUEUE_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
template <typename T>
|
||||
class CCheckQueueControl;
|
||||
|
||||
/**
|
||||
* Queue for verifications that have to be performed.
|
||||
* The verifications are represented by a type T, which must provide an
|
||||
* operator(), returning a bool.
|
||||
*
|
||||
* One thread (the master) is assumed to push batches of verifications
|
||||
* onto the queue, where they are processed by N-1 worker threads. When
|
||||
* the master is done adding work, it temporarily joins the worker pool
|
||||
* as an N'th worker, until all jobs are done.
|
||||
*/
|
||||
template <typename T>
|
||||
class CCheckQueue
|
||||
{
|
||||
private:
|
||||
//! Mutex to protect the inner state
|
||||
boost::mutex mutex;
|
||||
|
||||
//! Worker threads block on this when out of work
|
||||
boost::condition_variable condWorker;
|
||||
|
||||
//! Master thread blocks on this when out of work
|
||||
boost::condition_variable condMaster;
|
||||
|
||||
//! The queue of elements to be processed.
|
||||
//! As the order of booleans doesn't matter, it is used as a LIFO (stack)
|
||||
std::vector<T> queue;
|
||||
|
||||
//! The number of workers (including the master) that are idle.
|
||||
int nIdle;
|
||||
|
||||
//! The total number of workers (including the master).
|
||||
int nTotal;
|
||||
|
||||
//! The temporary evaluation result.
|
||||
bool fAllOk;
|
||||
|
||||
/**
|
||||
* Number of verifications that haven't completed yet.
|
||||
* This includes elements that are not anymore in queue, but still in
|
||||
* worker's own batches.
|
||||
*/
|
||||
unsigned int nTodo;
|
||||
|
||||
//! Whether we're shutting down.
|
||||
bool fQuit;
|
||||
|
||||
//! The maximum number of elements to be processed in one batch
|
||||
unsigned int nBatchSize;
|
||||
|
||||
/** Internal function that does bulk of the verification work. */
|
||||
bool Loop(bool fMaster = false)
|
||||
{
|
||||
boost::condition_variable& cond = fMaster ? condMaster : condWorker;
|
||||
std::vector<T> vChecks;
|
||||
vChecks.reserve(nBatchSize);
|
||||
unsigned int nNow = 0;
|
||||
bool fOk = true;
|
||||
do {
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(mutex);
|
||||
// first do the clean-up of the previous loop run (allowing us to do it in the same critsect)
|
||||
if (nNow) {
|
||||
fAllOk &= fOk;
|
||||
nTodo -= nNow;
|
||||
if (nTodo == 0 && !fMaster)
|
||||
// We processed the last element; inform the master he can exit and return the result
|
||||
condMaster.notify_one();
|
||||
} else {
|
||||
// first iteration
|
||||
nTotal++;
|
||||
}
|
||||
// logically, the do loop starts here
|
||||
while (queue.empty()) {
|
||||
if ((fMaster || fQuit) && nTodo == 0) {
|
||||
nTotal--;
|
||||
bool fRet = fAllOk;
|
||||
// reset the status for new work later
|
||||
if (fMaster)
|
||||
fAllOk = true;
|
||||
// return the current status
|
||||
return fRet;
|
||||
}
|
||||
nIdle++;
|
||||
cond.wait(lock); // wait
|
||||
nIdle--;
|
||||
}
|
||||
// Decide how many work units to process now.
|
||||
// * Do not try to do everything at once, but aim for increasingly smaller batches so
|
||||
// all workers finish approximately simultaneously.
|
||||
// * Try to account for idle jobs which will instantly start helping.
|
||||
// * Don't do batches smaller than 1 (duh), or larger than nBatchSize.
|
||||
nNow = std::max(1U, std::min(nBatchSize, (unsigned int)queue.size() / (nTotal + nIdle + 1)));
|
||||
vChecks.resize(nNow);
|
||||
for (unsigned int i = 0; i < nNow; i++) {
|
||||
// We want the lock on the mutex to be as short as possible, so swap jobs from the global
|
||||
// queue to the local batch vector instead of copying.
|
||||
vChecks[i].swap(queue.back());
|
||||
queue.pop_back();
|
||||
}
|
||||
// Check whether we need to do work at all
|
||||
fOk = fAllOk;
|
||||
}
|
||||
// execute work
|
||||
BOOST_FOREACH (T& check, vChecks)
|
||||
if (fOk)
|
||||
fOk = check();
|
||||
vChecks.clear();
|
||||
} while (true);
|
||||
}
|
||||
|
||||
public:
|
||||
//! Create a new check queue
|
||||
CCheckQueue(unsigned int nBatchSizeIn) : nIdle(0), nTotal(0), fAllOk(true), nTodo(0), fQuit(false), nBatchSize(nBatchSizeIn) {}
|
||||
|
||||
//! Worker thread
|
||||
void Thread()
|
||||
{
|
||||
Loop();
|
||||
}
|
||||
|
||||
//! Wait until execution finishes, and return whether all evaluations where successful.
|
||||
bool Wait()
|
||||
{
|
||||
return Loop(true);
|
||||
}
|
||||
|
||||
//! Add a batch of checks to the queue
|
||||
void Add(std::vector<T>& vChecks)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(mutex);
|
||||
BOOST_FOREACH (T& check, vChecks) {
|
||||
queue.push_back(T());
|
||||
check.swap(queue.back());
|
||||
}
|
||||
nTodo += vChecks.size();
|
||||
if (vChecks.size() == 1)
|
||||
condWorker.notify_one();
|
||||
else if (vChecks.size() > 1)
|
||||
condWorker.notify_all();
|
||||
}
|
||||
|
||||
~CCheckQueue()
|
||||
{
|
||||
}
|
||||
|
||||
bool IsIdle()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(mutex);
|
||||
return (nTotal == nIdle && nTodo == 0 && fAllOk == true);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* RAII-style controller object for a CCheckQueue that guarantees the passed
|
||||
* queue is finished before continuing.
|
||||
*/
|
||||
template <typename T>
|
||||
class CCheckQueueControl
|
||||
{
|
||||
private:
|
||||
CCheckQueue<T>* pqueue;
|
||||
bool fDone;
|
||||
|
||||
public:
|
||||
CCheckQueueControl(CCheckQueue<T>* pqueueIn) : pqueue(pqueueIn), fDone(false)
|
||||
{
|
||||
// passed queue is supposed to be unused, or NULL
|
||||
if (pqueue != NULL) {
|
||||
bool isIdle = pqueue->IsIdle();
|
||||
assert(isIdle);
|
||||
}
|
||||
}
|
||||
|
||||
bool Wait()
|
||||
{
|
||||
if (pqueue == NULL)
|
||||
return true;
|
||||
bool fRet = pqueue->Wait();
|
||||
fDone = true;
|
||||
return fRet;
|
||||
}
|
||||
|
||||
void Add(std::vector<T>& vChecks)
|
||||
{
|
||||
if (pqueue != NULL)
|
||||
pqueue->Add(vChecks);
|
||||
}
|
||||
|
||||
~CCheckQueueControl()
|
||||
{
|
||||
if (!fDone)
|
||||
Wait();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BITCOIN_CHECKQUEUE_H
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
// Copyright (c) 2012-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "clientversion.h"
|
||||
|
||||
#include "tinyformat.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* Name of client reported in the 'version' message. Report the same name
|
||||
* for both bitcoind and bitcoin-core, to make it harder for attackers to
|
||||
* target servers or GUI users specifically.
|
||||
*/
|
||||
const std::string CLIENT_NAME("Satoshi");
|
||||
|
||||
/**
|
||||
* Client version number
|
||||
*/
|
||||
#define CLIENT_VERSION_SUFFIX ""
|
||||
|
||||
|
||||
/**
|
||||
* The following part of the code determines the CLIENT_BUILD variable.
|
||||
* Several mechanisms are used for this:
|
||||
* * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is
|
||||
* generated by the build environment, possibly containing the output
|
||||
* of git-describe in a macro called BUILD_DESC
|
||||
* * secondly, if this is an exported version of the code, GIT_ARCHIVE will
|
||||
* be defined (automatically using the export-subst git attribute), and
|
||||
* GIT_COMMIT will contain the commit id.
|
||||
* * then, three options exist for determining CLIENT_BUILD:
|
||||
* * if BUILD_DESC is defined, use that literally (output of git-describe)
|
||||
* * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit]
|
||||
* * otherwise, use v[maj].[min].[rev].[build]-unk
|
||||
* finally CLIENT_VERSION_SUFFIX is added
|
||||
*/
|
||||
|
||||
//! First, include build.h if requested
|
||||
#ifdef HAVE_BUILD_INFO
|
||||
#include "build.h"
|
||||
#endif
|
||||
|
||||
//! git will put "#define GIT_ARCHIVE 1" on the next line inside archives. $Format:%n#define GIT_ARCHIVE 1$
|
||||
#ifdef GIT_ARCHIVE
|
||||
#define GIT_COMMIT_ID "$Format:%h$"
|
||||
#define GIT_COMMIT_DATE "$Format:%cD$"
|
||||
#endif
|
||||
|
||||
#define BUILD_DESC_WITH_SUFFIX(maj, min, rev, build, suffix) \
|
||||
"v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-" DO_STRINGIZE(suffix)
|
||||
|
||||
#define BUILD_DESC_FROM_COMMIT(maj, min, rev, build, commit) \
|
||||
"v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-g" commit
|
||||
|
||||
#define BUILD_DESC_FROM_UNKNOWN(maj, min, rev, build) \
|
||||
"v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-unk"
|
||||
|
||||
#ifndef BUILD_DESC
|
||||
#ifdef BUILD_SUFFIX
|
||||
#define BUILD_DESC BUILD_DESC_WITH_SUFFIX(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, BUILD_SUFFIX)
|
||||
#elif defined(GIT_COMMIT_ID)
|
||||
#define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID)
|
||||
#else
|
||||
#define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef BUILD_DATE
|
||||
#ifdef GIT_COMMIT_DATE
|
||||
#define BUILD_DATE GIT_COMMIT_DATE
|
||||
#else
|
||||
#define BUILD_DATE __DATE__ ", " __TIME__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);
|
||||
const std::string CLIENT_DATE(BUILD_DATE);
|
||||
|
||||
static std::string FormatVersion(int nVersion)
|
||||
{
|
||||
if (nVersion % 100 == 0)
|
||||
return strprintf("%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100);
|
||||
else
|
||||
return strprintf("%d.%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100, nVersion % 100);
|
||||
}
|
||||
|
||||
std::string FormatFullVersion()
|
||||
{
|
||||
return CLIENT_BUILD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the subversion field according to BIP 14 spec (https://github.com/bitcoin/bips/blob/master/bip-0014.mediawiki)
|
||||
*/
|
||||
std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << "/";
|
||||
ss << name << ":" << FormatVersion(nClientVersion);
|
||||
if (!comments.empty())
|
||||
{
|
||||
std::vector<std::string>::const_iterator it(comments.begin());
|
||||
ss << "(" << *it;
|
||||
for(++it; it != comments.end(); ++it)
|
||||
ss << "; " << *it;
|
||||
ss << ")";
|
||||
}
|
||||
ss << "/";
|
||||
return ss.str();
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_CLIENTVERSION_H
|
||||
#define BITCOIN_CLIENTVERSION_H
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config/bitcoin-config.h"
|
||||
#else
|
||||
|
||||
/**
|
||||
* client versioning and copyright year
|
||||
*/
|
||||
|
||||
//! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it
|
||||
#define CLIENT_VERSION_MAJOR 0
|
||||
#define CLIENT_VERSION_MINOR 10
|
||||
#define CLIENT_VERSION_REVISION 2
|
||||
#define CLIENT_VERSION_BUILD 0
|
||||
|
||||
//! Set to true for release, false for prerelease or test build
|
||||
#define CLIENT_VERSION_IS_RELEASE true
|
||||
|
||||
/**
|
||||
* Copyright year (2009-this)
|
||||
* Todo: update this when changing our copyright comments in the source
|
||||
*/
|
||||
#define COPYRIGHT_YEAR 2015
|
||||
|
||||
#endif //HAVE_CONFIG_H
|
||||
|
||||
/**
|
||||
* Converts the parameter X to a string after macro replacement on X has been performed.
|
||||
* Don't merge these into one macro!
|
||||
*/
|
||||
#define STRINGIZE(X) DO_STRINGIZE(X)
|
||||
#define DO_STRINGIZE(X) #X
|
||||
|
||||
//! Copyright string used in Windows .rc files
|
||||
#define COPYRIGHT_STR "2009-" STRINGIZE(COPYRIGHT_YEAR) " The Bitcoin Core Developers"
|
||||
|
||||
/**
|
||||
* bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
|
||||
* WINDRES_PREPROC is defined to indicate that its pre-processor is running.
|
||||
* Anything other than a define should be guarded below.
|
||||
*/
|
||||
|
||||
#if !defined(WINDRES_PREPROC)
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
static const int CLIENT_VERSION =
|
||||
1000000 * CLIENT_VERSION_MAJOR
|
||||
+ 10000 * CLIENT_VERSION_MINOR
|
||||
+ 100 * CLIENT_VERSION_REVISION
|
||||
+ 1 * CLIENT_VERSION_BUILD;
|
||||
|
||||
extern const std::string CLIENT_NAME;
|
||||
extern const std::string CLIENT_BUILD;
|
||||
extern const std::string CLIENT_DATE;
|
||||
|
||||
|
||||
std::string FormatFullVersion();
|
||||
std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments);
|
||||
|
||||
#endif // WINDRES_PREPROC
|
||||
|
||||
#endif // BITCOIN_CLIENTVERSION_H
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
// Copyright (c) 2011-2013 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_COINCONTROL_H
|
||||
#define BITCOIN_COINCONTROL_H
|
||||
|
||||
#include "primitives/transaction.h"
|
||||
|
||||
/** Coin Control Features. */
|
||||
class CCoinControl
|
||||
{
|
||||
public:
|
||||
CTxDestination destChange;
|
||||
|
||||
CCoinControl()
|
||||
{
|
||||
SetNull();
|
||||
}
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
destChange = CNoDestination();
|
||||
setSelected.clear();
|
||||
}
|
||||
|
||||
bool HasSelected() const
|
||||
{
|
||||
return (setSelected.size() > 0);
|
||||
}
|
||||
|
||||
bool IsSelected(const uint256& hash, unsigned int n) const
|
||||
{
|
||||
COutPoint outpt(hash, n);
|
||||
return (setSelected.count(outpt) > 0);
|
||||
}
|
||||
|
||||
void Select(const COutPoint& output)
|
||||
{
|
||||
setSelected.insert(output);
|
||||
}
|
||||
|
||||
void UnSelect(const COutPoint& output)
|
||||
{
|
||||
setSelected.erase(output);
|
||||
}
|
||||
|
||||
void UnSelectAll()
|
||||
{
|
||||
setSelected.clear();
|
||||
}
|
||||
|
||||
void ListSelected(std::vector<COutPoint>& vOutpoints)
|
||||
{
|
||||
vOutpoints.assign(setSelected.begin(), setSelected.end());
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<COutPoint> setSelected;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_COINCONTROL_H
|
||||
316
src/coins.cpp
316
src/coins.cpp
|
|
@ -1,316 +0,0 @@
|
|||
// Copyright (c) 2012-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "coins.h"
|
||||
|
||||
#include "random.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/**
|
||||
* calculate number of bytes for the bitmask, and its number of non-zero bytes
|
||||
* each bit in the bitmask represents the availability of one output, but the
|
||||
* availabilities of the first two outputs are encoded separately
|
||||
*/
|
||||
void CCoins::CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const {
|
||||
unsigned int nLastUsedByte = 0;
|
||||
for (unsigned int b = 0; 2+b*8 < vout.size(); b++) {
|
||||
bool fZero = true;
|
||||
for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++) {
|
||||
if (!vout[2+b*8+i].IsNull()) {
|
||||
fZero = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!fZero) {
|
||||
nLastUsedByte = b + 1;
|
||||
nNonzeroBytes++;
|
||||
}
|
||||
}
|
||||
nBytes += nLastUsedByte;
|
||||
}
|
||||
|
||||
bool CCoins::Spend(const COutPoint &out, CTxInUndo &undo) {
|
||||
if (out.n >= vout.size())
|
||||
return false;
|
||||
if (vout[out.n].IsNull())
|
||||
return false;
|
||||
undo = CTxInUndo(vout[out.n]);
|
||||
vout[out.n].SetNull();
|
||||
Cleanup();
|
||||
if (vout.size() == 0) {
|
||||
undo.nHeight = nHeight + 1;
|
||||
undo.fCoinBase = fCoinBase;
|
||||
undo.nVersion = this->nVersion;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCoins::Spend(int nPos) {
|
||||
CTxInUndo undo;
|
||||
COutPoint out(0, nPos);
|
||||
return Spend(out, undo);
|
||||
}
|
||||
|
||||
|
||||
bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; }
|
||||
bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; }
|
||||
COutPoint CCoinsView::GetWithdrawSpent(const std::pair<uint256, COutPoint> &outpoint) const { return COutPoint(); }
|
||||
uint256 CCoinsView::GetBestBlock() const { return uint256(0); }
|
||||
bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; }
|
||||
bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; }
|
||||
|
||||
|
||||
CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { }
|
||||
bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); }
|
||||
bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); }
|
||||
COutPoint CCoinsViewBacked::GetWithdrawSpent(const std::pair<uint256, COutPoint> &outpoint) const { return base->GetWithdrawSpent(outpoint); }
|
||||
uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
|
||||
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
|
||||
bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
|
||||
bool CCoinsViewBacked::GetStats(CCoinsStats &stats) const { return base->GetStats(stats); }
|
||||
|
||||
CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {}
|
||||
|
||||
CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), hasModifier(false), hashBlock(0) { }
|
||||
|
||||
CCoinsViewCache::~CCoinsViewCache()
|
||||
{
|
||||
assert(!hasModifier);
|
||||
}
|
||||
|
||||
static inline CCoinsMapKey make_txentry(const uint256 &txid) {
|
||||
return std::make_pair(txid, COutPoint());
|
||||
}
|
||||
|
||||
CCoinsMap::const_iterator CCoinsViewCache::FetchCoins(const uint256 &txid) const {
|
||||
CCoinsMap::iterator it = cacheCoins.find(make_txentry(txid));
|
||||
if (it != cacheCoins.end())
|
||||
return it;
|
||||
CCoins tmp;
|
||||
if (!base->GetCoins(txid, tmp))
|
||||
return cacheCoins.end();
|
||||
CCoinsMap::iterator ret = cacheCoins.insert(std::make_pair(make_txentry(txid), CCoinsCacheEntry())).first;
|
||||
tmp.swap(ret->second.coins);
|
||||
if (ret->second.coins.IsPruned()) {
|
||||
// The parent only has an empty entry for this txid; we can consider our
|
||||
// version as fresh.
|
||||
ret->second.flags = CCoinsCacheEntry::FRESH;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) const {
|
||||
CCoinsMap::const_iterator it = FetchCoins(txid);
|
||||
if (it != cacheCoins.end()) {
|
||||
coins = it->second.coins;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CCoinsModifier CCoinsViewCache::ModifyCoins(const uint256 &txid) {
|
||||
assert(!hasModifier);
|
||||
std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(make_txentry(txid), CCoinsCacheEntry()));
|
||||
if (ret.second) {
|
||||
if (!base->GetCoins(txid, ret.first->second.coins)) {
|
||||
// The parent view does not have this entry; mark it as fresh.
|
||||
ret.first->second.coins.Clear();
|
||||
ret.first->second.flags = CCoinsCacheEntry::FRESH;
|
||||
} else if (ret.first->second.coins.IsPruned()) {
|
||||
// The parent view only has a pruned entry for this; mark it as fresh.
|
||||
ret.first->second.flags = CCoinsCacheEntry::FRESH;
|
||||
}
|
||||
}
|
||||
// Assume that whenever ModifyCoins is called, the entry will be modified.
|
||||
ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
|
||||
return CCoinsModifier(*this, ret.first);
|
||||
}
|
||||
|
||||
const CCoins* CCoinsViewCache::AccessCoins(const uint256 &txid) const {
|
||||
CCoinsMap::const_iterator it = FetchCoins(txid);
|
||||
if (it == cacheCoins.end()) {
|
||||
return NULL;
|
||||
} else {
|
||||
return &it->second.coins;
|
||||
}
|
||||
}
|
||||
|
||||
bool CCoinsViewCache::HaveCoins(const uint256 &txid) const {
|
||||
CCoinsMap::const_iterator it = FetchCoins(txid);
|
||||
// We're using vtx.empty() instead of IsPruned here for performance reasons,
|
||||
// as we only care about the case where a transaction was replaced entirely
|
||||
// in a reorganization (which wipes vout entirely, as opposed to spending
|
||||
// which just cleans individual outputs).
|
||||
return (it != cacheCoins.end() && !it->second.coins.vout.empty());
|
||||
}
|
||||
|
||||
COutPoint CCoinsViewCache::GetWithdrawSpent(const std::pair<uint256, COutPoint> &outpoint) const {
|
||||
CCoinsMap::iterator it = cacheCoins.find(outpoint);
|
||||
if (it == cacheCoins.end()) {
|
||||
it = cacheCoins.insert(std::make_pair(outpoint, CCoinsCacheEntry())).first;
|
||||
it->second.withdrawSpent = base->GetWithdrawSpent(outpoint);
|
||||
it->second.flags |= CCoinsCacheEntry::WITHDRAW;
|
||||
}
|
||||
return it->second.withdrawSpent;
|
||||
}
|
||||
|
||||
void CCoinsViewCache::MaybeSetWithdrawSpent(const std::pair<uint256, COutPoint> &outpoint, COutPoint spender) {
|
||||
CCoinsMap::iterator it = cacheCoins.find(outpoint);
|
||||
|
||||
// If its already spent - dont overwrite, unless spender IsNull
|
||||
bool hadSpent;
|
||||
if (it == cacheCoins.end())
|
||||
hadSpent = !base->GetWithdrawSpent(outpoint).IsNull();
|
||||
else
|
||||
hadSpent = !it->second.withdrawSpent.IsNull();
|
||||
if (hadSpent && !spender.IsNull())
|
||||
return;
|
||||
|
||||
if (it == cacheCoins.end()) {
|
||||
it = cacheCoins.insert(std::make_pair(outpoint, CCoinsCacheEntry())).first;
|
||||
if (!hadSpent)
|
||||
it->second.flags = CCoinsCacheEntry::FRESH;
|
||||
}
|
||||
it->second.withdrawSpent = spender;
|
||||
it->second.flags |= CCoinsCacheEntry::WITHDRAW | CCoinsCacheEntry::DIRTY;
|
||||
}
|
||||
|
||||
uint256 CCoinsViewCache::GetBestBlock() const {
|
||||
if (hashBlock == uint256(0))
|
||||
hashBlock = base->GetBestBlock();
|
||||
return hashBlock;
|
||||
}
|
||||
|
||||
void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
|
||||
hashBlock = hashBlockIn;
|
||||
}
|
||||
|
||||
bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn) {
|
||||
assert(!hasModifier);
|
||||
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
|
||||
if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
|
||||
bool fIsWithdraw = it->second.flags & CCoinsCacheEntry::WITHDRAW;
|
||||
CCoinsMap::iterator itUs = cacheCoins.find(it->first);
|
||||
if (itUs == cacheCoins.end()) {
|
||||
if ((fIsWithdraw && !it->second.withdrawSpent.IsNull()) ||
|
||||
(!fIsWithdraw && !it->second.coins.IsPruned())) {
|
||||
// The parent cache does not have an entry, while the child
|
||||
// cache does have (a non-pruned) one. Move the data up, and
|
||||
// mark it as fresh (if the grandparent did have it, we
|
||||
// would have pulled it in at first GetCoins).
|
||||
assert(it->second.flags & CCoinsCacheEntry::FRESH);
|
||||
CCoinsCacheEntry& entry = cacheCoins[it->first];
|
||||
entry.flags = CCoinsCacheEntry::DIRTY | CCoinsCacheEntry::FRESH;
|
||||
if (fIsWithdraw) {
|
||||
entry.withdrawSpent = it->second.withdrawSpent;
|
||||
entry.flags |= CCoinsCacheEntry::WITHDRAW;
|
||||
} else
|
||||
entry.coins.swap(it->second.coins);
|
||||
}
|
||||
} else {
|
||||
if ((itUs->second.flags & CCoinsCacheEntry::FRESH) &&
|
||||
((fIsWithdraw && it->second.withdrawSpent.IsNull()) || (!fIsWithdraw && it->second.coins.IsPruned()))) {
|
||||
// The grandparent does not have an entry, and the child is
|
||||
// modified and being pruned. This means we can just delete
|
||||
// it from the parent.
|
||||
cacheCoins.erase(itUs);
|
||||
} else {
|
||||
// A normal modification.
|
||||
if (fIsWithdraw)
|
||||
itUs->second.withdrawSpent = it->second.withdrawSpent;
|
||||
else
|
||||
itUs->second.coins.swap(it->second.coins);
|
||||
itUs->second.flags |= CCoinsCacheEntry::DIRTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
CCoinsMap::iterator itOld = it++;
|
||||
mapCoins.erase(itOld);
|
||||
}
|
||||
hashBlock = hashBlockIn;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCoinsViewCache::Flush() {
|
||||
bool fOk = base->BatchWrite(cacheCoins, hashBlock);
|
||||
cacheCoins.clear();
|
||||
return fOk;
|
||||
}
|
||||
|
||||
unsigned int CCoinsViewCache::GetCacheSize() const {
|
||||
return cacheCoins.size();
|
||||
}
|
||||
|
||||
const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const
|
||||
{
|
||||
const CCoins* coins = AccessCoins(input.prevout.hash);
|
||||
assert(coins && coins->IsAvailable(input.prevout.n));
|
||||
return coins->vout[input.prevout.n];
|
||||
}
|
||||
|
||||
CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const
|
||||
{
|
||||
if (tx.IsCoinBase())
|
||||
return 0;
|
||||
|
||||
CAmount nResult = 0;
|
||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||
nResult += GetOutputFor(tx.vin[i]).nValue;
|
||||
|
||||
return nResult;
|
||||
}
|
||||
|
||||
bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const
|
||||
{
|
||||
if (!tx.IsCoinBase()) {
|
||||
for (unsigned int i = 0; i < tx.vin.size(); i++) {
|
||||
const COutPoint &prevout = tx.vin[i].prevout;
|
||||
const CCoins* coins = AccessCoins(prevout.hash);
|
||||
if (!coins || !coins->IsAvailable(prevout.n)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight) const
|
||||
{
|
||||
if (tx.IsCoinBase())
|
||||
return 0.0;
|
||||
double dResult = 0.0;
|
||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
||||
{
|
||||
const CCoins* coins = AccessCoins(txin.prevout.hash);
|
||||
assert(coins);
|
||||
if (!coins->IsAvailable(txin.prevout.n)) continue;
|
||||
int nOffset = 0;
|
||||
if (coins->vout[txin.prevout.n].scriptPubKey.IsWithdrawOutput() && txin.scriptSig.IsPushOnly() && txin.scriptSig.size() > 1 && txin.scriptSig.back() == OP_1) {
|
||||
// Fraud/reorg proofs get a significant priority bump
|
||||
nOffset = 10000;
|
||||
} else if (coins->vout[txin.prevout.n].scriptPubKey.IsWithdrawLock(0))
|
||||
// Coins moving to this chain get a priority bump
|
||||
nOffset = 100;
|
||||
int nCoinsHeight = coins->nHeight == 0x7fffffff ? nHeight + 1 : coins->nHeight;
|
||||
if (nCoinsHeight < nHeight + nOffset)
|
||||
dResult += (coins->vout[txin.prevout.n].nValue + nOffset) * (nHeight - nCoinsHeight + nOffset);
|
||||
}
|
||||
return tx.ComputePriority(dResult);
|
||||
}
|
||||
|
||||
CCoinsModifier::CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_) : cache(cache_), it(it_) {
|
||||
assert(!cache.hasModifier);
|
||||
cache.hasModifier = true;
|
||||
}
|
||||
|
||||
CCoinsModifier::~CCoinsModifier()
|
||||
{
|
||||
assert(cache.hasModifier);
|
||||
cache.hasModifier = false;
|
||||
it->second.coins.Cleanup();
|
||||
if ((it->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
|
||||
cache.cacheCoins.erase(it);
|
||||
}
|
||||
}
|
||||
458
src/coins.h
458
src/coins.h
|
|
@ -1,458 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_COINS_H
|
||||
#define BITCOIN_COINS_H
|
||||
|
||||
#include "compressor.h"
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include "undo.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
/**
|
||||
* Pruned version of CTransaction: only retains metadata and unspent transaction outputs
|
||||
*
|
||||
* Serialized format:
|
||||
* - VARINT(nVersion)
|
||||
* - VARINT(nCode)
|
||||
* - unspentness bitvector, for vout[2] and further; least significant byte first
|
||||
* - the non-spent CTxOuts (via CTxOutCompressor)
|
||||
* - VARINT(nHeight)
|
||||
*
|
||||
* The nCode value consists of:
|
||||
* - bit 1: IsCoinBase()
|
||||
* - bit 2: vout[0] is not spent
|
||||
* - bit 4: vout[1] is not spent
|
||||
* - The higher bits encode N, the number of non-zero bytes in the following bitvector.
|
||||
* - In case both bit 2 and bit 4 are unset, they encode N-1, as there must be at
|
||||
* least one non-spent output).
|
||||
*
|
||||
* Example: 0104835800816115944e077fe7c803cfa57f29b36bf87c1d358bb85e
|
||||
* <><><--------------------------------------------><---->
|
||||
* | \ | /
|
||||
* version code vout[1] height
|
||||
*
|
||||
* - version = 1
|
||||
* - code = 4 (vout[1] is not spent, and 0 non-zero bytes of bitvector follow)
|
||||
* - unspentness bitvector: as 0 non-zero bytes follow, it has length 0
|
||||
* - vout[1]: 835800816115944e077fe7c803cfa57f29b36bf87c1d35
|
||||
* * 8358: compact amount representation for 60000000000 (600 BTC)
|
||||
* * 00: special txout type pay-to-pubkey-hash
|
||||
* * 816115944e077fe7c803cfa57f29b36bf87c1d35: address uint160
|
||||
* - height = 203998
|
||||
*
|
||||
*
|
||||
* Example: 0109044086ef97d5790061b01caab50f1b8e9c50a5057eb43c2d9563a4eebbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa486af3b
|
||||
* <><><--><--------------------------------------------------><----------------------------------------------><---->
|
||||
* / \ \ | | /
|
||||
* version code unspentness vout[4] vout[16] height
|
||||
*
|
||||
* - version = 1
|
||||
* - code = 9 (coinbase, neither vout[0] or vout[1] are unspent,
|
||||
* 2 (1, +1 because both bit 2 and bit 4 are unset) non-zero bitvector bytes follow)
|
||||
* - unspentness bitvector: bits 2 (0x04) and 14 (0x4000) are set, so vout[2+2] and vout[14+2] are unspent
|
||||
* - vout[4]: 86ef97d5790061b01caab50f1b8e9c50a5057eb43c2d9563a4ee
|
||||
* * 86ef97d579: compact amount representation for 234925952 (2.35 BTC)
|
||||
* * 00: special txout type pay-to-pubkey-hash
|
||||
* * 61b01caab50f1b8e9c50a5057eb43c2d9563a4ee: address uint160
|
||||
* - vout[16]: bbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa4
|
||||
* * bbd123: compact amount representation for 110397 (0.001 BTC)
|
||||
* * 00: special txout type pay-to-pubkey-hash
|
||||
* * 8c988f1a4a4de2161e0f50aac7f17e7f9555caa4: address uint160
|
||||
* - height = 120891
|
||||
*/
|
||||
class CCoins
|
||||
{
|
||||
public:
|
||||
//! whether transaction is a coinbase
|
||||
bool fCoinBase;
|
||||
|
||||
//! unspent transaction outputs; spent outputs are .IsNull(); spent outputs at the end of the array are dropped
|
||||
std::vector<CTxOut> vout;
|
||||
|
||||
//! at which height this transaction was included in the active block chain
|
||||
int nHeight;
|
||||
|
||||
//! version of the CTransaction; accesses to this value should probably check for nHeight as well,
|
||||
//! as new tx version will probably only be introduced at certain heights
|
||||
int nVersion;
|
||||
|
||||
void FromTx(const CTransaction &tx, int nHeightIn) {
|
||||
fCoinBase = tx.IsCoinBase();
|
||||
vout = tx.vout;
|
||||
nHeight = nHeightIn;
|
||||
nVersion = tx.nVersion;
|
||||
ClearUnspendable();
|
||||
}
|
||||
|
||||
//! construct a CCoins from a CTransaction, at a given height
|
||||
CCoins(const CTransaction &tx, int nHeightIn) {
|
||||
FromTx(tx, nHeightIn);
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
fCoinBase = false;
|
||||
std::vector<CTxOut>().swap(vout);
|
||||
nHeight = 0;
|
||||
nVersion = 0;
|
||||
}
|
||||
|
||||
//! empty constructor
|
||||
CCoins() : fCoinBase(false), vout(0), nHeight(0), nVersion(0) { }
|
||||
|
||||
//!remove spent outputs at the end of vout
|
||||
void Cleanup() {
|
||||
while (vout.size() > 0 && vout.back().IsNull())
|
||||
vout.pop_back();
|
||||
if (vout.empty())
|
||||
std::vector<CTxOut>().swap(vout);
|
||||
}
|
||||
|
||||
void ClearUnspendable() {
|
||||
BOOST_FOREACH(CTxOut &txout, vout) {
|
||||
if (txout.scriptPubKey.IsUnspendable())
|
||||
txout.SetNull();
|
||||
}
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void swap(CCoins &to) {
|
||||
std::swap(to.fCoinBase, fCoinBase);
|
||||
to.vout.swap(vout);
|
||||
std::swap(to.nHeight, nHeight);
|
||||
std::swap(to.nVersion, nVersion);
|
||||
}
|
||||
|
||||
//! equality test
|
||||
friend bool operator==(const CCoins &a, const CCoins &b) {
|
||||
// Empty CCoins objects are always equal.
|
||||
if (a.IsPruned() && b.IsPruned())
|
||||
return true;
|
||||
return a.fCoinBase == b.fCoinBase &&
|
||||
a.nHeight == b.nHeight &&
|
||||
a.nVersion == b.nVersion &&
|
||||
a.vout == b.vout;
|
||||
}
|
||||
friend bool operator!=(const CCoins &a, const CCoins &b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
void CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const;
|
||||
|
||||
bool IsCoinBase() const {
|
||||
return fCoinBase;
|
||||
}
|
||||
|
||||
unsigned int GetSerializeSize(int nType, int nVersion) const {
|
||||
unsigned int nSize = 0;
|
||||
unsigned int nMaskSize = 0, nMaskCode = 0;
|
||||
CalcMaskSize(nMaskSize, nMaskCode);
|
||||
bool fFirst = vout.size() > 0 && !vout[0].IsNull();
|
||||
bool fSecond = vout.size() > 1 && !vout[1].IsNull();
|
||||
assert(fFirst || fSecond || nMaskCode);
|
||||
unsigned int nCode = 8*(nMaskCode - (fFirst || fSecond ? 0 : 1)) + (fCoinBase ? 1 : 0) + (fFirst ? 2 : 0) + (fSecond ? 4 : 0);
|
||||
// version
|
||||
nSize += ::GetSerializeSize(VARINT(this->nVersion), nType, nVersion);
|
||||
// size of header code
|
||||
nSize += ::GetSerializeSize(VARINT(nCode), nType, nVersion);
|
||||
// spentness bitmask
|
||||
nSize += nMaskSize;
|
||||
// txouts themself
|
||||
for (unsigned int i = 0; i < vout.size(); i++)
|
||||
if (!vout[i].IsNull())
|
||||
nSize += ::GetSerializeSize(CTxOutCompressor(REF(vout[i])), nType, nVersion);
|
||||
// height
|
||||
nSize += ::GetSerializeSize(VARINT(nHeight), nType, nVersion);
|
||||
return nSize;
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream &s, int nType, int nVersion) const {
|
||||
unsigned int nMaskSize = 0, nMaskCode = 0;
|
||||
CalcMaskSize(nMaskSize, nMaskCode);
|
||||
bool fFirst = vout.size() > 0 && !vout[0].IsNull();
|
||||
bool fSecond = vout.size() > 1 && !vout[1].IsNull();
|
||||
assert(fFirst || fSecond || nMaskCode);
|
||||
unsigned int nCode = 8*(nMaskCode - (fFirst || fSecond ? 0 : 1)) + (fCoinBase ? 1 : 0) + (fFirst ? 2 : 0) + (fSecond ? 4 : 0);
|
||||
// version
|
||||
::Serialize(s, VARINT(this->nVersion), nType, nVersion);
|
||||
// header code
|
||||
::Serialize(s, VARINT(nCode), nType, nVersion);
|
||||
// spentness bitmask
|
||||
for (unsigned int b = 0; b<nMaskSize; b++) {
|
||||
unsigned char chAvail = 0;
|
||||
for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++)
|
||||
if (!vout[2+b*8+i].IsNull())
|
||||
chAvail |= (1 << i);
|
||||
::Serialize(s, chAvail, nType, nVersion);
|
||||
}
|
||||
// txouts themself
|
||||
for (unsigned int i = 0; i < vout.size(); i++) {
|
||||
if (!vout[i].IsNull())
|
||||
::Serialize(s, CTxOutCompressor(REF(vout[i])), nType, nVersion);
|
||||
}
|
||||
// coinbase height
|
||||
::Serialize(s, VARINT(nHeight), nType, nVersion);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream &s, int nType, int nVersion) {
|
||||
unsigned int nCode = 0;
|
||||
// version
|
||||
::Unserialize(s, VARINT(this->nVersion), nType, nVersion);
|
||||
// header code
|
||||
::Unserialize(s, VARINT(nCode), nType, nVersion);
|
||||
fCoinBase = nCode & 1;
|
||||
std::vector<bool> vAvail(2, false);
|
||||
vAvail[0] = (nCode & 2) != 0;
|
||||
vAvail[1] = (nCode & 4) != 0;
|
||||
unsigned int nMaskCode = (nCode / 8) + ((nCode & 6) != 0 ? 0 : 1);
|
||||
// spentness bitmask
|
||||
while (nMaskCode > 0) {
|
||||
unsigned char chAvail = 0;
|
||||
::Unserialize(s, chAvail, nType, nVersion);
|
||||
for (unsigned int p = 0; p < 8; p++) {
|
||||
bool f = (chAvail & (1 << p)) != 0;
|
||||
vAvail.push_back(f);
|
||||
}
|
||||
if (chAvail != 0)
|
||||
nMaskCode--;
|
||||
}
|
||||
// txouts themself
|
||||
vout.assign(vAvail.size(), CTxOut());
|
||||
for (unsigned int i = 0; i < vAvail.size(); i++) {
|
||||
if (vAvail[i])
|
||||
::Unserialize(s, REF(CTxOutCompressor(vout[i])), nType, nVersion);
|
||||
}
|
||||
// coinbase height
|
||||
::Unserialize(s, VARINT(nHeight), nType, nVersion);
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
//! mark an outpoint spent, and construct undo information
|
||||
bool Spend(const COutPoint &out, CTxInUndo &undo);
|
||||
|
||||
//! mark a vout spent
|
||||
bool Spend(int nPos);
|
||||
|
||||
//! check whether a particular output is still available
|
||||
bool IsAvailable(unsigned int nPos) const {
|
||||
return (nPos < vout.size() && !vout[nPos].IsNull());
|
||||
}
|
||||
|
||||
//! check whether the entire CCoins is spent
|
||||
//! note that only !IsPruned() CCoins can be serialized
|
||||
bool IsPruned() const {
|
||||
BOOST_FOREACH(const CTxOut &out, vout)
|
||||
if (!out.IsNull())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// For ~WITHDRAW entries, the first element is the txhash, the second is IsNull()
|
||||
// For WITHDRAW entries, the first is the genesis hash, the second is the txo (on the other chain) spent
|
||||
typedef std::pair<uint256, COutPoint> CCoinsMapKey;
|
||||
class CCoinsKeyHasher
|
||||
{
|
||||
private:
|
||||
uint256 salt;
|
||||
|
||||
public:
|
||||
CCoinsKeyHasher();
|
||||
|
||||
/**
|
||||
* This *must* return size_t. With Boost 1.46 on 32-bit systems the
|
||||
* unordered_map will behave unpredictably if the custom hasher returns a
|
||||
* uint64_t, resulting in failures when syncing the chain (#4634).
|
||||
*/
|
||||
size_t operator()(const CCoinsMapKey& key) const {
|
||||
return key.first.GetHash(salt) ^ key.second.hash.GetHash(salt);
|
||||
}
|
||||
};
|
||||
|
||||
struct CCoinsCacheEntry
|
||||
{
|
||||
CCoins coins; // The actual cached data.
|
||||
COutPoint withdrawSpent;
|
||||
unsigned char flags;
|
||||
|
||||
enum Flags {
|
||||
DIRTY = (1 << 0), // This cache entry is potentially different from the version in the parent view.
|
||||
FRESH = (1 << 1), // The parent view does not have this entry (or it is pruned).
|
||||
WITHDRAW = (1 << 2), // represents a withdraw (coins is actually empty/useless, look at withdrawSpent instead)
|
||||
};
|
||||
|
||||
CCoinsCacheEntry() : coins(), withdrawSpent(), flags(0) {}
|
||||
};
|
||||
|
||||
typedef boost::unordered_map<CCoinsMapKey, CCoinsCacheEntry, CCoinsKeyHasher> CCoinsMap;
|
||||
|
||||
struct CCoinsStats
|
||||
{
|
||||
int nHeight;
|
||||
uint256 hashBlock;
|
||||
uint64_t nTransactions;
|
||||
uint64_t nTransactionOutputs;
|
||||
uint64_t nSerializedSize;
|
||||
uint256 hashSerialized;
|
||||
CAmount nTotalAmount;
|
||||
|
||||
CCoinsStats() : nHeight(0), hashBlock(0), nTransactions(0), nTransactionOutputs(0), nSerializedSize(0), hashSerialized(0), nTotalAmount(0) {}
|
||||
};
|
||||
|
||||
|
||||
/** Abstract view on the open txout dataset. */
|
||||
class CCoinsView
|
||||
{
|
||||
public:
|
||||
//! Retrieve the CCoins (unspent transaction outputs) for a given txid
|
||||
virtual bool GetCoins(const uint256 &txid, CCoins &coins) const;
|
||||
|
||||
//! Just check whether we have data for a given txid.
|
||||
//! This may (but cannot always) return true for fully spent transactions
|
||||
virtual bool HaveCoins(const uint256 &txid) const;
|
||||
|
||||
//! Check if a given withdraw has been spent
|
||||
//! Returning a txhash/input index pointer (bastardizing COutPoint to do so)
|
||||
virtual COutPoint GetWithdrawSpent(const std::pair<uint256, COutPoint> &outpoint) const;
|
||||
|
||||
//! Retrieve the block hash whose state this CCoinsView currently represents
|
||||
virtual uint256 GetBestBlock() const;
|
||||
|
||||
//! Do a bulk modification (multiple CCoins changes + BestBlock change).
|
||||
//! The passed mapCoins can be modified.
|
||||
virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
|
||||
|
||||
//! Calculate statistics about the unspent transaction output set
|
||||
virtual bool GetStats(CCoinsStats &stats) const;
|
||||
|
||||
//! As we use CCoinsViews polymorphically, have a virtual destructor
|
||||
virtual ~CCoinsView() {}
|
||||
};
|
||||
|
||||
|
||||
/** CCoinsView backed by another CCoinsView */
|
||||
class CCoinsViewBacked : public CCoinsView
|
||||
{
|
||||
protected:
|
||||
CCoinsView *base;
|
||||
|
||||
public:
|
||||
CCoinsViewBacked(CCoinsView *viewIn);
|
||||
bool GetCoins(const uint256 &txid, CCoins &coins) const;
|
||||
bool HaveCoins(const uint256 &txid) const;
|
||||
COutPoint GetWithdrawSpent(const std::pair<uint256, COutPoint> &outpoint) const;
|
||||
uint256 GetBestBlock() const;
|
||||
void SetBackend(CCoinsView &viewIn);
|
||||
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
|
||||
bool GetStats(CCoinsStats &stats) const;
|
||||
};
|
||||
|
||||
|
||||
class CCoinsViewCache;
|
||||
|
||||
/**
|
||||
* A reference to a mutable cache entry. Encapsulating it allows us to run
|
||||
* cleanup code after the modification is finished, and keeping track of
|
||||
* concurrent modifications.
|
||||
*/
|
||||
class CCoinsModifier
|
||||
{
|
||||
private:
|
||||
CCoinsViewCache& cache;
|
||||
CCoinsMap::iterator it;
|
||||
CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_);
|
||||
|
||||
public:
|
||||
CCoins* operator->() { return &it->second.coins; }
|
||||
CCoins& operator*() { return it->second.coins; }
|
||||
~CCoinsModifier();
|
||||
friend class CCoinsViewCache;
|
||||
};
|
||||
|
||||
/** CCoinsView that adds a memory cache for transactions to another CCoinsView */
|
||||
class CCoinsViewCache : public CCoinsViewBacked
|
||||
{
|
||||
protected:
|
||||
/* Whether this cache has an active modifier. */
|
||||
bool hasModifier;
|
||||
|
||||
/**
|
||||
* Make mutable so that we can "fill the cache" even from Get-methods
|
||||
* declared as "const".
|
||||
*/
|
||||
mutable uint256 hashBlock;
|
||||
mutable CCoinsMap cacheCoins;
|
||||
|
||||
public:
|
||||
CCoinsViewCache(CCoinsView *baseIn);
|
||||
~CCoinsViewCache();
|
||||
|
||||
// Standard CCoinsView methods
|
||||
bool GetCoins(const uint256 &txid, CCoins &coins) const;
|
||||
bool HaveCoins(const uint256 &txid) const;
|
||||
COutPoint GetWithdrawSpent(const std::pair<uint256, COutPoint> &outpoint) const;
|
||||
void MaybeSetWithdrawSpent(const std::pair<uint256, COutPoint> &outpoint, COutPoint spender);
|
||||
uint256 GetBestBlock() const;
|
||||
void SetBestBlock(const uint256 &hashBlock);
|
||||
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
|
||||
|
||||
/**
|
||||
* Return a pointer to CCoins in the cache, or NULL if not found. This is
|
||||
* more efficient than GetCoins. Modifications to other cache entries are
|
||||
* allowed while accessing the returned pointer.
|
||||
*/
|
||||
const CCoins* AccessCoins(const uint256 &txid) const;
|
||||
|
||||
/**
|
||||
* Return a modifiable reference to a CCoins. If no entry with the given
|
||||
* txid exists, a new one is created. Simultaneous modifications are not
|
||||
* allowed.
|
||||
*/
|
||||
CCoinsModifier ModifyCoins(const uint256 &txid);
|
||||
|
||||
/**
|
||||
* Push the modifications applied to this cache to its base.
|
||||
* Failure to call this method before destruction will cause the changes to be forgotten.
|
||||
* If false is returned, the state of this cache (and its backing view) will be undefined.
|
||||
*/
|
||||
bool Flush();
|
||||
|
||||
//! Calculate the size of the cache (in number of transactions)
|
||||
unsigned int GetCacheSize() const;
|
||||
|
||||
/**
|
||||
* Amount of bitcoins coming in to a transaction
|
||||
* Note that lightweight clients may not know anything besides the hash of previous transactions,
|
||||
* so may not be able to calculate this.
|
||||
*
|
||||
* @param[in] tx transaction for which we are checking input total
|
||||
* @return Sum of value of all inputs (scriptSigs)
|
||||
*/
|
||||
CAmount GetValueIn(const CTransaction& tx) const;
|
||||
|
||||
//! Check whether all prevouts of the transaction are present in the UTXO set represented by this view
|
||||
bool HaveInputs(const CTransaction& tx) const;
|
||||
|
||||
//! Return priority of tx at height nHeight
|
||||
double GetPriority(const CTransaction &tx, int nHeight) const;
|
||||
|
||||
const CTxOut &GetOutputFor(const CTxIn& input) const;
|
||||
|
||||
friend class CCoinsModifier;
|
||||
|
||||
private:
|
||||
CCoinsMap::iterator FetchCoins(const uint256 &txid);
|
||||
CCoinsMap::const_iterator FetchCoins(const uint256 &txid) const;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_COINS_H
|
||||
93
src/compat.h
93
src/compat.h
|
|
@ -1,93 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_COMPAT_H
|
||||
#define BITCOIN_COMPAT_H
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config/bitcoin-config.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
#endif
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#ifdef FD_SETSIZE
|
||||
#undef FD_SETSIZE // prevent redefinition compiler warning
|
||||
#endif
|
||||
#define FD_SETSIZE 1024 // max number of fds in fd_set
|
||||
|
||||
#include <winsock2.h> // Must be included before mswsock.h and windows.h
|
||||
|
||||
#include <mswsock.h>
|
||||
#include <windows.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <limits.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#define MSG_DONTWAIT 0
|
||||
#else
|
||||
typedef u_int SOCKET;
|
||||
#include "errno.h"
|
||||
#define WSAGetLastError() errno
|
||||
#define WSAEINVAL EINVAL
|
||||
#define WSAEALREADY EALREADY
|
||||
#define WSAEWOULDBLOCK EWOULDBLOCK
|
||||
#define WSAEMSGSIZE EMSGSIZE
|
||||
#define WSAEINTR EINTR
|
||||
#define WSAEINPROGRESS EINPROGRESS
|
||||
#define WSAEADDRINUSE EADDRINUSE
|
||||
#define WSAENOTSOCK EBADF
|
||||
#define INVALID_SOCKET (SOCKET)(~0)
|
||||
#define SOCKET_ERROR -1
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef S_IRUSR
|
||||
#define S_IRUSR 0400
|
||||
#define S_IWUSR 0200
|
||||
#endif
|
||||
#else
|
||||
#define MAX_PATH 1024
|
||||
#endif
|
||||
|
||||
// As Solaris does not have the MSG_NOSIGNAL flag for send(2) syscall, it is defined as 0
|
||||
#if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
// PRIO_MAX is not defined on Solaris
|
||||
#ifndef PRIO_MAX
|
||||
#define PRIO_MAX 20
|
||||
#endif
|
||||
#define THREAD_PRIORITY_LOWEST PRIO_MAX
|
||||
#define THREAD_PRIORITY_BELOW_NORMAL 2
|
||||
#define THREAD_PRIORITY_NORMAL 0
|
||||
#define THREAD_PRIORITY_ABOVE_NORMAL (-2)
|
||||
#endif
|
||||
|
||||
size_t strnlen_int( const char *start, size_t max_len);
|
||||
|
||||
#endif // BITCOIN_COMPAT_H
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config/bitcoin-config.h"
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#if defined(HAVE_SYS_SELECT_H)
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
// Prior to GLIBC_2.14, memcpy was aliased to memmove.
|
||||
extern "C" void* memmove(void* a, const void* b, size_t c);
|
||||
extern "C" void* memcpy(void* a, const void* b, size_t c)
|
||||
{
|
||||
return memmove(a, b, c);
|
||||
}
|
||||
|
||||
extern "C" void __chk_fail(void) __attribute__((__noreturn__));
|
||||
extern "C" FDELT_TYPE __fdelt_warn(FDELT_TYPE a)
|
||||
{
|
||||
if (a >= FD_SETSIZE)
|
||||
__chk_fail();
|
||||
return a / __NFDBITS;
|
||||
}
|
||||
extern "C" FDELT_TYPE __fdelt_chk(FDELT_TYPE) __attribute__((weak, alias("__fdelt_warn")));
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config/bitcoin-config.h"
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#if defined(HAVE_SYS_SELECT_H)
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
extern "C" void* memcpy(void* a, const void* b, size_t c);
|
||||
void* memcpy_int(void* a, const void* b, size_t c)
|
||||
{
|
||||
return memcpy(a, b, c);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// trigger: Use the memcpy_int wrapper which calls our internal memcpy.
|
||||
// A direct call to memcpy may be optimized away by the compiler.
|
||||
// test: Fill an array with a sequence of integers. memcpy to a new empty array.
|
||||
// Verify that the arrays are equal. Use an odd size to decrease the odds of
|
||||
// the call being optimized away.
|
||||
template <unsigned int T>
|
||||
bool sanity_test_memcpy()
|
||||
{
|
||||
unsigned int memcpy_test[T];
|
||||
unsigned int memcpy_verify[T] = {};
|
||||
for (unsigned int i = 0; i != T; ++i)
|
||||
memcpy_test[i] = i;
|
||||
|
||||
memcpy_int(memcpy_verify, memcpy_test, sizeof(memcpy_test));
|
||||
|
||||
for (unsigned int i = 0; i != T; ++i) {
|
||||
if (memcpy_verify[i] != i)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(HAVE_SYS_SELECT_H)
|
||||
// trigger: Call FD_SET to trigger __fdelt_chk. FORTIFY_SOURCE must be defined
|
||||
// as >0 and optimizations must be set to at least -O2.
|
||||
// test: Add a file descriptor to an empty fd_set. Verify that it has been
|
||||
// correctly added.
|
||||
bool sanity_test_fdelt()
|
||||
{
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(0, &fds);
|
||||
return FD_ISSET(0, &fds);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // anon namespace
|
||||
|
||||
bool glibc_sanity_test()
|
||||
{
|
||||
#if defined(HAVE_SYS_SELECT_H)
|
||||
if (!sanity_test_fdelt())
|
||||
return false;
|
||||
#endif
|
||||
return sanity_test_memcpy<1025>();
|
||||
}
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <cstddef>
|
||||
#include <istream>
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
|
||||
#ifndef _GLIBCXX_USE_NOEXCEPT
|
||||
#define _GLIBCXX_USE_NOEXCEPT throw()
|
||||
#endif
|
||||
|
||||
namespace std
|
||||
{
|
||||
const char* bad_exception::what() const throw()
|
||||
{
|
||||
return "std::bad_exception";
|
||||
}
|
||||
|
||||
const char* bad_cast::what() const throw()
|
||||
{
|
||||
return "std::bad_cast";
|
||||
}
|
||||
|
||||
const char* bad_alloc::what() const throw()
|
||||
{
|
||||
return "std::bad_alloc";
|
||||
}
|
||||
|
||||
namespace __detail
|
||||
{
|
||||
struct _List_node_base {
|
||||
void _M_hook(std::__detail::_List_node_base* const __position) throw() __attribute__((used))
|
||||
{
|
||||
_M_next = __position;
|
||||
_M_prev = __position->_M_prev;
|
||||
__position->_M_prev->_M_next = this;
|
||||
__position->_M_prev = this;
|
||||
}
|
||||
|
||||
void _M_unhook() __attribute__((used))
|
||||
{
|
||||
_List_node_base* const __next_node = _M_next;
|
||||
_List_node_base* const __prev_node = _M_prev;
|
||||
__prev_node->_M_next = __next_node;
|
||||
__next_node->_M_prev = __prev_node;
|
||||
}
|
||||
|
||||
_List_node_base* _M_next;
|
||||
_List_node_base* _M_prev;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template ostream& ostream::_M_insert(bool);
|
||||
template ostream& ostream::_M_insert(long);
|
||||
template ostream& ostream::_M_insert(double);
|
||||
template ostream& ostream::_M_insert(unsigned long);
|
||||
template ostream& ostream::_M_insert(const void*);
|
||||
template ostream& __ostream_insert(ostream&, const char*, streamsize);
|
||||
template istream& istream::_M_extract(long&);
|
||||
template istream& istream::_M_extract(unsigned short&);
|
||||
|
||||
out_of_range::~out_of_range() _GLIBCXX_USE_NOEXCEPT {}
|
||||
|
||||
length_error::~length_error() _GLIBCXX_USE_NOEXCEPT {}
|
||||
|
||||
// Used with permission.
|
||||
// See: https://github.com/madlib/madlib/commit/c3db418c0d34d6813608f2137fef1012ce03043d
|
||||
|
||||
void ctype<char>::_M_widen_init() const
|
||||
{
|
||||
char __tmp[sizeof(_M_widen)];
|
||||
for (unsigned __i = 0; __i < sizeof(_M_widen); ++__i)
|
||||
__tmp[__i] = __i;
|
||||
do_widen(__tmp, __tmp + sizeof(__tmp), _M_widen);
|
||||
|
||||
_M_widen_ok = 1;
|
||||
// Set _M_widen_ok to 2 if memcpy can't be used.
|
||||
for (unsigned __i = 0; __i < sizeof(_M_widen); ++__i)
|
||||
if (__tmp[__i] != _M_widen[__i]) {
|
||||
_M_widen_ok = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void __throw_out_of_range_fmt(const char*, ...) __attribute__((__noreturn__));
|
||||
void __throw_out_of_range_fmt(const char* err, ...)
|
||||
{
|
||||
// Safe and over-simplified version. Ignore the format and print it as-is.
|
||||
__throw_out_of_range(err);
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <list>
|
||||
#include <locale>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace
|
||||
{
|
||||
// trigger: use ctype<char>::widen to trigger ctype<char>::_M_widen_init().
|
||||
// test: convert a char from narrow to wide and back. Verify that the result
|
||||
// matches the original.
|
||||
bool sanity_test_widen(char testchar)
|
||||
{
|
||||
const std::ctype<char>& test(std::use_facet<std::ctype<char> >(std::locale()));
|
||||
return test.narrow(test.widen(testchar), 'b') == testchar;
|
||||
}
|
||||
|
||||
// trigger: use list::push_back and list::pop_back to trigger _M_hook and
|
||||
// _M_unhook.
|
||||
// test: Push a sequence of integers into a list. Pop them off and verify that
|
||||
// they match the original sequence.
|
||||
bool sanity_test_list(unsigned int size)
|
||||
{
|
||||
std::list<unsigned int> test;
|
||||
for (unsigned int i = 0; i != size; ++i)
|
||||
test.push_back(i + 1);
|
||||
|
||||
if (test.size() != size)
|
||||
return false;
|
||||
|
||||
while (!test.empty()) {
|
||||
if (test.back() != test.size())
|
||||
return false;
|
||||
test.pop_back();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // anon namespace
|
||||
|
||||
// trigger: string::at(x) on an empty string to trigger __throw_out_of_range_fmt.
|
||||
// test: force std::string to throw an out_of_range exception. Verify that
|
||||
// it's caught correctly.
|
||||
bool sanity_test_range_fmt()
|
||||
{
|
||||
std::string test;
|
||||
try {
|
||||
test.at(1);
|
||||
} catch (const std::out_of_range&) {
|
||||
return true;
|
||||
} catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool glibcxx_sanity_test()
|
||||
{
|
||||
return sanity_test_widen('a') && sanity_test_list(100) && sanity_test_range_fmt();
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_COMPAT_SANITY_H
|
||||
#define BITCOIN_COMPAT_SANITY_H
|
||||
|
||||
bool glibc_sanity_test();
|
||||
bool glibcxx_sanity_test();
|
||||
|
||||
#endif // BITCOIN_COMPAT_SANITY_H
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config/bitcoin-config.h"
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
// OSX 10.6 is missing strnlen at runtime, but builds targetting it will still
|
||||
// succeed. Define our own version here to avoid a crash.
|
||||
size_t strnlen_int( const char *start, size_t max_len)
|
||||
{
|
||||
const char *end = (const char *)memchr(start, '\0', max_len);
|
||||
|
||||
return end ? (size_t)(end - start) : max_len;
|
||||
}
|
||||
|
|
@ -1,185 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "compressor.h"
|
||||
|
||||
#include "hash.h"
|
||||
#include "pubkey.h"
|
||||
#include "script/standard.h"
|
||||
|
||||
bool CScriptCompressor::IsToKeyID(CKeyID &hash) const
|
||||
{
|
||||
if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160
|
||||
&& script[2] == 20 && script[23] == OP_EQUALVERIFY
|
||||
&& script[24] == OP_CHECKSIG) {
|
||||
memcpy(&hash, &script[3], 20);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CScriptCompressor::IsToScriptID(CScriptID &hash) const
|
||||
{
|
||||
if (script.size() == 23 && script[0] == OP_HASH160 && script[1] == 20
|
||||
&& script[22] == OP_EQUAL) {
|
||||
memcpy(&hash, &script[2], 20);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CScriptCompressor::IsToPubKey(CPubKey &pubkey) const
|
||||
{
|
||||
if (script.size() == 35 && script[0] == 33 && script[34] == OP_CHECKSIG
|
||||
&& (script[1] == 0x02 || script[1] == 0x03)) {
|
||||
pubkey.Set(&script[1], &script[34]);
|
||||
return true;
|
||||
}
|
||||
if (script.size() == 67 && script[0] == 65 && script[66] == OP_CHECKSIG
|
||||
&& script[1] == 0x04) {
|
||||
pubkey.Set(&script[1], &script[66]);
|
||||
return pubkey.IsFullyValid(); // if not fully valid, a case that would not be compressible
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CScriptCompressor::Compress(std::vector<unsigned char> &out) const
|
||||
{
|
||||
CKeyID keyID;
|
||||
if (IsToKeyID(keyID)) {
|
||||
out.resize(21);
|
||||
out[0] = 0x00;
|
||||
memcpy(&out[1], &keyID, 20);
|
||||
return true;
|
||||
}
|
||||
CScriptID scriptID;
|
||||
if (IsToScriptID(scriptID)) {
|
||||
out.resize(21);
|
||||
out[0] = 0x01;
|
||||
memcpy(&out[1], &scriptID, 20);
|
||||
return true;
|
||||
}
|
||||
CPubKey pubkey;
|
||||
if (IsToPubKey(pubkey)) {
|
||||
out.resize(33);
|
||||
memcpy(&out[1], &pubkey[1], 32);
|
||||
if (pubkey[0] == 0x02 || pubkey[0] == 0x03) {
|
||||
out[0] = pubkey[0];
|
||||
return true;
|
||||
} else if (pubkey[0] == 0x04) {
|
||||
out[0] = 0x04 | (pubkey[64] & 0x01);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int CScriptCompressor::GetSpecialSize(unsigned int nSize) const
|
||||
{
|
||||
if (nSize == 0 || nSize == 1)
|
||||
return 20;
|
||||
if (nSize == 2 || nSize == 3 || nSize == 4 || nSize == 5)
|
||||
return 32;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector<unsigned char> &in)
|
||||
{
|
||||
switch(nSize) {
|
||||
case 0x00:
|
||||
script.resize(25);
|
||||
script[0] = OP_DUP;
|
||||
script[1] = OP_HASH160;
|
||||
script[2] = 20;
|
||||
memcpy(&script[3], &in[0], 20);
|
||||
script[23] = OP_EQUALVERIFY;
|
||||
script[24] = OP_CHECKSIG;
|
||||
return true;
|
||||
case 0x01:
|
||||
script.resize(23);
|
||||
script[0] = OP_HASH160;
|
||||
script[1] = 20;
|
||||
memcpy(&script[2], &in[0], 20);
|
||||
script[22] = OP_EQUAL;
|
||||
return true;
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
script.resize(35);
|
||||
script[0] = 33;
|
||||
script[1] = nSize;
|
||||
memcpy(&script[2], &in[0], 32);
|
||||
script[34] = OP_CHECKSIG;
|
||||
return true;
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
unsigned char vch[33] = {};
|
||||
vch[0] = nSize - 2;
|
||||
memcpy(&vch[1], &in[0], 32);
|
||||
CPubKey pubkey(&vch[0], &vch[33]);
|
||||
if (!pubkey.Decompress())
|
||||
return false;
|
||||
assert(pubkey.size() == 65);
|
||||
script.resize(67);
|
||||
script[0] = 65;
|
||||
memcpy(&script[1], pubkey.begin(), 65);
|
||||
script[66] = OP_CHECKSIG;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Amount compression:
|
||||
// * If the amount is 0, output 0
|
||||
// * first, divide the amount (in base units) by the largest power of 10 possible; call the exponent e (e is max 9)
|
||||
// * if e<9, the last digit of the resulting number cannot be 0; store it as d, and drop it (divide by 10)
|
||||
// * call the result n
|
||||
// * output 1 + 10*(9*n + d - 1) + e
|
||||
// * if e==9, we only know the resulting number is not zero, so output 1 + 10*(n - 1) + 9
|
||||
// (this is decodable, as d is in [1-9] and e is in [0-9])
|
||||
|
||||
uint64_t CTxOutCompressor::CompressAmount(uint64_t n)
|
||||
{
|
||||
if (n == 0)
|
||||
return 0;
|
||||
int e = 0;
|
||||
while (((n % 10) == 0) && e < 9) {
|
||||
n /= 10;
|
||||
e++;
|
||||
}
|
||||
if (e < 9) {
|
||||
int d = (n % 10);
|
||||
assert(d >= 1 && d <= 9);
|
||||
n /= 10;
|
||||
return 1 + (n*9 + d - 1)*10 + e;
|
||||
} else {
|
||||
return 1 + (n - 1)*10 + 9;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t CTxOutCompressor::DecompressAmount(uint64_t x)
|
||||
{
|
||||
// x = 0 OR x = 1+10*(9*n + d - 1) + e OR x = 1+10*(n - 1) + 9
|
||||
if (x == 0)
|
||||
return 0;
|
||||
x--;
|
||||
// x = 10*(9*n + d - 1) + e
|
||||
int e = x % 10;
|
||||
x /= 10;
|
||||
uint64_t n = 0;
|
||||
if (e < 9) {
|
||||
// x = 9*n + d - 1
|
||||
int d = (x % 9) + 1;
|
||||
x /= 9;
|
||||
// x = n
|
||||
n = x*10 + d;
|
||||
} else {
|
||||
n = x+1;
|
||||
}
|
||||
while (e) {
|
||||
n *= 10;
|
||||
e--;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
123
src/compressor.h
123
src/compressor.h
|
|
@ -1,123 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_COMPRESSOR_H
|
||||
#define BITCOIN_COMPRESSOR_H
|
||||
|
||||
#include "primitives/transaction.h"
|
||||
#include "script/script.h"
|
||||
#include "serialize.h"
|
||||
|
||||
class CKeyID;
|
||||
class CPubKey;
|
||||
class CScriptID;
|
||||
|
||||
/** Compact serializer for scripts.
|
||||
*
|
||||
* It detects common cases and encodes them much more efficiently.
|
||||
* 3 special cases are defined:
|
||||
* * Pay to pubkey hash (encoded as 21 bytes)
|
||||
* * Pay to script hash (encoded as 21 bytes)
|
||||
* * Pay to pubkey starting with 0x02, 0x03 or 0x04 (encoded as 33 bytes)
|
||||
*
|
||||
* Other scripts up to 121 bytes require 1 byte + script length. Above
|
||||
* that, scripts up to 16505 bytes require 2 bytes + script length.
|
||||
*/
|
||||
class CScriptCompressor
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* make this static for now (there are only 6 special scripts defined)
|
||||
* this can potentially be extended together with a new nVersion for
|
||||
* transactions, in which case this value becomes dependent on nVersion
|
||||
* and nHeight of the enclosing transaction.
|
||||
*/
|
||||
static const unsigned int nSpecialScripts = 6;
|
||||
|
||||
CScript &script;
|
||||
protected:
|
||||
/**
|
||||
* These check for scripts for which a special case with a shorter encoding is defined.
|
||||
* They are implemented separately from the CScript test, as these test for exact byte
|
||||
* sequence correspondences, and are more strict. For example, IsToPubKey also verifies
|
||||
* whether the public key is valid (as invalid ones cannot be represented in compressed
|
||||
* form).
|
||||
*/
|
||||
bool IsToKeyID(CKeyID &hash) const;
|
||||
bool IsToScriptID(CScriptID &hash) const;
|
||||
bool IsToPubKey(CPubKey &pubkey) const;
|
||||
|
||||
bool Compress(std::vector<unsigned char> &out) const;
|
||||
unsigned int GetSpecialSize(unsigned int nSize) const;
|
||||
bool Decompress(unsigned int nSize, const std::vector<unsigned char> &out);
|
||||
public:
|
||||
CScriptCompressor(CScript &scriptIn) : script(scriptIn) { }
|
||||
|
||||
unsigned int GetSerializeSize(int nType, int nVersion) const {
|
||||
std::vector<unsigned char> compr;
|
||||
if (Compress(compr))
|
||||
return compr.size();
|
||||
unsigned int nSize = script.size() + nSpecialScripts;
|
||||
return script.size() + VARINT(nSize).GetSerializeSize(nType, nVersion);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream &s, int nType, int nVersion) const {
|
||||
std::vector<unsigned char> compr;
|
||||
if (Compress(compr)) {
|
||||
s << CFlatData(compr);
|
||||
return;
|
||||
}
|
||||
unsigned int nSize = script.size() + nSpecialScripts;
|
||||
s << VARINT(nSize);
|
||||
s << CFlatData(script);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream &s, int nType, int nVersion) {
|
||||
unsigned int nSize = 0;
|
||||
s >> VARINT(nSize);
|
||||
if (nSize < nSpecialScripts) {
|
||||
std::vector<unsigned char> vch(GetSpecialSize(nSize), 0x00);
|
||||
s >> REF(CFlatData(vch));
|
||||
Decompress(nSize, vch);
|
||||
return;
|
||||
}
|
||||
nSize -= nSpecialScripts;
|
||||
script.resize(nSize);
|
||||
s >> REF(CFlatData(script));
|
||||
}
|
||||
};
|
||||
|
||||
/** wrapper for CTxOut that provides a more compact serialization */
|
||||
class CTxOutCompressor
|
||||
{
|
||||
private:
|
||||
CTxOut &txout;
|
||||
|
||||
public:
|
||||
static uint64_t CompressAmount(uint64_t nAmount);
|
||||
static uint64_t DecompressAmount(uint64_t nAmount);
|
||||
|
||||
CTxOutCompressor(CTxOut &txoutIn) : txout(txoutIn) { }
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
if (!ser_action.ForRead()) {
|
||||
uint64_t nVal = CompressAmount(txout.nValue);
|
||||
READWRITE(VARINT(nVal));
|
||||
} else {
|
||||
uint64_t nVal = 0;
|
||||
READWRITE(VARINT(nVal));
|
||||
txout.nValue = DecompressAmount(nVal);
|
||||
}
|
||||
CScriptCompressor cscript(REF(txout.scriptPubKey));
|
||||
READWRITE(cscript);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BITCOIN_COMPRESSOR_H
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_CORE_IO_H
|
||||
#define BITCOIN_CORE_IO_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CBlock;
|
||||
class CScript;
|
||||
class CTransaction;
|
||||
class uint256;
|
||||
class UniValue;
|
||||
|
||||
// core_read.cpp
|
||||
extern CScript ParseScript(std::string s);
|
||||
extern bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx);
|
||||
extern bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
|
||||
extern uint256 ParseHashUV(const UniValue& v, const std::string& strName);
|
||||
extern uint256 ParseHashStr(const std::string&, const std::string& strName);
|
||||
extern std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName);
|
||||
|
||||
// core_write.cpp
|
||||
extern std::string FormatScript(const CScript& script);
|
||||
extern std::string EncodeHexTx(const CTransaction& tx);
|
||||
extern std::string EncodeHexBlock(const CBlock& block);
|
||||
extern void ScriptPubKeyToUniv(const CScript& scriptPubKey,
|
||||
UniValue& out, bool fIncludeHex);
|
||||
extern void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry);
|
||||
|
||||
#endif // BITCOIN_CORE_IO_H
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "core_io.h"
|
||||
|
||||
#include "primitives/block.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "script/script.h"
|
||||
#include "serialize.h"
|
||||
#include "streams.h"
|
||||
#include "univalue/univalue.h"
|
||||
#include "util.h"
|
||||
#include "utilstrencodings.h"
|
||||
#include "version.h"
|
||||
|
||||
#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/assign/list_of.hpp>
|
||||
|
||||
using namespace boost;
|
||||
using namespace boost::algorithm;
|
||||
using namespace std;
|
||||
|
||||
CScript ParseScript(std::string s)
|
||||
{
|
||||
CScript result;
|
||||
|
||||
static map<string, opcodetype> mapOpNames;
|
||||
|
||||
if (mapOpNames.empty())
|
||||
{
|
||||
for (int op = 0; op <= OP_NOP10; op++)
|
||||
{
|
||||
// Allow OP_RESERVED to get into mapOpNames
|
||||
if (op < OP_NOP && op != OP_RESERVED)
|
||||
continue;
|
||||
|
||||
const char* name = GetOpName((opcodetype)op);
|
||||
if (strcmp(name, "OP_UNKNOWN") == 0)
|
||||
continue;
|
||||
string strName(name);
|
||||
mapOpNames[strName] = (opcodetype)op;
|
||||
// Convenience: OP_ADD and just ADD are both recognized:
|
||||
replace_first(strName, "OP_", "");
|
||||
mapOpNames[strName] = (opcodetype)op;
|
||||
}
|
||||
}
|
||||
|
||||
vector<string> words;
|
||||
split(words, s, is_any_of(" \t\n"), token_compress_on);
|
||||
|
||||
for (std::vector<std::string>::const_iterator w = words.begin(); w != words.end(); ++w)
|
||||
{
|
||||
if (w->empty())
|
||||
{
|
||||
// Empty string, ignore. (boost::split given '' will return one word)
|
||||
}
|
||||
else if (all(*w, is_digit()) ||
|
||||
(starts_with(*w, "-") && all(string(w->begin()+1, w->end()), is_digit())))
|
||||
{
|
||||
// Number
|
||||
int64_t n = atoi64(*w);
|
||||
result << n;
|
||||
}
|
||||
else if (starts_with(*w, "0x") && (w->begin()+2 != w->end()) && IsHex(string(w->begin()+2, w->end())))
|
||||
{
|
||||
// Raw hex data, inserted NOT pushed onto stack:
|
||||
std::vector<unsigned char> raw = ParseHex(string(w->begin()+2, w->end()));
|
||||
result.insert(result.end(), raw.begin(), raw.end());
|
||||
}
|
||||
else if (w->size() >= 2 && starts_with(*w, "'") && ends_with(*w, "'"))
|
||||
{
|
||||
// Single-quoted string, pushed as data. NOTE: this is poor-man's
|
||||
// parsing, spaces/tabs/newlines in single-quoted strings won't work.
|
||||
std::vector<unsigned char> value(w->begin()+1, w->end()-1);
|
||||
result << value;
|
||||
}
|
||||
else if (mapOpNames.count(*w))
|
||||
{
|
||||
// opcode, e.g. OP_ADD or ADD:
|
||||
result << mapOpNames[*w];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw runtime_error("script parse error");
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx)
|
||||
{
|
||||
if (!IsHex(strHexTx))
|
||||
return false;
|
||||
|
||||
vector<unsigned char> txData(ParseHex(strHexTx));
|
||||
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
|
||||
try {
|
||||
ssData >> tx;
|
||||
if (!ssData.empty())
|
||||
return false;
|
||||
}
|
||||
catch (const std::exception &) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
|
||||
{
|
||||
if (!IsHex(strHexBlk))
|
||||
return false;
|
||||
|
||||
std::vector<unsigned char> blockData(ParseHex(strHexBlk));
|
||||
CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION);
|
||||
try {
|
||||
ssBlock >> block;
|
||||
}
|
||||
catch (const std::exception &) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint256 ParseHashUV(const UniValue& v, const string& strName)
|
||||
{
|
||||
string strHex;
|
||||
if (v.isStr())
|
||||
strHex = v.getValStr();
|
||||
return ParseHashStr(strHex, strName); // Note: ParseHashStr("") throws a runtime_error
|
||||
}
|
||||
|
||||
uint256 ParseHashStr(const std::string& strHex, const std::string& strName)
|
||||
{
|
||||
if (!IsHex(strHex)) // Note: IsHex("") is false
|
||||
throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");
|
||||
|
||||
uint256 result;
|
||||
result.SetHex(strHex);
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<unsigned char> ParseHexUV(const UniValue& v, const string& strName)
|
||||
{
|
||||
string strHex;
|
||||
if (v.isStr())
|
||||
strHex = v.getValStr();
|
||||
if (!IsHex(strHex))
|
||||
throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");
|
||||
return ParseHex(strHex);
|
||||
}
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "core_io.h"
|
||||
|
||||
#include "base58.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "script/script.h"
|
||||
#include "script/standard.h"
|
||||
#include "serialize.h"
|
||||
#include "streams.h"
|
||||
#include "univalue/univalue.h"
|
||||
#include "util.h"
|
||||
#include "utilmoneystr.h"
|
||||
#include "utilstrencodings.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
string FormatScript(const CScript& script)
|
||||
{
|
||||
string ret;
|
||||
CScript::const_iterator it = script.begin();
|
||||
opcodetype op;
|
||||
while (it != script.end()) {
|
||||
CScript::const_iterator it2 = it;
|
||||
vector<unsigned char> vch;
|
||||
if (script.GetOp2(it, op, &vch)) {
|
||||
if (op == OP_0) {
|
||||
ret += "0 ";
|
||||
continue;
|
||||
} else if ((op >= OP_1 && op <= OP_16) || op == OP_1NEGATE) {
|
||||
ret += strprintf("%i ", op - OP_1NEGATE - 1);
|
||||
continue;
|
||||
} else if (op >= OP_NOP && op <= OP_CHECKMULTISIGVERIFY) {
|
||||
string str(GetOpName(op));
|
||||
if (str.substr(0, 3) == string("OP_")) {
|
||||
ret += str.substr(3, string::npos) + " ";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (vch.size() > 0) {
|
||||
ret += strprintf("0x%x 0x%x ", HexStr(it2, it - vch.size()), HexStr(it - vch.size(), it));
|
||||
} else {
|
||||
ret += strprintf("0x%x", HexStr(it2, it));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
ret += strprintf("0x%x ", HexStr(it2, script.end()));
|
||||
break;
|
||||
}
|
||||
return ret.substr(0, ret.size() - 1);
|
||||
}
|
||||
|
||||
string EncodeHexTx(const CTransaction& tx)
|
||||
{
|
||||
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ssTx << tx;
|
||||
return HexStr(ssTx.begin(), ssTx.end());
|
||||
}
|
||||
|
||||
string EncodeHexBlock(const CBlock& block)
|
||||
{
|
||||
CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ssBlock << block;
|
||||
return HexStr(ssBlock.begin(), ssBlock.end());
|
||||
}
|
||||
|
||||
void ScriptPubKeyToUniv(const CScript& scriptPubKey,
|
||||
UniValue& out, bool fIncludeHex)
|
||||
{
|
||||
txnouttype type;
|
||||
vector<CTxDestination> addresses;
|
||||
int nRequired;
|
||||
|
||||
out.pushKV("asm", scriptPubKey.ToString());
|
||||
if (fIncludeHex)
|
||||
out.pushKV("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
|
||||
|
||||
if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) {
|
||||
out.pushKV("type", GetTxnOutputType(type));
|
||||
return;
|
||||
}
|
||||
|
||||
out.pushKV("reqSigs", nRequired);
|
||||
out.pushKV("type", GetTxnOutputType(type));
|
||||
|
||||
UniValue a(UniValue::VARR);
|
||||
BOOST_FOREACH(const CTxDestination& addr, addresses)
|
||||
a.push_back(CBitcoinAddress(addr).ToString());
|
||||
out.pushKV("addresses", a);
|
||||
}
|
||||
|
||||
void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry)
|
||||
{
|
||||
entry.pushKV("txid", tx.GetHash().GetHex());
|
||||
entry.pushKV("version", tx.nVersion);
|
||||
entry.pushKV("locktime", (int64_t)tx.nLockTime);
|
||||
|
||||
UniValue vin(UniValue::VARR);
|
||||
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
|
||||
UniValue in(UniValue::VOBJ);
|
||||
if (tx.IsCoinBase())
|
||||
in.pushKV("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()));
|
||||
else {
|
||||
in.pushKV("txid", txin.prevout.hash.GetHex());
|
||||
in.pushKV("vout", (int64_t)txin.prevout.n);
|
||||
UniValue o(UniValue::VOBJ);
|
||||
o.pushKV("asm", txin.scriptSig.ToString());
|
||||
o.pushKV("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()));
|
||||
in.pushKV("scriptSig", o);
|
||||
}
|
||||
in.pushKV("sequence", (int64_t)txin.nSequence);
|
||||
vin.push_back(in);
|
||||
}
|
||||
entry.pushKV("vin", vin);
|
||||
|
||||
UniValue vout(UniValue::VARR);
|
||||
for (unsigned int i = 0; i < tx.vout.size(); i++) {
|
||||
const CTxOut& txout = tx.vout[i];
|
||||
|
||||
UniValue out(UniValue::VOBJ);
|
||||
|
||||
UniValue outValue(UniValue::VNUM, FormatMoney(txout.nValue));
|
||||
out.pushKV("value", outValue);
|
||||
out.pushKV("n", (int64_t)i);
|
||||
|
||||
UniValue o(UniValue::VOBJ);
|
||||
ScriptPubKeyToUniv(txout.scriptPubKey, o, true);
|
||||
out.pushKV("scriptPubKey", o);
|
||||
vout.push_back(out);
|
||||
}
|
||||
entry.pushKV("vout", vout);
|
||||
|
||||
if (hashBlock != 0)
|
||||
entry.pushKV("blockhash", hashBlock.GetHex());
|
||||
|
||||
entry.pushKV("hex", EncodeHexTx(tx)); // the hex-encoded transaction. used the name "hex" to be consistent with the verbose output of "getrawtransaction".
|
||||
}
|
||||
297
src/crypter.cpp
297
src/crypter.cpp
|
|
@ -1,297 +0,0 @@
|
|||
// Copyright (c) 2009-2013 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "crypter.h"
|
||||
|
||||
#include "script/script.h"
|
||||
#include "script/standard.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
|
||||
{
|
||||
if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE)
|
||||
return false;
|
||||
|
||||
int i = 0;
|
||||
if (nDerivationMethod == 0)
|
||||
i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0],
|
||||
(unsigned char *)&strKeyData[0], strKeyData.size(), nRounds, chKey, chIV);
|
||||
|
||||
if (i != (int)WALLET_CRYPTO_KEY_SIZE)
|
||||
{
|
||||
OPENSSL_cleanse(chKey, sizeof(chKey));
|
||||
OPENSSL_cleanse(chIV, sizeof(chIV));
|
||||
return false;
|
||||
}
|
||||
|
||||
fKeySet = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCrypter::SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV)
|
||||
{
|
||||
if (chNewKey.size() != WALLET_CRYPTO_KEY_SIZE || chNewIV.size() != WALLET_CRYPTO_KEY_SIZE)
|
||||
return false;
|
||||
|
||||
memcpy(&chKey[0], &chNewKey[0], sizeof chKey);
|
||||
memcpy(&chIV[0], &chNewIV[0], sizeof chIV);
|
||||
|
||||
fKeySet = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext)
|
||||
{
|
||||
if (!fKeySet)
|
||||
return false;
|
||||
|
||||
// max ciphertext len for a n bytes of plaintext is
|
||||
// n + AES_BLOCK_SIZE - 1 bytes
|
||||
int nLen = vchPlaintext.size();
|
||||
int nCLen = nLen + AES_BLOCK_SIZE, nFLen = 0;
|
||||
vchCiphertext = std::vector<unsigned char> (nCLen);
|
||||
|
||||
EVP_CIPHER_CTX ctx;
|
||||
|
||||
bool fOk = true;
|
||||
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
if (fOk) fOk = EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0;
|
||||
if (fOk) fOk = EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen) != 0;
|
||||
if (fOk) fOk = EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0]) + nCLen, &nFLen) != 0;
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
|
||||
if (!fOk) return false;
|
||||
|
||||
vchCiphertext.resize(nCLen + nFLen);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCrypter::Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext)
|
||||
{
|
||||
if (!fKeySet)
|
||||
return false;
|
||||
|
||||
// plaintext will always be equal to or lesser than length of ciphertext
|
||||
int nLen = vchCiphertext.size();
|
||||
int nPLen = nLen, nFLen = 0;
|
||||
|
||||
vchPlaintext = CKeyingMaterial(nPLen);
|
||||
|
||||
EVP_CIPHER_CTX ctx;
|
||||
|
||||
bool fOk = true;
|
||||
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0;
|
||||
if (fOk) fOk = EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen) != 0;
|
||||
if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0]) + nPLen, &nFLen) != 0;
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
|
||||
if (!fOk) return false;
|
||||
|
||||
vchPlaintext.resize(nPLen + nFLen);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext)
|
||||
{
|
||||
CCrypter cKeyCrypter;
|
||||
std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE);
|
||||
memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE);
|
||||
if(!cKeyCrypter.SetKey(vMasterKey, chIV))
|
||||
return false;
|
||||
return cKeyCrypter.Encrypt(*((const CKeyingMaterial*)&vchPlaintext), vchCiphertext);
|
||||
}
|
||||
|
||||
bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext)
|
||||
{
|
||||
CCrypter cKeyCrypter;
|
||||
std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE);
|
||||
memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE);
|
||||
if(!cKeyCrypter.SetKey(vMasterKey, chIV))
|
||||
return false;
|
||||
return cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext));
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::SetCrypted()
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (fUseCrypto)
|
||||
return true;
|
||||
if (!mapKeys.empty())
|
||||
return false;
|
||||
fUseCrypto = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::Lock()
|
||||
{
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
vMasterKey.clear();
|
||||
}
|
||||
|
||||
NotifyStatusChanged(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
bool keyPass = false;
|
||||
bool keyFail = false;
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
|
||||
for (; mi != mapCryptedKeys.end(); ++mi)
|
||||
{
|
||||
const CPubKey &vchPubKey = (*mi).second.first;
|
||||
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
|
||||
CKeyingMaterial vchSecret;
|
||||
if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
|
||||
{
|
||||
keyFail = true;
|
||||
break;
|
||||
}
|
||||
if (vchSecret.size() != 32)
|
||||
{
|
||||
keyFail = true;
|
||||
break;
|
||||
}
|
||||
CKey key;
|
||||
key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
|
||||
if (key.GetPubKey() != vchPubKey)
|
||||
{
|
||||
keyFail = true;
|
||||
break;
|
||||
}
|
||||
keyPass = true;
|
||||
if (fDecryptionThoroughlyChecked)
|
||||
break;
|
||||
}
|
||||
if (keyPass && keyFail)
|
||||
{
|
||||
LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all.");
|
||||
assert(false);
|
||||
}
|
||||
if (keyFail || !keyPass)
|
||||
return false;
|
||||
vMasterKey = vMasterKeyIn;
|
||||
fDecryptionThoroughlyChecked = true;
|
||||
}
|
||||
NotifyStatusChanged(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return CBasicKeyStore::AddKeyPubKey(key, pubkey);
|
||||
|
||||
if (IsLocked())
|
||||
return false;
|
||||
|
||||
std::vector<unsigned char> vchCryptedSecret;
|
||||
CKeyingMaterial vchSecret(key.begin(), key.end());
|
||||
if (!EncryptSecret(vMasterKey, vchSecret, pubkey.GetHash(), vchCryptedSecret))
|
||||
return false;
|
||||
|
||||
if (!AddCryptedKey(pubkey, vchCryptedSecret))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return CBasicKeyStore::GetKey(address, keyOut);
|
||||
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
|
||||
if (mi != mapCryptedKeys.end())
|
||||
{
|
||||
const CPubKey &vchPubKey = (*mi).second.first;
|
||||
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
|
||||
CKeyingMaterial vchSecret;
|
||||
if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
|
||||
return false;
|
||||
if (vchSecret.size() != 32)
|
||||
return false;
|
||||
keyOut.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return CKeyStore::GetPubKey(address, vchPubKeyOut);
|
||||
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
|
||||
if (mi != mapCryptedKeys.end())
|
||||
{
|
||||
vchPubKeyOut = (*mi).second.first;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!mapCryptedKeys.empty() || IsCrypted())
|
||||
return false;
|
||||
|
||||
fUseCrypto = true;
|
||||
BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
|
||||
{
|
||||
const CKey &key = mKey.second;
|
||||
CPubKey vchPubKey = key.GetPubKey();
|
||||
CKeyingMaterial vchSecret(key.begin(), key.end());
|
||||
std::vector<unsigned char> vchCryptedSecret;
|
||||
if (!EncryptSecret(vMasterKeyIn, vchSecret, vchPubKey.GetHash(), vchCryptedSecret))
|
||||
return false;
|
||||
if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
|
||||
return false;
|
||||
}
|
||||
mapKeys.clear();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
199
src/crypter.h
199
src/crypter.h
|
|
@ -1,199 +0,0 @@
|
|||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_CRYPTER_H
|
||||
#define BITCOIN_CRYPTER_H
|
||||
|
||||
#include "allocators.h"
|
||||
#include "keystore.h"
|
||||
#include "serialize.h"
|
||||
|
||||
class uint256;
|
||||
|
||||
const unsigned int WALLET_CRYPTO_KEY_SIZE = 32;
|
||||
const unsigned int WALLET_CRYPTO_SALT_SIZE = 8;
|
||||
|
||||
/**
|
||||
* Private key encryption is done based on a CMasterKey,
|
||||
* which holds a salt and random encryption key.
|
||||
*
|
||||
* CMasterKeys are encrypted using AES-256-CBC using a key
|
||||
* derived using derivation method nDerivationMethod
|
||||
* (0 == EVP_sha512()) and derivation iterations nDeriveIterations.
|
||||
* vchOtherDerivationParameters is provided for alternative algorithms
|
||||
* which may require more parameters (such as scrypt).
|
||||
*
|
||||
* Wallet Private Keys are then encrypted using AES-256-CBC
|
||||
* with the double-sha256 of the public key as the IV, and the
|
||||
* master key's key as the encryption key (see keystore.[ch]).
|
||||
*/
|
||||
|
||||
/** Master key for wallet encryption */
|
||||
class CMasterKey
|
||||
{
|
||||
public:
|
||||
std::vector<unsigned char> vchCryptedKey;
|
||||
std::vector<unsigned char> vchSalt;
|
||||
//! 0 = EVP_sha512()
|
||||
//! 1 = scrypt()
|
||||
unsigned int nDerivationMethod;
|
||||
unsigned int nDeriveIterations;
|
||||
//! Use this for more parameters to key derivation,
|
||||
//! such as the various parameters to scrypt
|
||||
std::vector<unsigned char> vchOtherDerivationParameters;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(vchCryptedKey);
|
||||
READWRITE(vchSalt);
|
||||
READWRITE(nDerivationMethod);
|
||||
READWRITE(nDeriveIterations);
|
||||
READWRITE(vchOtherDerivationParameters);
|
||||
}
|
||||
|
||||
CMasterKey()
|
||||
{
|
||||
// 25000 rounds is just under 0.1 seconds on a 1.86 GHz Pentium M
|
||||
// ie slightly lower than the lowest hardware we need bother supporting
|
||||
nDeriveIterations = 25000;
|
||||
nDerivationMethod = 0;
|
||||
vchOtherDerivationParameters = std::vector<unsigned char>(0);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
|
||||
|
||||
/** Encryption/decryption context with key information */
|
||||
class CCrypter
|
||||
{
|
||||
private:
|
||||
unsigned char chKey[WALLET_CRYPTO_KEY_SIZE];
|
||||
unsigned char chIV[WALLET_CRYPTO_KEY_SIZE];
|
||||
bool fKeySet;
|
||||
|
||||
public:
|
||||
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod);
|
||||
bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext);
|
||||
bool Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext);
|
||||
bool SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV);
|
||||
|
||||
void CleanKey()
|
||||
{
|
||||
OPENSSL_cleanse(chKey, sizeof(chKey));
|
||||
OPENSSL_cleanse(chIV, sizeof(chIV));
|
||||
fKeySet = false;
|
||||
}
|
||||
|
||||
CCrypter()
|
||||
{
|
||||
fKeySet = false;
|
||||
|
||||
// Try to keep the key data out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap)
|
||||
// Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
|
||||
// Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.
|
||||
LockedPageManager::Instance().LockRange(&chKey[0], sizeof chKey);
|
||||
LockedPageManager::Instance().LockRange(&chIV[0], sizeof chIV);
|
||||
}
|
||||
|
||||
~CCrypter()
|
||||
{
|
||||
CleanKey();
|
||||
|
||||
LockedPageManager::Instance().UnlockRange(&chKey[0], sizeof chKey);
|
||||
LockedPageManager::Instance().UnlockRange(&chIV[0], sizeof chIV);
|
||||
}
|
||||
};
|
||||
|
||||
bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext);
|
||||
bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext);
|
||||
|
||||
/** Keystore which keeps the private keys encrypted.
|
||||
* It derives from the basic key store, which is used if no encryption is active.
|
||||
*/
|
||||
class CCryptoKeyStore : public CBasicKeyStore
|
||||
{
|
||||
private:
|
||||
CryptedKeyMap mapCryptedKeys;
|
||||
|
||||
CKeyingMaterial vMasterKey;
|
||||
|
||||
//! if fUseCrypto is true, mapKeys must be empty
|
||||
//! if fUseCrypto is false, vMasterKey must be empty
|
||||
bool fUseCrypto;
|
||||
|
||||
//! keeps track of whether Unlock has run a thorough check before
|
||||
bool fDecryptionThoroughlyChecked;
|
||||
|
||||
protected:
|
||||
bool SetCrypted();
|
||||
|
||||
//! will encrypt previously unencrypted keys
|
||||
bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
|
||||
|
||||
bool Unlock(const CKeyingMaterial& vMasterKeyIn);
|
||||
|
||||
public:
|
||||
CCryptoKeyStore() : fUseCrypto(false), fDecryptionThoroughlyChecked(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsCrypted() const
|
||||
{
|
||||
return fUseCrypto;
|
||||
}
|
||||
|
||||
bool IsLocked() const
|
||||
{
|
||||
if (!IsCrypted())
|
||||
return false;
|
||||
bool result;
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
result = vMasterKey.empty();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Lock();
|
||||
|
||||
virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
|
||||
bool HaveKey(const CKeyID &address) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return CBasicKeyStore::HaveKey(address);
|
||||
return mapCryptedKeys.count(address) > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool GetKey(const CKeyID &address, CKey& keyOut) const;
|
||||
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
|
||||
void GetKeys(std::set<CKeyID> &setAddress) const
|
||||
{
|
||||
if (!IsCrypted())
|
||||
{
|
||||
CBasicKeyStore::GetKeys(setAddress);
|
||||
return;
|
||||
}
|
||||
setAddress.clear();
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
|
||||
while (mi != mapCryptedKeys.end())
|
||||
{
|
||||
setAddress.insert((*mi).first);
|
||||
mi++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wallet status (encrypted, locked) changed.
|
||||
* Note: Called without locks held.
|
||||
*/
|
||||
boost::signals2::signal<void (CCryptoKeyStore* wallet)> NotifyStatusChanged;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_CRYPTER_H
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
// Copyright (c) 2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_CRYPTO_COMMON_H
|
||||
#define BITCOIN_CRYPTO_COMMON_H
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "bitcoin-config.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(HAVE_ENDIAN_H)
|
||||
#include <endian.h>
|
||||
#endif
|
||||
|
||||
uint32_t static inline ReadLE32(const unsigned char* ptr)
|
||||
{
|
||||
#if HAVE_DECL_LE32TOH == 1
|
||||
return le32toh(*((uint32_t*)ptr));
|
||||
#elif !defined(WORDS_BIGENDIAN)
|
||||
return *((uint32_t*)ptr);
|
||||
#else
|
||||
return ((uint32_t)ptr[3] << 24 | (uint32_t)ptr[2] << 16 | (uint32_t)ptr[1] << 8 | (uint32_t)ptr[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t static inline ReadLE64(const unsigned char* ptr)
|
||||
{
|
||||
#if HAVE_DECL_LE64TOH == 1
|
||||
return le64toh(*((uint64_t*)ptr));
|
||||
#elif !defined(WORDS_BIGENDIAN)
|
||||
return *((uint64_t*)ptr);
|
||||
#else
|
||||
return ((uint64_t)ptr[7] << 56 | (uint64_t)ptr[6] << 48 | (uint64_t)ptr[5] << 40 | (uint64_t)ptr[4] << 32 |
|
||||
(uint64_t)ptr[3] << 24 | (uint64_t)ptr[2] << 16 | (uint64_t)ptr[1] << 8 | (uint64_t)ptr[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void static inline WriteLE32(unsigned char* ptr, uint32_t x)
|
||||
{
|
||||
#if HAVE_DECL_HTOLE32 == 1
|
||||
*((uint32_t*)ptr) = htole32(x);
|
||||
#elif !defined(WORDS_BIGENDIAN)
|
||||
*((uint32_t*)ptr) = x;
|
||||
#else
|
||||
ptr[3] = x >> 24;
|
||||
ptr[2] = x >> 16;
|
||||
ptr[1] = x >> 8;
|
||||
ptr[0] = x;
|
||||
#endif
|
||||
}
|
||||
|
||||
void static inline WriteLE64(unsigned char* ptr, uint64_t x)
|
||||
{
|
||||
#if HAVE_DECL_HTOLE64 == 1
|
||||
*((uint64_t*)ptr) = htole64(x);
|
||||
#elif !defined(WORDS_BIGENDIAN)
|
||||
*((uint64_t*)ptr) = x;
|
||||
#else
|
||||
ptr[7] = x >> 56;
|
||||
ptr[6] = x >> 48;
|
||||
ptr[5] = x >> 40;
|
||||
ptr[4] = x >> 32;
|
||||
ptr[3] = x >> 24;
|
||||
ptr[2] = x >> 16;
|
||||
ptr[1] = x >> 8;
|
||||
ptr[0] = x;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t static inline ReadBE32(const unsigned char* ptr)
|
||||
{
|
||||
#if HAVE_DECL_BE32TOH == 1
|
||||
return be32toh(*((uint32_t*)ptr));
|
||||
#else
|
||||
return ((uint32_t)ptr[0] << 24 | (uint32_t)ptr[1] << 16 | (uint32_t)ptr[2] << 8 | (uint32_t)ptr[3]);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t static inline ReadBE64(const unsigned char* ptr)
|
||||
{
|
||||
#if HAVE_DECL_BE64TOH == 1
|
||||
return be64toh(*((uint64_t*)ptr));
|
||||
#else
|
||||
return ((uint64_t)ptr[0] << 56 | (uint64_t)ptr[1] << 48 | (uint64_t)ptr[2] << 40 | (uint64_t)ptr[3] << 32 |
|
||||
(uint64_t)ptr[4] << 24 | (uint64_t)ptr[5] << 16 | (uint64_t)ptr[6] << 8 | (uint64_t)ptr[7]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void static inline WriteBE32(unsigned char* ptr, uint32_t x)
|
||||
{
|
||||
#if HAVE_DECL_HTOBE32 == 1
|
||||
*((uint32_t*)ptr) = htobe32(x);
|
||||
#else
|
||||
ptr[0] = x >> 24;
|
||||
ptr[1] = x >> 16;
|
||||
ptr[2] = x >> 8;
|
||||
ptr[3] = x;
|
||||
#endif
|
||||
}
|
||||
|
||||
void static inline WriteBE64(unsigned char* ptr, uint64_t x)
|
||||
{
|
||||
#if HAVE_DECL_HTOBE64 == 1
|
||||
*((uint64_t*)ptr) = htobe64(x);
|
||||
#else
|
||||
ptr[0] = x >> 56;
|
||||
ptr[1] = x >> 48;
|
||||
ptr[2] = x >> 40;
|
||||
ptr[3] = x >> 32;
|
||||
ptr[4] = x >> 24;
|
||||
ptr[5] = x >> 16;
|
||||
ptr[6] = x >> 8;
|
||||
ptr[7] = x;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // BITCOIN_CRYPTO_COMMON_H
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright (c) 2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "crypto/hmac_sha256.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
CHMAC_SHA256::CHMAC_SHA256(const unsigned char* key, size_t keylen)
|
||||
{
|
||||
unsigned char rkey[64];
|
||||
if (keylen <= 64) {
|
||||
memcpy(rkey, key, keylen);
|
||||
memset(rkey + keylen, 0, 64 - keylen);
|
||||
} else {
|
||||
CSHA256().Write(key, keylen).Finalize(rkey);
|
||||
memset(rkey + 32, 0, 32);
|
||||
}
|
||||
|
||||
for (int n = 0; n < 64; n++)
|
||||
rkey[n] ^= 0x5c;
|
||||
outer.Write(rkey, 64);
|
||||
|
||||
for (int n = 0; n < 64; n++)
|
||||
rkey[n] ^= 0x5c ^ 0x36;
|
||||
inner.Write(rkey, 64);
|
||||
}
|
||||
|
||||
void CHMAC_SHA256::Finalize(unsigned char hash[OUTPUT_SIZE])
|
||||
{
|
||||
unsigned char temp[32];
|
||||
inner.Finalize(temp);
|
||||
outer.Write(temp, 32).Finalize(hash);
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright (c) 2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_CRYPTO_HMAC_SHA256_H
|
||||
#define BITCOIN_CRYPTO_HMAC_SHA256_H
|
||||
|
||||
#include "crypto/sha256.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/** A hasher class for HMAC-SHA-512. */
|
||||
class CHMAC_SHA256
|
||||
{
|
||||
private:
|
||||
CSHA256 outer;
|
||||
CSHA256 inner;
|
||||
|
||||
public:
|
||||
static const size_t OUTPUT_SIZE = 32;
|
||||
|
||||
CHMAC_SHA256(const unsigned char* key, size_t keylen);
|
||||
CHMAC_SHA256& Write(const unsigned char* data, size_t len)
|
||||
{
|
||||
inner.Write(data, len);
|
||||
return *this;
|
||||
}
|
||||
void Finalize(unsigned char hash[OUTPUT_SIZE]);
|
||||
};
|
||||
|
||||
#endif // BITCOIN_CRYPTO_HMAC_SHA256_H
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright (c) 2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "crypto/hmac_sha512.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
CHMAC_SHA512::CHMAC_SHA512(const unsigned char* key, size_t keylen)
|
||||
{
|
||||
unsigned char rkey[128];
|
||||
if (keylen <= 128) {
|
||||
memcpy(rkey, key, keylen);
|
||||
memset(rkey + keylen, 0, 128 - keylen);
|
||||
} else {
|
||||
CSHA512().Write(key, keylen).Finalize(rkey);
|
||||
memset(rkey + 64, 0, 64);
|
||||
}
|
||||
|
||||
for (int n = 0; n < 128; n++)
|
||||
rkey[n] ^= 0x5c;
|
||||
outer.Write(rkey, 128);
|
||||
|
||||
for (int n = 0; n < 128; n++)
|
||||
rkey[n] ^= 0x5c ^ 0x36;
|
||||
inner.Write(rkey, 128);
|
||||
}
|
||||
|
||||
void CHMAC_SHA512::Finalize(unsigned char hash[OUTPUT_SIZE])
|
||||
{
|
||||
unsigned char temp[64];
|
||||
inner.Finalize(temp);
|
||||
outer.Write(temp, 64).Finalize(hash);
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright (c) 2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_CRYPTO_HMAC_SHA512_H
|
||||
#define BITCOIN_CRYPTO_HMAC_SHA512_H
|
||||
|
||||
#include "crypto/sha512.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/** A hasher class for HMAC-SHA-512. */
|
||||
class CHMAC_SHA512
|
||||
{
|
||||
private:
|
||||
CSHA512 outer;
|
||||
CSHA512 inner;
|
||||
|
||||
public:
|
||||
static const size_t OUTPUT_SIZE = 64;
|
||||
|
||||
CHMAC_SHA512(const unsigned char* key, size_t keylen);
|
||||
CHMAC_SHA512& Write(const unsigned char* data, size_t len)
|
||||
{
|
||||
inner.Write(data, len);
|
||||
return *this;
|
||||
}
|
||||
void Finalize(unsigned char hash[OUTPUT_SIZE]);
|
||||
};
|
||||
|
||||
#endif // BITCOIN_CRYPTO_HMAC_SHA512_H
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
// Copyright (c) 2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "crypto/rfc6979_hmac_sha256.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
static const unsigned char zero[1] = {0x00};
|
||||
static const unsigned char one[1] = {0x01};
|
||||
|
||||
RFC6979_HMAC_SHA256::RFC6979_HMAC_SHA256(const unsigned char* key, size_t keylen, const unsigned char* msg, size_t msglen) : retry(false)
|
||||
{
|
||||
memset(V, 0x01, sizeof(V));
|
||||
memset(K, 0x00, sizeof(K));
|
||||
|
||||
CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(zero, sizeof(zero)).Write(key, keylen).Write(msg, msglen).Finalize(K);
|
||||
CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V);
|
||||
CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(one, sizeof(one)).Write(key, keylen).Write(msg, msglen).Finalize(K);
|
||||
CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V);
|
||||
}
|
||||
|
||||
RFC6979_HMAC_SHA256::~RFC6979_HMAC_SHA256()
|
||||
{
|
||||
memset(V, 0x01, sizeof(V));
|
||||
memset(K, 0x00, sizeof(K));
|
||||
}
|
||||
|
||||
void RFC6979_HMAC_SHA256::Generate(unsigned char* output, size_t outputlen)
|
||||
{
|
||||
if (retry) {
|
||||
CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(zero, sizeof(zero)).Finalize(K);
|
||||
CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V);
|
||||
}
|
||||
|
||||
while (outputlen > 0) {
|
||||
CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V);
|
||||
size_t len = std::min(outputlen, sizeof(V));
|
||||
memcpy(output, V, len);
|
||||
output += len;
|
||||
outputlen -= len;
|
||||
}
|
||||
|
||||
retry = true;
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
// Copyright (c) 2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_RFC6979_HMAC_SHA256_H
|
||||
#define BITCOIN_RFC6979_HMAC_SHA256_H
|
||||
|
||||
#include "crypto/hmac_sha256.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/** The RFC 6979 PRNG using HMAC-SHA256. */
|
||||
class RFC6979_HMAC_SHA256
|
||||
{
|
||||
private:
|
||||
unsigned char V[CHMAC_SHA256::OUTPUT_SIZE];
|
||||
unsigned char K[CHMAC_SHA256::OUTPUT_SIZE];
|
||||
bool retry;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a new RFC6979 PRNG, using the given key and message.
|
||||
* The message is assumed to be already hashed.
|
||||
*/
|
||||
RFC6979_HMAC_SHA256(const unsigned char* key, size_t keylen, const unsigned char* msg, size_t msglen);
|
||||
|
||||
/**
|
||||
* Generate a byte array.
|
||||
*/
|
||||
void Generate(unsigned char* output, size_t outputlen);
|
||||
|
||||
~RFC6979_HMAC_SHA256();
|
||||
};
|
||||
|
||||
#endif // BITCOIN_RFC6979_HMAC_SHA256_H
|
||||
|
|
@ -1,292 +0,0 @@
|
|||
// Copyright (c) 2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "crypto/ripemd160.h"
|
||||
|
||||
#include "crypto/common.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
// Internal implementation code.
|
||||
namespace
|
||||
{
|
||||
/// Internal RIPEMD-160 implementation.
|
||||
namespace ripemd160
|
||||
{
|
||||
uint32_t inline f1(uint32_t x, uint32_t y, uint32_t z) { return x ^ y ^ z; }
|
||||
uint32_t inline f2(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (~x & z); }
|
||||
uint32_t inline f3(uint32_t x, uint32_t y, uint32_t z) { return (x | ~y) ^ z; }
|
||||
uint32_t inline f4(uint32_t x, uint32_t y, uint32_t z) { return (x & z) | (y & ~z); }
|
||||
uint32_t inline f5(uint32_t x, uint32_t y, uint32_t z) { return x ^ (y | ~z); }
|
||||
|
||||
/** Initialize RIPEMD-160 state. */
|
||||
void inline Initialize(uint32_t* s)
|
||||
{
|
||||
s[0] = 0x67452301ul;
|
||||
s[1] = 0xEFCDAB89ul;
|
||||
s[2] = 0x98BADCFEul;
|
||||
s[3] = 0x10325476ul;
|
||||
s[4] = 0xC3D2E1F0ul;
|
||||
}
|
||||
|
||||
uint32_t inline rol(uint32_t x, int i) { return (x << i) | (x >> (32 - i)); }
|
||||
|
||||
void inline Round(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t f, uint32_t x, uint32_t k, int r)
|
||||
{
|
||||
a = rol(a + f + x + k, r) + e;
|
||||
c = rol(c, 10);
|
||||
}
|
||||
|
||||
void inline R11(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f1(b, c, d), x, 0, r); }
|
||||
void inline R21(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f2(b, c, d), x, 0x5A827999ul, r); }
|
||||
void inline R31(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f3(b, c, d), x, 0x6ED9EBA1ul, r); }
|
||||
void inline R41(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f4(b, c, d), x, 0x8F1BBCDCul, r); }
|
||||
void inline R51(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f5(b, c, d), x, 0xA953FD4Eul, r); }
|
||||
|
||||
void inline R12(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f5(b, c, d), x, 0x50A28BE6ul, r); }
|
||||
void inline R22(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f4(b, c, d), x, 0x5C4DD124ul, r); }
|
||||
void inline R32(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f3(b, c, d), x, 0x6D703EF3ul, r); }
|
||||
void inline R42(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f2(b, c, d), x, 0x7A6D76E9ul, r); }
|
||||
void inline R52(uint32_t& a, uint32_t b, uint32_t& c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f1(b, c, d), x, 0, r); }
|
||||
|
||||
/** Perform a RIPEMD-160 transformation, processing a 64-byte chunk. */
|
||||
void Transform(uint32_t* s, const unsigned char* chunk)
|
||||
{
|
||||
uint32_t a1 = s[0], b1 = s[1], c1 = s[2], d1 = s[3], e1 = s[4];
|
||||
uint32_t a2 = a1, b2 = b1, c2 = c1, d2 = d1, e2 = e1;
|
||||
uint32_t w0 = ReadLE32(chunk + 0), w1 = ReadLE32(chunk + 4), w2 = ReadLE32(chunk + 8), w3 = ReadLE32(chunk + 12);
|
||||
uint32_t w4 = ReadLE32(chunk + 16), w5 = ReadLE32(chunk + 20), w6 = ReadLE32(chunk + 24), w7 = ReadLE32(chunk + 28);
|
||||
uint32_t w8 = ReadLE32(chunk + 32), w9 = ReadLE32(chunk + 36), w10 = ReadLE32(chunk + 40), w11 = ReadLE32(chunk + 44);
|
||||
uint32_t w12 = ReadLE32(chunk + 48), w13 = ReadLE32(chunk + 52), w14 = ReadLE32(chunk + 56), w15 = ReadLE32(chunk + 60);
|
||||
|
||||
R11(a1, b1, c1, d1, e1, w0, 11);
|
||||
R12(a2, b2, c2, d2, e2, w5, 8);
|
||||
R11(e1, a1, b1, c1, d1, w1, 14);
|
||||
R12(e2, a2, b2, c2, d2, w14, 9);
|
||||
R11(d1, e1, a1, b1, c1, w2, 15);
|
||||
R12(d2, e2, a2, b2, c2, w7, 9);
|
||||
R11(c1, d1, e1, a1, b1, w3, 12);
|
||||
R12(c2, d2, e2, a2, b2, w0, 11);
|
||||
R11(b1, c1, d1, e1, a1, w4, 5);
|
||||
R12(b2, c2, d2, e2, a2, w9, 13);
|
||||
R11(a1, b1, c1, d1, e1, w5, 8);
|
||||
R12(a2, b2, c2, d2, e2, w2, 15);
|
||||
R11(e1, a1, b1, c1, d1, w6, 7);
|
||||
R12(e2, a2, b2, c2, d2, w11, 15);
|
||||
R11(d1, e1, a1, b1, c1, w7, 9);
|
||||
R12(d2, e2, a2, b2, c2, w4, 5);
|
||||
R11(c1, d1, e1, a1, b1, w8, 11);
|
||||
R12(c2, d2, e2, a2, b2, w13, 7);
|
||||
R11(b1, c1, d1, e1, a1, w9, 13);
|
||||
R12(b2, c2, d2, e2, a2, w6, 7);
|
||||
R11(a1, b1, c1, d1, e1, w10, 14);
|
||||
R12(a2, b2, c2, d2, e2, w15, 8);
|
||||
R11(e1, a1, b1, c1, d1, w11, 15);
|
||||
R12(e2, a2, b2, c2, d2, w8, 11);
|
||||
R11(d1, e1, a1, b1, c1, w12, 6);
|
||||
R12(d2, e2, a2, b2, c2, w1, 14);
|
||||
R11(c1, d1, e1, a1, b1, w13, 7);
|
||||
R12(c2, d2, e2, a2, b2, w10, 14);
|
||||
R11(b1, c1, d1, e1, a1, w14, 9);
|
||||
R12(b2, c2, d2, e2, a2, w3, 12);
|
||||
R11(a1, b1, c1, d1, e1, w15, 8);
|
||||
R12(a2, b2, c2, d2, e2, w12, 6);
|
||||
|
||||
R21(e1, a1, b1, c1, d1, w7, 7);
|
||||
R22(e2, a2, b2, c2, d2, w6, 9);
|
||||
R21(d1, e1, a1, b1, c1, w4, 6);
|
||||
R22(d2, e2, a2, b2, c2, w11, 13);
|
||||
R21(c1, d1, e1, a1, b1, w13, 8);
|
||||
R22(c2, d2, e2, a2, b2, w3, 15);
|
||||
R21(b1, c1, d1, e1, a1, w1, 13);
|
||||
R22(b2, c2, d2, e2, a2, w7, 7);
|
||||
R21(a1, b1, c1, d1, e1, w10, 11);
|
||||
R22(a2, b2, c2, d2, e2, w0, 12);
|
||||
R21(e1, a1, b1, c1, d1, w6, 9);
|
||||
R22(e2, a2, b2, c2, d2, w13, 8);
|
||||
R21(d1, e1, a1, b1, c1, w15, 7);
|
||||
R22(d2, e2, a2, b2, c2, w5, 9);
|
||||
R21(c1, d1, e1, a1, b1, w3, 15);
|
||||
R22(c2, d2, e2, a2, b2, w10, 11);
|
||||
R21(b1, c1, d1, e1, a1, w12, 7);
|
||||
R22(b2, c2, d2, e2, a2, w14, 7);
|
||||
R21(a1, b1, c1, d1, e1, w0, 12);
|
||||
R22(a2, b2, c2, d2, e2, w15, 7);
|
||||
R21(e1, a1, b1, c1, d1, w9, 15);
|
||||
R22(e2, a2, b2, c2, d2, w8, 12);
|
||||
R21(d1, e1, a1, b1, c1, w5, 9);
|
||||
R22(d2, e2, a2, b2, c2, w12, 7);
|
||||
R21(c1, d1, e1, a1, b1, w2, 11);
|
||||
R22(c2, d2, e2, a2, b2, w4, 6);
|
||||
R21(b1, c1, d1, e1, a1, w14, 7);
|
||||
R22(b2, c2, d2, e2, a2, w9, 15);
|
||||
R21(a1, b1, c1, d1, e1, w11, 13);
|
||||
R22(a2, b2, c2, d2, e2, w1, 13);
|
||||
R21(e1, a1, b1, c1, d1, w8, 12);
|
||||
R22(e2, a2, b2, c2, d2, w2, 11);
|
||||
|
||||
R31(d1, e1, a1, b1, c1, w3, 11);
|
||||
R32(d2, e2, a2, b2, c2, w15, 9);
|
||||
R31(c1, d1, e1, a1, b1, w10, 13);
|
||||
R32(c2, d2, e2, a2, b2, w5, 7);
|
||||
R31(b1, c1, d1, e1, a1, w14, 6);
|
||||
R32(b2, c2, d2, e2, a2, w1, 15);
|
||||
R31(a1, b1, c1, d1, e1, w4, 7);
|
||||
R32(a2, b2, c2, d2, e2, w3, 11);
|
||||
R31(e1, a1, b1, c1, d1, w9, 14);
|
||||
R32(e2, a2, b2, c2, d2, w7, 8);
|
||||
R31(d1, e1, a1, b1, c1, w15, 9);
|
||||
R32(d2, e2, a2, b2, c2, w14, 6);
|
||||
R31(c1, d1, e1, a1, b1, w8, 13);
|
||||
R32(c2, d2, e2, a2, b2, w6, 6);
|
||||
R31(b1, c1, d1, e1, a1, w1, 15);
|
||||
R32(b2, c2, d2, e2, a2, w9, 14);
|
||||
R31(a1, b1, c1, d1, e1, w2, 14);
|
||||
R32(a2, b2, c2, d2, e2, w11, 12);
|
||||
R31(e1, a1, b1, c1, d1, w7, 8);
|
||||
R32(e2, a2, b2, c2, d2, w8, 13);
|
||||
R31(d1, e1, a1, b1, c1, w0, 13);
|
||||
R32(d2, e2, a2, b2, c2, w12, 5);
|
||||
R31(c1, d1, e1, a1, b1, w6, 6);
|
||||
R32(c2, d2, e2, a2, b2, w2, 14);
|
||||
R31(b1, c1, d1, e1, a1, w13, 5);
|
||||
R32(b2, c2, d2, e2, a2, w10, 13);
|
||||
R31(a1, b1, c1, d1, e1, w11, 12);
|
||||
R32(a2, b2, c2, d2, e2, w0, 13);
|
||||
R31(e1, a1, b1, c1, d1, w5, 7);
|
||||
R32(e2, a2, b2, c2, d2, w4, 7);
|
||||
R31(d1, e1, a1, b1, c1, w12, 5);
|
||||
R32(d2, e2, a2, b2, c2, w13, 5);
|
||||
|
||||
R41(c1, d1, e1, a1, b1, w1, 11);
|
||||
R42(c2, d2, e2, a2, b2, w8, 15);
|
||||
R41(b1, c1, d1, e1, a1, w9, 12);
|
||||
R42(b2, c2, d2, e2, a2, w6, 5);
|
||||
R41(a1, b1, c1, d1, e1, w11, 14);
|
||||
R42(a2, b2, c2, d2, e2, w4, 8);
|
||||
R41(e1, a1, b1, c1, d1, w10, 15);
|
||||
R42(e2, a2, b2, c2, d2, w1, 11);
|
||||
R41(d1, e1, a1, b1, c1, w0, 14);
|
||||
R42(d2, e2, a2, b2, c2, w3, 14);
|
||||
R41(c1, d1, e1, a1, b1, w8, 15);
|
||||
R42(c2, d2, e2, a2, b2, w11, 14);
|
||||
R41(b1, c1, d1, e1, a1, w12, 9);
|
||||
R42(b2, c2, d2, e2, a2, w15, 6);
|
||||
R41(a1, b1, c1, d1, e1, w4, 8);
|
||||
R42(a2, b2, c2, d2, e2, w0, 14);
|
||||
R41(e1, a1, b1, c1, d1, w13, 9);
|
||||
R42(e2, a2, b2, c2, d2, w5, 6);
|
||||
R41(d1, e1, a1, b1, c1, w3, 14);
|
||||
R42(d2, e2, a2, b2, c2, w12, 9);
|
||||
R41(c1, d1, e1, a1, b1, w7, 5);
|
||||
R42(c2, d2, e2, a2, b2, w2, 12);
|
||||
R41(b1, c1, d1, e1, a1, w15, 6);
|
||||
R42(b2, c2, d2, e2, a2, w13, 9);
|
||||
R41(a1, b1, c1, d1, e1, w14, 8);
|
||||
R42(a2, b2, c2, d2, e2, w9, 12);
|
||||
R41(e1, a1, b1, c1, d1, w5, 6);
|
||||
R42(e2, a2, b2, c2, d2, w7, 5);
|
||||
R41(d1, e1, a1, b1, c1, w6, 5);
|
||||
R42(d2, e2, a2, b2, c2, w10, 15);
|
||||
R41(c1, d1, e1, a1, b1, w2, 12);
|
||||
R42(c2, d2, e2, a2, b2, w14, 8);
|
||||
|
||||
R51(b1, c1, d1, e1, a1, w4, 9);
|
||||
R52(b2, c2, d2, e2, a2, w12, 8);
|
||||
R51(a1, b1, c1, d1, e1, w0, 15);
|
||||
R52(a2, b2, c2, d2, e2, w15, 5);
|
||||
R51(e1, a1, b1, c1, d1, w5, 5);
|
||||
R52(e2, a2, b2, c2, d2, w10, 12);
|
||||
R51(d1, e1, a1, b1, c1, w9, 11);
|
||||
R52(d2, e2, a2, b2, c2, w4, 9);
|
||||
R51(c1, d1, e1, a1, b1, w7, 6);
|
||||
R52(c2, d2, e2, a2, b2, w1, 12);
|
||||
R51(b1, c1, d1, e1, a1, w12, 8);
|
||||
R52(b2, c2, d2, e2, a2, w5, 5);
|
||||
R51(a1, b1, c1, d1, e1, w2, 13);
|
||||
R52(a2, b2, c2, d2, e2, w8, 14);
|
||||
R51(e1, a1, b1, c1, d1, w10, 12);
|
||||
R52(e2, a2, b2, c2, d2, w7, 6);
|
||||
R51(d1, e1, a1, b1, c1, w14, 5);
|
||||
R52(d2, e2, a2, b2, c2, w6, 8);
|
||||
R51(c1, d1, e1, a1, b1, w1, 12);
|
||||
R52(c2, d2, e2, a2, b2, w2, 13);
|
||||
R51(b1, c1, d1, e1, a1, w3, 13);
|
||||
R52(b2, c2, d2, e2, a2, w13, 6);
|
||||
R51(a1, b1, c1, d1, e1, w8, 14);
|
||||
R52(a2, b2, c2, d2, e2, w14, 5);
|
||||
R51(e1, a1, b1, c1, d1, w11, 11);
|
||||
R52(e2, a2, b2, c2, d2, w0, 15);
|
||||
R51(d1, e1, a1, b1, c1, w6, 8);
|
||||
R52(d2, e2, a2, b2, c2, w3, 13);
|
||||
R51(c1, d1, e1, a1, b1, w15, 5);
|
||||
R52(c2, d2, e2, a2, b2, w9, 11);
|
||||
R51(b1, c1, d1, e1, a1, w13, 6);
|
||||
R52(b2, c2, d2, e2, a2, w11, 11);
|
||||
|
||||
uint32_t t = s[0];
|
||||
s[0] = s[1] + c1 + d2;
|
||||
s[1] = s[2] + d1 + e2;
|
||||
s[2] = s[3] + e1 + a2;
|
||||
s[3] = s[4] + a1 + b2;
|
||||
s[4] = t + b1 + c2;
|
||||
}
|
||||
|
||||
} // namespace ripemd160
|
||||
|
||||
} // namespace
|
||||
|
||||
////// RIPEMD160
|
||||
|
||||
CRIPEMD160::CRIPEMD160() : bytes(0)
|
||||
{
|
||||
ripemd160::Initialize(s);
|
||||
}
|
||||
|
||||
CRIPEMD160& CRIPEMD160::Write(const unsigned char* data, size_t len)
|
||||
{
|
||||
const unsigned char* end = data + len;
|
||||
size_t bufsize = bytes % 64;
|
||||
if (bufsize && bufsize + len >= 64) {
|
||||
// Fill the buffer, and process it.
|
||||
memcpy(buf + bufsize, data, 64 - bufsize);
|
||||
bytes += 64 - bufsize;
|
||||
data += 64 - bufsize;
|
||||
ripemd160::Transform(s, buf);
|
||||
bufsize = 0;
|
||||
}
|
||||
while (end >= data + 64) {
|
||||
// Process full chunks directly from the source.
|
||||
ripemd160::Transform(s, data);
|
||||
bytes += 64;
|
||||
data += 64;
|
||||
}
|
||||
if (end > data) {
|
||||
// Fill the buffer with what remains.
|
||||
memcpy(buf + bufsize, data, end - data);
|
||||
bytes += end - data;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void CRIPEMD160::Finalize(unsigned char hash[OUTPUT_SIZE])
|
||||
{
|
||||
static const unsigned char pad[64] = {0x80};
|
||||
unsigned char sizedesc[8];
|
||||
WriteLE64(sizedesc, bytes << 3);
|
||||
Write(pad, 1 + ((119 - (bytes % 64)) % 64));
|
||||
Write(sizedesc, 8);
|
||||
WriteLE32(hash, s[0]);
|
||||
WriteLE32(hash + 4, s[1]);
|
||||
WriteLE32(hash + 8, s[2]);
|
||||
WriteLE32(hash + 12, s[3]);
|
||||
WriteLE32(hash + 16, s[4]);
|
||||
}
|
||||
|
||||
CRIPEMD160& CRIPEMD160::Reset()
|
||||
{
|
||||
bytes = 0;
|
||||
ripemd160::Initialize(s);
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
// Copyright (c) 2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_CRYPTO_RIPEMD160_H
|
||||
#define BITCOIN_CRYPTO_RIPEMD160_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/** A hasher class for RIPEMD-160. */
|
||||
class CRIPEMD160
|
||||
{
|
||||
private:
|
||||
uint32_t s[5];
|
||||
unsigned char buf[64];
|
||||
size_t bytes;
|
||||
|
||||
public:
|
||||
static const size_t OUTPUT_SIZE = 20;
|
||||
|
||||
CRIPEMD160();
|
||||
CRIPEMD160& Write(const unsigned char* data, size_t len);
|
||||
void Finalize(unsigned char hash[OUTPUT_SIZE]);
|
||||
CRIPEMD160& Reset();
|
||||
};
|
||||
|
||||
#endif // BITCOIN_CRYPTO_RIPEMD160_H
|
||||
|
|
@ -1,199 +0,0 @@
|
|||
// Copyright (c) 2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "crypto/sha1.h"
|
||||
|
||||
#include "crypto/common.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
// Internal implementation code.
|
||||
namespace
|
||||
{
|
||||
/// Internal SHA-1 implementation.
|
||||
namespace sha1
|
||||
{
|
||||
/** One round of SHA-1. */
|
||||
void inline Round(uint32_t a, uint32_t& b, uint32_t c, uint32_t d, uint32_t& e, uint32_t f, uint32_t k, uint32_t w)
|
||||
{
|
||||
e += ((a << 5) | (a >> 27)) + f + k + w;
|
||||
b = (b << 30) | (b >> 2);
|
||||
}
|
||||
|
||||
uint32_t inline f1(uint32_t b, uint32_t c, uint32_t d) { return d ^ (b & (c ^ d)); }
|
||||
uint32_t inline f2(uint32_t b, uint32_t c, uint32_t d) { return b ^ c ^ d; }
|
||||
uint32_t inline f3(uint32_t b, uint32_t c, uint32_t d) { return (b & c) | (d & (b | c)); }
|
||||
|
||||
uint32_t inline left(uint32_t x) { return (x << 1) | (x >> 31); }
|
||||
|
||||
/** Initialize SHA-1 state. */
|
||||
void inline Initialize(uint32_t* s)
|
||||
{
|
||||
s[0] = 0x67452301ul;
|
||||
s[1] = 0xEFCDAB89ul;
|
||||
s[2] = 0x98BADCFEul;
|
||||
s[3] = 0x10325476ul;
|
||||
s[4] = 0xC3D2E1F0ul;
|
||||
}
|
||||
|
||||
const uint32_t k1 = 0x5A827999ul;
|
||||
const uint32_t k2 = 0x6ED9EBA1ul;
|
||||
const uint32_t k3 = 0x8F1BBCDCul;
|
||||
const uint32_t k4 = 0xCA62C1D6ul;
|
||||
|
||||
/** Perform a SHA-1 transformation, processing a 64-byte chunk. */
|
||||
void Transform(uint32_t* s, const unsigned char* chunk)
|
||||
{
|
||||
uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4];
|
||||
uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
|
||||
|
||||
Round(a, b, c, d, e, f1(b, c, d), k1, w0 = ReadBE32(chunk + 0));
|
||||
Round(e, a, b, c, d, f1(a, b, c), k1, w1 = ReadBE32(chunk + 4));
|
||||
Round(d, e, a, b, c, f1(e, a, b), k1, w2 = ReadBE32(chunk + 8));
|
||||
Round(c, d, e, a, b, f1(d, e, a), k1, w3 = ReadBE32(chunk + 12));
|
||||
Round(b, c, d, e, a, f1(c, d, e), k1, w4 = ReadBE32(chunk + 16));
|
||||
Round(a, b, c, d, e, f1(b, c, d), k1, w5 = ReadBE32(chunk + 20));
|
||||
Round(e, a, b, c, d, f1(a, b, c), k1, w6 = ReadBE32(chunk + 24));
|
||||
Round(d, e, a, b, c, f1(e, a, b), k1, w7 = ReadBE32(chunk + 28));
|
||||
Round(c, d, e, a, b, f1(d, e, a), k1, w8 = ReadBE32(chunk + 32));
|
||||
Round(b, c, d, e, a, f1(c, d, e), k1, w9 = ReadBE32(chunk + 36));
|
||||
Round(a, b, c, d, e, f1(b, c, d), k1, w10 = ReadBE32(chunk + 40));
|
||||
Round(e, a, b, c, d, f1(a, b, c), k1, w11 = ReadBE32(chunk + 44));
|
||||
Round(d, e, a, b, c, f1(e, a, b), k1, w12 = ReadBE32(chunk + 48));
|
||||
Round(c, d, e, a, b, f1(d, e, a), k1, w13 = ReadBE32(chunk + 52));
|
||||
Round(b, c, d, e, a, f1(c, d, e), k1, w14 = ReadBE32(chunk + 56));
|
||||
Round(a, b, c, d, e, f1(b, c, d), k1, w15 = ReadBE32(chunk + 60));
|
||||
|
||||
Round(e, a, b, c, d, f1(a, b, c), k1, w0 = left(w0 ^ w13 ^ w8 ^ w2));
|
||||
Round(d, e, a, b, c, f1(e, a, b), k1, w1 = left(w1 ^ w14 ^ w9 ^ w3));
|
||||
Round(c, d, e, a, b, f1(d, e, a), k1, w2 = left(w2 ^ w15 ^ w10 ^ w4));
|
||||
Round(b, c, d, e, a, f1(c, d, e), k1, w3 = left(w3 ^ w0 ^ w11 ^ w5));
|
||||
Round(a, b, c, d, e, f2(b, c, d), k2, w4 = left(w4 ^ w1 ^ w12 ^ w6));
|
||||
Round(e, a, b, c, d, f2(a, b, c), k2, w5 = left(w5 ^ w2 ^ w13 ^ w7));
|
||||
Round(d, e, a, b, c, f2(e, a, b), k2, w6 = left(w6 ^ w3 ^ w14 ^ w8));
|
||||
Round(c, d, e, a, b, f2(d, e, a), k2, w7 = left(w7 ^ w4 ^ w15 ^ w9));
|
||||
Round(b, c, d, e, a, f2(c, d, e), k2, w8 = left(w8 ^ w5 ^ w0 ^ w10));
|
||||
Round(a, b, c, d, e, f2(b, c, d), k2, w9 = left(w9 ^ w6 ^ w1 ^ w11));
|
||||
Round(e, a, b, c, d, f2(a, b, c), k2, w10 = left(w10 ^ w7 ^ w2 ^ w12));
|
||||
Round(d, e, a, b, c, f2(e, a, b), k2, w11 = left(w11 ^ w8 ^ w3 ^ w13));
|
||||
Round(c, d, e, a, b, f2(d, e, a), k2, w12 = left(w12 ^ w9 ^ w4 ^ w14));
|
||||
Round(b, c, d, e, a, f2(c, d, e), k2, w13 = left(w13 ^ w10 ^ w5 ^ w15));
|
||||
Round(a, b, c, d, e, f2(b, c, d), k2, w14 = left(w14 ^ w11 ^ w6 ^ w0));
|
||||
Round(e, a, b, c, d, f2(a, b, c), k2, w15 = left(w15 ^ w12 ^ w7 ^ w1));
|
||||
|
||||
Round(d, e, a, b, c, f2(e, a, b), k2, w0 = left(w0 ^ w13 ^ w8 ^ w2));
|
||||
Round(c, d, e, a, b, f2(d, e, a), k2, w1 = left(w1 ^ w14 ^ w9 ^ w3));
|
||||
Round(b, c, d, e, a, f2(c, d, e), k2, w2 = left(w2 ^ w15 ^ w10 ^ w4));
|
||||
Round(a, b, c, d, e, f2(b, c, d), k2, w3 = left(w3 ^ w0 ^ w11 ^ w5));
|
||||
Round(e, a, b, c, d, f2(a, b, c), k2, w4 = left(w4 ^ w1 ^ w12 ^ w6));
|
||||
Round(d, e, a, b, c, f2(e, a, b), k2, w5 = left(w5 ^ w2 ^ w13 ^ w7));
|
||||
Round(c, d, e, a, b, f2(d, e, a), k2, w6 = left(w6 ^ w3 ^ w14 ^ w8));
|
||||
Round(b, c, d, e, a, f2(c, d, e), k2, w7 = left(w7 ^ w4 ^ w15 ^ w9));
|
||||
Round(a, b, c, d, e, f3(b, c, d), k3, w8 = left(w8 ^ w5 ^ w0 ^ w10));
|
||||
Round(e, a, b, c, d, f3(a, b, c), k3, w9 = left(w9 ^ w6 ^ w1 ^ w11));
|
||||
Round(d, e, a, b, c, f3(e, a, b), k3, w10 = left(w10 ^ w7 ^ w2 ^ w12));
|
||||
Round(c, d, e, a, b, f3(d, e, a), k3, w11 = left(w11 ^ w8 ^ w3 ^ w13));
|
||||
Round(b, c, d, e, a, f3(c, d, e), k3, w12 = left(w12 ^ w9 ^ w4 ^ w14));
|
||||
Round(a, b, c, d, e, f3(b, c, d), k3, w13 = left(w13 ^ w10 ^ w5 ^ w15));
|
||||
Round(e, a, b, c, d, f3(a, b, c), k3, w14 = left(w14 ^ w11 ^ w6 ^ w0));
|
||||
Round(d, e, a, b, c, f3(e, a, b), k3, w15 = left(w15 ^ w12 ^ w7 ^ w1));
|
||||
|
||||
Round(c, d, e, a, b, f3(d, e, a), k3, w0 = left(w0 ^ w13 ^ w8 ^ w2));
|
||||
Round(b, c, d, e, a, f3(c, d, e), k3, w1 = left(w1 ^ w14 ^ w9 ^ w3));
|
||||
Round(a, b, c, d, e, f3(b, c, d), k3, w2 = left(w2 ^ w15 ^ w10 ^ w4));
|
||||
Round(e, a, b, c, d, f3(a, b, c), k3, w3 = left(w3 ^ w0 ^ w11 ^ w5));
|
||||
Round(d, e, a, b, c, f3(e, a, b), k3, w4 = left(w4 ^ w1 ^ w12 ^ w6));
|
||||
Round(c, d, e, a, b, f3(d, e, a), k3, w5 = left(w5 ^ w2 ^ w13 ^ w7));
|
||||
Round(b, c, d, e, a, f3(c, d, e), k3, w6 = left(w6 ^ w3 ^ w14 ^ w8));
|
||||
Round(a, b, c, d, e, f3(b, c, d), k3, w7 = left(w7 ^ w4 ^ w15 ^ w9));
|
||||
Round(e, a, b, c, d, f3(a, b, c), k3, w8 = left(w8 ^ w5 ^ w0 ^ w10));
|
||||
Round(d, e, a, b, c, f3(e, a, b), k3, w9 = left(w9 ^ w6 ^ w1 ^ w11));
|
||||
Round(c, d, e, a, b, f3(d, e, a), k3, w10 = left(w10 ^ w7 ^ w2 ^ w12));
|
||||
Round(b, c, d, e, a, f3(c, d, e), k3, w11 = left(w11 ^ w8 ^ w3 ^ w13));
|
||||
Round(a, b, c, d, e, f2(b, c, d), k4, w12 = left(w12 ^ w9 ^ w4 ^ w14));
|
||||
Round(e, a, b, c, d, f2(a, b, c), k4, w13 = left(w13 ^ w10 ^ w5 ^ w15));
|
||||
Round(d, e, a, b, c, f2(e, a, b), k4, w14 = left(w14 ^ w11 ^ w6 ^ w0));
|
||||
Round(c, d, e, a, b, f2(d, e, a), k4, w15 = left(w15 ^ w12 ^ w7 ^ w1));
|
||||
|
||||
Round(b, c, d, e, a, f2(c, d, e), k4, w0 = left(w0 ^ w13 ^ w8 ^ w2));
|
||||
Round(a, b, c, d, e, f2(b, c, d), k4, w1 = left(w1 ^ w14 ^ w9 ^ w3));
|
||||
Round(e, a, b, c, d, f2(a, b, c), k4, w2 = left(w2 ^ w15 ^ w10 ^ w4));
|
||||
Round(d, e, a, b, c, f2(e, a, b), k4, w3 = left(w3 ^ w0 ^ w11 ^ w5));
|
||||
Round(c, d, e, a, b, f2(d, e, a), k4, w4 = left(w4 ^ w1 ^ w12 ^ w6));
|
||||
Round(b, c, d, e, a, f2(c, d, e), k4, w5 = left(w5 ^ w2 ^ w13 ^ w7));
|
||||
Round(a, b, c, d, e, f2(b, c, d), k4, w6 = left(w6 ^ w3 ^ w14 ^ w8));
|
||||
Round(e, a, b, c, d, f2(a, b, c), k4, w7 = left(w7 ^ w4 ^ w15 ^ w9));
|
||||
Round(d, e, a, b, c, f2(e, a, b), k4, w8 = left(w8 ^ w5 ^ w0 ^ w10));
|
||||
Round(c, d, e, a, b, f2(d, e, a), k4, w9 = left(w9 ^ w6 ^ w1 ^ w11));
|
||||
Round(b, c, d, e, a, f2(c, d, e), k4, w10 = left(w10 ^ w7 ^ w2 ^ w12));
|
||||
Round(a, b, c, d, e, f2(b, c, d), k4, w11 = left(w11 ^ w8 ^ w3 ^ w13));
|
||||
Round(e, a, b, c, d, f2(a, b, c), k4, w12 = left(w12 ^ w9 ^ w4 ^ w14));
|
||||
Round(d, e, a, b, c, f2(e, a, b), k4, left(w13 ^ w10 ^ w5 ^ w15));
|
||||
Round(c, d, e, a, b, f2(d, e, a), k4, left(w14 ^ w11 ^ w6 ^ w0));
|
||||
Round(b, c, d, e, a, f2(c, d, e), k4, left(w15 ^ w12 ^ w7 ^ w1));
|
||||
|
||||
s[0] += a;
|
||||
s[1] += b;
|
||||
s[2] += c;
|
||||
s[3] += d;
|
||||
s[4] += e;
|
||||
}
|
||||
|
||||
} // namespace sha1
|
||||
|
||||
} // namespace
|
||||
|
||||
////// SHA1
|
||||
|
||||
CSHA1::CSHA1() : bytes(0)
|
||||
{
|
||||
sha1::Initialize(s);
|
||||
}
|
||||
|
||||
CSHA1& CSHA1::Write(const unsigned char* data, size_t len)
|
||||
{
|
||||
const unsigned char* end = data + len;
|
||||
size_t bufsize = bytes % 64;
|
||||
if (bufsize && bufsize + len >= 64) {
|
||||
// Fill the buffer, and process it.
|
||||
memcpy(buf + bufsize, data, 64 - bufsize);
|
||||
bytes += 64 - bufsize;
|
||||
data += 64 - bufsize;
|
||||
sha1::Transform(s, buf);
|
||||
bufsize = 0;
|
||||
}
|
||||
while (end >= data + 64) {
|
||||
// Process full chunks directly from the source.
|
||||
sha1::Transform(s, data);
|
||||
bytes += 64;
|
||||
data += 64;
|
||||
}
|
||||
if (end > data) {
|
||||
// Fill the buffer with what remains.
|
||||
memcpy(buf + bufsize, data, end - data);
|
||||
bytes += end - data;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void CSHA1::Finalize(unsigned char hash[OUTPUT_SIZE])
|
||||
{
|
||||
static const unsigned char pad[64] = {0x80};
|
||||
unsigned char sizedesc[8];
|
||||
WriteBE64(sizedesc, bytes << 3);
|
||||
Write(pad, 1 + ((119 - (bytes % 64)) % 64));
|
||||
Write(sizedesc, 8);
|
||||
WriteBE32(hash, s[0]);
|
||||
WriteBE32(hash + 4, s[1]);
|
||||
WriteBE32(hash + 8, s[2]);
|
||||
WriteBE32(hash + 12, s[3]);
|
||||
WriteBE32(hash + 16, s[4]);
|
||||
}
|
||||
|
||||
CSHA1& CSHA1::Reset()
|
||||
{
|
||||
bytes = 0;
|
||||
sha1::Initialize(s);
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
// Copyright (c) 2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_CRYPTO_SHA1_H
|
||||
#define BITCOIN_CRYPTO_SHA1_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/** A hasher class for SHA1. */
|
||||
class CSHA1
|
||||
{
|
||||
private:
|
||||
uint32_t s[5];
|
||||
unsigned char buf[64];
|
||||
size_t bytes;
|
||||
|
||||
public:
|
||||
static const size_t OUTPUT_SIZE = 20;
|
||||
|
||||
CSHA1();
|
||||
CSHA1& Write(const unsigned char* data, size_t len);
|
||||
void Finalize(unsigned char hash[OUTPUT_SIZE]);
|
||||
CSHA1& Reset();
|
||||
};
|
||||
|
||||
#endif // BITCOIN_CRYPTO_SHA1_H
|
||||
|
|
@ -1,189 +0,0 @@
|
|||
// Copyright (c) 2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "crypto/sha256.h"
|
||||
|
||||
#include "crypto/common.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
// Internal implementation code.
|
||||
namespace
|
||||
{
|
||||
/// Internal SHA-256 implementation.
|
||||
namespace sha256
|
||||
{
|
||||
uint32_t inline Ch(uint32_t x, uint32_t y, uint32_t z) { return z ^ (x & (y ^ z)); }
|
||||
uint32_t inline Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (z & (x | y)); }
|
||||
uint32_t inline Sigma0(uint32_t x) { return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); }
|
||||
uint32_t inline Sigma1(uint32_t x) { return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); }
|
||||
uint32_t inline sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); }
|
||||
uint32_t inline sigma1(uint32_t x) { return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); }
|
||||
|
||||
/** One round of SHA-256. */
|
||||
void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t& d, uint32_t e, uint32_t f, uint32_t g, uint32_t& h, uint32_t k, uint32_t w)
|
||||
{
|
||||
uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w;
|
||||
uint32_t t2 = Sigma0(a) + Maj(a, b, c);
|
||||
d += t1;
|
||||
h = t1 + t2;
|
||||
}
|
||||
|
||||
/** Initialize SHA-256 state. */
|
||||
void inline Initialize(uint32_t* s)
|
||||
{
|
||||
s[0] = 0x6a09e667ul;
|
||||
s[1] = 0xbb67ae85ul;
|
||||
s[2] = 0x3c6ef372ul;
|
||||
s[3] = 0xa54ff53aul;
|
||||
s[4] = 0x510e527ful;
|
||||
s[5] = 0x9b05688cul;
|
||||
s[6] = 0x1f83d9abul;
|
||||
s[7] = 0x5be0cd19ul;
|
||||
}
|
||||
|
||||
/** Perform one SHA-256 transformation, processing a 64-byte chunk. */
|
||||
void Transform(uint32_t* s, const unsigned char* chunk)
|
||||
{
|
||||
uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7];
|
||||
uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
|
||||
|
||||
Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0));
|
||||
Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4));
|
||||
Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8));
|
||||
Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12));
|
||||
Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16));
|
||||
Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20));
|
||||
Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24));
|
||||
Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28));
|
||||
Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32));
|
||||
Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36));
|
||||
Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40));
|
||||
Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44));
|
||||
Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48));
|
||||
Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = ReadBE32(chunk + 52));
|
||||
Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56));
|
||||
Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60));
|
||||
|
||||
Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1));
|
||||
Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2));
|
||||
Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3));
|
||||
Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4));
|
||||
Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5));
|
||||
Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6));
|
||||
Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7));
|
||||
Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8));
|
||||
Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9));
|
||||
Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10));
|
||||
Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11));
|
||||
Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12));
|
||||
Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13));
|
||||
Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14));
|
||||
Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15));
|
||||
Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0));
|
||||
|
||||
Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1));
|
||||
Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2));
|
||||
Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3));
|
||||
Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4));
|
||||
Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5));
|
||||
Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6));
|
||||
Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7));
|
||||
Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8));
|
||||
Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9));
|
||||
Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10));
|
||||
Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11));
|
||||
Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12));
|
||||
Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13));
|
||||
Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14));
|
||||
Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15));
|
||||
Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0));
|
||||
|
||||
Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1));
|
||||
Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2));
|
||||
Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3));
|
||||
Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4));
|
||||
Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5));
|
||||
Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6));
|
||||
Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7));
|
||||
Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8));
|
||||
Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9));
|
||||
Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10));
|
||||
Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11));
|
||||
Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12));
|
||||
Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13));
|
||||
Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14));
|
||||
Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15));
|
||||
Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0));
|
||||
|
||||
s[0] += a;
|
||||
s[1] += b;
|
||||
s[2] += c;
|
||||
s[3] += d;
|
||||
s[4] += e;
|
||||
s[5] += f;
|
||||
s[6] += g;
|
||||
s[7] += h;
|
||||
}
|
||||
|
||||
} // namespace sha256
|
||||
} // namespace
|
||||
|
||||
|
||||
////// SHA-256
|
||||
|
||||
CSHA256::CSHA256() : bytes(0)
|
||||
{
|
||||
sha256::Initialize(s);
|
||||
}
|
||||
|
||||
CSHA256& CSHA256::Write(const unsigned char* data, size_t len)
|
||||
{
|
||||
const unsigned char* end = data + len;
|
||||
size_t bufsize = bytes % 64;
|
||||
if (bufsize && bufsize + len >= 64) {
|
||||
// Fill the buffer, and process it.
|
||||
memcpy(buf + bufsize, data, 64 - bufsize);
|
||||
bytes += 64 - bufsize;
|
||||
data += 64 - bufsize;
|
||||
sha256::Transform(s, buf);
|
||||
bufsize = 0;
|
||||
}
|
||||
while (end >= data + 64) {
|
||||
// Process full chunks directly from the source.
|
||||
sha256::Transform(s, data);
|
||||
bytes += 64;
|
||||
data += 64;
|
||||
}
|
||||
if (end > data) {
|
||||
// Fill the buffer with what remains.
|
||||
memcpy(buf + bufsize, data, end - data);
|
||||
bytes += end - data;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE])
|
||||
{
|
||||
static const unsigned char pad[64] = {0x80};
|
||||
unsigned char sizedesc[8];
|
||||
WriteBE64(sizedesc, bytes << 3);
|
||||
Write(pad, 1 + ((119 - (bytes % 64)) % 64));
|
||||
Write(sizedesc, 8);
|
||||
WriteBE32(hash, s[0]);
|
||||
WriteBE32(hash + 4, s[1]);
|
||||
WriteBE32(hash + 8, s[2]);
|
||||
WriteBE32(hash + 12, s[3]);
|
||||
WriteBE32(hash + 16, s[4]);
|
||||
WriteBE32(hash + 20, s[5]);
|
||||
WriteBE32(hash + 24, s[6]);
|
||||
WriteBE32(hash + 28, s[7]);
|
||||
}
|
||||
|
||||
CSHA256& CSHA256::Reset()
|
||||
{
|
||||
bytes = 0;
|
||||
sha256::Initialize(s);
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
// Copyright (c) 2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_CRYPTO_SHA256_H
|
||||
#define BITCOIN_CRYPTO_SHA256_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/** A hasher class for SHA-256. */
|
||||
class CSHA256
|
||||
{
|
||||
private:
|
||||
uint32_t s[8];
|
||||
unsigned char buf[64];
|
||||
size_t bytes;
|
||||
|
||||
public:
|
||||
static const size_t OUTPUT_SIZE = 32;
|
||||
|
||||
CSHA256();
|
||||
CSHA256& Write(const unsigned char* data, size_t len);
|
||||
void Finalize(unsigned char hash[OUTPUT_SIZE]);
|
||||
CSHA256& Reset();
|
||||
};
|
||||
|
||||
#endif // BITCOIN_CRYPTO_SHA256_H
|
||||
|
|
@ -1,207 +0,0 @@
|
|||
// Copyright (c) 2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "crypto/sha512.h"
|
||||
|
||||
#include "crypto/common.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
// Internal implementation code.
|
||||
namespace
|
||||
{
|
||||
/// Internal SHA-512 implementation.
|
||||
namespace sha512
|
||||
{
|
||||
uint64_t inline Ch(uint64_t x, uint64_t y, uint64_t z) { return z ^ (x & (y ^ z)); }
|
||||
uint64_t inline Maj(uint64_t x, uint64_t y, uint64_t z) { return (x & y) | (z & (x | y)); }
|
||||
uint64_t inline Sigma0(uint64_t x) { return (x >> 28 | x << 36) ^ (x >> 34 | x << 30) ^ (x >> 39 | x << 25); }
|
||||
uint64_t inline Sigma1(uint64_t x) { return (x >> 14 | x << 50) ^ (x >> 18 | x << 46) ^ (x >> 41 | x << 23); }
|
||||
uint64_t inline sigma0(uint64_t x) { return (x >> 1 | x << 63) ^ (x >> 8 | x << 56) ^ (x >> 7); }
|
||||
uint64_t inline sigma1(uint64_t x) { return (x >> 19 | x << 45) ^ (x >> 61 | x << 3) ^ (x >> 6); }
|
||||
|
||||
/** One round of SHA-512. */
|
||||
void inline Round(uint64_t a, uint64_t b, uint64_t c, uint64_t& d, uint64_t e, uint64_t f, uint64_t g, uint64_t& h, uint64_t k, uint64_t w)
|
||||
{
|
||||
uint64_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w;
|
||||
uint64_t t2 = Sigma0(a) + Maj(a, b, c);
|
||||
d += t1;
|
||||
h = t1 + t2;
|
||||
}
|
||||
|
||||
/** Initialize SHA-256 state. */
|
||||
void inline Initialize(uint64_t* s)
|
||||
{
|
||||
s[0] = 0x6a09e667f3bcc908ull;
|
||||
s[1] = 0xbb67ae8584caa73bull;
|
||||
s[2] = 0x3c6ef372fe94f82bull;
|
||||
s[3] = 0xa54ff53a5f1d36f1ull;
|
||||
s[4] = 0x510e527fade682d1ull;
|
||||
s[5] = 0x9b05688c2b3e6c1full;
|
||||
s[6] = 0x1f83d9abfb41bd6bull;
|
||||
s[7] = 0x5be0cd19137e2179ull;
|
||||
}
|
||||
|
||||
/** Perform one SHA-512 transformation, processing a 128-byte chunk. */
|
||||
void Transform(uint64_t* s, const unsigned char* chunk)
|
||||
{
|
||||
uint64_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7];
|
||||
uint64_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
|
||||
|
||||
Round(a, b, c, d, e, f, g, h, 0x428a2f98d728ae22ull, w0 = ReadBE64(chunk + 0));
|
||||
Round(h, a, b, c, d, e, f, g, 0x7137449123ef65cdull, w1 = ReadBE64(chunk + 8));
|
||||
Round(g, h, a, b, c, d, e, f, 0xb5c0fbcfec4d3b2full, w2 = ReadBE64(chunk + 16));
|
||||
Round(f, g, h, a, b, c, d, e, 0xe9b5dba58189dbbcull, w3 = ReadBE64(chunk + 24));
|
||||
Round(e, f, g, h, a, b, c, d, 0x3956c25bf348b538ull, w4 = ReadBE64(chunk + 32));
|
||||
Round(d, e, f, g, h, a, b, c, 0x59f111f1b605d019ull, w5 = ReadBE64(chunk + 40));
|
||||
Round(c, d, e, f, g, h, a, b, 0x923f82a4af194f9bull, w6 = ReadBE64(chunk + 48));
|
||||
Round(b, c, d, e, f, g, h, a, 0xab1c5ed5da6d8118ull, w7 = ReadBE64(chunk + 56));
|
||||
Round(a, b, c, d, e, f, g, h, 0xd807aa98a3030242ull, w8 = ReadBE64(chunk + 64));
|
||||
Round(h, a, b, c, d, e, f, g, 0x12835b0145706fbeull, w9 = ReadBE64(chunk + 72));
|
||||
Round(g, h, a, b, c, d, e, f, 0x243185be4ee4b28cull, w10 = ReadBE64(chunk + 80));
|
||||
Round(f, g, h, a, b, c, d, e, 0x550c7dc3d5ffb4e2ull, w11 = ReadBE64(chunk + 88));
|
||||
Round(e, f, g, h, a, b, c, d, 0x72be5d74f27b896full, w12 = ReadBE64(chunk + 96));
|
||||
Round(d, e, f, g, h, a, b, c, 0x80deb1fe3b1696b1ull, w13 = ReadBE64(chunk + 104));
|
||||
Round(c, d, e, f, g, h, a, b, 0x9bdc06a725c71235ull, w14 = ReadBE64(chunk + 112));
|
||||
Round(b, c, d, e, f, g, h, a, 0xc19bf174cf692694ull, w15 = ReadBE64(chunk + 120));
|
||||
|
||||
Round(a, b, c, d, e, f, g, h, 0xe49b69c19ef14ad2ull, w0 += sigma1(w14) + w9 + sigma0(w1));
|
||||
Round(h, a, b, c, d, e, f, g, 0xefbe4786384f25e3ull, w1 += sigma1(w15) + w10 + sigma0(w2));
|
||||
Round(g, h, a, b, c, d, e, f, 0x0fc19dc68b8cd5b5ull, w2 += sigma1(w0) + w11 + sigma0(w3));
|
||||
Round(f, g, h, a, b, c, d, e, 0x240ca1cc77ac9c65ull, w3 += sigma1(w1) + w12 + sigma0(w4));
|
||||
Round(e, f, g, h, a, b, c, d, 0x2de92c6f592b0275ull, w4 += sigma1(w2) + w13 + sigma0(w5));
|
||||
Round(d, e, f, g, h, a, b, c, 0x4a7484aa6ea6e483ull, w5 += sigma1(w3) + w14 + sigma0(w6));
|
||||
Round(c, d, e, f, g, h, a, b, 0x5cb0a9dcbd41fbd4ull, w6 += sigma1(w4) + w15 + sigma0(w7));
|
||||
Round(b, c, d, e, f, g, h, a, 0x76f988da831153b5ull, w7 += sigma1(w5) + w0 + sigma0(w8));
|
||||
Round(a, b, c, d, e, f, g, h, 0x983e5152ee66dfabull, w8 += sigma1(w6) + w1 + sigma0(w9));
|
||||
Round(h, a, b, c, d, e, f, g, 0xa831c66d2db43210ull, w9 += sigma1(w7) + w2 + sigma0(w10));
|
||||
Round(g, h, a, b, c, d, e, f, 0xb00327c898fb213full, w10 += sigma1(w8) + w3 + sigma0(w11));
|
||||
Round(f, g, h, a, b, c, d, e, 0xbf597fc7beef0ee4ull, w11 += sigma1(w9) + w4 + sigma0(w12));
|
||||
Round(e, f, g, h, a, b, c, d, 0xc6e00bf33da88fc2ull, w12 += sigma1(w10) + w5 + sigma0(w13));
|
||||
Round(d, e, f, g, h, a, b, c, 0xd5a79147930aa725ull, w13 += sigma1(w11) + w6 + sigma0(w14));
|
||||
Round(c, d, e, f, g, h, a, b, 0x06ca6351e003826full, w14 += sigma1(w12) + w7 + sigma0(w15));
|
||||
Round(b, c, d, e, f, g, h, a, 0x142929670a0e6e70ull, w15 += sigma1(w13) + w8 + sigma0(w0));
|
||||
|
||||
Round(a, b, c, d, e, f, g, h, 0x27b70a8546d22ffcull, w0 += sigma1(w14) + w9 + sigma0(w1));
|
||||
Round(h, a, b, c, d, e, f, g, 0x2e1b21385c26c926ull, w1 += sigma1(w15) + w10 + sigma0(w2));
|
||||
Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc5ac42aedull, w2 += sigma1(w0) + w11 + sigma0(w3));
|
||||
Round(f, g, h, a, b, c, d, e, 0x53380d139d95b3dfull, w3 += sigma1(w1) + w12 + sigma0(w4));
|
||||
Round(e, f, g, h, a, b, c, d, 0x650a73548baf63deull, w4 += sigma1(w2) + w13 + sigma0(w5));
|
||||
Round(d, e, f, g, h, a, b, c, 0x766a0abb3c77b2a8ull, w5 += sigma1(w3) + w14 + sigma0(w6));
|
||||
Round(c, d, e, f, g, h, a, b, 0x81c2c92e47edaee6ull, w6 += sigma1(w4) + w15 + sigma0(w7));
|
||||
Round(b, c, d, e, f, g, h, a, 0x92722c851482353bull, w7 += sigma1(w5) + w0 + sigma0(w8));
|
||||
Round(a, b, c, d, e, f, g, h, 0xa2bfe8a14cf10364ull, w8 += sigma1(w6) + w1 + sigma0(w9));
|
||||
Round(h, a, b, c, d, e, f, g, 0xa81a664bbc423001ull, w9 += sigma1(w7) + w2 + sigma0(w10));
|
||||
Round(g, h, a, b, c, d, e, f, 0xc24b8b70d0f89791ull, w10 += sigma1(w8) + w3 + sigma0(w11));
|
||||
Round(f, g, h, a, b, c, d, e, 0xc76c51a30654be30ull, w11 += sigma1(w9) + w4 + sigma0(w12));
|
||||
Round(e, f, g, h, a, b, c, d, 0xd192e819d6ef5218ull, w12 += sigma1(w10) + w5 + sigma0(w13));
|
||||
Round(d, e, f, g, h, a, b, c, 0xd69906245565a910ull, w13 += sigma1(w11) + w6 + sigma0(w14));
|
||||
Round(c, d, e, f, g, h, a, b, 0xf40e35855771202aull, w14 += sigma1(w12) + w7 + sigma0(w15));
|
||||
Round(b, c, d, e, f, g, h, a, 0x106aa07032bbd1b8ull, w15 += sigma1(w13) + w8 + sigma0(w0));
|
||||
|
||||
Round(a, b, c, d, e, f, g, h, 0x19a4c116b8d2d0c8ull, w0 += sigma1(w14) + w9 + sigma0(w1));
|
||||
Round(h, a, b, c, d, e, f, g, 0x1e376c085141ab53ull, w1 += sigma1(w15) + w10 + sigma0(w2));
|
||||
Round(g, h, a, b, c, d, e, f, 0x2748774cdf8eeb99ull, w2 += sigma1(w0) + w11 + sigma0(w3));
|
||||
Round(f, g, h, a, b, c, d, e, 0x34b0bcb5e19b48a8ull, w3 += sigma1(w1) + w12 + sigma0(w4));
|
||||
Round(e, f, g, h, a, b, c, d, 0x391c0cb3c5c95a63ull, w4 += sigma1(w2) + w13 + sigma0(w5));
|
||||
Round(d, e, f, g, h, a, b, c, 0x4ed8aa4ae3418acbull, w5 += sigma1(w3) + w14 + sigma0(w6));
|
||||
Round(c, d, e, f, g, h, a, b, 0x5b9cca4f7763e373ull, w6 += sigma1(w4) + w15 + sigma0(w7));
|
||||
Round(b, c, d, e, f, g, h, a, 0x682e6ff3d6b2b8a3ull, w7 += sigma1(w5) + w0 + sigma0(w8));
|
||||
Round(a, b, c, d, e, f, g, h, 0x748f82ee5defb2fcull, w8 += sigma1(w6) + w1 + sigma0(w9));
|
||||
Round(h, a, b, c, d, e, f, g, 0x78a5636f43172f60ull, w9 += sigma1(w7) + w2 + sigma0(w10));
|
||||
Round(g, h, a, b, c, d, e, f, 0x84c87814a1f0ab72ull, w10 += sigma1(w8) + w3 + sigma0(w11));
|
||||
Round(f, g, h, a, b, c, d, e, 0x8cc702081a6439ecull, w11 += sigma1(w9) + w4 + sigma0(w12));
|
||||
Round(e, f, g, h, a, b, c, d, 0x90befffa23631e28ull, w12 += sigma1(w10) + w5 + sigma0(w13));
|
||||
Round(d, e, f, g, h, a, b, c, 0xa4506cebde82bde9ull, w13 += sigma1(w11) + w6 + sigma0(w14));
|
||||
Round(c, d, e, f, g, h, a, b, 0xbef9a3f7b2c67915ull, w14 += sigma1(w12) + w7 + sigma0(w15));
|
||||
Round(b, c, d, e, f, g, h, a, 0xc67178f2e372532bull, w15 += sigma1(w13) + w8 + sigma0(w0));
|
||||
|
||||
Round(a, b, c, d, e, f, g, h, 0xca273eceea26619cull, w0 += sigma1(w14) + w9 + sigma0(w1));
|
||||
Round(h, a, b, c, d, e, f, g, 0xd186b8c721c0c207ull, w1 += sigma1(w15) + w10 + sigma0(w2));
|
||||
Round(g, h, a, b, c, d, e, f, 0xeada7dd6cde0eb1eull, w2 += sigma1(w0) + w11 + sigma0(w3));
|
||||
Round(f, g, h, a, b, c, d, e, 0xf57d4f7fee6ed178ull, w3 += sigma1(w1) + w12 + sigma0(w4));
|
||||
Round(e, f, g, h, a, b, c, d, 0x06f067aa72176fbaull, w4 += sigma1(w2) + w13 + sigma0(w5));
|
||||
Round(d, e, f, g, h, a, b, c, 0x0a637dc5a2c898a6ull, w5 += sigma1(w3) + w14 + sigma0(w6));
|
||||
Round(c, d, e, f, g, h, a, b, 0x113f9804bef90daeull, w6 += sigma1(w4) + w15 + sigma0(w7));
|
||||
Round(b, c, d, e, f, g, h, a, 0x1b710b35131c471bull, w7 += sigma1(w5) + w0 + sigma0(w8));
|
||||
Round(a, b, c, d, e, f, g, h, 0x28db77f523047d84ull, w8 += sigma1(w6) + w1 + sigma0(w9));
|
||||
Round(h, a, b, c, d, e, f, g, 0x32caab7b40c72493ull, w9 += sigma1(w7) + w2 + sigma0(w10));
|
||||
Round(g, h, a, b, c, d, e, f, 0x3c9ebe0a15c9bebcull, w10 += sigma1(w8) + w3 + sigma0(w11));
|
||||
Round(f, g, h, a, b, c, d, e, 0x431d67c49c100d4cull, w11 += sigma1(w9) + w4 + sigma0(w12));
|
||||
Round(e, f, g, h, a, b, c, d, 0x4cc5d4becb3e42b6ull, w12 += sigma1(w10) + w5 + sigma0(w13));
|
||||
Round(d, e, f, g, h, a, b, c, 0x597f299cfc657e2aull, w13 += sigma1(w11) + w6 + sigma0(w14));
|
||||
Round(c, d, e, f, g, h, a, b, 0x5fcb6fab3ad6faecull, w14 + sigma1(w12) + w7 + sigma0(w15));
|
||||
Round(b, c, d, e, f, g, h, a, 0x6c44198c4a475817ull, w15 + sigma1(w13) + w8 + sigma0(w0));
|
||||
|
||||
s[0] += a;
|
||||
s[1] += b;
|
||||
s[2] += c;
|
||||
s[3] += d;
|
||||
s[4] += e;
|
||||
s[5] += f;
|
||||
s[6] += g;
|
||||
s[7] += h;
|
||||
}
|
||||
|
||||
} // namespace sha512
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
////// SHA-512
|
||||
|
||||
CSHA512::CSHA512() : bytes(0)
|
||||
{
|
||||
sha512::Initialize(s);
|
||||
}
|
||||
|
||||
CSHA512& CSHA512::Write(const unsigned char* data, size_t len)
|
||||
{
|
||||
const unsigned char* end = data + len;
|
||||
size_t bufsize = bytes % 128;
|
||||
if (bufsize && bufsize + len >= 128) {
|
||||
// Fill the buffer, and process it.
|
||||
memcpy(buf + bufsize, data, 128 - bufsize);
|
||||
bytes += 128 - bufsize;
|
||||
data += 128 - bufsize;
|
||||
sha512::Transform(s, buf);
|
||||
bufsize = 0;
|
||||
}
|
||||
while (end >= data + 128) {
|
||||
// Process full chunks directly from the source.
|
||||
sha512::Transform(s, data);
|
||||
data += 128;
|
||||
bytes += 128;
|
||||
}
|
||||
if (end > data) {
|
||||
// Fill the buffer with what remains.
|
||||
memcpy(buf + bufsize, data, end - data);
|
||||
bytes += end - data;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void CSHA512::Finalize(unsigned char hash[OUTPUT_SIZE])
|
||||
{
|
||||
static const unsigned char pad[128] = {0x80};
|
||||
unsigned char sizedesc[16] = {0x00};
|
||||
WriteBE64(sizedesc + 8, bytes << 3);
|
||||
Write(pad, 1 + ((239 - (bytes % 128)) % 128));
|
||||
Write(sizedesc, 16);
|
||||
WriteBE64(hash, s[0]);
|
||||
WriteBE64(hash + 8, s[1]);
|
||||
WriteBE64(hash + 16, s[2]);
|
||||
WriteBE64(hash + 24, s[3]);
|
||||
WriteBE64(hash + 32, s[4]);
|
||||
WriteBE64(hash + 40, s[5]);
|
||||
WriteBE64(hash + 48, s[6]);
|
||||
WriteBE64(hash + 56, s[7]);
|
||||
}
|
||||
|
||||
CSHA512& CSHA512::Reset()
|
||||
{
|
||||
bytes = 0;
|
||||
sha512::Initialize(s);
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
// Copyright (c) 2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_CRYPTO_SHA512_H
|
||||
#define BITCOIN_CRYPTO_SHA512_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/** A hasher class for SHA-512. */
|
||||
class CSHA512
|
||||
{
|
||||
private:
|
||||
uint64_t s[8];
|
||||
unsigned char buf[128];
|
||||
size_t bytes;
|
||||
|
||||
public:
|
||||
static const size_t OUTPUT_SIZE = 64;
|
||||
|
||||
CSHA512();
|
||||
CSHA512& Write(const unsigned char* data, size_t len);
|
||||
void Finalize(unsigned char hash[OUTPUT_SIZE]);
|
||||
CSHA512& Reset();
|
||||
};
|
||||
|
||||
#endif // BITCOIN_CRYPTO_SHA512_H
|
||||
454
src/db.cpp
454
src/db.cpp
|
|
@ -1,454 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "db.h"
|
||||
|
||||
#include "addrman.h"
|
||||
#include "hash.h"
|
||||
#include "protocol.h"
|
||||
#include "util.h"
|
||||
#include "utilstrencodings.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
|
||||
unsigned int nWalletDBUpdated;
|
||||
|
||||
|
||||
//
|
||||
// CDB
|
||||
//
|
||||
|
||||
CDBEnv bitdb;
|
||||
|
||||
void CDBEnv::EnvShutdown()
|
||||
{
|
||||
if (!fDbEnvInit)
|
||||
return;
|
||||
|
||||
fDbEnvInit = false;
|
||||
int ret = dbenv.close(0);
|
||||
if (ret != 0)
|
||||
LogPrintf("CDBEnv::EnvShutdown : Error %d shutting down database environment: %s\n", ret, DbEnv::strerror(ret));
|
||||
if (!fMockDb)
|
||||
DbEnv(0).remove(path.string().c_str(), 0);
|
||||
}
|
||||
|
||||
CDBEnv::CDBEnv() : dbenv(DB_CXX_NO_EXCEPTIONS)
|
||||
{
|
||||
fDbEnvInit = false;
|
||||
fMockDb = false;
|
||||
}
|
||||
|
||||
CDBEnv::~CDBEnv()
|
||||
{
|
||||
EnvShutdown();
|
||||
}
|
||||
|
||||
void CDBEnv::Close()
|
||||
{
|
||||
EnvShutdown();
|
||||
}
|
||||
|
||||
bool CDBEnv::Open(const boost::filesystem::path& pathIn)
|
||||
{
|
||||
if (fDbEnvInit)
|
||||
return true;
|
||||
|
||||
boost::this_thread::interruption_point();
|
||||
|
||||
path = pathIn;
|
||||
filesystem::path pathLogDir = path / "database";
|
||||
TryCreateDirectory(pathLogDir);
|
||||
filesystem::path pathErrorFile = path / "db.log";
|
||||
LogPrintf("CDBEnv::Open : LogDir=%s ErrorFile=%s\n", pathLogDir.string(), pathErrorFile.string());
|
||||
|
||||
unsigned int nEnvFlags = 0;
|
||||
if (GetBoolArg("-privdb", true))
|
||||
nEnvFlags |= DB_PRIVATE;
|
||||
|
||||
dbenv.set_lg_dir(pathLogDir.string().c_str());
|
||||
dbenv.set_cachesize(0, 0x100000, 1); // 1 MiB should be enough for just the wallet
|
||||
dbenv.set_lg_bsize(0x10000);
|
||||
dbenv.set_lg_max(1048576);
|
||||
dbenv.set_lk_max_locks(40000);
|
||||
dbenv.set_lk_max_objects(40000);
|
||||
dbenv.set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug
|
||||
dbenv.set_flags(DB_AUTO_COMMIT, 1);
|
||||
dbenv.set_flags(DB_TXN_WRITE_NOSYNC, 1);
|
||||
dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1);
|
||||
int ret = dbenv.open(path.string().c_str(),
|
||||
DB_CREATE |
|
||||
DB_INIT_LOCK |
|
||||
DB_INIT_LOG |
|
||||
DB_INIT_MPOOL |
|
||||
DB_INIT_TXN |
|
||||
DB_THREAD |
|
||||
DB_RECOVER |
|
||||
nEnvFlags,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (ret != 0)
|
||||
return error("CDBEnv::Open : Error %d opening database environment: %s\n", ret, DbEnv::strerror(ret));
|
||||
|
||||
fDbEnvInit = true;
|
||||
fMockDb = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDBEnv::MakeMock()
|
||||
{
|
||||
if (fDbEnvInit)
|
||||
throw runtime_error("CDBEnv::MakeMock : Already initialized");
|
||||
|
||||
boost::this_thread::interruption_point();
|
||||
|
||||
LogPrint("db", "CDBEnv::MakeMock\n");
|
||||
|
||||
dbenv.set_cachesize(1, 0, 1);
|
||||
dbenv.set_lg_bsize(10485760 * 4);
|
||||
dbenv.set_lg_max(10485760);
|
||||
dbenv.set_lk_max_locks(10000);
|
||||
dbenv.set_lk_max_objects(10000);
|
||||
dbenv.set_flags(DB_AUTO_COMMIT, 1);
|
||||
dbenv.log_set_config(DB_LOG_IN_MEMORY, 1);
|
||||
int ret = dbenv.open(NULL,
|
||||
DB_CREATE |
|
||||
DB_INIT_LOCK |
|
||||
DB_INIT_LOG |
|
||||
DB_INIT_MPOOL |
|
||||
DB_INIT_TXN |
|
||||
DB_THREAD |
|
||||
DB_PRIVATE,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (ret > 0)
|
||||
throw runtime_error(strprintf("CDBEnv::MakeMock : Error %d opening database environment.", ret));
|
||||
|
||||
fDbEnvInit = true;
|
||||
fMockDb = true;
|
||||
}
|
||||
|
||||
CDBEnv::VerifyResult CDBEnv::Verify(std::string strFile, bool (*recoverFunc)(CDBEnv& dbenv, std::string strFile))
|
||||
{
|
||||
LOCK(cs_db);
|
||||
assert(mapFileUseCount.count(strFile) == 0);
|
||||
|
||||
Db db(&dbenv, 0);
|
||||
int result = db.verify(strFile.c_str(), NULL, NULL, 0);
|
||||
if (result == 0)
|
||||
return VERIFY_OK;
|
||||
else if (recoverFunc == NULL)
|
||||
return RECOVER_FAIL;
|
||||
|
||||
// Try to recover:
|
||||
bool fRecovered = (*recoverFunc)(*this, strFile);
|
||||
return (fRecovered ? RECOVER_OK : RECOVER_FAIL);
|
||||
}
|
||||
|
||||
bool CDBEnv::Salvage(std::string strFile, bool fAggressive, std::vector<CDBEnv::KeyValPair>& vResult)
|
||||
{
|
||||
LOCK(cs_db);
|
||||
assert(mapFileUseCount.count(strFile) == 0);
|
||||
|
||||
u_int32_t flags = DB_SALVAGE;
|
||||
if (fAggressive)
|
||||
flags |= DB_AGGRESSIVE;
|
||||
|
||||
stringstream strDump;
|
||||
|
||||
Db db(&dbenv, 0);
|
||||
int result = db.verify(strFile.c_str(), NULL, &strDump, flags);
|
||||
if (result == DB_VERIFY_BAD) {
|
||||
LogPrintf("CDBEnv::Salvage : Database salvage found errors, all data may not be recoverable.\n");
|
||||
if (!fAggressive) {
|
||||
LogPrintf("CDBEnv::Salvage : Rerun with aggressive mode to ignore errors and continue.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (result != 0 && result != DB_VERIFY_BAD) {
|
||||
LogPrintf("CDBEnv::Salvage : Database salvage failed with result %d.\n", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Format of bdb dump is ascii lines:
|
||||
// header lines...
|
||||
// HEADER=END
|
||||
// hexadecimal key
|
||||
// hexadecimal value
|
||||
// ... repeated
|
||||
// DATA=END
|
||||
|
||||
string strLine;
|
||||
while (!strDump.eof() && strLine != "HEADER=END")
|
||||
getline(strDump, strLine); // Skip past header
|
||||
|
||||
std::string keyHex, valueHex;
|
||||
while (!strDump.eof() && keyHex != "DATA=END") {
|
||||
getline(strDump, keyHex);
|
||||
if (keyHex != "DATA_END") {
|
||||
getline(strDump, valueHex);
|
||||
vResult.push_back(make_pair(ParseHex(keyHex), ParseHex(valueHex)));
|
||||
}
|
||||
}
|
||||
|
||||
return (result == 0);
|
||||
}
|
||||
|
||||
|
||||
void CDBEnv::CheckpointLSN(const std::string& strFile)
|
||||
{
|
||||
dbenv.txn_checkpoint(0, 0, 0);
|
||||
if (fMockDb)
|
||||
return;
|
||||
dbenv.lsn_reset(strFile.c_str(), 0);
|
||||
}
|
||||
|
||||
|
||||
CDB::CDB(const std::string& strFilename, const char* pszMode) : pdb(NULL), activeTxn(NULL)
|
||||
{
|
||||
int ret;
|
||||
fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
|
||||
if (strFilename.empty())
|
||||
return;
|
||||
|
||||
bool fCreate = strchr(pszMode, 'c') != NULL;
|
||||
unsigned int nFlags = DB_THREAD;
|
||||
if (fCreate)
|
||||
nFlags |= DB_CREATE;
|
||||
|
||||
{
|
||||
LOCK(bitdb.cs_db);
|
||||
if (!bitdb.Open(GetDataDir()))
|
||||
throw runtime_error("CDB : Failed to open database environment.");
|
||||
|
||||
strFile = strFilename;
|
||||
++bitdb.mapFileUseCount[strFile];
|
||||
pdb = bitdb.mapDb[strFile];
|
||||
if (pdb == NULL) {
|
||||
pdb = new Db(&bitdb.dbenv, 0);
|
||||
|
||||
bool fMockDb = bitdb.IsMock();
|
||||
if (fMockDb) {
|
||||
DbMpoolFile* mpf = pdb->get_mpf();
|
||||
ret = mpf->set_flags(DB_MPOOL_NOFILE, 1);
|
||||
if (ret != 0)
|
||||
throw runtime_error(strprintf("CDB : Failed to configure for no temp file backing for database %s", strFile));
|
||||
}
|
||||
|
||||
ret = pdb->open(NULL, // Txn pointer
|
||||
fMockDb ? NULL : strFile.c_str(), // Filename
|
||||
fMockDb ? strFile.c_str() : "main", // Logical db name
|
||||
DB_BTREE, // Database type
|
||||
nFlags, // Flags
|
||||
0);
|
||||
|
||||
if (ret != 0) {
|
||||
delete pdb;
|
||||
pdb = NULL;
|
||||
--bitdb.mapFileUseCount[strFile];
|
||||
strFile = "";
|
||||
throw runtime_error(strprintf("CDB : Error %d, can't open database %s", ret, strFile));
|
||||
}
|
||||
|
||||
if (fCreate && !Exists(string("version"))) {
|
||||
bool fTmp = fReadOnly;
|
||||
fReadOnly = false;
|
||||
WriteVersion(CLIENT_VERSION);
|
||||
fReadOnly = fTmp;
|
||||
}
|
||||
|
||||
bitdb.mapDb[strFile] = pdb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CDB::Flush()
|
||||
{
|
||||
if (activeTxn)
|
||||
return;
|
||||
|
||||
// Flush database activity from memory pool to disk log
|
||||
unsigned int nMinutes = 0;
|
||||
if (fReadOnly)
|
||||
nMinutes = 1;
|
||||
|
||||
bitdb.dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100) * 1024 : 0, nMinutes, 0);
|
||||
}
|
||||
|
||||
void CDB::Close()
|
||||
{
|
||||
if (!pdb)
|
||||
return;
|
||||
if (activeTxn)
|
||||
activeTxn->abort();
|
||||
activeTxn = NULL;
|
||||
pdb = NULL;
|
||||
|
||||
Flush();
|
||||
|
||||
{
|
||||
LOCK(bitdb.cs_db);
|
||||
--bitdb.mapFileUseCount[strFile];
|
||||
}
|
||||
}
|
||||
|
||||
void CDBEnv::CloseDb(const string& strFile)
|
||||
{
|
||||
{
|
||||
LOCK(cs_db);
|
||||
if (mapDb[strFile] != NULL) {
|
||||
// Close the database handle
|
||||
Db* pdb = mapDb[strFile];
|
||||
pdb->close(0);
|
||||
delete pdb;
|
||||
mapDb[strFile] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CDBEnv::RemoveDb(const string& strFile)
|
||||
{
|
||||
this->CloseDb(strFile);
|
||||
|
||||
LOCK(cs_db);
|
||||
int rc = dbenv.dbremove(NULL, strFile.c_str(), NULL, DB_AUTO_COMMIT);
|
||||
return (rc == 0);
|
||||
}
|
||||
|
||||
bool CDB::Rewrite(const string& strFile, const char* pszSkip)
|
||||
{
|
||||
while (true) {
|
||||
{
|
||||
LOCK(bitdb.cs_db);
|
||||
if (!bitdb.mapFileUseCount.count(strFile) || bitdb.mapFileUseCount[strFile] == 0) {
|
||||
// Flush log data to the dat file
|
||||
bitdb.CloseDb(strFile);
|
||||
bitdb.CheckpointLSN(strFile);
|
||||
bitdb.mapFileUseCount.erase(strFile);
|
||||
|
||||
bool fSuccess = true;
|
||||
LogPrintf("CDB::Rewrite : Rewriting %s...\n", strFile);
|
||||
string strFileRes = strFile + ".rewrite";
|
||||
{ // surround usage of db with extra {}
|
||||
CDB db(strFile.c_str(), "r");
|
||||
Db* pdbCopy = new Db(&bitdb.dbenv, 0);
|
||||
|
||||
int ret = pdbCopy->open(NULL, // Txn pointer
|
||||
strFileRes.c_str(), // Filename
|
||||
"main", // Logical db name
|
||||
DB_BTREE, // Database type
|
||||
DB_CREATE, // Flags
|
||||
0);
|
||||
if (ret > 0) {
|
||||
LogPrintf("CDB::Rewrite : Can't create database file %s\n", strFileRes);
|
||||
fSuccess = false;
|
||||
}
|
||||
|
||||
Dbc* pcursor = db.GetCursor();
|
||||
if (pcursor)
|
||||
while (fSuccess) {
|
||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
||||
int ret = db.ReadAtCursor(pcursor, ssKey, ssValue, DB_NEXT);
|
||||
if (ret == DB_NOTFOUND) {
|
||||
pcursor->close();
|
||||
break;
|
||||
} else if (ret != 0) {
|
||||
pcursor->close();
|
||||
fSuccess = false;
|
||||
break;
|
||||
}
|
||||
if (pszSkip &&
|
||||
strncmp(&ssKey[0], pszSkip, std::min(ssKey.size(), strlen(pszSkip))) == 0)
|
||||
continue;
|
||||
if (strncmp(&ssKey[0], "\x07version", 8) == 0) {
|
||||
// Update version:
|
||||
ssValue.clear();
|
||||
ssValue << CLIENT_VERSION;
|
||||
}
|
||||
Dbt datKey(&ssKey[0], ssKey.size());
|
||||
Dbt datValue(&ssValue[0], ssValue.size());
|
||||
int ret2 = pdbCopy->put(NULL, &datKey, &datValue, DB_NOOVERWRITE);
|
||||
if (ret2 > 0)
|
||||
fSuccess = false;
|
||||
}
|
||||
if (fSuccess) {
|
||||
db.Close();
|
||||
bitdb.CloseDb(strFile);
|
||||
if (pdbCopy->close(0))
|
||||
fSuccess = false;
|
||||
delete pdbCopy;
|
||||
}
|
||||
}
|
||||
if (fSuccess) {
|
||||
Db dbA(&bitdb.dbenv, 0);
|
||||
if (dbA.remove(strFile.c_str(), NULL, 0))
|
||||
fSuccess = false;
|
||||
Db dbB(&bitdb.dbenv, 0);
|
||||
if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0))
|
||||
fSuccess = false;
|
||||
}
|
||||
if (!fSuccess)
|
||||
LogPrintf("CDB::Rewrite : Failed to rewrite database file %s\n", strFileRes);
|
||||
return fSuccess;
|
||||
}
|
||||
}
|
||||
MilliSleep(100);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void CDBEnv::Flush(bool fShutdown)
|
||||
{
|
||||
int64_t nStart = GetTimeMillis();
|
||||
// Flush log data to the actual data file on all files that are not in use
|
||||
LogPrint("db", "CDBEnv::Flush : Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started");
|
||||
if (!fDbEnvInit)
|
||||
return;
|
||||
{
|
||||
LOCK(cs_db);
|
||||
map<string, int>::iterator mi = mapFileUseCount.begin();
|
||||
while (mi != mapFileUseCount.end()) {
|
||||
string strFile = (*mi).first;
|
||||
int nRefCount = (*mi).second;
|
||||
LogPrint("db", "CDBEnv::Flush : Flushing %s (refcount = %d)...\n", strFile, nRefCount);
|
||||
if (nRefCount == 0) {
|
||||
// Move log data to the dat file
|
||||
CloseDb(strFile);
|
||||
LogPrint("db", "CDBEnv::Flush : %s checkpoint\n", strFile);
|
||||
dbenv.txn_checkpoint(0, 0, 0);
|
||||
LogPrint("db", "CDBEnv::Flush : %s detach\n", strFile);
|
||||
if (!fMockDb)
|
||||
dbenv.lsn_reset(strFile.c_str(), 0);
|
||||
LogPrint("db", "CDBEnv::Flush : %s closed\n", strFile);
|
||||
mapFileUseCount.erase(mi++);
|
||||
} else
|
||||
mi++;
|
||||
}
|
||||
LogPrint("db", "CDBEnv::Flush : Flush(%s)%s took %15dms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started", GetTimeMillis() - nStart);
|
||||
if (fShutdown) {
|
||||
char** listp;
|
||||
if (mapFileUseCount.empty()) {
|
||||
dbenv.log_archive(&listp, DB_ARCH_REMOVE);
|
||||
Close();
|
||||
if (!fMockDb)
|
||||
boost::filesystem::remove_all(path / "database");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
312
src/db.h
312
src/db.h
|
|
@ -1,312 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_DB_H
|
||||
#define BITCOIN_DB_H
|
||||
|
||||
#include "clientversion.h"
|
||||
#include "serialize.h"
|
||||
#include "streams.h"
|
||||
#include "sync.h"
|
||||
#include "version.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#include <db_cxx.h>
|
||||
|
||||
class CDiskBlockIndex;
|
||||
class COutPoint;
|
||||
|
||||
struct CBlockLocator;
|
||||
|
||||
extern unsigned int nWalletDBUpdated;
|
||||
|
||||
void ThreadFlushWalletDB(const std::string& strWalletFile);
|
||||
|
||||
|
||||
class CDBEnv
|
||||
{
|
||||
private:
|
||||
bool fDbEnvInit;
|
||||
bool fMockDb;
|
||||
boost::filesystem::path path;
|
||||
|
||||
void EnvShutdown();
|
||||
|
||||
public:
|
||||
mutable CCriticalSection cs_db;
|
||||
DbEnv dbenv;
|
||||
std::map<std::string, int> mapFileUseCount;
|
||||
std::map<std::string, Db*> mapDb;
|
||||
|
||||
CDBEnv();
|
||||
~CDBEnv();
|
||||
void MakeMock();
|
||||
bool IsMock() { return fMockDb; }
|
||||
|
||||
/**
|
||||
* Verify that database file strFile is OK. If it is not,
|
||||
* call the callback to try to recover.
|
||||
* This must be called BEFORE strFile is opened.
|
||||
* Returns true if strFile is OK.
|
||||
*/
|
||||
enum VerifyResult { VERIFY_OK,
|
||||
RECOVER_OK,
|
||||
RECOVER_FAIL };
|
||||
VerifyResult Verify(std::string strFile, bool (*recoverFunc)(CDBEnv& dbenv, std::string strFile));
|
||||
/**
|
||||
* Salvage data from a file that Verify says is bad.
|
||||
* fAggressive sets the DB_AGGRESSIVE flag (see berkeley DB->verify() method documentation).
|
||||
* Appends binary key/value pairs to vResult, returns true if successful.
|
||||
* NOTE: reads the entire database into memory, so cannot be used
|
||||
* for huge databases.
|
||||
*/
|
||||
typedef std::pair<std::vector<unsigned char>, std::vector<unsigned char> > KeyValPair;
|
||||
bool Salvage(std::string strFile, bool fAggressive, std::vector<KeyValPair>& vResult);
|
||||
|
||||
bool Open(const boost::filesystem::path& path);
|
||||
void Close();
|
||||
void Flush(bool fShutdown);
|
||||
void CheckpointLSN(const std::string& strFile);
|
||||
|
||||
void CloseDb(const std::string& strFile);
|
||||
bool RemoveDb(const std::string& strFile);
|
||||
|
||||
DbTxn* TxnBegin(int flags = DB_TXN_WRITE_NOSYNC)
|
||||
{
|
||||
DbTxn* ptxn = NULL;
|
||||
int ret = dbenv.txn_begin(NULL, &ptxn, flags);
|
||||
if (!ptxn || ret != 0)
|
||||
return NULL;
|
||||
return ptxn;
|
||||
}
|
||||
};
|
||||
|
||||
extern CDBEnv bitdb;
|
||||
|
||||
|
||||
/** RAII class that provides access to a Berkeley database */
|
||||
class CDB
|
||||
{
|
||||
protected:
|
||||
Db* pdb;
|
||||
std::string strFile;
|
||||
DbTxn* activeTxn;
|
||||
bool fReadOnly;
|
||||
|
||||
explicit CDB(const std::string& strFilename, const char* pszMode = "r+");
|
||||
~CDB() { Close(); }
|
||||
|
||||
public:
|
||||
void Flush();
|
||||
void Close();
|
||||
|
||||
private:
|
||||
CDB(const CDB&);
|
||||
void operator=(const CDB&);
|
||||
|
||||
protected:
|
||||
template <typename K, typename T>
|
||||
bool Read(const K& key, T& value)
|
||||
{
|
||||
if (!pdb)
|
||||
return false;
|
||||
|
||||
// Key
|
||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||
ssKey.reserve(1000);
|
||||
ssKey << key;
|
||||
Dbt datKey(&ssKey[0], ssKey.size());
|
||||
|
||||
// Read
|
||||
Dbt datValue;
|
||||
datValue.set_flags(DB_DBT_MALLOC);
|
||||
int ret = pdb->get(activeTxn, &datKey, &datValue, 0);
|
||||
memset(datKey.get_data(), 0, datKey.get_size());
|
||||
if (datValue.get_data() == NULL)
|
||||
return false;
|
||||
|
||||
// Unserialize value
|
||||
try {
|
||||
CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION);
|
||||
ssValue >> value;
|
||||
} catch (const std::exception&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clear and free memory
|
||||
memset(datValue.get_data(), 0, datValue.get_size());
|
||||
free(datValue.get_data());
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
template <typename K, typename T>
|
||||
bool Write(const K& key, const T& value, bool fOverwrite = true)
|
||||
{
|
||||
if (!pdb)
|
||||
return false;
|
||||
if (fReadOnly)
|
||||
assert(!"Write called on database in read-only mode");
|
||||
|
||||
// Key
|
||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||
ssKey.reserve(1000);
|
||||
ssKey << key;
|
||||
Dbt datKey(&ssKey[0], ssKey.size());
|
||||
|
||||
// Value
|
||||
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
||||
ssValue.reserve(10000);
|
||||
ssValue << value;
|
||||
Dbt datValue(&ssValue[0], ssValue.size());
|
||||
|
||||
// Write
|
||||
int ret = pdb->put(activeTxn, &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
|
||||
|
||||
// Clear memory in case it was a private key
|
||||
memset(datKey.get_data(), 0, datKey.get_size());
|
||||
memset(datValue.get_data(), 0, datValue.get_size());
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
bool Erase(const K& key)
|
||||
{
|
||||
if (!pdb)
|
||||
return false;
|
||||
if (fReadOnly)
|
||||
assert(!"Erase called on database in read-only mode");
|
||||
|
||||
// Key
|
||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||
ssKey.reserve(1000);
|
||||
ssKey << key;
|
||||
Dbt datKey(&ssKey[0], ssKey.size());
|
||||
|
||||
// Erase
|
||||
int ret = pdb->del(activeTxn, &datKey, 0);
|
||||
|
||||
// Clear memory
|
||||
memset(datKey.get_data(), 0, datKey.get_size());
|
||||
return (ret == 0 || ret == DB_NOTFOUND);
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
bool Exists(const K& key)
|
||||
{
|
||||
if (!pdb)
|
||||
return false;
|
||||
|
||||
// Key
|
||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||
ssKey.reserve(1000);
|
||||
ssKey << key;
|
||||
Dbt datKey(&ssKey[0], ssKey.size());
|
||||
|
||||
// Exists
|
||||
int ret = pdb->exists(activeTxn, &datKey, 0);
|
||||
|
||||
// Clear memory
|
||||
memset(datKey.get_data(), 0, datKey.get_size());
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
Dbc* GetCursor()
|
||||
{
|
||||
if (!pdb)
|
||||
return NULL;
|
||||
Dbc* pcursor = NULL;
|
||||
int ret = pdb->cursor(NULL, &pcursor, 0);
|
||||
if (ret != 0)
|
||||
return NULL;
|
||||
return pcursor;
|
||||
}
|
||||
|
||||
int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags = DB_NEXT)
|
||||
{
|
||||
// Read at cursor
|
||||
Dbt datKey;
|
||||
if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) {
|
||||
datKey.set_data(&ssKey[0]);
|
||||
datKey.set_size(ssKey.size());
|
||||
}
|
||||
Dbt datValue;
|
||||
if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) {
|
||||
datValue.set_data(&ssValue[0]);
|
||||
datValue.set_size(ssValue.size());
|
||||
}
|
||||
datKey.set_flags(DB_DBT_MALLOC);
|
||||
datValue.set_flags(DB_DBT_MALLOC);
|
||||
int ret = pcursor->get(&datKey, &datValue, fFlags);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
else if (datKey.get_data() == NULL || datValue.get_data() == NULL)
|
||||
return 99999;
|
||||
|
||||
// Convert to streams
|
||||
ssKey.SetType(SER_DISK);
|
||||
ssKey.clear();
|
||||
ssKey.write((char*)datKey.get_data(), datKey.get_size());
|
||||
ssValue.SetType(SER_DISK);
|
||||
ssValue.clear();
|
||||
ssValue.write((char*)datValue.get_data(), datValue.get_size());
|
||||
|
||||
// Clear and free memory
|
||||
memset(datKey.get_data(), 0, datKey.get_size());
|
||||
memset(datValue.get_data(), 0, datValue.get_size());
|
||||
free(datKey.get_data());
|
||||
free(datValue.get_data());
|
||||
return 0;
|
||||
}
|
||||
|
||||
public:
|
||||
bool TxnBegin()
|
||||
{
|
||||
if (!pdb || activeTxn)
|
||||
return false;
|
||||
DbTxn* ptxn = bitdb.TxnBegin();
|
||||
if (!ptxn)
|
||||
return false;
|
||||
activeTxn = ptxn;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TxnCommit()
|
||||
{
|
||||
if (!pdb || !activeTxn)
|
||||
return false;
|
||||
int ret = activeTxn->commit(0);
|
||||
activeTxn = NULL;
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
bool TxnAbort()
|
||||
{
|
||||
if (!pdb || !activeTxn)
|
||||
return false;
|
||||
int ret = activeTxn->abort();
|
||||
activeTxn = NULL;
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
bool ReadVersion(int& nVersion)
|
||||
{
|
||||
nVersion = 0;
|
||||
return Read(std::string("version"), nVersion);
|
||||
}
|
||||
|
||||
bool WriteVersion(int nVersion)
|
||||
{
|
||||
return Write(std::string("version"), nVersion);
|
||||
}
|
||||
|
||||
bool static Rewrite(const std::string& strFile, const char* pszSkip = NULL);
|
||||
};
|
||||
|
||||
#endif // BITCOIN_DB_H
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "eccryptoverify.h"
|
||||
|
||||
namespace {
|
||||
|
||||
int CompareBigEndian(const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) {
|
||||
while (c1len > c2len) {
|
||||
if (*c1)
|
||||
return 1;
|
||||
c1++;
|
||||
c1len--;
|
||||
}
|
||||
while (c2len > c1len) {
|
||||
if (*c2)
|
||||
return -1;
|
||||
c2++;
|
||||
c2len--;
|
||||
}
|
||||
while (c1len > 0) {
|
||||
if (*c1 > *c2)
|
||||
return 1;
|
||||
if (*c2 > *c1)
|
||||
return -1;
|
||||
c1++;
|
||||
c2++;
|
||||
c1len--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Order of secp256k1's generator minus 1. */
|
||||
const unsigned char vchMaxModOrder[32] = {
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
|
||||
0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
|
||||
0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40
|
||||
};
|
||||
|
||||
/** Half of the order of secp256k1's generator minus 1. */
|
||||
const unsigned char vchMaxModHalfOrder[32] = {
|
||||
0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0x5D,0x57,0x6E,0x73,0x57,0xA4,0x50,0x1D,
|
||||
0xDF,0xE9,0x2F,0x46,0x68,0x1B,0x20,0xA0
|
||||
};
|
||||
|
||||
const unsigned char vchZero[1] = {0};
|
||||
} // anon namespace
|
||||
|
||||
namespace eccrypto {
|
||||
|
||||
bool Check(const unsigned char *vch) {
|
||||
return vch &&
|
||||
CompareBigEndian(vch, 32, vchZero, 0) > 0 &&
|
||||
CompareBigEndian(vch, 32, vchMaxModOrder, 32) <= 0;
|
||||
}
|
||||
|
||||
bool CheckSignatureElement(const unsigned char *vch, int len, bool half) {
|
||||
return vch &&
|
||||
CompareBigEndian(vch, len, vchZero, 0) > 0 &&
|
||||
CompareBigEndian(vch, len, half ? vchMaxModHalfOrder : vchMaxModOrder, 32) <= 0;
|
||||
}
|
||||
|
||||
} // namespace eccrypto
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_ECCRYPTOVERIFY_H
|
||||
#define BITCOIN_ECCRYPTOVERIFY_H
|
||||
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
|
||||
class uint256;
|
||||
|
||||
namespace eccrypto {
|
||||
|
||||
bool Check(const unsigned char *vch);
|
||||
bool CheckSignatureElement(const unsigned char *vch, int len, bool half);
|
||||
|
||||
} // eccrypto namespace
|
||||
|
||||
#endif // BITCOIN_ECCRYPTOVERIFY_H
|
||||
|
|
@ -11,14 +11,10 @@
|
|||
#include "group.h"
|
||||
#include "ecmult.h"
|
||||
|
||||
typedef struct {
|
||||
secp256k1_scalar_t r, s;
|
||||
} secp256k1_ecdsa_sig_t;
|
||||
|
||||
static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size);
|
||||
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a);
|
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context_t *ctx, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message);
|
||||
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid);
|
||||
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid);
|
||||
static int secp256k1_ecdsa_sig_parse(secp256k1_scalar_t *r, secp256k1_scalar_t *s, const unsigned char *sig, int size);
|
||||
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_scalar_t *r, const secp256k1_scalar_t *s);
|
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context_t *ctx, const secp256k1_scalar_t* r, const secp256k1_scalar_t* s, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message);
|
||||
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, secp256k1_scalar_t* r, secp256k1_scalar_t* s, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid);
|
||||
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, const secp256k1_scalar_t* r, const secp256k1_scalar_t* s, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid);
|
||||
|
||||
#endif
|
||||
|
|
@ -46,7 +46,7 @@ static const secp256k1_fe_t secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_C
|
|||
0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL
|
||||
);
|
||||
|
||||
static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size) {
|
||||
static int secp256k1_ecdsa_sig_parse(secp256k1_scalar_t *rr, secp256k1_scalar_t *rs, const unsigned char *sig, int size) {
|
||||
unsigned char ra[32] = {0}, sa[32] = {0};
|
||||
const unsigned char *rp;
|
||||
const unsigned char *sp;
|
||||
|
|
@ -98,26 +98,27 @@ static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned ch
|
|||
memcpy(ra + 32 - lenr, rp, lenr);
|
||||
memcpy(sa + 32 - lens, sp, lens);
|
||||
overflow = 0;
|
||||
secp256k1_scalar_set_b32(&r->r, ra, &overflow);
|
||||
secp256k1_scalar_set_b32(rr, ra, &overflow);
|
||||
if (overflow) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_scalar_set_b32(&r->s, sa, &overflow);
|
||||
secp256k1_scalar_set_b32(rs, sa, &overflow);
|
||||
if (overflow) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a) {
|
||||
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_scalar_t* ar, const secp256k1_scalar_t* as) {
|
||||
unsigned char r[33] = {0}, s[33] = {0};
|
||||
unsigned char *rp = r, *sp = s;
|
||||
int lenR = 33, lenS = 33;
|
||||
secp256k1_scalar_get_b32(&r[1], &a->r);
|
||||
secp256k1_scalar_get_b32(&s[1], &a->s);
|
||||
secp256k1_scalar_get_b32(&r[1], ar);
|
||||
secp256k1_scalar_get_b32(&s[1], as);
|
||||
while (lenR > 1 && rp[0] == 0 && rp[1] < 0x80) { lenR--; rp++; }
|
||||
while (lenS > 1 && sp[0] == 0 && sp[1] < 0x80) { lenS--; sp++; }
|
||||
if (*size < 6+lenS+lenR) {
|
||||
*size = 6 + lenS + lenR;
|
||||
return 0;
|
||||
}
|
||||
*size = 6 + lenS + lenR;
|
||||
|
|
@ -132,26 +133,26 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const se
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context_t *ctx, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
|
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context_t *ctx, const secp256k1_scalar_t *sigr, const secp256k1_scalar_t *sigs, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
|
||||
unsigned char c[32];
|
||||
secp256k1_scalar_t sn, u1, u2;
|
||||
secp256k1_fe_t xr;
|
||||
secp256k1_gej_t pubkeyj;
|
||||
secp256k1_gej_t pr;
|
||||
|
||||
if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s)) {
|
||||
if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256k1_scalar_inverse_var(&sn, &sig->s);
|
||||
secp256k1_scalar_inverse_var(&sn, sigs);
|
||||
secp256k1_scalar_mul(&u1, &sn, message);
|
||||
secp256k1_scalar_mul(&u2, &sn, &sig->r);
|
||||
secp256k1_scalar_mul(&u2, &sn, sigr);
|
||||
secp256k1_gej_set_ge(&pubkeyj, pubkey);
|
||||
secp256k1_ecmult(ctx, &pr, &pubkeyj, &u2, &u1);
|
||||
if (secp256k1_gej_is_infinity(&pr)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_scalar_get_b32(c, &sig->r);
|
||||
secp256k1_scalar_get_b32(c, sigr);
|
||||
secp256k1_fe_set_b32(&xr, c);
|
||||
|
||||
/** We now have the recomputed R point in pr, and its claimed x coordinate (modulo n)
|
||||
|
|
@ -186,7 +187,7 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context_t *ctx, con
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid) {
|
||||
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, const secp256k1_scalar_t *sigr, const secp256k1_scalar_t* sigs, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid) {
|
||||
unsigned char brx[32];
|
||||
secp256k1_fe_t fx;
|
||||
secp256k1_ge_t x;
|
||||
|
|
@ -194,11 +195,11 @@ static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, co
|
|||
secp256k1_scalar_t rn, u1, u2;
|
||||
secp256k1_gej_t qj;
|
||||
|
||||
if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s)) {
|
||||
if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256k1_scalar_get_b32(brx, &sig->r);
|
||||
secp256k1_scalar_get_b32(brx, sigr);
|
||||
VERIFY_CHECK(secp256k1_fe_set_b32(&fx, brx)); /* brx comes from a scalar, so is less than the order; certainly less than p */
|
||||
if (recid & 2) {
|
||||
if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_const_p_minus_order) >= 0) {
|
||||
|
|
@ -210,16 +211,16 @@ static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, co
|
|||
return 0;
|
||||
}
|
||||
secp256k1_gej_set_ge(&xj, &x);
|
||||
secp256k1_scalar_inverse_var(&rn, &sig->r);
|
||||
secp256k1_scalar_inverse_var(&rn, sigr);
|
||||
secp256k1_scalar_mul(&u1, &rn, message);
|
||||
secp256k1_scalar_negate(&u1, &u1);
|
||||
secp256k1_scalar_mul(&u2, &rn, &sig->s);
|
||||
secp256k1_scalar_mul(&u2, &rn, sigs);
|
||||
secp256k1_ecmult(ctx, &qj, &xj, &u2, &u1);
|
||||
secp256k1_ge_set_gej_var(pubkey, &qj);
|
||||
return !secp256k1_gej_is_infinity(&qj);
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid) {
|
||||
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, secp256k1_scalar_t *sigr, secp256k1_scalar_t *sigs, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid) {
|
||||
unsigned char b[32];
|
||||
secp256k1_gej_t rp;
|
||||
secp256k1_ge_t r;
|
||||
|
|
@ -231,8 +232,8 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, s
|
|||
secp256k1_fe_normalize(&r.x);
|
||||
secp256k1_fe_normalize(&r.y);
|
||||
secp256k1_fe_get_b32(b, &r.x);
|
||||
secp256k1_scalar_set_b32(&sig->r, b, &overflow);
|
||||
if (secp256k1_scalar_is_zero(&sig->r)) {
|
||||
secp256k1_scalar_set_b32(sigr, b, &overflow);
|
||||
if (secp256k1_scalar_is_zero(sigr)) {
|
||||
/* P.x = order is on the curve, so technically sig->r could end up zero, which would be an invalid signature. */
|
||||
secp256k1_gej_clear(&rp);
|
||||
secp256k1_ge_clear(&r);
|
||||
|
|
@ -241,18 +242,18 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, s
|
|||
if (recid) {
|
||||
*recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0);
|
||||
}
|
||||
secp256k1_scalar_mul(&n, &sig->r, seckey);
|
||||
secp256k1_scalar_mul(&n, sigr, seckey);
|
||||
secp256k1_scalar_add(&n, &n, message);
|
||||
secp256k1_scalar_inverse(&sig->s, nonce);
|
||||
secp256k1_scalar_mul(&sig->s, &sig->s, &n);
|
||||
secp256k1_scalar_inverse(sigs, nonce);
|
||||
secp256k1_scalar_mul(sigs, sigs, &n);
|
||||
secp256k1_scalar_clear(&n);
|
||||
secp256k1_gej_clear(&rp);
|
||||
secp256k1_ge_clear(&r);
|
||||
if (secp256k1_scalar_is_zero(&sig->s)) {
|
||||
if (secp256k1_scalar_is_zero(sigs)) {
|
||||
return 0;
|
||||
}
|
||||
if (secp256k1_scalar_is_high(&sig->s)) {
|
||||
secp256k1_scalar_negate(&sig->s, &sig->s);
|
||||
if (secp256k1_scalar_is_high(sigs)) {
|
||||
secp256k1_scalar_negate(sigs, sigs);
|
||||
if (recid) {
|
||||
*recid ^= 1;
|
||||
}
|
||||
|
|
@ -19,9 +19,9 @@ typedef struct {
|
|||
} secp256k1_ecmult_context_t;
|
||||
|
||||
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context_t *ctx);
|
||||
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context_t *ctx);
|
||||
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context_t *ctx, const callback_t *cb);
|
||||
static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context_t *dst,
|
||||
const secp256k1_ecmult_context_t *src);
|
||||
const secp256k1_ecmult_context_t *src, const callback_t *cb);
|
||||
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context_t *ctx);
|
||||
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context_t *ctx);
|
||||
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2015 Pieter Wuille, Andrew Poelstra *
|
||||
* Copyright (c) 2015 Andrew Poelstra *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_ECDH_
|
||||
#define _SECP256K1_ECDH_
|
||||
#ifndef _SECP256K1_ECMULT_CONST_
|
||||
#define _SECP256K1_ECMULT_CONST_
|
||||
|
||||
#include "scalar.h"
|
||||
#include "group.h"
|
||||
|
||||
static void secp256k1_ecdh_point_multiply(secp256k1_gej_t *r, const secp256k1_ge_t *a, const secp256k1_scalar_t *q);
|
||||
static void secp256k1_ecmult_const(secp256k1_gej_t *r, const secp256k1_ge_t *a, const secp256k1_scalar_t *q);
|
||||
|
||||
#endif
|
||||
258
src/ecmult_const_impl.h
Normal file
258
src/ecmult_const_impl.h
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2015 Pieter Wuille, Andrew Poelstra *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_ECMULT_CONST_IMPL_
|
||||
#define _SECP256K1_ECMULT_CONST_IMPL_
|
||||
|
||||
#include "scalar.h"
|
||||
#include "group.h"
|
||||
#include "ecmult_const.h"
|
||||
#include "ecmult_impl.h"
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
#define WNAF_BITS 128
|
||||
#else
|
||||
#define WNAF_BITS 256
|
||||
#endif
|
||||
#define WNAF_SIZE(w) ((WNAF_BITS + (w) - 1) / (w))
|
||||
|
||||
/* This is like `ECMULT_TABLE_GET_GE` but is constant time */
|
||||
#define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \
|
||||
int m; \
|
||||
int abs_n = (n) * (((n) > 0) * 2 - 1); \
|
||||
int idx_n = abs_n / 2; \
|
||||
secp256k1_fe_t neg_y; \
|
||||
VERIFY_CHECK(((n) & 1) == 1); \
|
||||
VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
|
||||
VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
|
||||
VERIFY_SETUP(secp256k1_fe_clear(&(r)->x)); \
|
||||
VERIFY_SETUP(secp256k1_fe_clear(&(r)->y)); \
|
||||
for (m = 0; m < ECMULT_TABLE_SIZE(w); m++) { \
|
||||
/* This loop is used to avoid secret data in array indices. See
|
||||
* the comment in ecmult_gen_impl.h for rationale. */ \
|
||||
secp256k1_fe_cmov(&(r)->x, &(pre)[m].x, m == idx_n); \
|
||||
secp256k1_fe_cmov(&(r)->y, &(pre)[m].y, m == idx_n); \
|
||||
} \
|
||||
(r)->infinity = 0; \
|
||||
secp256k1_fe_negate(&neg_y, &(r)->y, 1); \
|
||||
secp256k1_fe_cmov(&(r)->y, &neg_y, (n) != abs_n); \
|
||||
} while(0)
|
||||
|
||||
|
||||
/** Convert a number to WNAF notation. The number becomes represented by sum(2^{wi} * wnaf[i], i=0..return_val)
|
||||
* with the following guarantees:
|
||||
* - each wnaf[i] an odd integer between -(1 << w) and (1 << w)
|
||||
* - each wnaf[i] is nonzero
|
||||
* - the number of words set is returned; this is always (WNAF_BITS + w - 1) / w
|
||||
*
|
||||
* Adapted from `The Width-w NAF Method Provides Small Memory and Fast Elliptic Scalar
|
||||
* Multiplications Secure against Side Channel Attacks`, Okeya and Tagaki. M. Joye (Ed.)
|
||||
* CT-RSA 2003, LNCS 2612, pp. 328-443, 2003. Springer-Verlagy Berlin Heidelberg 2003
|
||||
*
|
||||
* Numbers reference steps of `Algorithm SPA-resistant Width-w NAF with Odd Scalar` on pp. 335
|
||||
*/
|
||||
static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar_t s, int w) {
|
||||
int global_sign = 1;
|
||||
int skew = 0;
|
||||
int word = 0;
|
||||
/* 1 2 3 */
|
||||
int u_last;
|
||||
int u;
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
/* If we are using the endomorphism, we cannot handle even numbers by negating
|
||||
* them, since we are working with 128-bit numbers whose negations would be 256
|
||||
* bits, eliminating the performance advantage. Instead we use a technique from
|
||||
* Section 4.2 of the Okeya/Tagaki paper, which is to add either 1 (for even)
|
||||
* or 2 (for odd) to the number we are encoding, then compensating after the
|
||||
* multiplication. */
|
||||
/* Negative 128-bit numbers will be negated, since otherwise they are 256-bit */
|
||||
int flip = secp256k1_scalar_is_high(&s);
|
||||
/* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */
|
||||
int bit = flip ^ (s.d[0] & 1);
|
||||
/* We check for negative one, since adding 2 to it will cause an overflow */
|
||||
secp256k1_scalar_t neg_s;
|
||||
int not_neg_one;
|
||||
secp256k1_scalar_negate(&neg_s, &s);
|
||||
not_neg_one = !secp256k1_scalar_is_one(&neg_s);
|
||||
secp256k1_scalar_cadd_bit(&s, bit, not_neg_one);
|
||||
/* If we had negative one, flip == 1, s.d[0] == 0, bit == 1, so caller expects
|
||||
* that we added two to it and flipped it. In fact for -1 these operations are
|
||||
* identical. We only flipped, but since skewing is required (in the sense that
|
||||
* the skew must be 1 or 2, never zero) and flipping is not, we need to change
|
||||
* our flags to claim that we only skewed. */
|
||||
global_sign = secp256k1_scalar_cond_negate(&s, flip);
|
||||
global_sign *= not_neg_one * 2 - 1;
|
||||
skew = 1 << bit;
|
||||
#else
|
||||
/* Otherwise, we just negate to force oddness */
|
||||
int is_even = secp256k1_scalar_is_even(&s);
|
||||
global_sign = secp256k1_scalar_cond_negate(&s, is_even);
|
||||
#endif
|
||||
|
||||
/* 4 */
|
||||
u_last = secp256k1_scalar_shr_int(&s, w);
|
||||
while (word * w < WNAF_BITS) {
|
||||
int sign;
|
||||
int even;
|
||||
|
||||
/* 4.1 4.4 */
|
||||
u = secp256k1_scalar_shr_int(&s, w);
|
||||
/* 4.2 */
|
||||
even = ((u & 1) == 0);
|
||||
sign = 2 * (u_last > 0) - 1;
|
||||
u += sign * even;
|
||||
u_last -= sign * even * (1 << w);
|
||||
|
||||
/* 4.3, adapted for global sign change */
|
||||
wnaf[word++] = u_last * global_sign;
|
||||
|
||||
u_last = u;
|
||||
}
|
||||
wnaf[word] = u * global_sign;
|
||||
|
||||
VERIFY_CHECK(secp256k1_scalar_is_zero(&s));
|
||||
VERIFY_CHECK(word == WNAF_SIZE(w));
|
||||
return skew;
|
||||
}
|
||||
|
||||
|
||||
static void secp256k1_ecmult_const(secp256k1_gej_t *r, const secp256k1_ge_t *a, const secp256k1_scalar_t *scalar) {
|
||||
secp256k1_ge_t pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
|
||||
secp256k1_ge_t tmpa;
|
||||
secp256k1_fe_t Z;
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
secp256k1_ge_t pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)];
|
||||
int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)];
|
||||
int wnaf_lam[1 + WNAF_SIZE(WINDOW_A - 1)];
|
||||
int skew_1;
|
||||
int skew_lam;
|
||||
secp256k1_scalar_t q_1, q_lam;
|
||||
#else
|
||||
int wnaf[1 + WNAF_SIZE(WINDOW_A - 1)];
|
||||
#endif
|
||||
|
||||
int i;
|
||||
secp256k1_scalar_t sc = *scalar;
|
||||
|
||||
/* build wnaf representation for q. */
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
/* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */
|
||||
secp256k1_scalar_split_lambda(&q_1, &q_lam, &sc);
|
||||
/* no need for zero correction when using endomorphism since even
|
||||
* numbers have one added to them anyway */
|
||||
skew_1 = secp256k1_wnaf_const(wnaf_1, q_1, WINDOW_A - 1);
|
||||
skew_lam = secp256k1_wnaf_const(wnaf_lam, q_lam, WINDOW_A - 1);
|
||||
#else
|
||||
int is_zero = secp256k1_scalar_is_zero(scalar);
|
||||
/* the wNAF ladder cannot handle zero, so bump this to one .. we will
|
||||
* correct the result after the fact */
|
||||
sc.d[0] += is_zero;
|
||||
VERIFY_CHECK(!secp256k1_scalar_is_zero(&sc));
|
||||
|
||||
secp256k1_wnaf_const(wnaf, sc, WINDOW_A - 1);
|
||||
#endif
|
||||
|
||||
/* Calculate odd multiples of a.
|
||||
* All multiples are brought to the same Z 'denominator', which is stored
|
||||
* in Z. Due to secp256k1' isomorphism we can do all operations pretending
|
||||
* that the Z coordinate was 1, use affine addition formulae, and correct
|
||||
* the Z coordinate of the result once at the end.
|
||||
*/
|
||||
secp256k1_gej_set_ge(r, a);
|
||||
secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, r);
|
||||
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
|
||||
secp256k1_fe_normalize_weak(&pre_a[i].y);
|
||||
}
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
|
||||
secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* first loop iteration (separated out so we can directly set r, rather
|
||||
* than having it start at infinity, get doubled several times, then have
|
||||
* its new value added to it) */
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
i = wnaf_1[WNAF_SIZE(WINDOW_A - 1)];
|
||||
VERIFY_CHECK(i != 0);
|
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A);
|
||||
secp256k1_gej_set_ge(r, &tmpa);
|
||||
|
||||
i = wnaf_lam[WNAF_SIZE(WINDOW_A - 1)];
|
||||
VERIFY_CHECK(i != 0);
|
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A);
|
||||
secp256k1_gej_add_ge(r, r, &tmpa);
|
||||
#else
|
||||
i = wnaf[WNAF_SIZE(WINDOW_A - 1)];
|
||||
VERIFY_CHECK(i != 0);
|
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A);
|
||||
secp256k1_gej_set_ge(r, &tmpa);
|
||||
#endif
|
||||
/* remaining loop iterations */
|
||||
for (i = WNAF_SIZE(WINDOW_A - 1) - 1; i >= 0; i--) {
|
||||
int n;
|
||||
int j;
|
||||
for (j = 0; j < WINDOW_A - 1; ++j) {
|
||||
secp256k1_gej_double_nonzero(r, r, NULL);
|
||||
}
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
n = wnaf_1[i];
|
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A);
|
||||
VERIFY_CHECK(n != 0);
|
||||
secp256k1_gej_add_ge(r, r, &tmpa);
|
||||
|
||||
n = wnaf_lam[i];
|
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A);
|
||||
VERIFY_CHECK(n != 0);
|
||||
secp256k1_gej_add_ge(r, r, &tmpa);
|
||||
#else
|
||||
n = wnaf[i];
|
||||
VERIFY_CHECK(n != 0);
|
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A);
|
||||
secp256k1_gej_add_ge(r, r, &tmpa);
|
||||
#endif
|
||||
}
|
||||
|
||||
secp256k1_fe_mul(&r->z, &r->z, &Z);
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
{
|
||||
/* Correct for wNAF skew */
|
||||
secp256k1_ge_t correction = *a;
|
||||
secp256k1_ge_storage_t correction_1_stor;
|
||||
secp256k1_ge_storage_t correction_lam_stor;
|
||||
secp256k1_ge_storage_t a2_stor;
|
||||
secp256k1_gej_t tmpj;
|
||||
secp256k1_gej_set_ge(&tmpj, &correction);
|
||||
secp256k1_gej_double_var(&tmpj, &tmpj, NULL);
|
||||
secp256k1_ge_set_gej(&correction, &tmpj);
|
||||
secp256k1_ge_to_storage(&correction_1_stor, a);
|
||||
secp256k1_ge_to_storage(&correction_lam_stor, a);
|
||||
secp256k1_ge_to_storage(&a2_stor, &correction);
|
||||
|
||||
/* For odd numbers this is 2a (so replace it), for even ones a (so no-op) */
|
||||
secp256k1_ge_storage_cmov(&correction_1_stor, &a2_stor, skew_1 == 2);
|
||||
secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2);
|
||||
|
||||
/* Apply the correction */
|
||||
secp256k1_ge_from_storage(&correction, &correction_1_stor);
|
||||
secp256k1_ge_neg(&correction, &correction);
|
||||
secp256k1_gej_add_ge(r, r, &correction);
|
||||
|
||||
secp256k1_ge_from_storage(&correction, &correction_lam_stor);
|
||||
secp256k1_ge_neg(&correction, &correction);
|
||||
secp256k1_ge_mul_lambda(&correction, &correction);
|
||||
secp256k1_gej_add_ge(r, r, &correction);
|
||||
}
|
||||
#else
|
||||
/* correct for zero */
|
||||
r->infinity |= is_zero;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -28,14 +28,10 @@ typedef struct {
|
|||
secp256k1_gej_t initial;
|
||||
} secp256k1_ecmult_gen_context_t;
|
||||
|
||||
typedef struct {
|
||||
secp256k1_ge_storage_t (*prec)[16][16]; /* prec[j][i] = 16^j * i * G + U_i */
|
||||
} secp256k1_ecmult_gen2_context_t;
|
||||
|
||||
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context_t* ctx);
|
||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context_t* ctx);
|
||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context_t* ctx, const callback_t* cb);
|
||||
static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context_t *dst,
|
||||
const secp256k1_ecmult_gen_context_t* src);
|
||||
const secp256k1_ecmult_gen_context_t* src, const callback_t* cb);
|
||||
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context_t* ctx);
|
||||
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context_t* ctx);
|
||||
|
||||
|
|
@ -44,19 +40,4 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context_t* ctx, secp
|
|||
|
||||
static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context_t *ctx, const unsigned char *seed32);
|
||||
|
||||
static void secp256k1_ecmult_gen2_context_init(secp256k1_ecmult_gen2_context_t* ctx);
|
||||
static void secp256k1_ecmult_gen2_context_build(secp256k1_ecmult_gen2_context_t* ctx);
|
||||
static void secp256k1_ecmult_gen2_context_clone(secp256k1_ecmult_gen2_context_t *dst,
|
||||
const secp256k1_ecmult_gen2_context_t* src);
|
||||
static void secp256k1_ecmult_gen2_context_clear(secp256k1_ecmult_gen2_context_t* ctx);
|
||||
|
||||
static int secp256k1_ecmult_gen2_context_is_built(const secp256k1_ecmult_gen2_context_t* ctx);
|
||||
|
||||
/** Multiply a small number with the generator: r = gn*G2 */
|
||||
static void secp256k1_ecmult_gen2_small(const secp256k1_ecmult_gen2_context_t *ctx, secp256k1_gej_t *r, uint64_t gn);
|
||||
|
||||
/* sec * G + value * G2. */
|
||||
static void secp256k1_ecmult_gen_gen2(const secp256k1_ecmult_gen_context_t *ecmult_gen_ctx,
|
||||
const secp256k1_ecmult_gen2_context_t *cmult_gen2_ctx, secp256k1_gej_t *rj, const secp256k1_scalar_t *sec, uint64_t value);
|
||||
|
||||
#endif
|
||||
|
|
@ -11,26 +11,26 @@
|
|||
#include "group.h"
|
||||
#include "ecmult_gen.h"
|
||||
#include "hash_impl.h"
|
||||
|
||||
#ifdef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
#include "ecmult_static_context.h"
|
||||
#endif
|
||||
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context_t *ctx) {
|
||||
ctx->prec = NULL;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen2_context_init(secp256k1_ecmult_gen2_context_t *ctx) {
|
||||
ctx->prec = NULL;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context_t *ctx) {
|
||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context_t *ctx, const callback_t* cb) {
|
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
secp256k1_ge_t prec[1024];
|
||||
secp256k1_gej_t gj;
|
||||
secp256k1_gej_t nums_gej;
|
||||
int i, j;
|
||||
#endif
|
||||
|
||||
if (ctx->prec != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->prec = (secp256k1_ge_storage_t (*)[64][16])checked_malloc(sizeof(*ctx->prec));
|
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
ctx->prec = (secp256k1_ge_storage_t (*)[64][16])checked_malloc(cb, sizeof(*ctx->prec));
|
||||
|
||||
/* get the generator */
|
||||
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
|
||||
|
|
@ -72,119 +72,50 @@ static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context_t *c
|
|||
secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL);
|
||||
}
|
||||
}
|
||||
secp256k1_ge_set_all_gej_var(1024, prec, precj);
|
||||
secp256k1_ge_set_all_gej_var(1024, prec, precj, cb);
|
||||
}
|
||||
for (j = 0; j < 64; j++) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*16 + i]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)cb;
|
||||
ctx->prec = (secp256k1_ge_storage_t (*)[64][16])secp256k1_ecmult_static_context;
|
||||
#endif
|
||||
secp256k1_ecmult_gen_blind(ctx, NULL);
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen2_context_build(secp256k1_ecmult_gen2_context_t *ctx) {
|
||||
secp256k1_ge_t prec[256];
|
||||
secp256k1_gej_t gj;
|
||||
secp256k1_gej_t nums_gej;
|
||||
int i, j;
|
||||
|
||||
if (ctx->prec != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->prec = (secp256k1_ge_storage_t (*)[16][16])checked_malloc(sizeof(*ctx->prec));
|
||||
|
||||
/* get the generator */
|
||||
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g2);
|
||||
|
||||
/* Construct a group element with no known corresponding scalar (nothing up my sleeve). */
|
||||
{
|
||||
static const unsigned char nums_b32[33] = "The scalar for this x is unknown";
|
||||
secp256k1_fe_t nums_x;
|
||||
secp256k1_ge_t nums_ge;
|
||||
VERIFY_CHECK(secp256k1_fe_set_b32(&nums_x, nums_b32));
|
||||
VERIFY_CHECK(secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0));
|
||||
secp256k1_gej_set_ge(&nums_gej, &nums_ge);
|
||||
/* Add G to make the bits in x uniformly distributed. */
|
||||
secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g2, NULL);
|
||||
}
|
||||
|
||||
/* compute prec. */
|
||||
{
|
||||
secp256k1_gej_t precj[256]; /* Jacobian versions of prec. */
|
||||
secp256k1_gej_t gbase;
|
||||
secp256k1_gej_t numsbase;
|
||||
gbase = gj; /* 16^j * G */
|
||||
numsbase = nums_gej; /* 2^j * nums. */
|
||||
for (j = 0; j < 16; j++) {
|
||||
/* Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). */
|
||||
precj[j*16] = numsbase;
|
||||
for (i = 1; i < 16; i++) {
|
||||
secp256k1_gej_add_var(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase, NULL);
|
||||
}
|
||||
/* Multiply gbase by 16. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
secp256k1_gej_double_var(&gbase, &gbase, NULL);
|
||||
}
|
||||
/* Multiply numbase by 2. */
|
||||
secp256k1_gej_double_var(&numsbase, &numsbase, NULL);
|
||||
if (j == 14) {
|
||||
/* In the last iteration, numsbase is (1 - 2^j) * nums instead. */
|
||||
secp256k1_gej_neg(&numsbase, &numsbase);
|
||||
secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL);
|
||||
}
|
||||
}
|
||||
secp256k1_ge_set_all_gej_var(256, prec, precj);
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*16 + i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context_t* ctx) {
|
||||
return ctx->prec != NULL;
|
||||
}
|
||||
|
||||
static int secp256k1_ecmult_gen2_context_is_built(const secp256k1_ecmult_gen2_context_t* ctx) {
|
||||
return ctx->prec != NULL;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context_t *dst,
|
||||
const secp256k1_ecmult_gen_context_t *src) {
|
||||
const secp256k1_ecmult_gen_context_t *src, const callback_t* cb) {
|
||||
if (src->prec == NULL) {
|
||||
dst->prec = NULL;
|
||||
} else {
|
||||
dst->prec = (secp256k1_ge_storage_t (*)[64][16])checked_malloc(sizeof(*dst->prec));
|
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
dst->prec = (secp256k1_ge_storage_t (*)[64][16])checked_malloc(cb, sizeof(*dst->prec));
|
||||
memcpy(dst->prec, src->prec, sizeof(*dst->prec));
|
||||
#else
|
||||
(void)cb;
|
||||
dst->prec = src->prec;
|
||||
#endif
|
||||
dst->initial = src->initial;
|
||||
dst->blind = src->blind;
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen2_context_clone(secp256k1_ecmult_gen2_context_t *dst,
|
||||
const secp256k1_ecmult_gen2_context_t *src) {
|
||||
if (src->prec == NULL) {
|
||||
dst->prec = NULL;
|
||||
} else {
|
||||
dst->prec = (secp256k1_ge_storage_t (*)[16][16])checked_malloc(sizeof(*dst->prec));
|
||||
memcpy(dst->prec, src->prec, sizeof(*dst->prec));
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context_t *ctx) {
|
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
free(ctx->prec);
|
||||
#endif
|
||||
secp256k1_scalar_clear(&ctx->blind);
|
||||
secp256k1_gej_clear(&ctx->initial);
|
||||
ctx->prec = NULL;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen2_context_clear(secp256k1_ecmult_gen2_context_t *ctx) {
|
||||
free(ctx->prec);
|
||||
ctx->prec = NULL;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context_t *ctx, secp256k1_gej_t *r, const secp256k1_scalar_t *gn) {
|
||||
secp256k1_ge_t add;
|
||||
secp256k1_ge_storage_t adds;
|
||||
|
|
@ -227,6 +158,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context_t *ctx, cons
|
|||
unsigned char nonce32[32];
|
||||
secp256k1_rfc6979_hmac_sha256_t rng;
|
||||
int retry;
|
||||
unsigned char keydata[64] = {0};
|
||||
if (!seed32) {
|
||||
/* When seed is NULL, reset the initial point and blinding value. */
|
||||
secp256k1_gej_set_ge(&ctx->initial, &secp256k1_ge_const_g);
|
||||
|
|
@ -239,7 +171,12 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context_t *ctx, cons
|
|||
* and guards against weak or adversarial seeds. This is a simpler and safer interface than
|
||||
* asking the caller for blinding values directly and expecting them to retry on failure.
|
||||
*/
|
||||
secp256k1_rfc6979_hmac_sha256_initialize(&rng, seed32 ? seed32 : nonce32, 32, nonce32, 32, NULL, 0);
|
||||
memcpy(keydata, nonce32, 32);
|
||||
if (seed32) {
|
||||
memcpy(keydata + 32, seed32, 32);
|
||||
}
|
||||
secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, seed32 ? 64 : 32);
|
||||
memset(keydata, 0, sizeof(keydata));
|
||||
/* Retry for out of range results to achieve uniformity. */
|
||||
do {
|
||||
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
|
||||
|
|
@ -265,36 +202,4 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context_t *ctx, cons
|
|||
secp256k1_gej_clear(&gb);
|
||||
}
|
||||
|
||||
/* Version of secp256k1_ecmult_gen using the second generator and working only on numbers in the range [0 .. 2^64). */
|
||||
static void secp256k1_ecmult_gen2_small(const secp256k1_ecmult_gen2_context_t *ctx, secp256k1_gej_t *r, uint64_t gn) {
|
||||
secp256k1_ge_t add;
|
||||
secp256k1_ge_storage_t adds;
|
||||
int bits;
|
||||
int i, j;
|
||||
memset(&adds, 0, sizeof(adds));
|
||||
secp256k1_gej_set_infinity(r);
|
||||
add.infinity = 0;
|
||||
for (j = 0; j < 16; j++) {
|
||||
bits = (gn >> (j * 4)) & 15;
|
||||
for (i = 0; i < 16; i++) {
|
||||
secp256k1_ge_storage_cmov(&adds, &(*ctx->prec)[j][i], i == bits);
|
||||
}
|
||||
secp256k1_ge_from_storage(&add, &adds);
|
||||
secp256k1_gej_add_ge(r, r, &add);
|
||||
}
|
||||
bits = 0;
|
||||
secp256k1_ge_clear(&add);
|
||||
}
|
||||
|
||||
/* sec * G + value * G2. */
|
||||
SECP256K1_INLINE static void secp256k1_ecmult_gen_gen2(const secp256k1_ecmult_gen_context_t *ecmult_gen_ctx,
|
||||
const secp256k1_ecmult_gen2_context_t *cmult_gen2_ctx, secp256k1_gej_t *rj, const secp256k1_scalar_t *sec, uint64_t value) {
|
||||
secp256k1_gej_t vj;
|
||||
secp256k1_ecmult_gen(ecmult_gen_ctx, rj, sec);
|
||||
secp256k1_ecmult_gen2_small(cmult_gen2_ctx, &vj, value);
|
||||
/* FIXME: constant time. */
|
||||
secp256k1_gej_add_var(rj, rj, &vj, NULL);
|
||||
secp256k1_gej_clear(&vj);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -92,10 +92,10 @@ static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge_t
|
|||
secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A), pre, globalz, prej, zr);
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_odd_multiples_table_storage_var(int n, secp256k1_ge_storage_t *pre, const secp256k1_gej_t *a) {
|
||||
secp256k1_gej_t *prej = checked_malloc(sizeof(secp256k1_gej_t) * n);
|
||||
secp256k1_ge_t *prea = checked_malloc(sizeof(secp256k1_ge_t) * n);
|
||||
secp256k1_fe_t *zr = checked_malloc(sizeof(secp256k1_fe_t) * n);
|
||||
static void secp256k1_ecmult_odd_multiples_table_storage_var(int n, secp256k1_ge_storage_t *pre, const secp256k1_gej_t *a, const callback_t *cb) {
|
||||
secp256k1_gej_t *prej = (secp256k1_gej_t*)checked_malloc(cb, sizeof(secp256k1_gej_t) * n);
|
||||
secp256k1_ge_t *prea = (secp256k1_ge_t*)checked_malloc(cb, sizeof(secp256k1_ge_t) * n);
|
||||
secp256k1_fe_t *zr = (secp256k1_fe_t*)checked_malloc(cb, sizeof(secp256k1_fe_t) * n);
|
||||
int i;
|
||||
|
||||
/* Compute the odd multiples in Jacobian form. */
|
||||
|
|
@ -144,7 +144,7 @@ static void secp256k1_ecmult_context_init(secp256k1_ecmult_context_t *ctx) {
|
|||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context_t *ctx) {
|
||||
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context_t *ctx, const callback_t *cb) {
|
||||
secp256k1_gej_t gj;
|
||||
|
||||
if (ctx->pre_g != NULL) {
|
||||
|
|
@ -154,35 +154,35 @@ static void secp256k1_ecmult_context_build(secp256k1_ecmult_context_t *ctx) {
|
|||
/* get the generator */
|
||||
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
|
||||
|
||||
ctx->pre_g = (secp256k1_ge_storage_t (*)[])checked_malloc(sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G));
|
||||
ctx->pre_g = (secp256k1_ge_storage_t (*)[])checked_malloc(cb, sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G));
|
||||
|
||||
/* precompute the tables with odd multiples */
|
||||
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj);
|
||||
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj, cb);
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
{
|
||||
secp256k1_gej_t g_128j;
|
||||
int i;
|
||||
|
||||
ctx->pre_g_128 = (secp256k1_ge_storage_t (*)[])checked_malloc(sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G));
|
||||
ctx->pre_g_128 = (secp256k1_ge_storage_t (*)[])checked_malloc(cb, sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G));
|
||||
|
||||
/* calculate 2^128*generator */
|
||||
g_128j = gj;
|
||||
for (i = 0; i < 128; i++) {
|
||||
secp256k1_gej_double_var(&g_128j, &g_128j, NULL);
|
||||
}
|
||||
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g_128, &g_128j);
|
||||
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g_128, &g_128j, cb);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context_t *dst,
|
||||
const secp256k1_ecmult_context_t *src) {
|
||||
const secp256k1_ecmult_context_t *src, const callback_t *cb) {
|
||||
if (src->pre_g == NULL) {
|
||||
dst->pre_g = NULL;
|
||||
} else {
|
||||
size_t size = sizeof((*dst->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G);
|
||||
dst->pre_g = (secp256k1_ge_storage_t (*)[])checked_malloc(size);
|
||||
dst->pre_g = (secp256k1_ge_storage_t (*)[])checked_malloc(cb, size);
|
||||
memcpy(dst->pre_g, src->pre_g, size);
|
||||
}
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
|
|
@ -190,7 +190,7 @@ static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context_t *dst,
|
|||
dst->pre_g_128 = NULL;
|
||||
} else {
|
||||
size_t size = sizeof((*dst->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G);
|
||||
dst->pre_g_128 = (secp256k1_ge_storage_t (*)[])checked_malloc(size);
|
||||
dst->pre_g_128 = (secp256k1_ge_storage_t (*)[])checked_malloc(cb, size);
|
||||
memcpy(dst->pre_g_128, src->pre_g_128, size);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -213,43 +213,57 @@ static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context_t *ctx) {
|
|||
* - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1)
|
||||
* - two non-zero entries in wnaf are separated by at least w-1 zeroes.
|
||||
* - the number of set values in wnaf is returned. This number is at most 256, and at most one more
|
||||
* - than the number of bits in the (absolute value) of the input.
|
||||
* than the number of bits in the (absolute value) of the input.
|
||||
*/
|
||||
static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w) {
|
||||
static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar_t *a, int w) {
|
||||
secp256k1_scalar_t s = *a;
|
||||
int set_bits = 0;
|
||||
int last_set_bit = -1;
|
||||
int bit = 0;
|
||||
int sign = 1;
|
||||
int carry = 0;
|
||||
|
||||
VERIFY_CHECK(wnaf != NULL);
|
||||
VERIFY_CHECK(0 <= len && len <= 256);
|
||||
VERIFY_CHECK(a != NULL);
|
||||
VERIFY_CHECK(2 <= w && w <= 31);
|
||||
|
||||
memset(wnaf, 0, len * sizeof(wnaf[0]));
|
||||
|
||||
if (secp256k1_scalar_get_bits(&s, 255, 1)) {
|
||||
secp256k1_scalar_negate(&s, &s);
|
||||
sign = -1;
|
||||
}
|
||||
|
||||
while (bit < 256) {
|
||||
while (bit < len) {
|
||||
int now;
|
||||
int word;
|
||||
if (secp256k1_scalar_get_bits(&s, bit, 1) == 0) {
|
||||
if (secp256k1_scalar_get_bits(&s, bit, 1) == (unsigned int)carry) {
|
||||
bit++;
|
||||
continue;
|
||||
}
|
||||
while (set_bits < bit) {
|
||||
wnaf[set_bits++] = 0;
|
||||
}
|
||||
|
||||
now = w;
|
||||
if (bit + now > 256) {
|
||||
now = 256 - bit;
|
||||
}
|
||||
word = secp256k1_scalar_get_bits_var(&s, bit, now);
|
||||
if (word & (1 << (w-1))) {
|
||||
secp256k1_scalar_add_bit(&s, bit + w);
|
||||
wnaf[set_bits++] = sign * (word - (1 << w));
|
||||
} else {
|
||||
wnaf[set_bits++] = sign * word;
|
||||
if (now > len - bit) {
|
||||
now = len - bit;
|
||||
}
|
||||
|
||||
word = secp256k1_scalar_get_bits_var(&s, bit, now) + carry;
|
||||
|
||||
carry = (word >> (w-1)) & 1;
|
||||
word -= carry << w;
|
||||
|
||||
wnaf[bit] = sign * word;
|
||||
last_set_bit = bit;
|
||||
|
||||
bit += now;
|
||||
}
|
||||
return set_bits;
|
||||
#ifdef VERIFY
|
||||
CHECK(carry == 0);
|
||||
while (bit < 256) {
|
||||
CHECK(secp256k1_scalar_get_bits(&s, bit++, 1) == 0);
|
||||
}
|
||||
#endif
|
||||
return last_set_bit + 1;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_scalar_t *na, const secp256k1_scalar_t *ng) {
|
||||
|
|
@ -272,7 +286,7 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_ge
|
|||
#else
|
||||
int wnaf_na[256];
|
||||
int bits_na;
|
||||
int wnaf_ng[257];
|
||||
int wnaf_ng[256];
|
||||
int bits_ng;
|
||||
#endif
|
||||
int i;
|
||||
|
|
@ -280,11 +294,11 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_ge
|
|||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
/* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */
|
||||
secp256k1_scalar_split_lambda_var(&na_1, &na_lam, na);
|
||||
secp256k1_scalar_split_lambda(&na_1, &na_lam, na);
|
||||
|
||||
/* build wnaf representation for na_1 and na_lam. */
|
||||
bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A);
|
||||
bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, &na_lam, WINDOW_A);
|
||||
bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, 130, &na_1, WINDOW_A);
|
||||
bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, 130, &na_lam, WINDOW_A);
|
||||
VERIFY_CHECK(bits_na_1 <= 130);
|
||||
VERIFY_CHECK(bits_na_lam <= 130);
|
||||
bits = bits_na_1;
|
||||
|
|
@ -293,7 +307,7 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_ge
|
|||
}
|
||||
#else
|
||||
/* build wnaf representation for na. */
|
||||
bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A);
|
||||
bits_na = secp256k1_ecmult_wnaf(wnaf_na, 256, na, WINDOW_A);
|
||||
bits = bits_na;
|
||||
#endif
|
||||
|
||||
|
|
@ -318,8 +332,8 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_ge
|
|||
secp256k1_scalar_split_128(&ng_1, &ng_128, ng);
|
||||
|
||||
/* Build wnaf representation for ng_1 and ng_128 */
|
||||
bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, &ng_1, WINDOW_G);
|
||||
bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, &ng_128, WINDOW_G);
|
||||
bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G);
|
||||
bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G);
|
||||
if (bits_ng_1 > bits) {
|
||||
bits = bits_ng_1;
|
||||
}
|
||||
|
|
@ -327,7 +341,7 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_ge
|
|||
bits = bits_ng_128;
|
||||
}
|
||||
#else
|
||||
bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, ng, WINDOW_G);
|
||||
bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G);
|
||||
if (bits_ng > bits) {
|
||||
bits = bits_ng;
|
||||
}
|
||||
|
|
@ -1,195 +0,0 @@
|
|||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "ecwrapper.h"
|
||||
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
|
||||
* recid selects which key is recovered
|
||||
* if check is non-zero, additional checks are performed
|
||||
*/
|
||||
int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
|
||||
{
|
||||
if (!eckey) return 0;
|
||||
|
||||
int ret = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
BIGNUM *x = NULL;
|
||||
BIGNUM *e = NULL;
|
||||
BIGNUM *order = NULL;
|
||||
BIGNUM *sor = NULL;
|
||||
BIGNUM *eor = NULL;
|
||||
BIGNUM *field = NULL;
|
||||
EC_POINT *R = NULL;
|
||||
EC_POINT *O = NULL;
|
||||
EC_POINT *Q = NULL;
|
||||
BIGNUM *rr = NULL;
|
||||
BIGNUM *zero = NULL;
|
||||
int n = 0;
|
||||
int i = recid / 2;
|
||||
|
||||
const EC_GROUP *group = EC_KEY_get0_group(eckey);
|
||||
if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
|
||||
BN_CTX_start(ctx);
|
||||
order = BN_CTX_get(ctx);
|
||||
if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
|
||||
x = BN_CTX_get(ctx);
|
||||
if (!BN_copy(x, order)) { ret=-1; goto err; }
|
||||
if (!BN_mul_word(x, i)) { ret=-1; goto err; }
|
||||
if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
|
||||
field = BN_CTX_get(ctx);
|
||||
if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
|
||||
if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
|
||||
if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
|
||||
if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
|
||||
if (check)
|
||||
{
|
||||
if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
|
||||
if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
|
||||
if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
|
||||
}
|
||||
if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
|
||||
n = EC_GROUP_get_degree(group);
|
||||
e = BN_CTX_get(ctx);
|
||||
if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
|
||||
if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
|
||||
zero = BN_CTX_get(ctx);
|
||||
if (!BN_zero(zero)) { ret=-1; goto err; }
|
||||
if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
|
||||
rr = BN_CTX_get(ctx);
|
||||
if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
|
||||
sor = BN_CTX_get(ctx);
|
||||
if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
|
||||
eor = BN_CTX_get(ctx);
|
||||
if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
|
||||
if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
|
||||
if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (ctx) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
if (R != NULL) EC_POINT_free(R);
|
||||
if (O != NULL) EC_POINT_free(O);
|
||||
if (Q != NULL) EC_POINT_free(Q);
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // anon namespace
|
||||
|
||||
CECKey::CECKey() {
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
assert(pkey != NULL);
|
||||
}
|
||||
|
||||
CECKey::~CECKey() {
|
||||
EC_KEY_free(pkey);
|
||||
}
|
||||
|
||||
void CECKey::GetPubKey(std::vector<unsigned char> &pubkey, bool fCompressed) {
|
||||
EC_KEY_set_conv_form(pkey, fCompressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED);
|
||||
int nSize = i2o_ECPublicKey(pkey, NULL);
|
||||
assert(nSize);
|
||||
assert(nSize <= 65);
|
||||
pubkey.clear();
|
||||
pubkey.resize(nSize);
|
||||
unsigned char *pbegin(begin_ptr(pubkey));
|
||||
int nSize2 = i2o_ECPublicKey(pkey, &pbegin);
|
||||
assert(nSize == nSize2);
|
||||
}
|
||||
|
||||
bool CECKey::SetPubKey(const unsigned char* pubkey, size_t size) {
|
||||
return o2i_ECPublicKey(&pkey, &pubkey, size) != NULL;
|
||||
}
|
||||
|
||||
bool CECKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
|
||||
if (vchSig.empty())
|
||||
return false;
|
||||
|
||||
// New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first.
|
||||
unsigned char *norm_der = NULL;
|
||||
ECDSA_SIG *norm_sig = ECDSA_SIG_new();
|
||||
const unsigned char* sigptr = &vchSig[0];
|
||||
assert(norm_sig);
|
||||
if (d2i_ECDSA_SIG(&norm_sig, &sigptr, vchSig.size()) == NULL)
|
||||
{
|
||||
/* As of OpenSSL 1.0.0p d2i_ECDSA_SIG frees and nulls the pointer on
|
||||
* error. But OpenSSL's own use of this function redundantly frees the
|
||||
* result. As ECDSA_SIG_free(NULL) is a no-op, and in the absence of a
|
||||
* clear contract for the function behaving the same way is more
|
||||
* conservative.
|
||||
*/
|
||||
ECDSA_SIG_free(norm_sig);
|
||||
return false;
|
||||
}
|
||||
int derlen = i2d_ECDSA_SIG(norm_sig, &norm_der);
|
||||
ECDSA_SIG_free(norm_sig);
|
||||
if (derlen <= 0)
|
||||
return false;
|
||||
|
||||
// -1 = error, 0 = bad sig, 1 = good
|
||||
bool ret = ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1;
|
||||
OPENSSL_free(norm_der);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CECKey::Recover(const uint256 &hash, const unsigned char *p64, int rec)
|
||||
{
|
||||
if (rec<0 || rec>=3)
|
||||
return false;
|
||||
ECDSA_SIG *sig = ECDSA_SIG_new();
|
||||
BN_bin2bn(&p64[0], 32, sig->r);
|
||||
BN_bin2bn(&p64[32], 32, sig->s);
|
||||
bool ret = ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), rec, 0) == 1;
|
||||
ECDSA_SIG_free(sig);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CECKey::TweakPublic(const unsigned char vchTweak[32]) {
|
||||
bool ret = true;
|
||||
BN_CTX *ctx = BN_CTX_new();
|
||||
BN_CTX_start(ctx);
|
||||
BIGNUM *bnTweak = BN_CTX_get(ctx);
|
||||
BIGNUM *bnOrder = BN_CTX_get(ctx);
|
||||
BIGNUM *bnOne = BN_CTX_get(ctx);
|
||||
const EC_GROUP *group = EC_KEY_get0_group(pkey);
|
||||
EC_GROUP_get_order(group, bnOrder, ctx); // what a grossly inefficient way to get the (constant) group order...
|
||||
BN_bin2bn(vchTweak, 32, bnTweak);
|
||||
if (BN_cmp(bnTweak, bnOrder) >= 0)
|
||||
ret = false; // extremely unlikely
|
||||
EC_POINT *point = EC_POINT_dup(EC_KEY_get0_public_key(pkey), group);
|
||||
BN_one(bnOne);
|
||||
EC_POINT_mul(group, point, bnTweak, point, bnOne, ctx);
|
||||
if (EC_POINT_is_at_infinity(group, point))
|
||||
ret = false; // ridiculously unlikely
|
||||
EC_KEY_set_public_key(pkey, point);
|
||||
EC_POINT_free(point);
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CECKey::SanityCheck()
|
||||
{
|
||||
EC_KEY *pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if(pkey == NULL)
|
||||
return false;
|
||||
EC_KEY_free(pkey);
|
||||
|
||||
// TODO Is there more EC functionality that could be missing?
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_ECWRAPPER_H
|
||||
#define BITCOIN_ECWRAPPER_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/ec.h>
|
||||
|
||||
class uint256;
|
||||
|
||||
/** RAII Wrapper around OpenSSL's EC_KEY */
|
||||
class CECKey {
|
||||
private:
|
||||
EC_KEY *pkey;
|
||||
|
||||
public:
|
||||
CECKey();
|
||||
~CECKey();
|
||||
|
||||
void GetPubKey(std::vector<unsigned char>& pubkey, bool fCompressed);
|
||||
bool SetPubKey(const unsigned char* pubkey, size_t size);
|
||||
bool Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig);
|
||||
|
||||
/**
|
||||
* reconstruct public key from a compact signature
|
||||
* This is only slightly more CPU intensive than just verifying it.
|
||||
* If this function succeeds, the recovered public key is guaranteed to be valid
|
||||
* (the signature is a valid signature of the given data for that key)
|
||||
*/
|
||||
bool Recover(const uint256 &hash, const unsigned char *p64, int rec);
|
||||
|
||||
bool TweakPublic(const unsigned char vchTweak[32]);
|
||||
static bool SanityCheck();
|
||||
};
|
||||
|
||||
#endif // BITCOIN_ECWRAPPER_H
|
||||
|
|
@ -21,15 +21,15 @@ typedef struct {
|
|||
/* Unpacks a constant into a overlapping multi-limbed FE element. */
|
||||
#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \
|
||||
(d0) & 0x3FFFFFFUL, \
|
||||
((d0) >> 26) | ((d1) & 0xFFFFFUL) << 6, \
|
||||
((d1) >> 20) | ((d2) & 0x3FFFUL) << 12, \
|
||||
((d2) >> 14) | ((d3) & 0xFFUL) << 18, \
|
||||
((d3) >> 8) | ((d4) & 0x3) << 24, \
|
||||
((d4) >> 2) & 0x3FFFFFFUL, \
|
||||
((d4) >> 28) | ((d5) & 0x3FFFFFUL) << 4, \
|
||||
((d5) >> 22) | ((d6) & 0xFFFF) << 10, \
|
||||
((d6) >> 16) | ((d7) & 0x3FF) << 16, \
|
||||
((d7) >> 10) \
|
||||
(((uint32_t)d0) >> 26) | ((uint32_t)(d1) & 0xFFFFFUL) << 6, \
|
||||
(((uint32_t)d1) >> 20) | ((uint32_t)(d2) & 0x3FFFUL) << 12, \
|
||||
(((uint32_t)d2) >> 14) | ((uint32_t)(d3) & 0xFFUL) << 18, \
|
||||
(((uint32_t)d3) >> 8) | ((uint32_t)(d4) & 0x3UL) << 24, \
|
||||
(((uint32_t)d4) >> 2) & 0x3FFFFFFUL, \
|
||||
(((uint32_t)d4) >> 28) | ((uint32_t)(d5) & 0x3FFFFFUL) << 4, \
|
||||
(((uint32_t)d5) >> 22) | ((uint32_t)(d6) & 0xFFFFUL) << 10, \
|
||||
(((uint32_t)d6) >> 16) | ((uint32_t)(d7) & 0x3FFUL) << 16, \
|
||||
(((uint32_t)d7) >> 10) \
|
||||
}
|
||||
|
||||
#ifdef VERIFY
|
||||
|
|
@ -43,5 +43,5 @@ typedef struct {
|
|||
} secp256k1_fe_storage_t;
|
||||
|
||||
#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}
|
||||
|
||||
#define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0]
|
||||
#endif
|
||||
|
|
@ -1083,8 +1083,10 @@ static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe_t *r, const secp256k
|
|||
r->n[8] = (r->n[8] & mask0) | (a->n[8] & mask1);
|
||||
r->n[9] = (r->n[9] & mask0) | (a->n[9] & mask1);
|
||||
#ifdef VERIFY
|
||||
r->magnitude = (r->magnitude & mask0) | (a->magnitude & mask1);
|
||||
r->normalized = (r->normalized & mask0) | (a->normalized & mask1);
|
||||
if (a->magnitude > r->magnitude) {
|
||||
r->magnitude = a->magnitude;
|
||||
}
|
||||
r->normalized &= a->normalized;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -21,10 +21,10 @@ typedef struct {
|
|||
/* Unpacks a constant into a overlapping multi-limbed FE element. */
|
||||
#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \
|
||||
(d0) | ((uint64_t)(d1) & 0xFFFFFUL) << 32, \
|
||||
((d1) >> 20) | ((uint64_t)(d2)) << 12 | ((uint64_t)(d3) & 0xFFUL) << 44, \
|
||||
((d3) >> 8) | ((uint64_t)(d4) & 0xFFFFFFFUL) << 24, \
|
||||
((d4) >> 28) | ((uint64_t)(d5)) << 4 | ((uint64_t)(d6) & 0xFFFFUL) << 36, \
|
||||
((d6) >> 16) | ((uint64_t)(d7)) << 16 \
|
||||
((uint64_t)(d1) >> 20) | ((uint64_t)(d2)) << 12 | ((uint64_t)(d3) & 0xFFUL) << 44, \
|
||||
((uint64_t)(d3) >> 8) | ((uint64_t)(d4) & 0xFFFFFFFUL) << 24, \
|
||||
((uint64_t)(d4) >> 28) | ((uint64_t)(d5)) << 4 | ((uint64_t)(d6) & 0xFFFFUL) << 36, \
|
||||
((uint64_t)(d6) >> 16) | ((uint64_t)(d7)) << 16 \
|
||||
}
|
||||
|
||||
#ifdef VERIFY
|
||||
|
|
@ -414,8 +414,10 @@ static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe_t *r, const secp256k
|
|||
r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1);
|
||||
r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1);
|
||||
#ifdef VERIFY
|
||||
r->magnitude = (r->magnitude & mask0) | (a->magnitude & mask1);
|
||||
r->normalized = (r->normalized & mask0) | (a->normalized & mask1);
|
||||
if (a->magnitude > r->magnitude) {
|
||||
r->magnitude = a->magnitude;
|
||||
}
|
||||
r->normalized &= a->normalized;
|
||||
#endif
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue